@sema-agent/cli 1.0.112 → 1.0.113

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.
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@sema-agent/cli",
3
- "version": "1.0.112",
3
+ "version": "1.0.113",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@sema-agent/cli",
9
- "version": "1.0.112",
9
+ "version": "1.0.113",
10
10
  "license": "BUSL-1.1",
11
11
  "dependencies": {
12
12
  "@sema-agent/sdk": "9.3.0",
13
- "@sema-agent/server": "7.75.4"
13
+ "@sema-agent/server": "7.76.1"
14
14
  },
15
15
  "bin": {
16
16
  "sema": "sema.js"
@@ -620,9 +620,9 @@
620
620
  }
621
621
  },
622
622
  "node_modules/@sema-agent/core": {
623
- "version": "7.17.6",
624
- "resolved": "https://registry.npmjs.org/@sema-agent/core/-/core-7.17.6.tgz",
625
- "integrity": "sha512-ubDEJyOLiB8SkaS+nwVIw/Fh8xP56mpgk0rKcIJyNtWBJNQugW6yw9fHd8a9ZTT+lGJQjD+dGH+ITogXshvIqQ==",
623
+ "version": "7.17.7",
624
+ "resolved": "https://registry.npmjs.org/@sema-agent/core/-/core-7.17.7.tgz",
625
+ "integrity": "sha512-7rETEzf8dRvuBO+js9r+GRFBCyFq7oYqrRpd/zbTKwLEc44X1JjsK0yAYRGebTS5K+/EHKc15KXiqWu6XsAsHw==",
626
626
  "license": "BUSL-1.1",
627
627
  "dependencies": {
628
628
  "@modelcontextprotocol/sdk": "1.30.0",
@@ -645,12 +645,12 @@
645
645
  }
646
646
  },
647
647
  "node_modules/@sema-agent/server": {
648
- "version": "7.75.4",
649
- "resolved": "https://registry.npmjs.org/@sema-agent/server/-/server-7.75.4.tgz",
650
- "integrity": "sha512-WLh3T2s1RF4EYr+bKOa8UiVRdJHpQwaRkVDC+UgztpnRvx21Bu8lt21H8/N2K/Ub4SXetprhvtitshTUtMjFJA==",
648
+ "version": "7.76.1",
649
+ "resolved": "https://registry.npmjs.org/@sema-agent/server/-/server-7.76.1.tgz",
650
+ "integrity": "sha512-q8LrcnZfyLPlRZwJyTDAoVYGEEeMjoWoZX1gwg6g/bQ1PnjZL8f9F5dyFjg3tqB1Az7qFgNULN4hfQfposmXBw==",
651
651
  "license": "BUSL-1.1",
652
652
  "dependencies": {
653
- "@sema-agent/core": "7.17.6",
653
+ "@sema-agent/core": "7.17.7",
654
654
  "@sema-agent/settings-schema": "1.10.0",
655
655
  "e2b": "^2.28.0",
656
656
  "libsodium-wrappers": "^0.8.4",
@@ -826,9 +826,9 @@
826
826
  }
827
827
  },
828
828
  "node_modules/brace-expansion": {
829
- "version": "5.0.9",
830
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
831
- "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
829
+ "version": "5.0.12",
830
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
831
+ "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
832
832
  "license": "MIT",
833
833
  "dependencies": {
834
834
  "balanced-match": "^4.0.2"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/cli",
3
- "version": "1.0.112",
3
+ "version": "1.0.113",
4
4
  "description": "Sema — your own Claude Code-grade coding agent, in the terminal.",
5
5
  "license": "BUSL-1.1",
6
6
  "bin": {
@@ -24,13 +24,13 @@
24
24
  ],
25
25
  "dependencies": {
26
26
  "@sema-agent/sdk": "9.3.0",
27
- "@sema-agent/server": "7.75.4"
27
+ "@sema-agent/server": "7.76.1"
28
28
  },
29
29
  "overrides": {
30
- "@sema-agent/core": "7.17.6",
30
+ "@sema-agent/core": "7.17.7",
31
31
  "@sema-agent/settings-schema": "1.10.0"
32
32
  },
33
- "semaEngineVersion": "server 7.75.4 / core 7.17.6 / settings-schema 1.10.0",
33
+ "semaEngineVersion": "server 7.76.1 / core 7.17.7 / settings-schema 1.10.0",
34
34
  "engines": {
35
35
  "node": ">=20.3"
36
36
  }
package/sema-main.js CHANGED
@@ -4075,8 +4075,13 @@ var CHROME_ARM_TABLE, CHROME_ARMS, init_seam = __esm({
4075
4075
  duty: "\u7528 sdk isApprovalRevokeFrameV1 \u7A84\u5316 frame \u53D6 batchId/askIds/taskId;\u7A84\u4E0D\u4E0B\u6765\u6309\u901A\u7528\u64A4\u5361\u5904\u7406(\u8BE5\u6279\u672C\u5730\u5361\u7167\u6E05);\u{1F534} \u4E09\u7EAA\u5F8B:\u2460\u6309 taskId \u5F52\u5C5E\u8FC7\u6EE4(\u5B64\u513F\u64A4\u5E27\u884C\u975E\u6211\u5373\u5FFD\u7565)\u2461\u8D26\u672C\u91CD\u653E\u7684\u64A4\u5E27\u53EA\u7528\u4E8E\u65F6\u95F4\u7EBF\u6E32\u67D3,\u5361\u96C6\u57FA\u51C6\u6052\u4E3A\u5F00\u6D41 preamble(\u64A4\u5E27\u53EF\u80FD\u6574\u5E27\u4E22\u5931)\u2462\u5DF2 DECIDED \u7684\u5144\u5F1F\u4E0D\u5728 askIds \u91CC;\u771F\u64A4\u5230\u672C\u5730\u5361\u65F6\u7ED9\u4E00\u884C\u5F52\u56E0(reason \u6D88\u6BD2\u540E\u5448\u73B0),\u96F6\u547D\u4E2D\u4E0D\u8981\u591A\u8BF4\u90A3\u4E00\u884C"
4076
4076
  },
4077
4077
  text_segment_end: {
4078
- required: !1,
4079
- duty: "\u53EF\u9009:\u5F15\u64CE\u660E\u62A5\u7684 assistant \u6563\u6587\u6BB5\u8FB9\u754C(#323/core #447)\u3002\u{1F534} content \u662F\u5BF9\u8D26/\u5B9A\u754C\u7528\u7684\u6743\u5A01\u5168\u6587,\u62FF\u5B83\u518D\u6E32\u4E00\u884C = \u540C\u4E00\u6BB5\u4E0A\u5C4F\u4E24\u904D;\u7F3A\u5E2D\u53EA\u8868\u793A\u300C\u6CA1\u62A5\u300D,\u7EDD\u4E0D\u7B49\u4E8E\u300C\u6BB5\u6CA1\u7ED3\u675F\u300D\u2014\u2014\u8981\u9000\u56DE\u81EA\u5BB6\u542F\u53D1\u5F0F\u5FC5\u987B\u6309\u6574\u6761\u6D41\u5224\u3001\u4E0D\u6309\u5355\u5E27\u5224"
4078
+ // 🔴 0.68.1 / L-310:`false` → `true`。改的理由不是「这一面更重要了」,是**后果类目变了**:
4079
+ // 本表的 `false` 语义逐字是「不接 = 这条披露看不见,不属『已发生的行为丢失』」,而 server
4080
+ // 7.75.3 起不接的后果是**未脱敏字节留在本地转录里**(b2 那一形上,那条明文消息**已经渲过**
4081
+ // ⇒ 就是「已发生的行为」)。留 `false` = 把一条安全面义务标成可选,正是本仓点名要治的
4082
+ // 「假 affordance / 悄悄的谎」。⚠️ 这一位翻面会让按本表自检覆盖率的端**当场显形**——那正是目的。
4083
+ required: !0,
4084
+ duty: "\u{1F534} \u5F15\u64CE\u660E\u62A5\u7684 assistant \u6563\u6587\u6BB5\u8FB9\u754C + **\u8BE5\u6BB5\u6743\u5A01\u5168\u6587**(#323/core #447;server \u22657.75.3 \u8D77 content \u7ECF\u8131\u654F\u5668\u3001text_delta \u4ECD\u9010\u5B57 \u21D2 \u4E24\u8005**\u53EF\u4EE5\u4E0D\u76F8\u7B49**)\u3002\u2460`diverged` \u5728\u573A(never false)\u21D2 \u4F60\u6309\u589E\u91CF\u62FC\u51FA\u6765\u7684\u90A3\u4E00\u6BB5\u662F\u8FC7\u671F\u7684,\u5FC5\u987B\u7528 content **\u91CD\u6E32\u8BE5\u6BB5**\u5E76\u4EE5\u5B83\u4E3A\u8BE5\u6BB5 committed \u6587\u672C,\u4E0D\u8BB8\u4FDD\u7559\u589E\u91CF\u62FC\u6587;\u2461`committedPrefixDiverged` \u5728\u573A(never false)\u21D2 \u8FD9\u4E00\u6BB5\u6B64\u524D\u5DF2 committed \u4E0A\u5C4F\u7684\u6B63\u6587**\u4E5F**\u8FC7\u671F\u4E86,\u{1F534} \u672C\u5305\u5728\u8FD9\u4E00\u5F62\u4E0A**\u4E00\u4E2A\u5B57\u8282\u90FD\u4E0D\u518D\u4EA4**(\u64A4\u4E0D\u56DE\u7684\u90A3\u622A\u62FC\u4E0D\u51FA content)\u21D2 \u628A committedPrefixLen \u6307\u7684\u90A3\u4E00\u622A\u6362\u6210 content,\u8FD9\u4E00\u6761**\u6240\u6709\u5BBF\u4E3B\u90FD\u8981\u505A**;\u7F3A\u5E2D \u21D2 \u672C\u5305\u4EA4\u7684\u662F\u5C3E\u6BB5,\u524D\u7F00+\u5C3E\u6BB5=content,\u4EC0\u4E48\u90FD\u4E0D\u7528\u4E22;\u2462`committedPrefixLen`(never 0)= \u5B9A\u4F4D\u91CF,\u{1F534} **\u5355\u4F4D = JS \u5B57\u7B26\u4E32\u957F\u5EA6(UTF-16 \u4EE3\u7801\u5355\u5143),\u4E0D\u662F UTF-8 \u5B57\u8282\u3001\u4E5F\u4E0D\u662F\u51E0\u6761\u6D88\u606F**(\u6309 UTF-8 \u5B57\u8282\u622A\u4F1A\u5728\u975E ASCII \u6B63\u6587\u4E0A\u622A\u9519\u4F4D\u7F6E\u628A\u51ED\u636E\u7559\u5728\u5C4F\u4E0A;\u6309\u6D88\u606F\u4E22\u4F1A\u8FDE\u5408\u5E76\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u7684\u4E0A\u4E00\u6BB5\u5B9A\u7A3F\u4E00\u8D77\u5220\u6389),\u7167\u6284 `\u5DF2committed\u6B63\u6587.slice(0, \u957F\u5EA6 - committedPrefixLen) + content`;\u6309**\u589E\u91CF\u62FC\u6587**\u8BA1\u957F\u3001\u4E0D\u662F content \u4E0A\u7684\u504F\u79FB;\u2463\u4E09\u952E\u5168\u7F3A\u5E2D \u21D2 \u7167\u65E7\u53EA\u5F53\u5BF9\u8D26/\u5B9A\u754C,\u62FF content \u518D\u6E32\u4E00\u884C = \u540C\u4E00\u6BB5\u4E0A\u5C4F\u4E24\u904D\u3002\u{1F534} \u7F3A\u5E2D\u53EA\u8868\u793A\u300C\u6CA1\u62A5\u300D,\u7EDD\u4E0D\u7B49\u4E8E\u300C\u6BB5\u6CA1\u7ED3\u675F\u300D\u2014\u2014\u8981\u9000\u56DE\u81EA\u5BB6\u542F\u53D1\u5F0F\u5FC5\u987B\u6309\u6574\u6761\u6D41\u5224\u3001\u4E0D\u6309\u5355\u5E27\u5224"
4080
4085
  }
4081
4086
  }, CHROME_ARMS = Object.entries(CHROME_ARM_TABLE).map(([kind, d4]) => ({ kind, required: d4.required, duty: d4.duty }));
4082
4087
  }
@@ -5384,7 +5389,7 @@ function endsAtSentenceBoundary(s) {
5384
5389
  ` || last3 === "\r" || SENTENCE_END_CHARS.has(last3);
5385
5390
  }
5386
5391
  function createTextStream(ctx, idOf) {
5387
- let answer = "", answerSegment = "", thinking = "", emittedAssistantText = !1, committedText = "", previousCommittedText = "", textPending = "", thinkingPending = "", textBlockOpen = !1, thinkingBlockOpen = !1, lastFlushAt = 0, idleFlushUsedInSegment = !1, flushEveryMs = typeof ctx.coalesceIntervalMs == "number" && ctx.coalesceIntervalMs >= 0 ? ctx.coalesceIntervalMs : 100, segmentAnchor = null, thinkingAnchor = null;
5392
+ let answer = "", answerSegment = "", thinking = "", emittedAssistantText = !1, committedText = "", previousCommittedText = "", textPending = "", thinkingPending = "", textBlockOpen = !1, thinkingBlockOpen = !1, lastFlushAt = 0, idleFlushUsedInSegment = !1, segmentCommitted = "", previousSegmentCommitted = "", segmentSealed = "", flushEveryMs = typeof ctx.coalesceIntervalMs == "number" && ctx.coalesceIntervalMs >= 0 ? ctx.coalesceIntervalMs : 100, segmentAnchor = null, thinkingAnchor = null;
5388
5393
  function* takeThinking() {
5389
5394
  if (thinking.length === 0)
5390
5395
  return;
@@ -5400,23 +5405,25 @@ function createTextStream(ctx, idOf) {
5400
5405
  thinking = "", thinkingAnchor = null, thinkingBlockOpen = !1, yield chrome({ kind: "thinking_activity", laneProof: MAIN, active: !1 }), yield transcript(msg, ctx.now());
5401
5406
  }
5402
5407
  function* emitAnswerSegment() {
5403
- if (answerSegment.length === 0)
5408
+ let body = segmentSealed + answerSegment;
5409
+ if (body.length === 0)
5404
5410
  return;
5405
5411
  let anchor = segmentAnchor ?? {}, msg = {
5406
5412
  type: "assistant",
5407
5413
  // L-215③:同 takeThinking —— 身份位接力(帧优先、ctx 兜底;两位都读不出就一个都不铸)。
5408
- message: { role: "assistant", content: [{ type: "text", text: answerSegment }], ...messageIdentityOf(anchor, ctx) },
5414
+ message: { role: "assistant", content: [{ type: "text", text: body }], ...messageIdentityOf(anchor, ctx) },
5409
5415
  uuid: idOf(anchor, "text"),
5410
5416
  session_id: ctx.sessionId,
5411
5417
  parent_tool_use_id: null
5412
5418
  };
5413
- committedText += answerSegment, answerSegment = "", segmentAnchor = null, emittedAssistantText = !0, textBlockOpen = !1, yield transcript(msg, ctx.now());
5419
+ committedText += body, segmentCommitted += answerSegment, segmentSealed = "", answerSegment = "", segmentAnchor = null, emittedAssistantText = !0, textBlockOpen = !1, yield transcript(msg, ctx.now());
5414
5420
  }
5415
5421
  function* takeAnswerSegment() {
5416
- idleFlushUsedInSegment = !1, yield* emitAnswerSegment();
5422
+ idleFlushUsedInSegment = !1, yield* emitAnswerSegment(), previousSegmentCommitted += segmentCommitted, segmentCommitted = "";
5417
5423
  }
5418
5424
  function* takeAnswerSegmentOnIdle() {
5419
- answerSegment.length !== 0 && (idleFlushUsedInSegment || endsAtSentenceBoundary(answerSegment) && (idleFlushUsedInSegment = !0, yield* emitAnswerSegment()));
5425
+ let body = segmentSealed + answerSegment;
5426
+ body.length !== 0 && (idleFlushUsedInSegment || endsAtSentenceBoundary(body) && (idleFlushUsedInSegment = !0, yield* emitAnswerSegment()));
5420
5427
  }
5421
5428
  function* drainLive() {
5422
5429
  if (thinkingPending.length > 0) {
@@ -5444,7 +5451,7 @@ function createTextStream(ctx, idOf) {
5444
5451
  }
5445
5452
  return {
5446
5453
  *feedText(delta, frame) {
5447
- (thinking.length > 0 || thinkingPending.length > 0) && (yield* drainLive(), yield* takeThinking()), answerSegment.length === 0 && (segmentAnchor = frame), answer += delta, answerSegment += delta, textPending += delta;
5454
+ (thinking.length > 0 || thinkingPending.length > 0) && (yield* drainLive(), yield* takeThinking()), answerSegment.length === 0 && segmentSealed.length === 0 && (segmentAnchor = frame), answer += delta, answerSegment += delta, textPending += delta;
5448
5455
  },
5449
5456
  *feedThinking(delta, frame) {
5450
5457
  thinking.length === 0 && (thinkingAnchor = frame, yield chrome({ kind: "thinking_activity", laneProof: MAIN, active: !0 })), thinking += delta, thinkingPending += delta;
@@ -5453,7 +5460,18 @@ function createTextStream(ctx, idOf) {
5453
5460
  takeThinking,
5454
5461
  takeAnswerSegment,
5455
5462
  takeAnswerSegmentOnIdle,
5456
- hasPendingContent: () => thinking.length > 0 || answerSegment.length > 0 || thinkingPending.length > 0 || textPending.length > 0,
5463
+ replaceAnswerSegment: (content, anchor) => {
5464
+ let prevSegment = answerSegment, livePrefix = previousSegmentCommitted + segmentCommitted;
5465
+ if (livePrefix.length === 0 && prevSegment.length === 0)
5466
+ return { diverged: !1, committedPrefixLen: 0, committedPrefixDiverged: !1 };
5467
+ let liveSegment = livePrefix + prevSegment, diverged = liveSegment !== content, committedPrefixLen = livePrefix.length, committedPrefixDiverged = committedPrefixLen > 0 && !content.startsWith(livePrefix);
5468
+ if (committedPrefixDiverged && previousSegmentCommitted.length > 0)
5469
+ return segmentCommitted = "", previousSegmentCommitted = "", idleFlushUsedInSegment = !1, { diverged, committedPrefixLen, committedPrefixDiverged };
5470
+ let segTailLen = Math.min(textPending.length, prevSegment.length), carry = textPending.slice(0, textPending.length - segTailLen), emittedForSegment = livePrefix + prevSegment.slice(0, prevSegment.length - segTailLen);
5471
+ return textPending = content.startsWith(emittedForSegment) ? carry + content.slice(emittedForSegment.length) : carry, committedPrefixDiverged ? committedText.endsWith(livePrefix) && (committedText = committedText.slice(0, committedText.length - livePrefix.length) + content) : segmentSealed += content.slice(committedPrefixLen), answerSegment = "", answer.endsWith(liveSegment) && (answer = answer.slice(0, answer.length - liveSegment.length) + content), segmentAnchor === null && anchor !== void 0 && (segmentAnchor = anchor), segmentCommitted = "", previousSegmentCommitted = "", idleFlushUsedInSegment = !1, { diverged, committedPrefixLen, committedPrefixDiverged };
5472
+ },
5473
+ hasPendingContent: () => thinking.length > 0 || // L-310:已封存的定稿段同样是「有已生成未提交的内容」(不算进来会让它一直押到 turn 收口)。
5474
+ segmentSealed.length > 0 || answerSegment.length > 0 || thinkingPending.length > 0 || textPending.length > 0,
5457
5475
  *maybeFlushOnBeat(nowMs2) {
5458
5476
  (textPending.length > 0 || thinkingPending.length > 0) && nowMs2 - lastFlushAt >= flushEveryMs && (yield* drainLive(), lastFlushAt = nowMs2);
5459
5477
  },
@@ -5464,7 +5482,7 @@ function createTextStream(ctx, idOf) {
5464
5482
  emittedAssistantText = !0, typeof committed == "string" && (committedText += committed);
5465
5483
  },
5466
5484
  beginAssistantMessage: () => {
5467
- committedText.length > 0 && (previousCommittedText = committedText), committedText = "";
5485
+ committedText.length > 0 && (previousCommittedText = committedText), committedText = "", previousSegmentCommitted += segmentCommitted, segmentCommitted = "";
5468
5486
  },
5469
5487
  get committedAnswerText() {
5470
5488
  return committedText;
@@ -7807,16 +7825,22 @@ var assistantArm, userArm, systemArm, diagnosticsArm, steeringInjectedArm, works
7807
7825
  return;
7808
7826
  let frame = m2.frame;
7809
7827
  typeof frame != "object" || frame === null || (yield chrome({ kind, laneProof: MAIN, frame, schemaVersion }));
7810
- }, textSegmentEndArm = function* (m2) {
7828
+ }, textSegmentEndArm = function* (m2, { text: text2 }) {
7811
7829
  if (m2.parentToolCallId !== void 0)
7812
7830
  return;
7813
7831
  let content = typeof m2.content == "string" ? m2.content : "";
7814
- content.length !== 0 && (yield chrome({
7832
+ if (content.length === 0)
7833
+ return;
7834
+ let r = text2.replaceAnswerSegment(content, m2);
7835
+ yield chrome({
7815
7836
  kind: "text_segment_end",
7816
7837
  laneProof: MAIN,
7817
7838
  content,
7839
+ ...r.diverged ? { diverged: !0 } : {},
7840
+ ...r.committedPrefixDiverged ? { committedPrefixDiverged: !0 } : {},
7841
+ ...r.committedPrefixLen > 0 ? { committedPrefixLen: r.committedPrefixLen } : {},
7818
7842
  ...typeof m2.eventId == "string" && m2.eventId.length > 0 ? { eventId: m2.eventId } : {}
7819
- }));
7843
+ });
7820
7844
  }, promptSuggestionsArm = function* (m2) {
7821
7845
  if (typeof m2.parentToolCallId == "string")
7822
7846
  return;
@@ -8141,7 +8165,10 @@ var ADAPTER_COVERAGE, ADAPTER_DIVERGENCES, WireToCcAdapterImpl, init_adapt = __e
8141
8165
  "message_committed",
8142
8166
  // #318 件①(2026-08-21):`engine_notice` 引擎结构化通告 —— 投 chrome(开集,一个码都不判)。
8143
8167
  "engine_notice",
8144
- // #323 / core #447:assistant 散文段边界 → chrome text_segment_end(子流断闸;本批**不**动文本缓冲)。
8168
+ // #323 / core #447 + L-310(0.68.1 改口):assistant 散文段边界 → **整段替换文本缓冲** +
8169
+ // chrome text_segment_end(子流断闸在替换之前)。修前这里写「本批**不**动文本缓冲」——
8170
+ // server 7.75.3 起 `text_end.content` 经脱敏器而 `text_delta` 仍逐字,不动缓冲 = 未脱敏字节
8171
+ // committed 进本地转录;替换语义见 `adapt/textStream.ts` 的 `replaceAnswerSegment` 头注。
8145
8172
  "text_end",
8146
8173
  "prompt_suggestions",
8147
8174
  "retry_status",
@@ -9631,9 +9658,13 @@ function readEntry(raw2) {
9631
9658
  ...str3(o.cardId) !== void 0 ? { cardId: str3(o.cardId) } : {},
9632
9659
  ...str3(o.capabilityId) !== void 0 ? { capabilityId: str3(o.capabilityId) } : {},
9633
9660
  ...str3(o.effect) !== void 0 ? { effect: str3(o.effect) } : {},
9661
+ // L-290 族扫:三根轴各自的**出身**键(开集读,`str()` 同律;坏形只丢这一格,行还在 —— 出身不是身份)。
9662
+ ...str3(o.effectProvenance) !== void 0 ? { effectProvenance: str3(o.effectProvenance) } : {},
9634
9663
  ...typeof o.egress == "boolean" ? { egress: o.egress } : {},
9664
+ ...str3(o.egressProvenance) !== void 0 ? { egressProvenance: str3(o.egressProvenance) } : {},
9635
9665
  ...str3(o.irreversibility) !== void 0 ? { irreversibility: str3(o.irreversibility) } : {},
9636
9666
  ...str3(o.contentOrigin) !== void 0 ? { contentOrigin: str3(o.contentOrigin) } : {},
9667
+ ...str3(o.contentOriginProvenance) !== void 0 ? { contentOriginProvenance: str3(o.contentOriginProvenance) } : {},
9637
9668
  ...str3(o.family) !== void 0 ? { family: str3(o.family) } : {},
9638
9669
  ...readPathTarget(o.pathTarget) !== void 0 ? { pathTarget: readPathTarget(o.pathTarget) } : {},
9639
9670
  ...hintsRaw !== void 0 ? {
@@ -10338,7 +10369,12 @@ var ControlSafetyError, BAND_RANK, ControlRouter, STEERING_CODE_TO_SAFETY, STEER
10338
10369
  ["steering.duplicate_input_id", "duplicate_input_id"],
10339
10370
  ["steering.ambiguous_target", "ambiguous_target"],
10340
10371
  ["steering.ambiguous_label", "ambiguous_target"],
10341
- ["steering.still_running", "still_running"]
10372
+ ["steering.still_running", "still_running"],
10373
+ // [7226] 包侧缺口 ①(0.68.1):server 契约 (2) 表第 8 码(422)。SDK 8.8.0 **没有**专属子类
10374
+ // (`errors.d.ts` 的 `Steering*Error` 只有六只)⇒ 只能按 `errorCode` 认;认不出时它会落开集位
10375
+ // `steering_other`,而那一位的判词是「别猜它的意思」—— 恰好把一条「改内容重试即可」的拒绝
10376
+ // 说成没救。所以码表必须点名它,不能靠前缀兜底。
10377
+ ["steering.blocked_by_hook", "blocked_by_hook"]
10342
10378
  ]), STEERING_NAME_TO_SAFETY = /* @__PURE__ */ new Map([
10343
10379
  ["SteeringNotRunningError", "not_running"],
10344
10380
  ["SteeringInvalidContentError", "invalid_content"],
@@ -10352,6 +10388,7 @@ var ControlSafetyError, BAND_RANK, ControlRouter, STEERING_CODE_TO_SAFETY, STEER
10352
10388
  ["duplicate_input_id", "this Idempotency-Key is already parked with DIFFERENT steering content \u2014 reissue with a fresh key, resending verbatim will never succeed"],
10353
10389
  ["ambiguous_target", "more than one live target matches \u2014 address it uniquely (sub-agent: parentToolCallId; workflow: a more specific label); retrying verbatim yields the same result"],
10354
10390
  ["still_running", "the target is STILL RUNNING \u2014 steer it instead of resuming, or wait for it to settle (this is the exact opposite of not_running: never collapse the two)"],
10391
+ ["blocked_by_hook", "this deployment's userPromptSubmit gate refused the input (block, timeout and crash all report this one code, fail-closed) \u2014 the input was NOT accepted: no human_input frame, the inputId is not on the ledger, so editing the text and sending again is a normal retry, not a duplicate"],
10355
10392
  ["steering_other", "an unrecognized steering.* refusal (open set) \u2014 the steer did NOT land; log the errorCode verbatim, do not guess its meaning"]
10356
10393
  ]);
10357
10394
  }
@@ -13483,7 +13520,9 @@ var PLAN_REVIEW_GATE_KIND, PLAN_REVIEW_GATE_KINDS, ASK_PARK_GATE_KINDS, PLAN_REV
13483
13520
 
13484
13521
  // node_modules/@sema-agent/client-core/dist/request/taskRequest.js
13485
13522
  function buildTaskRequest(input, lane) {
13486
- let live = input.live, on = (field, value) => {
13523
+ let live = input.live;
13524
+ refuseBadMemoryCapture(input.memoryCapture);
13525
+ let on = (field, value) => {
13487
13526
  if (value == null)
13488
13527
  return !1;
13489
13528
  let spec = REQUEST_FIELD_MATRIX.find((f) => f.field === field);
@@ -13531,6 +13570,8 @@ function buildTaskRequest(input, lane) {
13531
13570
  ...on("limits", input.limits) ? { limits: input.limits } : {},
13532
13571
  ...on("interactiveTools", input.interactiveTools) && input.interactiveTools === !1 ? { interactiveTools: !1 } : {},
13533
13572
  ...on("oneShot", input.oneShot) && input.oneShot === !0 ? { oneShot: !0 } : {},
13573
+ // ⑤ 单成员闭集:值**恰是** `'off'` 才 stamp。表外拼写在上面已经**响亮拒**(见 `refuseBadMemoryCapture`)。
13574
+ ...on("memoryCapture", input.memoryCapture) && input.memoryCapture === "off" ? { memoryCapture: "off" } : {},
13534
13575
  ...Object.keys(settingsOut).length > 0 ? { settings: settingsOut } : {}
13535
13576
  };
13536
13577
  }
@@ -13572,7 +13613,7 @@ function unregisteredRequestKeys(req, lane) {
13572
13613
  }
13573
13614
  return out6;
13574
13615
  }
13575
- var REQUEST_FIELD_MATRIX, LIVE_DEFAULT_FIELDS, laneHas, foreignSettingsSubKeys, namedSettingsSubKeys, PERMISSION_FACE_KEY, shapeTag, isPlainRecord, materializeJsonFaithful, resolvedSnapshotForWire, init_taskRequest = __esm({
13616
+ var REQUEST_FIELD_MATRIX, LIVE_DEFAULT_FIELDS, laneHas, foreignSettingsSubKeys, namedSettingsSubKeys, PERMISSION_FACE_KEY, shapeTag, isPlainRecord, materializeJsonFaithful, resolvedSnapshotForWire, refuseBadMemoryCapture, init_taskRequest = __esm({
13576
13617
  "node_modules/@sema-agent/client-core/dist/request/taskRequest.js"() {
13577
13618
  REQUEST_FIELD_MATRIX = [
13578
13619
  // ── 两条车道都有 ────────────────────────────────────────────────────────────────────────────
@@ -13612,6 +13653,15 @@ var REQUEST_FIELD_MATRIX, LIVE_DEFAULT_FIELDS, laneHas, foreignSettingsSubKeys,
13612
13653
  { field: "debate", lanes: ["interactive", "print"], live: !0, why: "council \u7684 debate \u53D8\u4F53\u5F00\u5173(server \u8BFB `=== true`)" },
13613
13654
  { field: "rounds", lanes: ["interactive", "print"], live: !0, why: "debate \u8F6E\u6570(server clamp [1,3],\u975E\u6709\u9650\u6570\u88AB server \u5F52 undefined\u2014\u2014\u672C\u5C42\u539F\u6837\u900F\u4F20\u4E0D\u9884 clamp)" },
13614
13655
  { field: "lenses", lanes: ["interactive", "print"], live: !0, why: "code-review \u955C\u5934\u96C6(passthrough \u540C repo;\u5F62\u72B6\u7531 server \u573A\u666F\u5B9A\u4E49,\u672C\u5C42\u4E0D\u95ED\u96C6)" },
13656
+ // ── memoryCapture([7226] 包侧缺口 ⑤,0.68.1)──────────────────────────────────────────────
13657
+ // 🔴 **单成员闭集**:server 契约 §12.4 逐字「`memoryCapture?: "off"`。单成员闭集(**没有**
13658
+ // `"on"`)」—— 所以本层只在值**恰是** `'off'` 时 stamp;`'on'` / 坏拼写一律不上 wire
13659
+ // (坏拼写 server 判 400 `request.field_invalid`,本层不预铸第二判官,但也不替它买路)。
13660
+ // 🔴 与**中途翻转 verb** `POST /v1/runs/:id/memory/capture-optout`(§12.5,能力位
13661
+ // `runMemoryCaptureOptOut`)是**同一条一次性单向记录的两个口**,不是两个轴:verb 管这一条
13662
+ // 在飞的 run,本键管「本会话的下一次新提交」。非 live 的 verb(parked / 终态 / 他副本)回
13663
+ // 409 `steering.not_running` 并**指路本键** —— 端没有本键就接不住那条指路。
13664
+ { field: "memoryCapture", lanes: ["interactive", "print"], live: !0, why: '\u672C\u4F1A\u8BDD\u6C38\u8FDC\u4E0D\u8FDB\u957F\u671F\u8BB0\u5FC6\u7684**\u58F0\u660E\u5F62**(server \xA712.4 body \u952E,\u5355\u6210\u5458\u95ED\u96C6 "off");\u4E24\u6761\u8F66\u9053\u90FD\u662F\u63D0\u4EA4\u9762 \u21D2 \u90FD\u80FD\u58F0\u660E\u3002\u4E0E memoryWrite:false \u4E0D\u662F\u4E00\u4E2A\u8F74(\u90A3\u662F\u300C\u672C run \u53EA\u8BFB\u5E73\u9762\u300D)\u3002\u26A0\uFE0F parked \u7EED\u8DD1\u817F\u7ED3\u6784\u6027\u62FF\u4E0D\u5230\u58F0\u660E(\u51B3\u7B56/\u7EED\u8DD1\u7AEF\u70B9\u4ECE\u6301\u4E45 body \u91CD\u5EFA spec),\u90A3\u662F\u5F15\u64CE\u4FA7\u4E8B\u5B9E,\u4E0D\u662F\u672C\u5C42\u7684\u6F0F' },
13615
13665
  // ── print 独有(§8-5 认定的**有理由**的差异)──────────────────────────────────────────────
13616
13666
  { field: "finalVerification", lanes: ["print"], live: !0, why: "P1-1 \u7EC8\u9A8C:\u65E0\u4EBA\u503C\u5B88\u8F66\u9053\u624D\u9700\u8981\u5F15\u64CE\u81EA\u8BC1;\u4EA4\u4E92 REPL \u7531\u4EBA\u5F53\u573A\u770B\u7ED3\u679C\u3002#106 \u88C1 B(\u8BA9\u4F4D+\u544A\u77E5)\u540E\u4EA4\u4E92\u9762\u9ED8\u8BA4\u5173" },
13617
13667
  { field: "limits", lanes: ["print"], live: !0, why: "P2-3-b:`-p` \u7684\u9884\u7B97\u62A4\u680F(--max-* flag \u65CF),\u4EA4\u4E92 REPL \u7531\u4EBA\u968F\u65F6 Esc" },
@@ -13740,6 +13790,9 @@ var REQUEST_FIELD_MATRIX, LIVE_DEFAULT_FIELDS, laneHas, foreignSettingsSubKeys,
13740
13790
  if (!isPlainRecord(resolved))
13741
13791
  throw new TypeError(`buildTaskRequest: settings.resolved \u53EA\u63A5\u53D7 plain object \u6216\u7F3A\u5E2D(undefined/null)\u2014\u2014 \u6536\u5230 ${shapeTag(resolved)}\u3002\u8FD9\u4E00\u4F4D\u644A\u5F00\u7684\u662F\u5DF2\u89E3\u6790\u6743\u9650\u9762(permissions.deny/ask \u7B49\u5B50\u952E\u5373 wire \u952E):\u628A\u7578\u5F62\u503C\u964D\u6210\u7A7A\u5BF9\u8C61\u7B49\u4E8E\u8BA9\u8BF7\u6C42\u5E26\u7740\u88AB\u5265\u6389\u7684\u6743\u9650\u9762\u53D1\u51FA\u53BB(deny \u9759\u9ED8\u5931\u6548),\u6240\u4EE5\u5728\u63D0\u4EA4\u524D\u62D2\u3002\u9519\u8BEF\u6587\u672C\u53EA\u62A5\u5F62\u72B6,\u4E0D\u56DE\u663E\u5FEB\u7167\u5185\u5BB9\u3002`);
13742
13792
  return out6;
13793
+ }, refuseBadMemoryCapture = (v2) => {
13794
+ if (v2 != null && v2 !== "off")
13795
+ throw new TypeError(`buildTaskRequest: memoryCapture \u53EA\u63A5\u53D7\u5B57\u9762\u91CF \`'off'\` \u6216\u7F3A\u5E2D(undefined/null)\u2014\u2014 \u6536\u5230 ${shapeTag(v2)}\u3002\u8FD9\u4E00\u4F4D\u662F**\u4F1A\u8BDD\u7EA7\u9690\u79C1\u58F0\u660E**(\u300C\u672C\u4F1A\u8BDD\u6C38\u8FDC\u4E0D\u8FDB\u957F\u671F\u8BB0\u5FC6\u300D),\u4E0A\u6E38\u662F**\u5355\u6210\u5458\u95ED\u96C6**(\u6CA1\u6709 \`"on"\`)\u4E14\u5BF9\u574F\u62FC\u5199**\u54CD\u4EAE\u62D2**(core \`config.memory_capture_spelling\` / server 400 \`request.field_invalid\`)\u3002\u672C\u5C42\u82E5\u628A\u574F\u503C\u9759\u9ED8\u5220\u952E,\u8BF7\u6C42\u4F1A\u7167\u53D1\u3001\u5F15\u64CE\u4F1A\u7167\u5E38\u91C7\u96C6,\u800C\u58F0\u660E\u4EBA\u4E0D\u4F1A\u77E5\u9053\u81EA\u5DF1\u7684 opt-out \u4E22\u4E86 \u2014\u2014 \u628A\u4E00\u6761\u9690\u79C1\u8BF7\u6C42\u6309\u6253\u5B57\u9519\u8BEF\u9759\u9ED8\u4E22\u6389\u662F**\u7981\u7684\u65B9\u5411**\u3002\u9519\u8BEF\u6587\u672C\u53EA\u62A5\u5F62\u72B6,\u4E0D\u56DE\u663E\u503C\u3002`);
13743
13796
  };
13744
13797
  }
13745
13798
  });
@@ -144738,6 +144791,7 @@ __export(interactiveReattach_exports, {
144738
144791
  _resetInteractiveReattachForTest: () => _resetInteractiveReattachForTest,
144739
144792
  _setReattachTuningForTest: () => _setReattachTuningForTest,
144740
144793
  activeReattachMachine: () => activeReattachMachine,
144794
+ committedPrefixUnretractableRow: () => committedPrefixUnretractableRow,
144741
144795
  isReattachSettleError: () => isReattachSettleError,
144742
144796
  isReattachableTear: () => isReattachableTear,
144743
144797
  isRetriableTailFailure: () => isRetriableTailFailure,
@@ -144831,6 +144885,9 @@ function reattachSynthesizedTerminalRow(state5, partial2) {
144831
144885
  function resultTextDivergedRow() {
144832
144886
  return "the engine's final answer for this turn does not match the text streamed above; neither version is shown as the other \u2014 read the run on the engine if you need the authoritative one";
144833
144887
  }
144888
+ function committedPrefixUnretractableRow() {
144889
+ return "the engine sent a redacted authoritative copy of a passage that is already on screen above, and this shell could not substitute it in place \u2014 the copy above may still contain the raw text; read the run on the engine for the authoritative version";
144890
+ }
144834
144891
  function reattachSettleRow(err8, entry = "reconnect") {
144835
144892
  if (err8.name === "ReattachUnauthorizedError")
144836
144893
  return `The engine rejected this session's credentials while run ${err8.taskId} was still in flight, so sema stopped reattaching \u2014 this is NOT a lost connection. The usual cause: the engine was restarted by another sema session, and a restarted engine mints a fresh service token, so the token this screen was holding belongs to the engine that went away. sema already re-read the engine's credential file before giving up. What you see above may be incomplete. ${NEXT_MESSAGE_EXIT} If that message is rejected too, this session never picked up the new credential \u2014 restart sema and it will attach to the engine that is running now.`;
@@ -152959,6 +153016,88 @@ var init_applySettingsChange = __esm({
152959
153016
  }
152960
153017
  });
152961
153018
 
153019
+ // build-src/src/sema/controlSafetyAdvice.ts
153020
+ function controlSafetyAdvice(code2) {
153021
+ switch (code2) {
153022
+ case "not_running":
153023
+ return {
153024
+ headline: "that run is not in flight (it is suspended, already finished, or lives on another replica)",
153025
+ nextStep: "resolve its gate first \u2014 steering a run that is not running has no effect",
153026
+ accepted: "refused"
153027
+ };
153028
+ case "invalid_content":
153029
+ return {
153030
+ // 🔴 文案里**不复述**被拒的正文(它正是越狱串本身),只说「正文里有控制面标记」。
153031
+ headline: "the engine rejected that message because its text carries control-plane markers",
153032
+ nextStep: "rewrite the message yourself \u2014 this shell will not strip parts of it and resend",
153033
+ accepted: "refused"
153034
+ };
153035
+ case "queue_full":
153036
+ return {
153037
+ headline: "the steering queue on that checkpoint is full \u2014 the engine refuses to evict anything it already accepted",
153038
+ nextStep: "wait for it to drain, then send again",
153039
+ accepted: "refused"
153040
+ };
153041
+ case "duplicate_input_id":
153042
+ return {
153043
+ headline: "that idempotency key was already used with DIFFERENT text",
153044
+ nextStep: "send it under a new key \u2014 resending the same body under the reused key cannot land",
153045
+ accepted: "refused"
153046
+ };
153047
+ case "ambiguous_target":
153048
+ return {
153049
+ headline: "more than one live target matched",
153050
+ nextStep: "name it unambiguously (an id rather than a label) and try again",
153051
+ accepted: "refused"
153052
+ };
153053
+ case "still_running":
153054
+ return {
153055
+ headline: "that agent is STILL running \u2014 resume only applies to one that has stopped",
153056
+ nextStep: "steer it instead, or wait for it to settle",
153057
+ accepted: "refused"
153058
+ };
153059
+ case "blocked_by_hook":
153060
+ return {
153061
+ headline: "that message was not accepted \u2014 a deployment prompt hook blocked it, so nothing was delivered to the model",
153062
+ nextStep: "edit the content and send it again \u2014 this is not a duplicate submission",
153063
+ accepted: "refused"
153064
+ };
153065
+ case "steering_other":
153066
+ return UNRECOGNISED;
153067
+ case "cancel_lost_race":
153068
+ return {
153069
+ headline: "the pending gate was decided or expired concurrently, so the cancel lost the race",
153070
+ nextStep: "re-read the run state, then cancel again if it is still pending",
153071
+ accepted: "refused"
153072
+ };
153073
+ case "not_found":
153074
+ return {
153075
+ headline: "the engine does not have that run (unknown id, or it belongs to another owner)",
153076
+ nextStep: "nothing was cancelled \u2014 re-read the run list",
153077
+ accepted: "refused"
153078
+ };
153079
+ default:
153080
+ return UNRECOGNISED;
153081
+ }
153082
+ }
153083
+ function controlSafetyNote(code2) {
153084
+ let a = controlSafetyAdvice(code2);
153085
+ return [`control request refused (${code2})`, a.headline, a.nextStep].join(" \xB7 ");
153086
+ }
153087
+ function controlSafetyCodeOf(err8) {
153088
+ let c3 = err8?.code;
153089
+ return typeof c3 == "string" && c3.length > 0 ? c3 : void 0;
153090
+ }
153091
+ var UNRECOGNISED, init_controlSafetyAdvice = __esm({
153092
+ "build-src/src/sema/controlSafetyAdvice.ts"() {
153093
+ UNRECOGNISED = {
153094
+ headline: "the engine refused that control request with a reason this shell does not recognise",
153095
+ nextStep: "nothing was delivered \u2014 retry it, and report the code above if it keeps happening",
153096
+ accepted: "refused"
153097
+ };
153098
+ }
153099
+ });
153100
+
152962
153101
  // node_modules/lodash-es/_baseForOwn.js
152963
153102
  function baseForOwn(object4, iteratee) {
152964
153103
  return object4 && baseFor_default(object4, iteratee, keys_default);
@@ -389202,7 +389341,7 @@ function splitShellCompoundSegments(source, options) {
389202
389341
  }
389203
389342
  return segments.push(cur), { segments, pipeFed: connectors.map((k2) => k2 === "|"), connectors };
389204
389343
  }
389205
- var NOT_AUTO_ALLOWED, BASH_READONLY_DEFAULT_ALLOW, BASH_CLASSIFY_DEFAULT_ALLOW, SHELL_OPERATORS2, SHELL_SEGMENT_HARD_REJECT, SHELL_REDIRECTION_OPERATORS, SHELL_CONNECTOR_CHARS, init_bash_readonly_classifier = __esm({
389344
+ var NOT_AUTO_ALLOWED, BASH_READONLY_DEFAULT_ALLOW, BASH_CLASSIFY_DEFAULT_ALLOW, SHELL_OPERATORS2, SHELL_SEGMENT_HARD_REJECT, SHELL_REDIRECTION_OPERATORS, SHELL_CONNECTOR_CHARS, BLANK_INLINE, PERL_INLINE, RUBY_INLINE, PYTHON_INLINE, NODE_INLINE, PHP_INLINE, LUA_INLINE, TCL_INLINE, EXPECT_INLINE, AWK_INLINE, JQ_INLINE, BC_INLINE, DC_INLINE, SQLITE_INLINE, PSQL_INLINE, OSASCRIPT_INLINE, RSCRIPT_INLINE, JULIA_INLINE, GHCI_INLINE, GROOVY_INLINE, BUN_INLINE, init_bash_readonly_classifier = __esm({
389206
389345
  "node_modules/@sema-agent/core/dist/tools/fs/bash-readonly-classifier.js"() {
389207
389346
  init_safety();
389208
389347
  NOT_AUTO_ALLOWED = "\u2014 not auto-allowed", BASH_READONLY_DEFAULT_ALLOW = [
@@ -389245,6 +389384,181 @@ var NOT_AUTO_ALLOWED, BASH_READONLY_DEFAULT_ALLOW, BASH_CLASSIFY_DEFAULT_ALLOW,
389245
389384
  ], BASH_CLASSIFY_DEFAULT_ALLOW = [...BASH_READONLY_DEFAULT_ALLOW, "find", "sed", "cd"], SHELL_OPERATORS2 = /[;&|<>$()`\n\r\\]/;
389246
389385
  SHELL_SEGMENT_HARD_REJECT = /[<>$()`\n\r\\]/;
389247
389386
  SHELL_REDIRECTION_OPERATORS = /[<>]/, SHELL_CONNECTOR_CHARS = /[|&;]/;
389387
+ BLANK_INLINE = {
389388
+ longText: /* @__PURE__ */ new Set(),
389389
+ longFile: /* @__PURE__ */ new Set(),
389390
+ longNamesProgram: /* @__PURE__ */ new Set(),
389391
+ longSupplemental: /* @__PURE__ */ new Set(),
389392
+ longValue: /* @__PURE__ */ new Set(),
389393
+ longPlain: /* @__PURE__ */ new Set(),
389394
+ fileOptionEndsOptions: !1,
389395
+ textLetters: "",
389396
+ fileLetters: "",
389397
+ separatedValueLetters: "",
389398
+ attachedValueLetters: "",
389399
+ plainLetters: "",
389400
+ bannerLetters: "",
389401
+ interactiveLetters: "",
389402
+ programOperand: { at: 0, isText: !1 }
389403
+ }, PERL_INLINE = {
389404
+ ...BLANK_INLINE,
389405
+ textLetters: "eEmM",
389406
+ separatedValueLetters: "I",
389407
+ attachedValueLetters: "iCFxDV",
389408
+ plainLetters: "nplawcsStTUWX",
389409
+ bannerLetters: "vVh",
389410
+ stdinWhenUnnamed: !0
389411
+ }, RUBY_INLINE = {
389412
+ ...BLANK_INLINE,
389413
+ textLetters: "e",
389414
+ separatedValueLetters: "IrECFKT",
389415
+ plainLetters: "nplawcsSU",
389416
+ bannerLetters: "vh",
389417
+ stdinWhenUnnamed: !0
389418
+ }, PYTHON_INLINE = {
389419
+ ...BLANK_INLINE,
389420
+ textLetters: "c",
389421
+ fileLetters: "m",
389422
+ separatedValueLetters: "WXQ",
389423
+ plainLetters: "uBEIsSqbdvxOtR",
389424
+ bannerLetters: "Vh?",
389425
+ interactiveLetters: "i",
389426
+ fileOptionEndsOptions: !0,
389427
+ stdinWhenUnnamed: !0
389428
+ }, NODE_INLINE = {
389429
+ ...BLANK_INLINE,
389430
+ longText: /* @__PURE__ */ new Set(["--eval", "--print"]),
389431
+ textLetters: "ep",
389432
+ longValue: /* @__PURE__ */ new Set(["--import", "--loader", "--experimental-loader", "--require", "--env-file", "--conditions", "--max-old-space-size"]),
389433
+ longNamesProgram: /* @__PURE__ */ new Set(["--test"]),
389434
+ longPlain: /* @__PURE__ */ new Set(["--inspect", "--inspect-brk", "--no-warnings", "--trace-warnings", "--watch", "--enable-source-maps", "--experimental-modules", "--no-deprecation", "--check"]),
389435
+ separatedValueLetters: "r",
389436
+ plainLetters: "c",
389437
+ bannerLetters: "vh",
389438
+ interactiveLetters: "i",
389439
+ stdinWhenUnnamed: !0
389440
+ }, PHP_INLINE = {
389441
+ ...BLANK_INLINE,
389442
+ longText: /* @__PURE__ */ new Set(["--run", "--process-begin", "--process-code", "--process-end"]),
389443
+ textLetters: "rRBE",
389444
+ fileLetters: "fF",
389445
+ separatedValueLetters: "dcz",
389446
+ plainLetters: "nqswl",
389447
+ bannerLetters: "vhi",
389448
+ interactiveLetters: "a",
389449
+ stdinWhenUnnamed: !0
389450
+ }, LUA_INLINE = {
389451
+ ...BLANK_INLINE,
389452
+ textLetters: "e",
389453
+ separatedValueLetters: "l",
389454
+ bannerLetters: "vh",
389455
+ interactiveLetters: "i",
389456
+ stdinWhenUnnamed: !0
389457
+ }, TCL_INLINE = { ...BLANK_INLINE, stdinWhenUnnamed: !0 }, EXPECT_INLINE = {
389458
+ ...BLANK_INLINE,
389459
+ textLetters: "c",
389460
+ separatedValueLetters: "Db",
389461
+ plainLetters: "dN",
389462
+ bannerLetters: "vh",
389463
+ interactiveLetters: "i",
389464
+ stdinWhenUnnamed: !0
389465
+ }, AWK_INLINE = {
389466
+ ...BLANK_INLINE,
389467
+ longText: /* @__PURE__ */ new Set(["--source"]),
389468
+ textLetters: "e",
389469
+ longFile: /* @__PURE__ */ new Set(["--file", "--exec"]),
389470
+ fileLetters: "fE",
389471
+ separatedValueLetters: "vF",
389472
+ bannerLetters: "V",
389473
+ programOperand: { at: 0, isText: !0 },
389474
+ stdinWhenUnnamed: !1
389475
+ }, JQ_INLINE = {
389476
+ ...BLANK_INLINE,
389477
+ longFile: /* @__PURE__ */ new Set(["--from-file"]),
389478
+ fileLetters: "f",
389479
+ separatedValueLetters: "L",
389480
+ plainLetters: "nrjcsSaCMRe",
389481
+ bannerLetters: "h",
389482
+ programOperand: { at: 0, isText: !0 },
389483
+ stdinWhenUnnamed: !1
389484
+ }, BC_INLINE = {
389485
+ ...BLANK_INLINE,
389486
+ longText: /* @__PURE__ */ new Set(["--expression"]),
389487
+ textLetters: "e",
389488
+ plainLetters: "lqsw",
389489
+ bannerLetters: "vh",
389490
+ interactiveLetters: "i",
389491
+ programOperand: void 0,
389492
+ stdinWhenUnnamed: !0
389493
+ }, DC_INLINE = {
389494
+ ...BLANK_INLINE,
389495
+ longText: /* @__PURE__ */ new Set(["--expression"]),
389496
+ textLetters: "e",
389497
+ longFile: /* @__PURE__ */ new Set(["--file"]),
389498
+ fileLetters: "f",
389499
+ bannerLetters: "hV",
389500
+ programOperand: void 0,
389501
+ stdinWhenUnnamed: !0
389502
+ }, SQLITE_INLINE = {
389503
+ ...BLANK_INLINE,
389504
+ longText: /* @__PURE__ */ new Set(["-cmd"]),
389505
+ longSupplemental: /* @__PURE__ */ new Set(["-init"]),
389506
+ programOperand: { at: 1, isText: !0 },
389507
+ stdinWhenUnnamed: !0
389508
+ }, PSQL_INLINE = {
389509
+ ...BLANK_INLINE,
389510
+ longText: /* @__PURE__ */ new Set(["--command"]),
389511
+ textLetters: "c",
389512
+ longFile: /* @__PURE__ */ new Set(["--file"]),
389513
+ fileLetters: "f",
389514
+ separatedValueLetters: "hpUdoF",
389515
+ plainLetters: "aeEqtxXwW",
389516
+ bannerLetters: "lV?",
389517
+ programOperand: void 0,
389518
+ stdinWhenUnnamed: !0
389519
+ }, OSASCRIPT_INLINE = {
389520
+ ...BLANK_INLINE,
389521
+ textLetters: "e",
389522
+ separatedValueLetters: "ls",
389523
+ plainLetters: "i",
389524
+ bannerLetters: "h",
389525
+ stdinWhenUnnamed: !0
389526
+ }, RSCRIPT_INLINE = {
389527
+ ...BLANK_INLINE,
389528
+ textLetters: "e",
389529
+ bannerLetters: "h",
389530
+ stdinWhenUnnamed: !1
389531
+ }, JULIA_INLINE = {
389532
+ ...BLANK_INLINE,
389533
+ longText: /* @__PURE__ */ new Set(["--eval", "--print"]),
389534
+ textLetters: "eE",
389535
+ separatedValueLetters: "JLp",
389536
+ plainLetters: "q",
389537
+ bannerLetters: "vh",
389538
+ interactiveLetters: "i",
389539
+ stdinWhenUnnamed: !0
389540
+ }, GHCI_INLINE = {
389541
+ ...BLANK_INLINE,
389542
+ textLetters: "e",
389543
+ separatedValueLetters: "io",
389544
+ programOperand: void 0,
389545
+ stdinWhenUnnamed: !0
389546
+ }, GROOVY_INLINE = {
389547
+ ...BLANK_INLINE,
389548
+ textLetters: "e",
389549
+ separatedValueLetters: "Dcl",
389550
+ plainLetters: "n",
389551
+ bannerLetters: "vh",
389552
+ interactiveLetters: "i",
389553
+ stdinWhenUnnamed: !1
389554
+ }, BUN_INLINE = {
389555
+ ...BLANK_INLINE,
389556
+ longText: /* @__PURE__ */ new Set(["--eval", "--print"]),
389557
+ textLetters: "ep",
389558
+ separatedValueLetters: "r",
389559
+ bannerLetters: "vh",
389560
+ stdinWhenUnnamed: !1
389561
+ };
389248
389562
  }
389249
389563
  });
389250
389564
 
@@ -401635,7 +401949,8 @@ async function durableCancelAttempt(router, taskId) {
401635
401949
  })
401636
401950
  ]);
401637
401951
  } catch (e) {
401638
- throw !deadlineHit && isDefiniteCancelRefusal(e) && restoreTerminationIntentIf(taskId, durableVersion, beforeAttempt), e;
401952
+ let safetyCode = controlSafetyCodeOf(e);
401953
+ throw safetyCode !== void 0 && semaDebugLine(`[sema][seamQuery] durable cancel refused \xB7 ${controlSafetyNote(safetyCode)}`), !deadlineHit && isDefiniteCancelRefusal(e) && restoreTerminationIntentIf(taskId, durableVersion, beforeAttempt), e;
401639
401954
  } finally {
401640
401955
  deadlineTimer !== void 0 && clearTimeout(deadlineTimer);
401641
401956
  }
@@ -401920,6 +402235,7 @@ function resumeRunningArmWiring() {
401920
402235
  var BG_TEAR_MAX_RESENDS, BG_RECOVERY_WAIT_MS, DRAINING_MAX_RETRIES, drainingBackoffMs, client, clientExplicitlySet, seamSettings, seamSettingsLastGood, seamSettingsLastGoodSet, printResolvedSettingsProvider, seamWebSearch, seamSkills, seamMcp, seamRewindCapture, seamPendingRewind, INTERRUPT_WIRE_MARKER, seamHistorySeedPending, seamSandbox, seamAutoSandboxInjected, semaAutoResumeStore, HISTORY_SEED_MAX_CHARS, SCENARIO_KEYS, API_ERROR_PREFIX, defaultGatePrompt, canUseTool, durableCancelInFlight, foregroundInteractiveRunId, foregroundInteractiveRunChanged, subscribeToForegroundInteractiveRun, foregroundInteractiveDetachArmed, escCancelInFlight, ESC_CANCEL_TIMEOUT_MS, escCancelTimeoutOverrideMs, RUN_PROBE_TIMEOUT_MS, init_seamQuery = __esm({
401921
402236
  "build-src/src/sema/seamQuery.ts"() {
401922
402237
  init_debugLine();
402238
+ init_controlSafetyAdvice();
401923
402239
  init_hotReconcile();
401924
402240
  init_selfOrchestrationDenial2();
401925
402241
  init_adapter();
@@ -432049,21 +432365,19 @@ var sema_brand_default, init_sema_brand = __esm({
432049
432365
  _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"
432050
432366
  },
432051
432367
  whatsNew: {
432052
- version: "1.0.112",
432368
+ version: "1.0.113",
432053
432369
  notes: [
432054
- "The bundled engine moves from 7.75.3 to 7.75.4 (core 7.17.5 to 7.17.6). The shell itself is unchanged in this release; the client SDK stays at 9.3.0 and the shared client runtime at 0.68.0.",
432055
- "Read these next three together with one precondition: the execute-time recheck they describe runs only where the deployment has pinned the read roots (`READ_FACE=roots`, or `engineReadFace` in your settings). With no configuration at all the engine reports an open read face and the recheck does not run, so these three change nothing for a default single-machine setup. `sema doctor` states the engine's read-boundary posture in the engine's own words.",
432056
- "Security, where read roots are pinned: a shell read that only leaves the roots once the filesystem resolves it is now refused before the command runs. Previously the check was skipped on the lane sema itself uses to run the engine, so reading through a link pointing outside the roots succeeded with no prompt. It now comes back as a failed tool call naming the resolved path and the directories that are allowed. Upgrading is recommended.",
432057
- "The same refusal now also covers what a glob expands to: `cat vendor/*` is refused when a match resolves outside the roots, as is a pattern the engine cannot enumerate (an unreadable directory, or one matching more than 256 directories). As the engine reports plainly, this also refuses `ls -d .*` and `cat .*`, because `.*` includes the parent of the root.",
432058
- "A `..` written after a link is now judged where the kernel actually lands: `cat link/../file` is refused when the link's target sits outside the roots, even though the path reads as if it stayed inside. A `..` that stays inside is unchanged.",
432059
- "These three are refusals, not questions: they happen after the approval step, so a deployment with no approver sees them refused rather than asked. The refusal message states the fix: declare the link's target as a read root. A deployment that declares its execution environment as isolated skips the check entirely.",
432060
- "Separately, and with no read-face precondition: `sed` is now judged by what its script does, not only by its flags. A script that names a file or runs a command (`r`, `R`, `w`, `W`, `e`, `s///w FILE`, `s///e`) or a script read from a file (`-f FILE`, `--file=`) asks once before the command would run, the request cannot be cleared by an allow rule, and the command does not execute. Plain `sed -i`, `s///` and `sed -n '1,10p'` are unchanged. `env -- <program>` and `coproc <command>` are handled the same way. Widening the read roots does not clear this one.",
432061
- "For deployments that keep the engine's control directory and its memory directory on two different mounts: a delegated memory hold is no longer quarantined as polluted when the two cannot be renamed across. Single-mount setups are unchanged, and notes already sitting in quarantine are not brought back automatically.",
432062
- "Known limitation, stated plainly: the shell read boundary is a friction floor at the text level, not containment. It does not model a file read written inside an inline interpreter script (`perl -e`, `ruby -e`, a script piped to `tclsh`), and `time -p` in front of a command can defeat the check for programs invoked through `xargs`. If a task is not trusted, run it in a sandboxed execution environment rather than relying on this floor."
432370
+ "A model answer that quotes a credential now reaches your screen in its redacted form. The engine sends a redacted authoritative copy of each finished passage, and the shell now re-renders the live text from it instead of leaving the character-by-character stream on screen.",
432371
+ "When part of such a passage was already committed above and the engine's redacted copy no longer matches it, the shell now says so in one line \u2014 it names that the copy above may still hold the raw text and that the authoritative version is on the engine. Previously it said nothing at all.",
432372
+ "When a deployment's submit gate blocks something you typed, the line you get now says the three things that matter: it was not accepted, a submit gate blocked it, and editing the content and sending again is the way forward \u2014 it is no longer worded as a duplicate submission or as a content violation.",
432373
+ "The bundled engine moves to 7.76.1 and its read-boundary rules to 7.17.7: passing a program inline to an interpreter (perl -e, python3 -c, node -e, php -r, an awk program, a jq filter, SQL after a database name), starting a bare interpreter that would read its program from standard input, `time -p xargs cat <<< <path>`, and `busybox sh -c ...` now ask for approval instead of running straight through.",
432374
+ "Unchanged by that: running a program from a file. `awk -f prog.awk`, `jq -f filter.jq`, `perl script.pl`, `node app.js`, `python3 -m pytest`, `node --version`, `time -p ls` and `busybox cat f` behave exactly as before. On a setup with nobody to approve, the first group is refused, so move the program into a file if you need it to run unattended.",
432375
+ "Waking a long session is faster on MySQL-protocol and TiDB stores: the engine now pins the query plan for reading a session's newest events instead of letting stale table statistics pick a full-session scan.",
432376
+ "/doctor and the engine line report 7.76.1 so you can confirm which engine you are actually talking to."
432063
432377
  ]
432064
432378
  },
432065
- productVersion: "1.0.112",
432066
- announcement: "sema 1.0.112 \u2014 engine pickup only: bundled engine 7.75.4 (core 7.17.6); the shell, client SDK 9.3.0 and client runtime 0.68.0 are unchanged. Security, for deployments that pin read roots: shell reads that only escape the roots once resolved (a link target, a glob match, a `..` after a link) are now refused before the command runs, on every lane including the default host lane. `sed` scripts that name a file or run a command are judged as scripts. Known limitation: inline interpreter scripts (perl -e, ruby -e) are not modelled yet.",
432379
+ productVersion: "1.0.113",
432380
+ announcement: "sema 1.0.113 \u2014 engine pickup + redaction on screen: bundled engine 7.76.1 (core 7.17.7), client runtime 0.68.1, client SDK 9.3.0. A model answer that quotes a credential now reaches the screen in the engine's redacted form; where an earlier part of the passage was already committed, the shell says so in one line instead of staying silent. A message refused by a deployment's prompt hook now explains itself and what to do next. Interpreter one-liners (perl -e, ruby -e, time -p xargs, busybox sh -c) are now judged as programs by the read boundary.",
432067
432381
  version: "1.0.91"
432068
432382
  };
432069
432383
  }
@@ -436396,21 +436710,19 @@ var require_sema_brand = __commonJS({
436396
436710
  _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"
436397
436711
  },
436398
436712
  whatsNew: {
436399
- version: "1.0.112",
436713
+ version: "1.0.113",
436400
436714
  notes: [
436401
- "The bundled engine moves from 7.75.3 to 7.75.4 (core 7.17.5 to 7.17.6). The shell itself is unchanged in this release; the client SDK stays at 9.3.0 and the shared client runtime at 0.68.0.",
436402
- "Read these next three together with one precondition: the execute-time recheck they describe runs only where the deployment has pinned the read roots (`READ_FACE=roots`, or `engineReadFace` in your settings). With no configuration at all the engine reports an open read face and the recheck does not run, so these three change nothing for a default single-machine setup. `sema doctor` states the engine's read-boundary posture in the engine's own words.",
436403
- "Security, where read roots are pinned: a shell read that only leaves the roots once the filesystem resolves it is now refused before the command runs. Previously the check was skipped on the lane sema itself uses to run the engine, so reading through a link pointing outside the roots succeeded with no prompt. It now comes back as a failed tool call naming the resolved path and the directories that are allowed. Upgrading is recommended.",
436404
- "The same refusal now also covers what a glob expands to: `cat vendor/*` is refused when a match resolves outside the roots, as is a pattern the engine cannot enumerate (an unreadable directory, or one matching more than 256 directories). As the engine reports plainly, this also refuses `ls -d .*` and `cat .*`, because `.*` includes the parent of the root.",
436405
- "A `..` written after a link is now judged where the kernel actually lands: `cat link/../file` is refused when the link's target sits outside the roots, even though the path reads as if it stayed inside. A `..` that stays inside is unchanged.",
436406
- "These three are refusals, not questions: they happen after the approval step, so a deployment with no approver sees them refused rather than asked. The refusal message states the fix: declare the link's target as a read root. A deployment that declares its execution environment as isolated skips the check entirely.",
436407
- "Separately, and with no read-face precondition: `sed` is now judged by what its script does, not only by its flags. A script that names a file or runs a command (`r`, `R`, `w`, `W`, `e`, `s///w FILE`, `s///e`) or a script read from a file (`-f FILE`, `--file=`) asks once before the command would run, the request cannot be cleared by an allow rule, and the command does not execute. Plain `sed -i`, `s///` and `sed -n '1,10p'` are unchanged. `env -- <program>` and `coproc <command>` are handled the same way. Widening the read roots does not clear this one.",
436408
- "For deployments that keep the engine's control directory and its memory directory on two different mounts: a delegated memory hold is no longer quarantined as polluted when the two cannot be renamed across. Single-mount setups are unchanged, and notes already sitting in quarantine are not brought back automatically.",
436409
- "Known limitation, stated plainly: the shell read boundary is a friction floor at the text level, not containment. It does not model a file read written inside an inline interpreter script (`perl -e`, `ruby -e`, a script piped to `tclsh`), and `time -p` in front of a command can defeat the check for programs invoked through `xargs`. If a task is not trusted, run it in a sandboxed execution environment rather than relying on this floor."
436715
+ "A model answer that quotes a credential now reaches your screen in its redacted form. The engine sends a redacted authoritative copy of each finished passage, and the shell now re-renders the live text from it instead of leaving the character-by-character stream on screen.",
436716
+ "When part of such a passage was already committed above and the engine's redacted copy no longer matches it, the shell now says so in one line \u2014 it names that the copy above may still hold the raw text and that the authoritative version is on the engine. Previously it said nothing at all.",
436717
+ "When a deployment's submit gate blocks something you typed, the line you get now says the three things that matter: it was not accepted, a submit gate blocked it, and editing the content and sending again is the way forward \u2014 it is no longer worded as a duplicate submission or as a content violation.",
436718
+ "The bundled engine moves to 7.76.1 and its read-boundary rules to 7.17.7: passing a program inline to an interpreter (perl -e, python3 -c, node -e, php -r, an awk program, a jq filter, SQL after a database name), starting a bare interpreter that would read its program from standard input, `time -p xargs cat <<< <path>`, and `busybox sh -c ...` now ask for approval instead of running straight through.",
436719
+ "Unchanged by that: running a program from a file. `awk -f prog.awk`, `jq -f filter.jq`, `perl script.pl`, `node app.js`, `python3 -m pytest`, `node --version`, `time -p ls` and `busybox cat f` behave exactly as before. On a setup with nobody to approve, the first group is refused, so move the program into a file if you need it to run unattended.",
436720
+ "Waking a long session is faster on MySQL-protocol and TiDB stores: the engine now pins the query plan for reading a session's newest events instead of letting stale table statistics pick a full-session scan.",
436721
+ "/doctor and the engine line report 7.76.1 so you can confirm which engine you are actually talking to."
436410
436722
  ]
436411
436723
  },
436412
- productVersion: "1.0.112",
436413
- announcement: "sema 1.0.112 \u2014 engine pickup only: bundled engine 7.75.4 (core 7.17.6); the shell, client SDK 9.3.0 and client runtime 0.68.0 are unchanged. Security, for deployments that pin read roots: shell reads that only escape the roots once resolved (a link target, a glob match, a `..` after a link) are now refused before the command runs, on every lane including the default host lane. `sed` scripts that name a file or run a command are judged as scripts. Known limitation: inline interpreter scripts (perl -e, ruby -e) are not modelled yet.",
436724
+ productVersion: "1.0.113",
436725
+ announcement: "sema 1.0.113 \u2014 engine pickup + redaction on screen: bundled engine 7.76.1 (core 7.17.7), client runtime 0.68.1, client SDK 9.3.0. A model answer that quotes a credential now reaches the screen in the engine's redacted form; where an earlier part of the passage was already committed, the shell says so in one line instead of staying silent. A message refused by a deployment's prompt hook now explains itself and what to do next. Interpreter one-liners (perl -e, ruby -e, time -p xargs, busybox sh -c) are now judged as programs by the read boundary.",
436414
436726
  version: "1.0.91"
436415
436727
  };
436416
436728
  }
@@ -475277,8 +475589,18 @@ async function* sdkMessagesToCcEvents(sdk, meta3) {
475277
475589
  }
475278
475590
  case "text_segment_end": {
475279
475591
  textSegmentEndSeen++;
475280
- let authoritative = e.content, blocks = liveSegmentBlocks, truncated = segmentTruncated, stitchedLen = liveSegmentLen, stitched = liveSegmentText;
475281
- if (liveSegmentText = "", liveSegmentLen = 0, liveSegmentBlocks = 0, segmentTruncated = !1, !process.env.SEMA_DEBUG) return [];
475592
+ let authoritative = e.content, blocks = liveSegmentBlocks, truncated = segmentTruncated, stitchedLen = liveSegmentLen, stitched = liveSegmentText, out6 = [], divergedLive = e.diverged === !0, committedStale = e.committedPrefixDiverged === !0, prefixLen = typeof e.committedPrefixLen == "number" && Number.isInteger(e.committedPrefixLen) && e.committedPrefixLen > 0 ? e.committedPrefixLen : 0;
475593
+ if (liveSegmentText = "", liveSegmentLen = 0, liveSegmentBlocks = 0, segmentTruncated = !1, divergedLive || committedStale) {
475594
+ let liveTail = committedStale ? "" : authoritative.slice(prefixLen);
475595
+ textBlockIndex = nextBlockIndex++, out6.push(
475596
+ streamEvt({ type: "content_block_start", index: textBlockIndex, content_block: { type: "text", text: "" } })
475597
+ ), liveTail.length > 0 && out6.push(
475598
+ streamEvt({ type: "content_block_delta", index: textBlockIndex, delta: { type: "text_delta", text: liveTail } })
475599
+ );
475600
+ }
475601
+ if (committedStale && (surfaceTranscriptSystemNotice(committedPrefixUnretractableRow(), "warning"), logForDebugging(
475602
+ `[sema][bridge] text_segment_end committedPrefixDiverged (disclosed, not substituted; L-312): prefixLen=${String(prefixLen)} authoritativeLen=${String(authoritative.length)}`
475603
+ )), !process.env.SEMA_DEBUG) return out6;
475282
475604
  try {
475283
475605
  let verdict = stitchedLen === 0 ? "no-live-material" : truncated ? stitchedLen === authoritative.length ? "length-only-match" : "length-only-mismatch" : stitched === authoritative ? "match" : "mismatch", id = wireIdentity(e.eventId);
475284
475606
  semaDebugLine(
@@ -475287,7 +475609,7 @@ async function* sdkMessagesToCcEvents(sdk, meta3) {
475287
475609
  } catch (err8) {
475288
475610
  logForDebugging(`[sema][bridge] text_segment_end reconcile failed (non-fatal): ${String(err8)}`);
475289
475611
  }
475290
- return [];
475612
+ return out6;
475291
475613
  }
475292
475614
  // 🔴 `tasks_expand`:本通道**今天**无对位面(ctrl+t 面板的展开态由 `task_ledger_sync` 供给,
475293
475615
  // adapt() 现不发这一臂)。但它仍然是一条**显式臂**,不靠豁免表放行 ——
@@ -502463,7 +502785,7 @@ function refusalKind(err8) {
502463
502785
  return code2 !== void 0 || status3 !== void 0 ? `engine refused: ${code2 ?? ""}${code2 !== void 0 && status3 !== void 0 ? " " : ""}${status3 ?? ""}`.trim() : "outcome UNKNOWN (no status \u2014 the engine may or may not have taken it; steer is at-most-once and is never retried)";
502464
502786
  }
502465
502787
  function blockedByHookNoticeLine(err8) {
502466
- let raw2 = err8?.message, why = cleanUntrustedForDisplay(typeof raw2 == "string" ? raw2 : "", STEER_BLOCKED_REASON_MAX), head = "That message was not accepted \u2014 a deployment prompt hook blocked it, so nothing was delivered to the model", tail = "it stays queued and will be submitted as-is when this turn ends \u2014 press Up to edit it first.";
502788
+ let raw2 = err8?.message, why = cleanUntrustedForDisplay(typeof raw2 == "string" ? raw2 : "", STEER_BLOCKED_REASON_MAX), headline = controlSafetyAdvice("blocked_by_hook").headline, head = headline.charAt(0).toUpperCase() + headline.slice(1), tail = "it stays queued and will be submitted as-is when this turn ends \u2014 press Up to edit it first.";
502467
502789
  return why.length > 0 ? `${head} (${why}) \u2014 ${tail}` : `${head} \u2014 ${tail}`;
502468
502790
  }
502469
502791
  async function absorbQueuedPromptsViaSteer(deps2) {
@@ -502559,6 +502881,7 @@ var absorbing, host, STEERING_BLOCKED_BY_HOOK_CODE, STEER_BLOCKED_REASON_MAX, in
502559
502881
  init_debug();
502560
502882
  init_transcriptSystemNotice();
502561
502883
  init_untrustedDisplayText();
502884
+ init_controlSafetyAdvice();
502562
502885
  init_messageQueueManager();
502563
502886
  absorbing = !1, host = {};
502564
502887
  STEERING_BLOCKED_BY_HOOK_CODE = "steering.blocked_by_hook", STEER_BLOCKED_REASON_MAX = 400;
@@ -554128,7 +554451,7 @@ Usage: sema --remote "your task description"`, () => gracefulShutdown(1));
554128
554451
  pendingHookMessages
554129
554452
  }, renderAndRun);
554130
554453
  }
554131
- }).version("sema 1.0.112", "-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 () => {
554454
+ }).version("sema 1.0.113", "-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 () => {
554132
554455
  await (await Promise.resolve().then(() => (init_bg2(), bg_exports))).psHandler([]), process.exit(process.exitCode ?? 0);
554133
554456
  }), program2.command("logs [id]").description("Print a background session's recent terminal output").action(async (id) => {
554134
554457
  await (await Promise.resolve().then(() => (init_bg2(), bg_exports))).logsHandler(id, []), process.exit(process.exitCode ?? 0);
package/sema.js CHANGED
@@ -80,7 +80,7 @@ function installBootSignalTailFrame(argv2 = process.argv.slice(2)) {
80
80
  installBootSignalTailFrame();
81
81
 
82
82
  // build-src/src/sema/preludeEntry.ts
83
- var versionLine = "sema 1.0.112" ? "sema 1.0.112" : "";
83
+ var versionLine = "sema 1.0.113" ? "sema 1.0.113" : "";
84
84
  var argv = process.argv.slice(2);
85
85
  var wantsVersionFastPath = argv.length === 1 && (argv[0] === "--version" || argv[0] === "-v");
86
86
  var EARLY_INPUT_PRELUDE_SLOT = /* @__PURE__ */ Symbol.for("sema.earlyInputPrelude");