@sema-agent/cli 1.0.76 → 1.0.78

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
@@ -39088,9 +39088,9 @@ var require_abort = __commonJS({
39088
39088
  "node_modules/asynckit/lib/abort.js"(exports2, module2) {
39089
39089
  module2.exports = abort;
39090
39090
  function abort(state4) {
39091
- Object.keys(state4.jobs).forEach(clean5.bind(state4)), state4.jobs = {};
39091
+ Object.keys(state4.jobs).forEach(clean6.bind(state4)), state4.jobs = {};
39092
39092
  }
39093
- function clean5(key) {
39093
+ function clean6(key) {
39094
39094
  typeof this.jobs[key] == "function" && this.jobs[key]();
39095
39095
  }
39096
39096
  }
@@ -55606,7 +55606,7 @@ function isRewindFamilyCode(code2) {
55606
55606
  function asModelFallbackReason(v2) {
55607
55607
  return v2 === MODEL_FALLBACK_INHERIT_NO_TIER_BINDING ? MODEL_FALLBACK_INHERIT_NO_TIER_BINDING : void 0;
55608
55608
  }
55609
- var LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, USAGE_WINDOW_EXHAUSTED, ENV_LIFETIME_EXPIRED, CONFIG_LIMIT_INVALID, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_REFUSAL_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, REWIND_ERROR_CODE_PREFIXES, STREAM_MAX_DURATION, MODEL_FALLBACK_INHERIT_NO_TIER_BINDING, init_engineErrorCodes = __esm({
55609
+ var LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, USAGE_WINDOW_EXHAUSTED, ENV_LIFETIME_EXPIRED, CONFIG_LIMIT_INVALID, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_REFUSAL_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({
55610
55610
  "node_modules/@sema-agent/client-core/dist/engineErrorCodes.js"() {
55611
55611
  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", 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_REFUSAL_CODES = /* @__PURE__ */ new Set([
55612
55612
  CONFIG_LIMIT_INVALID,
@@ -55624,8 +55624,8 @@ var LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TURNS_EXCEE
55624
55624
  STOP_NOT_LANDED,
55625
55625
  STOP_NOT_LOCAL,
55626
55626
  STOP_PARKED
55627
- ], OUTPUT_INVALID = "output.invalid", REWIND_ERROR_CODE_PREFIXES = ["resume_at.", "rewind_snapshot."];
55628
- STREAM_MAX_DURATION = "STREAM_MAX_DURATION", MODEL_FALLBACK_INHERIT_NO_TIER_BINDING = "inherit_no_tier_binding";
55627
+ ], OUTPUT_INVALID = "output.invalid", RESUME_AT_ERROR_CODE_PREFIX = "resume_at.", REWIND_ERROR_CODE_PREFIXES = [RESUME_AT_ERROR_CODE_PREFIX, "rewind_snapshot."];
55628
+ DRAINING_ERROR_CODE = "draining", SCENARIO_NOT_ALLOWED_ERROR_CODE = "scenario_not_allowed", STREAM_MAX_DURATION = "STREAM_MAX_DURATION", MODEL_FALLBACK_INHERIT_NO_TIER_BINDING = "inherit_no_tier_binding";
55629
55629
  }
55630
55630
  });
55631
55631
 
@@ -58146,6 +58146,15 @@ var SSE_HEARTBEAT_GRACE_ENV, SSE_GRACE_MIN_MS, SSE_GRACE_MAX_MS, SDK_DEFAULT_GRA
58146
58146
  }
58147
58147
  });
58148
58148
 
58149
+ // node_modules/@sema-agent/client-core/dist/principalWire.js
58150
+ function normalizeWirePrincipal(v2) {
58151
+ return v2 !== void 0 && v2.trim() !== "" ? v2 : void 0;
58152
+ }
58153
+ var init_principalWire = __esm({
58154
+ "node_modules/@sema-agent/client-core/dist/principalWire.js"() {
58155
+ }
58156
+ });
58157
+
58149
58158
  // node_modules/@sema-agent/client-core/dist/engineWireSdk.js
58150
58159
  import { AgentClient } from "@sema-agent/sdk";
58151
58160
  function isLoopbackWireUrl(url3) {
@@ -58164,10 +58173,11 @@ function wireAuthTokenFor(baseUrl, token) {
58164
58173
  }
58165
58174
  function makeEngineWireClient(cfg) {
58166
58175
  try {
58167
- let base = {
58176
+ let principal = normalizeWirePrincipal(cfg.principal), base = {
58168
58177
  baseUrl: cfg.baseUrl,
58169
58178
  // F-011 停发:缺席/空串=不给键(SDK 6.11 缺席=不发 x-agent-principal 头,owner-null)。
58170
- ...cfg.principal !== void 0 && cfg.principal !== "" ? { principal: cfg.principal } : {},
58179
+ // A-028.10(0.30.3):空串判升级为 trim 判(principalWire 同尺)——全空白值同罪,归缺席。
58180
+ ...principal !== void 0 ? { principal } : {},
58171
58181
  ...cfg.timeoutMs !== void 0 ? { timeoutMs: cfg.timeoutMs } : {},
58172
58182
  maxRetries: cfg.maxRetries ?? 0,
58173
58183
  ...cfg.fetchImpl ? { fetch: cfg.fetchImpl } : {}
@@ -58179,6 +58189,7 @@ function makeEngineWireClient(cfg) {
58179
58189
  }
58180
58190
  var init_engineWireSdk = __esm({
58181
58191
  "node_modules/@sema-agent/client-core/dist/engineWireSdk.js"() {
58192
+ init_principalWire();
58182
58193
  }
58183
58194
  });
58184
58195
 
@@ -60010,14 +60021,14 @@ function claimProbeLease(caller, remainingMs) {
60010
60021
  };
60011
60022
  }
60012
60023
  async function waitForClaimRelease(taskId, deps2) {
60013
- let now2 = typeof deps2.now == "function" ? deps2.now : () => Date.now(), sleep10 = typeof deps2.sleep == "function" ? deps2.sleep : claimPollSleep, budgetMs = Number.isFinite(deps2.budgetMs) && deps2.budgetMs > 0 ? deps2.budgetMs : 0, startedAt = now2(), deadline = startedAt + budgetMs, waited = () => now2() - startedAt, isAborted3 = () => deps2.signal?.aborted === !0, delay = CANCEL_POLL_START_MS, lastStatus = null;
60024
+ let now2 = typeof deps2.now == "function" ? deps2.now : () => Date.now(), sleep9 = typeof deps2.sleep == "function" ? deps2.sleep : claimPollSleep, budgetMs = Number.isFinite(deps2.budgetMs) && deps2.budgetMs > 0 ? deps2.budgetMs : 0, startedAt = now2(), deadline = startedAt + budgetMs, waited = () => now2() - startedAt, isAborted3 = () => deps2.signal?.aborted === !0, delay = CANCEL_POLL_START_MS, lastStatus = null;
60014
60025
  for (; ; ) {
60015
60026
  if (isAborted3())
60016
60027
  return { released: !1, waitedMs: waited(), aborted: !0, lastStatus };
60017
60028
  let remaining = deadline - now2();
60018
60029
  if (remaining <= 0)
60019
60030
  return { released: !1, waitedMs: waited(), aborted: !1, lastStatus };
60020
- if (await sleep10(Math.min(delay, remaining), deps2.signal), isAborted3())
60031
+ if (await sleep9(Math.min(delay, remaining), deps2.signal), isAborted3())
60021
60032
  return { released: !1, waitedMs: waited(), aborted: !0, lastStatus };
60022
60033
  delay = Math.min(Math.round(delay * 1.5), CANCEL_POLL_MAX_MS);
60023
60034
  let status3, lease = claimProbeLease(deps2.signal, deadline - now2());
@@ -60027,8 +60038,11 @@ async function waitForClaimRelease(taskId, deps2) {
60027
60038
  ...deps2.session !== void 0 ? { session: deps2.session } : {}
60028
60039
  }));
60029
60040
  } catch {
60030
- if (lastStatus = null, lease.release(), isAborted3())
60041
+ if (lease.release(), isAborted3())
60031
60042
  return { released: !1, waitedMs: waited(), aborted: !0, lastStatus };
60043
+ if (lease.signal.aborted)
60044
+ continue;
60045
+ lastStatus = null;
60032
60046
  continue;
60033
60047
  }
60034
60048
  if (lease.release(), lastStatus = status3, status3 !== null && CLAIM_RELEASED_STATES.includes(status3))
@@ -60042,6 +60056,22 @@ async function attemptActiveRunSelfHeal(signal, runs, deps2) {
60042
60056
  } catch {
60043
60057
  pending2 = !1;
60044
60058
  }
60059
+ let callerAborted = () => deps2?.signal?.aborted === !0;
60060
+ if (pending2 && typeof deps2?.listOwnedPendingApprovals == "function" && !callerAborted()) {
60061
+ let recheckCtl = new AbortController(), onCallerAbort = () => {
60062
+ recheckCtl.abort(deps2.signal?.reason);
60063
+ };
60064
+ deps2.signal?.addEventListener("abort", onCallerAbort, { once: !0 });
60065
+ try {
60066
+ await Promise.race([
60067
+ deps2.listOwnedPendingApprovals({ signal: recheckCtl.signal }),
60068
+ claimPollSleep(OWNED_PENDING_RECHECK_TIMEOUT_MS, recheckCtl.signal).then(() => null)
60069
+ ]) === 0 && !callerAborted() && (pending2 = !1);
60070
+ } catch {
60071
+ } finally {
60072
+ deps2.signal?.removeEventListener("abort", onCallerAbort), recheckCtl.abort(new Error("owned-pending recheck settled"));
60073
+ }
60074
+ }
60045
60075
  if (pending2)
60046
60076
  return { kind: "decision-pending", taskId: signal.activeTaskId };
60047
60077
  let taskId = signal.activeTaskId;
@@ -60235,13 +60265,13 @@ function activeRunBusyHeadlessRow(signal, copy2) {
60235
60265
  let startOver = `${freshSession.charAt(0).toUpperCase()}${freshSession.slice(1)}`;
60236
60266
  return `This session is locked by an earlier run${handle2} that was never released, so this message was NOT sent. Nothing here clears on its own. ${startOver}, or release the run on the engine: ${cancelPath}`;
60237
60267
  }
60238
- var PLAN_REVIEW_GATE_KIND, PLAN_REVIEW_GATE_KINDS, ASK_PARK_GATE_KINDS, PLAN_REVIEW_STATES, ASK_PARK_STATES, RUNNING_STATES, CLAIM_RELEASED_STATES, CLAIM_HELD_STATES, CANCEL_RELEASE_WAIT_MS, CANCEL_POLL_START_MS, CANCEL_POLL_MAX_MS, DEFAULT_WAY_OUT, DEFAULT_FRESH_SESSION, init_activeRunSelfHeal = __esm({
60268
+ var PLAN_REVIEW_GATE_KIND, PLAN_REVIEW_GATE_KINDS, ASK_PARK_GATE_KINDS, PLAN_REVIEW_STATES, ASK_PARK_STATES, RUNNING_STATES, CLAIM_RELEASED_STATES, CLAIM_HELD_STATES, CANCEL_RELEASE_WAIT_MS, OWNED_PENDING_RECHECK_TIMEOUT_MS, CANCEL_POLL_START_MS, CANCEL_POLL_MAX_MS, INTERACTIVE_WAY_OUT, DEFAULT_WAY_OUT, DEFAULT_FRESH_SESSION, init_activeRunSelfHeal = __esm({
60239
60269
  "node_modules/@sema-agent/client-core/dist/adapter/activeRunSelfHeal.js"() {
60240
60270
  init_abortableSleep();
60241
60271
  PLAN_REVIEW_GATE_KIND = "plan_review", PLAN_REVIEW_GATE_KINDS = [PLAN_REVIEW_GATE_KIND, "dry_run_review"], ASK_PARK_GATE_KINDS = ["human", "irreversible_ask", "policy_ask", "tool_approval"];
60242
60272
  PLAN_REVIEW_STATES = ["needs_review"], ASK_PARK_STATES = ["suspended"], RUNNING_STATES = ["running"], CLAIM_RELEASED_STATES = ["completed", "failed", "blocked", "timeout"], CLAIM_HELD_STATES = ["running", "suspended", "needs_review"];
60243
- CANCEL_RELEASE_WAIT_MS = 1e4, CANCEL_POLL_START_MS = 200, CANCEL_POLL_MAX_MS = 2e3;
60244
- DEFAULT_WAY_OUT = "run /clear to keep working in a fresh session", DEFAULT_FRESH_SESSION = "start a new session (drop --resume/--continue)";
60273
+ CANCEL_RELEASE_WAIT_MS = 1e4, OWNED_PENDING_RECHECK_TIMEOUT_MS = 4e3, CANCEL_POLL_START_MS = 200, CANCEL_POLL_MAX_MS = 2e3;
60274
+ INTERACTIVE_WAY_OUT = "run /clear to keep working in a fresh session", DEFAULT_WAY_OUT = INTERACTIVE_WAY_OUT, DEFAULT_FRESH_SESSION = "start a new session (drop --resume/--continue)";
60245
60275
  }
60246
60276
  });
60247
60277
 
@@ -60300,7 +60330,7 @@ function buildTaskRequest(input, lane) {
60300
60330
  }
60301
60331
  function applyLiveRequestDefaults(req, host) {
60302
60332
  let out6 = { ...req };
60303
- if (out6.cwd == null && host.cwd !== void 0 && (out6.cwd = host.cwd), out6.additionalDirectories === void 0 && (host.additionalDirectories?.length ?? 0) > 0 && (out6.additionalDirectories = [...host.additionalDirectories ?? []]), out6.forwardSubagentEvents === void 0 && (out6.forwardSubagentEvents = !0), out6.retainSubagentSessions === void 0 && (out6.retainSubagentSessions = !0), out6.agents === void 0 && host.agents !== void 0 && (out6.agents = host.agents), typeof out6.scenario == "string" && host.mockScenarioKeys?.has(out6.scenario) && delete out6.scenario, host.selfKnowledge !== void 0)
60333
+ if (out6.cwd == null && host.cwd !== void 0 && (out6.cwd = host.cwd), out6.additionalDirectories === void 0 && (host.additionalDirectories?.length ?? 0) > 0 && (out6.additionalDirectories = [...host.additionalDirectories ?? []]), out6.additionalReadDirectories === void 0 && (host.additionalReadDirectories?.length ?? 0) > 0 && (out6.additionalReadDirectories = [...host.additionalReadDirectories ?? []]), out6.forwardSubagentEvents === void 0 && (out6.forwardSubagentEvents = !0), out6.retainSubagentSessions === void 0 && (out6.retainSubagentSessions = !0), out6.agents === void 0 && host.agents !== void 0 && (out6.agents = host.agents), typeof out6.scenario == "string" && host.mockScenarioKeys?.has(out6.scenario) && delete out6.scenario, host.selfKnowledge !== void 0)
60304
60334
  if (host.appendSystemPromptCapable)
60305
60335
  out6.appendSystemPrompt = host.selfKnowledge.forAppend;
60306
60336
  else {
@@ -60387,6 +60417,7 @@ var REQUEST_FIELD_MATRIX, LIVE_DEFAULT_FIELDS, laneHas, init_taskRequest = __esm
60387
60417
  ], LIVE_DEFAULT_FIELDS = [
60388
60418
  "cwd",
60389
60419
  "additionalDirectories",
60420
+ "additionalReadDirectories",
60390
60421
  "forwardSubagentEvents",
60391
60422
  "retainSubagentSessions",
60392
60423
  "agents",
@@ -61009,17 +61040,21 @@ function engineWireTarget() {
61009
61040
  }
61010
61041
  function engineWireTargetFor(sessionKey) {
61011
61042
  let installed3 = installedByKey.get(sessionKey) ?? null;
61012
- if (installed3 !== null)
61013
- return installed3;
61043
+ if (installed3 !== null) {
61044
+ if (normalizeWirePrincipal(installed3.principal) === installed3.principal)
61045
+ return installed3;
61046
+ let { principal: _dropped, ...rest } = installed3;
61047
+ return rest;
61048
+ }
61014
61049
  let env5 = hostEnv(), baseUrl = env5.SEMA_LIVE_BASEURL;
61015
- return baseUrl ? {
61050
+ if (!baseUrl)
61051
+ return null;
61052
+ let envPrincipal = normalizeWirePrincipal(env5.SEMA_LIVE_PRINCIPAL);
61053
+ return {
61016
61054
  baseUrl,
61017
- // principal must match the run's owner (stamped by the live stream) — the owner-gated routes answer
61018
- // 404 for non-owners (no existence oracle). F-011 停发([3279]):缺席=不发头,owner-null 两侧
61019
- // 对齐(server 7.8.1 读写面窄互认盖存量);显式 SEMA_LIVE_PRINCIPAL 恒赢,绝不铸哨兵值。
61020
61055
  ...env5.SEMA_LIVE_TOKEN ? { token: env5.SEMA_LIVE_TOKEN } : {},
61021
- ...env5.SEMA_LIVE_PRINCIPAL ? { principal: env5.SEMA_LIVE_PRINCIPAL } : {}
61022
- } : null;
61056
+ ...envPrincipal !== void 0 ? { principal: envPrincipal } : {}
61057
+ };
61023
61058
  }
61024
61059
  function engineWireDebugEnabled() {
61025
61060
  return !!hostEnv().SEMA_DEBUG;
@@ -61028,6 +61063,7 @@ var installedByKey, init_engineWireTarget = __esm({
61028
61063
  "node_modules/@sema-agent/client-core/dist/engineWireTarget.js"() {
61029
61064
  init_hostEnv();
61030
61065
  init_sessionSlot();
61066
+ init_principalWire();
61031
61067
  installedByKey = createSessionSlot();
61032
61068
  }
61033
61069
  });
@@ -61762,6 +61798,12 @@ function installSubagentActivitySink(sink2) {
61762
61798
  activitySink = prev;
61763
61799
  };
61764
61800
  }
61801
+ function installSubagentTailMetaSink(sink2) {
61802
+ let prev = tailMetaSink;
61803
+ return tailMetaSink = sink2, () => {
61804
+ tailMetaSink = prev;
61805
+ };
61806
+ }
61765
61807
  function isEngineSubagentTailActive(taskId) {
61766
61808
  return activeTails.has(taskId);
61767
61809
  }
@@ -61797,8 +61839,22 @@ function tailEngineSubagent(taskId) {
61797
61839
  for await (let ev of stream5) {
61798
61840
  if (ac.signal.aborted)
61799
61841
  break;
61800
- if (connectLogged || (connectLogged = !0, hostLog("debug", `[subagent-tail] ${taskId} stream connected +${Date.now() - openedAt}ms`)), ev.event !== "forward")
61801
- continue;
61842
+ switch (connectLogged || (connectLogged = !0, hostLog("debug", `[subagent-tail] ${taskId} stream connected +${Date.now() - openedAt}ms`)), ev.event) {
61843
+ case "meta":
61844
+ try {
61845
+ let out6 = tailMetaSink?.({ taskId, meta: ev.data });
61846
+ out6 !== null && typeof out6 == "object" && typeof out6.then == "function" && out6.then(void 0, (e) => {
61847
+ hostLog("debug", `[subagent-tail] ${taskId} meta sink rejected: ${String(e).slice(0, 160)}`);
61848
+ });
61849
+ } catch (e) {
61850
+ hostLog("debug", `[subagent-tail] ${taskId} meta sink threw: ${String(e).slice(0, 160)}`);
61851
+ }
61852
+ continue;
61853
+ case "forward":
61854
+ break;
61855
+ default:
61856
+ continue;
61857
+ }
61802
61858
  let d4 = ev.data, t2 = d4.type;
61803
61859
  if (frames += 1, !firstContentLogged && (t2 === "text_delta" || t2 === "reasoning_delta" || t2 === "tool_start") && (firstContentLogged = !0, hostLog("debug", `[subagent-tail] ${taskId} first content frame +${Date.now() - openedAt}ms (${String(t2)})`)), t2 === "text_delta" || t2 === "reasoning_delta")
61804
61860
  typeof d4.delta == "string" && d4.delta.length > 0 && publishSubagentContentEvent({
@@ -61849,7 +61905,7 @@ function hasActiveSubagentTail(taskId) {
61849
61905
  function __activeTailCountForTests() {
61850
61906
  return activeTails.size;
61851
61907
  }
61852
- var capByBase2, CAP_FALSE_RETRY_TTL_MS2, activeTails, activitySink, init_engineSubagentTail = __esm({
61908
+ var capByBase2, CAP_FALSE_RETRY_TTL_MS2, activeTails, activitySink, tailMetaSink, init_engineSubagentTail = __esm({
61853
61909
  "node_modules/@sema-agent/client-core/dist/subagent/engineSubagentTail.js"() {
61854
61910
  init_host();
61855
61911
  init_engineWireSdk();
@@ -61858,6 +61914,93 @@ var capByBase2, CAP_FALSE_RETRY_TTL_MS2, activeTails, activitySink, init_engineS
61858
61914
  init_subagentContentStore();
61859
61915
  capByBase2 = /* @__PURE__ */ new Map(), CAP_FALSE_RETRY_TTL_MS2 = 5 * 6e4;
61860
61916
  activeTails = /* @__PURE__ */ new Map(), activitySink = null;
61917
+ tailMetaSink = null;
61918
+ }
61919
+ });
61920
+
61921
+ // node_modules/@sema-agent/client-core/dist/wireErrorTriage.js
61922
+ function wireErrorDetail(err8) {
61923
+ let e = err8, cause = e?.cause;
61924
+ return typeof cause?.message == "string" && cause.message.length > 0 && cause.message || typeof e?.message == "string" && e.message.length > 0 && e.message || String(err8);
61925
+ }
61926
+ function classifyTurnWireError(err8) {
61927
+ let e = err8;
61928
+ if (typeof e?.status == "number") {
61929
+ let errorCode = typeof e.errorCode == "string" && e.errorCode.length > 0 ? e.errorCode : void 0, message = typeof e.message == "string" && e.message.length > 0 ? e.message : String(err8);
61930
+ return { kind: "http", status: e.status, ...errorCode !== void 0 ? { errorCode } : {}, message };
61931
+ }
61932
+ if ((typeof err8 == "object" && err8 !== null && typeof err8.name == "string" ? err8.name : void 0) === "StreamEndedWithoutTerminalError")
61933
+ return { kind: "stream-ended-without-terminal" };
61934
+ let detail = wireErrorDetail(err8);
61935
+ return e?.cause !== void 0 || WIRE_NETWORK_ERROR_PATTERN.test(detail) ? { kind: "transport", detail } : { kind: "internal", name: err8 instanceof Error ? err8.name : typeof err8, detail };
61936
+ }
61937
+ function isWireTransportError(err8) {
61938
+ let e = err8;
61939
+ return typeof e?.status == "number" ? !1 : e?.cause !== void 0 || WIRE_NETWORK_ERROR_PATTERN.test(wireErrorDetail(err8));
61940
+ }
61941
+ function isPreStreamDrainingReject(err8) {
61942
+ let e = err8;
61943
+ return typeof e?.status == "number" && e.status === 503 && e.errorCode === DRAINING_ERROR_CODE;
61944
+ }
61945
+ function isResumeAtRejection(err8) {
61946
+ let e = err8;
61947
+ return typeof e?.errorCode == "string" && e.errorCode.startsWith(RESUME_AT_ERROR_CODE_PREFIX);
61948
+ }
61949
+ function drainingRetryDelayMs(err8, attempt, opts) {
61950
+ let ra = err8?.retryAfterMs;
61951
+ if (typeof ra == "number" && Number.isFinite(ra) && ra >= 0)
61952
+ return Math.min(ra, opts?.retryAfterCapMs ?? 15e3);
61953
+ let ladder = opts?.ladder && opts.ladder.length > 0 ? opts.ladder : [1e3, 2e3, 4e3];
61954
+ return ladder[Math.min(attempt, ladder.length - 1)] ?? 1e3;
61955
+ }
61956
+ function scenarioDenyFromError(err8) {
61957
+ if (typeof err8 != "object" || err8 === null)
61958
+ return null;
61959
+ let e = err8;
61960
+ return e.status !== 400 || e.errorCode !== SCENARIO_NOT_ALLOWED_ERROR_CODE ? null : { allowlist: Array.isArray(e.allowlist) ? e.allowlist.filter((x3) => typeof x3 == "string" && x3.length > 0) : [] };
61961
+ }
61962
+ var WIRE_NETWORK_ERROR_PATTERN, init_wireErrorTriage = __esm({
61963
+ "node_modules/@sema-agent/client-core/dist/wireErrorTriage.js"() {
61964
+ init_engineErrorCodes();
61965
+ WIRE_NETWORK_ERROR_PATTERN = /fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|EHOSTUNREACH|ENETUNREACH|EPIPE|socket hang up|UND_ERR|terminated|other side closed/i;
61966
+ }
61967
+ });
61968
+
61969
+ // node_modules/@sema-agent/client-core/dist/sessionMap.js
61970
+ function engineNamespaceKeyFor(baseUrl) {
61971
+ if (!baseUrl)
61972
+ return "local";
61973
+ try {
61974
+ return new URL(baseUrl).origin.toLowerCase();
61975
+ } catch {
61976
+ return baseUrl.toLowerCase();
61977
+ }
61978
+ }
61979
+ function mergeSessionMapRecord(prior, partial2, now2 = isoNow) {
61980
+ let shellSessionId = partial2.shellSessionId ?? prior?.shellSessionId;
61981
+ return shellSessionId ? { ok: !0, record: { ...prior, ...partial2, shellSessionId, updatedAt: now2() } } : { ok: !1, reason: "no-shell-session-id" };
61982
+ }
61983
+ function mergeEngineEntry(prior, key, partial2, shellSessionId, now2 = isoNow) {
61984
+ let priorEntry = prior?.engines?.[key], engineSessionId = partial2.engineSessionId ?? priorEntry?.engineSessionId;
61985
+ if (!engineSessionId)
61986
+ return { ok: !1, reason: "no-engine-session-id" };
61987
+ let sid = shellSessionId ?? prior?.shellSessionId;
61988
+ if (!sid)
61989
+ return { ok: !1, reason: "no-shell-session-id" };
61990
+ let entry = { ...priorEntry, ...partial2, engineSessionId, updatedAt: now2() };
61991
+ return {
61992
+ ok: !0,
61993
+ record: {
61994
+ ...prior,
61995
+ shellSessionId: sid,
61996
+ engines: { ...prior?.engines, [key]: entry },
61997
+ updatedAt: now2()
61998
+ }
61999
+ };
62000
+ }
62001
+ var isoNow, init_sessionMap = __esm({
62002
+ "node_modules/@sema-agent/client-core/dist/sessionMap.js"() {
62003
+ isoNow = () => (/* @__PURE__ */ new Date()).toISOString();
61861
62004
  }
61862
62005
  });
61863
62006
 
@@ -64252,13 +64395,14 @@ async function surfaceFsApprovalAndDecide(deps2, taskId, argsByCall, signal) {
64252
64395
  let { pending: pending2, gatedCallId } = found, toolName2 = typeof pending2.toolName == "string" ? pending2.toolName : "", args = (gatedCallId !== void 0 ? argsByCall.get(gatedCallId) : void 0) ?? pending2.input ?? {};
64253
64396
  if (typeof args != "object" || args === null)
64254
64397
  return { kind: "failed", gatedCallId, reason: "gate has no tool input payload" };
64255
- let bridge3 = new HitlBridge(deps2.client, taskId), callKey = approvalCallKey(gatedCallId, taskId), ruleSuggestionsReadOnly = readRuleSuggestions(pending2.ruleSuggestions), card = await surfaceApprovalCard({
64398
+ let bridge3 = new HitlBridge(deps2.client, taskId), callKey = approvalCallKey(gatedCallId, taskId), ruleSuggestionsReadOnly = readRuleSuggestions(pending2.ruleSuggestions), durableProbeCause = pending2.riskDescriptor?.probeCause, card = await surfaceApprovalCard({
64256
64399
  toolName: toolName2,
64257
64400
  args,
64258
64401
  callKey,
64259
64402
  ...signal ? { signal } : {},
64260
64403
  ...pending2.governanceForced === !0 ? { governanceForced: !0 } : {},
64261
- ...ruleSuggestionsReadOnly !== void 0 ? { ruleSuggestionsReadOnly } : {}
64404
+ ...ruleSuggestionsReadOnly !== void 0 ? { ruleSuggestionsReadOnly } : {},
64405
+ ...isProbeCauseCarrier(durableProbeCause) ? { probeCause: durableProbeCause } : {}
64262
64406
  });
64263
64407
  switch (card.kind) {
64264
64408
  case "failed":
@@ -64327,6 +64471,9 @@ function pathFromGateMessage(message) {
64327
64471
  if (typeof message == "string")
64328
64472
  return FS_WRITE_GATE_ASK_PATTERN.exec(message)?.[1];
64329
64473
  }
64474
+ function isProbeCauseCarrier(v2) {
64475
+ return typeof v2 == "object" && v2 !== null && !Array.isArray(v2);
64476
+ }
64330
64477
  function readRuleSuggestions(v2) {
64331
64478
  if (!Array.isArray(v2) || v2.length === 0 || v2.length > 8)
64332
64479
  return;
@@ -64379,7 +64526,10 @@ async function surfaceToolApprovalFrameAndRespond(frame, respond, streamArgs, si
64379
64526
  // (server 明说空串不铸键:「空串是坏值不是『空规则』」)—— 一格空白的规则解释比没有解释更坏。
64380
64527
  // 🔴 stamp 的是**原文字节**(不 trim、不截、不改写):展示值一改写就不再是「你那条规则」的原文;
64381
64528
  // 渲染面的长度夹取归壳,与 `message`/`sourceAgentName` 同族口径(本模块对展示文本零加工)。
64382
- ...typeof frame.persistedRuleShadowed == "string" && frame.persistedRuleShadowed.trim() !== "" ? { persistedRuleShadowed: frame.persistedRuleShadowed } : {}
64529
+ ...typeof frame.persistedRuleShadowed == "string" && frame.persistedRuleShadowed.trim() !== "" ? { persistedRuleShadowed: frame.persistedRuleShadowed } : {},
64530
+ // #280 件1(0.30.4):探针因由随卡透传 —— 载体形判之外零校验零改写(内部结构归呈卡端窄读器,
64531
+ // isProbeCauseCarrier 顶注);缺席/坏载体 ⇒ 键不 stamp,卡形字节不变。
64532
+ ...isProbeCauseCarrier(frame.probeCause) ? { probeCause: frame.probeCause } : {}
64383
64533
  }), decision = card.kind === "allow" ? card.allowSession ? "allow_session" : "allow" : "deny";
64384
64534
  card.kind === "failed" && hostLog("debug", `liveToolApprovalWire: approval card unavailable (${card.reason}) \u2014 fail-closed deny for ${frame.approvalId}`);
64385
64535
  let note;
@@ -64431,6 +64581,11 @@ var cardPortByKey, cardPortMissesByKey, TOOL_APPROVAL_FRAME_KEYS_MIRROR, RESPOND
64431
64581
  // (sdk 6.14.0/6.15.0 的 TOOL_APPROVAL_FRAME_KEYS 都还没有它)⇒ 对账门里有一条**带退出条件**的
64432
64582
  // 领先登记(AHEAD_OF_ANCHOR):SDK 锚一旦补上,那条登记当场红,逼人删登记而不是让豁免长住。
64433
64583
  "persistedRuleShadowed",
64584
+ // #280 件1(client-core 0.30.4):server 7.21.0-rc(#253)起真发 `probeCause`(直证 = engine
64585
+ // 7.22.0 fixture 的 `@sema-agent/server/dist/tool-approval.d.ts`)。⚠️ 本键**领先** SDK 运行期锚
64586
+ // 一代(sdk 6.17.2 尚无)⇒ 对账门里有一条带退出条件的领先登记(AHEAD_OF_ANCHOR),SDK 锚一旦
64587
+ // 补上,那条登记当场红,逼人删登记回到逐元素相等 —— #144 persistedRuleShadowed 同形先例。
64588
+ "probeCause",
64434
64589
  "delegation",
64435
64590
  "outcome"
64436
64591
  ];
@@ -64892,11 +65047,30 @@ function setFor(sessionKey) {
64892
65047
  let s = armedGatesByKey.get(sessionKey);
64893
65048
  return s || (s = /* @__PURE__ */ new Set(), armedGatesByKey.set(sessionKey, s)), s;
64894
65049
  }
65050
+ function listenersFor(sessionKey) {
65051
+ let s = armedListenersByKey.get(sessionKey);
65052
+ return s || (s = /* @__PURE__ */ new Set(), armedListenersByKey.set(sessionKey, s)), s;
65053
+ }
65054
+ function genMapFor(sessionKey) {
65055
+ let m2 = planReviewGenByKey.get(sessionKey);
65056
+ return m2 || (m2 = /* @__PURE__ */ new Map(), planReviewGenByKey.set(sessionKey, m2)), m2;
65057
+ }
65058
+ function notedIdsFor(sessionKey) {
65059
+ let s = notedPlanReviewIdsByKey.get(sessionKey);
65060
+ return s || (s = /* @__PURE__ */ new Set(), notedPlanReviewIdsByKey.set(sessionKey, s)), s;
65061
+ }
65062
+ function emitGateArmedEventFor(sessionKey, key) {
65063
+ for (let listener5 of [...listenersFor(sessionKey)])
65064
+ try {
65065
+ listener5(key);
65066
+ } catch {
65067
+ }
65068
+ }
64895
65069
  function registerArmedGate(key) {
64896
65070
  registerArmedGateFor(DEFAULT_SESSION_KEY, key);
64897
65071
  }
64898
65072
  function registerArmedGateFor(sessionKey, key) {
64899
- typeof key == "string" && key.length > 0 && setFor(sessionKey).add(key);
65073
+ typeof key != "string" || key.length === 0 || (setFor(sessionKey).add(key), emitGateArmedEventFor(sessionKey, key));
64900
65074
  }
64901
65075
  function wasGateArmed(key) {
64902
65076
  return wasGateArmedFor(DEFAULT_SESSION_KEY, key);
@@ -64910,20 +65084,86 @@ function clearArmedGate(key) {
64910
65084
  function clearArmedGateFor(sessionKey, key) {
64911
65085
  typeof key == "string" && key.length > 0 && armedGatesByKey.get(sessionKey)?.delete(key);
64912
65086
  }
65087
+ function onGateArmed(listener5) {
65088
+ return onGateArmedFor(DEFAULT_SESSION_KEY, listener5);
65089
+ }
65090
+ function onGateArmedFor(sessionKey, listener5) {
65091
+ let listeners10 = listenersFor(sessionKey);
65092
+ return listeners10.add(listener5), () => {
65093
+ listeners10.delete(listener5);
65094
+ };
65095
+ }
65096
+ function _setGateArmedWaitMsForTest(ms) {
65097
+ gateArmedWaitOverrideMs = ms;
65098
+ }
65099
+ function gateArmedWaitMs() {
65100
+ return gateArmedWaitOverrideMs ?? GATE_ARMED_WAIT_MS;
65101
+ }
65102
+ function waitForGateArmed(keys2, timeoutMs) {
65103
+ return waitForGateArmedFor(DEFAULT_SESSION_KEY, keys2, timeoutMs);
65104
+ }
65105
+ function waitForGateArmedFor(sessionKey, keys2, timeoutMs) {
65106
+ let wanted = new Set(keys2.filter((k2) => typeof k2 == "string" && k2.length > 0));
65107
+ if (wanted.size === 0)
65108
+ return Promise.resolve(!1);
65109
+ let listeners10 = listenersFor(sessionKey);
65110
+ return new Promise((resolve57) => {
65111
+ let listener5 = (key) => {
65112
+ wanted.has(key) && (listeners10.delete(listener5), clearTimeout(timer2), resolve57(!0));
65113
+ };
65114
+ listeners10.add(listener5);
65115
+ let timer2 = setTimeout(() => {
65116
+ listeners10.delete(listener5), resolve57(!1);
65117
+ }, timeoutMs);
65118
+ });
65119
+ }
65120
+ function armedKeyForQuestionIdFor(sessionKey, questionId) {
65121
+ let base = armedKeyFromQuestionId(questionId);
65122
+ return base.startsWith(PLAN_REVIEW_QUESTION_ID_PREFIX) ? planReviewArmedKeyFor(sessionKey, base.slice(PLAN_REVIEW_QUESTION_ID_PREFIX.length)) : base;
65123
+ }
64913
65124
  function registerArmedGateFromQuestionId(questionId) {
64914
65125
  registerArmedGateFromQuestionIdFor(DEFAULT_SESSION_KEY, questionId);
64915
65126
  }
64916
65127
  function registerArmedGateFromQuestionIdFor(sessionKey, questionId) {
64917
- typeof questionId != "string" || questionId.length === 0 || registerArmedGateFor(sessionKey, armedKeyFromQuestionId(questionId));
65128
+ if (typeof questionId != "string" || questionId.length === 0)
65129
+ return;
65130
+ questionId.startsWith(PLAN_REVIEW_QUESTION_ID_PREFIX) && !questionId.includes(REOPEN_ID_TAIL) && notedPlanReviewIdsByKey.get(sessionKey)?.delete(questionId);
65131
+ let normalized = armedKeyForQuestionIdFor(sessionKey, questionId);
65132
+ registerArmedGateFor(sessionKey, normalized), questionId !== normalized && emitGateArmedEventFor(sessionKey, questionId);
65133
+ }
65134
+ function planReviewArmedKey(taskId) {
65135
+ return planReviewArmedKeyFor(DEFAULT_SESSION_KEY, taskId);
65136
+ }
65137
+ function planReviewArmedKeyFor(sessionKey, taskId) {
65138
+ let gen = planReviewGenByKey.get(sessionKey)?.get(taskId) ?? 0, canonical2 = planReviewQuestionId(taskId);
65139
+ return gen > 0 ? `${canonical2}#g${String(gen)}` : canonical2;
65140
+ }
65141
+ function notePlanReviewAnswered(questionId) {
65142
+ notePlanReviewAnsweredFor(DEFAULT_SESSION_KEY, questionId);
65143
+ }
65144
+ function notePlanReviewAnsweredFor(sessionKey, questionId) {
65145
+ if (typeof questionId != "string" || !questionId.startsWith(PLAN_REVIEW_QUESTION_ID_PREFIX))
65146
+ return;
65147
+ let noted = notedIdsFor(sessionKey);
65148
+ if (noted.has(questionId))
65149
+ return;
65150
+ noted.add(questionId);
65151
+ let base = questionId.slice(PLAN_REVIEW_QUESTION_ID_PREFIX.length), cut = base.indexOf(REOPEN_ID_TAIL), taskId = cut >= 0 ? base.slice(0, cut) : base;
65152
+ if (taskId.length === 0)
65153
+ return;
65154
+ clearArmedGateFor(sessionKey, planReviewArmedKeyFor(sessionKey, taskId));
65155
+ let gens = genMapFor(sessionKey);
65156
+ gens.set(taskId, (gens.get(taskId) ?? 0) + 1);
64918
65157
  }
64919
65158
  function _resetArmedGateRegistryForTest() {
64920
- armedGatesByKey.clear();
65159
+ armedGatesByKey.clear(), armedListenersByKey.clear(), planReviewGenByKey.clear(), notedPlanReviewIdsByKey.clear();
64921
65160
  }
64922
- var armedGatesByKey, init_armedGateRegistry = __esm({
65161
+ var armedGatesByKey, armedListenersByKey, planReviewGenByKey, notedPlanReviewIdsByKey, GATE_ARMED_WAIT_MS, gateArmedWaitOverrideMs, init_armedGateRegistry = __esm({
64923
65162
  "node_modules/@sema-agent/client-core/dist/hitl/armedGateRegistry.js"() {
64924
65163
  init_sessionSlot();
64925
65164
  init_gateIdentity();
64926
- armedGatesByKey = createSessionSlot();
65165
+ armedGatesByKey = createSessionSlot(), armedListenersByKey = createSessionSlot(), planReviewGenByKey = createSessionSlot(), notedPlanReviewIdsByKey = createSessionSlot();
65166
+ GATE_ARMED_WAIT_MS = 5e3, gateArmedWaitOverrideMs = null;
64927
65167
  }
64928
65168
  });
64929
65169
 
@@ -64932,6 +65172,12 @@ function planReviewDecisionFromAnswer(answer) {
64932
65172
  let selected = answer?.answers?.[0]?.selected?.[0];
64933
65173
  return selected === APPROVE_LABEL ? "approve" : selected === REJECT_LABEL ? "reject" : "dismissed";
64934
65174
  }
65175
+ function notePlanReviewAnsweredIfDecisive(questionId, answer) {
65176
+ notePlanReviewAnsweredIfDecisiveFor(DEFAULT_SESSION_KEY, questionId, answer);
65177
+ }
65178
+ function notePlanReviewAnsweredIfDecisiveFor(sessionKey, questionId, answer) {
65179
+ planReviewDecisionFromAnswer(answer ?? { answers: [] }) !== "dismissed" && notePlanReviewAnsweredFor(sessionKey, questionId);
65180
+ }
64935
65181
  function isPlanReviewPark(result) {
64936
65182
  let r = result;
64937
65183
  return !!r && r.status === "needs_review" && r.checkpointGate?.kind === "plan_review" && typeof r.taskId == "string" && r.taskId.length > 0;
@@ -64974,7 +65220,7 @@ function armPlanReviewApproval(result) {
64974
65220
  let questionId = planReviewQuestionId(taskId), unregister = registerLocalQuestionResponder(questionId, async (_id, answer) => {
64975
65221
  unregister(), armedPlanReviewTaskIds.delete(taskId);
64976
65222
  let decided = planReviewDecisionFromAnswer(answer);
64977
- return decided === "dismissed" ? { ok: !0 } : (clearArmedGate(planReviewQuestionId(taskId)), decidePlanReview(taskId, decided), { ok: !0 });
65223
+ return decided === "dismissed" ? { ok: !0 } : (notePlanReviewAnswered(questionId), decidePlanReview(taskId, decided), { ok: !0 });
64978
65224
  });
64979
65225
  return publishPlanReviewCard(taskId), hostLog("debug", `planReviewWire: approval card armed for parked plan (task ${taskId})`), !0;
64980
65226
  } catch (e) {
@@ -65049,19 +65295,29 @@ function _resetActiveReopenRespondersForTest() {
65049
65295
  activeReopenResponders.clear();
65050
65296
  }
65051
65297
  function reopenPlanReviewCard(taskId, opts) {
65298
+ let receiptMs = opts?.presentationReceiptMs, settleOnReceipt = (receipt, firstSight) => receipt.then((presented) => presented ? { reopened: !0, firstSight } : { reopened: !1 }, () => ({ reopened: !1 }));
65052
65299
  try {
65053
65300
  if (typeof taskId != "string" || taskId.length === 0)
65054
- return { reopened: !1 };
65301
+ return receiptMs === void 0 ? { reopened: !1 } : Promise.resolve({ reopened: !1 });
65055
65302
  let sessionKey = opts?.sessionKey ?? DEFAULT_SESSION_KEY;
65056
65303
  if (!hasQuestionOverlayFor(sessionKey))
65057
- return { reopened: !1 };
65058
- let canonicalId = planReviewQuestionId(taskId), firstSight = !wasGateArmedFor(sessionKey, canonicalId);
65059
- if (!(opts?.mintFreshQuestionId !== !1) && hasLocalQuestionResponder(canonicalId))
65060
- return opts?.deliverDecision !== void 0 && hostLog("debug", `planReviewWire: reopen canonical-reuse branch for task ${taskId} ignores opts.deliverDecision (answers route through the existing arm responder \u2014 documented exception)`), retireActiveReopen(sessionKey, canonicalId), publishQuestionFrameFor(sessionKey, {
65304
+ return receiptMs === void 0 ? { reopened: !1 } : Promise.resolve({ reopened: !1 });
65305
+ let canonicalId = planReviewQuestionId(taskId), armedKey = planReviewArmedKeyFor(sessionKey, taskId), firstSight = !wasGateArmedFor(sessionKey, armedKey);
65306
+ if (!(opts?.mintFreshQuestionId !== !1) && hasLocalQuestionResponder(canonicalId)) {
65307
+ if (opts?.deliverDecision !== void 0 && hostLog("debug", `planReviewWire: reopen canonical-reuse branch for task ${taskId} ignores opts.deliverDecision (answers route through the existing arm responder \u2014 documented exception)`), retireActiveReopen(sessionKey, canonicalId), receiptMs !== void 0) {
65308
+ let receipt = waitForGateArmedFor(sessionKey, [canonicalId], receiptMs);
65309
+ return publishQuestionFrameFor(sessionKey, {
65310
+ type: "question",
65311
+ questionId: canonicalId,
65312
+ questions: planReviewQuestions(ARM_QUESTION)
65313
+ }), settleOnReceipt(receipt, firstSight);
65314
+ }
65315
+ return publishQuestionFrameFor(sessionKey, {
65061
65316
  type: "question",
65062
65317
  questionId: canonicalId,
65063
65318
  questions: planReviewQuestions(ARM_QUESTION)
65064
- }), registerArmedGateFor(sessionKey, canonicalId), { reopened: !0, firstSight };
65319
+ }), registerArmedGateFor(sessionKey, armedKey), { reopened: !0, firstSight };
65320
+ }
65065
65321
  retireActiveReopen(sessionKey, canonicalId), unregisterLocalQuestionResponder(canonicalId) && hostLog("debug", `planReviewWire: reopen retired the canonical responder for task ${taskId} (single-active discipline)`), publishQuestionFrameFor(sessionKey, { type: "question_complete", questionId: canonicalId });
65066
65322
  let questionId = `${canonicalId}${REOPEN_ID_TAIL}${reopenIdSuffix()}`, deliver = opts?.deliverDecision ?? ((tid, decision) => {
65067
65323
  decidePlanReview(tid, decision);
@@ -65070,7 +65326,7 @@ function reopenPlanReviewCard(taskId, opts) {
65070
65326
  let decided = planReviewDecisionFromAnswer(answer);
65071
65327
  if (decided === "dismissed")
65072
65328
  return { ok: !0 };
65073
- clearArmedGateFor(sessionKey, canonicalId);
65329
+ notePlanReviewAnsweredFor(sessionKey, questionId);
65074
65330
  try {
65075
65331
  await deliver(taskId, decided);
65076
65332
  } catch (e) {
@@ -65078,13 +65334,21 @@ function reopenPlanReviewCard(taskId, opts) {
65078
65334
  }
65079
65335
  return { ok: !0 };
65080
65336
  });
65081
- return activeReopenResponders.set(activeKey, { questionId, unregister }), registerArmedGateFor(sessionKey, canonicalId), publishQuestionFrameFor(sessionKey, {
65337
+ if (activeReopenResponders.set(activeKey, { questionId, unregister }), receiptMs !== void 0) {
65338
+ let receipt = waitForGateArmedFor(sessionKey, [questionId], receiptMs);
65339
+ return publishQuestionFrameFor(sessionKey, {
65340
+ type: "question",
65341
+ questionId,
65342
+ questions: planReviewQuestions(REOPEN_QUESTION)
65343
+ }), settleOnReceipt(receipt, firstSight);
65344
+ }
65345
+ return registerArmedGateFor(sessionKey, armedKey), publishQuestionFrameFor(sessionKey, {
65082
65346
  type: "question",
65083
65347
  questionId,
65084
65348
  questions: planReviewQuestions(REOPEN_QUESTION)
65085
65349
  }), { reopened: !0, firstSight };
65086
65350
  } catch {
65087
- return { reopened: !1 };
65351
+ return receiptMs === void 0 ? { reopened: !1 } : Promise.resolve({ reopened: !1 });
65088
65352
  }
65089
65353
  }
65090
65354
  var PLAN_REVIEW_RESUME_TIMEOUT_MS, PLAN_REVIEW_APPROVE_LABEL, PLAN_REVIEW_REJECT_LABEL, APPROVE_LABEL, REJECT_LABEL, armedPlanReviewTaskIds, ARM_QUESTION, REOPEN_QUESTION, activeReopenResponders, init_planReviewWire = __esm({
@@ -65106,9 +65370,12 @@ var PLAN_REVIEW_RESUME_TIMEOUT_MS, PLAN_REVIEW_APPROVE_LABEL, PLAN_REVIEW_REJECT
65106
65370
 
65107
65371
  // node_modules/@sema-agent/client-core/dist/hitl/parkOwnership.js
65108
65372
  function pendingRowIsOwnedByThisSession(row2, deps2) {
65109
- let sessionKey = deps2?.sessionKey ?? DEFAULT_SESSION_KEY, rowTaskId = typeof row2.taskId == "string" ? row2.taskId : "", ownRun = deps2?.isOwnRun ?? (sessionKey === DEFAULT_SESSION_KEY ? isOwnEngineRun : void 0);
65110
- if (ownRun !== void 0 && rowTaskId.length > 0 && ownRun(rowIdTail(rowTaskId)))
65111
- return !0;
65373
+ let sessionKey = deps2?.sessionKey ?? DEFAULT_SESSION_KEY, rowTaskId = typeof row2.taskId == "string" ? row2.taskId : "";
65374
+ if (rowTaskId.length > 0) {
65375
+ let tail = rowIdTail(rowTaskId);
65376
+ if (deps2?.isOwnRun !== void 0 && deps2.isOwnRun(tail) || sessionKey === DEFAULT_SESSION_KEY && isOwnEngineRun(tail))
65377
+ return !0;
65378
+ }
65112
65379
  let sessionId = (deps2?.currentSessionId ?? (() => hostSessionFor(sessionKey)?.currentSessionId()))(), rowSessionId = typeof row2.sessionId == "string" ? row2.sessionId : "";
65113
65380
  return typeof sessionId == "string" && sessionId.length > 0 && rowSessionId.length > 0 && rowSessionId === sessionId;
65114
65381
  }
@@ -65136,7 +65403,7 @@ function parkRowPollDelay(ms, signal) {
65136
65403
  return abortableSleep(ms, signal ?? new AbortController().signal);
65137
65404
  }
65138
65405
  async function waitForParkRowBirth(deps2) {
65139
- let now2 = typeof deps2.now == "function" ? deps2.now : () => Date.now(), sleep10 = typeof deps2.sleep == "function" ? deps2.sleep : parkRowPollDelay, budgetMs = Number.isFinite(deps2.budgetMs) && deps2.budgetMs > 0 ? deps2.budgetMs : 0, intervalMs = Number.isFinite(deps2.intervalMs) && deps2.intervalMs > 0 ? deps2.intervalMs : 1, startedAt = now2(), probes = 0, lastReason = "no decidable pending row for this park", aborted2 = () => deps2.signal?.aborted === !0, safeProbe = async (attempt, signal) => {
65406
+ let now2 = typeof deps2.now == "function" ? deps2.now : () => Date.now(), sleep9 = typeof deps2.sleep == "function" ? deps2.sleep : parkRowPollDelay, budgetMs = Number.isFinite(deps2.budgetMs) && deps2.budgetMs > 0 ? deps2.budgetMs : 0, intervalMs = Number.isFinite(deps2.intervalMs) && deps2.intervalMs > 0 ? deps2.intervalMs : 1, startedAt = now2(), probes = 0, lastReason = "no decidable pending row for this park", aborted2 = () => deps2.signal?.aborted === !0, safeProbe = async (attempt, signal) => {
65140
65407
  try {
65141
65408
  return await deps2.probe(attempt, signal);
65142
65409
  } catch (e) {
@@ -65203,7 +65470,7 @@ async function waitForParkRowBirth(deps2) {
65203
65470
  let remainingMs = budgetMs - (now2() - startedAt);
65204
65471
  if (remainingMs <= 0)
65205
65472
  return { kind: "unborn", reason: lastReason, waitedMs: now2() - startedAt, probes };
65206
- if (await sleep10(Math.min(intervalMs, remainingMs), deps2.signal), aborted2())
65473
+ if (await sleep9(Math.min(intervalMs, remainingMs), deps2.signal), aborted2())
65207
65474
  return { kind: "aborted", waitedMs: now2() - startedAt, probes };
65208
65475
  }
65209
65476
  }
@@ -65385,6 +65652,175 @@ var RESUME_CHOICE_ATTACH_LABEL, RESUME_CHOICE_CANCEL_LABEL, RESUME_CHOICE_BACKGR
65385
65652
  }
65386
65653
  });
65387
65654
 
65655
+ // node_modules/@sema-agent/client-core/dist/hitl/persistedRulesWire.js
65656
+ function persistedRulesLaneAvailable(baseUrl) {
65657
+ return engineCapTrue(baseUrl, "permissionRules");
65658
+ }
65659
+ function persistedRulesGovernanceAvailable(baseUrl) {
65660
+ return engineCapTrue(baseUrl, "permissionRulesRevoke") && engineCapTrue(baseUrl, "permissionRules");
65661
+ }
65662
+ function errShape(e) {
65663
+ let o = e ?? {};
65664
+ return {
65665
+ ...typeof o.status == "number" ? { status: o.status } : {},
65666
+ ...typeof o.errorCode == "string" ? { errorCode: o.errorCode } : {},
65667
+ message: typeof o.message == "string" && o.message !== "" ? o.message : String(e)
65668
+ };
65669
+ }
65670
+ function retryAfterSecOf(e) {
65671
+ let ms = e.retryAfterMs;
65672
+ if (!(typeof ms != "number" || !Number.isFinite(ms) || ms < 0))
65673
+ return Math.ceil(ms / 1e3);
65674
+ }
65675
+ function classifyRulesFailure(e) {
65676
+ let { status: status3, errorCode, message } = errShape(e);
65677
+ if (status3 === 501 || errorCode === "capability.rule_store_required")
65678
+ return { kind: "lane-unavailable", message };
65679
+ if (status3 === 404)
65680
+ return errorCode === "not_found.route" ? { kind: "route-missing", message } : errorCode === "not_found.rule_ticket" ? { kind: "ticket-dead", message } : { kind: "error", message };
65681
+ if (errorCode === "state.rule_import_retry") {
65682
+ let sec = retryAfterSecOf(e);
65683
+ return { kind: "retry-same-ticket", message, ...sec !== void 0 ? { retryAfterSec: sec } : {} };
65684
+ }
65685
+ return errorCode === "state.rule_remove_failed" ? { kind: "retryable", message } : status3 === 400 && errorCode === "request.query_invalid" ? { kind: "cursor-stale", message } : status3 === 413 ? { kind: "too-many-candidates", message } : status3 === 403 && errorCode === "auth.operator_only" ? { kind: "forbidden", message } : { kind: "error", message };
65686
+ }
65687
+ async function listAllPersistedRules(facade, params = {}, opts) {
65688
+ let { cursor: callerCursor, ...cleanParams3 } = params;
65689
+ callerCursor !== void 0 && hostLog("debug", "persistedRulesWire: caller-supplied cursor ignored by listAllPersistedRules \u2014 a drain that starts mid-keyset cannot prove completeness, so it always starts from the top");
65690
+ for (let attempt = 0; attempt < 2; attempt++) {
65691
+ let rules = [], cursor, rev2 = null, restart = !1;
65692
+ for (let page = 0; page < MAX_PAGES; page++) {
65693
+ let res;
65694
+ try {
65695
+ res = await facade.list({ limit: PAGE_LIMIT, ...cleanParams3, ...cursor !== void 0 ? { cursor } : {} }, opts);
65696
+ } catch (e) {
65697
+ let failure = classifyRulesFailure(e);
65698
+ if (failure.kind === "cursor-stale" && cursor !== void 0 && attempt === 0) {
65699
+ hostLog("debug", "persistedRulesWire: rule list cursor was minted on another rev/principal/scope \u2014 dropping it and re-listing from the top (never resuming a stale keyset)"), restart = !0;
65700
+ break;
65701
+ }
65702
+ return { ok: !1, failure };
65703
+ }
65704
+ if (typeof res != "object" || res === null || !Array.isArray(res.rules) || typeof res.rev != "number" || !Number.isFinite(res.rev))
65705
+ return {
65706
+ ok: !1,
65707
+ failure: {
65708
+ kind: "error",
65709
+ message: "rule list page was malformed (missing/ill-typed rules array or rev on a 2xx) \u2014 refusing to certify it as a complete governance list"
65710
+ }
65711
+ };
65712
+ if (rev2 !== null && res.rev !== rev2)
65713
+ return {
65714
+ ok: !1,
65715
+ failure: {
65716
+ kind: "error",
65717
+ message: `rule list rev changed mid-drain (page rev ${res.rev} \u2260 first page rev ${rev2}) on a 2xx \u2014 refusing to stitch a mixed snapshot into one governance list`
65718
+ }
65719
+ };
65720
+ for (let r of res.rules) {
65721
+ let rr = r;
65722
+ if (rr === null || typeof rr != "object" || typeof rr.rule != "string" || rr.rule === "" || typeof rr.scope != "string" || rr.scope === "")
65723
+ return {
65724
+ ok: !1,
65725
+ failure: {
65726
+ kind: "error",
65727
+ message: "rule list page carried a malformed rule row (missing/ill-typed rule or scope) \u2014 refusing to present a list that hides or garbles live rules"
65728
+ }
65729
+ };
65730
+ }
65731
+ rev2 = res.rev, rules.push(...res.rules);
65732
+ let next = res.nextCursor;
65733
+ if (next === void 0)
65734
+ return { ok: !0, rules, rev: rev2 };
65735
+ if (typeof next != "string" || next === "")
65736
+ return {
65737
+ ok: !1,
65738
+ failure: {
65739
+ kind: "error",
65740
+ message: "rule list page carried a malformed nextCursor (neither absent nor a non-empty string) \u2014 refusing to guess where the list ends"
65741
+ }
65742
+ };
65743
+ cursor = next;
65744
+ }
65745
+ if (!restart)
65746
+ return {
65747
+ ok: !1,
65748
+ failure: {
65749
+ kind: "error",
65750
+ message: `rule list did not terminate within ${MAX_PAGES} pages \u2014 refusing to present a partial governance list`
65751
+ }
65752
+ };
65753
+ }
65754
+ return { ok: !1, failure: { kind: "cursor-stale", message: "rule list kept changing under the cursor \u2014 try again" } };
65755
+ }
65756
+ function classifySkippedReason(reason) {
65757
+ let text2 = typeof reason == "string" ? reason : String(reason), idx = text2.indexOf(":");
65758
+ if (idx <= 0)
65759
+ return { text: text2 };
65760
+ let head = text2.slice(0, idx);
65761
+ return /^[a-z][a-z0-9_]*(\.[a-z0-9_]+)*$/.test(head) ? { code: head, text: text2 } : { text: text2 };
65762
+ }
65763
+ function readRulePersistOutcome(ack) {
65764
+ let parsed = readToolApprovalRespondAck(ack);
65765
+ return parsed === void 0 ? { state: "unknown" } : parsed.rulePersisted === !0 ? { state: "persisted" } : parsed.rulePersisted === !1 ? {
65766
+ state: "refused",
65767
+ ...typeof parsed.ruleRefusal == "string" ? { reason: parsed.ruleRefusal } : {}
65768
+ } : { state: "unknown" };
65769
+ }
65770
+ var PAGE_LIMIT, MAX_PAGES, init_persistedRulesWire = __esm({
65771
+ "node_modules/@sema-agent/client-core/dist/hitl/persistedRulesWire.js"() {
65772
+ init_engineCapsCache();
65773
+ init_host();
65774
+ init_toolApprovalWire();
65775
+ PAGE_LIMIT = 200, MAX_PAGES = 25;
65776
+ }
65777
+ });
65778
+
65779
+ // node_modules/@sema-agent/client-core/dist/hitl/localAllowRule.js
65780
+ function parseLocalAllowRule(rule, expectedToolName, deps2) {
65781
+ if (typeof rule != "string" || rule === "")
65782
+ return { ok: !1, error: "rule text is empty" };
65783
+ let value;
65784
+ try {
65785
+ value = deps2.parseRule(rule);
65786
+ } catch (e) {
65787
+ return { ok: !1, error: `rule text did not parse (${String(e)})` };
65788
+ }
65789
+ return typeof value.toolName != "string" || value.toolName === "" ? { ok: !1, error: "rule text carries no tool name" } : value.ruleContent === void 0 || value.ruleContent === "" ? {
65790
+ ok: !1,
65791
+ error: "candidate is a whole-tool allow rule (broader than this ask) \u2014 not offered locally"
65792
+ } : expectedToolName !== void 0 && value.toolName !== expectedToolName ? {
65793
+ ok: !1,
65794
+ error: `candidate names tool "${value.toolName}" but this ask is for "${expectedToolName}" \u2014 a rule for another tool would never match`
65795
+ } : hasLiteralAnchor(value.ruleContent) ? value.toolName === BASH_TOOL_NAME_FOR_RULES && deps2.bashRuleContentHasDangerousBarePrefix(value.ruleContent) ? {
65796
+ ok: !1,
65797
+ error: "candidate is a bare interpreter/wrapper prefix (bash/sh/env/sudo/\u2026) \u2014 persisting it would authorize arbitrary commands, not offered locally"
65798
+ } : deps2.isDangerousBashPermission(value.toolName, value.ruleContent) || deps2.isDangerousPowerShellPermission(value.toolName, value.ruleContent) ? {
65799
+ ok: !1,
65800
+ error: "candidate allow-rule matches a code-execution interpreter/wrapper pattern (python/node/eval/ssh/\u2026) \u2014 persisting it would authorize arbitrary code, not offered locally"
65801
+ } : { ok: !0, value, canonical: deps2.formatRule(value) } : {
65802
+ ok: !1,
65803
+ error: "candidate is all wildcard (matches every command for this tool) \u2014 equivalent to a whole-tool allow, not offered locally"
65804
+ };
65805
+ }
65806
+ function hasLiteralAnchor(ruleContent) {
65807
+ let out6 = "";
65808
+ for (let i = 0; i < ruleContent.length; i++) {
65809
+ let ch2 = ruleContent[i];
65810
+ if (ch2 === "\\" && i + 1 < ruleContent.length) {
65811
+ out6 += ruleContent[i + 1], i++;
65812
+ continue;
65813
+ }
65814
+ ch2 !== "*" && (out6 += ch2);
65815
+ }
65816
+ return out6.trim() !== "";
65817
+ }
65818
+ var BASH_TOOL_NAME_FOR_RULES, init_localAllowRule = __esm({
65819
+ "node_modules/@sema-agent/client-core/dist/hitl/localAllowRule.js"() {
65820
+ BASH_TOOL_NAME_FOR_RULES = "Bash";
65821
+ }
65822
+ });
65823
+
65388
65824
  // node_modules/@sema-agent/client-core/dist/hitl/approvalsFeed.js
65389
65825
  function digestOf(rows2) {
65390
65826
  return rows2.map((r) => [r.sessionId ?? "", r.taskId ?? "", r.toolCallId ?? "", r.boundCallId ?? "", r.boundInputHash ?? "", r.toolName ?? ""].join("")).sort().join("");
@@ -67067,6 +67503,7 @@ __export(dist_exports, {
67067
67503
  DEVICE_CODE_MAX_LIFETIME_MS: () => DEVICE_CODE_MAX_LIFETIME_MS,
67068
67504
  DEVICE_CODE_MIN_INTERVAL_MS: () => DEVICE_CODE_MIN_INTERVAL_MS,
67069
67505
  DIFF_TIMEOUT_MS: () => DIFF_TIMEOUT_MS,
67506
+ DRAINING_ERROR_CODE: () => DRAINING_ERROR_CODE,
67070
67507
  EDIT_NOT_FORWARDED_WARN_TEXT: () => EDIT_NOT_FORWARDED_WARN_TEXT,
67071
67508
  ENABLE_FORK_ENV: () => ENABLE_FORK_ENV,
67072
67509
  ENGINE_ABORT_TOOL_RESULT: () => ENGINE_ABORT_TOOL_RESULT,
@@ -67104,6 +67541,7 @@ __export(dist_exports, {
67104
67541
  HitlBridge: () => HitlBridge,
67105
67542
  HitlSafetyError: () => HitlSafetyError,
67106
67543
  IDLE_FLUSH_MS: () => IDLE_FLUSH_MS,
67544
+ INTERACTIVE_WAY_OUT: () => INTERACTIVE_WAY_OUT,
67107
67545
  INTERNAL_SDK_ARM_TYPES: () => INTERNAL_SDK_ARM_TYPES,
67108
67546
  LIMITS_MAX_COST_EXCEEDED: () => LIMITS_MAX_COST_EXCEEDED,
67109
67547
  LIMITS_MAX_TOKENS_EXCEEDED: () => LIMITS_MAX_TOKENS_EXCEEDED,
@@ -67152,6 +67590,7 @@ __export(dist_exports, {
67152
67590
  REMEMBER_NOT_APPLIED_WARN_TEXT: () => REMEMBER_NOT_APPLIED_WARN_TEXT,
67153
67591
  REOPEN_ID_TAIL: () => REOPEN_ID_TAIL,
67154
67592
  REQUEST_FIELD_MATRIX: () => REQUEST_FIELD_MATRIX,
67593
+ RESUME_AT_ERROR_CODE_PREFIX: () => RESUME_AT_ERROR_CODE_PREFIX,
67155
67594
  RESUME_CHOICE_ATTACH_LABEL: () => RESUME_CHOICE_ATTACH_LABEL,
67156
67595
  RESUME_CHOICE_BACKGROUND_LABEL: () => RESUME_CHOICE_BACKGROUND_LABEL,
67157
67596
  RESUME_CHOICE_CANCEL_LABEL: () => RESUME_CHOICE_CANCEL_LABEL,
@@ -67166,6 +67605,7 @@ __export(dist_exports, {
67166
67605
  SANDBOX_NO_IMAGE_INDEX_400_ANCHOR: () => SANDBOX_NO_IMAGE_INDEX_400_ANCHOR,
67167
67606
  SANDBOX_NO_PUBLISHED_IMAGE_404_ANCHOR: () => SANDBOX_NO_PUBLISHED_IMAGE_404_ANCHOR,
67168
67607
  SCENARIO_NAME_RE: () => SCENARIO_NAME_RE,
67608
+ SCENARIO_NOT_ALLOWED_ERROR_CODE: () => SCENARIO_NOT_ALLOWED_ERROR_CODE,
67169
67609
  SDK_DEFAULT_GRACE_MS: () => SDK_DEFAULT_GRACE_MS,
67170
67610
  SEARCH_PROVIDER_PRESETS: () => SEARCH_PROVIDER_PRESETS,
67171
67611
  SEAT_CHROME_ENVELOPE_KEYS: () => SEAT_CHROME_ENVELOPE_KEYS,
@@ -67213,6 +67653,7 @@ __export(dist_exports, {
67213
67653
  WEB_SEARCH_ENV_KEYS: () => WEB_SEARCH_ENV_KEYS,
67214
67654
  WEB_SEARCH_MAX_RESULTS_MAX: () => WEB_SEARCH_MAX_RESULTS_MAX,
67215
67655
  WEB_SEARCH_MAX_RESULTS_MIN: () => WEB_SEARCH_MAX_RESULTS_MIN,
67656
+ WIRE_NETWORK_ERROR_PATTERN: () => WIRE_NETWORK_ERROR_PATTERN,
67216
67657
  WORKFLOW_DEFER_ENV: () => WORKFLOW_DEFER_ENV,
67217
67658
  WORKFLOW_TOOL_NAMES: () => WORKFLOW_TOOL_NAMES,
67218
67659
  __activeTailCountForTests: () => __activeTailCountForTests,
@@ -67245,6 +67686,7 @@ __export(dist_exports, {
67245
67686
  _resetNotificationQueuePortForTest: () => _resetNotificationQueuePortForTest,
67246
67687
  _resetScratchpadEnsuredForTest: () => _resetScratchpadEnsuredForTest,
67247
67688
  _resetUltracodePreset: () => _resetUltracodePreset,
67689
+ _setGateArmedWaitMsForTest: () => _setGateArmedWaitMsForTest,
67248
67690
  _setWatcherTimingForTest: () => _setWatcherTimingForTest,
67249
67691
  _tickWatchOnceForTest: () => _tickWatchOnceForTest,
67250
67692
  activeEngineRunId: () => activeEngineRunId,
@@ -67290,7 +67732,10 @@ __export(dist_exports, {
67290
67732
  classifyAskParkChainFailure: () => classifyAskParkChainFailure,
67291
67733
  classifyAskParkRows: () => classifyAskParkRows,
67292
67734
  classifyHookNoticeFrame: () => classifyHookNoticeFrame,
67735
+ classifyRulesFailure: () => classifyRulesFailure,
67736
+ classifySkippedReason: () => classifySkippedReason,
67293
67737
  classifyTaskStopConflict: () => classifyTaskStopConflict,
67738
+ classifyTurnWireError: () => classifyTurnWireError,
67294
67739
  clearAllRetainedFleetRows: () => clearAllRetainedFleetRows,
67295
67740
  clearAllRetainedFleetRowsFor: () => clearAllRetainedFleetRowsFor,
67296
67741
  clearArmedGate: () => clearArmedGate,
@@ -67335,6 +67780,7 @@ __export(dist_exports, {
67335
67780
  deviceAuthProviderFor: () => deviceAuthProviderFor,
67336
67781
  diagnoseSseIdleTear: () => diagnoseSseIdleTear,
67337
67782
  doneToSdkResult: () => doneToSdkResult,
67783
+ drainingRetryDelayMs: () => drainingRetryDelayMs,
67338
67784
  dropQueuedNotificationsForRun: () => dropQueuedNotificationsForRun,
67339
67785
  effortToReasoningEffort: () => effortToReasoningEffort,
67340
67786
  enableForkFromEnv: () => enableForkFromEnv,
@@ -67345,6 +67791,7 @@ __export(dist_exports, {
67345
67791
  engineCapsSettled: () => engineCapsSettled,
67346
67792
  engineCcStopSemantics: () => engineCcStopSemantics,
67347
67793
  engineLimitsSupportWarning: () => engineLimitsSupportWarning,
67794
+ engineNamespaceKeyFor: () => engineNamespaceKeyFor,
67348
67795
  engineOwnedRowIds: () => engineOwnedRowIds,
67349
67796
  engineRowNeedsStopConfirm: () => engineRowNeedsStopConfirm,
67350
67797
  engineSessionParam: () => engineSessionParam,
@@ -67379,6 +67826,7 @@ __export(dist_exports, {
67379
67826
  fleetViewStubRowIds: () => fleetViewStubRowIds,
67380
67827
  fmtCtxOut: () => fmtCtxOut,
67381
67828
  fmtTokens: () => fmtTokens,
67829
+ gateArmedWaitMs: () => gateArmedWaitMs,
67382
67830
  gateKind: () => gateKind,
67383
67831
  getBgParentRun: () => getBgParentRun,
67384
67832
  getBgTerminalFacts: () => getBgTerminalFacts,
@@ -67435,6 +67883,7 @@ __export(dist_exports, {
67435
67883
  installHostFor: () => installHostFor,
67436
67884
  installNotificationQueuePort: () => installNotificationQueuePort,
67437
67885
  installSubagentActivitySink: () => installSubagentActivitySink,
67886
+ installSubagentTailMetaSink: () => installSubagentTailMetaSink,
67438
67887
  installWorkflowStatusProbe: () => installWorkflowStatusProbe,
67439
67888
  isAllowedCatalogUrl: () => isAllowedCatalogUrl,
67440
67889
  isAlreadyResolvedGateReason: () => isAlreadyResolvedGateReason,
@@ -67462,6 +67911,8 @@ __export(dist_exports, {
67462
67911
  isOwnEngineRun: () => isOwnEngineRun,
67463
67912
  isOwnWorkflowRun: () => isOwnWorkflowRun,
67464
67913
  isPlanReviewPark: () => isPlanReviewPark,
67914
+ isPreStreamDrainingReject: () => isPreStreamDrainingReject,
67915
+ isResumeAtRejection: () => isResumeAtRejection,
67465
67916
  isRewindFamilyCode: () => isRewindFamilyCode,
67466
67917
  isRunStreamActive: () => isRunStreamActive,
67467
67918
  isSeatModelCatalog: () => isSeatModelCatalog,
@@ -67472,10 +67923,12 @@ __export(dist_exports, {
67472
67923
  isToolApprovalFrame: () => isToolApprovalFrame,
67473
67924
  isToolApprovalGate: () => isToolApprovalGate,
67474
67925
  isToolPermissionRequest: () => isToolPermissionRequest,
67926
+ isWireTransportError: () => isWireTransportError,
67475
67927
  isWorkflowAgentTaskId: () => isWorkflowAgentTaskId,
67476
67928
  isWorkflowCompletionCardEnqueued: () => isWorkflowCompletionCardEnqueued,
67477
67929
  kickEngineCapsProbe: () => kickEngineCapsProbe,
67478
67930
  limitsForPrint: () => limitsForPrint,
67931
+ listAllPersistedRules: () => listAllPersistedRules,
67479
67932
  listNotifiedRuns: () => listNotifiedRuns,
67480
67933
  listOwnWorkflowRuns: () => listOwnWorkflowRuns,
67481
67934
  listWorkflowCompletionCardsEnqueued: () => listWorkflowCompletionCardsEnqueued,
@@ -67492,7 +67945,9 @@ __export(dist_exports, {
67492
67945
  markUserModelPickThisSession: () => markUserModelPickThisSession,
67493
67946
  mcpConfigToSpec: () => mcpConfigToSpec,
67494
67947
  mcpConfigsToSpecs: () => mcpConfigsToSpecs,
67948
+ mergeEngineEntry: () => mergeEngineEntry,
67495
67949
  mergeProviderLayers: () => mergeProviderLayers,
67950
+ mergeSessionMapRecord: () => mergeSessionMapRecord,
67496
67951
  mergeTaskOutput: () => mergeTaskOutput,
67497
67952
  modelFacingParseCalls: () => modelFacingParseCalls,
67498
67953
  modelFromAppState: () => modelFromAppState,
@@ -67500,11 +67955,18 @@ __export(dist_exports, {
67500
67955
  normalizeLiveModelRef: () => normalizeLiveModelRef,
67501
67956
  normalizeShellPermissionModeForWire: () => normalizeShellPermissionModeForWire,
67502
67957
  normalizeTaskNotification: () => normalizeTaskNotification,
67958
+ normalizeWirePrincipal: () => normalizeWirePrincipal,
67959
+ notePlanReviewAnswered: () => notePlanReviewAnswered,
67960
+ notePlanReviewAnsweredFor: () => notePlanReviewAnsweredFor,
67961
+ notePlanReviewAnsweredIfDecisive: () => notePlanReviewAnsweredIfDecisive,
67962
+ notePlanReviewAnsweredIfDecisiveFor: () => notePlanReviewAnsweredIfDecisiveFor,
67503
67963
  noteWorkflowCompletionCardEnqueued: () => noteWorkflowCompletionCardEnqueued,
67504
67964
  notificationDropCounters: () => notificationDropCounters,
67505
67965
  notificationQueuePortMisses: () => notificationQueuePortMisses,
67506
67966
  observeCancelByDeny: () => observeCancelByDeny,
67507
67967
  onEngineTaskBound: () => onEngineTaskBound,
67968
+ onGateArmed: () => onGateArmed,
67969
+ onGateArmedFor: () => onGateArmedFor,
67508
67970
  onQuestionFrame: () => onQuestionFrame,
67509
67971
  onQuestionFrameFor: () => onQuestionFrameFor,
67510
67972
  oneShotFromEnv: () => oneShotFromEnv,
@@ -67518,6 +67980,7 @@ __export(dist_exports, {
67518
67980
  parseCatalogSources: () => parseCatalogSources,
67519
67981
  parseFinalVerifyArgv: () => parseFinalVerifyArgv,
67520
67982
  parseLimitsArgv: () => parseLimitsArgv,
67983
+ parseLocalAllowRule: () => parseLocalAllowRule,
67521
67984
  parseModelFacingBash: () => parseModelFacingBash,
67522
67985
  parseModelFacingTaskOutput: () => parseModelFacingTaskOutput,
67523
67986
  parseNoFinalVerifyArgv: () => parseNoFinalVerifyArgv,
@@ -67528,9 +67991,13 @@ __export(dist_exports, {
67528
67991
  pendingRowIsOwnedByThisSession: () => pendingRowIsOwnedByThisSession,
67529
67992
  permissionModeField: () => permissionModeField,
67530
67993
  permissionModeFromArgv: () => permissionModeFromArgv,
67994
+ persistedRulesGovernanceAvailable: () => persistedRulesGovernanceAvailable,
67995
+ persistedRulesLaneAvailable: () => persistedRulesLaneAvailable,
67531
67996
  pickCheapCandidate: () => pickCheapCandidate,
67532
67997
  pickDelegatedPrompt: () => pickDelegatedPrompt,
67533
67998
  planModeExplicitlyRequested: () => planModeExplicitlyRequested,
67999
+ planReviewArmedKey: () => planReviewArmedKey,
68000
+ planReviewArmedKeyFor: () => planReviewArmedKeyFor,
67534
68001
  planReviewDecisionFromAnswer: () => planReviewDecisionFromAnswer,
67535
68002
  planReviewQuestionId: () => planReviewQuestionId,
67536
68003
  planSubagentViewSlots: () => planSubagentViewSlots,
@@ -67562,6 +68029,7 @@ __export(dist_exports, {
67562
68029
  readDecisionNoteAudit: () => readDecisionNoteAudit,
67563
68030
  readEngineActiveBgTasks: () => readEngineActiveBgTasks,
67564
68031
  readEngineActiveBgTasksFor: () => readEngineActiveBgTasksFor,
68032
+ readRulePersistOutcome: () => readRulePersistOutcome,
67565
68033
  readSteerDelivery: () => readSteerDelivery,
67566
68034
  readSteerReceiptStatus: () => readSteerReceiptStatus,
67567
68035
  readToolApprovalRespondAck: () => readToolApprovalRespondAck,
@@ -67617,6 +68085,7 @@ __export(dist_exports, {
67617
68085
  sandboxDegradeHint: () => sandboxDegradeHint,
67618
68086
  sandboxRequestFields: () => sandboxRequestFields,
67619
68087
  sanitizeToolUseBlock: () => sanitizeToolUseBlock,
68088
+ scenarioDenyFromError: () => scenarioDenyFromError,
67620
68089
  scenarioForPrint: () => scenarioForPrint,
67621
68090
  scratchpadDirField: () => scratchpadDirField,
67622
68091
  searchPresetTableViolations: () => searchPresetTableViolations,
@@ -67690,6 +68159,8 @@ __export(dist_exports, {
67690
68159
  versionSupportsDetach: () => versionSupportsDetach,
67691
68160
  versionSupportsLimits: () => versionSupportsLimits,
67692
68161
  waitForClaimRelease: () => waitForClaimRelease,
68162
+ waitForGateArmed: () => waitForGateArmed,
68163
+ waitForGateArmedFor: () => waitForGateArmedFor,
67693
68164
  waitForParkRowBirth: () => waitForParkRowBirth,
67694
68165
  wasGateArmed: () => wasGateArmed,
67695
68166
  wasGateArmedFor: () => wasGateArmedFor,
@@ -67789,6 +68260,9 @@ var init_dist = __esm({
67789
68260
  init_engineSubagentTail();
67790
68261
  init_engineSessionParam();
67791
68262
  init_engineWireTarget();
68263
+ init_principalWire();
68264
+ init_wireErrorTriage();
68265
+ init_sessionMap();
67792
68266
  init_detachWire();
67793
68267
  init_workflowMonitor();
67794
68268
  init_workflowClient();
@@ -67809,6 +68283,8 @@ var init_dist = __esm({
67809
68283
  init_approvalDecisionNoteAudit();
67810
68284
  init_askParkRowRouting();
67811
68285
  init_resumeRunningCard();
68286
+ init_persistedRulesWire();
68287
+ init_localAllowRule();
67812
68288
  init_approvalsFeed();
67813
68289
  init_compensations();
67814
68290
  init_printNotification();
@@ -106717,11 +107193,11 @@ var require_valid = __commonJS({
106717
107193
  var require_clean = __commonJS({
106718
107194
  "node_modules/semver/functions/clean.js"(exports2, module2) {
106719
107195
  "use strict";
106720
- var parse12 = require_parse2(), clean5 = (version4, options) => {
107196
+ var parse12 = require_parse2(), clean6 = (version4, options) => {
106721
107197
  let s = parse12(version4.trim().replace(/^[=v]+/, ""), options);
106722
107198
  return s ? s.version : null;
106723
107199
  };
106724
- module2.exports = clean5;
107200
+ module2.exports = clean6;
106725
107201
  }
106726
107202
  });
106727
107203
 
@@ -107509,11 +107985,11 @@ var require_subset = __commonJS({
107509
107985
  var require_semver2 = __commonJS({
107510
107986
  "node_modules/semver/index.js"(exports2, module2) {
107511
107987
  "use strict";
107512
- var internalRe = require_re(), constants7 = require_constants2(), SemVer = require_semver(), identifiers = require_identifiers(), parse12 = require_parse2(), valid = require_valid(), clean5 = require_clean(), inc = require_inc(), diff2 = require_diff(), major2 = require_major(), minor2 = require_minor(), patch2 = require_patch(), prerelease = require_prerelease(), compare = require_compare(), rcompare = require_rcompare(), compareLoose = require_compare_loose(), compareBuild = require_compare_build(), sort = require_sort(), rsort = require_rsort(), gt2 = require_gt(), lt2 = require_lt(), eq2 = require_eq(), neq = require_neq(), gte2 = require_gte(), lte = require_lte(), cmp = require_cmp(), coerce5 = require_coerce(), truncate4 = require_truncate(), Comparator = require_comparator(), Range2 = require_range2(), satisfies2 = require_satisfies(), toComparators = require_to_comparators(), maxSatisfying = require_max_satisfying(), minSatisfying = require_min_satisfying(), minVersion = require_min_version(), validRange = require_valid2(), outside = require_outside(), gtr = require_gtr(), ltr = require_ltr(), intersects = require_intersects(), simplifyRange = require_simplify(), subset = require_subset();
107988
+ var internalRe = require_re(), constants7 = require_constants2(), SemVer = require_semver(), identifiers = require_identifiers(), parse12 = require_parse2(), valid = require_valid(), clean6 = require_clean(), inc = require_inc(), diff2 = require_diff(), major2 = require_major(), minor2 = require_minor(), patch2 = require_patch(), prerelease = require_prerelease(), compare = require_compare(), rcompare = require_rcompare(), compareLoose = require_compare_loose(), compareBuild = require_compare_build(), sort = require_sort(), rsort = require_rsort(), gt2 = require_gt(), lt2 = require_lt(), eq2 = require_eq(), neq = require_neq(), gte2 = require_gte(), lte = require_lte(), cmp = require_cmp(), coerce5 = require_coerce(), truncate4 = require_truncate(), Comparator = require_comparator(), Range2 = require_range2(), satisfies2 = require_satisfies(), toComparators = require_to_comparators(), maxSatisfying = require_max_satisfying(), minSatisfying = require_min_satisfying(), minVersion = require_min_version(), validRange = require_valid2(), outside = require_outside(), gtr = require_gtr(), ltr = require_ltr(), intersects = require_intersects(), simplifyRange = require_simplify(), subset = require_subset();
107513
107989
  module2.exports = {
107514
107990
  parse: parse12,
107515
107991
  valid,
107516
- clean: clean5,
107992
+ clean: clean6,
107517
107993
  inc,
107518
107994
  diff: diff2,
107519
107995
  major: major2,
@@ -108625,7 +109101,7 @@ var import_stack_utils, import_jsx_runtime6, cleanupPath, stackUtils, init_Error
108625
109101
  // build-src/src/ink/components/TerminalSizeContext.tsx
108626
109102
  var import_react9, TerminalSizeContext, init_TerminalSizeContext = __esm({
108627
109103
  "build-src/src/ink/components/TerminalSizeContext.tsx"() {
108628
- import_react9 = __toESM(require_react()), TerminalSizeContext = (0, import_react9.createContext)(null);
109104
+ import_react9 = __toESM(require_react(), 1), TerminalSizeContext = (0, import_react9.createContext)(null);
108629
109105
  }
108630
109106
  });
108631
109107
 
@@ -114575,8 +115051,8 @@ function useTerminalTitle(title) {
114575
115051
  let writeRaw = (0, import_react23.useContext)(TerminalWriteContext);
114576
115052
  (0, import_react23.useEffect)(() => {
114577
115053
  if (title === null || !writeRaw) return;
114578
- let clean5 = stripAnsi(title);
114579
- process.platform === "win32" ? process.title = clean5 : writeRaw(osc(OSC.SET_TITLE_AND_ICON, clean5));
115054
+ let clean6 = stripAnsi(title);
115055
+ process.platform === "win32" ? process.title = clean6 : writeRaw(osc(OSC.SET_TITLE_AND_ICON, clean6));
114580
115056
  }, [title, writeRaw]);
114581
115057
  }
114582
115058
  var import_react23, init_use_terminal_title = __esm({
@@ -114701,265 +115177,15 @@ var init_types8 = __esm({
114701
115177
  });
114702
115178
 
114703
115179
  // build-src/src/sema/activeRunSelfHeal.ts
114704
- function activeRunBusySignal2(ev) {
114705
- if (typeof ev != "object" || ev === null || !("type" in ev)) return null;
114706
- let type = ev.type, carrier;
114707
- if (type === "done") {
114708
- if (!("result" in ev)) return null;
114709
- let result = ev.result;
114710
- if (typeof result != "object" || result === null || !("status" in result) || result.status !== "failed") return null;
114711
- carrier = result;
114712
- } else if (type === "failed")
114713
- carrier = ev;
114714
- else
114715
- return null;
114716
- let errorCode = "errorCode" in carrier ? carrier.errorCode : void 0, activeTaskId = "activeTaskId" in carrier ? carrier.activeTaskId : void 0, activeTaskStatus = "activeTaskStatus" in carrier ? carrier.activeTaskStatus : void 0, rawGate = "pendingGate" in carrier ? carrier.pendingGate : void 0, codeHit = errorCode === ACTIVE_RUN_BUSY_ERROR_CODE, handle2 = typeof activeTaskId == "string" && activeTaskId.length > 0 ? activeTaskId : null;
114717
- if (!codeHit && handle2 === null) return null;
114718
- let pendingGate = null;
114719
- if (typeof rawGate == "object" && rawGate !== null) {
114720
- let k2 = "kind" in rawGate ? rawGate.kind : void 0, p = "decidePath" in rawGate ? rawGate.decidePath : void 0, g6 = "governanceForced" in rawGate ? rawGate.governanceForced : void 0;
114721
- pendingGate = {
114722
- kind: typeof k2 == "string" && k2.length > 0 ? k2 : null,
114723
- decidePath: typeof p == "string" && p.length > 0 ? p : null,
114724
- ...g6 === !0 ? { governanceForced: !0 } : {}
114725
- };
114726
- }
114727
- return {
114728
- activeTaskId: handle2,
114729
- activeTaskStatus: typeof activeTaskStatus == "string" && activeTaskStatus.length > 0 ? activeTaskStatus : null,
114730
- pendingGate
114731
- };
114732
- }
114733
- function describeFailure2(e) {
114734
- if (typeof e == "object" && e !== null && "message" in e) {
114735
- let m2 = e.message;
114736
- if (typeof m2 == "string" && m2.length > 0) return m2.length > 200 ? `${m2.slice(0, 200)}\u2026` : m2;
114737
- }
114738
- return "the engine gave no detail";
114739
- }
114740
- function readStatus2(record2) {
114741
- if (typeof record2 != "object" || record2 === null || !("status" in record2)) return null;
114742
- let st2 = record2.status;
114743
- return typeof st2 == "string" && st2.length > 0 ? st2 : null;
114744
- }
114745
- function steerFailureClass(e) {
114746
- let status3 = e?.status;
114747
- return typeof status3 == "number" && status3 >= 400 && status3 < 500 ? "rejected" : "unknown";
114748
- }
114749
- function readDelivery(receipt) {
114750
- if (typeof receipt != "object" || receipt === null || !("delivery" in receipt)) return null;
114751
- let d4 = receipt.delivery;
114752
- return typeof d4 == "string" && d4.length > 0 ? d4 : null;
114753
- }
114754
- function readReceiptStatus(receipt) {
114755
- if (typeof receipt != "object" || receipt === null || !("status" in receipt)) return null;
114756
- let s = receipt.status;
114757
- return typeof s == "string" && s.length > 0 ? s : null;
114758
- }
114759
- function cancelReleaseWaitMs() {
114760
- return cancelReleaseWaitOverrideMs ?? CANCEL_RELEASE_WAIT_MS2;
114761
- }
114762
- function sleep2(ms, signal) {
114763
- return signal?.aborted === !0 ? Promise.resolve() : new Promise((resolve57) => {
114764
- let timer2 = setTimeout(() => {
114765
- signal?.removeEventListener("abort", onAbort), resolve57();
114766
- }, ms), onAbort = () => {
114767
- clearTimeout(timer2), resolve57();
114768
- };
114769
- signal?.addEventListener("abort", onAbort, { once: !0 });
114770
- });
114771
- }
114772
- function claimProbeSignal(caller, deadline) {
114773
- let remaining = Math.max(1, deadline - Date.now()), budget = AbortSignal.timeout(remaining);
114774
- if (caller === void 0) return budget;
114775
- if (typeof AbortSignal.any == "function") return AbortSignal.any([caller, budget]);
114776
- let ac = new AbortController(), abort = (s) => ac.abort(s.reason);
114777
- return caller.aborted ? abort(caller) : caller.addEventListener("abort", () => abort(caller), { once: !0 }), budget.addEventListener("abort", () => abort(budget), { once: !0 }), ac.signal;
114778
- }
114779
- async function waitForClaimRelease2(taskId, get4, budgetMs, signal) {
114780
- let startedAt = Date.now(), deadline = startedAt + budgetMs, waited = () => Date.now() - startedAt, isAborted3 = () => signal?.aborted === !0, delay = CANCEL_POLL_START_MS2;
114781
- for (; ; ) {
114782
- if (isAborted3()) return { released: !1, waitedMs: waited(), aborted: !0 };
114783
- let remaining = deadline - Date.now();
114784
- if (remaining <= 0) return { released: !1, waitedMs: waited(), aborted: !1 };
114785
- if (await sleep2(Math.min(delay, remaining), signal), isAborted3()) return { released: !1, waitedMs: waited(), aborted: !0 };
114786
- delay = Math.min(Math.round(delay * 1.5), CANCEL_POLL_MAX_MS2);
114787
- let status3;
114788
- try {
114789
- status3 = readStatus2(await get4(taskId, { signal: claimProbeSignal(signal, deadline) }));
114790
- } catch (e) {
114791
- if (isAborted3()) return { released: !1, waitedMs: waited(), aborted: !0 };
114792
- if (e?.status === 404) return { released: !0, waitedMs: waited(), aborted: !1 };
114793
- continue;
114794
- }
114795
- if (status3 !== null && CLAIM_RELEASED_STATES2.includes(status3)) return { released: !0, waitedMs: waited(), aborted: !1 };
114796
- }
115180
+ function attemptActiveRunSelfHeal2(signal, runs, deps2) {
115181
+ let override = cancelReleaseWaitOverrideMs, merged = override === null || deps2?.cancelReleaseWaitMs !== void 0 ? deps2 : { ...deps2 ?? {}, cancelReleaseWaitMs: override };
115182
+ return attemptActiveRunSelfHeal(signal, runs, merged);
114797
115183
  }
114798
- async function attemptActiveRunSelfHeal2(signal, runs, deps2) {
114799
- let pending2 = !1;
114800
- try {
114801
- pending2 = deps2?.hasPendingDecision?.() === !0;
114802
- } catch {
114803
- pending2 = !1;
114804
- }
114805
- if (pending2 && deps2?.listOwnedPendingApprovals !== void 0)
114806
- try {
114807
- await deps2.listOwnedPendingApprovals() === 0 && (pending2 = !1);
114808
- } catch {
114809
- }
114810
- if (pending2) return { kind: "decision-pending", taskId: signal.activeTaskId };
114811
- let taskId = signal.activeTaskId;
114812
- if (taskId === null)
114813
- return {
114814
- kind: "state-unknown",
114815
- taskId: null,
114816
- detail: "the engine did not name the run that holds this session"
114817
- };
114818
- let planVerdict2 = async () => {
114819
- try {
114820
- return await deps2?.reopenPlanReview?.(taskId) ?? { reopened: !1 };
114821
- } catch {
114822
- return { reopened: !1 };
114823
- }
114824
- }, askVerdict2 = async () => {
114825
- try {
114826
- return await deps2?.reopenAskPark?.(taskId) ?? { reopened: !1 };
114827
- } catch {
114828
- return { reopened: !1 };
114829
- }
114830
- }, reopenPlanArm = async () => {
114831
- let verdict = await planVerdict2();
114832
- return verdict.reopened === !0 ? { kind: "plan-review-reopened", taskId, firstSight: verdict.firstSight === !0 } : { kind: "plan-review-reopen-failed", taskId, decidePath: signal.pendingGate?.decidePath ?? null };
114833
- }, reopenAskArm = async () => {
114834
- let verdict = await askVerdict2();
114835
- return verdict.reopened === !0 ? { kind: "ask-reopened", taskId, firstSight: verdict.firstSight === !0 } : { kind: "ask-reopen-failed", taskId, decidePath: signal.pendingGate?.decidePath ?? null };
114836
- }, runningChoiceArm2 = async (status4) => {
114837
- let notParked = { kind: "not-parked", taskId, status: status4 }, offer = deps2?.offerRunningChoice;
114838
- if (typeof offer != "function") return notParked;
114839
- let text2 = typeof deps2?.deniedMessage == "string" ? deps2.deniedMessage : "", steer = typeof runs?.steer == "function" ? runs.steer.bind(runs) : void 0, cancel = typeof runs?.cancel == "function" ? runs.cancel.bind(runs) : void 0, get4 = typeof runs?.get == "function" ? runs.get.bind(runs) : void 0, canSteer = typeof steer == "function" && text2.length > 0, canCancel = typeof cancel == "function" && typeof get4 == "function";
114840
- if (!canSteer && !canCancel) return notParked;
114841
- let choice = "wait";
114842
- try {
114843
- choice = await offer({ taskId, status: status4, canSteer, canCancel }) ?? "wait";
114844
- } catch {
114845
- choice = "wait";
114846
- }
114847
- if (choice === "steer" && canSteer && steer !== void 0)
114848
- try {
114849
- let receipt = await steer(taskId, { text: text2 }), delivery = readDelivery(receipt), receiptStatus = readReceiptStatus(receipt);
114850
- if (delivery === "queued") {
114851
- let verdict = receiptStatus !== null && PLAN_REVIEW_STATES2.includes(receiptStatus) ? await planVerdict2() : receiptStatus !== null && ASK_PARK_STATES2.includes(receiptStatus) ? await askVerdict2() : null;
114852
- return { kind: "running-steered", taskId, delivery, status: receiptStatus, reopened: verdict };
114853
- }
114854
- return { kind: "running-steered", taskId, delivery, status: receiptStatus, reopened: null };
114855
- } catch (e) {
114856
- return { kind: "running-steer-failed", taskId, detail: describeFailure2(e), delivery: steerFailureClass(e) };
114857
- }
114858
- if (choice === "cancel" && canCancel && cancel !== void 0 && get4 !== void 0) {
114859
- try {
114860
- await cancel(taskId);
114861
- } catch (e) {
114862
- return { kind: "running-cancel-failed", taskId, detail: describeFailure2(e) };
114863
- }
114864
- let verdict = await waitForClaimRelease2(taskId, get4, cancelReleaseWaitMs(), deps2?.signal);
114865
- return verdict.released ? { kind: "running-cancelled", taskId } : { kind: "running-cancel-timeout", taskId, waitedMs: verdict.waitedMs, aborted: verdict.aborted };
114866
- }
114867
- return notParked;
114868
- }, gateKind2 = signal.pendingGate?.kind ?? null;
114869
- if (gateKind2 !== null && PLAN_REVIEW_GATE_KINDS2.includes(gateKind2)) return reopenPlanArm();
114870
- if (gateKind2 !== null && ASK_PARK_GATE_KINDS2.includes(gateKind2)) return reopenAskArm();
114871
- let status3 = signal.activeTaskStatus;
114872
- if (status3 === null) {
114873
- if (typeof runs?.get != "function")
114874
- return { kind: "state-unknown", taskId, detail: "this client exposes no durable run verbs" };
114875
- let record2;
114876
- try {
114877
- record2 = await runs.get(taskId);
114878
- } catch (e) {
114879
- return { kind: "state-unknown", taskId, detail: describeFailure2(e) };
114880
- }
114881
- status3 = readStatus2(record2);
114882
- }
114883
- return status3 === null ? { kind: "state-unknown", taskId, detail: "the engine reported no status for that run" } : gateKind2 !== null ? { kind: "not-parked", taskId, status: status3 } : PLAN_REVIEW_STATES2.includes(status3) ? reopenPlanArm() : ASK_PARK_STATES2.includes(status3) ? reopenAskArm() : RUNNING_STATES2.includes(status3) ? runningChoiceArm2(status3) : { kind: "not-parked", taskId, status: status3 };
114884
- }
114885
- function gateKindPhrase2(kind) {
114886
- return kind ? `a ${kind} decision` : "a decision";
114887
- }
114888
- function decidePathClause2(signal) {
114889
- let decidePath = signal?.pendingGate?.decidePath;
114890
- return decidePath ? ` The engine says that run is waiting on ${gateKindPhrase2(signal?.pendingGate?.kind)} and that it is decided at POST ${decidePath} \u2014 deciding it releases the session.` : "";
114891
- }
114892
- function activeRunSelfHealRow2(outcome, signal) {
114893
- let base = activeRunSelfHealBaseRow2(outcome, signal);
114894
- switch (outcome.kind) {
114895
- // 这两条是「用户此刻卡住了、而且没有别的把手」的结局 —— wire 给的 decide 入口在这里才有用。
114896
- case "not-parked":
114897
- case "state-unknown":
114898
- return base + decidePathClause2(signal) + governanceOriginClause2(signal);
114899
- // 其余结局手上都另有一张更好的把手(重开的卡 / 已开的卡 / 失败臂基句自己渲的 decidePath)
114900
- // (重开的卡 / 已开的卡 / 基句自己渲的 decidePath)—— 再叠一条引擎路由只会稀释那一个动作。
114901
- default:
114902
- return base + governanceOriginClause2(signal);
114903
- }
114904
- }
114905
- function governanceOriginClause2(signal) {
114906
- return signal?.pendingGate?.governanceForced === !0 ? " That gate is enforced by this deployment's governance policy, not by a permission rule you set." : "";
114907
- }
114908
- function activeRunSelfHealBaseRow2(outcome, signal) {
114909
- switch (outcome.kind) {
114910
- case "decision-pending":
114911
- return `This session is held by an earlier turn${outcome.taskId ? ` (run ${outcome.taskId})` : ""} that is waiting on a decision you have not made yet, and there is a decision card open for it. sema did NOT cancel it \u2014 answering that card is what releases the session, and cancelling would decide it for you. Your message was NOT sent; answer the open card and send it again.`;
114912
- case "ask-reopened":
114913
- return outcome.firstSight ? `The previous turn advanced to a decision it needs from you (run ${outcome.taskId}), which is why nothing new could start \u2014 sema has surfaced that decision card. Answer it and send your message again. (sema did NOT cancel the run: cancelling would have decided it for you.)` : `The previous turn is parked waiting for your decision (run ${outcome.taskId}), which is why nothing new could start \u2014 that card was closed without being answered, so sema reopened it. Answer it and send your message again. (sema did NOT cancel the run: cancelling would have decided it for you.)`;
114914
- case "plan-review-reopened":
114915
- return outcome.firstSight ? `The previous turn produced a plan that is waiting for your review (run ${outcome.taskId}), which is why nothing new could start \u2014 sema has surfaced the review card. Answer it and send your message again. (sema did NOT cancel the run: cancelling would have thrown the plan away on your behalf.)` : `The previous turn is parked waiting for you to review its plan (run ${outcome.taskId}), which is why nothing new could start \u2014 that approval card was closed without being answered, so sema reopened it. Answer it and send your message again. (sema did NOT cancel the run: cancelling would have thrown the plan away on your behalf.)`;
114916
- case "ask-reopen-failed": {
114917
- let viaEngine = outcome.decidePath ? ` You can also decide it on the engine directly: POST ${outcome.decidePath}.` : "";
114918
- return `The previous turn is parked waiting for your decision (run ${outcome.taskId}) and sema could not reopen that card here. It did NOT cancel the run \u2014 that would have decided it for you. Your message was NOT sent; ${INTERACTIVE_WAY_OUT} if you no longer want it.${viaEngine}`;
114919
- }
114920
- case "plan-review-reopen-failed": {
114921
- let viaEngine = outcome.decidePath ? ` You can also decide it on the engine directly: POST ${outcome.decidePath}.` : "";
114922
- return `The previous turn is parked waiting for a plan review (run ${outcome.taskId}) and sema could not reopen that approval card. It did NOT cancel the run \u2014 that would have discarded the plan for you. Your message was NOT sent; ${INTERACTIVE_WAY_OUT} if you no longer want that plan.${viaEngine}`;
114923
- }
114924
- // ── C3 三选卡的四种动作结局(选 ③/没答/没呈上都落 not-parked,见下)────────────────────
114925
- case "running-steered": {
114926
- let handle2 = `run ${outcome.taskId}`, textOnly = "Only the TEXT of your message was handed over \u2014 a steer carries no attachments, so any images in that submission were NOT sent.";
114927
- if (outcome.delivery === "applied")
114928
- return `sema handed your message to the run that is already working (${handle2}) \u2014 the engine applied it to that run, so it is picked up at that run's next step. ${textOnly} Nothing was cancelled, and your message did NOT start a new turn \u2014 watch that run for what it does with it.`;
114929
- if (outcome.delivery === "queued") {
114930
- let parked = outcome.status ? `parked (status ${outcome.status})` : "parked", next = outcome.reopened?.reopened === !0 ? "sema has surfaced that decision card \u2014 answering it is what lets that run resume and pick your message up." : `sema could not surface that decision card here, so nothing will resume that run until that decision is made; ${INTERACTIVE_WAY_OUT} if you no longer want it.`;
114931
- return `${handle2} is not actually working right now: the engine reports it ${parked} on a decision it needs from you, so it queued your message on that park instead of running it. ${next} ${textOnly} Nothing was cancelled, and your message did NOT start a new turn.`;
114932
- }
114933
- return outcome.delivery === "parked_for_wake" ? `${handle2} had already finished, so the engine parked your message on that finished run instead of running it \u2014 a parked message is delivered only if this session is woken on the engine (POST /v1/sessions/:id/wake), which sema does not do here. That run is no longer holding this session: send your message again to run it as a new turn. ${textOnly} Nothing was cancelled.` : `sema handed your message to ${handle2}, but the engine did not say how it will be delivered${outcome.status ? ` (it reported that run as ${outcome.status})` : ""}. ${textOnly} Nothing was cancelled, and your message did NOT start a new turn \u2014 watch that run before sending it again.`;
114934
- }
114935
- case "running-steer-failed":
114936
- return outcome.delivery === "rejected" ? `The engine rejected handing your message to the running run (run ${outcome.taskId}): ${outcome.detail}. sema did NOT retry it (a steer is not safe to send twice) and it did NOT cancel that run. Your message was NOT sent; send it again if you still want it.` : `sema sent your message to the running run (run ${outcome.taskId}) but could not confirm what happened to it (${outcome.detail}). A steer is not safe to send twice, so sema did NOT retry it, and it did NOT cancel that run. That run may or may not have received your message \u2014 watch what it does next before sending it again.`;
114937
- case "running-cancelled":
114938
- return `You chose to cancel run ${outcome.taskId}. The engine confirmed it is no longer holding this session, so sema is sending your message now.`;
114939
- case "running-cancel-timeout": {
114940
- let waited = `${String(Math.max(1, Math.round(outcome.waitedMs / 1e3)))}s`;
114941
- return outcome.aborted ? `sema asked the engine to cancel run ${outcome.taskId} and you interrupted while it was still confirming (${waited} in). Cancelling is asynchronous, so that run may still be winding down and may still hold this session. Your message was NOT sent; send it again in a moment, or ${INTERACTIVE_WAY_OUT}.` : `sema asked the engine to cancel run ${outcome.taskId}, but that run still held this session ${waited} later \u2014 cancelling is asynchronous and it may still be winding down. Your message was NOT sent; send it again in a moment, or ${INTERACTIVE_WAY_OUT}.`;
114942
- }
114943
- case "running-cancel-failed":
114944
- return `sema could not cancel run ${outcome.taskId} (${outcome.detail}), so that run is still holding this session and your message was NOT sent. Send it again to retry, or ${INTERACTIVE_WAY_OUT}.`;
114945
- case "not-parked":
114946
- return signal?.pendingGate ? `This session is held by an earlier run (run ${outcome.taskId}, status ${outcome.status}) that is waiting on ${gateKindPhrase2(signal.pendingGate.kind)} \u2014 it will not finish on its own. sema did NOT cancel it, because cancelling would decide that item for you. Your message was NOT sent; ${INTERACTIVE_WAY_OUT} if you no longer want it.` : `This session already has a run in flight (run ${outcome.taskId}, status ${outcome.status}) \u2014 most likely a turn you sent to the background. sema did NOT cancel it, because that would throw away work you asked for. Wait for it to finish, or ${INTERACTIVE_WAY_OUT}.`;
114947
- case "state-unknown":
114948
- return `This session is locked by an earlier run${outcome.taskId ? ` (run ${outcome.taskId})` : ""} and sema could not read that run's state, so it did not touch it (${outcome.detail}). Your message was NOT sent. This session cannot start a new turn until that run settles \u2014 ${INTERACTIVE_WAY_OUT}.`;
114949
- }
114950
- }
114951
- function activeRunBusyHeadlessRow2(signal) {
114952
- let activeTaskId = signal.activeTaskId, handle2 = activeTaskId ? ` (run ${activeTaskId})` : "", cancelPath = `POST /v1/runs/${activeTaskId ?? "<id>"}/cancel`, status3 = signal.activeTaskStatus, decidePath = signal.pendingGate?.decidePath ?? null, freshSession = "start a new session (drop --resume/--continue)";
114953
- return decidePath ? `This session is held by an earlier run${handle2}${status3 ? ` (status ${status3})` : ""} that is parked waiting on ${gateKindPhrase2(signal.pendingGate?.kind)}, so this message was NOT sent. Decide it and the session unlocks: POST ${decidePath}. Cancelling instead (${cancelPath}) also unlocks it, but it decides that item against you. Or ${freshSession}.` + // 出身归因同款(见 governanceOriginClause):这条车道更需要它 —— 没有卡可看,
114954
- // 用户唯一能读到的就是这一段话。
114955
- governanceOriginClause2(signal) : status3 ? `This session is held by an earlier run${handle2} with status ${status3}, so this message was NOT sent. The engine reported no decision pending on that run: if it is still working, wait for it to finish; if it will never settle, release it with ${cancelPath} (that discards whatever it was doing). Or ${freshSession}.` : `This session is locked by an earlier run${handle2} that was never released, so this message was NOT sent. Nothing here clears on its own. Start a new session (drop --resume/--continue), or release the run on the engine: ${cancelPath}`;
114956
- }
114957
- var PLAN_REVIEW_STATES2, ASK_PARK_STATES2, PLAN_REVIEW_GATE_KINDS2, ASK_PARK_GATE_KINDS2, RUNNING_STATES2, CLAIM_RELEASED_STATES2, CANCEL_RELEASE_WAIT_MS2, CANCEL_POLL_START_MS2, CANCEL_POLL_MAX_MS2, cancelReleaseWaitOverrideMs, INTERACTIVE_WAY_OUT, init_activeRunSelfHeal2 = __esm({
115184
+ var cancelReleaseWaitOverrideMs, init_activeRunSelfHeal2 = __esm({
114958
115185
  "build-src/src/sema/activeRunSelfHeal.ts"() {
114959
115186
  init_dist();
114960
- PLAN_REVIEW_STATES2 = ["needs_review"], ASK_PARK_STATES2 = ["suspended"], PLAN_REVIEW_GATE_KINDS2 = ["plan_review", "dry_run_review"], ASK_PARK_GATE_KINDS2 = ["human", "irreversible_ask", "policy_ask", "tool_approval"], RUNNING_STATES2 = ["running"], CLAIM_RELEASED_STATES2 = ["completed", "failed", "blocked", "timeout"];
114961
- CANCEL_RELEASE_WAIT_MS2 = 1e4, CANCEL_POLL_START_MS2 = 200, CANCEL_POLL_MAX_MS2 = 2e3, cancelReleaseWaitOverrideMs = null;
114962
- INTERACTIVE_WAY_OUT = "run /clear to keep working in a fresh session";
115187
+ init_dist();
115188
+ cancelReleaseWaitOverrideMs = null;
114963
115189
  }
114964
115190
  });
114965
115191
 
@@ -114977,7 +115203,7 @@ __export(runStream_exports, {
114977
115203
  function watchActiveRunBusy(events3, seen2) {
114978
115204
  return (async function* () {
114979
115205
  for await (let ev of events3) {
114980
- let busy = activeRunBusySignal2(ev);
115206
+ let busy = activeRunBusySignal(ev);
114981
115207
  busy && (seen2.busy = busy), yield ev;
114982
115208
  }
114983
115209
  })();
@@ -115025,7 +115251,7 @@ function rewriteActiveRunBusyRow(msgs, seen2) {
115025
115251
  ...m2,
115026
115252
  message: {
115027
115253
  ...envelope,
115028
- content: [{ type: "text", text: activeRunBusyHeadlessRow2(busy) }]
115254
+ content: [{ type: "text", text: activeRunBusyHeadlessRow(busy) }]
115029
115255
  }
115030
115256
  };
115031
115257
  continue;
@@ -115049,13 +115275,13 @@ function hostSink(e, billTurnCosts = !0) {
115049
115275
  return;
115050
115276
  }
115051
115277
  if (e.kind === "human_input") {
115052
- let clean5 = (v2) => (
115278
+ let clean6 = (v2) => (
115053
115279
  // eslint-disable-next-line no-control-regex
115054
115280
  String(v2 ?? "").replace(/[\x00-\x1f\x7f]/g, ".").slice(0, 120)
115055
- ), who = e.actor?.id ? `${clean5(e.actor.id)}${e.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
115281
+ ), who = e.actor?.id ? `${clean6(e.actor.id)}${e.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
115056
115282
  Promise.resolve().then(() => (init_debug(), debug_exports)).then(
115057
115283
  (m2) => m2.logForDebugging(
115058
- `[sema][wire] human_input ledger: carrier=${clean5(e.carrier)} source=${clean5(e.source)} delivery=${clean5(e.delivery)} actor=${who}${e.eventId ? ` eventId=${clean5(e.eventId)}` : ""}`
115284
+ `[sema][wire] human_input ledger: carrier=${clean6(e.carrier)} source=${clean6(e.source)} delivery=${clean6(e.delivery)} actor=${who}${e.eventId ? ` eventId=${clean6(e.eventId)}` : ""}`
115059
115285
  )
115060
115286
  ).catch(() => {
115061
115287
  });
@@ -115073,10 +115299,10 @@ function _resetHostDroppedFrameMemoForTest() {
115073
115299
  reportedDroppedTypes2.clear();
115074
115300
  }
115075
115301
  function hostDroppedFrameSink(info) {
115076
- let clean5 = (v2) => (
115302
+ let clean6 = (v2) => (
115077
115303
  // eslint-disable-next-line no-control-regex
115078
115304
  String(v2).replace(/[\x00-\x1f\x7f]/g, ".").slice(0, 120)
115079
- ), type = clean5(info.type), line = `[sema][wire] dropped engine frame: type=${type} why=${clean5(info.why)} \u2014 this build's projector has no arm for it (engine newer than the client, or a malformed frame). It renders NOWHERE.`;
115305
+ ), type = clean6(info.type), line = `[sema][wire] dropped engine frame: type=${type} why=${clean6(info.why)} \u2014 this build's projector has no arm for it (engine newer than the client, or a malformed frame). It renders NOWHERE.`;
115080
115306
  Promise.resolve().then(() => (init_debug(), debug_exports)).then((m2) => {
115081
115307
  m2.logForDebugging(line, { level: "warn" }), !m2.isDebugMode() && process.env.USER_TYPE !== "ant" && consoleLegForDroppedFrame(type, line);
115082
115308
  }).catch(() => consoleLegForDroppedFrame(type, line));
@@ -138794,7 +139020,7 @@ var KEYCHAIN_PREFETCH_TIMEOUT_MS, legacyApiKeyPrefetch, prefetchPromise, init_ke
138794
139020
  });
138795
139021
 
138796
139022
  // build-src/src/utils/sleep.ts
138797
- function sleep3(ms, signal, opts) {
139023
+ function sleep2(ms, signal, opts) {
138798
139024
  return new Promise((resolve57, reject3) => {
138799
139025
  if (signal?.aborted) {
138800
139026
  opts?.throwOnAbort || opts?.abortError ? reject3(opts.abortError?.() ?? new Error("aborted")) : resolve57();
@@ -139221,7 +139447,7 @@ async function checkGcpCredentialsValid() {
139221
139447
  scopes: ["https://www.googleapis.com/auth/cloud-platform"]
139222
139448
  }), probe3 = (async () => {
139223
139449
  await (await auth2.getClient()).getAccessToken();
139224
- })(), timeout3 = sleep3(GCP_CREDENTIALS_CHECK_TIMEOUT_MS).then(() => {
139450
+ })(), timeout3 = sleep2(GCP_CREDENTIALS_CHECK_TIMEOUT_MS).then(() => {
139225
139451
  throw new GcpCredentialsTimeoutError("GCP credentials check timed out");
139226
139452
  });
139227
139453
  return await Promise.race([probe3, timeout3]), !0;
@@ -139425,7 +139651,7 @@ async function checkAndRefreshOAuthTokenIfNeededImpl(retryCount, force) {
139425
139651
  try {
139426
139652
  release2 = await lock(claudeDir), noteStorageLockAcquired();
139427
139653
  } catch (err8) {
139428
- return err8.code === "ELOCKED" ? retryCount < 5 ? (retryCount + 1, await sleep3(1e3 + Math.random() * 1e3), checkAndRefreshOAuthTokenIfNeededImpl(retryCount + 1, force)) : !1 : (logError(err8), errorMessage(
139654
+ return err8.code === "ELOCKED" ? retryCount < 5 ? (retryCount + 1, await sleep2(1e3 + Math.random() * 1e3), checkAndRefreshOAuthTokenIfNeededImpl(retryCount + 1, force)) : !1 : (logError(err8), errorMessage(
139429
139655
  err8
139430
139656
  ), !1);
139431
139657
  }
@@ -143465,7 +143691,7 @@ async function cleanupWorktree() {
143465
143691
  ...current5,
143466
143692
  activeWorktreeSession: void 0
143467
143693
  })), !hookBased && worktreeBranch) {
143468
- await sleep3(100);
143694
+ await sleep2(100);
143469
143695
  let { code: deleteBranchCode, stderr: deleteBranchError } = await execFileNoThrowWithCwd(
143470
143696
  gitExe(),
143471
143697
  ["branch", "-D", worktreeBranch],
@@ -176808,19 +177034,17 @@ function acquireFileLockSyncRetrying(path28) {
176808
177034
  return;
176809
177035
  }
176810
177036
  }
176811
- function engineNamespaceKeyFor(baseUrl) {
176812
- if (!baseUrl) return "local";
176813
- try {
176814
- return new URL(baseUrl).origin.toLowerCase();
176815
- } catch {
176816
- return baseUrl.toLowerCase();
176817
- }
177037
+ function logMergeSkip(reason, key) {
177038
+ logForDebugging(
177039
+ reason === "no-engine-session-id" ? `sessionIdMapping: persistEngineEntry(${key}) skipped \u2014 no engineSessionId` : "sessionIdMapping: persist skipped \u2014 no shellSessionId"
177040
+ );
176818
177041
  }
176819
177042
  var LOCK_STALE_MS3, SessionIdMapping, init_sessionIdMapping = __esm({
176820
177043
  "build-src/src/sema/sessionIdMapping.ts"() {
176821
177044
  init_debug();
176822
177045
  init_lockfile();
176823
177046
  init_slowOperations();
177047
+ init_dist();
176824
177048
  LOCK_STALE_MS3 = 1e4;
176825
177049
  SessionIdMapping = class {
176826
177050
  path;
@@ -176856,21 +177080,21 @@ var LOCK_STALE_MS3, SessionIdMapping, init_sessionIdMapping = __esm({
176856
177080
  */
176857
177081
  persist(partial2) {
176858
177082
  if (!this.path || process.env.SEMA_NO_PERSIST_WIRE === "1") {
176859
- let prior = this.freshPrior(), shellSessionId = partial2.shellSessionId ?? prior?.shellSessionId;
176860
- if (!shellSessionId) {
176861
- logForDebugging("sessionIdMapping: persist skipped \u2014 no shellSessionId");
177083
+ let verdict = mergeSessionMapRecord(this.freshPrior(), partial2);
177084
+ if (!verdict.ok) {
177085
+ logMergeSkip(verdict.reason);
176862
177086
  return;
176863
177087
  }
176864
- this.cache = { ...prior, ...partial2, shellSessionId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
177088
+ this.cache = verdict.record;
176865
177089
  return;
176866
177090
  }
176867
- let next = this.lockedReadMergeWrite(this.path, (prior) => {
176868
- let shellSessionId = partial2.shellSessionId ?? prior?.shellSessionId;
176869
- if (!shellSessionId) {
176870
- logForDebugging("sessionIdMapping: persist skipped \u2014 no shellSessionId");
177091
+ let next = this.storeFor(this.path).readMergeWrite((prior) => {
177092
+ let verdict = mergeSessionMapRecord(prior, partial2);
177093
+ if (!verdict.ok) {
177094
+ logMergeSkip(verdict.reason);
176871
177095
  return;
176872
177096
  }
176873
- return { ...prior, ...partial2, shellSessionId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
177097
+ return verdict.record;
176874
177098
  });
176875
177099
  next && (this.cache = next);
176876
177100
  }
@@ -176893,43 +177117,21 @@ var LOCK_STALE_MS3, SessionIdMapping, init_sessionIdMapping = __esm({
176893
177117
  */
176894
177118
  persistEngineEntry(key, partial2, shellSessionId) {
176895
177119
  if (!this.path || process.env.SEMA_NO_PERSIST_WIRE === "1") {
176896
- let prior = this.freshPrior(), priorEntry = prior?.engines?.[key], engineSessionId = partial2.engineSessionId ?? priorEntry?.engineSessionId;
176897
- if (!engineSessionId) {
176898
- logForDebugging(`sessionIdMapping: persistEngineEntry(${key}) skipped \u2014 no engineSessionId`);
176899
- return;
176900
- }
176901
- let sid = shellSessionId ?? prior?.shellSessionId;
176902
- if (!sid) {
176903
- logForDebugging("sessionIdMapping: persist skipped \u2014 no shellSessionId");
177120
+ let verdict = mergeEngineEntry(this.freshPrior(), key, partial2, shellSessionId);
177121
+ if (!verdict.ok) {
177122
+ logMergeSkip(verdict.reason, key);
176904
177123
  return;
176905
177124
  }
176906
- let entry = { ...priorEntry, ...partial2, engineSessionId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
176907
- this.cache = {
176908
- ...prior,
176909
- shellSessionId: sid,
176910
- engines: { ...prior?.engines, [key]: entry },
176911
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
176912
- };
177125
+ this.cache = verdict.record;
176913
177126
  return;
176914
177127
  }
176915
- let next = this.lockedReadMergeWrite(this.path, (prior) => {
176916
- let priorEntry = prior?.engines?.[key], engineSessionId = partial2.engineSessionId ?? priorEntry?.engineSessionId;
176917
- if (!engineSessionId) {
176918
- logForDebugging(`sessionIdMapping: persistEngineEntry(${key}) skipped \u2014 no engineSessionId`);
177128
+ let next = this.storeFor(this.path).readMergeWrite((prior) => {
177129
+ let verdict = mergeEngineEntry(prior, key, partial2, shellSessionId);
177130
+ if (!verdict.ok) {
177131
+ logMergeSkip(verdict.reason, key);
176919
177132
  return;
176920
177133
  }
176921
- let sid = shellSessionId ?? prior?.shellSessionId;
176922
- if (!sid) {
176923
- logForDebugging("sessionIdMapping: persist skipped \u2014 no shellSessionId");
176924
- return;
176925
- }
176926
- let entry = { ...priorEntry, ...partial2, engineSessionId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
176927
- return {
176928
- ...prior,
176929
- shellSessionId: sid,
176930
- engines: { ...prior?.engines, [key]: entry },
176931
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
176932
- };
177134
+ return verdict.record;
176933
177135
  });
176934
177136
  next && (this.cache = next);
176935
177137
  }
@@ -176946,6 +177148,17 @@ var LOCK_STALE_MS3, SessionIdMapping, init_sessionIdMapping = __esm({
176946
177148
  _reset() {
176947
177149
  this.path = void 0, this.cache = void 0;
176948
177150
  }
177151
+ /**
177152
+ * A-028.12:包 `SessionMapStorePort` 的 cli 文件实现(read = 无副作用新鲜读盘;
177153
+ * readMergeWrite = 锁内读-合-写)。端口在这里**真被消费**(persist/persistEngineEntry 经它写),
177154
+ * 不是装饰性 satisfies —— web 半场用 localStorage 实现同一契约。
177155
+ */
177156
+ storeFor(path28) {
177157
+ return {
177158
+ read: () => this.readRecordFromDisk(path28),
177159
+ readMergeWrite: (build2) => this.lockedReadMergeWrite(path28, build2)
177160
+ };
177161
+ }
176949
177162
  /**
176950
177163
  * M1 修 core: lock `path`, read the FRESH on-disk record (not `this.cache` / not a pre-lock read),
176951
177164
  * let `build` compute the next record from that fresh prior, and atomically persist it — all inside
@@ -178203,15 +178416,7 @@ function validateEngineUrlTransport(url3) {
178203
178416
  );
178204
178417
  }
178205
178418
  function resolveLiveAuthToken(baseUrl, token = process.env.SEMA_LIVE_TOKEN) {
178206
- return token || (baseUrl && isLoopbackEngineUrl(baseUrl) ? { mode: "loopback-unauthed" } : "anon");
178207
- }
178208
- function isLoopbackEngineUrl(url3) {
178209
- try {
178210
- let h = new URL(url3).hostname;
178211
- return h === "127.0.0.1" || h === "localhost" || h === "::1" || h === "[::1]";
178212
- } catch {
178213
- return !1;
178214
- }
178419
+ return resolveWireAuth(baseUrl, token);
178215
178420
  }
178216
178421
  function configuredEngineUrl() {
178217
178422
  let v2 = settingsEnv()[ENGINE_URL_ENV] ?? process.env[ENGINE_URL_ENV];
@@ -178318,14 +178523,6 @@ function enginePinUnreachableHint(pin) {
178318
178523
  \xB7 Leftover from an older install, or want the shell-managed engine back? ${removal} \u2014 the next launch self-spawns a local engine.
178319
178524
  \xB7 Not sure? Run \`sema doctor\` to see the engine status.`;
178320
178525
  }
178321
- function isEngineTransportError(err8) {
178322
- let e = err8;
178323
- if (typeof e?.status == "number") return !1;
178324
- let cause = e?.cause, detail = typeof cause?.message == "string" && cause.message.length > 0 && cause.message || typeof e?.message == "string" && e.message.length > 0 && e.message || String(err8);
178325
- return e?.cause !== void 0 || /fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|EHOSTUNREACH|ENETUNREACH|EPIPE|socket hang up|UND_ERR|terminated|other side closed/i.test(
178326
- detail
178327
- );
178328
- }
178329
178526
  function noteEnginePinUnreachable(pin) {
178330
178527
  enginePinUnreachable = pin;
178331
178528
  }
@@ -178451,7 +178648,7 @@ function noteRemoteResumeWarning() {
178451
178648
  function remoteResumeWarningActive() {
178452
178649
  return remoteResumeWarning;
178453
178650
  }
178454
- var ENGINE_URL_ENV, TRUSTED_ENGINE_HOSTS_KEY, enginePinUnreachable, SYNC_ENGINE_URL_ENV, AUTO_SYNC_SOURCE_LABEL, AUTO_SYNC_LOCKED_BY_POLICY_ERROR, DEFAULT_BIND_HOST, engineRoutingRefusal, remoteResumeWarning, init_engineTarget = __esm({
178651
+ var ENGINE_URL_ENV, TRUSTED_ENGINE_HOSTS_KEY, isLoopbackEngineUrl, isEngineTransportError, enginePinUnreachable, SYNC_ENGINE_URL_ENV, AUTO_SYNC_SOURCE_LABEL, AUTO_SYNC_LOCKED_BY_POLICY_ERROR, DEFAULT_BIND_HOST, engineRoutingRefusal, remoteResumeWarning, init_engineTarget = __esm({
178455
178652
  "build-src/src/sema/engineTarget.ts"() {
178456
178653
  init_concurrencyTestHooks();
178457
178654
  init_envUtils();
@@ -178460,8 +178657,10 @@ var ENGINE_URL_ENV, TRUSTED_ENGINE_HOSTS_KEY, enginePinUnreachable, SYNC_ENGINE_
178460
178657
  init_enginePortDerive();
178461
178658
  init_envKnobs();
178462
178659
  init_cloudExecutionPolicy();
178660
+ init_dist();
178463
178661
  ENGINE_URL_ENV = "SEMA_ENGINE_URL", TRUSTED_ENGINE_HOSTS_KEY = "trustedEngineHosts";
178464
- enginePinUnreachable = null;
178662
+ isLoopbackEngineUrl = isLoopbackWireUrl;
178663
+ isEngineTransportError = isWireTransportError, enginePinUnreachable = null;
178465
178664
  SYNC_ENGINE_URL_ENV = "SEMA_SYNC_ENGINE_URL", AUTO_SYNC_SOURCE_LABEL = {
178466
178665
  "sync-target": "sync target",
178467
178666
  "org-default": "org default",
@@ -178771,67 +178970,9 @@ var mockClientIds, init_mockClient = __esm({
178771
178970
  });
178772
178971
 
178773
178972
  // build-src/src/sema/armedGateRegistry.ts
178774
- function emitGateArmedEvent(key) {
178775
- for (let listener5 of [...armedListeners])
178776
- try {
178777
- listener5(key);
178778
- } catch {
178779
- }
178780
- }
178781
- function registerArmedGate2(key) {
178782
- typeof key != "string" || key.length === 0 || (armedKeys.add(key), emitGateArmedEvent(key));
178783
- }
178784
- function wasGateArmed2(key) {
178785
- return typeof key == "string" && key.length > 0 && armedKeys.has(key);
178786
- }
178787
- function onGateArmed(listener5) {
178788
- return armedListeners.add(listener5), () => {
178789
- armedListeners.delete(listener5);
178790
- };
178791
- }
178792
- function gateArmedWaitMs() {
178793
- return gateArmedWaitOverrideMs ?? GATE_ARMED_WAIT_MS;
178794
- }
178795
- function waitForGateArmed(keys2, timeoutMs) {
178796
- let wanted = new Set(keys2.filter((k2) => typeof k2 == "string" && k2.length > 0));
178797
- return wanted.size === 0 ? Promise.resolve(!1) : new Promise((resolve57) => {
178798
- let listener5 = (key) => {
178799
- wanted.has(key) && (armedListeners.delete(listener5), clearTimeout(timer2), resolve57(!0));
178800
- };
178801
- armedListeners.add(listener5);
178802
- let timer2 = setTimeout(() => {
178803
- armedListeners.delete(listener5), resolve57(!1);
178804
- }, timeoutMs);
178805
- });
178806
- }
178807
- function armedKeyFromQuestionId2(questionId) {
178808
- let trimmed2 = armedKeyFromQuestionId(questionId);
178809
- return trimmed2.startsWith(PLAN_REVIEW_QUESTION_ID_PREFIX) ? planReviewArmedKey(trimmed2.slice(PLAN_REVIEW_QUESTION_ID_PREFIX.length)) : trimmed2;
178810
- }
178811
- function registerArmedGateFromQuestionId2(questionId) {
178812
- if (typeof questionId != "string" || questionId.length === 0) return;
178813
- let normalized = armedKeyFromQuestionId2(questionId);
178814
- registerArmedGate2(normalized), questionId !== normalized && emitGateArmedEvent(questionId);
178815
- }
178816
- function planReviewArmedKey(taskId) {
178817
- let gen = planReviewGenByTask.get(taskId) ?? 0, canonical2 = planReviewQuestionId(taskId);
178818
- return gen > 0 ? `${canonical2}#g${String(gen)}` : canonical2;
178819
- }
178820
- function notePlanReviewAnswered(questionId) {
178821
- if (typeof questionId != "string" || !questionId.startsWith(PLAN_REVIEW_QUESTION_ID_PREFIX) || notedPlanReviewQuestionIds.has(questionId)) return;
178822
- notedPlanReviewQuestionIds.add(questionId);
178823
- let base = questionId.slice(PLAN_REVIEW_QUESTION_ID_PREFIX.length), cut = base.indexOf(REOPEN_ID_TAIL), taskId = cut >= 0 ? base.slice(0, cut) : base;
178824
- taskId.length !== 0 && planReviewGenByTask.set(taskId, (planReviewGenByTask.get(taskId) ?? 0) + 1);
178825
- }
178826
- function notePlanReviewAnsweredIfDecisive(questionId, answer) {
178827
- planReviewDecisionFromAnswer(answer ?? { answers: [] }) !== "dismissed" && notePlanReviewAnswered(questionId);
178828
- }
178829
- var armedKeys, armedListeners, GATE_ARMED_WAIT_MS, gateArmedWaitOverrideMs, planReviewGenByTask, notedPlanReviewQuestionIds, init_armedGateRegistry2 = __esm({
178973
+ var init_armedGateRegistry2 = __esm({
178830
178974
  "build-src/src/sema/armedGateRegistry.ts"() {
178831
178975
  init_dist();
178832
- armedKeys = /* @__PURE__ */ new Set(), armedListeners = /* @__PURE__ */ new Set();
178833
- GATE_ARMED_WAIT_MS = 5e3, gateArmedWaitOverrideMs = null;
178834
- planReviewGenByTask = /* @__PURE__ */ new Map(), notedPlanReviewQuestionIds = /* @__PURE__ */ new Set();
178835
178976
  }
178836
178977
  });
178837
178978
 
@@ -178878,81 +179019,33 @@ __export(planReviewReopen_exports, {
178878
179019
  _resetPlanReviewReopenSeqForTest: () => _resetPlanReviewReopenSeqForTest,
178879
179020
  reopenPlanReviewCard: () => reopenPlanReviewCard2
178880
179021
  });
178881
- function retireActiveReopen2(canonicalId) {
178882
- let prev = activeReopenByCanonical.get(canonicalId);
178883
- if (prev) {
178884
- activeReopenByCanonical.delete(canonicalId);
179022
+ function deliverPlanReviewDecision(taskId, decision) {
179023
+ decidePlanReview(taskId, decision).catch((e) => {
178885
179024
  try {
178886
- prev.unregister();
179025
+ let line = "sema: your plan review decision could not be delivered to the engine \u2014 the session may still be held; send your message again to retry";
179026
+ surfaceTranscriptSystemNotice(line) || process.stderr.write(`${line}
179027
+ `), process.env.SEMA_DEBUG && console.error(`[sema][planReviewReopen] decide (${decision}, run ${taskId}) threw unexpectedly: ${String(e)}`);
178887
179028
  } catch {
178888
179029
  }
178889
- publishQuestionFrame({ type: "question_complete", questionId: prev.questionId });
178890
- }
179030
+ });
178891
179031
  }
178892
179032
  function _resetPlanReviewReopenSeqForTest() {
178893
- reopenSeq = 0;
178894
- for (let [, entry] of activeReopenByCanonical)
178895
- try {
178896
- entry.unregister();
178897
- } catch (e) {
178898
- failOpen("plan-review-reopen-unregister", void 0, String(e));
178899
- }
178900
- activeReopenByCanonical.clear();
179033
+ _resetActiveReopenRespondersForTest();
178901
179034
  }
178902
179035
  async function reopenPlanReviewCard2(taskId) {
178903
- try {
178904
- if (typeof taskId != "string" || taskId.length === 0) return { reopened: !1 };
178905
- if (!hasQuestionOverlay()) return { reopened: !1 };
178906
- let armedKey = planReviewArmedKey(taskId), firstSight = !wasGateArmed2(armedKey), canonicalId = planReviewQuestionId(taskId);
178907
- retireActiveReopen2(canonicalId), reopenSeq += 1;
178908
- let questionId = `${canonicalId}${REOPEN_ID_TAIL}${String(reopenSeq)}`, unregister = registerLocalQuestionResponder(questionId, async (id, answer) => {
178909
- activeReopenByCanonical.get(canonicalId)?.questionId === questionId && activeReopenByCanonical.delete(canonicalId);
178910
- let decision = planReviewDecisionFromAnswer(answer);
178911
- return decision === "dismissed" ? { ok: !0 } : (notePlanReviewAnswered(id), decidePlanReview(taskId, decision).catch((e) => {
178912
- try {
178913
- let line = "sema: your plan review decision could not be delivered to the engine \u2014 the session may still be held; send your message again to retry";
178914
- surfaceTranscriptSystemNotice(line) || process.stderr.write(`${line}
178915
- `), process.env.SEMA_DEBUG && console.error(`[sema][planReviewReopen] decide (${decision}, run ${taskId}) threw unexpectedly: ${String(e)}`);
178916
- } catch {
178917
- }
178918
- }), { ok: !0 });
178919
- });
178920
- activeReopenByCanonical.set(canonicalId, { questionId, unregister });
178921
- let frame = {
178922
- type: "question",
178923
- questionId,
178924
- questions: [
178925
- {
178926
- header: "Plan review",
178927
- question: "This plan is still waiting for your review \u2014 it is what is holding this session. Approve it and start the implementation?",
178928
- options: [
178929
- {
178930
- label: APPROVE_LABEL2,
178931
- description: "Resume the task now and execute the plan (runs to completion engine-side)"
178932
- },
178933
- {
178934
- label: REJECT_LABEL2,
178935
- description: "Discard this plan and stay in plan mode to refine it"
178936
- }
178937
- ],
178938
- multiSelect: !1
178939
- }
178940
- ]
178941
- }, receipt = waitForGateArmed([questionId], gateArmedWaitMs());
178942
- return publishQuestionFrame(frame), await receipt ? { reopened: !0, firstSight } : (process.env.SEMA_DEBUG && console.error(
178943
- `[sema][planReviewReopen] question frame ${questionId} published but no presentation receipt arrived within ${String(gateArmedWaitMs())}ms \u2014 reporting reopened:false (the overlay did not enqueue the card)`
178944
- ), { reopened: !1 });
178945
- } catch {
178946
- return { reopened: !1 };
178947
- }
179036
+ let verdict = await reopenPlanReviewCard(taskId, {
179037
+ presentationReceiptMs: gateArmedWaitMs(),
179038
+ deliverDecision: deliverPlanReviewDecision
179039
+ });
179040
+ return verdict.reopened === !1 && process.env.SEMA_DEBUG && console.error(
179041
+ hasQuestionOverlay() ? `[sema][planReviewReopen] reopen for task ${taskId} got no presentation receipt within ${String(gateArmedWaitMs())}ms \u2014 reporting reopened:false (the overlay did not enqueue the card)` : `[sema][planReviewReopen] reopen for task ${taskId} has no overlay subscriber (headless / REPL not mounted) \u2014 reporting reopened:false`
179042
+ ), verdict;
178948
179043
  }
178949
- var APPROVE_LABEL2, REJECT_LABEL2, reopenSeq, activeReopenByCanonical, init_planReviewReopen = __esm({
179044
+ var init_planReviewReopen = __esm({
178950
179045
  "build-src/src/sema/planReviewReopen.ts"() {
178951
179046
  init_dist();
178952
179047
  init_armedGateRegistry2();
178953
179048
  init_transcriptSystemNotice();
178954
- init_failOpen();
178955
- APPROVE_LABEL2 = PLAN_REVIEW_APPROVE_LABEL, REJECT_LABEL2 = PLAN_REVIEW_REJECT_LABEL, reopenSeq = 0, activeReopenByCanonical = /* @__PURE__ */ new Map();
178956
179049
  }
178957
179050
  });
178958
179051
 
@@ -178960,7 +179053,7 @@ var APPROVE_LABEL2, REJECT_LABEL2, reopenSeq, activeReopenByCanonical, init_plan
178960
179053
  function retryDelayMs() {
178961
179054
  return delayOverrideMs ?? DECIDE_RETRY_DELAY_MS;
178962
179055
  }
178963
- function sleep4(ms) {
179056
+ function sleep3(ms) {
178964
179057
  return new Promise((resolve57) => {
178965
179058
  setTimeout(resolve57, ms);
178966
179059
  });
@@ -178986,7 +179079,7 @@ async function attemptDecideWithOneRetry(opts) {
178986
179079
  }
178987
179080
  process.env.SEMA_DEBUG && console.error(
178988
179081
  `[sema][decideRetry] ${opts.label} failed (${first.detail}) \u2014 retrying once in ${String(retryDelayMs())}ms`
178989
- ), await sleep4(retryDelayMs());
179082
+ ), await sleep3(retryDelayMs());
178990
179083
  let second = await opts.attempt();
178991
179084
  return second.ok ? !0 : (surface(second.detail), !1);
178992
179085
  } catch (e) {
@@ -179010,8 +179103,8 @@ __export(askParkReopen_exports, {
179010
179103
  countOwnedPendingApprovals: () => countOwnedPendingApprovals,
179011
179104
  reopenAskParkCard: () => reopenAskParkCard
179012
179105
  });
179013
- async function countOwnedPendingApprovals(client3) {
179014
- return ((await client3.approvals.list()).pending ?? []).filter((row2) => pendingRowIsOwnedByThisSession(row2, ownershipDeps)).length;
179106
+ async function countOwnedPendingApprovals(client3, signal) {
179107
+ return ((await client3.approvals.list(signal ? { signal } : void 0)).pending ?? []).filter((row2) => pendingRowIsOwnedByThisSession(row2, ownershipDeps)).length;
179015
179108
  }
179016
179109
  function reopenAskParkCard(taskId, client3, signal) {
179017
179110
  if (typeof taskId != "string" || taskId.length === 0) return Promise.resolve({ reopened: !1 });
@@ -179095,7 +179188,7 @@ function armPendingRowCoalesced(flight, taskId, pending2, client3) {
179095
179188
  }
179096
179189
  async function armPendingRow(taskId, pending2, client3, identity3) {
179097
179190
  try {
179098
- let { rowTaskId, gatedCallId, armedKey } = identity3, firstSight = !wasGateArmed2(armedKey), rowStillPending = async () => {
179191
+ let { rowTaskId, gatedCallId, armedKey } = identity3, firstSight = !wasGateArmed(armedKey), rowStillPending = async () => {
179099
179192
  try {
179100
179193
  return askParkRowStillPending((await client3.approvals.list()).pending, identity3);
179101
179194
  } catch {
@@ -179119,8 +179212,8 @@ async function armPendingRow(taskId, pending2, client3, identity3) {
179119
179212
  `[sema][askParkReopen] row (task ${rowTaskId}) routed to the question arm but carries no question payload \u2014 refusing to mint an empty card, reporting reopened:false`
179120
179213
  ), { kind: "verdict", verdict: { reopened: !1 } };
179121
179214
  let attributedQuestions = rowTaskId !== taskId ? questions.map((q2, i) => i === 0 ? { ...q2, question: `[pending on run ${rowTaskId}] ${q2.question}` } : q2) : questions;
179122
- reopenSeq2 += 1;
179123
- let questionId = `ask-park:${rowTaskId}${REOPEN_ID_TAIL}${String(reopenSeq2)}`, unregister = registerLocalQuestionResponder(questionId, async (_id, answer) => {
179215
+ reopenSeq += 1;
179216
+ let questionId = `ask-park:${rowTaskId}${REOPEN_ID_TAIL}${String(reopenSeq)}`, unregister = registerLocalQuestionResponder(questionId, async (_id, answer) => {
179124
179217
  try {
179125
179218
  unregister();
179126
179219
  } catch (e) {
@@ -179151,7 +179244,7 @@ async function armPendingRow(taskId, pending2, client3, identity3) {
179151
179244
  questionId,
179152
179245
  questions: attributedQuestions
179153
179246
  }, receipt2 = waitForGateArmed([questionId], gateArmedWaitMs());
179154
- return publishQuestionFrame(frame), await receipt2 ? (registerArmedGate2(armedKey), { kind: "verdict", verdict: { reopened: !0, firstSight } }) : (process.env.SEMA_DEBUG && console.error(
179247
+ return publishQuestionFrame(frame), await receipt2 ? (registerArmedGate(armedKey), { kind: "verdict", verdict: { reopened: !0, firstSight } }) : (process.env.SEMA_DEBUG && console.error(
179155
179248
  `[sema][askParkReopen] question frame ${questionId} published but no presentation receipt arrived within ${String(gateArmedWaitMs())}ms \u2014 reporting reopened:false (the overlay did not enqueue the card)`
179156
179249
  ), { kind: "verdict", verdict: { reopened: !1 } });
179157
179250
  }
@@ -179201,14 +179294,14 @@ async function armPendingRow(taskId, pending2, client3, identity3) {
179201
179294
  ), { kind: "verdict", verdict: { reopened: !1 } };
179202
179295
  }
179203
179296
  }
179204
- var reopenSeq2, ownershipDeps, inFlightReopenByTask, rowWaitOverrideMs, rowPollOverrideMs, rowArmFlightEpoch, rowArmFlight, init_askParkReopen = __esm({
179297
+ var reopenSeq, ownershipDeps, inFlightReopenByTask, rowWaitOverrideMs, rowPollOverrideMs, rowArmFlightEpoch, rowArmFlight, init_askParkReopen = __esm({
179205
179298
  "build-src/src/sema/askParkReopen.ts"() {
179206
179299
  init_dist();
179207
179300
  init_liveSessionStore();
179208
179301
  init_armedGateRegistry2();
179209
179302
  init_decideRetry();
179210
179303
  init_failOpen();
179211
- reopenSeq2 = 0, ownershipDeps = {
179304
+ reopenSeq = 0, ownershipDeps = {
179212
179305
  currentSessionId: getLiveSessionId,
179213
179306
  isOwnRun: (taskIdTail) => {
179214
179307
  if (isOwnEngineRun(taskIdTail)) return !0;
@@ -179528,7 +179621,7 @@ async function* withInteractiveReattach(live, o) {
179528
179621
  }
179529
179622
  }
179530
179623
  async function* reattachLoop(machine, taskId, deps2, readLastEventId, writeLastEventId, originalTear) {
179531
- let { windowMs } = tuning(), now2 = deps2.now ?? Date.now, sleep10 = deps2.sleep ?? abortAwareSleep, log2 = deps2.log ?? (() => {
179624
+ let { windowMs } = tuning(), now2 = deps2.now ?? Date.now, sleep9 = deps2.sleep ?? abortAwareSleep, log2 = deps2.log ?? (() => {
179532
179625
  }), deadline = now2() + windowMs, attempt = 0, lastState2 = null, serverRetryAfterMs;
179533
179626
  for (log2(`[sema][reattach] live stream tore mid-turn for run ${taskId} \u2014 entering the reattach window (${String(windowMs)}ms)`); !machine.stopped && now2() < deadline; ) {
179534
179627
  attempt += 1, machine.noteAttempt(attempt), machine.setPhase("probing");
@@ -179568,7 +179661,7 @@ async function* reattachLoop(machine, taskId, deps2, readLastEventId, writeLastE
179568
179661
  if (machine.stopped) break;
179569
179662
  let backoff3 = reattachBackoffMs(attempt), delay = serverRetryAfterMs !== void 0 ? Math.max(backoff3, serverRetryAfterMs) : backoff3;
179570
179663
  if (serverRetryAfterMs = void 0, now2() + delay >= deadline) break;
179571
- machine.setPhase("waiting"), await sleep10(delay, machine.signal);
179664
+ machine.setPhase("waiting"), await sleep9(delay, machine.signal);
179572
179665
  }
179573
179666
  if (machine.stopped) {
179574
179667
  log2(`[sema][reattach] reconnect stopped by the user after ${String(attempt)} attempt(s) \u2014 no further requests`);
@@ -180790,11 +180883,6 @@ var MONTH_ABBR, init_quotaExhaustedCopy = __esm({
180790
180883
  });
180791
180884
 
180792
180885
  // build-src/src/sema/scenarioNotAllowedCopy.ts
180793
- function scenarioDenyFromError(err8) {
180794
- if (typeof err8 != "object" || err8 === null) return null;
180795
- let e = err8;
180796
- return e.status !== 400 || e.errorCode !== "scenario_not_allowed" ? null : { allowlist: Array.isArray(e.allowlist) ? e.allowlist.filter((x3) => typeof x3 == "string" && x3.length > 0) : [] };
180797
- }
180798
180886
  function scenarioNotAllowedContent(detail, requestedScenario) {
180799
180887
  let parts = [];
180800
180888
  return parts.push(
@@ -180803,6 +180891,7 @@ function scenarioNotAllowedContent(detail, requestedScenario) {
180803
180891
  }
180804
180892
  var init_scenarioNotAllowedCopy = __esm({
180805
180893
  "build-src/src/sema/scenarioNotAllowedCopy.ts"() {
180894
+ init_dist();
180806
180895
  }
180807
180896
  });
180808
180897
 
@@ -182142,7 +182231,7 @@ async function killEngineChildWithAutopsyWindow(child, opts) {
182142
182231
  let t0 = Date.now();
182143
182232
  for (; Date.now() - t0 < windowMs; ) {
182144
182233
  if (child.exitCode !== null || child.signalCode !== null) return;
182145
- await sleep5(pollMs);
182234
+ await sleep4(pollMs);
182146
182235
  }
182147
182236
  if (child.exitCode === null && child.signalCode === null)
182148
182237
  try {
@@ -182480,18 +182569,18 @@ async function reapStaleEngine(portFile, opts) {
182480
182569
  };
182481
182570
  signal("SIGTERM");
182482
182571
  let t0 = Date.now();
182483
- for (; Date.now() - t0 < SHUTDOWN_GRACE_MS && isProcessAlive(portFile.pid); ) await sleep5(200);
182572
+ for (; Date.now() - t0 < SHUTDOWN_GRACE_MS && isProcessAlive(portFile.pid); ) await sleep4(200);
182484
182573
  if (isProcessAlive(portFile.pid)) {
182485
182574
  logForDebugging(
182486
182575
  `[engine-lifecycle] reap pid=${portFile.pid}: no exit in ${SHUTDOWN_GRACE_MS}ms \u2192 second SIGTERM (engine hardShutdown)`
182487
182576
  ), signal("SIGTERM");
182488
182577
  let t1 = Date.now();
182489
- for (; Date.now() - t1 < SHUTDOWN_SECOND_TERM_GRACE_MS && isProcessAlive(portFile.pid); ) await sleep5(200);
182578
+ for (; Date.now() - t1 < SHUTDOWN_SECOND_TERM_GRACE_MS && isProcessAlive(portFile.pid); ) await sleep4(200);
182490
182579
  }
182491
182580
  if (isProcessAlive(portFile.pid)) {
182492
182581
  logForDebugging(`[engine-lifecycle] reap pid=${portFile.pid}: still alive after second SIGTERM \u2192 SIGKILL`), signal("SIGKILL");
182493
182582
  let t2 = Date.now();
182494
- for (; Date.now() - t2 < 2e3 && isProcessAlive(portFile.pid); ) await sleep5(200);
182583
+ for (; Date.now() - t2 < 2e3 && isProcessAlive(portFile.pid); ) await sleep4(200);
182495
182584
  }
182496
182585
  }
182497
182586
  let portPath = getEnginePortFilePath();
@@ -182756,7 +182845,7 @@ async function waitForLockOrAttach(portFilePath, configHome) {
182756
182845
  let budget = engineLockWaitBudgetMs(), t0 = Date.now();
182757
182846
  for (; Date.now() - t0 < budget; ) {
182758
182847
  let remaining = budget - (Date.now() - t0);
182759
- await sleep5(Math.max(1, Math.min(ENGINE_LOCK_WAIT_POLL_MS, remaining)));
182848
+ await sleep4(Math.max(1, Math.min(ENGINE_LOCK_WAIT_POLL_MS, remaining)));
182760
182849
  try {
182761
182850
  let release2 = await lock(portFilePath, { stale: LOCK_OPTS2.stale });
182762
182851
  return logForDebugging(
@@ -182842,11 +182931,11 @@ async function waitForHealthy(port2, child) {
182842
182931
  if (delay === null) break;
182843
182932
  delay === HEALTH_POLL_EXTENDED_INTERVAL_MS && !extensionLogged && (extensionLogged = !0, logForDebugging(
182844
182933
  "[engine-lifecycle] engine is slow to start (possibly high load) \u2014 child is alive, extending health wait to 60s total"
182845
- )), await sleep5(delay);
182934
+ )), await sleep4(delay);
182846
182935
  }
182847
182936
  return await probeHealth(port2);
182848
182937
  }
182849
- function sleep5(ms) {
182938
+ function sleep4(ms) {
182850
182939
  return new Promise((resolve57) => setTimeout(resolve57, ms));
182851
182940
  }
182852
182941
  function startHealthCheckLoop(instance2, onDead) {
@@ -182967,7 +183056,7 @@ async function runEngineDeadRespawn(deps2) {
182967
183056
  "[engine-lifecycle] host terminal is gone \u2014 refusing engine respawn, shutting down the orphaned shell"
182968
183057
  ), teardownOwnedEngineSync("orphan-respawn-guard"), process.exit(129)), deadRespawnInFlight) return !1;
182969
183058
  deadRespawnInFlight = !0;
182970
- let now2 = deps2.now ?? Date.now, doSleep = deps2.sleep ?? sleep5, backoff3 = deps2.backoffMs ?? [1e3, 5e3, 15e3];
183059
+ let now2 = deps2.now ?? Date.now, doSleep = deps2.sleep ?? sleep4, backoff3 = deps2.backoffMs ?? [1e3, 5e3, 15e3];
182971
183060
  try {
182972
183061
  let t2 = now2();
182973
183062
  if (lastRespawnOkAt !== null && t2 - lastRespawnOkAt >= CRASH_LOOP_WINDOW_MS && (cooldownRetryLevel = 0, cooldownRetriesUsed = 0, cooldownSpentMs = 0), recentDeathTimestamps = recentDeathTimestamps.filter((d4) => t2 - d4 < CRASH_LOOP_WINDOW_MS), recentDeathTimestamps.push(t2), recentDeathTimestamps.length > CRASH_LOOP_MAX_DEATHS) {
@@ -183167,7 +183256,7 @@ async function waitForExit(pid, timeoutMs) {
183167
183256
  let deadline = Date.now() + timeoutMs;
183168
183257
  for (; Date.now() < deadline; ) {
183169
183258
  if (!isProcessAlive(pid)) return !0;
183170
- await sleep5(100);
183259
+ await sleep4(100);
183171
183260
  }
183172
183261
  return !isProcessAlive(pid);
183173
183262
  }
@@ -183910,7 +183999,7 @@ __export(seamQuery_exports, {
183910
183999
  SCENARIO_KEYS: () => SCENARIO_KEYS,
183911
184000
  canUseTool: () => canUseTool,
183912
184001
  cancelEngineRun: () => cancelEngineRun,
183913
- drainingRetryDelayMs: () => drainingRetryDelayMs,
184002
+ drainingRetryDelayMs: () => drainingRetryDelayMs2,
183914
184003
  getSeamHitlClient: () => getSeamHitlClient,
183915
184004
  getSeamMcp: () => getSeamMcp,
183916
184005
  getSeamSandbox: () => getSeamSandbox,
@@ -183945,22 +184034,10 @@ function hasHitlVerbs(c2) {
183945
184034
  return typeof o.approvals?.list == "function" && typeof o.approvals?.decide == "function" && typeof o.assistant?.planReview == "function" && typeof o.assistant?.resume == "function";
183946
184035
  }
183947
184036
  function setDrainingBackoffForTest(ms) {
183948
- drainingBackoffMs = ms && ms.length > 0 ? ms : DEFAULT_DRAINING_BACKOFF_MS;
183949
- }
183950
- function isPreStreamDrainingReject(err8) {
183951
- let e = err8;
183952
- return typeof e?.status == "number" && e.status === 503 && e.errorCode === "draining";
184037
+ drainingBackoffMs = ms && ms.length > 0 ? ms : void 0;
183953
184038
  }
183954
- function isResumeAtRejection(err8) {
183955
- let e = err8;
183956
- return typeof e?.errorCode == "string" && e.errorCode.startsWith("resume_at.");
183957
- }
183958
- function drainingRetryDelayMs(err8, attempt) {
183959
- let ra = err8?.retryAfterMs;
183960
- if (typeof ra == "number" && Number.isFinite(ra) && ra >= 0)
183961
- return Math.min(ra, DRAINING_RETRY_AFTER_CAP_MS);
183962
- let ladder = drainingBackoffMs;
183963
- return ladder[Math.min(attempt, ladder.length - 1)] ?? 1e3;
184039
+ function drainingRetryDelayMs2(err8, attempt) {
184040
+ return drainingRetryDelayMs(err8, attempt, drainingBackoffMs ? { ladder: drainingBackoffMs } : void 0);
183964
184041
  }
183965
184042
  function isBgHeadlessWorker() {
183966
184043
  return process.env.SEMA_CODE_SESSION_KIND === "bg" && !!process.env.SEMA_JOB_DIR && !!process.env.SEMA_LIVE_BASEURL;
@@ -184274,23 +184351,18 @@ ${objective}`, process.env.SEMA_DEBUG && console.error("[sema][seamQuery] interr
184274
184351
  );
184275
184352
  }
184276
184353
  function semaApiErrorContent(err8, requestedScenario) {
184277
- let e = err8;
184278
- if (typeof e?.status == "number") {
184279
- let code2 = typeof e.errorCode == "string" && e.errorCode.length > 0 ? ` ${e.errorCode}` : "", msg = typeof e.message == "string" && e.message.length > 0 ? e.message : String(err8), lines = [`${API_ERROR_PREFIX}: ${e.status}${code2} \xB7 ${msg}`], supplement = semaApiErrorSupplement(err8, requestedScenario);
184354
+ let verdict = classifyTurnWireError(err8);
184355
+ if (verdict.kind === "http") {
184356
+ let code2 = verdict.errorCode !== void 0 ? ` ${verdict.errorCode}` : "", lines = [`${API_ERROR_PREFIX}: ${verdict.status}${code2} \xB7 ${verdict.message}`], supplement = semaApiErrorSupplement(err8, requestedScenario);
184280
184357
  supplement && lines.push(supplement);
184281
184358
  let sandboxHint = sandboxDegradeHint(err8);
184282
184359
  return sandboxHint && lines.push(sandboxHint), lines.join(`
184283
184360
  `);
184284
184361
  }
184285
- let cause = e?.cause, detail = typeof cause?.message == "string" && cause.message.length > 0 && cause.message || typeof e?.message == "string" && e.message.length > 0 && e.message || String(err8), isNetworkError = e?.cause !== void 0 || /fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|EHOSTUNREACH|ENETUNREACH|EPIPE|socket hang up|UND_ERR|terminated|other side closed/i.test(
184286
- detail
184287
- );
184288
- if (err8 instanceof Error && err8.name === "StreamEndedWithoutTerminalError")
184362
+ if (verdict.kind === "stream-ended-without-terminal")
184289
184363
  return `${API_ERROR_PREFIX}: the event stream ended while the run had not reached a terminal state \u2014 the run is likely parked waiting for an approval decision (suspended / needs_review), not crashed. Check /tasks for its real status and decide any pending approval; the turn did not complete on this screen.`;
184290
- if (!isNetworkError) {
184291
- let name = err8 instanceof Error ? err8.name : typeof err8;
184292
- return `${API_ERROR_PREFIX}: internal shell error (${name}: ${detail}) \u2014 this is a bug in the sema shell, not an engine outage; the turn did not complete. Re-run with SEMA_DEBUG=1 and report it.`;
184293
- }
184364
+ if (verdict.kind === "internal")
184365
+ return `${API_ERROR_PREFIX}: internal shell error (${verdict.name}: ${verdict.detail}) \u2014 this is a bug in the sema shell, not an engine outage; the turn did not complete. Re-run with SEMA_DEBUG=1 and report it.`;
184294
184366
  let pinHint = "";
184295
184367
  try {
184296
184368
  let pin = activeEnginePin();
@@ -184298,7 +184370,7 @@ function semaApiErrorContent(err8, requestedScenario) {
184298
184370
  ${enginePinUnreachableHint(pin)}`);
184299
184371
  } catch {
184300
184372
  }
184301
- return `${API_ERROR_PREFIX}: ${detail} \xB7 the engine is unreachable \u2014 your message did not run; check the engine is up, then send it again.${pinHint}`;
184373
+ return `${API_ERROR_PREFIX}: ${verdict.detail} \xB7 the engine is unreachable \u2014 your message did not run; check the engine is up, then send it again.${pinHint}`;
184302
184374
  }
184303
184375
  function apiErrorRow(content) {
184304
184376
  return createAssistantAPIErrorMessage({ content, error: "unknown" });
@@ -184445,7 +184517,7 @@ Fix: run \`sema doctor\` to diagnose, or restart sema to retry.`
184445
184517
  let notice = fileLinkNoticeText(ev);
184446
184518
  notice !== null && surfaceFileLinkNotice(notice);
184447
184519
  }
184448
- let busy = activeRunBusySignal2(ev);
184520
+ let busy = activeRunBusySignal(ev);
184449
184521
  if (busy) {
184450
184522
  busySignal = busy;
184451
184523
  return;
@@ -184501,7 +184573,9 @@ Fix: run \`sema doctor\` to diagnose, or restart sema to retry.`
184501
184573
  // **属主** pending 行数,恰 0 = 脏值正面证据 ⇒ 放行真分诊;归属过滤见
184502
184574
  // countOwnedPendingApprovals 头注(引擎全局队列有别家陈年行,裸计数恒非零
184503
184575
  // = 防御恒不触发)。mock 车道无 approvals 面 ⇒ 读口不装 = 旧行为(S-g)。
184504
- listOwnedPendingApprovals: () => countOwnedPendingApprovals(hitl)
184576
+ // 🔴 opts.signal = 包内复核竞速的合流截止口(4s 窗 × turn Esc),透传进
184577
+ // approvals.list —— 超时/中止掐的是底层请求,不是只掐 await(复审轮二)。
184578
+ listOwnedPendingApprovals: (opts) => countOwnedPendingApprovals(hitl, opts?.signal)
184505
184579
  } : {};
184506
184580
  })(),
184507
184581
  // C3([3777]/[3779])running 形的三选卡口。**一条用户消息至多一张**(runningChoiceOffered
@@ -184521,14 +184595,14 @@ Fix: run \`sema doctor\` to diagnose, or restart sema to retry.`
184521
184595
  // 车B 的消费面(deps.signal)逐字不变。
184522
184596
  ...signal ? { signal } : {}
184523
184597
  });
184524
- if (yield apiErrorRow(activeRunSelfHealRow2(outcome, detectedBusy)), outcome.kind === "running-cancelled" && !signal?.aborted) {
184598
+ if (yield apiErrorRow(activeRunSelfHealRow(outcome, detectedBusy)), outcome.kind === "running-cancelled" && !signal?.aborted) {
184525
184599
  retryStream = !0;
184526
184600
  continue;
184527
184601
  }
184528
184602
  }
184529
184603
  } catch (err8) {
184530
184604
  if (!signal?.aborted && !engineFrameSeen && isPreStreamDrainingReject(err8) && drainingRetries < DRAINING_MAX_RETRIES) {
184531
- let waitMs = drainingRetryDelayMs(err8, drainingRetries);
184605
+ let waitMs = drainingRetryDelayMs2(err8, drainingRetries);
184532
184606
  if (drainingRetries++, process.env.SEMA_DEBUG && console.error(
184533
184607
  `[sema][seamQuery] engine draining (pre-stream 503) \u2014 retrying submit ${drainingRetries}/${DRAINING_MAX_RETRIES} in ${waitMs}ms`
184534
184608
  ), await new Promise((res) => setTimeout(res, waitMs)), !signal?.aborted) {
@@ -184741,7 +184815,7 @@ function resumeRunningArmWiring() {
184741
184815
  shellSessionId: () => getSessionId()
184742
184816
  };
184743
184817
  }
184744
- var BG_TEAR_MAX_RESENDS, BG_RECOVERY_WAIT_MS, DRAINING_MAX_RETRIES, DEFAULT_DRAINING_BACKOFF_MS, DRAINING_RETRY_AFTER_CAP_MS, drainingBackoffMs, client, clientExplicitlySet, seamSettings, 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({
184818
+ var BG_TEAR_MAX_RESENDS, BG_RECOVERY_WAIT_MS, DRAINING_MAX_RETRIES, drainingBackoffMs, client, clientExplicitlySet, seamSettings, 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({
184745
184819
  "build-src/src/sema/seamQuery.ts"() {
184746
184820
  init_adapter();
184747
184821
  init_dist();
@@ -184763,6 +184837,7 @@ var BG_TEAR_MAX_RESENDS, BG_RECOVERY_WAIT_MS, DRAINING_MAX_RETRIES, DEFAULT_DRAI
184763
184837
  init_dist();
184764
184838
  init_dist();
184765
184839
  init_dist();
184840
+ init_dist();
184766
184841
  init_deferSessionExemption();
184767
184842
  init_debug();
184768
184843
  init_hooksWireCaps2();
@@ -184798,7 +184873,7 @@ var BG_TEAR_MAX_RESENDS, BG_RECOVERY_WAIT_MS, DRAINING_MAX_RETRIES, DEFAULT_DRAI
184798
184873
  init_log2();
184799
184874
  init_engineRuntimeStatus();
184800
184875
  init_activeRunSelfHeal2();
184801
- BG_TEAR_MAX_RESENDS = 2, BG_RECOVERY_WAIT_MS = 12e4, DRAINING_MAX_RETRIES = 3, DEFAULT_DRAINING_BACKOFF_MS = [1e3, 2e3, 4e3], DRAINING_RETRY_AFTER_CAP_MS = 15e3, drainingBackoffMs = DEFAULT_DRAINING_BACKOFF_MS;
184876
+ BG_TEAR_MAX_RESENDS = 2, BG_RECOVERY_WAIT_MS = 12e4, DRAINING_MAX_RETRIES = 3;
184802
184877
  client = makeMockClient(), clientExplicitlySet = !1;
184803
184878
  seamRewindCapture = !0;
184804
184879
  INTERRUPT_WIRE_MARKER = "[Request interrupted by user]", seamPendingInterrupt = !1;
@@ -201033,7 +201108,7 @@ var require_ceylon = __commonJS({
201033
201108
  // node_modules/highlight.js/lib/languages/clean.js
201034
201109
  var require_clean2 = __commonJS({
201035
201110
  "node_modules/highlight.js/lib/languages/clean.js"(exports2, module2) {
201036
- function clean5(hljs2) {
201111
+ function clean6(hljs2) {
201037
201112
  return {
201038
201113
  name: "Clean",
201039
201114
  aliases: [
@@ -201089,7 +201164,7 @@ var require_clean2 = __commonJS({
201089
201164
  ]
201090
201165
  };
201091
201166
  }
201092
- module2.exports = clean5;
201167
+ module2.exports = clean6;
201093
201168
  }
201094
201169
  });
201095
201170
 
@@ -257943,7 +258018,7 @@ function stripUnderlineAnsi(content) {
257943
258018
  }
257944
258019
  var import_compiler_runtime24, React16, import_jsx_runtime27, MAX_JSON_FORMAT_LENGTH, URL_IN_JSON, init_OutputLine = __esm({
257945
258020
  "build-src/src/components/shell/OutputLine.tsx"() {
257946
- import_compiler_runtime24 = __toESM(require_compiler_runtime(), 1), React16 = __toESM(require_react(), 1);
258021
+ import_compiler_runtime24 = __toESM(require_compiler_runtime()), React16 = __toESM(require_react());
257947
258022
  init_useTerminalSize();
257948
258023
  init_ink2();
257949
258024
  init_hyperlink();
@@ -257952,7 +258027,7 @@ var import_compiler_runtime24, React16, import_jsx_runtime27, MAX_JSON_FORMAT_LE
257952
258027
  init_MessageResponse();
257953
258028
  init_messageActions();
257954
258029
  init_ExpandShellOutputContext();
257955
- import_jsx_runtime27 = __toESM(require_jsx_runtime(), 1);
258030
+ import_jsx_runtime27 = __toESM(require_jsx_runtime());
257956
258031
  MAX_JSON_FORMAT_LENGTH = 1e4;
257957
258032
  URL_IN_JSON = /https?:\/\/[^\s"'<>\\]+/g;
257958
258033
  }
@@ -262544,7 +262619,7 @@ var import_xss2, AUTH_REQUEST_TIMEOUT_MS, MAX_LOCK_RETRIES, SENSITIVE_OAUTH_PARA
262544
262619
  logMCPDebug(
262545
262620
  this.serverName,
262546
262621
  `Refresh lock held by another process, waiting (attempt ${retry + 1}/${MAX_LOCK_RETRIES})`
262547
- ), await sleep3(1e3 + Math.random() * 1e3);
262622
+ ), await sleep2(1e3 + Math.random() * 1e3);
262548
262623
  continue;
262549
262624
  }
262550
262625
  logMCPDebug(
@@ -262685,7 +262760,7 @@ var import_xss2, AUTH_REQUEST_TIMEOUT_MS, MAX_LOCK_RETRIES, SENSITIVE_OAUTH_PARA
262685
262760
  logMCPDebug(
262686
262761
  this.serverName,
262687
262762
  `Token refresh failed, retrying in ${delayMs}ms (attempt ${attempt}/3)`
262688
- ), await sleep3(delayMs);
262763
+ ), await sleep2(delayMs);
262689
262764
  }
262690
262765
  }
262691
262766
  };
@@ -263926,7 +264001,7 @@ async function findAvailableIDE() {
263926
264001
  let startTime = Date.now();
263927
264002
  for (; Date.now() - startTime < 3e4 && !signal.aborted; ) {
263928
264003
  if (getIsScrollDraining()) {
263929
- await sleep3(1e3, signal);
264004
+ await sleep2(1e3, signal);
263930
264005
  continue;
263931
264006
  }
263932
264007
  let ides = await detectIDEs(!1);
@@ -263934,7 +264009,7 @@ async function findAvailableIDE() {
263934
264009
  return null;
263935
264010
  if (ides.length === 1)
263936
264011
  return ides[0];
263937
- await sleep3(1e3, signal);
264012
+ await sleep2(1e3, signal);
263938
264013
  }
263939
264014
  return null;
263940
264015
  }
@@ -264038,7 +264113,7 @@ async function installIDEExtension(ideType) {
264038
264113
  return await installFromArtifactory(command8);
264039
264114
  let version4 = await getInstalledVSCodeExtensionVersion(command8);
264040
264115
  if (!version4 || lt(version4, getClaudeCodeVersion())) {
264041
- await sleep3(500);
264116
+ await sleep2(500);
264042
264117
  let result = await execFileNoThrowWithCwd(
264043
264118
  command8,
264044
264119
  ["--force", "--install-extension", "anthropic.claude-code"],
@@ -264306,7 +264381,7 @@ async function installFromArtifactory(command8) {
264306
264381
  }), writeStream = getFsImplementation().createWriteStream(tempVsixPath);
264307
264382
  await new Promise((resolve57, reject3) => {
264308
264383
  vsixResponse.data.pipe(writeStream), writeStream.on("finish", resolve57), writeStream.on("error", reject3);
264309
- }), await sleep3(500);
264384
+ }), await sleep2(500);
264310
264385
  let result = await execFileNoThrowWithCwd(
264311
264386
  command8,
264312
264387
  ["--force", "--install-extension", tempVsixPath],
@@ -268672,18 +268747,17 @@ var FINGERPRINT_SALT, init_fingerprint = __esm({
268672
268747
 
268673
268748
  // build-src/src/sema/livePrincipal.ts
268674
268749
  function resolveLivePrincipal() {
268675
- let v2 = process.env.SEMA_LIVE_PRINCIPAL;
268676
- return v2 && v2.trim() !== "" ? v2 : void 0;
268750
+ return normalizeWirePrincipal(process.env.SEMA_LIVE_PRINCIPAL);
268677
268751
  }
268678
268752
  function resolveFleetPrincipal() {
268679
- let v2 = process.env.SEMA_FLEET_PRINCIPAL;
268680
- return v2 && v2.trim() !== "" ? v2 : resolveLivePrincipal();
268753
+ return normalizeWirePrincipal(process.env.SEMA_FLEET_PRINCIPAL) ?? resolveLivePrincipal();
268681
268754
  }
268682
268755
  function describeLivePrincipal() {
268683
268756
  return resolveLivePrincipal() ?? "absent(owner-null)";
268684
268757
  }
268685
268758
  var init_livePrincipal = __esm({
268686
268759
  "build-src/src/sema/livePrincipal.ts"() {
268760
+ init_dist();
268687
268761
  }
268688
268762
  });
268689
268763
 
@@ -270679,7 +270753,7 @@ var McpAuthError, McpSessionExpiredError, McpToolCallError_I_VERIFIED_THIS_IS_NO
270679
270753
  ), resolve57());
270680
270754
  }, 600);
270681
270755
  try {
270682
- if (await sleep3(100), !resolved) {
270756
+ if (await sleep2(100), !resolved) {
270683
270757
  try {
270684
270758
  process.kill(childPid, 0), logMCPDebug(
270685
270759
  name,
@@ -270695,7 +270769,7 @@ var McpAuthError, McpSessionExpiredError, McpToolCallError_I_VERIFIED_THIS_IS_NO
270695
270769
  resolved = !0, clearInterval(checkInterval), clearTimeout(failsafeTimeout), resolve57();
270696
270770
  return;
270697
270771
  }
270698
- if (await sleep3(400), !resolved)
270772
+ if (await sleep2(400), !resolved)
270699
270773
  try {
270700
270774
  process.kill(childPid, 0), logMCPDebug(
270701
270775
  name,
@@ -274687,7 +274761,7 @@ function createLSPServerInstance(name, config4) {
274687
274761
  let delay = RETRY_BASE_DELAY_MS * Math.pow(2, attempt);
274688
274762
  logForDebugging(
274689
274763
  `LSP request '${method}' to '${name}' got ContentModified error, retrying in ${delay}ms (attempt ${attempt + 1}/${MAX_RETRIES_FOR_TRANSIENT_ERRORS})\u2026`
274690
- ), await sleep3(delay);
274764
+ ), await sleep2(delay);
274691
274765
  continue;
274692
274766
  }
274693
274767
  break;
@@ -281346,9 +281420,9 @@ function checkStartProcess(parsed) {
281346
281420
  }
281347
281421
  }
281348
281422
  if (cmd.args.some((a) => {
281349
- let clean5 = a.replace(/`/g, "");
281423
+ let clean6 = a.replace(/`/g, "");
281350
281424
  return /^[-\u2013\u2014\u2015/]v[a-z]*:['"` ]*runas['"` ]*$/i.test(
281351
- clean5
281425
+ clean6
281352
281426
  );
281353
281427
  }))
281354
281428
  return {
@@ -286127,7 +286201,7 @@ function FileEditToolUseRejectedMessage(t0) {
286127
286201
  }
286128
286202
  var import_compiler_runtime43, import_jsx_runtime52, MAX_LINES_TO_RENDER, init_FileEditToolUseRejectedMessage = __esm({
286129
286203
  "build-src/src/components/FileEditToolUseRejectedMessage.tsx"() {
286130
- import_compiler_runtime43 = __toESM(require_compiler_runtime());
286204
+ import_compiler_runtime43 = __toESM(require_compiler_runtime(), 1);
286131
286205
  init_useTerminalSize();
286132
286206
  init_cwd();
286133
286207
  init_ink2();
@@ -286135,7 +286209,7 @@ var import_compiler_runtime43, import_jsx_runtime52, MAX_LINES_TO_RENDER, init_F
286135
286209
  init_MessageResponse();
286136
286210
  init_StructuredDiffList();
286137
286211
  init_stringUtils();
286138
- import_jsx_runtime52 = __toESM(require_jsx_runtime()), MAX_LINES_TO_RENDER = 10;
286212
+ import_jsx_runtime52 = __toESM(require_jsx_runtime(), 1), MAX_LINES_TO_RENDER = 10;
286139
286213
  }
286140
286214
  });
286141
286215
 
@@ -294728,7 +294802,7 @@ async function* withRetry(getClient, operation, options) {
294728
294802
  }
294729
294803
  let retryAfterMs = getRetryAfterMs(error51);
294730
294804
  if (retryAfterMs !== null && retryAfterMs < SHORT_RETRY_THRESHOLD_MS) {
294731
- await sleep3(retryAfterMs, options.signal, { abortError });
294805
+ await sleep2(retryAfterMs, options.signal, { abortError });
294732
294806
  continue;
294733
294807
  }
294734
294808
  let cooldownMs = Math.max(
@@ -294814,11 +294888,11 @@ async function* withRetry(getClient, operation, options) {
294814
294888
  maxRetries
294815
294889
  ));
294816
294890
  let chunk2 = Math.min(remaining, HEARTBEAT_INTERVAL_MS2);
294817
- await sleep3(chunk2, options.signal, { abortError }), remaining -= chunk2;
294891
+ await sleep2(chunk2, options.signal, { abortError }), remaining -= chunk2;
294818
294892
  }
294819
294893
  attempt >= maxRetries && (attempt = maxRetries);
294820
294894
  } else
294821
- error51 instanceof APIError && (yield createSystemAPIErrorMessage(error51, delayMs, attempt, maxRetries)), await sleep3(delayMs, options.signal, { abortError });
294895
+ error51 instanceof APIError && (yield createSystemAPIErrorMessage(error51, delayMs, attempt, maxRetries)), await sleep2(delayMs, options.signal, { abortError });
294822
294896
  }
294823
294897
  }
294824
294898
  throw new CannotRetryError(lastError, retryContext);
@@ -296573,7 +296647,7 @@ async function waitForSessionMemoryExtraction() {
296573
296647
  for (; extractionStartedAt; ) {
296574
296648
  if (Date.now() - extractionStartedAt > EXTRACTION_STALE_THRESHOLD_MS || Date.now() - startTime > EXTRACTION_WAIT_TIMEOUT_MS)
296575
296649
  return;
296576
- await sleep3(1e3);
296650
+ await sleep2(1e3);
296577
296651
  }
296578
296652
  }
296579
296653
  async function getSessionMemoryContent() {
@@ -299857,7 +299931,7 @@ async function streamCompactSummary({
299857
299931
  if (context3.abortController.signal.aborted)
299858
299932
  throw new Error(ERROR_MESSAGE_USER_ABORT);
299859
299933
  if (attempt < maxAttempts) {
299860
- await sleep3(getRetryDelay(attempt), context3.abortController.signal, {
299934
+ await sleep2(getRetryDelay(attempt), context3.abortController.signal, {
299861
299935
  abortError: () => new APIUserAbortError()
299862
299936
  });
299863
299937
  continue;
@@ -301111,7 +301185,7 @@ async function gracefulShutdown(exitCode = 0, reason = "other", options) {
301111
301185
  try {
301112
301186
  await Promise.race([
301113
301187
  Promise.all([shutdown1PEventLogging(), shutdownDatadog()]),
301114
- sleep3(500)
301188
+ sleep2(500)
301115
301189
  ]);
301116
301190
  } catch {
301117
301191
  }
@@ -301506,7 +301580,7 @@ async function fetchWithRetry(cachedChecksum) {
301506
301580
  let delayMs = getRetryDelay(attempt);
301507
301581
  logForDebugging(
301508
301582
  `Policy limits: Retry ${attempt}/${DEFAULT_MAX_RETRIES2} after ${delayMs}ms`
301509
- ), await sleep3(delayMs);
301583
+ ), await sleep2(delayMs);
301510
301584
  }
301511
301585
  return lastResult2;
301512
301586
  }
@@ -304001,7 +304075,7 @@ async function fetchWithRetry2(cachedChecksum) {
304001
304075
  let delayMs = getRetryDelay(attempt);
304002
304076
  logForDebugging(
304003
304077
  `Remote settings: Retry ${attempt}/${DEFAULT_MAX_RETRIES3} after ${delayMs}ms`
304004
- ), await sleep3(delayMs);
304078
+ ), await sleep2(delayMs);
304005
304079
  }
304006
304080
  return lastResult2;
304007
304081
  }
@@ -306333,7 +306407,7 @@ async function downloadAndVerifyBinary(binaryUrl, expectedChecksum, binaryPath,
306333
306407
  if (isStallTimeout ? lastError = new StallTimeoutError() : lastError = toError(error51), isStallTimeout && attempt < MAX_DOWNLOAD_RETRIES) {
306334
306408
  logForDebugging(
306335
306409
  `Download stalled on attempt ${attempt}/${MAX_DOWNLOAD_RETRIES}, retrying...`
306336
- ), await sleep3(1e3);
306410
+ ), await sleep2(1e3);
306337
306411
  continue;
306338
306412
  }
306339
306413
  throw lastError;
@@ -306687,7 +306761,7 @@ async function tryWithVersionLock(versionFilePath, callback, retries = 0) {
306687
306761
  minTimeout * Math.pow(2, attempts - 1),
306688
306762
  maxTimeout
306689
306763
  );
306690
- await sleep3(timeout3);
306764
+ await sleep2(timeout3);
306691
306765
  }
306692
306766
  }
306693
306767
  return logLockAcquisitionError(
@@ -312749,7 +312823,7 @@ async function waitForNextPromptOrShutdown(identity3, abortController, taskId, g
312749
312823
  from: "user"
312750
312824
  };
312751
312825
  }
312752
- if (pollCount > 0 && await sleep3(500), pollCount++, abortController.signal.aborted)
312826
+ if (pollCount > 0 && await sleep2(500), pollCount++, abortController.signal.aborted)
312753
312827
  return logForDebugging(
312754
312828
  `[inProcessRunner] ${identity3.agentName} aborted while waiting (poll #${pollCount})`
312755
312829
  ), { type: "aborted" };
@@ -313936,7 +314010,7 @@ __export(TmuxBackend_exports, {
313936
314010
  TmuxBackend: () => TmuxBackend
313937
314011
  });
313938
314012
  function waitForPaneShellReady() {
313939
- return sleep3(PANE_SHELL_INIT_DELAY_MS);
314013
+ return sleep2(PANE_SHELL_INIT_DELAY_MS);
313940
314014
  }
313941
314015
  function acquirePaneCreationLock() {
313942
314016
  let release2, newLock = new Promise((resolve57) => {
@@ -316475,7 +316549,7 @@ async function axiosGetWithRetry(url3, config4) {
316475
316549
  let delay = TELEPORT_RETRY_DELAYS[attempt] ?? 2e3;
316476
316550
  logForDebugging(
316477
316551
  `Teleport request failed (attempt ${attempt + 1}/${MAX_TELEPORT_RETRIES + 1}), retrying in ${delay}ms: ${errorMessage(error51)}`
316478
- ), await sleep3(delay);
316552
+ ), await sleep2(delay);
316479
316553
  }
316480
316554
  throw lastError;
316481
316555
  }
@@ -323650,7 +323724,7 @@ async function appendSessionLogImpl(sessionId, entry, url3, headers) {
323650
323724
  let delayMs = Math.min(BASE_DELAY_MS2 * Math.pow(2, attempt - 1), 8e3);
323651
323725
  logForDebugging(
323652
323726
  `Remote persistence attempt ${attempt}/${MAX_RETRIES} failed, retrying in ${delayMs}ms\u2026`
323653
- ), await sleep3(delayMs);
323727
+ ), await sleep2(delayMs);
323654
323728
  }
323655
323729
  return !1;
323656
323730
  }
@@ -323887,7 +323961,7 @@ async function ensureDaemonRunning() {
323887
323961
  { detached: !0, stdio: "ignore", env: process.env, windowsHide: !0 }
323888
323962
  ).unref());
323889
323963
  for (let i = 0; i < 100; i++)
323890
- if (await sleep7(150), info = await readDaemonInfo(), info && isDaemonAlive(info) && await pingOk(info)) return info;
323964
+ if (await sleep6(150), info = await readDaemonInfo(), info && isDaemonAlive(info) && await pingOk(info)) return info;
323891
323965
  return null;
323892
323966
  }
323893
323967
  function daemonStartupFailureMessage(registeredLate) {
@@ -323923,7 +323997,7 @@ async function dispatchJob(job) {
323923
323997
  return { ok: !1, code: "daemon-unreachable" };
323924
323998
  }
323925
323999
  for (let i = 0; i < 40; i++) {
323926
- await sleep7(200);
324000
+ await sleep6(200);
323927
324001
  try {
323928
324002
  let r = await daemonRpc(info, { op: "await-ack", short: job.short }, 2e3), mapped = mapResponse(r);
323929
324003
  if (mapped) return mapped;
@@ -323951,11 +324025,11 @@ async function dispatchJob(job) {
323951
324025
  }
323952
324026
  return { ok: !1, code: "daemon-unreachable" };
323953
324027
  }
323954
- var MAX_RPC_BYTES, sleep7, init_client7 = __esm({
324028
+ var MAX_RPC_BYTES, sleep6, init_client7 = __esm({
323955
324029
  "build-src/src/daemon/client.ts"() {
323956
324030
  init_envUtils();
323957
324031
  init_state2();
323958
- MAX_RPC_BYTES = 1048576, sleep7 = (ms) => new Promise((r) => setTimeout(r, ms));
324032
+ MAX_RPC_BYTES = 1048576, sleep6 = (ms) => new Promise((r) => setTimeout(r, ms));
323959
324033
  }
323960
324034
  });
323961
324035
 
@@ -323969,7 +324043,7 @@ async function waitPidGone(pid, deadlineMs) {
323969
324043
  let until = Date.now() + deadlineMs;
323970
324044
  for (; Date.now() < until; ) {
323971
324045
  if (!isPidAlive(pid)) return !0;
323972
- await sleep8(100);
324046
+ await sleep7(100);
323973
324047
  }
323974
324048
  return !isPidAlive(pid);
323975
324049
  }
@@ -323979,7 +324053,7 @@ async function stopDaemonWorker(short) {
323979
324053
  try {
323980
324054
  let r = await daemonRpc(info, { op: "kill", short }, 1e4);
323981
324055
  for (let i = 0; !r.ok && r.code === "ESTARTING" && i < 10; i++)
323982
- await sleep8(200), r = await daemonRpc(info, { op: "kill", short }, 1e4);
324056
+ await sleep7(200), r = await daemonRpc(info, { op: "kill", short }, 1e4);
323983
324057
  if (r.ok) return { confirmed: !0 };
323984
324058
  if (r.code !== "ENOJOB")
323985
324059
  return { confirmed: !1, error: r.message ?? r.code };
@@ -324061,11 +324135,11 @@ async function respawnJob(short, opts = {}) {
324061
324135
  error: "Previous session is still shutting down \u2014 try again in a moment"
324062
324136
  } : { ok: !1, alive: !1, error: "Couldn't reach the daemon (not running)" };
324063
324137
  }
324064
- var sleep8, init_respawn = __esm({
324138
+ var sleep7, init_respawn = __esm({
324065
324139
  "build-src/src/daemon/respawn.ts"() {
324066
324140
  init_client7();
324067
324141
  init_state2();
324068
- sleep8 = (ms) => new Promise((r) => setTimeout(r, ms));
324142
+ sleep7 = (ms) => new Promise((r) => setTimeout(r, ms));
324069
324143
  }
324070
324144
  });
324071
324145
 
@@ -325319,7 +325393,7 @@ async function retryWithBackoff(operation, attemptFn) {
325319
325393
  `${operation} attempt ${attempt}/${MAX_RETRIES2} failed: ${lastError}`
325320
325394
  ), attempt < MAX_RETRIES2) {
325321
325395
  let delayMs = BASE_DELAY_MS3 * Math.pow(2, attempt - 1);
325322
- logDebug(`Retrying ${operation} in ${delayMs}ms...`), await sleep3(delayMs);
325396
+ logDebug(`Retrying ${operation} in ${delayMs}ms...`), await sleep2(delayMs);
325323
325397
  }
325324
325398
  }
325325
325399
  throw new Error(`${lastError} after ${MAX_RETRIES2} attempts`);
@@ -328602,7 +328676,7 @@ var import_jsx_runtime140, proactiveModule, PROGRESS_THRESHOLD_MS2, isBackground
328602
328676
  let hasPendingRequiredServers = appState.mcp.clients.some((c2) => c2.type === "pending" && requiredMcpServers.some((pattern) => c2.name.toLowerCase().includes(pattern.toLowerCase()))), currentAppState = appState;
328603
328677
  if (hasPendingRequiredServers) {
328604
328678
  let deadline = Date.now() + 3e4;
328605
- for (; Date.now() < deadline && (await sleep3(500), currentAppState = toolUseContext.getAppState(), !(currentAppState.mcp.clients.some((c2) => c2.type === "failed" && requiredMcpServers.some((pattern) => c2.name.toLowerCase().includes(pattern.toLowerCase()))) || !currentAppState.mcp.clients.some((c2) => c2.type === "pending" && requiredMcpServers.some((pattern) => c2.name.toLowerCase().includes(pattern.toLowerCase()))))); )
328679
+ for (; Date.now() < deadline && (await sleep2(500), currentAppState = toolUseContext.getAppState(), !(currentAppState.mcp.clients.some((c2) => c2.type === "failed" && requiredMcpServers.some((pattern) => c2.name.toLowerCase().includes(pattern.toLowerCase()))) || !currentAppState.mcp.clients.some((c2) => c2.type === "pending" && requiredMcpServers.some((pattern) => c2.name.toLowerCase().includes(pattern.toLowerCase()))))); )
328606
328680
  ;
328607
328681
  }
328608
328682
  let serversWithTools = [];
@@ -328859,7 +328933,7 @@ var import_jsx_runtime140, proactiveModule, PROGRESS_THRESHOLD_MS2, isBackground
328859
328933
  let stopBackgroundedSummarization;
328860
328934
  try {
328861
328935
  await Promise.race([agentIterator.return(void 0).catch(() => {
328862
- }), sleep3(1e3)]);
328936
+ }), sleep2(1e3)]);
328863
328937
  let tracker = createProgressTracker(), resolveActivity2 = createActivityDescriptionResolver(toolUseContext.options.tools);
328864
328938
  for (let existingMsg of agentMessages)
328865
328939
  updateProgressFromMessage(tracker, existingMsg, resolveActivity2, toolUseContext.options.tools);
@@ -345693,7 +345767,7 @@ async function waitForTaskCompletion(taskId, getAppState, timeoutMs, abortContro
345693
345767
  return null;
345694
345768
  if (task.status !== "running" && task.status !== "pending")
345695
345769
  return task;
345696
- await sleep3(100);
345770
+ await sleep2(100);
345697
345771
  }
345698
345772
  return getAppState().tasks?.[taskId] ?? null;
345699
345773
  }
@@ -373094,7 +373168,7 @@ async function flushPromptHistory(retries) {
373094
373168
  try {
373095
373169
  await immediateFlushHistory();
373096
373170
  } finally {
373097
- isWriting = !1, pendingEntries.length > 0 && (await sleep3(500), flushPromptHistory(retries + 1));
373171
+ isWriting = !1, pendingEntries.length > 0 && (await sleep2(500), flushPromptHistory(retries + 1));
373098
373172
  }
373099
373173
  }
373100
373174
  }
@@ -400115,20 +400189,15 @@ var sema_brand_default, init_sema_brand = __esm({
400115
400189
  _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"
400116
400190
  },
400117
400191
  whatsNew: {
400118
- version: "1.0.76",
400192
+ version: "1.0.78",
400119
400193
  notes: [
400120
- "The agents panel no longer opens mid-turn: while a turn is in flight, the left-arrow key stays with the composer, and the footer hint plus the background-agent placeholder only advertise \u2190 when the prompt is idle and empty \u2014 the panel can no longer yank the screen away from a streaming turn",
400121
- "ctrl+b (send the current work to the background) no longer takes the turn's already-backgrounded subagents down with it",
400122
- "Resuming a session with a parked approval no longer risks a false deadlock: the ownership recheck that guards card re-presentation now recognizes runs by their persisted task id as well as the in-process ledger, so a first-turn park \u2192 kill \u2192 resume re-presents exactly one live card",
400123
- `Approval-card rule suggestions got stricter and more honest: interpreter-style commands (python, node, npx, eval, exec, ssh and friends) are never offered as persistent allow rules in any spelling, and "won't ask again" is only claimed when the rule took effect live \u2014 otherwise the card says it fully applies after restart`,
400124
- "Background subagents stream their transcript into the viewing pane while they run (per-agent detail stream), and the idle placeholder points at the agents panel instead of a stale hint",
400125
- "Task list rendering no longer collapses rows in fullscreen (alt-screen) terminals",
400126
- "Durable run controls from a reconnected session no longer fail due to a lost client binding on the run verbs",
400127
- "Engine unchanged at 7.19.0 (same pin as 1.0.75); this release is a shell-side interaction-safety and correctness batch"
400194
+ "Approval cards now actually show the reversibility-probe note promised in 1.0.77: client-core 0.30.4 forwards the probe cause on both the live approval frame and the durable parked row, so the one-line 'reversibility probe: \u2026 \u2014 roots: \u2026' explanation reaches the card in the default interactive path (this closes the gap where 1.0.77 advertised the note but the wire dropped it in transit)",
400195
+ "The subagent tail stream now publishes engine meta frames to the shell, so content-frame availability is knowable per subagent (groundwork; the viewing-pane hint that consumes it ships separately)",
400196
+ "No engine change: still 7.22.0"
400128
400197
  ]
400129
400198
  },
400130
- productVersion: "1.0.76",
400131
- announcement: `sema 1.0.76 \u2014 Interaction-safety batch: the agents panel no longer opens mid-turn (\u2190 stays with the composer while a turn is in flight, and every hint that advertises it follows the same predicate), ctrl+b no longer takes backgrounded subagents down with it, and resume ownership rechecks recognize persisted task ids so parked approvals re-present exactly once instead of dead-locking. Approval-card rule suggestions refuse interpreter-family commands in every spelling and only claim "won't ask again" when the rule applied live. Background subagents stream their transcripts into the viewer, and fullscreen task lists render without row collapse. Engine unchanged at 7.19.0.`
400199
+ productVersion: "1.0.78",
400200
+ announcement: "sema 1.0.78 \u2014 Fix release: the reversibility-probe note on approval cards (advertised in 1.0.77) now actually renders \u2014 client-core 0.30.4 forwards the probe cause across both the live frame and durable parked rows, closing the transit gap a black-box audit caught. Subagent tail streams now surface engine meta frames as groundwork for per-agent content-frame hints. Engine unchanged at 7.22.0."
400132
400201
  };
400133
400202
  }
400134
400203
  });
@@ -404175,7 +404244,7 @@ function VirtualMessageList({
404175
404244
  if (indexWarmed.current) return 0;
404176
404245
  let msgs = jumpState.current.messages, CHUNK = 500, workMs = 0, wallStart = performance.now();
404177
404246
  for (let i = 0; i < msgs.length; i += CHUNK) {
404178
- await sleep3(0);
404247
+ await sleep2(0);
404179
404248
  let t0 = performance.now(), end2 = Math.min(i + CHUNK, msgs.length);
404180
404249
  for (let j3 = i; j3 < end2; j3++)
404181
404250
  extractSearchText(msgs[j3]);
@@ -404331,20 +404400,15 @@ var require_sema_brand = __commonJS({
404331
404400
  _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"
404332
404401
  },
404333
404402
  whatsNew: {
404334
- version: "1.0.76",
404403
+ version: "1.0.78",
404335
404404
  notes: [
404336
- "The agents panel no longer opens mid-turn: while a turn is in flight, the left-arrow key stays with the composer, and the footer hint plus the background-agent placeholder only advertise \u2190 when the prompt is idle and empty \u2014 the panel can no longer yank the screen away from a streaming turn",
404337
- "ctrl+b (send the current work to the background) no longer takes the turn's already-backgrounded subagents down with it",
404338
- "Resuming a session with a parked approval no longer risks a false deadlock: the ownership recheck that guards card re-presentation now recognizes runs by their persisted task id as well as the in-process ledger, so a first-turn park \u2192 kill \u2192 resume re-presents exactly one live card",
404339
- `Approval-card rule suggestions got stricter and more honest: interpreter-style commands (python, node, npx, eval, exec, ssh and friends) are never offered as persistent allow rules in any spelling, and "won't ask again" is only claimed when the rule took effect live \u2014 otherwise the card says it fully applies after restart`,
404340
- "Background subagents stream their transcript into the viewing pane while they run (per-agent detail stream), and the idle placeholder points at the agents panel instead of a stale hint",
404341
- "Task list rendering no longer collapses rows in fullscreen (alt-screen) terminals",
404342
- "Durable run controls from a reconnected session no longer fail due to a lost client binding on the run verbs",
404343
- "Engine unchanged at 7.19.0 (same pin as 1.0.75); this release is a shell-side interaction-safety and correctness batch"
404405
+ "Approval cards now actually show the reversibility-probe note promised in 1.0.77: client-core 0.30.4 forwards the probe cause on both the live approval frame and the durable parked row, so the one-line 'reversibility probe: \u2026 \u2014 roots: \u2026' explanation reaches the card in the default interactive path (this closes the gap where 1.0.77 advertised the note but the wire dropped it in transit)",
404406
+ "The subagent tail stream now publishes engine meta frames to the shell, so content-frame availability is knowable per subagent (groundwork; the viewing-pane hint that consumes it ships separately)",
404407
+ "No engine change: still 7.22.0"
404344
404408
  ]
404345
404409
  },
404346
- productVersion: "1.0.76",
404347
- announcement: `sema 1.0.76 \u2014 Interaction-safety batch: the agents panel no longer opens mid-turn (\u2190 stays with the composer while a turn is in flight, and every hint that advertises it follows the same predicate), ctrl+b no longer takes backgrounded subagents down with it, and resume ownership rechecks recognize persisted task ids so parked approvals re-present exactly once instead of dead-locking. Approval-card rule suggestions refuse interpreter-family commands in every spelling and only claim "won't ask again" when the rule applied live. Background subagents stream their transcripts into the viewer, and fullscreen task lists render without row collapse. Engine unchanged at 7.19.0.`
404410
+ productVersion: "1.0.78",
404411
+ announcement: "sema 1.0.78 \u2014 Fix release: the reversibility-probe note on approval cards (advertised in 1.0.77) now actually renders \u2014 client-core 0.30.4 forwards the probe cause across both the live frame and durable parked rows, closing the transit gap a black-box audit caught. Subagent tail streams now surface engine meta frames as groundwork for per-agent content-frame hints. Engine unchanged at 7.22.0."
404348
404412
  };
404349
404413
  }
404350
404414
  });
@@ -407531,7 +407595,7 @@ async function pollForApprovedExitPlanMode(sessionId, timeoutMs, onPhaseChange,
407531
407595
  scanner.rejectCount,
407532
407596
  { cause: e }
407533
407597
  );
407534
- await sleep3(POLL_INTERVAL_MS2);
407598
+ await sleep2(POLL_INTERVAL_MS2);
407535
407599
  continue;
407536
407600
  }
407537
407601
  let result;
@@ -407563,7 +407627,7 @@ async function pollForApprovedExitPlanMode(sessionId, timeoutMs, onPhaseChange,
407563
407627
  scanner.rejectCount
407564
407628
  );
407565
407629
  let quietIdle = (sessionStatus === "idle" || sessionStatus === "requires_action") && newEvents.length === 0, phase = scanner.hasPendingPlan ? "plan_ready" : quietIdle ? "needs_input" : "running";
407566
- phase !== lastPhase && (logForDebugging(`[ultraplan] phase ${lastPhase} \u2192 ${phase}`), lastPhase = phase, onPhaseChange?.(phase)), await sleep3(POLL_INTERVAL_MS2);
407630
+ phase !== lastPhase && (logForDebugging(`[ultraplan] phase ${lastPhase} \u2192 ${phase}`), lastPhase = phase, onPhaseChange?.(phase)), await sleep2(POLL_INTERVAL_MS2);
407567
407631
  }
407568
407632
  throw new UltraplanPollError(
407569
407633
  scanner.everSeenPending ? `no approval after ${timeoutMs / 1e3}s` : `ExitPlanMode never reached after ${timeoutMs / 1e3}s (the remote container failed to start, or session ID mismatch?)`,
@@ -412562,11 +412626,11 @@ function capsBaseUrl2() {
412562
412626
  let raw2 = process.env.SEMA_LIVE_BASEURL;
412563
412627
  return typeof raw2 == "string" && raw2.trim() !== "" ? raw2 : void 0;
412564
412628
  }
412565
- function persistedRulesLaneAvailable(baseUrl = capsBaseUrl2()) {
412566
- return engineCapTrue(baseUrl, "permissionRules");
412629
+ function persistedRulesLaneAvailable2(baseUrl = capsBaseUrl2()) {
412630
+ return persistedRulesLaneAvailable(baseUrl);
412567
412631
  }
412568
- function persistedRulesGovernanceAvailable(baseUrl = capsBaseUrl2()) {
412569
- return engineCapTrue(baseUrl, "permissionRulesRevoke") && engineCapTrue(baseUrl, "permissionRules");
412632
+ function persistedRulesGovernanceAvailable2(baseUrl = capsBaseUrl2()) {
412633
+ return persistedRulesGovernanceAvailable(baseUrl);
412570
412634
  }
412571
412635
  async function resolveRulesFacade() {
412572
412636
  if (facadeOverride) return facadeOverride;
@@ -412600,67 +412664,6 @@ async function kickRulesCapsProbe() {
412600
412664
  logForDebugging(`persistedRulesWire: capability re-probe failed (cache stays unresolved): ${String(e)}`);
412601
412665
  });
412602
412666
  }
412603
- function errShape(e) {
412604
- let o = e ?? {};
412605
- return {
412606
- ...typeof o.status == "number" ? { status: o.status } : {},
412607
- ...typeof o.errorCode == "string" ? { errorCode: o.errorCode } : {},
412608
- message: typeof o.message == "string" && o.message !== "" ? o.message : String(e)
412609
- };
412610
- }
412611
- function retryAfterSecOf(e) {
412612
- let ms = e.retryAfterMs;
412613
- if (!(typeof ms != "number" || !Number.isFinite(ms) || ms < 0))
412614
- return Math.ceil(ms / 1e3);
412615
- }
412616
- function classifyRulesFailure(e) {
412617
- let { status: status3, errorCode, message } = errShape(e);
412618
- if (status3 === 501 || errorCode === "capability.rule_store_required")
412619
- return { kind: "lane-unavailable", message };
412620
- if (status3 === 404)
412621
- return errorCode === "not_found.route" ? { kind: "route-missing", message } : errorCode === "not_found.rule_ticket" ? { kind: "ticket-dead", message } : { kind: "error", message };
412622
- if (errorCode === "state.rule_import_retry") {
412623
- let sec = retryAfterSecOf(e);
412624
- return { kind: "retry-same-ticket", message, ...sec !== void 0 ? { retryAfterSec: sec } : {} };
412625
- }
412626
- return errorCode === "state.rule_remove_failed" ? { kind: "retryable", message } : status3 === 400 && errorCode === "request.query_invalid" ? { kind: "cursor-stale", message } : status3 === 413 ? { kind: "too-many-candidates", message } : status3 === 403 && errorCode === "auth.operator_only" ? { kind: "forbidden", message } : { kind: "error", message };
412627
- }
412628
- async function listAllPersistedRules(facade, params = {}, opts) {
412629
- for (let attempt = 0; attempt < 2; attempt++) {
412630
- let rules = [], cursor, rev2 = 0, restart = !1;
412631
- for (let page = 0; page < MAX_PAGES; page++) {
412632
- let res;
412633
- try {
412634
- res = await facade.list(
412635
- { limit: PAGE_LIMIT, ...params, ...cursor !== void 0 ? { cursor } : {} },
412636
- opts
412637
- );
412638
- } catch (e) {
412639
- let failure = classifyRulesFailure(e);
412640
- if (failure.kind === "cursor-stale" && cursor !== void 0 && attempt === 0) {
412641
- logForDebugging(
412642
- "persistedRulesWire: rule list cursor was minted on another rev/principal/scope \u2014 dropping it and re-listing from the top (never resuming a stale keyset)"
412643
- ), restart = !0;
412644
- break;
412645
- }
412646
- return { ok: !1, failure };
412647
- }
412648
- rev2 = typeof res.rev == "number" ? res.rev : rev2, Array.isArray(res.rules) && rules.push(...res.rules);
412649
- let next = res.nextCursor;
412650
- if (typeof next != "string" || next === "") return { ok: !0, rules, rev: rev2 };
412651
- cursor = next;
412652
- }
412653
- if (!restart)
412654
- return {
412655
- ok: !1,
412656
- failure: {
412657
- kind: "error",
412658
- message: `rule list did not terminate within ${MAX_PAGES} pages \u2014 refusing to present a partial governance list`
412659
- }
412660
- };
412661
- }
412662
- return { ok: !1, failure: { kind: "cursor-stale", message: "rule list kept changing under the cursor \u2014 try again" } };
412663
- }
412664
412667
  async function revokePersistedRule(facade, input, opts) {
412665
412668
  try {
412666
412669
  return { ok: !0, result: await facade.revoke(input, opts) };
@@ -412682,12 +412685,6 @@ async function redeemCcRuleImport(facade, ticket, opts) {
412682
412685
  return { ok: !1, failure: classifyRulesFailure(e) };
412683
412686
  }
412684
412687
  }
412685
- function classifySkippedReason(reason) {
412686
- let text2 = typeof reason == "string" ? reason : String(reason), idx = text2.indexOf(":");
412687
- if (idx <= 0) return { text: text2 };
412688
- let head = text2.slice(0, idx);
412689
- return /^[a-z][a-z0-9_]*(\.[a-z0-9_]+)*$/.test(head) ? { code: head, text: text2 } : { text: text2 };
412690
- }
412691
412688
  function ccRoot() {
412692
412689
  return process.env.SEMA_CC_ROOT || join156(homedir41(), CC_DIR4);
412693
412690
  }
@@ -412791,13 +412788,6 @@ function buildToolApprovalRespondBody(input) {
412791
412788
  ...input.note !== void 0 ? { note: input.note } : {}
412792
412789
  };
412793
412790
  }
412794
- function readRulePersistOutcome(ack) {
412795
- let o = ack ?? {};
412796
- return o.rulePersisted === !0 ? { state: "persisted" } : o.rulePersisted === !1 ? {
412797
- state: "refused",
412798
- ...typeof o.ruleRefusal == "string" && o.ruleRefusal !== "" ? { reason: o.ruleRefusal } : {}
412799
- } : { state: "unknown" };
412800
- }
412801
412791
  function surfaceRulePersistOutcome(ack) {
412802
412792
  let outcome = readRulePersistOutcome(ack);
412803
412793
  if (outcome.state === "unknown") return;
@@ -412818,7 +412808,7 @@ function surfaceRulePersistOutcome(ack) {
412818
412808
  }
412819
412809
  }
412820
412810
  function surfaceLocalRulePersistOutcome(outcome) {
412821
- let text2 = outcome.ok ? outcome.appliedLive ? "Saved: won't ask again for this rule" : "Saved to settings \u2014 fully applies after restart (this session may ask once more)" : `"Don't ask again" was not saved (${outcome.error}) \u2014 the one-time approval is still being submitted`;
412811
+ let text2 = outcome.ok ? outcome.redemptionGated === "budget-disabled" ? "Saved to settings \u2014 but automatic approval is disabled (SEMA_GATE_SYNC_ALLOW_BUDGET=0), so this rule will not silence asks until that changes" : outcome.redemptionGated === "budget-exhausted" ? "Saved to settings \u2014 but this session's automatic-approval budget is used up, so it may keep asking (fully applies after restart)" : outcome.appliedLive ? "Saved: won't ask again for this rule" : "Saved to settings \u2014 fully applies after restart (this session may ask once more)" : `"Don't ask again" was not saved (${outcome.error}) \u2014 the one-time approval is still being submitted`;
412822
412812
  try {
412823
412813
  surfaceWireNotice(
412824
412814
  {
@@ -412834,15 +412824,15 @@ function surfaceLocalRulePersistOutcome(outcome) {
412834
412824
  logForDebugging(`persistedRulesWire: surfacing local rule-persist outcome failed (non-fatal): ${String(e)}`);
412835
412825
  }
412836
412826
  }
412837
- var facadeOverride, PAGE_LIMIT, MAX_PAGES, CC_DIR4, LAYER_BYTE_CAP, RULE_PERSIST_NOTICE_KEY, RULE_PERSIST_NOTICE_DEFAULT_MS, rulePersistNoticeMs, init_persistedRulesWire = __esm({
412827
+ var facadeOverride, CC_DIR4, LAYER_BYTE_CAP, RULE_PERSIST_NOTICE_KEY, RULE_PERSIST_NOTICE_DEFAULT_MS, rulePersistNoticeMs, init_persistedRulesWire2 = __esm({
412838
412828
  "build-src/src/sema/persistedRulesWire.ts"() {
412839
412829
  init_main2();
412840
412830
  init_dist();
412841
412831
  init_debug();
412842
412832
  init_wireNoticePort();
412843
412833
  init_livePrincipal();
412834
+ init_dist();
412844
412835
  facadeOverride = null;
412845
- PAGE_LIMIT = 200, MAX_PAGES = 25;
412846
412836
  CC_DIR4 = ".claude";
412847
412837
  LAYER_BYTE_CAP = 16 * 1024;
412848
412838
  RULE_PERSIST_NOTICE_KEY = "rule-persist-outcome", RULE_PERSIST_NOTICE_DEFAULT_MS = 8e3, rulePersistNoticeMs = RULE_PERSIST_NOTICE_DEFAULT_MS;
@@ -412851,7 +412841,7 @@ var facadeOverride, PAGE_LIMIT, MAX_PAGES, CC_DIR4, LAYER_BYTE_CAP, RULE_PERSIST
412851
412841
 
412852
412842
  // build-src/src/sema/onboard/ccRulesImport.ts
412853
412843
  function detectCcRulesImport(cwd5) {
412854
- if (!persistedRulesLaneAvailable()) return { offer: !1, layers: [], why: "lane-unavailable" };
412844
+ if (!persistedRulesLaneAvailable2()) return { offer: !1, layers: [], why: "lane-unavailable" };
412855
412845
  let { layers: layers2 } = collectCcSettingsLayers(cwd5);
412856
412846
  return layers2.length === 0 ? { offer: !1, layers: [], why: "no-cc-settings" } : { offer: !0, layers: layers2 };
412857
412847
  }
@@ -412887,7 +412877,7 @@ function makeSingleFlightGate() {
412887
412877
  }
412888
412878
  var init_ccRulesImport = __esm({
412889
412879
  "build-src/src/sema/onboard/ccRulesImport.ts"() {
412890
- init_persistedRulesWire();
412880
+ init_persistedRulesWire2();
412891
412881
  }
412892
412882
  });
412893
412883
 
@@ -412921,7 +412911,7 @@ function writeCcImportMarker(marker) {
412921
412911
  var init_ccImportMarker = __esm({
412922
412912
  "build-src/src/sema/rules/ccImportMarker.ts"() {
412923
412913
  init_envUtils();
412924
- init_persistedRulesWire();
412914
+ init_persistedRulesWire2();
412925
412915
  }
412926
412916
  });
412927
412917
 
@@ -413108,7 +413098,7 @@ var React104, import_jsx_runtime305, init_CcRulesImportFlow = __esm({
413108
413098
  init_select();
413109
413099
  init_ink2();
413110
413100
  init_debug();
413111
- init_persistedRulesWire();
413101
+ init_persistedRulesWire2();
413112
413102
  init_ccImportMarker();
413113
413103
  init_ccRulesImport();
413114
413104
  import_jsx_runtime305 = __toESM(require_jsx_runtime(), 1);
@@ -413130,14 +413120,14 @@ function originsLabel(rule) {
413130
413120
  return seen2.length === 0 ? "unknown origin" : seen2.map((o) => o === "user" ? "approved on a card" : o === "imported-cc" ? "imported" : o === "starter" ? "preset" : o).join(" + ");
413131
413121
  }
413132
413122
  function usePersistedRulesGovernanceVisible() {
413133
- let [visible, setVisible] = React105.useState(() => persistedRulesGovernanceAvailable());
413123
+ let [visible, setVisible] = React105.useState(() => persistedRulesGovernanceAvailable2());
413134
413124
  return React105.useEffect(() => {
413135
413125
  if (visible) return;
413136
413126
  let alive = !0, timer2 = setInterval(() => {
413137
- alive && persistedRulesGovernanceAvailable() && (setVisible(!0), clearInterval(timer2));
413127
+ alive && persistedRulesGovernanceAvailable2() && (setVisible(!0), clearInterval(timer2));
413138
413128
  }, CAPS_POLL_MS);
413139
413129
  return kickRulesCapsProbe().then(() => {
413140
- alive && persistedRulesGovernanceAvailable() && (setVisible(!0), clearInterval(timer2));
413130
+ alive && persistedRulesGovernanceAvailable2() && (setVisible(!0), clearInterval(timer2));
413141
413131
  }), () => {
413142
413132
  alive = !1, clearInterval(timer2);
413143
413133
  };
@@ -413279,7 +413269,7 @@ var React105, import_jsx_runtime306, CAPS_POLL_MS, init_PersistedRulesTab = __es
413279
413269
  init_ink2();
413280
413270
  init_select();
413281
413271
  init_Tabs();
413282
- init_persistedRulesWire();
413272
+ init_persistedRulesWire2();
413283
413273
  init_detectSources();
413284
413274
  init_ccRulesImport();
413285
413275
  init_CcRulesImportFlow();
@@ -432779,12 +432769,12 @@ async function* sdkMessagesToCcEvents(sdk, meta3) {
432779
432769
  // 绝不铸 transcript 行(帧不带正文,替引擎编话=谎),落 debug 审计留痕(「这条 run 被谁插过话」
432780
432770
  // 可查);wire 值 UNTRUSTED,白名单键+控制字符消毒。
432781
432771
  case "human_input": {
432782
- let clean5 = (v2) => (
432772
+ let clean6 = (v2) => (
432783
432773
  // eslint-disable-next-line no-control-regex
432784
432774
  String(v2 ?? "").replace(/[\x00-\x1f\x7f]/g, ".").slice(0, 120)
432785
- ), who = e.actor?.id ? `${clean5(e.actor.id)}${e.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
432775
+ ), who = e.actor?.id ? `${clean6(e.actor.id)}${e.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
432786
432776
  return logForDebugging(
432787
- `[sema][bridge] human_input ledger frame (audit): carrier=${clean5(e.carrier)} eventId=${clean5(e.eventId)} by=${who}`
432777
+ `[sema][bridge] human_input ledger frame (audit): carrier=${clean6(e.carrier)} eventId=${clean6(e.eventId)} by=${who}`
432788
432778
  ), [];
432789
432779
  }
432790
432780
  default:
@@ -432873,8 +432863,121 @@ var BRIDGE_PROBE_ENV, init_upstreamBridge = __esm({
432873
432863
  });
432874
432864
 
432875
432865
  // node_modules/@sema-agent/core/dist/tools/fs/read-deny.js
432876
- var init_read_deny = __esm({
432866
+ function resolveReadDenyBuiltins(config4) {
432867
+ let activeTiers;
432868
+ if (config4?.tiers === void 0)
432869
+ activeTiers = new Set(READ_DENY_DEFAULT_TIERS);
432870
+ else {
432871
+ if (!Array.isArray(config4.tiers))
432872
+ throw new Error(`readDenyBuiltinTiers: expected an array of tier names, got ${JSON.stringify(config4.tiers)}.`);
432873
+ for (let t2 of config4.tiers)
432874
+ if (typeof t2 != "string" || !READ_DENY_BUILTIN_TIERS.includes(t2))
432875
+ throw new Error(`readDenyBuiltinTiers: unknown tier ${JSON.stringify(t2)} \u2014 known tiers: ${READ_DENY_BUILTIN_TIERS.join(", ")}.`);
432876
+ activeTiers = new Set(config4.tiers);
432877
+ }
432878
+ let excluded;
432879
+ if (config4?.exclude === void 0)
432880
+ excluded = /* @__PURE__ */ new Set();
432881
+ else {
432882
+ if (!Array.isArray(config4.exclude))
432883
+ throw new Error(`readDenyBuiltinExclude: expected an array of built-in row names (canonical pattern texts), got ${JSON.stringify(config4.exclude)}.`);
432884
+ for (let name of config4.exclude)
432885
+ if (typeof name != "string" || !READ_FACE_BUILTIN_DENY_TABLE.some((r) => r.pattern === name))
432886
+ throw new Error(`readDenyBuiltinExclude: ${JSON.stringify(name)} names no built-in row \u2014 row names are the canonical pattern texts of READ_FACE_BUILTIN_DENY_TABLE (e.g. ".ssh", ".config/gcloud").`);
432887
+ excluded = new Set(config4.exclude);
432888
+ }
432889
+ return READ_FACE_BUILTIN_DENY_TABLE.filter((r) => activeTiers.has(r.tier) && !excluded.has(r.pattern));
432890
+ }
432891
+ var READ_DENY_BUILTIN_TIERS, READ_FACE_BUILTIN_DENY_TABLE, READ_DENY_DEFAULT_TIERS, READ_FACE_DEFAULT_DENY_ENTRIES, init_read_deny = __esm({
432877
432892
  "node_modules/@sema-agent/core/dist/tools/fs/read-deny.js"() {
432893
+ READ_DENY_BUILTIN_TIERS = ["credentials", "shell-history", "browser", "wallet"], READ_FACE_BUILTIN_DENY_TABLE = [
432894
+ { pattern: ".ssh", tier: "credentials" },
432895
+ { pattern: "id_rsa*", tier: "credentials" },
432896
+ { pattern: "id_ed25519*", tier: "credentials" },
432897
+ { pattern: "id_ecdsa*", tier: "credentials" },
432898
+ { pattern: ".gnupg", tier: "credentials" },
432899
+ { pattern: ".aws", tier: "credentials" },
432900
+ { pattern: ".config/gcloud", tier: "credentials" },
432901
+ { pattern: ".azure", tier: "credentials" },
432902
+ { pattern: ".kube", tier: "credentials" },
432903
+ { pattern: ".netrc", tier: "credentials" },
432904
+ { pattern: "_netrc", tier: "credentials" },
432905
+ { pattern: ".git-credentials", tier: "credentials" },
432906
+ { pattern: ".docker/config.json", tier: "credentials" },
432907
+ { pattern: ".config/gh", tier: "credentials" },
432908
+ { pattern: ".npmrc", tier: "credentials" },
432909
+ { pattern: ".pypirc", tier: "credentials" },
432910
+ { pattern: ".local/share/keyrings", tier: "credentials" },
432911
+ { pattern: "Library/Keychains", tier: "credentials" },
432912
+ { pattern: ".bash_history", tier: "shell-history" },
432913
+ { pattern: ".zsh_history", tier: "shell-history" },
432914
+ { pattern: "Library/Application Support/Google/Chrome", tier: "browser" },
432915
+ { pattern: "Library/Application Support/Firefox", tier: "browser" },
432916
+ { pattern: "Library/Safari", tier: "browser" },
432917
+ { pattern: ".config/google-chrome", tier: "browser" },
432918
+ { pattern: ".config/chromium", tier: "browser" },
432919
+ { pattern: ".mozilla/firefox", tier: "browser" },
432920
+ { pattern: "AppData/Local/Google/Chrome/User Data", tier: "browser" },
432921
+ { pattern: "AppData/Local/Microsoft/Edge/User Data", tier: "browser" },
432922
+ { pattern: "AppData/Roaming/Mozilla/Firefox", tier: "browser" },
432923
+ { pattern: ".bitcoin", tier: "wallet" },
432924
+ { pattern: ".ethereum", tier: "wallet" },
432925
+ { pattern: ".electrum", tier: "wallet" },
432926
+ { pattern: "Library/Application Support/Exodus", tier: "wallet" },
432927
+ { pattern: "Library/Application Support/Ledger Live", tier: "wallet" },
432928
+ { pattern: "wallet.dat", tier: "wallet" }
432929
+ ], READ_DENY_DEFAULT_TIERS = READ_DENY_BUILTIN_TIERS.filter((t2) => t2 !== "shell-history");
432930
+ READ_FACE_DEFAULT_DENY_ENTRIES = resolveReadDenyBuiltins().map((r) => r.pattern);
432931
+ }
432932
+ });
432933
+
432934
+ // node_modules/@sema-agent/core/dist/core/safe-notify.js
432935
+ function createSafeNotifier(opts) {
432936
+ let onError = opts?.onError, sites, total = 0, record2 = (site, thrown) => {
432937
+ let error51 = thrown instanceof Error ? thrown : new Error(String(thrown));
432938
+ total += 1, sites === void 0 && (sites = /* @__PURE__ */ new Map());
432939
+ let state4 = sites.get(site);
432940
+ if (state4 !== void 0) {
432941
+ state4.count += 1, state4.last = error51;
432942
+ return;
432943
+ }
432944
+ if (sites.set(site, { count: 1, last: error51 }), onError !== void 0)
432945
+ try {
432946
+ onError({ site, error: error51, failures: 1 });
432947
+ } catch {
432948
+ }
432949
+ };
432950
+ return {
432951
+ notify(run2, site) {
432952
+ try {
432953
+ return run2(), !0;
432954
+ } catch (e) {
432955
+ return record2(site, e), !1;
432956
+ }
432957
+ },
432958
+ async notifyAsync(run2, site) {
432959
+ try {
432960
+ return await run2(), !0;
432961
+ } catch (e) {
432962
+ return record2(site, e), !1;
432963
+ }
432964
+ },
432965
+ get failures() {
432966
+ return total;
432967
+ },
432968
+ failuresAt(site) {
432969
+ return sites?.get(site)?.count ?? 0;
432970
+ },
432971
+ lastErrorAt(site) {
432972
+ return sites?.get(site)?.last;
432973
+ },
432974
+ failedSites() {
432975
+ return sites === void 0 ? [] : [...sites.keys()];
432976
+ }
432977
+ };
432978
+ }
432979
+ var init_safe_notify = __esm({
432980
+ "node_modules/@sema-agent/core/dist/core/safe-notify.js"() {
432878
432981
  }
432879
432982
  });
432880
432983
 
@@ -442853,9 +442956,9 @@ var init_union_priority_sort = __esm({
442853
442956
  // node_modules/typebox/build/value/clean/from_union.mjs
442854
442957
  function FromUnion9(context3, type, value) {
442855
442958
  for (let schema of UnionPrioritySort(type.anyOf)) {
442856
- let clean5 = FromType19(context3, schema, Clone2(value));
442857
- if (Check2(context3, schema, clean5))
442858
- return clean5;
442959
+ let clean6 = FromType19(context3, schema, Clone2(value));
442960
+ if (Check2(context3, schema, clean6))
442961
+ return clean6;
442859
442962
  }
442860
442963
  return value;
442861
442964
  }
@@ -446130,56 +446233,6 @@ var REVIVED_ROW_CLEARED_FIELDS, BackgroundAgentStoreError, STALE_RUNNING_REAP_AT
446130
446233
  }
446131
446234
  });
446132
446235
 
446133
- // node_modules/@sema-agent/core/dist/core/safe-notify.js
446134
- function createSafeNotifier(opts) {
446135
- let onError = opts?.onError, sites, total = 0, record2 = (site, thrown) => {
446136
- let error51 = thrown instanceof Error ? thrown : new Error(String(thrown));
446137
- total += 1, sites === void 0 && (sites = /* @__PURE__ */ new Map());
446138
- let state4 = sites.get(site);
446139
- if (state4 !== void 0) {
446140
- state4.count += 1, state4.last = error51;
446141
- return;
446142
- }
446143
- if (sites.set(site, { count: 1, last: error51 }), onError !== void 0)
446144
- try {
446145
- onError({ site, error: error51, failures: 1 });
446146
- } catch {
446147
- }
446148
- };
446149
- return {
446150
- notify(run2, site) {
446151
- try {
446152
- return run2(), !0;
446153
- } catch (e) {
446154
- return record2(site, e), !1;
446155
- }
446156
- },
446157
- async notifyAsync(run2, site) {
446158
- try {
446159
- return await run2(), !0;
446160
- } catch (e) {
446161
- return record2(site, e), !1;
446162
- }
446163
- },
446164
- get failures() {
446165
- return total;
446166
- },
446167
- failuresAt(site) {
446168
- return sites?.get(site)?.count ?? 0;
446169
- },
446170
- lastErrorAt(site) {
446171
- return sites?.get(site)?.last;
446172
- },
446173
- failedSites() {
446174
- return sites === void 0 ? [] : [...sites.keys()];
446175
- }
446176
- };
446177
- }
446178
- var init_safe_notify = __esm({
446179
- "node_modules/@sema-agent/core/dist/core/safe-notify.js"() {
446180
- }
446181
- });
446182
-
446183
446236
  // node_modules/@sema-agent/core/dist/core/workflow-run-store.js
446184
446237
  function summarizeWorkflowRun(run2) {
446185
446238
  let latestPhase = run2.phases.at(-1);
@@ -448998,6 +449051,8 @@ var init_fs_bash = __esm({
448998
449051
  init_remote_env3();
448999
449052
  init_gh_rate_limit();
449000
449053
  init_fs_shared();
449054
+ init_checkpoint_store();
449055
+ init_untrusted_text();
449001
449056
  init_bash_readonly_classifier();
449002
449057
  }
449003
449058
  });
@@ -451022,6 +451077,7 @@ var objectPrototype, init_hooks7 = __esm({
451022
451077
  init_tool_policy();
451023
451078
  init_ask_class();
451024
451079
  init_untrusted_text();
451080
+ init_checkpoint_store();
451025
451081
  init_ask_question();
451026
451082
  init_safe_notify();
451027
451083
  init_permission_rule_org();
@@ -451029,12 +451085,6 @@ var objectPrototype, init_hooks7 = __esm({
451029
451085
  }
451030
451086
  });
451031
451087
 
451032
- // node_modules/@sema-agent/core/dist/core/session-reconcile.js
451033
- var init_session_reconcile = __esm({
451034
- "node_modules/@sema-agent/core/dist/core/session-reconcile.js"() {
451035
- }
451036
- });
451037
-
451038
451088
  // node_modules/@sema-agent/core/dist/core/cache-break-detector.js
451039
451089
  var SERVER_GAP_MS, init_cache_break_detector = __esm({
451040
451090
  "node_modules/@sema-agent/core/dist/core/cache-break-detector.js"() {
@@ -451262,24 +451312,12 @@ var MEMORY_INDEX_MAX_BYTES, init_engine4 = __esm({
451262
451312
  }
451263
451313
  });
451264
451314
 
451265
- // node_modules/@sema-agent/core/dist/core/locked-config.js
451266
- var init_locked_config = __esm({
451267
- "node_modules/@sema-agent/core/dist/core/locked-config.js"() {
451268
- }
451269
- });
451270
-
451271
451315
  // node_modules/@sema-agent/core/dist/core/compliance.js
451272
451316
  var init_compliance = __esm({
451273
451317
  "node_modules/@sema-agent/core/dist/core/compliance.js"() {
451274
451318
  }
451275
451319
  });
451276
451320
 
451277
- // node_modules/@sema-agent/core/dist/core/retention.js
451278
- var init_retention = __esm({
451279
- "node_modules/@sema-agent/core/dist/core/retention.js"() {
451280
- }
451281
- });
451282
-
451283
451321
  // node_modules/@sema-agent/core/dist/core/memory-engine/dual-root.js
451284
451322
  var init_dual_root = __esm({
451285
451323
  "node_modules/@sema-agent/core/dist/core/memory-engine/dual-root.js"() {
@@ -451302,6 +451340,101 @@ var init_prepare_memory = __esm({
451302
451340
  }
451303
451341
  });
451304
451342
 
451343
+ // node_modules/@sema-agent/core/dist/core/locked-config.js
451344
+ var init_locked_config = __esm({
451345
+ "node_modules/@sema-agent/core/dist/core/locked-config.js"() {
451346
+ }
451347
+ });
451348
+
451349
+ // node_modules/@sema-agent/core/dist/core/retention.js
451350
+ var init_retention = __esm({
451351
+ "node_modules/@sema-agent/core/dist/core/retention.js"() {
451352
+ }
451353
+ });
451354
+
451355
+ // node_modules/@sema-agent/core/dist/core/usage-window-store.js
451356
+ var EMPTY_USAGE_WINDOW_RECORD, init_usage_window_store = __esm({
451357
+ "node_modules/@sema-agent/core/dist/core/usage-window-store.js"() {
451358
+ EMPTY_USAGE_WINDOW_RECORD = Object.freeze({
451359
+ slots: Object.freeze([]),
451360
+ buckets: Object.freeze([])
451361
+ });
451362
+ }
451363
+ });
451364
+
451365
+ // node_modules/@sema-agent/core/dist/core/wiring-manifest.js
451366
+ var init_wiring_manifest = __esm({
451367
+ "node_modules/@sema-agent/core/dist/core/wiring-manifest.js"() {
451368
+ init_canonical_json();
451369
+ init_checkpoint_store();
451370
+ init_ask_question();
451371
+ }
451372
+ });
451373
+
451374
+ // node_modules/@sema-agent/core/dist/core/runner/prepare-config-doors.js
451375
+ var TASK_LIMIT_KEY_DICT, TASK_LIMIT_KEYS, init_prepare_config_doors = __esm({
451376
+ "node_modules/@sema-agent/core/dist/core/runner/prepare-config-doors.js"() {
451377
+ init_timeout();
451378
+ init_fs();
451379
+ init_checkpoint_store();
451380
+ init_locked_config();
451381
+ init_retention();
451382
+ init_roles();
451383
+ init_usage_window_store();
451384
+ init_wiring_manifest();
451385
+ TASK_LIMIT_KEY_DICT = {
451386
+ maxTokens: !0,
451387
+ maxCostUsd: !0,
451388
+ maxTurns: !0,
451389
+ maxWalltimeMs: !0,
451390
+ maxOutputTokens: !0,
451391
+ approachNotice: !0,
451392
+ budgetStreamCancel: !0,
451393
+ degrade: !0,
451394
+ brainCallGuardrailMs: !0
451395
+ }, TASK_LIMIT_KEYS = Object.keys(TASK_LIMIT_KEY_DICT);
451396
+ }
451397
+ });
451398
+
451399
+ // node_modules/@sema-agent/core/dist/core/runner/prepare-safety-scan.js
451400
+ var NAMESPACED_NAME_SHAPES, init_prepare_safety_scan = __esm({
451401
+ "node_modules/@sema-agent/core/dist/core/runner/prepare-safety-scan.js"() {
451402
+ init_protocol_table();
451403
+ init_fs();
451404
+ init_tool_result_store();
451405
+ init_present_plan_tool();
451406
+ NAMESPACED_NAME_SHAPES = PROTOCOL_TABLE.map((ns) => `${ns.prefix}<peer>__<tool>`).join(", ");
451407
+ }
451408
+ });
451409
+
451410
+ // node_modules/@sema-agent/core/dist/core/session-reconcile.js
451411
+ var init_session_reconcile = __esm({
451412
+ "node_modules/@sema-agent/core/dist/core/session-reconcile.js"() {
451413
+ }
451414
+ });
451415
+
451416
+ // node_modules/@sema-agent/core/dist/core/runner/prepare-acquire-reconcile.js
451417
+ var init_prepare_acquire_reconcile = __esm({
451418
+ "node_modules/@sema-agent/core/dist/core/runner/prepare-acquire-reconcile.js"() {
451419
+ init_session4();
451420
+ init_session_reconcile();
451421
+ }
451422
+ });
451423
+
451424
+ // node_modules/@sema-agent/core/dist/core/with-retry.js
451425
+ var init_with_retry = __esm({
451426
+ "node_modules/@sema-agent/core/dist/core/with-retry.js"() {
451427
+ }
451428
+ });
451429
+
451430
+ // node_modules/@sema-agent/core/dist/core/runner/prepare-workspace-restore.js
451431
+ var init_prepare_workspace_restore = __esm({
451432
+ "node_modules/@sema-agent/core/dist/core/runner/prepare-workspace-restore.js"() {
451433
+ init_remote_env3();
451434
+ init_with_retry();
451435
+ }
451436
+ });
451437
+
451305
451438
  // node_modules/@sema-agent/core/dist/prompt-assembly/composer.js
451306
451439
  var SINGLE_BLOCK_LAYOUT, init_composer = __esm({
451307
451440
  "node_modules/@sema-agent/core/dist/prompt-assembly/composer.js"() {
@@ -451361,12 +451494,6 @@ var init_stub_env = __esm({
451361
451494
  }
451362
451495
  });
451363
451496
 
451364
- // node_modules/@sema-agent/core/dist/core/with-retry.js
451365
- var init_with_retry = __esm({
451366
- "node_modules/@sema-agent/core/dist/core/with-retry.js"() {
451367
- }
451368
- });
451369
-
451370
451497
  // node_modules/@sema-agent/core/dist/core/runner/teardown-bounded.js
451371
451498
  var init_teardown_bounded = __esm({
451372
451499
  "node_modules/@sema-agent/core/dist/core/runner/teardown-bounded.js"() {
@@ -451489,28 +451616,9 @@ var init_session_file_state_replay = __esm({
451489
451616
  }
451490
451617
  });
451491
451618
 
451492
- // node_modules/@sema-agent/core/dist/core/wiring-manifest.js
451493
- var init_wiring_manifest = __esm({
451494
- "node_modules/@sema-agent/core/dist/core/wiring-manifest.js"() {
451495
- init_canonical_json();
451496
- init_checkpoint_store();
451497
- init_ask_question();
451498
- }
451499
- });
451500
-
451501
- // node_modules/@sema-agent/core/dist/core/usage-window-store.js
451502
- var EMPTY_USAGE_WINDOW_RECORD, init_usage_window_store = __esm({
451503
- "node_modules/@sema-agent/core/dist/core/usage-window-store.js"() {
451504
- EMPTY_USAGE_WINDOW_RECORD = Object.freeze({
451505
- slots: Object.freeze([]),
451506
- buckets: Object.freeze([])
451507
- });
451508
- }
451509
- });
451510
-
451511
451619
  // node_modules/@sema-agent/core/dist/core/runner/prepare-task.js
451512
451620
  import { createHash as createHash27, randomBytes as randomBytes27 } from "node:crypto";
451513
- var PROMPT_HASH_SALT, TASK_LIMIT_KEY_DICT, TASK_LIMIT_KEYS, DEFAULT_RESOURCE_TTL_MS, USAGE_WINDOW_REAP_MARGIN_MS, DEFAULT_UNATTENDED_APPROVAL_TTL_MS, NAMESPACED_NAME_SHAPES, init_prepare_task = __esm({
451621
+ var PROMPT_HASH_SALT, DEFAULT_RESOURCE_TTL_MS, USAGE_WINDOW_REAP_MARGIN_MS, DEFAULT_UNATTENDED_APPROVAL_TTL_MS, init_prepare_task = __esm({
451514
451622
  "node_modules/@sema-agent/core/dist/core/runner/prepare-task.js"() {
451515
451623
  init_harness();
451516
451624
  init_auto_compaction();
@@ -451540,7 +451648,6 @@ var PROMPT_HASH_SALT, TASK_LIMIT_KEY_DICT, TASK_LIMIT_KEYS, DEFAULT_RESOURCE_TTL
451540
451648
  init_session_rule_policy();
451541
451649
  init_hooks7();
451542
451650
  init_permission_rule_org();
451543
- init_session_reconcile();
451544
451651
  init_cache_break_detector();
451545
451652
  init_request_params();
451546
451653
  init_timeout();
@@ -451559,11 +451666,13 @@ var PROMPT_HASH_SALT, TASK_LIMIT_KEY_DICT, TASK_LIMIT_KEYS, DEFAULT_RESOURCE_TTL
451559
451666
  init_content_origin();
451560
451667
  init_delegation_provenance();
451561
451668
  init_memory4();
451562
- init_locked_config();
451563
451669
  init_compliance();
451564
- init_retention();
451565
451670
  init_memory_admission();
451566
451671
  init_prepare_memory();
451672
+ init_prepare_config_doors();
451673
+ init_prepare_safety_scan();
451674
+ init_prepare_acquire_reconcile();
451675
+ init_prepare_workspace_restore();
451567
451676
  init_default6();
451568
451677
  init_assemble();
451569
451678
  init_tool_catalog();
@@ -451577,7 +451686,6 @@ var PROMPT_HASH_SALT, TASK_LIMIT_KEY_DICT, TASK_LIMIT_KEYS, DEFAULT_RESOURCE_TTL
451577
451686
  init_context_guard();
451578
451687
  init_stub_env();
451579
451688
  init_remote_env3();
451580
- init_with_retry();
451581
451689
  init_teardown_bounded();
451582
451690
  init_background_shell();
451583
451691
  init_task_registry();
@@ -451600,17 +451708,9 @@ var PROMPT_HASH_SALT, TASK_LIMIT_KEY_DICT, TASK_LIMIT_KEYS, DEFAULT_RESOURCE_TTL
451600
451708
  init_usage_window_store();
451601
451709
  init_types26();
451602
451710
  init_checkpoint_store();
451603
- PROMPT_HASH_SALT = randomBytes27(16), TASK_LIMIT_KEY_DICT = {
451604
- maxTokens: !0,
451605
- maxCostUsd: !0,
451606
- maxTurns: !0,
451607
- maxWalltimeMs: !0,
451608
- maxOutputTokens: !0,
451609
- approachNotice: !0,
451610
- budgetStreamCancel: !0,
451611
- degrade: !0,
451612
- brainCallGuardrailMs: !0
451613
- }, TASK_LIMIT_KEYS = Object.keys(TASK_LIMIT_KEY_DICT), DEFAULT_RESOURCE_TTL_MS = 720 * 60 * 60 * 1e3, USAGE_WINDOW_REAP_MARGIN_MS = 3600 * 1e3, DEFAULT_UNATTENDED_APPROVAL_TTL_MS = 720 * 60 * 60 * 1e3, NAMESPACED_NAME_SHAPES = PROTOCOL_TABLE.map((ns) => `${ns.prefix}<peer>__<tool>`).join(", ");
451711
+ init_prepare_config_doors();
451712
+ init_prepare_workspace_restore();
451713
+ PROMPT_HASH_SALT = randomBytes27(16), DEFAULT_RESOURCE_TTL_MS = 720 * 60 * 60 * 1e3, USAGE_WINDOW_REAP_MARGIN_MS = 3600 * 1e3, DEFAULT_UNATTENDED_APPROVAL_TTL_MS = 720 * 60 * 60 * 1e3;
451614
451714
  }
451615
451715
  });
451616
451716
 
@@ -451675,6 +451775,7 @@ var init_tool_output_projection = __esm({
451675
451775
  var SNAPSHOT_TOO_LARGE_TTL_MS, init_runtask = __esm({
451676
451776
  "node_modules/@sema-agent/core/dist/core/runner/runtask.js"() {
451677
451777
  init_read_deny();
451778
+ init_safe_notify();
451678
451779
  init_harness();
451679
451780
  init_llm2();
451680
451781
  init_checkpoint_store();
@@ -462899,7 +463000,7 @@ var WorkerStateUploader, init_WorkerStateUploader = __esm({
462899
463000
  let current5 = payload2, failures = 0;
462900
463001
  for (; !this.closed; ) {
462901
463002
  if (await this.config.send(current5)) return;
462902
- failures++, await sleep3(this.retryDelay(failures)), this.pending && !this.closed && (current5 = coalescePatches(current5, this.pending), this.pending = null);
463003
+ failures++, await sleep2(this.retryDelay(failures)), this.pending && !this.closed && (current5 = coalescePatches(current5, this.pending), this.pending = null);
462903
463004
  }
462904
463005
  }
462905
463006
  retryDelay(failures) {
@@ -463463,7 +463564,7 @@ var DEFAULT_HEARTBEAT_INTERVAL_MS, STREAM_EVENT_FLUSH_INTERVAL_MS, CCRInitError,
463463
463564
  { level: "warn" }
463464
463565
  ), attempt < 10) {
463465
463566
  let delay = Math.min(500 * 2 ** (attempt - 1), 3e4) + Math.random() * 500;
463466
- await sleep3(delay);
463567
+ await sleep2(delay);
463467
463568
  }
463468
463569
  continue;
463469
463570
  }
@@ -463474,7 +463575,7 @@ var DEFAULT_HEARTBEAT_INTERVAL_MS, STREAM_EVENT_FLUSH_INTERVAL_MS, CCRInitError,
463474
463575
  { level: "warn" }
463475
463576
  ), attempt < 10) {
463476
463577
  let delay = Math.min(500 * 2 ** (attempt - 1), 3e4) + Math.random() * 500;
463477
- await sleep3(delay);
463578
+ await sleep2(delay);
463478
463579
  }
463479
463580
  }
463480
463581
  return logForDebugging("CCRClient: GET retries exhausted", { level: "error" }), logForDiagnosticsNoPII("error", "cli_worker_get_retries_exhausted", {
@@ -463855,7 +463956,7 @@ var RECONNECT_BASE_DELAY_MS, RECONNECT_MAX_DELAY_MS, RECONNECT_GIVE_UP_MS, LIVEN
463855
463956
  POST_BASE_DELAY_MS * Math.pow(2, attempt - 1),
463856
463957
  POST_MAX_DELAY_MS
463857
463958
  );
463858
- await sleep3(delayMs);
463959
+ await sleep2(delayMs);
463859
463960
  }
463860
463961
  }
463861
463962
  // -----------------------------------------------------------------------
@@ -464950,7 +465051,7 @@ async function startWorkPollLoop({
464950
465051
  break;
464951
465052
  }
464952
465053
  }
464953
- hbCycles++, await sleep3(
465054
+ hbCycles++, await sleep2(
464954
465055
  hbConfig.non_exclusive_heartbeat_interval_ms,
464955
465056
  cap2.signal
464956
465057
  ), cap2.cleanup();
@@ -464966,14 +465067,14 @@ async function startWorkPollLoop({
464966
465067
  let sleepMs2 = atCapMs > 0 ? atCapMs : pollConfig.non_exclusive_heartbeat_interval_ms;
464967
465068
  if (sleepMs2 > 0) {
464968
465069
  let cap2 = capacitySignal(), sleepStart = Date.now();
464969
- await sleep3(sleepMs2, cap2.signal), cap2.cleanup();
465070
+ await sleep2(sleepMs2, cap2.signal), cap2.cleanup();
464970
465071
  let overrun = Date.now() - sleepStart - sleepMs2;
464971
465072
  overrun > 6e4 && (logForDebugging(
464972
465073
  `[bridge:repl] At-capacity sleep overran by ${Math.round(overrun / 1e3)}s \u2014 process suspension detected, forcing one fast-poll cycle`
464973
465074
  ), suspensionDetected = !0);
464974
465075
  }
464975
465076
  } else
464976
- await sleep3(pollConfig.poll_interval_ms_not_at_capacity, signal);
465077
+ await sleep2(pollConfig.poll_interval_ms_not_at_capacity, signal);
464977
465078
  continue;
464978
465079
  }
464979
465080
  let secret;
@@ -465096,7 +465197,7 @@ async function startWorkPollLoop({
465096
465197
  } catch {
465097
465198
  }
465098
465199
  }
465099
- await sleep3(backoff3, signal);
465200
+ await sleep2(backoff3, signal);
465100
465201
  }
465101
465202
  }
465102
465203
  logForDebugging(
@@ -465639,7 +465740,7 @@ async function withRetry3(fn2, label, cfg) {
465639
465740
  let base = cfg.init_retry_base_delay_ms * 2 ** (attempt - 1), jitter2 = base * cfg.init_retry_jitter_fraction * (2 * Math.random() - 1), delay = Math.min(base + jitter2, cfg.init_retry_max_delay_ms);
465640
465741
  logForDebugging(
465641
465742
  `[remote-bridge] ${label} failed (attempt ${attempt}/${max2}), retrying in ${Math.round(delay)}ms`
465642
- ), await sleep3(delay);
465743
+ ), await sleep2(delay);
465643
465744
  }
465644
465745
  }
465645
465746
  return null;
@@ -465908,7 +466009,7 @@ async function initReplBridge(options) {
465908
466009
  });
465909
466010
  }
465910
466011
  function deriveTitle(raw2) {
465911
- let clean5 = stripDisplayTagsAllowEmpty(raw2), flat = (/^(.*?[.!?])\s/.exec(clean5)?.[1] ?? clean5).replace(/\s+/g, " ").trim();
466012
+ let clean6 = stripDisplayTagsAllowEmpty(raw2), flat = (/^(.*?[.!?])\s/.exec(clean6)?.[1] ?? clean6).replace(/\s+/g, " ").trim();
465912
466013
  if (flat)
465913
466014
  return flat.length > TITLE_MAX_LEN ? flat.slice(0, TITLE_MAX_LEN - 1) + "\u2026" : flat;
465914
466015
  }
@@ -467032,6 +467133,47 @@ var RENDERED_UUID_PREFIX_LEN, init_rewindArm = __esm({
467032
467133
  }
467033
467134
  });
467034
467135
 
467136
+ // build-src/src/sema/sessionBackgroundArm.ts
467137
+ function engineHostsTheTurn(env5 = process.env) {
467138
+ let live = env5.SEMA_LIVE_BASEURL;
467139
+ return typeof live == "string" && live.length > 0;
467140
+ }
467141
+ function remoteHostsTheTurn(readGlobal = getIsRemoteMode, readPosture = hasRemoteConnection) {
467142
+ try {
467143
+ return readGlobal() || readPosture();
467144
+ } catch {
467145
+ return !0;
467146
+ }
467147
+ }
467148
+ function noteEngineCapsForSessionBackground(baseUrl, caps) {
467149
+ try {
467150
+ if (typeof caps != "object" || caps === null) return;
467151
+ let v2 = caps.sessionBackgroundable;
467152
+ sessionBackgroundableByBase.set(baseUrl, v2 === !0 ? "advertised" : v2 === !1 ? "declined" : "unknown");
467153
+ } catch {
467154
+ }
467155
+ }
467156
+ function engineSessionBackgroundableCap(baseUrl) {
467157
+ return sessionBackgroundableByBase.get(baseUrl) ?? "unknown";
467158
+ }
467159
+ function noteRemoteLaneEngagement(engaged) {
467160
+ remoteLaneEngaged = engaged === !0;
467161
+ }
467162
+ function sessionBackgroundingVerdict(env5 = process.env) {
467163
+ let cap2 = engineSessionBackgroundableCap(env5.SEMA_LIVE_BASEURL ?? "");
467164
+ return remoteLaneEngaged ? { available: !1, lane: "remote-lane", sessionBackgroundable: cap2 } : engineHostsTheTurn(env5) ? { available: !1, lane: "engine", sessionBackgroundable: cap2 } : remoteHostsTheTurn() ? { available: !1, lane: "remote", sessionBackgroundable: cap2 } : { available: !0 };
467165
+ }
467166
+ function sessionBackgroundingAvailable(env5 = process.env) {
467167
+ return sessionBackgroundingVerdict(env5).available;
467168
+ }
467169
+ var sessionBackgroundableByBase, remoteLaneEngaged, init_sessionBackgroundArm = __esm({
467170
+ "build-src/src/sema/sessionBackgroundArm.ts"() {
467171
+ init_state();
467172
+ init_remoteWriteSeam();
467173
+ sessionBackgroundableByBase = /* @__PURE__ */ new Map(), remoteLaneEngaged = !1;
467174
+ }
467175
+ });
467176
+
467035
467177
  // build-src/src/sema/footerFleetRows.ts
467036
467178
  function sameShape(a, b3) {
467037
467179
  if (a.viewedRowPresent !== b3.viewedRowPresent || a.taskRowIds.length !== b3.taskRowIds.length || a.workflowIds.length !== b3.workflowIds.length) return !1;
@@ -469650,9 +469792,9 @@ var pyright_default, init_pyright = __esm({
469650
469792
  });
469651
469793
 
469652
469794
  // build-src/src/utils/bash/specs/sleep.ts
469653
- var sleep9, sleep_default, init_sleep3 = __esm({
469795
+ var sleep8, sleep_default, init_sleep3 = __esm({
469654
469796
  "build-src/src/utils/bash/specs/sleep.ts"() {
469655
- sleep9 = {
469797
+ sleep8 = {
469656
469798
  name: "sleep",
469657
469799
  description: "Delay for a specified amount of time",
469658
469800
  args: {
@@ -469660,7 +469802,7 @@ var sleep9, sleep_default, init_sleep3 = __esm({
469660
469802
  description: "Duration to sleep (seconds or with suffix like 5s, 2m, 1h)",
469661
469803
  isOptional: !1
469662
469804
  }
469663
- }, sleep_default = sleep9;
469805
+ }, sleep_default = sleep8;
469664
469806
  }
469665
469807
  });
469666
469808
 
@@ -469878,47 +470020,283 @@ var NUMERIC, ENV_VAR, WRAPPER_COMMANDS, toArray4, init_prefix2 = __esm({
469878
470020
  }
469879
470021
  });
469880
470022
 
469881
- // build-src/src/sema/localAllowRuleWrite.ts
469882
- function parseLocalAllowRule(rule, expectedToolName) {
469883
- if (typeof rule != "string" || rule === "")
469884
- return { ok: !1, error: "rule text is empty" };
469885
- let value;
470023
+ // build-src/src/sema/engineGateSyncAllow.ts
470024
+ function cap() {
470025
+ return budgetCap !== null || (budgetCap = loudEnvInt("SEMA_GATE_SYNC_ALLOW_BUDGET", { min: 0, fallback: DEFAULT_BUDGET })), budgetCap;
470026
+ }
470027
+ function engineGateSyncAllowBudget() {
470028
+ return { used: budgetUsed, cap: cap() };
470029
+ }
470030
+ function readPermissionContext() {
470031
+ try {
470032
+ return getAppStateStoreRef()?.getState?.()?.toolPermissionContext ?? null;
470033
+ } catch {
470034
+ return null;
470035
+ }
470036
+ }
470037
+ function canonicalToolName(name) {
470038
+ let n2 = name.replace(/[\s_-]+/g, "").toLowerCase();
470039
+ return n2 === "bash" ? { canonical: "Bash", family: "bash" } : n2 === "write" || n2 === "filewrite" ? { canonical: "Write", family: "fsWrite", pathKey: "file_path" } : n2 === "edit" || n2 === "fileedit" ? { canonical: "Edit", family: "fsWrite", pathKey: "file_path" } : n2 === "multiedit" ? { canonical: "MultiEdit", family: "fsWrite", pathKey: "file_path" } : n2 === "notebookedit" ? { canonical: "NotebookEdit", family: "fsWrite", pathKey: "notebook_path" } : n2 === "read" || n2 === "fileread" ? { canonical: "Read", family: "fsRead", pathKey: "file_path" } : n2 === "webfetch" ? { canonical: "WebFetch", family: "webFetch" } : n2 === "agent" ? { canonical: "Agent", family: "agent" } : n2 === "powershell" ? { canonical: "PowerShell", family: "powershell" } : { canonical: name, family: "other" };
470040
+ }
470041
+ function permissionsModule() {
470042
+ return init_permissions2(), __toCommonJS(permissions_exports2);
470043
+ }
470044
+ function filesystemModule() {
470045
+ return init_filesystem(), __toCommonJS(filesystem_exports);
470046
+ }
470047
+ function bashPermissionsModule() {
470048
+ return init_bashPermissions(), __toCommonJS(bashPermissions_exports);
470049
+ }
470050
+ function bashCommandsModule() {
470051
+ return init_commands(), __toCommonJS(commands_exports);
470052
+ }
470053
+ function powershellPermissionsModule() {
470054
+ return init_powershellPermissions(), __toCommonJS(powershellPermissions_exports);
470055
+ }
470056
+ function webFetchRuleContent(args) {
470057
+ let url3 = args.url;
470058
+ if (typeof url3 != "string" || url3 === "") return null;
470059
+ try {
470060
+ return `domain:${new URL(url3).hostname}`;
470061
+ } catch {
470062
+ return null;
470063
+ }
470064
+ }
470065
+ function ruleCoord(rule) {
470066
+ let v2 = rule.ruleValue, shape = v2.ruleContent !== void 0 ? `content-rule\xB7len${v2.ruleContent.length}` : "bare";
470067
+ return `${v2.toolName} (${shape}) [${rule.source}]`;
470068
+ }
470069
+ function hasContentDenyRules(ctx, canonical2) {
470070
+ try {
470071
+ return permissionsModule().getDenyRules(ctx).some((r) => r.ruleValue.toolName === canonical2 && r.ruleValue.ruleContent !== void 0);
470072
+ } catch {
470073
+ return !0;
470074
+ }
470075
+ }
470076
+ function familyIdentityPresent(family, pathKey2, args) {
470077
+ if (family === "bash" || family === "powershell")
470078
+ return typeof args.command == "string" && args.command.trim() !== "";
470079
+ if (family === "fsWrite" || family === "fsRead") {
470080
+ let p = args[pathKey2 ?? "file_path"];
470081
+ return typeof p == "string" && p !== "";
470082
+ }
470083
+ return family === "webFetch" ? webFetchRuleContent(args) !== null : family === "agent" ? typeof args.subagent_type == "string" && args.subagent_type !== "" : !1;
470084
+ }
470085
+ function denyVerdict(ctx, req) {
470086
+ let { canonical: canonical2, family, pathKey: pathKey2 } = canonicalToolName(req.toolName), perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 }, toolRule = perms.getDenyRuleForTool(ctx, tool);
470087
+ if (toolRule !== null) return { allow: !1, deny: !0, reason: `deny rule ${ruleCoord(toolRule)}` };
470088
+ if (typeof req.args != "object" || req.args === null) return null;
470089
+ let args = req.args, denyHit = (rule) => rule ? { allow: !1, deny: !0, reason: `deny rule ${ruleCoord(rule)}` } : null;
470090
+ if (family === "bash") {
470091
+ let command8 = args.command;
470092
+ if (typeof command8 == "string" && command8.trim() !== "") {
470093
+ let segments = bashCommandsModule().splitCommand_DEPRECATED(command8);
470094
+ if (segments.length > bashPermissionsModule().MAX_SUBCOMMANDS_FOR_SECURITY_CHECK)
470095
+ throw new Error(
470096
+ `compound command has ${segments.length} subcommands (cap ${bashPermissionsModule().MAX_SUBCOMMANDS_FOR_SECURITY_CHECK}) \u2014 fail-closed to card`
470097
+ );
470098
+ let candidates = segments.length > 1 ? [command8, ...segments] : [command8], candidateEvalFailed = null;
470099
+ for (let cand of candidates)
470100
+ if (!(typeof cand != "string" || cand.trim() === ""))
470101
+ try {
470102
+ let result = bashPermissionsModule().bashToolCheckPermission({ command: cand }, ctx);
470103
+ if (result.behavior === "deny" && result.decisionReason?.type === "rule") {
470104
+ let rule = result.decisionReason.rule;
470105
+ return {
470106
+ allow: !1,
470107
+ deny: !0,
470108
+ reason: `deny rule ${rule ? ruleCoord(rule) : "(bash content rule)"}`
470109
+ };
470110
+ }
470111
+ } catch (e) {
470112
+ candidateEvalFailed = e;
470113
+ }
470114
+ if (candidateEvalFailed !== null) throw candidateEvalFailed;
470115
+ }
470116
+ } else if (family === "powershell") {
470117
+ let command8 = args.command;
470118
+ if (typeof command8 == "string" && command8.trim() !== "") {
470119
+ let fragments = /[`'"]/.test(command8) ? [] : command8.split(/[;|\n\r{}()&]+/).filter((f) => f.trim() !== "");
470120
+ if (fragments.length > bashPermissionsModule().MAX_SUBCOMMANDS_FOR_SECURITY_CHECK)
470121
+ throw new Error(
470122
+ `powershell command has ${fragments.length} fragments (cap ${bashPermissionsModule().MAX_SUBCOMMANDS_FOR_SECURITY_CHECK}) \u2014 fail-closed to card`
470123
+ );
470124
+ let candidates = fragments.length > 1 ? [command8, ...fragments] : [command8], candidateEvalFailed = null;
470125
+ for (let cand of candidates)
470126
+ try {
470127
+ let result = powershellPermissionsModule().powershellToolCheckPermission(
470128
+ { command: cand },
470129
+ ctx
470130
+ );
470131
+ if (result.behavior === "deny" && result.decisionReason?.type === "rule") {
470132
+ let rule = result.decisionReason.rule;
470133
+ return {
470134
+ allow: !1,
470135
+ deny: !0,
470136
+ reason: `deny rule ${rule ? ruleCoord(rule) : "(powershell content rule)"}`
470137
+ };
470138
+ }
470139
+ } catch (e) {
470140
+ candidateEvalFailed = e;
470141
+ }
470142
+ if (candidateEvalFailed !== null) throw candidateEvalFailed;
470143
+ }
470144
+ } else if (family === "fsWrite" || family === "fsRead") {
470145
+ let path28 = args[pathKey2 ?? "file_path"];
470146
+ if (typeof path28 == "string" && path28 !== "") {
470147
+ let toolType = family === "fsWrite" ? "edit" : "read";
470148
+ return denyHit(filesystemModule().matchingRuleForInput(path28, ctx, toolType, "deny"));
470149
+ }
470150
+ } else if (family === "webFetch") {
470151
+ let content = webFetchRuleContent(args);
470152
+ if (content !== null)
470153
+ return denyHit(perms.getRuleByContentsForToolName(ctx, canonical2, "deny").get(content));
470154
+ } else if (family === "agent") {
470155
+ let agentType = args.subagent_type;
470156
+ if (typeof agentType == "string" && agentType !== "")
470157
+ return denyHit(perms.getDenyRuleForAgent(ctx, canonical2, agentType));
470158
+ }
470159
+ return null;
470160
+ }
470161
+ function bashVerdict(ctx, args) {
470162
+ let command8 = args.command;
470163
+ if (typeof command8 != "string" || command8.trim() === "")
470164
+ return { allow: !1, reason: "bash gate carries no command string" };
470165
+ let result = bashPermissionsModule().bashToolCheckPermission(
470166
+ { command: command8 },
470167
+ ctx
470168
+ );
470169
+ return result.behavior !== "allow" ? { allow: !1, reason: `bash rules say ${String(result.behavior)}` } : result.decisionReason?.type !== "rule" ? { allow: !1, reason: `bash allow came from ${String(result.decisionReason?.type)}, not a remembered rule` } : { allow: !0, reason: "remembered Bash allow rule" };
470170
+ }
470171
+ function fsWriteVerdict(ctx, canonical2, pathKey2, args) {
470172
+ let perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 };
470173
+ if (perms.getDenyRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level deny rule" };
470174
+ if (perms.getAskRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level ask rule" };
470175
+ let path28 = args[pathKey2];
470176
+ if (typeof path28 != "string" || path28 === "")
470177
+ return { allow: !1, reason: "fs-write gate carries no path identity (scoped rules unverifiable)" };
470178
+ let fs15 = filesystemModule();
470179
+ return fs15.matchingRuleForInput(path28, ctx, "edit", "deny") !== null ? { allow: !1, reason: "path deny rule" } : fs15.matchingRuleForInput(path28, ctx, "edit", "ask") !== null ? { allow: !1, reason: "path ask rule" } : fs15.matchingRuleForInput(path28, ctx, "edit", "allow") !== null ? { allow: !0, reason: "remembered path allow rule" } : perms.toolAlwaysAllowedRule(ctx, tool) !== null ? { allow: !0, reason: "remembered whole-tool allow rule" } : { allow: !1, reason: "no remembered allow rule for this write" };
470180
+ }
470181
+ function fsReadVerdict(ctx, canonical2, pathKey2, args) {
470182
+ let perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 };
470183
+ if (perms.getDenyRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level deny rule" };
470184
+ if (perms.getAskRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level ask rule" };
470185
+ let path28 = args[pathKey2];
470186
+ if (typeof path28 == "string" && path28 !== "") {
470187
+ let fs15 = filesystemModule();
470188
+ if (fs15.matchingRuleForInput(path28, ctx, "read", "deny") !== null) return { allow: !1, reason: "path deny rule" };
470189
+ if (fs15.matchingRuleForInput(path28, ctx, "read", "ask") !== null) return { allow: !1, reason: "path ask rule" };
470190
+ if (fs15.matchingRuleForInput(path28, ctx, "read", "allow") !== null)
470191
+ return { allow: !0, reason: "remembered read-path allow rule" };
470192
+ }
470193
+ return perms.toolAlwaysAllowedRule(ctx, tool) !== null ? { allow: !0, reason: "remembered whole-tool allow rule" } : { allow: !1, reason: "no remembered allow rule for this read" };
470194
+ }
470195
+ function webFetchVerdict(ctx, canonical2, args) {
470196
+ let perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 };
470197
+ if (perms.getDenyRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level deny rule" };
470198
+ if (perms.getAskRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level ask rule" };
470199
+ let content = webFetchRuleContent(args);
470200
+ if (content !== null) {
470201
+ if (perms.getRuleByContentsForToolName(ctx, canonical2, "deny").get(content) !== void 0)
470202
+ return { allow: !1, reason: "domain deny rule" };
470203
+ if (perms.getRuleByContentsForToolName(ctx, canonical2, "ask").get(content) !== void 0)
470204
+ return { allow: !1, reason: "domain ask rule" };
470205
+ if (perms.getRuleByContentsForToolName(ctx, canonical2, "allow").get(content) !== void 0)
470206
+ return { allow: !0, reason: "remembered WebFetch domain allow rule" };
470207
+ }
470208
+ return perms.toolAlwaysAllowedRule(ctx, tool) !== null ? { allow: !0, reason: "remembered whole-tool allow rule" } : { allow: !1, reason: "no remembered allow rule for this fetch" };
470209
+ }
470210
+ function agentVerdict(ctx, canonical2, args) {
470211
+ let perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 };
470212
+ if (perms.getDenyRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level deny rule" };
470213
+ if (perms.getAskRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level ask rule" };
470214
+ let agentType = args.subagent_type;
470215
+ return typeof agentType == "string" && agentType !== "" && perms.getAskRules(ctx).some((r) => r.ruleValue.toolName === canonical2 && r.ruleValue.ruleContent === agentType) ? { allow: !1, reason: "agent-type ask rule" } : perms.toolAlwaysAllowedRule(ctx, tool) !== null ? { allow: !0, reason: "remembered whole-tool allow rule" } : { allow: !1, reason: "no remembered allow rule for this agent spawn" };
470216
+ }
470217
+ function genericVerdict(ctx, canonical2) {
470218
+ let perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 };
470219
+ return perms.getDenyRuleForTool(ctx, tool) !== null ? { allow: !1, reason: "tool-level deny rule" } : perms.getAskRuleForTool(ctx, tool) !== null ? { allow: !1, reason: "tool-level ask rule" } : perms.toolAlwaysAllowedRule(ctx, tool) !== null ? { allow: !0, reason: "remembered whole-tool allow rule" } : { allow: !1, reason: "no remembered allow rule for this tool" };
470220
+ }
470221
+ function _evaluateWithContextForTest(ctx, req) {
470222
+ if (ctx === null) return { allow: !1, reason: "no toolPermissionContext on this lane" };
469886
470223
  try {
469887
- value = permissionRuleValueFromString(rule);
470224
+ let denied = denyVerdict(ctx, req);
470225
+ if (denied !== null) return denied;
469888
470226
  } catch (e) {
469889
- return { ok: !1, error: `rule text did not parse (${String(e)})` };
470227
+ return logForDebugging(`engineGateSyncAllow: deny-rule evaluation threw for "${req.toolName}": ${String(e)}`), { allow: !1, reason: "deny-rule evaluation failed" };
469890
470228
  }
469891
- if (typeof value.toolName != "string" || value.toolName === "")
469892
- return { ok: !1, error: "rule text carries no tool name" };
469893
- if (value.ruleContent === void 0 || value.ruleContent === "")
469894
- return {
469895
- ok: !1,
469896
- error: "candidate is a whole-tool allow rule (broader than this ask) \u2014 not offered locally"
469897
- };
469898
- if (expectedToolName !== void 0 && value.toolName !== expectedToolName)
469899
- return {
469900
- ok: !1,
469901
- error: `candidate names tool "${value.toolName}" but this ask is for "${expectedToolName}" \u2014 a rule for another tool would never match`
469902
- };
469903
- if (!hasLiteralAnchor(value.ruleContent))
470229
+ if (req.governanceForced === !0)
469904
470230
  return {
469905
- ok: !1,
469906
- error: "candidate is all wildcard (matches every command for this tool) \u2014 equivalent to a whole-tool allow, not offered locally"
470231
+ allow: !1,
470232
+ reason: "governance-forced gate: posture/saved-rule auto-allow suspended (deployment governance requires an explicit decision)"
469907
470233
  };
469908
- if (value.toolName === BASH_TOOL_NAME_FOR_RULES && bashPermissionsModule().bashRuleContentHasDangerousBarePrefix(value.ruleContent))
469909
- return {
469910
- ok: !1,
469911
- error: "candidate is a bare interpreter/wrapper prefix (bash/sh/env/sudo/\u2026) \u2014 persisting it would authorize arbitrary commands, not offered locally"
470234
+ if (ctx.mode === "bypassPermissions") {
470235
+ if (typeof req.args != "object" || req.args === null || Array.isArray(req.args))
470236
+ return { allow: !1, reason: "bypassPermissions posture withheld: gate carries no tool input record (argsOmitted?)" };
470237
+ let { canonical: canonical3, family: family2, pathKey: pathKey3 } = canonicalToolName(req.toolName);
470238
+ return hasContentDenyRules(ctx, canonical3) && !familyIdentityPresent(family2, pathKey3, req.args) ? {
470239
+ allow: !1,
470240
+ reason: "bypassPermissions posture withheld: content-scoped deny rules exist for this tool but the gate carries no verifiable identity (argsOmitted?)"
470241
+ } : {
470242
+ allow: !0,
470243
+ postureAllow: !0,
470244
+ reason: "bypassPermissions posture auto-approves the engine gate (deny rules evaluated first)"
469912
470245
  };
469913
- {
469914
- let setup2 = permissionSetupModule2();
469915
- if (setup2.isDangerousBashPermission(value.toolName, value.ruleContent) || setup2.isDangerousPowerShellPermission(value.toolName, value.ruleContent))
469916
- return {
469917
- ok: !1,
469918
- error: "candidate allow-rule matches a code-execution interpreter/wrapper pattern (python/node/eval/ssh/\u2026) \u2014 persisting it would authorize arbitrary code, not offered locally"
469919
- };
469920
470246
  }
469921
- return { ok: !0, value, canonical: permissionRuleValueToString(value) };
470247
+ if (!SYNC_ALLOW_MODES.has(ctx.mode)) return { allow: !1, reason: `mode ${ctx.mode} never auto-allows` };
470248
+ if (typeof req.args != "object" || req.args === null)
470249
+ return { allow: !1, reason: "gate carries no tool input (argsOmitted?)" };
470250
+ let args = req.args, { canonical: canonical2, family, pathKey: pathKey2 } = canonicalToolName(req.toolName);
470251
+ try {
470252
+ return family === "bash" ? bashVerdict(ctx, args) : family === "powershell" ? genericVerdict(ctx, canonical2) : family === "fsWrite" ? fsWriteVerdict(ctx, canonical2, pathKey2 ?? "file_path", args) : family === "fsRead" ? fsReadVerdict(ctx, canonical2, pathKey2 ?? "file_path", args) : family === "webFetch" ? webFetchVerdict(ctx, canonical2, args) : family === "agent" ? agentVerdict(ctx, canonical2, args) : genericVerdict(ctx, canonical2);
470253
+ } catch (e) {
470254
+ return logForDebugging(`engineGateSyncAllow: rule evaluation threw for "${req.toolName}": ${String(e)}`), { allow: !1, reason: "rule evaluation failed" };
470255
+ }
470256
+ }
470257
+ function evaluateEngineGateSyncAllow(req) {
470258
+ let ctx = readPermissionContext(), verdict = _evaluateWithContextForTest(ctx, req);
470259
+ if (verdict.allow === !1 && verdict.deny === !0)
470260
+ return logForDebugging(
470261
+ `engineGateSyncAllow: gate for "${req.toolName}" AUTO-DENIED by permission rule (${verdict.reason}; mode=${ctx?.mode ?? "none"})`
470262
+ ), verdict;
470263
+ if (!verdict.allow) {
470264
+ let allowRuleCount = -1;
470265
+ try {
470266
+ ctx && (allowRuleCount = permissionsModule().getAllowRules(ctx).length);
470267
+ } catch {
470268
+ }
470269
+ return logForDebugging(
470270
+ `engineGateSyncAllow: no sync allow for "${req.toolName}" (${verdict.reason}; mode=${ctx?.mode ?? "none"}, allowRules=${allowRuleCount})`
470271
+ ), verdict;
470272
+ }
470273
+ return verdict.postureAllow === !0 ? (logForDebugging(
470274
+ `engineGateSyncAllow: gate for "${req.toolName}" AUTO-ALLOWED by bypassPermissions posture (${verdict.reason})`
470275
+ ), verdict) : budgetUsed >= cap() ? (budgetExhaustedLogged || (budgetExhaustedLogged = !0, logForDebugging(
470276
+ `engineGateSyncAllow: programmatic-allow budget exhausted (${budgetUsed}/${cap()}) \u2014 every further gate goes back to the approval card`
470277
+ )), { allow: !1, reason: "programmatic-allow budget exhausted" }) : (budgetUsed++, verdict);
470278
+ }
470279
+ var SYNC_ALLOW_MODES, DEFAULT_BUDGET, budgetUsed, budgetCap, budgetExhaustedLogged, init_engineGateSyncAllow = __esm({
470280
+ "build-src/src/sema/engineGateSyncAllow.ts"() {
470281
+ init_appStateRef();
470282
+ init_envKnobs();
470283
+ init_debug();
470284
+ SYNC_ALLOW_MODES = /* @__PURE__ */ new Set(["default", "acceptEdits", "auto"]), DEFAULT_BUDGET = 100, budgetUsed = 0, budgetCap = null, budgetExhaustedLogged = !1;
470285
+ }
470286
+ });
470287
+
470288
+ // build-src/src/sema/localAllowRuleWrite.ts
470289
+ function localAllowRuleDeps() {
470290
+ return {
470291
+ parseRule: (rule) => permissionRuleValueFromString(rule),
470292
+ formatRule: (value) => permissionRuleValueToString(value),
470293
+ bashRuleContentHasDangerousBarePrefix: (ruleContent) => bashPermissionsModule2().bashRuleContentHasDangerousBarePrefix(ruleContent),
470294
+ isDangerousBashPermission: (toolName2, ruleContent) => permissionSetupModule2().isDangerousBashPermission(toolName2, ruleContent),
470295
+ isDangerousPowerShellPermission: (toolName2, ruleContent) => permissionSetupModule2().isDangerousPowerShellPermission(toolName2, ruleContent)
470296
+ };
470297
+ }
470298
+ function parseLocalAllowRule2(rule, expectedToolName) {
470299
+ return parseLocalAllowRule(rule, expectedToolName, localAllowRuleDeps());
469922
470300
  }
469923
470301
  function localAllowRulesPermittedByPolicy() {
469924
470302
  try {
@@ -469927,25 +470305,13 @@ function localAllowRulesPermittedByPolicy() {
469927
470305
  return !1;
469928
470306
  }
469929
470307
  }
469930
- function hasLiteralAnchor(ruleContent) {
469931
- let out6 = "";
469932
- for (let i = 0; i < ruleContent.length; i++) {
469933
- let ch2 = ruleContent[i];
469934
- if (ch2 === "\\" && i + 1 < ruleContent.length) {
469935
- out6 += ruleContent[i + 1], i++;
469936
- continue;
469937
- }
469938
- ch2 !== "*" && (out6 += ch2);
469939
- }
469940
- return out6.trim() !== "";
469941
- }
469942
470308
  function permissionUpdateModule() {
469943
470309
  return init_PermissionUpdate(), __toCommonJS(PermissionUpdate_exports);
469944
470310
  }
469945
470311
  function permissionsLoaderModule() {
469946
470312
  return init_permissionsLoader(), __toCommonJS(permissionsLoader_exports);
469947
470313
  }
469948
- function bashPermissionsModule() {
470314
+ function bashPermissionsModule2() {
469949
470315
  return init_bashPermissions(), __toCommonJS(bashPermissions_exports);
469950
470316
  }
469951
470317
  function permissionSetupModule2() {
@@ -469954,8 +470320,16 @@ function permissionSetupModule2() {
469954
470320
  function leaderBridgeModule() {
469955
470321
  return init_leaderPermissionBridge(), __toCommonJS(leaderPermissionBridge_exports);
469956
470322
  }
470323
+ function redemptionGate() {
470324
+ try {
470325
+ let { used, cap: cap2 } = engineGateSyncAllowBudget();
470326
+ if (cap2 === 0) return "budget-disabled";
470327
+ if (used >= cap2) return "budget-exhausted";
470328
+ } catch {
470329
+ }
470330
+ }
469957
470331
  function persistLocalAllowRule(rule) {
469958
- let parsed = parseLocalAllowRule(rule);
470332
+ let parsed = parseLocalAllowRule2(rule);
469959
470333
  if (!parsed.ok)
469960
470334
  return logForDebugging(`localAllowRuleWrite: refusing to persist a rule candidate \u2014 ${parsed.error}`), { ok: !1, error: parsed.error };
469961
470335
  let update2 = {
@@ -469985,7 +470359,7 @@ function persistLocalAllowRule(rule) {
469985
470359
  try {
469986
470360
  let setCtx = leaderBridgeModule().getLeaderSetToolPermissionContext(), state4 = getAppStateStoreRef()?.getState?.();
469987
470361
  if (setCtx && state4?.toolPermissionContext)
469988
- return setCtx(mod.applyPermissionUpdate(state4.toolPermissionContext, update2)), { ok: !0, appliedLive: !0 };
470362
+ return setCtx(mod.applyPermissionUpdate(state4.toolPermissionContext, update2)), { ok: !0, appliedLive: !0, ...gatedStamp() };
469989
470363
  logForDebugging(
469990
470364
  "localAllowRuleWrite: rule persisted to local settings, but this lane has no in-memory permission context to update (it will take effect on next start)"
469991
470365
  );
@@ -469994,14 +470368,19 @@ function persistLocalAllowRule(rule) {
469994
470368
  `localAllowRuleWrite: rule persisted, but applying it to the in-memory permission context failed (non-fatal): ${String(e)}`
469995
470369
  );
469996
470370
  }
469997
- return { ok: !0, appliedLive: !1 };
470371
+ return { ok: !0, appliedLive: !1, ...gatedStamp() };
469998
470372
  }
469999
- var BASH_TOOL_NAME_FOR_RULES, init_localAllowRuleWrite = __esm({
470373
+ function gatedStamp() {
470374
+ let gate = redemptionGate();
470375
+ return gate !== void 0 ? { redemptionGated: gate } : {};
470376
+ }
470377
+ var init_localAllowRuleWrite = __esm({
470000
470378
  "build-src/src/sema/localAllowRuleWrite.ts"() {
470001
470379
  init_permissionRuleParser();
470380
+ init_dist();
470002
470381
  init_debug();
470003
470382
  init_appStateRef();
470004
- BASH_TOOL_NAME_FOR_RULES = "Bash";
470383
+ init_engineGateSyncAllow();
470005
470384
  }
470006
470385
  });
470007
470386
 
@@ -470046,7 +470425,7 @@ function tryEngineRulePersistSelection(confirm2, value, onDone) {
470046
470425
  function readLocalRedeemable(confirm2) {
470047
470426
  let expected = typeof confirm2.tool?.name == "string" ? confirm2.tool.name : void 0, out6 = [];
470048
470427
  for (let s of readSuggestions(confirm2, "ruleSuggestionsReadOnly")) {
470049
- let parsed = parseLocalAllowRule(s.rule, expected);
470428
+ let parsed = parseLocalAllowRule2(s.rule, expected);
470050
470429
  parsed.ok && out6.push({ rule: s.rule, canonical: parsed.canonical });
470051
470430
  }
470052
470431
  return out6;
@@ -476557,7 +476936,7 @@ var import_jsx_runtime414, init_chrome_context_window_warning = __esm({
476557
476936
  init_autoCompact();
476558
476937
  init_compactWarningHook();
476559
476938
  init_contextWindowUpgradeCheck();
476560
- import_jsx_runtime414 = __toESM(require_jsx_runtime(), 1);
476939
+ import_jsx_runtime414 = __toESM(require_jsx_runtime());
476561
476940
  }
476562
476941
  });
476563
476942
 
@@ -491796,7 +492175,7 @@ async function reconcileResumePendingApprovals(deps2) {
491796
492175
  debug3("an owned pending row carries no taskId handle \u2014 both reopen arms address by taskId, nothing to reopen"), verdict.skipped.push({ taskId: null, reason: "no-task-handle" });
491797
492176
  continue;
491798
492177
  }
491799
- let kind = gateKindOf(row2), arm = kind === null ? null : ASK_PARK_GATE_KINDS2.includes(kind) ? "ask" : PLAN_REVIEW_GATE_KINDS2.includes(kind) ? "plan" : null;
492178
+ let kind = gateKindOf(row2), arm = kind === null ? null : ASK_PARK_GATE_KINDS.includes(kind) ? "ask" : PLAN_REVIEW_GATE_KINDS.includes(kind) ? "plan" : null;
491800
492179
  if (arm === null) {
491801
492180
  debug3(
491802
492181
  `owned pending row (task ${taskId}) is parked on gate kind '${kind ?? "<absent>"}' \u2014 not in either triage table, refusing to route it into a known reopen arm`
@@ -492064,7 +492443,7 @@ function useLiveQuestionOverlay({
492064
492443
  }
492065
492444
  alive && (setToolUseConfirmQueue(
492066
492445
  (queue3) => queue3.some((e) => e.toolUseID === frame.questionId) ? queue3 : [...queue3, entry]
492067
- ), registerArmedGateFromQuestionId2(frame.questionId));
492446
+ ), registerArmedGateFromQuestionId(frame.questionId));
492068
492447
  }
492069
492448
  })();
492070
492449
  } else frame.type === "question_complete" && (completedBeforeDialog.add(frame.questionId), setToolUseConfirmQueue((queue3) => queue3.filter((e) => e.toolUseID !== frame.questionId)));
@@ -492129,28 +492508,6 @@ var import_compiler_runtime299, import_react298, init_useIDEIntegration = __esm(
492129
492508
  }
492130
492509
  });
492131
492510
 
492132
- // build-src/src/sema/sessionBackgroundArm.ts
492133
- function engineHostsTheTurn(env5 = process.env) {
492134
- let live = env5.SEMA_LIVE_BASEURL;
492135
- return typeof live == "string" && live.length > 0;
492136
- }
492137
- function remoteHostsTheTurn(readGlobal = getIsRemoteMode, readPosture = hasRemoteConnection) {
492138
- try {
492139
- return readGlobal() || readPosture();
492140
- } catch {
492141
- return !0;
492142
- }
492143
- }
492144
- function sessionBackgroundingAvailable(env5 = process.env) {
492145
- return !engineHostsTheTurn(env5) && !remoteHostsTheTurn();
492146
- }
492147
- var init_sessionBackgroundArm = __esm({
492148
- "build-src/src/sema/sessionBackgroundArm.ts"() {
492149
- init_state();
492150
- init_remoteWriteSeam();
492151
- }
492152
- });
492153
-
492154
492511
  // build-src/src/components/SessionBackgroundHint.tsx
492155
492512
  function SessionBackgroundHint(t0) {
492156
492513
  let $3 = (0, import_compiler_runtime300.c)(10), {
@@ -495342,7 +495699,7 @@ function _temp158() {
495342
495699
  }
495343
495700
  var import_compiler_runtime308, import_react313, SETTINGS_ERRORS_NOTIFICATION_KEY, init_useSettingsErrors = __esm({
495344
495701
  "build-src/src/hooks/notifs/useSettingsErrors.tsx"() {
495345
- import_compiler_runtime308 = __toESM(require_compiler_runtime(), 1), import_react313 = __toESM(require_react(), 1);
495702
+ import_compiler_runtime308 = __toESM(require_compiler_runtime()), import_react313 = __toESM(require_react());
495346
495703
  init_notifications2();
495347
495704
  init_state();
495348
495705
  init_allErrors();
@@ -498247,7 +498604,11 @@ function REPL({
498247
498604
  setIsLoading: setIsExternalLoading,
498248
498605
  setToolUseConfirmQueue,
498249
498606
  tools: combinedInitialTools
498250
- }), activeRemote = sshRemote.isRemoteMode ? sshRemote : directConnect.isRemoteMode ? directConnect : remoteSession, [pastedContents, setPastedContents] = (0, import_react332.useState)({}), [submitCount, setSubmitCount] = (0, import_react332.useState)(0), responseLengthRef = (0, import_react332.useRef)(0), apiMetricsRef2 = (0, import_react332.useRef)([]), setResponseLength = (0, import_react332.useCallback)((f) => {
498607
+ }), activeRemote = sshRemote.isRemoteMode ? sshRemote : directConnect.isRemoteMode ? directConnect : remoteSession;
498608
+ (0, import_react332.useLayoutEffect)(() => {
498609
+ noteRemoteLaneEngagement(activeRemote.isRemoteMode);
498610
+ }, [activeRemote.isRemoteMode]);
498611
+ let [pastedContents, setPastedContents] = (0, import_react332.useState)({}), [submitCount, setSubmitCount] = (0, import_react332.useState)(0), responseLengthRef = (0, import_react332.useRef)(0), apiMetricsRef2 = (0, import_react332.useRef)([]), setResponseLength = (0, import_react332.useCallback)((f) => {
498251
498612
  let prev = responseLengthRef.current;
498252
498613
  if (responseLengthRef.current = f(prev), responseLengthRef.current > prev) {
498253
498614
  let entries = apiMetricsRef2.current;
@@ -500120,6 +500481,7 @@ var import_compiler_runtime325, React175, import_react332, import_jsx_runtime477
500120
500481
  init_userMessageSelect();
500121
500482
  init_engineAgentView();
500122
500483
  init_appStateRef();
500484
+ init_sessionBackgroundArm();
500123
500485
  init_chrome_agentprogress();
500124
500486
  init_selectors();
500125
500487
  init_dist();
@@ -509532,265 +509894,41 @@ var NOTICE_KEY, NOTICE_TIMEOUT_MS, init_classifierVerdictWire2 = __esm({
509532
509894
  }
509533
509895
  });
509534
509896
 
509535
- // build-src/src/sema/engineGateSyncAllow.ts
509536
- function cap() {
509537
- return budgetCap !== null || (budgetCap = loudEnvInt("SEMA_GATE_SYNC_ALLOW_BUDGET", { min: 0, fallback: DEFAULT_BUDGET })), budgetCap;
509538
- }
509539
- function readPermissionContext() {
509540
- try {
509541
- return getAppStateStoreRef()?.getState?.()?.toolPermissionContext ?? null;
509542
- } catch {
509543
- return null;
509544
- }
509545
- }
509546
- function canonicalToolName(name) {
509547
- let n2 = name.replace(/[\s_-]+/g, "").toLowerCase();
509548
- return n2 === "bash" ? { canonical: "Bash", family: "bash" } : n2 === "write" || n2 === "filewrite" ? { canonical: "Write", family: "fsWrite", pathKey: "file_path" } : n2 === "edit" || n2 === "fileedit" ? { canonical: "Edit", family: "fsWrite", pathKey: "file_path" } : n2 === "multiedit" ? { canonical: "MultiEdit", family: "fsWrite", pathKey: "file_path" } : n2 === "notebookedit" ? { canonical: "NotebookEdit", family: "fsWrite", pathKey: "notebook_path" } : n2 === "read" || n2 === "fileread" ? { canonical: "Read", family: "fsRead", pathKey: "file_path" } : n2 === "webfetch" ? { canonical: "WebFetch", family: "webFetch" } : n2 === "agent" ? { canonical: "Agent", family: "agent" } : n2 === "powershell" ? { canonical: "PowerShell", family: "powershell" } : { canonical: name, family: "other" };
509549
- }
509550
- function permissionsModule() {
509551
- return init_permissions2(), __toCommonJS(permissions_exports2);
509552
- }
509553
- function filesystemModule() {
509554
- return init_filesystem(), __toCommonJS(filesystem_exports);
509555
- }
509556
- function bashPermissionsModule2() {
509557
- return init_bashPermissions(), __toCommonJS(bashPermissions_exports);
509558
- }
509559
- function bashCommandsModule() {
509560
- return init_commands(), __toCommonJS(commands_exports);
509561
- }
509562
- function powershellPermissionsModule() {
509563
- return init_powershellPermissions(), __toCommonJS(powershellPermissions_exports);
509564
- }
509565
- function webFetchRuleContent(args) {
509566
- let url3 = args.url;
509567
- if (typeof url3 != "string" || url3 === "") return null;
509568
- try {
509569
- return `domain:${new URL(url3).hostname}`;
509570
- } catch {
509571
- return null;
509572
- }
509573
- }
509574
- function ruleCoord(rule) {
509575
- let v2 = rule.ruleValue, shape = v2.ruleContent !== void 0 ? `content-rule\xB7len${v2.ruleContent.length}` : "bare";
509576
- return `${v2.toolName} (${shape}) [${rule.source}]`;
509577
- }
509578
- function hasContentDenyRules(ctx, canonical2) {
509579
- try {
509580
- return permissionsModule().getDenyRules(ctx).some((r) => r.ruleValue.toolName === canonical2 && r.ruleValue.ruleContent !== void 0);
509581
- } catch {
509582
- return !0;
509583
- }
509584
- }
509585
- function familyIdentityPresent(family, pathKey2, args) {
509586
- if (family === "bash" || family === "powershell")
509587
- return typeof args.command == "string" && args.command.trim() !== "";
509588
- if (family === "fsWrite" || family === "fsRead") {
509589
- let p = args[pathKey2 ?? "file_path"];
509590
- return typeof p == "string" && p !== "";
509591
- }
509592
- return family === "webFetch" ? webFetchRuleContent(args) !== null : family === "agent" ? typeof args.subagent_type == "string" && args.subagent_type !== "" : !1;
509897
+ // build-src/src/sema/probeCauseNote.ts
509898
+ function readOperands(v2) {
509899
+ if (typeof v2 != "object" || v2 === null) return;
509900
+ let o = v2;
509901
+ if (!(!Array.isArray(o.shown) || o.shown.some((s) => typeof s != "string")) && !(typeof o.total != "number" || !Number.isInteger(o.total) || o.total < 0) && !(o.total < o.shown.length))
509902
+ return { shown: o.shown, total: o.total };
509593
509903
  }
509594
- function denyVerdict(ctx, req) {
509595
- let { canonical: canonical2, family, pathKey: pathKey2 } = canonicalToolName(req.toolName), perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 }, toolRule = perms.getDenyRuleForTool(ctx, tool);
509596
- if (toolRule !== null) return { allow: !1, deny: !0, reason: `deny rule ${ruleCoord(toolRule)}` };
509597
- if (typeof req.args != "object" || req.args === null) return null;
509598
- let args = req.args, denyHit = (rule) => rule ? { allow: !1, deny: !0, reason: `deny rule ${ruleCoord(rule)}` } : null;
509599
- if (family === "bash") {
509600
- let command8 = args.command;
509601
- if (typeof command8 == "string" && command8.trim() !== "") {
509602
- let segments = bashCommandsModule().splitCommand_DEPRECATED(command8);
509603
- if (segments.length > bashPermissionsModule2().MAX_SUBCOMMANDS_FOR_SECURITY_CHECK)
509604
- throw new Error(
509605
- `compound command has ${segments.length} subcommands (cap ${bashPermissionsModule2().MAX_SUBCOMMANDS_FOR_SECURITY_CHECK}) \u2014 fail-closed to card`
509606
- );
509607
- let candidates = segments.length > 1 ? [command8, ...segments] : [command8], candidateEvalFailed = null;
509608
- for (let cand of candidates)
509609
- if (!(typeof cand != "string" || cand.trim() === ""))
509610
- try {
509611
- let result = bashPermissionsModule2().bashToolCheckPermission({ command: cand }, ctx);
509612
- if (result.behavior === "deny" && result.decisionReason?.type === "rule") {
509613
- let rule = result.decisionReason.rule;
509614
- return {
509615
- allow: !1,
509616
- deny: !0,
509617
- reason: `deny rule ${rule ? ruleCoord(rule) : "(bash content rule)"}`
509618
- };
509619
- }
509620
- } catch (e) {
509621
- candidateEvalFailed = e;
509622
- }
509623
- if (candidateEvalFailed !== null) throw candidateEvalFailed;
509624
- }
509625
- } else if (family === "powershell") {
509626
- let command8 = args.command;
509627
- if (typeof command8 == "string" && command8.trim() !== "") {
509628
- let fragments = /[`'"]/.test(command8) ? [] : command8.split(/[;|\n\r{}()&]+/).filter((f) => f.trim() !== "");
509629
- if (fragments.length > bashPermissionsModule2().MAX_SUBCOMMANDS_FOR_SECURITY_CHECK)
509630
- throw new Error(
509631
- `powershell command has ${fragments.length} fragments (cap ${bashPermissionsModule2().MAX_SUBCOMMANDS_FOR_SECURITY_CHECK}) \u2014 fail-closed to card`
509632
- );
509633
- let candidates = fragments.length > 1 ? [command8, ...fragments] : [command8], candidateEvalFailed = null;
509634
- for (let cand of candidates)
509635
- try {
509636
- let result = powershellPermissionsModule().powershellToolCheckPermission(
509637
- { command: cand },
509638
- ctx
509639
- );
509640
- if (result.behavior === "deny" && result.decisionReason?.type === "rule") {
509641
- let rule = result.decisionReason.rule;
509642
- return {
509643
- allow: !1,
509644
- deny: !0,
509645
- reason: `deny rule ${rule ? ruleCoord(rule) : "(powershell content rule)"}`
509646
- };
509647
- }
509648
- } catch (e) {
509649
- candidateEvalFailed = e;
509650
- }
509651
- if (candidateEvalFailed !== null) throw candidateEvalFailed;
509904
+ function readProbeCauseKey(source) {
509905
+ if (typeof source != "object" || source === null) return;
509906
+ let raw2 = source.probeCause;
509907
+ if (typeof raw2 != "object" || raw2 === null) return;
509908
+ let o = raw2;
509909
+ if (typeof o.code != "string" || o.code.length === 0) return;
509910
+ let roots = readOperands(o.roots);
509911
+ if (roots !== void 0) {
509912
+ if (o.further !== void 0) {
509913
+ let further = readOperands(o.further);
509914
+ return further === void 0 ? void 0 : { code: o.code, roots, further };
509652
509915
  }
509653
- } else if (family === "fsWrite" || family === "fsRead") {
509654
- let path28 = args[pathKey2 ?? "file_path"];
509655
- if (typeof path28 == "string" && path28 !== "") {
509656
- let toolType = family === "fsWrite" ? "edit" : "read";
509657
- return denyHit(filesystemModule().matchingRuleForInput(path28, ctx, toolType, "deny"));
509658
- }
509659
- } else if (family === "webFetch") {
509660
- let content = webFetchRuleContent(args);
509661
- if (content !== null)
509662
- return denyHit(perms.getRuleByContentsForToolName(ctx, canonical2, "deny").get(content));
509663
- } else if (family === "agent") {
509664
- let agentType = args.subagent_type;
509665
- if (typeof agentType == "string" && agentType !== "")
509666
- return denyHit(perms.getDenyRuleForAgent(ctx, canonical2, agentType));
509916
+ return { code: o.code, roots };
509667
509917
  }
509668
- return null;
509669
509918
  }
509670
- function bashVerdict(ctx, args) {
509671
- let command8 = args.command;
509672
- if (typeof command8 != "string" || command8.trim() === "")
509673
- return { allow: !1, reason: "bash gate carries no command string" };
509674
- let result = bashPermissionsModule2().bashToolCheckPermission(
509675
- { command: command8 },
509676
- ctx
509677
- );
509678
- return result.behavior !== "allow" ? { allow: !1, reason: `bash rules say ${String(result.behavior)}` } : result.decisionReason?.type !== "rule" ? { allow: !1, reason: `bash allow came from ${String(result.decisionReason?.type)}, not a remembered rule` } : { allow: !0, reason: "remembered Bash allow rule" };
509919
+ function clean5(v2, max2) {
509920
+ return v2.replace(/[\x00-\x1f\x7f]/g, ".").slice(0, max2);
509679
509921
  }
509680
- function fsWriteVerdict(ctx, canonical2, pathKey2, args) {
509681
- let perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 };
509682
- if (perms.getDenyRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level deny rule" };
509683
- if (perms.getAskRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level ask rule" };
509684
- let path28 = args[pathKey2];
509685
- if (typeof path28 != "string" || path28 === "")
509686
- return { allow: !1, reason: "fs-write gate carries no path identity (scoped rules unverifiable)" };
509687
- let fs15 = filesystemModule();
509688
- return fs15.matchingRuleForInput(path28, ctx, "edit", "deny") !== null ? { allow: !1, reason: "path deny rule" } : fs15.matchingRuleForInput(path28, ctx, "edit", "ask") !== null ? { allow: !1, reason: "path ask rule" } : fs15.matchingRuleForInput(path28, ctx, "edit", "allow") !== null ? { allow: !0, reason: "remembered path allow rule" } : perms.toolAlwaysAllowedRule(ctx, tool) !== null ? { allow: !0, reason: "remembered whole-tool allow rule" } : { allow: !1, reason: "no remembered allow rule for this write" };
509689
- }
509690
- function fsReadVerdict(ctx, canonical2, pathKey2, args) {
509691
- let perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 };
509692
- if (perms.getDenyRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level deny rule" };
509693
- if (perms.getAskRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level ask rule" };
509694
- let path28 = args[pathKey2];
509695
- if (typeof path28 == "string" && path28 !== "") {
509696
- let fs15 = filesystemModule();
509697
- if (fs15.matchingRuleForInput(path28, ctx, "read", "deny") !== null) return { allow: !1, reason: "path deny rule" };
509698
- if (fs15.matchingRuleForInput(path28, ctx, "read", "ask") !== null) return { allow: !1, reason: "path ask rule" };
509699
- if (fs15.matchingRuleForInput(path28, ctx, "read", "allow") !== null)
509700
- return { allow: !0, reason: "remembered read-path allow rule" };
509701
- }
509702
- return perms.toolAlwaysAllowedRule(ctx, tool) !== null ? { allow: !0, reason: "remembered whole-tool allow rule" } : { allow: !1, reason: "no remembered allow rule for this read" };
509703
- }
509704
- function webFetchVerdict(ctx, canonical2, args) {
509705
- let perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 };
509706
- if (perms.getDenyRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level deny rule" };
509707
- if (perms.getAskRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level ask rule" };
509708
- let content = webFetchRuleContent(args);
509709
- if (content !== null) {
509710
- if (perms.getRuleByContentsForToolName(ctx, canonical2, "deny").get(content) !== void 0)
509711
- return { allow: !1, reason: "domain deny rule" };
509712
- if (perms.getRuleByContentsForToolName(ctx, canonical2, "ask").get(content) !== void 0)
509713
- return { allow: !1, reason: "domain ask rule" };
509714
- if (perms.getRuleByContentsForToolName(ctx, canonical2, "allow").get(content) !== void 0)
509715
- return { allow: !0, reason: "remembered WebFetch domain allow rule" };
509716
- }
509717
- return perms.toolAlwaysAllowedRule(ctx, tool) !== null ? { allow: !0, reason: "remembered whole-tool allow rule" } : { allow: !1, reason: "no remembered allow rule for this fetch" };
509718
- }
509719
- function agentVerdict(ctx, canonical2, args) {
509720
- let perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 };
509721
- if (perms.getDenyRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level deny rule" };
509722
- if (perms.getAskRuleForTool(ctx, tool) !== null) return { allow: !1, reason: "tool-level ask rule" };
509723
- let agentType = args.subagent_type;
509724
- return typeof agentType == "string" && agentType !== "" && perms.getAskRules(ctx).some((r) => r.ruleValue.toolName === canonical2 && r.ruleValue.ruleContent === agentType) ? { allow: !1, reason: "agent-type ask rule" } : perms.toolAlwaysAllowedRule(ctx, tool) !== null ? { allow: !0, reason: "remembered whole-tool allow rule" } : { allow: !1, reason: "no remembered allow rule for this agent spawn" };
509725
- }
509726
- function genericVerdict(ctx, canonical2) {
509727
- let perms = permissionsModule(), tool = { name: canonical2, mcpInfo: void 0 };
509728
- return perms.getDenyRuleForTool(ctx, tool) !== null ? { allow: !1, reason: "tool-level deny rule" } : perms.getAskRuleForTool(ctx, tool) !== null ? { allow: !1, reason: "tool-level ask rule" } : perms.toolAlwaysAllowedRule(ctx, tool) !== null ? { allow: !0, reason: "remembered whole-tool allow rule" } : { allow: !1, reason: "no remembered allow rule for this tool" };
509729
- }
509730
- function _evaluateWithContextForTest(ctx, req) {
509731
- if (ctx === null) return { allow: !1, reason: "no toolPermissionContext on this lane" };
509732
- try {
509733
- let denied = denyVerdict(ctx, req);
509734
- if (denied !== null) return denied;
509735
- } catch (e) {
509736
- return logForDebugging(`engineGateSyncAllow: deny-rule evaluation threw for "${req.toolName}": ${String(e)}`), { allow: !1, reason: "deny-rule evaluation failed" };
509737
- }
509738
- if (req.governanceForced === !0)
509739
- return {
509740
- allow: !1,
509741
- reason: "governance-forced gate: posture/saved-rule auto-allow suspended (deployment governance requires an explicit decision)"
509742
- };
509743
- if (ctx.mode === "bypassPermissions") {
509744
- if (typeof req.args != "object" || req.args === null || Array.isArray(req.args))
509745
- return { allow: !1, reason: "bypassPermissions posture withheld: gate carries no tool input record (argsOmitted?)" };
509746
- let { canonical: canonical3, family: family2, pathKey: pathKey3 } = canonicalToolName(req.toolName);
509747
- return hasContentDenyRules(ctx, canonical3) && !familyIdentityPresent(family2, pathKey3, req.args) ? {
509748
- allow: !1,
509749
- reason: "bypassPermissions posture withheld: content-scoped deny rules exist for this tool but the gate carries no verifiable identity (argsOmitted?)"
509750
- } : {
509751
- allow: !0,
509752
- postureAllow: !0,
509753
- reason: "bypassPermissions posture auto-approves the engine gate (deny rules evaluated first)"
509754
- };
509755
- }
509756
- if (!SYNC_ALLOW_MODES.has(ctx.mode)) return { allow: !1, reason: `mode ${ctx.mode} never auto-allows` };
509757
- if (typeof req.args != "object" || req.args === null)
509758
- return { allow: !1, reason: "gate carries no tool input (argsOmitted?)" };
509759
- let args = req.args, { canonical: canonical2, family, pathKey: pathKey2 } = canonicalToolName(req.toolName);
509760
- try {
509761
- return family === "bash" ? bashVerdict(ctx, args) : family === "powershell" ? genericVerdict(ctx, canonical2) : family === "fsWrite" ? fsWriteVerdict(ctx, canonical2, pathKey2 ?? "file_path", args) : family === "fsRead" ? fsReadVerdict(ctx, canonical2, pathKey2 ?? "file_path", args) : family === "webFetch" ? webFetchVerdict(ctx, canonical2, args) : family === "agent" ? agentVerdict(ctx, canonical2, args) : genericVerdict(ctx, canonical2);
509762
- } catch (e) {
509763
- return logForDebugging(`engineGateSyncAllow: rule evaluation threw for "${req.toolName}": ${String(e)}`), { allow: !1, reason: "rule evaluation failed" };
509764
- }
509922
+ function operandsText(f) {
509923
+ let shown = f.shown.slice(0, 8).map((p) => clean5(p, 120)), more = Math.max(0, f.total - shown.length);
509924
+ return shown.length === 0 ? `${String(f.total)} total` : more > 0 ? `${shown.join(", ")} (+${String(more)} more)` : shown.join(", ");
509765
509925
  }
509766
- function evaluateEngineGateSyncAllow(req) {
509767
- let ctx = readPermissionContext(), verdict = _evaluateWithContextForTest(ctx, req);
509768
- if (verdict.allow === !1 && verdict.deny === !0)
509769
- return logForDebugging(
509770
- `engineGateSyncAllow: gate for "${req.toolName}" AUTO-DENIED by permission rule (${verdict.reason}; mode=${ctx?.mode ?? "none"})`
509771
- ), verdict;
509772
- if (!verdict.allow) {
509773
- let allowRuleCount = -1;
509774
- try {
509775
- ctx && (allowRuleCount = permissionsModule().getAllowRules(ctx).length);
509776
- } catch {
509777
- }
509778
- return logForDebugging(
509779
- `engineGateSyncAllow: no sync allow for "${req.toolName}" (${verdict.reason}; mode=${ctx?.mode ?? "none"}, allowRules=${allowRuleCount})`
509780
- ), verdict;
509781
- }
509782
- return verdict.postureAllow === !0 ? (logForDebugging(
509783
- `engineGateSyncAllow: gate for "${req.toolName}" AUTO-ALLOWED by bypassPermissions posture (${verdict.reason})`
509784
- ), verdict) : budgetUsed >= cap() ? (budgetExhaustedLogged || (budgetExhaustedLogged = !0, logForDebugging(
509785
- `engineGateSyncAllow: programmatic-allow budget exhausted (${budgetUsed}/${cap()}) \u2014 every further gate goes back to the approval card`
509786
- )), { allow: !1, reason: "programmatic-allow budget exhausted" }) : (budgetUsed++, verdict);
509926
+ function probeCauseNoteText(pc) {
509927
+ let parts = [`reversibility probe: ${clean5(pc.code, 200)} \u2014 roots: ${operandsText(pc.roots)}`];
509928
+ return pc.further !== void 0 && parts.push(`further: ${operandsText(pc.further)}`), parts.join(" \u2014 ");
509787
509929
  }
509788
- var SYNC_ALLOW_MODES, DEFAULT_BUDGET, budgetUsed, budgetCap, budgetExhaustedLogged, init_engineGateSyncAllow = __esm({
509789
- "build-src/src/sema/engineGateSyncAllow.ts"() {
509790
- init_appStateRef();
509791
- init_envKnobs();
509792
- init_debug();
509793
- SYNC_ALLOW_MODES = /* @__PURE__ */ new Set(["default", "acceptEdits", "auto"]), DEFAULT_BUDGET = 100, budgetUsed = 0, budgetCap = null, budgetExhaustedLogged = !1;
509930
+ var init_probeCauseNote = __esm({
509931
+ "build-src/src/sema/probeCauseNote.ts"() {
509794
509932
  }
509795
509933
  });
509796
509934
 
@@ -509838,6 +509976,14 @@ function stubToolUseContext() {
509838
509976
  options: {}
509839
509977
  };
509840
509978
  }
509979
+ function composeCardWireNote(req) {
509980
+ let probeCause = readProbeCauseKey(req), parts = [
509981
+ ...req.governanceForced === !0 ? ["Required by deployment governance \u2014 permission-mode overrides do not apply"] : [],
509982
+ ...req.wireNote !== void 0 ? [req.wireNote] : [],
509983
+ ...probeCause !== void 0 ? [probeCauseNoteText(probeCause)] : []
509984
+ ];
509985
+ return parts.length > 0 ? parts.join(" \xB7 ") : void 0;
509986
+ }
509841
509987
  function shellApprovalCardPort(req) {
509842
509988
  let setQueue = getLeaderToolUseConfirmQueue();
509843
509989
  if (!setQueue) {
@@ -509933,12 +510079,11 @@ function shellApprovalCardPort(req) {
509933
510079
  // (AUTONOMY/commandPolicy/MANUAL_MODE_SHELL_GATE/SENSITIVE_WRITE_PATTERNS),权限模式
509934
510080
  // 表态掀不掉——呈现走 wireNote 超集车道(dim 行,与 argsOmitted 提示同位,可叠加)。
509935
510081
  // 🔴 缺席 ≠ false:键只在为真时在场;缺席帧绝不合成治理句(缺席=无治理来源证据)。
509936
- ...req.governanceForced === !0 || req.wireNote !== void 0 ? {
509937
- wireNote: [
509938
- ...req.governanceForced === !0 ? ["Required by deployment governance \u2014 permission-mode overrides do not apply"] : [],
509939
- ...req.wireNote !== void 0 ? [req.wireNote] : []
509940
- ].join(" \xB7 ")
509941
- } : {},
510082
+ // #280 件4:probeCause 探针因由句并入同车道(组装单源 composeCardWireNote,见其顶注)。
510083
+ ...(() => {
510084
+ let wireNote = composeCardWireNote(req);
510085
+ return wireNote !== void 0 ? { wireNote } : {};
510086
+ })(),
509942
510087
  permissionPromptStartTimeMs: Date.now(),
509943
510088
  onUserInteraction() {
509944
510089
  },
@@ -509973,7 +510118,7 @@ function shellApprovalCardPort(req) {
509973
510118
  }
509974
510119
  };
509975
510120
  try {
509976
- setQueue((queue3) => [...queue3, confirm2]), registerArmedGate2(callKey);
510121
+ setQueue((queue3) => [...queue3, confirm2]), registerArmedGate(callKey);
509977
510122
  } catch (e) {
509978
510123
  settle2({ kind: "failed", reason: `enqueue ToolUseConfirm failed: ${String(e)}` });
509979
510124
  }
@@ -509991,7 +510136,8 @@ var asWireTool, forcedToolLoadFailureForTest, forcedToolNilExportForTest, loadFi
509991
510136
  init_debug();
509992
510137
  init_engineGateSyncAllow();
509993
510138
  init_localAllowRuleWrite();
509994
- init_persistedRulesWire();
510139
+ init_probeCauseNote();
510140
+ init_persistedRulesWire2();
509995
510141
  init_armedGateRegistry2();
509996
510142
  init_dist();
509997
510143
  asWireTool = (t2) => t2, forcedToolLoadFailureForTest = null, forcedToolNilExportForTest = null, loadFileWrite = () => (init_FileWriteTool(), __toCommonJS(FileWriteTool_exports)).FileWriteTool, loadFileEdit = () => (init_FileEditTool(), __toCommonJS(FileEditTool_exports)).FileEditTool, loadNotebookEdit = () => (init_NotebookEditTool(), __toCommonJS(NotebookEditTool_exports)).NotebookEditTool, loadBash = () => (init_BashTool(), __toCommonJS(BashTool_exports)).BashTool, loadEngineWorkflow = () => (init_EngineWorkflowTool(), __toCommonJS(EngineWorkflowTool_exports)).EngineWorkflowTool, KNOWN_TOOL_LOADERS = {
@@ -510124,6 +510270,8 @@ function askCallKey(askId) {
510124
510270
  function approvalCardRequestFrom(frame, opts) {
510125
510271
  let card = frame.card, notes = [riskNoteFor(card.risk)];
510126
510272
  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");
510273
+ let probeCause = readProbeCauseKey(card);
510274
+ probeCause !== void 0 && notes.push(probeCauseNoteText(probeCause));
510127
510275
  let args = card.argsOmitted === !0 || typeof card.args != "object" || card.args === null ? {} : card.args;
510128
510276
  return {
510129
510277
  toolName: card.toolName,
@@ -510410,6 +510558,7 @@ var STREAM_APPROVAL_CAP, ASK_DECISION_DISABLED_CODE, IDEMPOTENCY_KEY_MAX, PARKIN
510410
510558
  init_dist();
510411
510559
  init_debug();
510412
510560
  init_appStateRef();
510561
+ init_probeCauseNote();
510413
510562
  init_wireNoticePort();
510414
510563
  STREAM_APPROVAL_CAP = "streamApproval", ASK_DECISION_DISABLED_CODE = "feature.approval_ask_disabled", IDEMPOTENCY_KEY_MAX = 255, PARKING_POLL_MAX = 2, PARKING_POLL_DELAY_MS = 400, CAPS_SETTLE_BUDGET_MS = 1500, LEGACY_SETTLE_GRACE_MS = 750, MAX_DECISION_NOTE_CHARS = 2048, TEARDOWN_BUDGET_MS = 1e3;
510415
510564
  TYPED_NAME_TO_KIND = /* @__PURE__ */ new Map([
@@ -510848,7 +510997,7 @@ async function* withDurableSuggestionsTail(events3, taskId, runsGet, opts) {
510848
510997
  for await (let ev of events3)
510849
510998
  ev?.type === "suggestions" && (settledOnStream = !0), yield ev;
510850
510999
  if (settledOnStream || !promptSuggestionsOptIn() || opts?.signal?.aborted) return;
510851
- let sleep10 = opts?.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms))), now2 = opts?.now ?? Date.now, t0 = now2();
511000
+ let sleep9 = opts?.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms))), now2 = opts?.now ?? Date.now, t0 = now2();
510852
511001
  for (let attempt = 1; attempt <= SUGGESTIONS_TAIL_MAX_ATTEMPTS; attempt++) {
510853
511002
  let rec;
510854
511003
  try {
@@ -510865,7 +511014,7 @@ async function* withDurableSuggestionsTail(events3, taskId, runsGet, opts) {
510865
511014
  }
510866
511015
  if (attempt >= SUGGESTIONS_TAIL_MAX_ATTEMPTS) return;
510867
511016
  let wait = Math.min(SUGGESTIONS_TAIL_RETRY_MS * attempt, SUGGESTIONS_TAIL_RETRY_CAP_MS), left = SUGGESTIONS_TAIL_BUDGET_MS - (now2() - t0);
510868
- if (left <= 0 || opts?.signal?.aborted || (await sleep10(Math.min(wait, left)), opts?.signal?.aborted)) return;
511017
+ if (left <= 0 || opts?.signal?.aborted || (await sleep9(Math.min(wait, left)), opts?.signal?.aborted)) return;
510869
511018
  }
510870
511019
  }
510871
511020
  async function* normalizeToolNames(events3) {
@@ -510906,53 +511055,53 @@ function promptSuggestionsOptIn() {
510906
511055
  return v2 === "1" || v2 === "true" || v2 === "yes" || v2 === "on";
510907
511056
  }
510908
511057
  function toLiveRequest(req, capturedSessionId) {
510909
- let out6 = { ...req };
510910
- if (out6.cwd == null && (out6.cwd = process.cwd()), out6.additionalDirectories === void 0)
510911
- try {
510912
- let dirs = getAppStateStoreRef()?.getState().toolPermissionContext?.additionalWorkingDirectories;
510913
- if (dirs && dirs.size > 0)
510914
- out6.additionalDirectories = [...dirs.keys()];
510915
- else if (dirs === void 0) {
510916
- let boot = getBootAdditionalDirectories();
510917
- boot && boot.length > 0 && (out6.additionalDirectories = [...boot]);
510918
- }
510919
- } catch {
510920
- }
510921
- if (out6.additionalReadDirectories === void 0) {
510922
- let configHome;
510923
- try {
510924
- configHome = getClaudeConfigHomeDir();
510925
- } catch {
510926
- configHome = void 0;
511058
+ let additionalDirectories;
511059
+ try {
511060
+ let dirs = getAppStateStoreRef()?.getState().toolPermissionContext?.additionalWorkingDirectories;
511061
+ if (dirs && dirs.size > 0)
511062
+ additionalDirectories = [...dirs.keys()];
511063
+ else if (dirs === void 0) {
511064
+ let boot = getBootAdditionalDirectories();
511065
+ boot && boot.length > 0 && (additionalDirectories = [...boot]);
510927
511066
  }
510928
- let roots = hostDefaultReadRoots({
510929
- configHome,
510930
- tmpdir: osTmpdir2(),
510931
- tmpdirEnv: process.env.TMPDIR,
510932
- homeDir: safeHomedir(),
510933
- cwd: out6.cwd ?? process.cwd(),
510934
- // 符号链接解析器:词法闸挡不住 `TMPDIR=/looks/fine`→`/`(复审轮二 [high])。
510935
- // 只用于**判决**,上 wire 的仍是词法值 —— canonicalize 是 core 的活,壳不写第二份。
510936
- realpath: realpathSyncNative
510937
- });
510938
- roots.length > 0 && (out6.additionalReadDirectories = roots);
510939
- }
510940
- if (out6.forwardSubagentEvents === void 0 && (out6.forwardSubagentEvents = !0), out6.retainSubagentSessions === void 0 && (out6.retainSubagentSessions = !0), out6.agents === void 0) {
510941
- let agentsField = taskAgentsField();
510942
- agentsField.agents && (out6.agents = agentsField.agents);
510943
- }
510944
- if (typeof out6.scenario == "string" && SEMA_MOCK_SCENARIO_KEYS.has(out6.scenario) && delete out6.scenario, appendSystemPromptCapable(liveCapsBaseUrl)) {
510945
- let existing = out6.appendSystemPrompt;
510946
- out6.appendSystemPrompt = withSelfKnowledgeAppend(existing);
510947
- } else {
510948
- let settings2 = out6.settings ?? {};
510949
- out6.settings = { ...settings2, outputStyle: withSelfKnowledgeOutputStyle(settings2.outputStyle) };
510950
- }
510951
- if (out6.suggestNextPrompts === void 0 && out6.verify === void 0 && out6.cascade === void 0 && promptSuggestionsOptIn() && (out6.suggestNextPrompts = !0), out6.compactionModel === void 0) {
510952
- let cheap = process.env.MODEL_CHEAP_ID?.trim();
510953
- cheap && engineCapTrue(liveCapsBaseUrl, "compactionModel") && getLiveModelCatalog()?.models.some((m2) => m2.name === cheap || m2.id === cheap) === !0 && (out6.compactionModel = cheap);
511067
+ } catch {
510954
511068
  }
510955
- return capturedSessionId ? out6.sessionId = capturedSessionId : out6.sessionId === mockClientIds.sessionId && delete out6.sessionId, out6;
511069
+ let configHome;
511070
+ try {
511071
+ configHome = getClaudeConfigHomeDir();
511072
+ } catch {
511073
+ configHome = void 0;
511074
+ }
511075
+ let readRoots = hostDefaultReadRoots({
511076
+ configHome,
511077
+ tmpdir: osTmpdir2(),
511078
+ tmpdirEnv: process.env.TMPDIR,
511079
+ homeDir: safeHomedir(),
511080
+ cwd: req.cwd ?? process.cwd(),
511081
+ // 符号链接解析器只用于**判决**,上 wire 的仍是词法值(canonicalize 是 core 的活)。
511082
+ realpath: realpathSyncNative
511083
+ }), compactionModel, cheap = process.env.MODEL_CHEAP_ID?.trim();
511084
+ cheap && engineCapTrue(liveCapsBaseUrl, "compactionModel") && getLiveModelCatalog()?.models.some((m2) => m2.name === cheap || m2.id === cheap) === !0 && (compactionModel = cheap);
511085
+ let agentsField = taskAgentsField(), existingAppend = req.appendSystemPrompt, existingOutputStyle = (req.settings ?? {}).outputStyle, reqLike = { ...req };
511086
+ return applyLiveRequestDefaults(reqLike, {
511087
+ cwd: process.cwd(),
511088
+ ...additionalDirectories !== void 0 ? { additionalDirectories } : {},
511089
+ additionalReadDirectories: readRoots,
511090
+ ...agentsField.agents ? { agents: agentsField.agents } : {},
511091
+ mockScenarioKeys: SEMA_MOCK_SCENARIO_KEYS,
511092
+ appendSystemPromptCapable: appendSystemPromptCapable(liveCapsBaseUrl),
511093
+ selfKnowledge: {
511094
+ forAppend: withSelfKnowledgeAppend(existingAppend),
511095
+ forOutputStyle: withSelfKnowledgeOutputStyle(existingOutputStyle)
511096
+ },
511097
+ suggestNextPrompts: promptSuggestionsOptIn(),
511098
+ ...compactionModel !== void 0 ? { compactionModel } : {},
511099
+ ...capturedSessionId !== void 0 ? { capturedSessionId } : {},
511100
+ mockSessionIdConstant: mockClientIds.sessionId
511101
+ // 出参定向转换(type-hygiene 基线 7→8 随批抬,理由注释即此行):包按结构操作返回
511102
+ // TaskRequestLike(Record 宽形),真 wire 形仍是 TaskRequest —— seamQuery.toTaskRequest
511103
+ // 出口的同款收窄惯例(同一转换形)。
511104
+ });
510956
511105
  }
510957
511106
  async function* captureSessionId(events3, onSession, wasEarlyAcquired, getEarlyTaskId, isCurrentEpoch) {
510958
511107
  for await (let ev of events3) {
@@ -510995,7 +511144,7 @@ function createLiveConversationClient(config4) {
510995
511144
  () => client3.capabilities()
510996
511145
  ), kickEngineCapsProbe(
510997
511146
  config4.baseUrl,
510998
- () => client3.capabilities().then((caps) => (noteEngineCapsForMcpGate(config4.baseUrl, caps), caps))
511147
+ () => client3.capabilities().then((caps) => (noteEngineCapsForMcpGate(config4.baseUrl, caps), noteEngineCapsForSessionBackground(config4.baseUrl, caps), caps))
510999
511148
  ), prepareTaskAgentsWire({
511000
511149
  baseUrl: config4.baseUrl,
511001
511150
  // loopback-unauthed = 不传 token(agentsWireCaps 对缺省 token 自然零 Authorization 头)。
@@ -511274,7 +511423,7 @@ function createLiveConversationClient(config4) {
511274
511423
  }
511275
511424
  var ENGINE_TO_CC_TOOL, SUGGESTIONS_TAIL_MAX_ATTEMPTS, SUGGESTIONS_TAIL_RETRY_MS, SUGGESTIONS_TAIL_RETRY_CAP_MS, SUGGESTIONS_TAIL_BUDGET_MS, SEMA_MOCK_SCENARIO_KEYS, liveCapsBaseUrl, liveClient_default, init_liveClient = __esm({
511276
511425
  "build-src/src/sema/liveClient.ts"() {
511277
- init_persistedRulesWire();
511426
+ init_persistedRulesWire2();
511278
511427
  init_rewindAnchorStore();
511279
511428
  init_engineToolDetach();
511280
511429
  init_dist();
@@ -511296,11 +511445,13 @@ var ENGINE_TO_CC_TOOL, SUGGESTIONS_TAIL_MAX_ATTEMPTS, SUGGESTIONS_TAIL_RETRY_MS,
511296
511445
  init_dist();
511297
511446
  init_agentsWire();
511298
511447
  init_mcpInjectionGate();
511448
+ init_sessionBackgroundArm();
511299
511449
  init_detachWire2();
511300
511450
  init_dist();
511301
511451
  init_selfKnowledge();
511302
511452
  init_dist();
511303
511453
  init_dist();
511454
+ init_dist();
511304
511455
  init_mockClient();
511305
511456
  init_seamQuery();
511306
511457
  ENGINE_TO_CC_TOOL = {
@@ -511987,12 +512138,12 @@ async function* ask(params) {
511987
512138
  }
511988
512139
  if (!(t2 === "retry_status" || t2 === "turn_usage" || t2 === "task_progress" || t2 === "steering_injected")) {
511989
512140
  if (t2 === "human_input") {
511990
- let hi = msg, clean5 = (v2) => (
512141
+ let hi = msg, clean6 = (v2) => (
511991
512142
  // eslint-disable-next-line no-control-regex
511992
512143
  String(v2 ?? "").replace(/[\x00-\x1f\x7f]/g, ".").slice(0, 120)
511993
- ), who = hi.actor?.id ? `${clean5(hi.actor.id)}${hi.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
512144
+ ), who = hi.actor?.id ? `${clean6(hi.actor.id)}${hi.actor.hostAsserted === !0 ? "" : " (unverified)"}` : "unattributed";
511994
512145
  logForDebugging(
511995
- `[sema][print] human_input ledger frame (audit): carrier=${clean5(hi.carrier)} eventId=${clean5(hi.eventId)} by=${who}`
512146
+ `[sema][print] human_input ledger frame (audit): carrier=${clean6(hi.carrier)} eventId=${clean6(hi.eventId)} by=${who}`
511996
512147
  );
511997
512148
  continue;
511998
512149
  }
@@ -513236,7 +513387,7 @@ function runHeadlessStreaming(structuredIO, mcpClients, commands, tools, initial
513236
513387
  10
513237
513388
  );
513238
513389
  if (timeoutMs > 0) {
513239
- let timeout3 = sleep3(timeoutMs).then(() => "timeout");
513390
+ let timeout3 = sleep2(timeoutMs).then(() => "timeout");
513240
513391
  await Promise.race([pluginInstallPromise, timeout3]) === "timeout" && (logError(
513241
513392
  new Error(
513242
513393
  `SEMA_CODE_SYNC_PLUGIN_INSTALL: plugin installation timed out after ${timeoutMs}ms`
@@ -513482,7 +513633,7 @@ function runHeadlessStreaming(structuredIO, mcpClients, commands, tools, initial
513482
513633
  let state4 = getAppState(), hasRunningBg = getRunningTasks(state4).some(
513483
513634
  (t2) => isBackgroundTask(t2) && t2.type !== "in_process_teammate"
513484
513635
  ), hasDeliverableEngineWork = outstandingDeliverableWorkflowCount() > 0, hasMainThreadQueued = peek(isMainThread) !== void 0;
513485
- (hasRunningBg || hasMainThreadQueued || hasDeliverableEngineWork) && (waitingForAgents = !0, hasMainThreadQueued || (runPhase = "waiting_for_agents", await sleep3(100)));
513636
+ (hasRunningBg || hasMainThreadQueued || hasDeliverableEngineWork) && (waitingForAgents = !0, hasMainThreadQueued || (runPhase = "waiting_for_agents", await sleep2(100)));
513486
513637
  }
513487
513638
  } while (waitingForAgents);
513488
513639
  heldBackResult && (output.enqueue(heldBackResult), heldBackResult = null, suggestionState.pendingSuggestion && (output.enqueue(suggestionState.pendingSuggestion), suggestionState.pendingLastEmittedEntry && (suggestionState.lastEmitted = {
@@ -513607,7 +513758,7 @@ ${m2.text}
513607
513758
  }), run2();
513608
513759
  return;
513609
513760
  }
513610
- await sleep3(500);
513761
+ await sleep2(500);
513611
513762
  }
513612
513763
  }
513613
513764
  }
@@ -513620,7 +513771,7 @@ ${m2.text}
513620
513771
  mode: "prompt",
513621
513772
  value: SHUTDOWN_TEAM_PROMPT,
513622
513773
  uuid: randomUUID57()
513623
- }), run2()) : (suggestionState.inflightPromise && await Promise.race([suggestionState.inflightPromise, sleep3(5e3)]), suggestionState.abortController?.abort(), suggestionState.abortController = null, await finalizePendingAsyncHooks(), unsubscribeSkillChanges(), unsubscribeAuthStatus?.(), statusListeners.delete(rateLimitListener), output.done()));
513774
+ }), run2()) : (suggestionState.inflightPromise && await Promise.race([suggestionState.inflightPromise, sleep2(5e3)]), suggestionState.abortController?.abort(), suggestionState.abortController = null, await finalizePendingAsyncHooks(), unsubscribeSkillChanges(), unsubscribeAuthStatus?.(), statusListeners.delete(rateLimitListener), output.done()));
513624
513775
  }, cronScheduler = null, sendControlResponseSuccess = function(message, response) {
513625
513776
  output.enqueue({
513626
513777
  type: "control_response",
@@ -514381,7 +514532,7 @@ ${m2.text}
514381
514532
  }), run2();
514382
514533
  }
514383
514534
  }
514384
- inputClosed = !0, cronScheduler?.stop(), running || (suggestionState.inflightPromise && await Promise.race([suggestionState.inflightPromise, sleep3(5e3)]), suggestionState.abortController?.abort(), suggestionState.abortController = null, await finalizePendingAsyncHooks(), unsubscribeSkillChanges(), unsubscribeAuthStatus?.(), statusListeners.delete(rateLimitListener), output.done());
514535
+ inputClosed = !0, cronScheduler?.stop(), running || (suggestionState.inflightPromise && await Promise.race([suggestionState.inflightPromise, sleep2(5e3)]), suggestionState.abortController?.abort(), suggestionState.abortController = null, await finalizePendingAsyncHooks(), unsubscribeSkillChanges(), unsubscribeAuthStatus?.(), statusListeners.delete(rateLimitListener), output.done());
514385
514536
  })(), output;
514386
514537
  }
514387
514538
  function createCanUseToolWithPermissionPrompt(permissionPromptTool) {
@@ -518761,8 +518912,8 @@ function buildModelsValue(currentValue, uploaded, localRoles) {
518761
518912
  return Object.keys(roles).length > 0 && (value.roles = roles), Array.isArray(cur?.atModelAllowlist) && (value.atModelAllowlist = cur.atModelAllowlist), value;
518762
518913
  }
518763
518914
  function headerRefEnvName(server, header) {
518764
- let clean5 = (s) => s.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
518765
- return `SEMA_MCP_${clean5(server) || "SERVER"}_${clean5(header) || "HEADER"}`;
518915
+ let clean6 = (s) => s.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
518916
+ return `SEMA_MCP_${clean6(server) || "SERVER"}_${clean6(header) || "HEADER"}`;
518766
518917
  }
518767
518918
  function prepareMcp(name, c2) {
518768
518919
  let kind = asStr4(c2.type) ?? "stdio", display2 = `${name} (${kind}${kind === "stdio" ? `: ${asStr4(c2.command) ?? "?"}` : `: ${asStr4(c2.url) ?? "?"}`})`;
@@ -521072,7 +521223,7 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
521072
521223
  cap2.cleanup();
521073
521224
  break;
521074
521225
  }
521075
- hbCycles++, await sleep3(
521226
+ hbCycles++, await sleep2(
521076
521227
  hbConfig.non_exclusive_heartbeat_interval_ms,
521077
521228
  cap2.signal
521078
521229
  ), cap2.cleanup();
@@ -521082,18 +521233,18 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
521082
521233
  `[bridge:poll] Heartbeat poll_due after ${hbCycles} cycles \u2014 falling through to pollForWork`
521083
521234
  ), hbResult === "auth_failed" || hbResult === "fatal") {
521084
521235
  let cap2 = capacityWake.signal();
521085
- await sleep3(
521236
+ await sleep2(
521086
521237
  atCapMs > 0 ? atCapMs : pollConfig.non_exclusive_heartbeat_interval_ms,
521087
521238
  cap2.signal
521088
521239
  ), cap2.cleanup();
521089
521240
  }
521090
521241
  } else if (atCapMs > 0) {
521091
521242
  let cap2 = capacityWake.signal();
521092
- await sleep3(atCapMs, cap2.signal), cap2.cleanup();
521243
+ await sleep2(atCapMs, cap2.signal), cap2.cleanup();
521093
521244
  }
521094
521245
  } else {
521095
521246
  let interval = activeSessions.size > 0 ? pollConfig.multisession_poll_interval_ms_partial_capacity : pollConfig.multisession_poll_interval_ms_not_at_capacity;
521096
- await sleep3(interval, loopSignal);
521247
+ await sleep2(interval, loopSignal);
521097
521248
  }
521098
521249
  continue;
521099
521250
  }
@@ -521103,15 +521254,15 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
521103
521254
  `[bridge:work] Skipping already-completed workId=${work.id}`
521104
521255
  ), atCapacityBeforeSwitch) {
521105
521256
  let cap2 = capacityWake.signal();
521106
- pollConfig.non_exclusive_heartbeat_interval_ms > 0 ? (await heartbeatActiveWorkItems(), await sleep3(
521257
+ pollConfig.non_exclusive_heartbeat_interval_ms > 0 ? (await heartbeatActiveWorkItems(), await sleep2(
521107
521258
  pollConfig.non_exclusive_heartbeat_interval_ms,
521108
521259
  cap2.signal
521109
- )) : pollConfig.multisession_poll_interval_ms_at_capacity > 0 && await sleep3(
521260
+ )) : pollConfig.multisession_poll_interval_ms_at_capacity > 0 && await sleep2(
521110
521261
  pollConfig.multisession_poll_interval_ms_at_capacity,
521111
521262
  cap2.signal
521112
521263
  ), cap2.cleanup();
521113
521264
  } else
521114
- await sleep3(1e3, loopSignal);
521265
+ await sleep2(1e3, loopSignal);
521115
521266
  continue;
521116
521267
  }
521117
521268
  let secret;
@@ -521131,10 +521282,10 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
521131
521282
  )
521132
521283
  ), atCapacityBeforeSwitch) {
521133
521284
  let cap2 = capacityWake.signal();
521134
- pollConfig.non_exclusive_heartbeat_interval_ms > 0 ? (await heartbeatActiveWorkItems(), await sleep3(
521285
+ pollConfig.non_exclusive_heartbeat_interval_ms > 0 ? (await heartbeatActiveWorkItems(), await sleep2(
521135
521286
  pollConfig.non_exclusive_heartbeat_interval_ms,
521136
521287
  cap2.signal
521137
- )) : pollConfig.multisession_poll_interval_ms_at_capacity > 0 && await sleep3(
521288
+ )) : pollConfig.multisession_poll_interval_ms_at_capacity > 0 && await sleep2(
521138
521289
  pollConfig.multisession_poll_interval_ms_at_capacity,
521139
521290
  cap2.signal
521140
521291
  ), cap2.cleanup();
@@ -521198,7 +521349,7 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
521198
521349
  if (attempt < 2) {
521199
521350
  if (logForDebugging(
521200
521351
  `[bridge:session] CCR v2: registerWorker attempt ${attempt} failed, retrying: ${errMsg}`
521201
- ), await sleep3(2e3, loopSignal), loopSignal.aborted) break;
521352
+ ), await sleep2(2e3, loopSignal), loopSignal.aborted) break;
521202
521353
  continue;
521203
521354
  }
521204
521355
  logger.logError(
@@ -521360,10 +521511,10 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
521360
521511
  }
521361
521512
  if (atCapacityBeforeSwitch) {
521362
521513
  let cap2 = capacityWake.signal();
521363
- pollConfig.non_exclusive_heartbeat_interval_ms > 0 ? (await heartbeatActiveWorkItems(), await sleep3(
521514
+ pollConfig.non_exclusive_heartbeat_interval_ms > 0 ? (await heartbeatActiveWorkItems(), await sleep2(
521364
521515
  pollConfig.non_exclusive_heartbeat_interval_ms,
521365
521516
  cap2.signal
521366
- )) : pollConfig.multisession_poll_interval_ms_at_capacity > 0 && await sleep3(
521517
+ )) : pollConfig.multisession_poll_interval_ms_at_capacity > 0 && await sleep2(
521367
521518
  pollConfig.multisession_poll_interval_ms_at_capacity,
521368
521519
  cap2.signal
521369
521520
  ), cap2.cleanup();
@@ -521404,7 +521555,7 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
521404
521555
  ), logger.updateReconnectingStatus(
521405
521556
  formatDelay(delay),
521406
521557
  formatDuration(elapsed)
521407
- ), getPollIntervalConfig().non_exclusive_heartbeat_interval_ms > 0 && await heartbeatActiveWorkItems(), await sleep3(delay, loopSignal);
521558
+ ), getPollIntervalConfig().non_exclusive_heartbeat_interval_ms > 0 && await heartbeatActiveWorkItems(), await sleep2(delay, loopSignal);
521408
521559
  } else {
521409
521560
  let now2 = Date.now();
521410
521561
  lastPollErrorTime !== null && now2 - lastPollErrorTime > pollSleepDetectionThresholdMs(backoffConfig) && (logForDebugging(
@@ -521429,7 +521580,7 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
521429
521580
  ), logger.updateReconnectingStatus(
521430
521581
  formatDelay(delay),
521431
521582
  formatDuration(elapsed)
521432
- ), getPollIntervalConfig().non_exclusive_heartbeat_interval_ms > 0 && await heartbeatActiveWorkItems(), await sleep3(delay, loopSignal);
521583
+ ), getPollIntervalConfig().non_exclusive_heartbeat_interval_ms > 0 && await heartbeatActiveWorkItems(), await sleep2(delay, loopSignal);
521433
521584
  }
521434
521585
  }
521435
521586
  }
@@ -521456,7 +521607,7 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
521456
521607
  let timeout3 = new AbortController();
521457
521608
  await Promise.race([
521458
521609
  Promise.allSettled([...activeSessions.values()].map((h) => h.done)),
521459
- sleep3(backoffConfig.shutdownGraceMs ?? 3e4, timeout3.signal)
521610
+ sleep2(backoffConfig.shutdownGraceMs ?? 3e4, timeout3.signal)
521460
521611
  ]), timeout3.abort();
521461
521612
  for (let [sid, handle2] of activeSessions.entries())
521462
521613
  logForDebugging(`[bridge:shutdown] Force-killing stuck sessionId=${sid}`), handle2.forceKill();
@@ -521542,7 +521693,7 @@ async function stopWorkWithRetry(api2, environmentId, workId, logger, baseDelayM
521542
521693
  let delay = addJitter(baseDelayMs * Math.pow(2, attempt - 1));
521543
521694
  logger.logVerbose(
521544
521695
  `Failed to stop work ${workId} (attempt ${attempt}/3), retrying in ${formatDelay(delay)}: ${errMsg}`
521545
- ), await sleep3(delay);
521696
+ ), await sleep2(delay);
521546
521697
  } else
521547
521698
  logger.logError(
521548
521699
  `Failed to stop work ${workId} after 3 attempts: ${errMsg}`
@@ -521746,7 +521897,7 @@ async function bridgeMain(args) {
521746
521897
  used_create_session_in_dir: parsedCreateSessionInDir !== void 0
521747
521898
  }), await Promise.race([
521748
521899
  Promise.all([shutdown1PEventLogging(), shutdownDatadog()]),
521749
- sleep3(500, void 0, { unref: !0 })
521900
+ sleep2(500, void 0, { unref: !0 })
521750
521901
  ]).catch(() => {
521751
521902
  }), console.error(
521752
521903
  "Error: Multi-session Remote Control is not enabled for your account yet."
@@ -529396,7 +529547,7 @@ Usage: sema --remote "your task description"`, () => gracefulShutdown(1));
529396
529547
  pendingHookMessages
529397
529548
  }, renderAndRun);
529398
529549
  }
529399
- }).version("sema 1.0.76", "-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 () => {
529550
+ }).version("sema 1.0.78", "-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 () => {
529400
529551
  await (await Promise.resolve().then(() => (init_bg2(), bg_exports))).psHandler([]), process.exit(process.exitCode ?? 0);
529401
529552
  }), program2.command("logs [id]").description("Print a background session's recent terminal output").action(async (id) => {
529402
529553
  await (await Promise.resolve().then(() => (init_bg2(), bg_exports))).logsHandler(id, []), process.exit(process.exitCode ?? 0);
@@ -535522,10 +535673,10 @@ async function deleteJobFromView(short) {
535522
535673
  return `Worktree ${keptReason === "dirty" ? "has uncommitted changes" : "could not be removed"} \u2014 kept at ${keptWorktree}`;
535523
535674
  }
535524
535675
  async function renameJobFromView(short, name) {
535525
- let clean5 = cleanName(name);
535676
+ let clean6 = cleanName(name);
535526
535677
  await patchJobState(short, {
535527
- name: clean5,
535528
- nameSource: clean5 ? "user" : void 0
535678
+ name: clean6,
535679
+ nameSource: clean6 ? "user" : void 0
535529
535680
  });
535530
535681
  }
535531
535682
  function jobLabel(j3) {