@sema-agent/client-core 0.108.0 → 0.110.0

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.
Files changed (179) hide show
  1. package/CHANGELOG.md +294 -0
  2. package/README.md +77 -40
  3. package/dist/adapt/arms.js +41 -13
  4. package/dist/adapt/textStream.d.ts +2 -0
  5. package/dist/adapt/textStream.js +37 -16
  6. package/dist/adapter/activeRunSelfHeal.js +1 -1
  7. package/dist/adapter/downstream/eventToSdkMessage.js +11 -5
  8. package/dist/agentSession/engineAgentRegistryRead.js +2 -0
  9. package/dist/bashExitReading.d.ts +12 -0
  10. package/dist/bashExitReading.js +44 -0
  11. package/dist/checkpointRowVerdict.d.ts +1 -1
  12. package/dist/checkpointRowVerdict.js +4 -2
  13. package/dist/compensations.js +1 -1
  14. package/dist/declared/supportFloorDeclared.js +1 -1
  15. package/dist/displayUntrusted.js +132 -14
  16. package/dist/engineAgentAbsence.d.ts +2 -0
  17. package/dist/engineAgentAbsence.js +28 -0
  18. package/dist/engineErrorCodes.d.ts +7 -0
  19. package/dist/engineErrorCodes.js +7 -0
  20. package/dist/engineHealthFacts.d.ts +26 -0
  21. package/dist/engineHealthFacts.js +63 -4
  22. package/dist/engineInlineTaskStats.d.ts +4 -3
  23. package/dist/engineInlineTaskStats.js +18 -2
  24. package/dist/engineNoticeCodes.d.ts +138 -0
  25. package/dist/engineNoticeCodes.js +662 -55
  26. package/dist/engineRepoint.d.ts +140 -0
  27. package/dist/engineRepoint.js +285 -0
  28. package/dist/engineRowRef.js +2 -0
  29. package/dist/engineSessionMessages.d.ts +2 -1
  30. package/dist/engineSessionMessages.js +5 -0
  31. package/dist/errorSupplementRoles.js +5 -1
  32. package/dist/fleet/fleetProjection.js +3 -2
  33. package/dist/fleetTaskDesc.js +3 -3
  34. package/dist/generated/engineFactTables.d.ts +3 -0
  35. package/dist/generated/engineFactTables.js +18 -0
  36. package/dist/generated/engineNoticeTables.js +3 -0
  37. package/dist/generated/sdkFactTables.d.ts +1 -0
  38. package/dist/generated/sdkFactTables.js +4 -0
  39. package/dist/hitl/approvalAskers.d.ts +6 -0
  40. package/dist/hitl/approvalAskers.js +30 -0
  41. package/dist/hitl/approvalCardReasons.js +25 -4
  42. package/dist/hitl/approvalRequestFrameReading.d.ts +21 -0
  43. package/dist/hitl/approvalRequestFrameReading.js +90 -0
  44. package/dist/hitl/approvalResolution.d.ts +8 -1
  45. package/dist/hitl/approvalResolution.js +4 -0
  46. package/dist/hitl/approvalsFeed.js +1 -1
  47. package/dist/hitl/askGateWire.js +0 -2
  48. package/dist/hitl/askParkRowRouting.js +5 -2
  49. package/dist/hitl/automaticAnswerVerdict.d.ts +5 -2
  50. package/dist/hitl/automaticAnswerVerdict.js +18 -4
  51. package/dist/hitl/decisionConflict.d.ts +2 -1
  52. package/dist/hitl/decisionConflict.js +10 -4
  53. package/dist/hitl/decisionRefusal.js +1 -0
  54. package/dist/hitl/decisionSend.d.ts +3 -0
  55. package/dist/hitl/decisionSend.js +29 -11
  56. package/dist/hitl/editedApprovalAcceptance.d.ts +25 -0
  57. package/dist/hitl/editedApprovalAcceptance.js +26 -0
  58. package/dist/hitl/frameRouter.js +13 -19
  59. package/dist/hitl/gateLedger.d.ts +0 -4
  60. package/dist/hitl/gateLedger.js +0 -19
  61. package/dist/hitl/hitlBridge.d.ts +5 -0
  62. package/dist/hitl/hitlBridge.js +13 -9
  63. package/dist/hitl/hitlHostSurface.d.ts +1 -0
  64. package/dist/hitl/hitlHostSurface.js +7 -2
  65. package/dist/hitl/hostWithdrawal.d.ts +15 -0
  66. package/dist/hitl/hostWithdrawal.js +38 -0
  67. package/dist/hitl/livePendingAsk.js +17 -16
  68. package/dist/hitl/localAllowRule.js +2 -1
  69. package/dist/hitl/noAllowCause.d.ts +1 -1
  70. package/dist/hitl/noAllowCause.js +4 -2
  71. package/dist/hitl/parkExpiryJudgements.js +26 -1
  72. package/dist/hitl/parkOwnership.d.ts +2 -0
  73. package/dist/hitl/parkOwnership.js +48 -8
  74. package/dist/hitl/parkResolver.js +32 -16
  75. package/dist/hitl/parkedUnresumable.d.ts +13 -0
  76. package/dist/hitl/parkedUnresumable.js +80 -0
  77. package/dist/hitl/permissionRuleScope.d.ts +4 -0
  78. package/dist/hitl/permissionRuleScope.js +31 -0
  79. package/dist/hitl/persistedRulesWire.d.ts +2 -0
  80. package/dist/hitl/persistedRulesWire.js +13 -12
  81. package/dist/hitl/planReviewWire.js +14 -4
  82. package/dist/hitl/sessionAllowRoute.js +5 -4
  83. package/dist/hitl/sessionPolicyWire.js +6 -4
  84. package/dist/hitl/standingRows.d.ts +2 -5
  85. package/dist/hitl/standingRows.js +30 -15
  86. package/dist/hitl/toolApprovalWire.d.ts +42 -9
  87. package/dist/hitl/toolApprovalWire.js +267 -44
  88. package/dist/hooksWireCaps.js +35 -4
  89. package/dist/hostSettingsSource.js +2 -0
  90. package/dist/hostTurnSettings.d.ts +10 -4
  91. package/dist/hostTurnSettings.js +112 -5
  92. package/dist/i18n/messages.en.d.ts +251 -0
  93. package/dist/i18n/messages.en.js +254 -2
  94. package/dist/i18n/messages.zh.js +264 -2
  95. package/dist/index.d.ts +48 -12
  96. package/dist/index.js +29 -7
  97. package/dist/inheritEnvCapability.js +2 -0
  98. package/dist/inputAuthor.d.ts +16 -0
  99. package/dist/inputAuthor.js +44 -0
  100. package/dist/interruptRefusalNote.d.ts +2 -0
  101. package/dist/interruptRefusalNote.js +17 -0
  102. package/dist/liveModelCatalog.d.ts +2 -0
  103. package/dist/liveModelCatalog.js +21 -7
  104. package/dist/liveQuestionStore.d.ts +4 -1
  105. package/dist/liveQuestionStore.js +12 -3
  106. package/dist/localEngineJudge.d.ts +75 -0
  107. package/dist/localEngineJudge.js +242 -0
  108. package/dist/localEngineOccupancy.d.ts +88 -0
  109. package/dist/localEngineOccupancy.js +269 -0
  110. package/dist/localEngineSeatReading.d.ts +29 -0
  111. package/dist/localEngineSeatReading.js +294 -0
  112. package/dist/localEngineSpawn.d.ts +113 -0
  113. package/dist/localEngineSpawn.js +486 -0
  114. package/dist/localEngineStep.d.ts +286 -0
  115. package/dist/localEngineStep.js +1086 -0
  116. package/dist/localEngineStopLadder.d.ts +29 -0
  117. package/dist/localEngineStopLadder.js +139 -0
  118. package/dist/localEngineSwapCard.d.ts +43 -0
  119. package/dist/localEngineSwapCard.js +205 -0
  120. package/dist/localEngineTiming.d.ts +8 -0
  121. package/dist/localEngineTiming.js +8 -0
  122. package/dist/mcpEngineLeg.d.ts +3 -0
  123. package/dist/mcpEngineLeg.js +38 -1
  124. package/dist/mcpPanel.js +2 -0
  125. package/dist/mcpReconnect.d.ts +9 -1
  126. package/dist/mcpReconnect.js +132 -20
  127. package/dist/mcpWireCaps.js +2 -2
  128. package/dist/memoryEntriesWire.d.ts +1 -1
  129. package/dist/memoryEntriesWire.js +5 -0
  130. package/dist/modelCapabilityProbe.js +4 -3
  131. package/dist/modsFace.d.ts +8 -1
  132. package/dist/modsFace.js +27 -0
  133. package/dist/noticePresentation.d.ts +2 -0
  134. package/dist/noticePresentation.js +79 -1
  135. package/dist/notifications.d.ts +17 -6
  136. package/dist/notifications.js +67 -19
  137. package/dist/ownKey.d.ts +5 -0
  138. package/dist/ownKey.js +8 -1
  139. package/dist/peerFrames.d.ts +40 -2
  140. package/dist/peerFrames.js +158 -3
  141. package/dist/pluginHooksWire.d.ts +2 -1
  142. package/dist/pluginHooksWire.js +56 -1
  143. package/dist/replayBody.js +10 -2
  144. package/dist/request/taskRequest.d.ts +5 -0
  145. package/dist/request/taskRequest.js +138 -21
  146. package/dist/resumeRefusalCopy.d.ts +1 -3
  147. package/dist/resumeRefusalCopy.js +2 -1
  148. package/dist/retryStatus.d.ts +2 -2
  149. package/dist/retryStatus.js +2 -0
  150. package/dist/ruleReadings.js +1 -1
  151. package/dist/seam.d.ts +24 -2
  152. package/dist/seam.js +15 -2
  153. package/dist/seatContract.d.ts +125 -10
  154. package/dist/seatContract.js +373 -7
  155. package/dist/sessionBackground.js +4 -1
  156. package/dist/sessionBackgroundHandoff.js +2 -1
  157. package/dist/sessionEngine.d.ts +2 -0
  158. package/dist/sessionEngine.js +111 -0
  159. package/dist/sessionMemoryStatus.d.ts +2 -1
  160. package/dist/sessionSyncFileHistory.d.ts +4 -0
  161. package/dist/sessionSyncFileHistory.js +28 -0
  162. package/dist/sseIdleTriage.d.ts +13 -1
  163. package/dist/sseIdleTriage.js +24 -6
  164. package/dist/subagent/engineSubagentTail.js +6 -0
  165. package/dist/subagentContentStore.d.ts +12 -0
  166. package/dist/subagentContentStore.js +72 -11
  167. package/dist/terminalStatuses.d.ts +1 -0
  168. package/dist/terminalStatuses.js +4 -1
  169. package/dist/toolResult.js +18 -5
  170. package/dist/turnFailurePresentation.js +9 -2
  171. package/dist/typePins.d.ts +11 -0
  172. package/dist/usageAnalytics.d.ts +17 -0
  173. package/dist/usageAnalytics.js +44 -2
  174. package/dist/wireFailureShape.d.ts +22 -5
  175. package/dist/wireFailureShape.js +47 -26
  176. package/dist/wireRefusalCopy.d.ts +31 -1
  177. package/dist/wireRefusalCopy.js +167 -2
  178. package/docs/INTEGRATION-CLIENTS.md +3269 -21
  179. package/package.json +5 -5
@@ -1,13 +1,13 @@
1
1
  import { APPROVAL_CARD_PORT_KEY_MISMATCH_REASON, DEFAULT_DENY_REASON, HitlBridge, NO_APPROVAL_CARD_PORT_REASON, denyReasonForWire, findPendingForTask, readWireErrorCodeReading, } from './hitlBridge.js';
2
2
  import { askParkRowArm } from './askParkRowRouting.js';
3
3
  import { parkGateArmOf } from './frameRouter.js';
4
- import { seatSessionRowOf } from './standingRows.js';
4
+ import { seatAllowNoteCarriedOf, seatSessionRowOf } from './standingRows.js';
5
5
  import { hostLog } from '../host.js';
6
6
  import { trimEditedRuleText } from './editedRuleTextPrecheck.js';
7
7
  import { appendOwnElement, guardedRead, readAskOrigin, readOwnDataNonEmptyString, readOwnDataValue, readOwnNonEmptyString } from '../ownKey.js';
8
8
  import { ownReadingSlot } from '../engineWireFor.js';
9
9
  import { DEPLOYMENT_LIST_ASK_CLASSES, readAskClassPair } from './askClassPair.js';
10
- import { approvalAgentIdOf, approvalAskReasonsOf } from './approvalAskers.js';
10
+ import { approvalAgentIdOf, approvalAskReasonsOf, approvalRequestedByOf } from './approvalAskers.js';
11
11
  import { invokeHostCallbackIsolated } from '../hostCallbackGuard.js';
12
12
  import { approvalWindowKeysOf, readApprovalCardWord, readRequiresRealApproval } from './approvalCardReading.js';
13
13
  import { readAllowRuleShadowFromWire, retiredAllowRuleShadowKeyPresent, RETIRED_SHADOW_EVIDENCE_LABEL } from './allowRuleShadow.js';
@@ -17,26 +17,29 @@ import { CORE_SKILL_TOOL_NAME } from '../generated/toolNameTables.js';
17
17
  import { CORE_ALLOW_ENTRY_INERT_REASONS, CORE_PERSISTED_RULE_MATCHES } from '../generated/engineFactTables.js';
18
18
  import { msg, renderMessage } from '../i18n/translate.js';
19
19
  import { sessionAllowCarried, sessionAllowEligible } from './sessionAllowRoute.js';
20
- import { INTERRUPT_DENY_REASON, observeCancelByDeny, surfaceApprovalParking, surfaceRememberNotApplied, surfaceEditNotForwarded, surfaceEditRefusedOnBlindAsk, surfaceRuleArmNotSent, surfaceRuleArmRejected } from './hitlHostSurface.js';
20
+ import { INTERRUPT_DENY_REASON, observeCancelByDeny, surfaceApprovalParking, surfaceAllowNoteNotCarried, surfaceRememberNotApplied, surfaceEditNotForwarded, surfaceEditRefusedOnBlindAsk, surfaceRuleArmNotSent, surfaceRuleArmRejected } from './hitlHostSurface.js';
21
21
  import { approvalCallKey, liveFrameCallKey } from './gateIdentity.js';
22
22
  import { displayUntrusted, quoteUntrustedForSentence } from '../displayUntrusted.js';
23
23
  import { frameBindingOf } from '../frameBinding.js';
24
24
  import { carriesAttributionKey, deliverWithAttributionLadder } from './attributionLadder.js';
25
25
  import { deliverApprovalDecision, newSendTally } from './approvalDelivery.js';
26
26
  import { approvalDecisionHolds, approvalHoldFor, awaitApprovalHolder, claimApprovalCardFor, enterLiveRespondPhase, holdLiveCard, joinLiveCard, liveCardHoldOf, clearSettledApprovals, noteHolderSettledApproval, settledApprovalOf, settledForDurableLane, settledLiveCardOutcome } from './approvalHolds.js';
27
- import { directFailureVerdictOf, directSafetyStopOf, joinedResolution, resolutionOfDecisionFailure } from './approvalResolution.js';
27
+ import { directFailureVerdictOf, directSafetyStopOf, joinedResolution, resolutionOfDecisionFailure, toolPermissionSettledElsewhereOf } from './approvalResolution.js';
28
+ import { hostWithdrawalOf } from './hostWithdrawal.js';
28
29
  import { parkRowDeadlineState } from './parkExpiryJudgements.js';
29
30
  import { isApprovalMandateWord } from '../gateVocabulary.js';
30
31
  import { approvalDecidedByAdmitted } from '../approvalDecidedByCapability.js';
31
32
  import { decideFailureNote } from '../decideFailureNote.js';
33
+ import { editedApprovalAcceptanceOf } from './editedApprovalAcceptance.js';
32
34
  import { readPolicyDenyCause } from './policyDenyCause.js';
33
- import { slotPresenceOf, wireFailureTextsOf } from '../wireFailureShape.js';
35
+ import { inValueOf, slotPresenceOf, slotReadOf, wireFailureTextsOf } from '../wireFailureShape.js';
34
36
  import { APPROVAL_LIVE_FACE_KEYS, approvalLiveFaceOf, hasOwnStrictTrue } from './approvalLiveFace.js';
37
+ import { approvalFrameUnreadableWhyOf, approvalRequestFrameReadingThrowing, cardPayloadReadingOf, } from './approvalRequestFrameReading.js';
35
38
  import { subagentSourceSessionOf } from './subagentSource.js';
36
39
  import { isPlainRecord } from '../jsonFaithful.js';
37
40
  import { DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED } from '../engineErrorCodes.js';
38
41
  import { readDecideReceipt } from '../decideReceipt.js';
39
- import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, ASK_ORIGINS, isApprovalRequestFrameV1, } from '@sema-agent/sdk';
42
+ import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, ASK_ORIGINS, } from '@sema-agent/sdk';
40
43
  export function toolNameIsFsWrite(name) {
41
44
  const n = name.replace(/[\s_-]+/g, '').toLowerCase();
42
45
  return (n === 'write' || n === 'filewrite' || n === 'edit' || n === 'fileedit' || n === 'multiedit' || n === 'notebookedit');
@@ -97,6 +100,16 @@ export function readApprovalDenySettledBy(decision) {
97
100
  : undefined;
98
101
  }
99
102
  export const RETRACTED_CARD_DECISION_KIND = 'retracted';
103
+ export const WITHDRAWN_CARD_DECISION_KIND = 'withdrawn';
104
+ function withdrawnCardResolution(card, at, logTag) {
105
+ const w = hostWithdrawalOf(card);
106
+ if (w === undefined) {
107
+ hostLog('debug', `${logTag}: card-withdrawn-unreadable as=retracted`);
108
+ return { kind: 'not_sent', ...at, cause: 'retracted' };
109
+ }
110
+ hostLog('debug', `${logTag}: card-withdrawn-by-host verdict=${w.rowVerdict.kind}`);
111
+ return { kind: 'not_sent', ...at, cause: 'withdrawn', toldBy: w.toldBy, rowVerdict: w.rowVerdict };
112
+ }
100
113
  function parkRowOf(taskId, row, gatedCallId) {
101
114
  const d = parkRowDeadlineState(row, Date.now());
102
115
  return Object.freeze({
@@ -173,6 +186,16 @@ export function rememberRefusalOf(error) {
173
186
  function rememberRefusalIn(reading) {
174
187
  return reading.state === 'code' ? REMEMBER_REFUSAL_CODES.find((c) => c === reading.code) : undefined;
175
188
  }
189
+ const FEEDBACK_REFUSAL_CODES = Object.freeze(['feedback_not_in_proof']);
190
+ function feedbackRefusalOf(error) {
191
+ const reading = readWireErrorCodeReading(error);
192
+ return reading.state === 'code' && FEEDBACK_REFUSAL_CODES.some((c) => c === reading.code);
193
+ }
194
+ function approveBodyWithoutFeedback(body) {
195
+ const { feedback: _feedback, ...rest } = body;
196
+ void _feedback;
197
+ return rest;
198
+ }
176
199
  function logAfterDecided(msg) {
177
200
  try {
178
201
  hostLog('debug', msg);
@@ -248,6 +271,14 @@ function cardInputOf(recorded, stream) {
248
271
  return { from: 'stream', args: stream, shape };
249
272
  return { from: 'none', shape, recorded };
250
273
  }
274
+ function inputSourceBitOf(reading) {
275
+ return reading.from === 'recorded' ? { inputSource: 'record' } : reading.from === 'stream' ? { inputSource: 'stream' } : {};
276
+ }
277
+ function approvalInputSourceOf(card) {
278
+ const raw = ownDataValue(card, 'inputSource');
279
+ const known = { record: true, stream: true };
280
+ return typeof raw === 'string' && Object.hasOwn(known, raw) ? raw : undefined;
281
+ }
251
282
  const CARD_ARGS_COMPARE_MAX_NODES = 20_000;
252
283
  const CARD_ARGS_COMPARE_MAX_DEPTH = 256;
253
284
  const NOT_COMPARABLE = Symbol('not comparable');
@@ -493,6 +524,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
493
524
  const rowArgsGap = reading.from !== 'none' ? undefined : reading.shape === 'absent' ? 'absent' : reading.shape === 'size_marker' ? 'truncated' : undefined;
494
525
  const args = reading.from !== 'none' ? reading.args : rowArgsGap !== undefined ? {} : reading.recorded;
495
526
  const argsRewritten = reading.from === 'recorded' && reading.rewritten;
527
+ const argsFromModelCall = reading.from === 'stream';
496
528
  if (typeof args !== 'object' || args === null) {
497
529
  return { kind: 'not_sent', ...at, cause: 'no_input', detail: 'gate has no tool input payload' };
498
530
  }
@@ -516,6 +548,8 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
516
548
  }
517
549
  : {}),
518
550
  ...(argsRewritten ? { argsRewritten: true, wireNote: ARGS_REWRITTEN_NOTE } : {}),
551
+ ...(argsFromModelCall ? { argsUnavailable: true, wireNote: renderMessage(msg('approval.park.argsFromModelCall')) } : {}),
552
+ ...inputSourceBitOf(reading),
519
553
  ...(pending.governanceForced === true ? { governanceForced: true } : {}),
520
554
  ...(readRequiresRealApproval(pending) ? { requiresRealApproval: true } : {}),
521
555
  ...approvalLiveFaceOf(pending).facts,
@@ -538,11 +572,13 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
538
572
  allowSessionCarried: true,
539
573
  grantBinding: readApprovalGrantBinding(pending),
540
574
  parkRow: parkRowOf(taskId, pending, gatedCallId),
575
+ ...(typeof taskId === 'string' && taskId !== '' ? { taskId } : {}),
541
576
  });
577
+ const editAcceptance = editedApprovalAcceptanceOf(cardRequest);
542
578
  const card = await surfaceCallTrackedCard(gatedCallId, undefined, ledgerSlot, cardRequest);
543
579
  hold.phase = 'respond';
544
- if (rowArgsGap !== undefined && card.kind === 'allow' && card.updatedInput !== undefined) {
545
- hostLog('error', `liveToolApprovalWire: approval card for ${gatedCallId ?? `task ${taskId}`} returned an edited approval, but the tool input is ${rowArgsGap === 'truncated' ? 'a size marker on the pending row' : 'missing from both the stream and the pending row'} — nothing sent (the park stays pending)`);
580
+ if (editAcceptance.state !== 'accepts' && card.kind === 'allow' && card.updatedInput !== undefined) {
581
+ hostLog('error', `liveToolApprovalWire: approval card for ${gatedCallId ?? `task ${taskId}`} returned an edited approval, but the tool input is ${rowArgsGap === 'truncated' ? 'a size marker on the pending row' : rowArgsGap === 'absent' ? 'missing from both the stream and the pending row' : 'not recorded on the pending row'} — nothing sent (the park stays pending)`);
546
582
  surfaceEditRefusedOnBlindAsk();
547
583
  return { kind: 'not_sent', ...at, cause: 'edit_refused', detail: PARK_EDIT_REFUSED_REASON };
548
584
  }
@@ -555,6 +591,8 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
555
591
  case 'retracted':
556
592
  hostLog('debug', `liveHitlAskWire: approval card retracted without a decision for ${gatedCallId ?? '(no call)'} — nothing sent`);
557
593
  return { kind: 'not_sent', ...at, cause: 'retracted' };
594
+ case WITHDRAWN_CARD_DECISION_KIND:
595
+ return withdrawnCardResolution(card, at, 'liveHitlAskWire');
558
596
  case 'aborted':
559
597
  {
560
598
  const cancelDeny = bridge.decideTool({ decision: 'deny', reason: INTERRUPT_DENY_REASON }, gatedCallId, undefined, pending);
@@ -575,11 +613,30 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
575
613
  const { remember: _remember, ...plainApproveBody } = approveBody;
576
614
  void _remember;
577
615
  emitAnswerCommitted(callKey, 'decide', answered, approveBody);
616
+ let feedbackDropped = false;
617
+ const sendApprove = async (body) => {
618
+ const wire = feedbackDropped ? approveBodyWithoutFeedback(body) : body;
619
+ try {
620
+ return await bridge.decideTool(wire, gatedCallId, decideOpts, pending);
621
+ }
622
+ catch (e) {
623
+ if (wire.feedback === undefined || !feedbackRefusalOf(e))
624
+ throw e;
625
+ const verdict = directFailureVerdictOf(e, directSafetyStopOf(e));
626
+ if (verdict.yields) {
627
+ rememberStop = ownReadingSlot(verdict, 'directStop');
628
+ throw e;
629
+ }
630
+ feedbackDropped = true;
631
+ logAfterDecided(`liveToolApprovalWire: decide(approve+feedback) refused the feedback part (${String(e)}) — resending without the note`);
632
+ return await bridge.decideTool(approveBodyWithoutFeedback(wire), gatedCallId, decideOpts, pending);
633
+ }
634
+ };
578
635
  if (approveBody.remember === 'session') {
579
636
  let sessionReceipt;
580
637
  let sessionDecided = false;
581
638
  try {
582
- const raw = await bridge.decideTool(approveBody, gatedCallId, decideOpts, pending);
639
+ const raw = await sendApprove(approveBody);
583
640
  sessionReceipt = readDecideReceipt(raw);
584
641
  sessionDecided = true;
585
642
  }
@@ -597,13 +654,17 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
597
654
  if (sessionDecided) {
598
655
  if (sessionReceipt?.rememberApplied === false)
599
656
  surfaceRememberNotApplied();
657
+ if (feedbackDropped)
658
+ surfaceAllowNoteNotCarried(allowNoteNotCarriedSentence());
600
659
  return { kind: 'decided', ...at, decision: 'allow', ...(sessionReceipt !== undefined ? { receipt: sessionReceipt } : {}) };
601
660
  }
602
661
  }
603
- const raw = await bridge.decideTool(plainApproveBody, gatedCallId, decideOpts, pending);
662
+ const raw = await sendApprove(plainApproveBody);
604
663
  const receipt = readDecideReceipt(raw);
605
664
  if (rememberRefused || sessionDowngraded)
606
665
  surfaceRememberNotApplied();
666
+ if (feedbackDropped)
667
+ surfaceAllowNoteNotCarried(allowNoteNotCarriedSentence());
607
668
  return { kind: 'decided', ...at, decision: 'allow', ...(receipt !== undefined ? { receipt } : {}) };
608
669
  }
609
670
  catch (e) {
@@ -685,8 +746,11 @@ function readReadRootCandidate(v) {
685
746
  const o = v;
686
747
  if (typeof o.dir !== 'string' || o.dir.length === 0 || o.clearsThisAsk !== true)
687
748
  return undefined;
688
- if ('covers' in o)
689
- return o.covers === 'exact' ? { dir: o.dir, clearsThisAsk: true, covers: 'exact' } : undefined;
749
+ const covers = inValueOf(o, 'covers');
750
+ if (covers.state === 'unproven')
751
+ return undefined;
752
+ if (covers.state === 'present')
753
+ return covers.value === 'exact' ? { dir: o.dir, clearsThisAsk: true, covers: 'exact' } : undefined;
690
754
  return { dir: o.dir, clearsThisAsk: true };
691
755
  }
692
756
  export const TOOL_APPROVAL_FRAME_KEYS_MIRROR = [
@@ -764,6 +828,12 @@ export function toolPermissionRequestAskBits(card, requestId) {
764
828
  const origin = readAskOrigin(card);
765
829
  const ruleOffersAbsence = readOwnNonEmptyString(card, 'ruleOffersAbsence');
766
830
  const askClassPair = readAskClassPair(card);
831
+ const probeLayer = probeCarrierOf(card);
832
+ const probe = probeFactsAt(probeLayer);
833
+ const onTop = probeLayer === card;
834
+ const requestedBy = onTop ? approvalRequestedByOf(card) : undefined;
835
+ const payload = onTop ? cardPayloadReadingOf(card) : undefined;
836
+ const inputSource = onTop ? approvalInputSourceOf(card) : undefined;
767
837
  return {
768
838
  ...(mandated ? { mandated: true } : {}),
769
839
  ...(mandate !== undefined ? { mandate } : {}),
@@ -771,6 +841,12 @@ export function toolPermissionRequestAskBits(card, requestId) {
771
841
  ...(ruleOffersAbsence !== undefined ? { ruleOffersAbsence } : {}),
772
842
  ...(askClassPair ?? {}),
773
843
  ...(seatSessionRowOf(card, requestId) ? { sessionRow: true } : {}),
844
+ ...(probe.prose !== undefined ? { probeReason: probe.prose } : {}),
845
+ ...(probe.cause !== undefined ? { probeCause: probe.cause } : {}),
846
+ ...(seatAllowNoteCarriedOf(card, requestId) ? { feedbackCapable: true } : {}),
847
+ ...(requestedBy !== undefined ? { requestedBy } : {}),
848
+ ...(payload !== undefined && payload.payloadUnreadable && payload.why !== undefined ? { frameReading: payload.why } : {}),
849
+ ...(inputSource !== undefined ? { inputSource } : {}),
774
850
  };
775
851
  }
776
852
  function isToolApprovalDelegation(v) {
@@ -797,6 +873,14 @@ function respondDecisionOfAnswer(answer) {
797
873
  return answer.allowSession ? 'allow_session' : 'allow';
798
874
  return answer.kind === 'deny' ? 'deny' : undefined;
799
875
  }
876
+ export function allowNoteReadingOf(answer) {
877
+ const note = readOwnDataValue(answer, 'note');
878
+ if (note === undefined)
879
+ return { kind: 'absent' };
880
+ if (typeof note !== 'string')
881
+ return { kind: 'invalid' };
882
+ return note.trim() === '' ? { kind: 'blank' } : { kind: 'text', text: note };
883
+ }
800
884
  function respondNoteGate(reason, capable) {
801
885
  if (reason === undefined || reason.trim() === '')
802
886
  return { dropped: 'blank' };
@@ -815,10 +899,14 @@ export function answerPayloadFor(answer, lane, caps) {
815
899
  const reason = answer.kind === 'deny' && typeof answer.reason === 'string' ? answer.reason : undefined;
816
900
  return Object.freeze({ decision: 'deny', reason: denyReasonForWire(reason, 'answer') ?? DEFAULT_DENY_REASON });
817
901
  }
902
+ const fb = allowNoteReadingOf(answer);
903
+ if (fb.kind === 'invalid')
904
+ hostLog('error', `answerPayloadFor: the allow note must be a string (got ${typeof readOwnDataValue(answer, 'note')}) — not sent as feedback; the decision itself is sent`);
818
905
  return Object.freeze({
819
906
  decision: 'approve',
820
907
  ...(word === 'allow_session' ? { remember: 'session' } : {}),
821
908
  ...(answer.updatedInput !== undefined ? { updatedInput: answer.updatedInput } : {}),
909
+ ...(fb.kind === 'text' ? { feedback: fb.text } : {}),
822
910
  });
823
911
  }
824
912
  if (answer.kind === 'allow')
@@ -827,9 +915,25 @@ export function answerPayloadFor(answer, lane, caps) {
827
915
  return Object.freeze({ decision: word, ...('note' in gate ? { note: gate.note } : {}) });
828
916
  }
829
917
  const ANSWER_CARRIAGE_NONE = Object.freeze({ allowNote: 'none' });
918
+ const ANSWER_CARRIAGE_MODEL = Object.freeze({ allowNote: 'model' });
830
919
  export function answerCarriage(card) {
831
- void card;
832
- return ANSWER_CARRIAGE_NONE;
920
+ return cardIsOnParkRow(card) ? ANSWER_CARRIAGE_MODEL : ANSWER_CARRIAGE_NONE;
921
+ }
922
+ function cardIsOnParkRow(card) {
923
+ try {
924
+ if (typeof card !== 'object' || card === null)
925
+ return false;
926
+ const park = readOwnDataValue(card, 'parkRow');
927
+ if (typeof park !== 'object' || park === null || Array.isArray(park))
928
+ return false;
929
+ return readOwnDataNonEmptyString(park, 'taskId') !== undefined;
930
+ }
931
+ catch {
932
+ return false;
933
+ }
934
+ }
935
+ export function allowNoteNotCarriedSentence(lang) {
936
+ return renderMessage(msg('approval.allowNote.notCarried'), lang);
833
937
  }
834
938
  export function observeApprovalAnswerCommitted(listener) {
835
939
  answerCommittedListeners.add(listener);
@@ -846,12 +950,30 @@ function emitAnswerCommitted(callKey, lane, answer, payload) {
846
950
  invokeHostCallbackIsolated('liveToolApprovalWire: answer-committed listener', () => l(event));
847
951
  }
848
952
  export function isToolApprovalRespondReplayed(ack) {
849
- return typeof ack === 'object' && ack !== null && ack.idempotent === true;
953
+ return typeof ack === 'object' && ack !== null && ack.idempotent === true && ack.accepted !== 'parked_redeemed';
954
+ }
955
+ export function isToolApprovalRespondParkedRedeemed(ack) {
956
+ return typeof ack === 'object' && ack !== null && ack.accepted === 'parked_redeemed';
957
+ }
958
+ export function replayedFirstDecisionOf(ack) {
959
+ if (ack === undefined)
960
+ return undefined;
961
+ if (isToolApprovalRespondReplayed(ack))
962
+ return ack.decision;
963
+ if (isToolApprovalRespondParkedRedeemed(ack) && ack.idempotent === true)
964
+ return ack.decision === 'allow' || ack.decision === 'deny' ? ack.decision : undefined;
965
+ return undefined;
966
+ }
967
+ export function settlementAckOf(read) {
968
+ return read !== undefined && isToolApprovalRespondParkedRedeemed(read) && read.idempotent !== true ? undefined : read;
850
969
  }
851
970
  export function readToolApprovalRespondAck(v) {
852
971
  if (v === null || typeof v !== 'object')
853
972
  return undefined;
854
973
  const o = v;
974
+ const accepted = slotReadOf(o, 'accepted');
975
+ if (accepted.presence === 'present' && accepted.value === 'parked_redeemed')
976
+ return readParkedRedeemedAck(o);
855
977
  if (o.idempotent === true)
856
978
  return o.delivery === undefined ? readReplayedAck(o) : undefined;
857
979
  if (o.delivery !== 'applied')
@@ -969,6 +1091,44 @@ function readReplayedAck(o) {
969
1091
  ...(o.rememberApplied === false ? { rememberApplied: false } : {}),
970
1092
  };
971
1093
  }
1094
+ function readParkedRedeemedAck(o) {
1095
+ if (slotReadOf(o, 'delivery').presence !== 'absent')
1096
+ return undefined;
1097
+ const text = (key) => {
1098
+ const slot = slotReadOf(o, key);
1099
+ return slot.presence === 'present' && typeof slot.value === 'string' && slot.value !== '' ? slot.value : undefined;
1100
+ };
1101
+ const approvalId = text('approvalId');
1102
+ const askId = text('askId');
1103
+ if (approvalId === undefined || askId === undefined)
1104
+ return undefined;
1105
+ const idem = slotReadOf(o, 'idempotent');
1106
+ if (idem.presence === 'unreadable')
1107
+ return undefined;
1108
+ const replay = idem.presence === 'present' && idem.value === true;
1109
+ const dec = slotReadOf(o, 'decision');
1110
+ let decision;
1111
+ if (replay) {
1112
+ if (dec.presence !== 'present' || (dec.value !== 'allow' && dec.value !== 'deny'))
1113
+ return undefined;
1114
+ decision = dec.value === 'allow' ? 'allow' : 'deny';
1115
+ }
1116
+ else {
1117
+ decision = dec.presence === 'present' && typeof dec.value === 'string' && dec.value !== '' ? dec.value : undefined;
1118
+ }
1119
+ const remember = slotReadOf(o, 'rememberApplied');
1120
+ return {
1121
+ approvalId,
1122
+ askId,
1123
+ accepted: 'parked_redeemed',
1124
+ ...(replay ? { idempotent: true } : {}),
1125
+ ...(decision !== undefined ? { decision } : {}),
1126
+ ...(remember.presence === 'present' && typeof remember.value === 'boolean' ? { rememberApplied: remember.value } : {}),
1127
+ };
1128
+ }
1129
+ function replayedDecisionOf(first, sent, ack) {
1130
+ return { kind: 'decided', lane: 'respond', decision: first, ...(ack !== undefined ? { ack } : {}), settledElsewhere: toolPermissionSettledElsewhereOf(first, sent) };
1131
+ }
972
1132
  function isNonEmptyStringArray(v) {
973
1133
  return Array.isArray(v) && v.length > 0 && v.every(x => typeof x === 'string' && x !== '');
974
1134
  }
@@ -1074,19 +1234,44 @@ function readProbeReason(v) {
1074
1234
  function usableProbeReason(raw) {
1075
1235
  return typeof raw === 'string' && raw.trim() !== '' ? raw : undefined;
1076
1236
  }
1237
+ function probeFactsAt(at) {
1238
+ const prose = usableProbeReason(ownDataValue(at, 'probeReason'));
1239
+ let cause;
1240
+ try {
1241
+ const raw = ownDataValue(at, 'probeCause');
1242
+ if (isWireRecordCarrier(raw))
1243
+ cause = raw;
1244
+ }
1245
+ catch {
1246
+ cause = undefined;
1247
+ }
1248
+ return { prose, cause };
1249
+ }
1250
+ function probeCarrierOf(carrier) {
1251
+ let d;
1252
+ try {
1253
+ d = Object.getOwnPropertyDescriptor(carrier, 'riskDescriptor');
1254
+ }
1255
+ catch {
1256
+ return undefined;
1257
+ }
1258
+ if (d === undefined)
1259
+ return carrier;
1260
+ return Object.hasOwn(d, 'value') ? d.value : undefined;
1261
+ }
1077
1262
  const PROBE_CAUSE_CODE_WORD = /^[a-z][a-z0-9_]{0,31}(?:\.[a-z][a-z0-9_]{0,31}){1,3}$/;
1078
1263
  export function askProbeReasonDetail(card, lang) {
1079
- const prose = usableProbeReason(ownDataValue(card, 'probeReason'));
1264
+ const { prose, cause } = probeFactsAt(card);
1080
1265
  const shown = prose === undefined ? '' : displayUntrusted(prose);
1081
- const sentence = probeCauseSentence(ownDataValue(card, 'probeCause'), shown !== '', lang);
1266
+ const sentence = probeCauseSentence(cause, shown !== '', lang);
1082
1267
  if (sentence === undefined)
1083
1268
  return shown === '' ? undefined : shown;
1084
1269
  return shown === '' ? sentence : renderMessage(msg('approval.probe.proseJoin', { sentence, prose: shown }), lang);
1085
1270
  }
1086
1271
  function probeCauseSentence(cause, withProse, lang) {
1272
+ if (cause === undefined)
1273
+ return undefined;
1087
1274
  try {
1088
- if (!isWireRecordCarrier(cause))
1089
- return undefined;
1090
1275
  const code = ownDataValue(cause, 'code');
1091
1276
  const withCode = typeof code === 'string' && PROBE_CAUSE_CODE_WORD.test(code);
1092
1277
  const key = withProse
@@ -1679,7 +1864,7 @@ function v1Bit(stamp) {
1679
1864
  const SUSPENDED_ASK_ARGS_NOTE = "this request's tool arguments are not available on this surface — it was raised while no client was connected, " +
1680
1865
  'so you are deciding without seeing them; deny it if you are not sure what it will do. ' +
1681
1866
  'Edits are not accepted on this card: there is no original input to edit';
1682
- function cardFactsOf(carrier, leg, opts, liveFacts, approvalId) {
1867
+ function cardFactsOf(carrier, leg, opts, liveFacts, approvalId, payloadWhy) {
1683
1868
  const c = carrier;
1684
1869
  const full = leg !== 'generic';
1685
1870
  const live = leg === 'frame' ? carrier : leg === 'v1' ? liveFacts : undefined;
@@ -1707,12 +1892,14 @@ function cardFactsOf(carrier, leg, opts, liveFacts, approvalId) {
1707
1892
  if (reading.from === 'recorded') {
1708
1893
  if (blind)
1709
1894
  return { args: reading.args, argsUnavailable: true };
1710
- return reading.rewritten ? { args: reading.args, argsRewritten: true, wireNote: ARGS_REWRITTEN_NOTE } : { args: reading.args };
1895
+ return reading.rewritten
1896
+ ? { args: reading.args, argsRewritten: true, wireNote: ARGS_REWRITTEN_NOTE, ...inputSourceBitOf(reading) }
1897
+ : { args: reading.args, ...inputSourceBitOf(reading) };
1711
1898
  }
1712
1899
  if (reading.from === 'stream' && typeof reading.args === 'object' && reading.args !== null) {
1713
1900
  if (blind)
1714
1901
  return { args: reading.args, argsUnavailable: true };
1715
- return { args: reading.args, wireNote: ARGS_FROM_MODEL_CALL_NOTE };
1902
+ return { args: reading.args, wireNote: ARGS_FROM_MODEL_CALL_NOTE, ...inputSourceBitOf(reading) };
1716
1903
  }
1717
1904
  const omitted = c.argsOmitted === true || reading.shape === 'size_marker';
1718
1905
  const fallback = argsFallbackOf(c.message, omitted);
@@ -1743,6 +1930,8 @@ function cardFactsOf(carrier, leg, opts, liveFacts, approvalId) {
1743
1930
  out.argsUnavailable = true;
1744
1931
  if (argsPart.argsRewritten === true)
1745
1932
  out.argsRewritten = true;
1933
+ if (argsPart.inputSource !== undefined)
1934
+ out.inputSource = argsPart.inputSource;
1746
1935
  if (full) {
1747
1936
  v1Bit(() => {
1748
1937
  if (c.governanceForced === true)
@@ -1778,6 +1967,11 @@ function cardFactsOf(carrier, leg, opts, liveFacts, approvalId) {
1778
1967
  if (r !== undefined)
1779
1968
  out.probeReason = r;
1780
1969
  });
1970
+ v1Bit(() => {
1971
+ const by = approvalRequestedByOf(live);
1972
+ if (by !== undefined)
1973
+ out.requestedBy = by;
1974
+ });
1781
1975
  }
1782
1976
  v1Bit(() => {
1783
1977
  if (readApprovalRememberRefused(carrier))
@@ -1865,8 +2059,11 @@ function cardFactsOf(carrier, leg, opts, liveFacts, approvalId) {
1865
2059
  if (typeof msg === 'string' && msg.trim() !== '')
1866
2060
  out.message = msg;
1867
2061
  });
1868
- if (leg === 'generic')
2062
+ if (leg === 'generic') {
1869
2063
  out.cardPayloadUnreadable = true;
2064
+ if (payloadWhy !== undefined)
2065
+ out.cardPayloadUnreadableWhy = payloadWhy;
2066
+ }
1870
2067
  if (sessionAllowCarried(leg, approvalId))
1871
2068
  out.allowSessionCarried = true;
1872
2069
  out.grantBinding = readApprovalGrantBinding(carrier);
@@ -1898,17 +2095,29 @@ export function approvalCardFactsOfFrame(frame, opts) {
1898
2095
  return undefined;
1899
2096
  return Object.freeze(cardFactsOf(frame, 'frame', opts));
1900
2097
  }
1901
- export function approvalCardFactsOfGeneric(card) {
2098
+ export function approvalCardFactsOfGeneric(card, reading) {
1902
2099
  if (typeof card !== 'object' || card === null)
1903
2100
  return undefined;
1904
- return Object.freeze(cardFactsOf(card, 'generic'));
2101
+ return Object.freeze(cardFactsOf(card, 'generic', null, undefined, undefined, approvalFrameUnreadableWhyOf(reading)));
1905
2102
  }
1906
2103
  const MAX_RESPOND_NOTE_CHARS = 2048;
1907
2104
  export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamArgs, signal, lane, run) {
2105
+ const approvalId = readOwnDataNonEmptyString(frame, 'approvalId');
2106
+ if (approvalId === undefined)
2107
+ return approvalIdUnreadableRefusal();
2108
+ return surfaceApprovalFrameWithId(frame, approvalId, respond, streamArgs, signal, lane, run);
2109
+ }
2110
+ function approvalIdUnreadableRefusal() {
2111
+ hostLog('debug', 'liveToolApprovalWire: refused (approvalId_unreadable)');
2112
+ return { kind: 'not_sent', lane: 'respond', cause: 'card_unavailable' };
2113
+ }
2114
+ export async function surfaceApprovalFrameWithId(frame, approvalId, respond, streamArgs, signal, lane, run) {
1908
2115
  const receivedAtMs = Date.now();
1909
- const approvalId = frame.approvalId;
2116
+ if (typeof approvalId !== 'string' || approvalId === '')
2117
+ return approvalIdUnreadableRefusal();
1910
2118
  const carriers = openingFrameCarriersOf(frame);
1911
- const entry = { frame, carriers, approvalId, identity: liveCardIdentityOf(approvalId, frame, carriers, run), respond, streamArgs, signal, lane, receivedAtMs };
2119
+ const liveRun = liveCardRunOf(frame, run);
2120
+ const entry = { frame, carriers, approvalId, identity: liveCardIdentityOf(approvalId, carriers, liveRun), respond, streamArgs, signal, lane, receivedAtMs };
1912
2121
  return enterLiveCard(entry);
1913
2122
  }
1914
2123
  function openingFrameCarriersOf(frame) {
@@ -1916,9 +2125,10 @@ function openingFrameCarriersOf(frame) {
1916
2125
  return { body: frame, live: frame, leg: 'frame' };
1917
2126
  const card = frame.card;
1918
2127
  const pinned = Object.create(frame, { card: { value: card, enumerable: true } });
1919
- if (isApprovalRequestFrameV1(pinned))
2128
+ const reading = approvalRequestFrameReadingThrowing(pinned);
2129
+ if (reading.v1)
1920
2130
  return { body: pinned.card, live: frame, leg: 'v1' };
1921
- return { body: typeof card === 'object' && card !== null ? card : {}, live: undefined, leg: 'generic' };
2131
+ return { body: typeof card === 'object' && card !== null ? card : {}, live: undefined, leg: 'generic', why: reading.why };
1922
2132
  }
1923
2133
  function enterLiveCard(e) {
1924
2134
  const { approvalId, signal } = e;
@@ -1933,7 +2143,7 @@ function enterLiveCard(e) {
1933
2143
  return joinOtherLaneHolder(e, other);
1934
2144
  return holdLiveCard(e.identity, signal, async (hold) => {
1935
2145
  const slot = {};
1936
- const out = await presentToolApprovalFrameAndRespond(e.frame, e.carriers, approvalId, e.respond, e.streamArgs, signal, e.lane, hold, slot, e.receivedAtMs);
2146
+ const out = await presentToolApprovalFrameAndRespond(e.frame, e.carriers, approvalId, e.respond, e.streamArgs, signal, e.lane, hold, slot, e.receivedAtMs, e.identity.taskId);
1937
2147
  noteCallOutcome(slot, out);
1938
2148
  return out;
1939
2149
  });
@@ -1948,15 +2158,20 @@ async function joinOtherLaneHolder(e, other) {
1948
2158
  return { kind: 'not_sent', lane: 'respond', cause: 'retracted', joinedInFlight: true };
1949
2159
  return enterLiveCard(e);
1950
2160
  }
1951
- function liveCardIdentityOf(approvalId, frame, carriers, run) {
2161
+ function liveCardRunOf(frame, run) {
2162
+ const source = frameBindingOf(frame) ?? run;
2163
+ return {
2164
+ taskId: guardedRead(() => readOwnDataNonEmptyString(source, 'taskId')),
2165
+ sessionId: guardedRead(() => readOwnDataNonEmptyString(source, 'sessionId')),
2166
+ };
2167
+ }
2168
+ function liveCardIdentityOf(approvalId, carriers, liveRun) {
1952
2169
  const body = carriers.body;
1953
2170
  const toolCallId = typeof body.toolCallId === 'string' && body.toolCallId !== '' ? body.toolCallId : undefined;
1954
2171
  const fromSubagent = isFromSubagent(carriers.body);
1955
- const bound = fromSubagent ? undefined : frameBindingOf(frame);
1956
- const source = bound ?? run;
1957
- const ownRun = fromSubagent ? subagentSourceSessionOf(carriers.body) : source?.taskId;
2172
+ const ownRun = fromSubagent ? subagentSourceSessionOf(carriers.body) : liveRun.taskId;
1958
2173
  const taskId = typeof ownRun === 'string' && ownRun !== '' ? ownRun : undefined;
1959
- const sessionId = !fromSubagent && typeof source?.sessionId === 'string' && source.sessionId !== '' ? source.sessionId : undefined;
2174
+ const sessionId = fromSubagent ? undefined : liveRun.sessionId;
1960
2175
  const askSig = carrierAskSig(carriers.body, carriers.live);
1961
2176
  return {
1962
2177
  approvalId,
@@ -2012,12 +2227,13 @@ function readApprovalCardClaimSignal(v) {
2012
2227
  export function claimApprovalCard(identity, options) {
2013
2228
  return claimApprovalCardFor(readApprovalHolderIdentity(identity), readApprovalCardClaimSignal(options));
2014
2229
  }
2015
- async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, respond, streamArgs, signal, lane, hold, ledgerSlot, receivedAtMs) {
2230
+ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, respond, streamArgs, signal, lane, hold, ledgerSlot, receivedAtMs, cardTaskId) {
2016
2231
  const bodyToolCallId = carriers.body.toolCallId;
2017
2232
  const frameToolCallId = typeof bodyToolCallId === 'string' && bodyToolCallId !== '' ? bodyToolCallId : undefined;
2018
2233
  const decidedByReading = decidedByReadingSnapshotOf(lane);
2019
- const facts = cardFactsOf(carriers.body, carriers.leg, { streamArgs, ...(lane?.argsUnavailable === true ? { argsUnavailable: true } : {}) }, carriers.live, approvalId);
2234
+ const facts = cardFactsOf(carriers.body, carriers.leg, { streamArgs, ...(lane?.argsUnavailable === true ? { argsUnavailable: true } : {}) }, carriers.live, approvalId, carriers.why);
2020
2235
  const argsNotRealInput = facts.argsUnavailable === true;
2236
+ const editAcceptance = editedApprovalAcceptanceOf(facts);
2021
2237
  const ruleOffers = facts.ruleOffers;
2022
2238
  if (argsNotRealInput && lane?.argsUnavailable !== true && facts.wireNote !== undefined) {
2023
2239
  hostLog('debug', `liveToolApprovalWire: frame ${approvalId} args omitted (>16KiB wire cap) — card falls back to ${Object.hasOwn(facts.args, 'file_path') ? 'the message-derived path' : 'an empty input (no path could be derived from the message)'}`);
@@ -2025,6 +2241,7 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
2025
2241
  const card = await surfaceCallTrackedCard(frameToolCallId, approvalId, ledgerSlot, {
2026
2242
  ...facts,
2027
2243
  callKey: liveFrameCallKey(approvalId),
2244
+ ...(cardTaskId !== undefined ? { taskId: cardTaskId } : {}),
2028
2245
  signal: hold.cardSignal,
2029
2246
  ...approvalWindowKeysOf(frame, { windowIsCurrent: lane?.windowIsCurrent === true, receivedAtMs, ...(carriers.leg === 'generic' ? { unknownShape: true } : {}) }),
2030
2247
  });
@@ -2035,11 +2252,13 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
2035
2252
  surfaceApprovalParking();
2036
2253
  return { kind: 'not_sent', lane: 'respond', cause: 'retracted' };
2037
2254
  }
2038
- if (argsNotRealInput && card.kind === 'allow' && card.updatedInput !== undefined) {
2255
+ if (editAcceptance.state !== 'accepts' && card.kind === 'allow' && card.updatedInput !== undefined) {
2039
2256
  hostLog('error', `liveToolApprovalWire: ${approvalId} card returned an edited approval on a card whose arguments are not the tool's real input (${lane?.argsUnavailable === true ? 'args-unavailable ask' : 'arguments omitted or absent on the frame'}) — nothing sent (the ask stays pending)`);
2040
2257
  surfaceEditRefusedOnBlindAsk();
2041
2258
  return { kind: 'not_sent', lane: 'respond', cause: 'edit_refused' };
2042
2259
  }
2260
+ if (card.kind === WITHDRAWN_CARD_DECISION_KIND)
2261
+ return withdrawnCardResolution(card, { lane: 'respond' }, 'liveToolApprovalWire');
2043
2262
  if (card.kind === RETRACTED_CARD_DECISION_KIND) {
2044
2263
  hostLog('debug', `liveToolApprovalWire: ${approvalId} card retracted without a decision${card.reason ? ` (${card.reason})` : ''} — nothing sent`);
2045
2264
  return { kind: 'not_sent', lane: 'respond', cause: 'retracted' };
@@ -2073,8 +2292,10 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
2073
2292
  : card;
2074
2293
  const basePayload = answerPayloadFor(answerSnapshot, 'respond', { approvalDecisionNoteCapable: noteCapable });
2075
2294
  const decision = basePayload?.decision ?? 'deny';
2076
- if (card.kind === 'allow' && typeof card.note === 'string' && card.note.trim() !== '' && answerCarriage({ callKey: liveFrameCallKey(approvalId) }).allowNote === 'none') {
2077
- hostLog('debug', `liveToolApprovalWire: ${approvalId} card carried a note on Yes (len=${card.note.length}) — this engine has no field that brings it to the model, so it was not sent`);
2295
+ const allowNoteText = decision !== 'deny' ? allowNoteReadingOf(answerSnapshot) : { kind: 'absent' };
2296
+ const allowNoteDropped = allowNoteText.kind === 'text' && answerCarriage({ callKey: liveFrameCallKey(approvalId) }).allowNote === 'none';
2297
+ if (allowNoteDropped && allowNoteText.kind === 'text') {
2298
+ hostLog('debug', `liveToolApprovalWire: ${approvalId} card carried a note on Yes (len=${allowNoteText.text.length}) — this approval door has no field that brings it to the model, so it was not sent`);
2078
2299
  }
2079
2300
  const denySettledByForWire = card.kind === 'deny' ? readApprovalDenySettledBy(card) : undefined;
2080
2301
  const denyPolicyCauseForWire = card.kind === 'deny' ? readPolicyDenyCause(card) : undefined;
@@ -2228,15 +2449,15 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
2228
2449
  'reporting the answer as NOT settled (never as decided, never as parked); not re-sent');
2229
2450
  return { kind: 'unsettled', lane: 'respond', cause: 'unreadable' };
2230
2451
  }
2231
- const parsed = readToolApprovalRespondAck(raw);
2452
+ const parsed = settlementAckOf(readToolApprovalRespondAck(raw));
2232
2453
  const replayedForThisCard = parsed !== undefined && isToolApprovalRespondReplayed(parsed) && parsed.approvalId === approvalId;
2233
- const claimsReplay = ownIdempotentTrue(raw) || (parsed !== undefined && isToolApprovalRespondReplayed(parsed));
2454
+ const claimsReplay = ownIdempotentTrue(raw) || replayedFirstDecisionOf(parsed) !== undefined;
2234
2455
  if (claimsReplay && !replayedForThisCard) {
2235
2456
  const claimed = replayClaimOf(raw);
2236
2457
  if (claimed.approvalId === approvalId && claimed.decision !== undefined && !claimed.carriesDelivery) {
2237
2458
  hostLog('debug', `liveToolApprovalWire: respond(${decision}) for ${approvalId} answered with a replay (body not in the full replay shape) — the approval was already decided ` +
2238
2459
  `(${claimed.decision}); this answer was not delivered, reporting the earlier decision`);
2239
- return { kind: 'decided', lane: 'respond', decision: claimed.decision };
2460
+ return replayedDecisionOf(claimed.decision, decision, parsed !== undefined && isToolApprovalRespondParkedRedeemed(parsed) && parsed.approvalId === approvalId ? parsed : undefined);
2240
2461
  }
2241
2462
  hostLog('error', `liveToolApprovalWire: respond(${decision}) for ${approvalId} answered with a replay of an earlier decision that cannot be read or names another approval — ` +
2242
2463
  'reporting the answer as NOT settled (never as the decision this client sent); not re-sent');
@@ -2306,6 +2527,8 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
2306
2527
  }
2307
2528
  if (replayed === undefined && sessionDowngraded)
2308
2529
  surfaceRememberNotApplied();
2530
+ if (replayed === undefined && allowNoteDropped)
2531
+ surfaceAllowNoteNotCarried(allowNoteNotCarriedSentence());
2309
2532
  if (respondOpts.updatedInput !== undefined && applied?.updatedInputForwarded === false) {
2310
2533
  logAfterDecided(`liveToolApprovalWire: ${approvalId} edited args were NOT forwarded (ack.updatedInputForwarded=false) — the tool runs on the ORIGINAL input`);
2311
2534
  surfaceEditNotForwarded();
@@ -2317,7 +2540,7 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
2317
2540
  if (replayed !== undefined) {
2318
2541
  hostLog('debug', `liveToolApprovalWire: respond(${decision}) for ${approvalId} answered with a replay — the approval was already decided (${replayed.decision}); ` +
2319
2542
  'this answer was not delivered, reporting the earlier decision');
2320
- return { kind: 'decided', lane: 'respond', decision: replayed.decision, ack: replayed };
2543
+ return replayedDecisionOf(replayed.decision, decision, replayed);
2321
2544
  }
2322
2545
  const deny = decision === 'deny' ? denyFactsOf(denySettledByForWire, denyReasonSnapshot, attributionDropped, attributionRenamed, denyPolicyCauseForWire) : undefined;
2323
2546
  return { kind: 'decided', lane: 'respond', decision, ...(ack !== undefined ? { ack } : {}), ...(deny !== undefined ? { deny } : {}) };