@sema-agent/client-core 0.110.0 → 0.112.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 (243) hide show
  1. package/CHANGELOG.md +244 -0
  2. package/README.md +59 -18
  3. package/dist/abortableSleep.d.ts +7 -0
  4. package/dist/abortableSleep.js +37 -0
  5. package/dist/adapt/arms.js +25 -4
  6. package/dist/adapt/toolCards.d.ts +3 -1
  7. package/dist/adapt/toolCards.js +4 -2
  8. package/dist/adapter/activeRunSelfHeal.d.ts +39 -0
  9. package/dist/adapter/activeRunSelfHeal.js +171 -3
  10. package/dist/adapter/downstream/eventToSdkMessage.js +10 -10
  11. package/dist/adapter/downstream/terminalToSdkResult.d.ts +2 -0
  12. package/dist/adapter/downstream/terminalToSdkResult.js +11 -0
  13. package/dist/adapter/runStream.d.ts +5 -0
  14. package/dist/adapter/runStream.js +15 -3
  15. package/dist/agentSession/engineSessionBackgroundStop.js +2 -2
  16. package/dist/attachmentRoute.d.ts +20 -0
  17. package/dist/attachmentRoute.js +39 -0
  18. package/dist/attachmentsWireCaps.js +1 -1
  19. package/dist/builtinOutputStyles.d.ts +12 -0
  20. package/dist/builtinOutputStyles.js +147 -0
  21. package/dist/checkpointRowVerdict.d.ts +3 -0
  22. package/dist/checkpointRowVerdict.js +14 -1
  23. package/dist/compactionStatus.d.ts +9 -0
  24. package/dist/compactionStatus.js +29 -5
  25. package/dist/consoleCaPin.d.ts +136 -0
  26. package/dist/consoleCaPin.js +827 -0
  27. package/dist/controlRouter.js +2 -1
  28. package/dist/coreValuePorts.d.ts +39 -1
  29. package/dist/coreValuePorts.js +10 -0
  30. package/dist/decideReceipt.d.ts +2 -1
  31. package/dist/deviceRebind.js +3 -3
  32. package/dist/displayUntrusted.d.ts +1 -0
  33. package/dist/displayUntrusted.js +6 -0
  34. package/dist/effectiveFacts.d.ts +9 -0
  35. package/dist/effectiveFacts.js +33 -0
  36. package/dist/engineAddress.d.ts +1 -0
  37. package/dist/engineAddress.js +4 -1
  38. package/dist/engineCredentialRelease.d.ts +54 -0
  39. package/dist/engineCredentialRelease.js +146 -0
  40. package/dist/engineErrorCodes.d.ts +1 -0
  41. package/dist/engineErrorCodes.js +1 -0
  42. package/dist/engineHealthProbeVerdict.d.ts +24 -0
  43. package/dist/engineHealthProbeVerdict.js +123 -0
  44. package/dist/engineNoticeCodes.js +5 -7
  45. package/dist/engineRepoint.d.ts +12 -5
  46. package/dist/engineRepoint.js +44 -19
  47. package/dist/engineRowRef.d.ts +3 -0
  48. package/dist/engineRowRef.js +11 -1
  49. package/dist/engineSwapCrossing.d.ts +57 -0
  50. package/dist/engineSwapCrossing.js +297 -0
  51. package/dist/engineUnavailable.d.ts +45 -0
  52. package/dist/engineUnavailable.js +496 -0
  53. package/dist/engineUrl.js +4 -2
  54. package/dist/eventLeg.js +3 -3
  55. package/dist/gateFailureCodes.js +2 -2
  56. package/dist/generated/sdkFactTables.d.ts +2 -1
  57. package/dist/generated/sdkFactTables.js +14 -0
  58. package/dist/generated/settingsSchemaFns.d.ts +1 -0
  59. package/dist/generated/settingsSchemaFns.js +3 -0
  60. package/dist/generated/settingsSchemaHooksClassifier.js +38 -9
  61. package/dist/generated/settingsSchemaTables.d.ts +56 -0
  62. package/dist/generated/settingsSchemaTables.js +19 -0
  63. package/dist/generated/settingsSchemaTypes.d.ts +23 -13
  64. package/dist/generated/settingsSchemaUrlShape.d.ts +1 -0
  65. package/dist/generated/settingsSchemaUrlShape.js +17 -0
  66. package/dist/hitl/approvalDelivery.d.ts +1 -0
  67. package/dist/hitl/approvalDelivery.js +1 -1
  68. package/dist/hitl/approvalResolution.d.ts +1 -1
  69. package/dist/hitl/approvalResolution.js +2 -1
  70. package/dist/hitl/askGateWire.js +5 -6
  71. package/dist/hitl/decisionRefusal.d.ts +6 -0
  72. package/dist/hitl/decisionRefusal.js +19 -10
  73. package/dist/hitl/decisionRefusalCarrier.d.ts +3 -0
  74. package/dist/hitl/decisionRefusalCarrier.js +348 -0
  75. package/dist/hitl/decisionSend.d.ts +7 -0
  76. package/dist/hitl/decisionSend.js +34 -12
  77. package/dist/hitl/editedApprovalAcceptance.js +1 -1
  78. package/dist/hitl/elicitationRefusal.d.ts +4 -0
  79. package/dist/hitl/elicitationRefusal.js +23 -0
  80. package/dist/hitl/frameRouter.d.ts +2 -2
  81. package/dist/hitl/frameRouter.js +8 -15
  82. package/dist/hitl/gateIdentity.d.ts +5 -0
  83. package/dist/hitl/gateIdentity.js +23 -0
  84. package/dist/hitl/hitlBridge.d.ts +6 -0
  85. package/dist/hitl/hitlBridge.js +10 -4
  86. package/dist/hitl/hitlHostSurface.d.ts +2 -1
  87. package/dist/hitl/hitlHostSurface.js +7 -2
  88. package/dist/hitl/localAllowRedemption.d.ts +70 -0
  89. package/dist/hitl/localAllowRedemption.js +276 -0
  90. package/dist/hitl/parkOwnership.js +2 -1
  91. package/dist/hitl/parkResolver.js +14 -4
  92. package/dist/hitl/persistedRulesWire.d.ts +16 -0
  93. package/dist/hitl/persistedRulesWire.js +70 -0
  94. package/dist/hitl/planReviewWire.d.ts +3 -0
  95. package/dist/hitl/planReviewWire.js +23 -6
  96. package/dist/hitl/policyDenyCause.d.ts +1 -1
  97. package/dist/hitl/policyDenyCause.js +1 -1
  98. package/dist/hitl/resumeRunningCard.d.ts +1 -0
  99. package/dist/hitl/resumeRunningCard.js +1 -0
  100. package/dist/hitl/screenCardCarriers.d.ts +15 -0
  101. package/dist/hitl/screenCardCarriers.js +41 -0
  102. package/dist/hitl/screenDecisionCards.d.ts +98 -0
  103. package/dist/hitl/screenDecisionCards.js +363 -0
  104. package/dist/hitl/sessionPolicyWire.js +2 -2
  105. package/dist/hitl/standingRows.d.ts +6 -2
  106. package/dist/hitl/standingRows.js +27 -2
  107. package/dist/hitl/toolApprovalWire.d.ts +30 -8
  108. package/dist/hitl/toolApprovalWire.js +264 -121
  109. package/dist/hooksReaderGenerations.js +1 -1
  110. package/dist/hooksWireCaps.js +3 -3
  111. package/dist/hostSettingNoticeArm.d.ts +3 -0
  112. package/dist/hostSettingNoticeArm.js +12 -0
  113. package/dist/hostTurnSettings.d.ts +3 -0
  114. package/dist/hostTurnSettings.js +38 -5
  115. package/dist/humanTurnRead.js +11 -1
  116. package/dist/i18n/messages.en.d.ts +292 -0
  117. package/dist/i18n/messages.en.js +298 -7
  118. package/dist/i18n/messages.zh.js +316 -6
  119. package/dist/i18n/translate.d.ts +3 -0
  120. package/dist/i18n/translate.js +78 -10
  121. package/dist/i18n/zh.d.ts +1 -0
  122. package/dist/i18n/zh.js +1 -0
  123. package/dist/index.d.ts +71 -20
  124. package/dist/index.js +44 -13
  125. package/dist/interactiveHalt.js +2 -1
  126. package/dist/interactiveInterrupt.js +20 -2
  127. package/dist/liveModelCatalog.d.ts +4 -0
  128. package/dist/liveModelCatalog.js +12 -3
  129. package/dist/localConfig/documents.d.ts +61 -0
  130. package/dist/localConfig/documents.js +51 -0
  131. package/dist/localConfig/kernel.d.ts +149 -0
  132. package/dist/localConfig/kernel.js +597 -0
  133. package/dist/localConfig/mcp/edit.d.ts +161 -0
  134. package/dist/localConfig/mcp/edit.js +846 -0
  135. package/dist/localConfig/mcp/servers.d.ts +165 -0
  136. package/dist/localConfig/mcp/servers.js +776 -0
  137. package/dist/localConfig/mcp/views.d.ts +170 -0
  138. package/dist/localConfig/mcp/views.js +429 -0
  139. package/dist/localConfig/modelPool.d.ts +262 -0
  140. package/dist/localConfig/modelPool.js +1489 -0
  141. package/dist/localConfig/modelPoolWords.d.ts +13 -0
  142. package/dist/localConfig/modelPoolWords.js +20 -0
  143. package/dist/localConfig/receiptShape.d.ts +7 -0
  144. package/dist/localConfig/receiptShape.js +135 -0
  145. package/dist/localConfig/settingsWrite.d.ts +127 -0
  146. package/dist/localConfig/settingsWrite.js +237 -0
  147. package/dist/localConfig/skills.d.ts +124 -0
  148. package/dist/localConfig/skills.js +397 -0
  149. package/dist/localConfig/skillsWords.d.ts +10 -0
  150. package/dist/localConfig/skillsWords.js +5 -0
  151. package/dist/localEngineSeatReading.d.ts +2 -2
  152. package/dist/localEngineSeatReading.js +5 -3
  153. package/dist/localEngineSpawn.d.ts +0 -7
  154. package/dist/localEngineSpawn.js +0 -92
  155. package/dist/localEngineStep.d.ts +2 -2
  156. package/dist/localEngineStep.js +2 -0
  157. package/dist/mcpProbeWire.js +2 -1
  158. package/dist/mcpReconnect.js +3 -3
  159. package/dist/mcpWireCaps.js +1 -1
  160. package/dist/memoryVerbsWire.js +3 -2
  161. package/dist/model/engineModelWords.d.ts +3 -0
  162. package/dist/model/engineModelWords.js +13 -0
  163. package/dist/model/onboardJudgement.d.ts +14 -4
  164. package/dist/model/onboardJudgement.js +91 -139
  165. package/dist/model/subagentModelWord.d.ts +21 -2
  166. package/dist/model/subagentModelWord.js +100 -29
  167. package/dist/modelCapabilityProbe.js +3 -40
  168. package/dist/modelConfigGapNotice.d.ts +20 -0
  169. package/dist/modelConfigGapNotice.js +102 -0
  170. package/dist/modsKernelIdentity.js +2 -47
  171. package/dist/notifications.d.ts +19 -0
  172. package/dist/notifications.js +114 -12
  173. package/dist/ownKey.d.ts +7 -0
  174. package/dist/ownKey.js +71 -8
  175. package/dist/pendingUserRow.d.ts +4 -0
  176. package/dist/pendingUserRow.js +16 -0
  177. package/dist/permissionsDeclaration.d.ts +3 -1
  178. package/dist/permissionsDeclaration.js +33 -9
  179. package/dist/planReviewCardFacts.d.ts +3 -0
  180. package/dist/planReviewCardFacts.js +52 -2
  181. package/dist/pluginHooksWire.d.ts +9 -1
  182. package/dist/pluginHooksWire.js +40 -6
  183. package/dist/printToolResultFrame.js +4 -2
  184. package/dist/promptBlockedCopy.js +12 -7
  185. package/dist/promptSuggestionBatch.d.ts +7 -0
  186. package/dist/promptSuggestionBatch.js +9 -0
  187. package/dist/promptSuggestionsTail.d.ts +39 -0
  188. package/dist/promptSuggestionsTail.js +116 -0
  189. package/dist/request/taskRequest.js +10 -6
  190. package/dist/requestCoordinate.d.ts +1 -0
  191. package/dist/requestCoordinate.js +13 -0
  192. package/dist/resumeRefusalCopy.d.ts +3 -1
  193. package/dist/resumeRefusalCopy.js +12 -4
  194. package/dist/rewindArchiveReading.js +4 -4
  195. package/dist/runCancelContext.d.ts +2 -1
  196. package/dist/runCancelContext.js +1 -0
  197. package/dist/runLedgerSnapshot.js +3 -3
  198. package/dist/runPermissionModeSwitch.js +3 -4
  199. package/dist/scenarioRefusal.js +11 -13
  200. package/dist/scenarioSkills.js +11 -6
  201. package/dist/seam.d.ts +16 -2
  202. package/dist/seam.js +10 -0
  203. package/dist/seatContract.d.ts +259 -9
  204. package/dist/seatContract.js +444 -15
  205. package/dist/sessionCostReading.d.ts +70 -0
  206. package/dist/sessionCostReading.js +150 -0
  207. package/dist/sessionHooksRoster.d.ts +4 -0
  208. package/dist/sessionHooksRoster.js +158 -0
  209. package/dist/sessionIdSegment.d.ts +1 -0
  210. package/dist/sessionIdSegment.js +4 -1
  211. package/dist/sessionMemoryErase.js +2 -1
  212. package/dist/sessionMemoryStatus.js +2 -2
  213. package/dist/sessionReadRedaction.d.ts +7 -0
  214. package/dist/sessionReadRedaction.js +26 -0
  215. package/dist/sessionSyncFileHistory.js +8 -9
  216. package/dist/settingsHooksSalvage.js +2 -1
  217. package/dist/sha256Bytes.d.ts +1 -0
  218. package/dist/sha256Bytes.js +46 -0
  219. package/dist/skillOverrideChain.d.ts +83 -0
  220. package/dist/skillOverrideChain.js +378 -0
  221. package/dist/skillsWireCaps.d.ts +3 -0
  222. package/dist/skillsWireCaps.js +16 -1
  223. package/dist/sseIdleTriage.js +2 -1
  224. package/dist/storeDurabilityWord.d.ts +15 -0
  225. package/dist/storeDurabilityWord.js +18 -0
  226. package/dist/storePostureCapability.d.ts +7 -3
  227. package/dist/storePostureCapability.js +69 -39
  228. package/dist/subagent/engineSubagentResume.js +2 -2
  229. package/dist/subagent/engineSubagentTail.js +2 -1
  230. package/dist/subagentContentStore.d.ts +11 -0
  231. package/dist/subagentContentStore.js +28 -2
  232. package/dist/toolResult.d.ts +1 -0
  233. package/dist/toolResult.js +2 -0
  234. package/dist/turnFailurePresentation.js +4 -10
  235. package/dist/userAttachmentEnvelope.d.ts +2 -1
  236. package/dist/userAttachmentEnvelope.js +10 -0
  237. package/dist/wireErrorTriage.js +2 -1
  238. package/dist/wireFailureShape.d.ts +4 -0
  239. package/dist/wireFailureShape.js +141 -19
  240. package/dist/wireRefusalCopy.d.ts +6 -5
  241. package/dist/wireRefusalCopy.js +49 -92
  242. package/docs/INTEGRATION-CLIENTS.md +2718 -17
  243. package/package.json +7 -3
@@ -4,7 +4,7 @@ import { parkGateArmOf } from './frameRouter.js';
4
4
  import { seatAllowNoteCarriedOf, seatSessionRowOf } from './standingRows.js';
5
5
  import { hostLog } from '../host.js';
6
6
  import { trimEditedRuleText } from './editedRuleTextPrecheck.js';
7
- import { appendOwnElement, guardedRead, readAskOrigin, readOwnDataNonEmptyString, readOwnDataValue, readOwnNonEmptyString } from '../ownKey.js';
7
+ import { appendOwnElement, guardedRead, ownSendableField, ownSnapshot, 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
10
  import { approvalAgentIdOf, approvalAskReasonsOf, approvalRequestedByOf } from './approvalAskers.js';
@@ -17,7 +17,7 @@ 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, surfaceAllowNoteNotCarried, surfaceRememberNotApplied, surfaceEditNotForwarded, surfaceEditRefusedOnBlindAsk, surfaceRuleArmNotSent, surfaceRuleArmRejected } from './hitlHostSurface.js';
20
+ import { INTERRUPT_DENY_REASON, interruptDenyLifetime, 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';
@@ -39,6 +39,7 @@ import { subagentSourceSessionOf } from './subagentSource.js';
39
39
  import { isPlainRecord } from '../jsonFaithful.js';
40
40
  import { DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED } from '../engineErrorCodes.js';
41
41
  import { readDecideReceipt } from '../decideReceipt.js';
42
+ import { sourceGenerationBit, sourceGenerationNow } from './screenCardCarriers.js';
42
43
  import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, ASK_ORIGINS, } from '@sema-agent/sdk';
43
44
  export function toolNameIsFsWrite(name) {
44
45
  const n = name.replace(/[\s_-]+/g, '').toLowerCase();
@@ -110,10 +111,9 @@ function withdrawnCardResolution(card, at, logTag) {
110
111
  hostLog('debug', `${logTag}: card-withdrawn-by-host verdict=${w.rowVerdict.kind}`);
111
112
  return { kind: 'not_sent', ...at, cause: 'withdrawn', toldBy: w.toldBy, rowVerdict: w.rowVerdict };
112
113
  }
113
- function parkRowOf(taskId, row, gatedCallId) {
114
+ function parkRowOf(row, gatedCallId) {
114
115
  const d = parkRowDeadlineState(row, Date.now());
115
116
  return Object.freeze({
116
- taskId,
117
117
  ...(gatedCallId !== undefined && gatedCallId !== '' ? { gatedCallId } : {}),
118
118
  ...(d.kind !== 'none' ? { deadlineMs: d.deadlineMs } : {}),
119
119
  });
@@ -225,12 +225,10 @@ const PARK_ROW_ARGS_TRUNCATED_NOTE = "this request's tool arguments were too lar
225
225
  'Edits are not accepted on this card: there is no original input to edit';
226
226
  const ARGS_REWRITTEN_NOTE = "this request's tool arguments were changed after the model made the call (for example by a hook) — " +
227
227
  'the arguments shown here are the changed ones recorded for this approval, and they differ from the call shown in the conversation';
228
- const ARGS_FROM_MODEL_CALL_NOTE = 'this approval request did not carry usable tool arguments (for example because they were too large to include), ' +
229
- "so the arguments shown are the model's original call from the conversation — " +
230
- 'if they were changed after that call (for example by a hook), what runs differs from what is shown';
231
- const PARK_EDIT_REFUSED_REASON = "the card returned an edited approval, but this request's tool arguments are not available on this surface " +
232
- '(missing, or replaced by a size marker on the pending approval record), so the edit cannot be applied — nothing was sent; ' +
233
- 'approve or deny it as it is';
228
+ function argsFromModelCallBitsOf() {
229
+ return { argsUnavailable: true, wireNote: renderMessage(msg('approval.park.argsFromModelCall')) };
230
+ }
231
+ const parkEditRefusedReason = () => renderMessage(msg('approval.editRefusal.parkReason', { stem: msg('approval.editRefusal.stem') }));
234
232
  function isParkRowInputSizeMarker(v) {
235
233
  if (typeof v !== 'object' || v === null || Array.isArray(v))
236
234
  return false;
@@ -472,6 +470,7 @@ async function joinDurableDecision(hold, deps, signal) {
472
470
  }
473
471
  export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signal, parkGatedCallId, parkToolName) {
474
472
  const decidedByReading = decidedByReadingSnapshotOf(deps);
473
+ const sourceGeneration = sourceGenerationNow(deps);
475
474
  const readMark = openDurableRead();
476
475
  let found;
477
476
  let held;
@@ -501,7 +500,7 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
501
500
  const fetched = found;
502
501
  return holdDurableDecision(durableHoldKey(fetched.pending, callKey), rowIdentity, signal, async (hold) => {
503
502
  const slot = {};
504
- const out = await presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, fetched, decidedByReading, callKey, hold, slot);
503
+ const out = await presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, fetched, decidedByReading, callKey, hold, slot, sourceGeneration);
505
504
  noteCallOutcome(slot, out);
506
505
  return out;
507
506
  });
@@ -515,7 +514,7 @@ function parkRowHolderIdentity(row, gatedCallId) {
515
514
  ...(askSig !== undefined ? { askSig } : {}),
516
515
  };
517
516
  }
518
- async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, found, decidedByReading, callKey, hold, ledgerSlot) {
517
+ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, found, decidedByReading, callKey, hold, ledgerSlot, sourceGeneration) {
519
518
  const { pending, gatedCallId } = found;
520
519
  const at = { lane: 'decide', ...(gatedCallId !== undefined ? { gatedCallId } : {}) };
521
520
  const toolName = typeof pending.toolName === 'string' ? pending.toolName : '';
@@ -548,7 +547,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
548
547
  }
549
548
  : {}),
550
549
  ...(argsRewritten ? { argsRewritten: true, wireNote: ARGS_REWRITTEN_NOTE } : {}),
551
- ...(argsFromModelCall ? { argsUnavailable: true, wireNote: renderMessage(msg('approval.park.argsFromModelCall')) } : {}),
550
+ ...(argsFromModelCall ? argsFromModelCallBitsOf() : {}),
552
551
  ...inputSourceBitOf(reading),
553
552
  ...(pending.governanceForced === true ? { governanceForced: true } : {}),
554
553
  ...(readRequiresRealApproval(pending) ? { requiresRealApproval: true } : {}),
@@ -571,8 +570,9 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
571
570
  : {}),
572
571
  allowSessionCarried: true,
573
572
  grantBinding: readApprovalGrantBinding(pending),
574
- parkRow: parkRowOf(taskId, pending, gatedCallId),
573
+ parkRow: parkRowOf(pending, gatedCallId),
575
574
  ...(typeof taskId === 'string' && taskId !== '' ? { taskId } : {}),
575
+ ...sourceGenerationBit(sourceGeneration),
576
576
  });
577
577
  const editAcceptance = editedApprovalAcceptanceOf(cardRequest);
578
578
  const card = await surfaceCallTrackedCard(gatedCallId, undefined, ledgerSlot, cardRequest);
@@ -580,7 +580,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
580
580
  if (editAcceptance.state !== 'accepts' && card.kind === 'allow' && card.updatedInput !== undefined) {
581
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)`);
582
582
  surfaceEditRefusedOnBlindAsk();
583
- return { kind: 'not_sent', ...at, cause: 'edit_refused', detail: PARK_EDIT_REFUSED_REASON };
583
+ return { kind: 'not_sent', ...at, cause: 'edit_refused', detail: parkEditRefusedReason() };
584
584
  }
585
585
  const decideSpan = bridge.openDecideOperation();
586
586
  const decideOpts = { ...(signal ? { signal } : {}), operation: decideSpan };
@@ -595,7 +595,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
595
595
  return withdrawnCardResolution(card, at, 'liveHitlAskWire');
596
596
  case 'aborted':
597
597
  {
598
- const cancelDeny = bridge.decideTool({ decision: 'deny', reason: INTERRUPT_DENY_REASON }, gatedCallId, undefined, pending);
598
+ const cancelDeny = bridge.decideTool({ decision: 'deny', reason: INTERRUPT_DENY_REASON }, gatedCallId, { signal: interruptDenyLifetime() }, pending);
599
599
  hold.trailing = cancelDeny;
600
600
  observeCancelByDeny(cancelDeny, taskId);
601
601
  }
@@ -919,14 +919,14 @@ const ANSWER_CARRIAGE_MODEL = Object.freeze({ allowNote: 'model' });
919
919
  export function answerCarriage(card) {
920
920
  return cardIsOnParkRow(card) ? ANSWER_CARRIAGE_MODEL : ANSWER_CARRIAGE_NONE;
921
921
  }
922
- function cardIsOnParkRow(card) {
922
+ export function cardIsOnParkRow(card) {
923
923
  try {
924
924
  if (typeof card !== 'object' || card === null)
925
925
  return false;
926
926
  const park = readOwnDataValue(card, 'parkRow');
927
927
  if (typeof park !== 'object' || park === null || Array.isArray(park))
928
928
  return false;
929
- return readOwnDataNonEmptyString(park, 'taskId') !== undefined;
929
+ return readOwnDataNonEmptyString(card, 'taskId') !== undefined;
930
930
  }
931
931
  catch {
932
932
  return false;
@@ -970,35 +970,43 @@ export function settlementAckOf(read) {
970
970
  export function readToolApprovalRespondAck(v) {
971
971
  if (v === null || typeof v !== 'object')
972
972
  return undefined;
973
- const o = v;
974
- const accepted = slotReadOf(o, 'accepted');
975
- if (accepted.presence === 'present' && accepted.value === 'parked_redeemed')
976
- return readParkedRedeemedAck(o);
977
- if (o.idempotent === true)
978
- return o.delivery === undefined ? readReplayedAck(o) : undefined;
979
- if (o.delivery !== 'applied')
980
- return undefined;
981
- if (typeof o.approvalId !== 'string' || o.approvalId.length === 0)
982
- return undefined;
983
- if (!isRespondDecision(o.decision))
984
- return undefined;
973
+ const s = respondAckSlotsOf(v);
974
+ if (s.accepted.presence === 'unreadable' || s.idempotent.presence === 'unreadable' || s.delivery.presence === 'unreadable')
975
+ return undefined;
976
+ if (slotValueOf(s.accepted) === 'parked_redeemed')
977
+ return readParkedRedeemedAck(s);
978
+ if (slotValueOf(s.idempotent) === true)
979
+ return s.delivery.presence === 'absent' ? readReplayedAck(s) : undefined;
980
+ if (slotValueOf(s.delivery) !== 'applied')
981
+ return undefined;
982
+ const approvalId = slotValueOf(s.approvalId);
983
+ const decision = slotValueOf(s.decision);
984
+ if (typeof approvalId !== 'string' || approvalId.length === 0)
985
+ return undefined;
986
+ if (!isRespondDecision(decision))
987
+ return undefined;
988
+ const rememberApplied = slotValueOf(s.rememberApplied);
989
+ const updatedInputForwarded = slotValueOf(s.updatedInputForwarded);
990
+ const rulePersisted = slotValueOf(s.rulePersisted);
991
+ const ruleRefusal = slotValueOf(s.ruleRefusal);
992
+ const noteRecorded = slotValueOf(s.noteRecorded);
993
+ const persistedRule = slotValueOf(s.persistedRule);
994
+ const persistedRules = slotValueOf(s.persistedRules);
995
+ const anchors = readPersistedRuleAnchors(slotValueOf(s.persistedRuleAnchors));
985
996
  const out = {
986
- approvalId: o.approvalId,
997
+ approvalId,
987
998
  delivery: 'applied',
988
- decision: o.decision,
989
- ...(typeof o.rememberApplied === 'boolean' ? { rememberApplied: o.rememberApplied } : {}),
990
- ...(typeof o.updatedInputForwarded === 'boolean' ? { updatedInputForwarded: o.updatedInputForwarded } : {}),
991
- ...(typeof o.rulePersisted === 'boolean' ? { rulePersisted: o.rulePersisted } : {}),
992
- ...(typeof o.ruleRefusal === 'string' && o.ruleRefusal !== ''
993
- ? { ruleRefusal: o.ruleRefusal }
999
+ decision: decision,
1000
+ ...(typeof rememberApplied === 'boolean' ? { rememberApplied } : {}),
1001
+ ...(typeof updatedInputForwarded === 'boolean' ? { updatedInputForwarded } : {}),
1002
+ ...(typeof rulePersisted === 'boolean' ? { rulePersisted } : {}),
1003
+ ...(typeof ruleRefusal === 'string' && ruleRefusal !== ''
1004
+ ? { ruleRefusal: ruleRefusal }
994
1005
  : {}),
995
- ...(typeof o.noteRecorded === 'boolean' ? { noteRecorded: o.noteRecorded } : {}),
996
- ...(typeof o.persistedRule === 'string' && o.persistedRule !== '' ? { persistedRule: o.persistedRule } : {}),
997
- ...(isNonEmptyStringArray(o.persistedRules) ? { persistedRules: o.persistedRules } : {}),
998
- ...(() => {
999
- const anchors = readPersistedRuleAnchors(o.persistedRuleAnchors);
1000
- return anchors !== undefined ? { persistedRuleAnchors: anchors } : {};
1001
- })(),
1006
+ ...(typeof noteRecorded === 'boolean' ? { noteRecorded } : {}),
1007
+ ...(typeof persistedRule === 'string' && persistedRule !== '' ? { persistedRule } : {}),
1008
+ ...(isNonEmptyStringArray(persistedRules) ? { persistedRules: persistedRules.slice() } : {}),
1009
+ ...(anchors !== undefined ? { persistedRuleAnchors: anchors } : {}),
1002
1010
  };
1003
1011
  if (out.persistedRule !== undefined && (out.persistedRules !== undefined || out.persistedRuleAnchors !== undefined)) {
1004
1012
  delete out.persistedRule;
@@ -1019,6 +1027,35 @@ export function readToolApprovalRespondAck(v) {
1019
1027
  }
1020
1028
  return out;
1021
1029
  }
1030
+ const RESPOND_ACK_SLOT_KEYS = [
1031
+ 'accepted',
1032
+ 'idempotent',
1033
+ 'delivery',
1034
+ 'approvalId',
1035
+ 'askId',
1036
+ 'decision',
1037
+ 'decidedAtMs',
1038
+ 'decisionNote',
1039
+ 'rememberApplied',
1040
+ 'updatedInputForwarded',
1041
+ 'rulePersisted',
1042
+ 'ruleRefusal',
1043
+ 'noteRecorded',
1044
+ 'persistedRule',
1045
+ 'persistedRules',
1046
+ 'persistedRuleAnchors',
1047
+ ];
1048
+ function respondAckSlotsOf(o) {
1049
+ const slots = {};
1050
+ for (const key of RESPOND_ACK_SLOT_KEYS) {
1051
+ const slot = slotReadOf(o, key);
1052
+ slots[key] = slot.presence === 'present' ? { presence: 'present', value: ownSnapshot(slot.value) } : slot;
1053
+ }
1054
+ return slots;
1055
+ }
1056
+ function slotValueOf(slot) {
1057
+ return slot.presence === 'present' ? slot.value : undefined;
1058
+ }
1022
1059
  export function readToolApprovalRespondParking(v) {
1023
1060
  if (typeof v !== 'object' || v === null)
1024
1061
  return undefined;
@@ -1061,6 +1098,17 @@ function replayClaimOf(raw) {
1061
1098
  }
1062
1099
  return { ...(approvalId !== undefined ? { approvalId } : {}), ...(d === 'allow' || d === 'deny' ? { decision: d } : {}), carriesDelivery };
1063
1100
  }
1101
+ function idempotentSlotUnreadable(raw) {
1102
+ if (typeof raw !== 'object' || raw === null)
1103
+ return false;
1104
+ try {
1105
+ const d = Object.getOwnPropertyDescriptor(raw, 'idempotent');
1106
+ return d !== undefined && !Object.hasOwn(d, 'value');
1107
+ }
1108
+ catch {
1109
+ return true;
1110
+ }
1111
+ }
1064
1112
  function ownIdempotentTrue(raw) {
1065
1113
  if (typeof raw !== 'object' || raw === null)
1066
1114
  return false;
@@ -1072,65 +1120,103 @@ function ownIdempotentTrue(raw) {
1072
1120
  return false;
1073
1121
  }
1074
1122
  }
1075
- function readReplayedAck(o) {
1076
- if (typeof o.approvalId !== 'string' || o.approvalId.length === 0)
1123
+ export function replayVerdictFrom(raw, parsed, approvalId) {
1124
+ if (parsed !== undefined && isToolApprovalRespondReplayed(parsed) && parsed.approvalId === approvalId)
1125
+ return { kind: 'replayed', firstDecision: parsed.decision, via: 'arm' };
1126
+ if (!(ownIdempotentTrue(raw) || replayedFirstDecisionOf(parsed) !== undefined))
1127
+ return idempotentSlotUnreadable(raw) ? { kind: 'unreadable' } : { kind: 'none' };
1128
+ const claimed = replayClaimOf(raw);
1129
+ if (claimed.approvalId === approvalId && claimed.decision !== undefined && !claimed.carriesDelivery)
1130
+ return { kind: 'replayed', firstDecision: claimed.decision, via: 'claim' };
1131
+ return { kind: 'unreadable' };
1132
+ }
1133
+ const REPLAY_VERDICT_NONE = Object.freeze({ kind: 'not_replay' });
1134
+ const REPLAY_VERDICT_ALLOW = Object.freeze({ kind: 'replayed', firstDecision: 'allow' });
1135
+ const REPLAY_VERDICT_DENY = Object.freeze({ kind: 'replayed', firstDecision: 'deny' });
1136
+ const REPLAY_VERDICT_UNREADABLE = Object.freeze({ kind: 'unreadable' });
1137
+ export function toolApprovalReplayVerdictOf(raw, approvalId) {
1138
+ try {
1139
+ if (typeof approvalId !== 'string' || approvalId === '')
1140
+ return REPLAY_VERDICT_UNREADABLE;
1141
+ const v = replayVerdictFrom(raw, settlementAckOf(readToolApprovalRespondAck(raw)), approvalId);
1142
+ if (v.kind === 'none')
1143
+ return REPLAY_VERDICT_NONE;
1144
+ if (v.kind === 'replayed')
1145
+ return v.firstDecision === 'allow' ? REPLAY_VERDICT_ALLOW : REPLAY_VERDICT_DENY;
1146
+ return REPLAY_VERDICT_UNREADABLE;
1147
+ }
1148
+ catch {
1149
+ return REPLAY_VERDICT_UNREADABLE;
1150
+ }
1151
+ }
1152
+ function readReplayedAck(s) {
1153
+ const approvalId = slotValueOf(s.approvalId);
1154
+ const askId = slotValueOf(s.askId);
1155
+ const decision = slotValueOf(s.decision);
1156
+ const decidedAtMs = slotValueOf(s.decidedAtMs);
1157
+ const decisionNote = slotValueOf(s.decisionNote);
1158
+ if (typeof approvalId !== 'string' || approvalId.length === 0)
1077
1159
  return undefined;
1078
- if (typeof o.askId !== 'string' || o.askId.length === 0)
1160
+ if (typeof askId !== 'string' || askId.length === 0)
1079
1161
  return undefined;
1080
- if (o.decision !== 'allow' && o.decision !== 'deny')
1162
+ if (decision !== 'allow' && decision !== 'deny')
1081
1163
  return undefined;
1082
- if (typeof o.decidedAtMs !== 'number' || !Number.isFinite(o.decidedAtMs) || o.decidedAtMs < 0)
1164
+ if (typeof decidedAtMs !== 'number' || !Number.isFinite(decidedAtMs) || decidedAtMs < 0)
1083
1165
  return undefined;
1084
1166
  return {
1085
- approvalId: o.approvalId,
1086
- askId: o.askId,
1167
+ approvalId,
1168
+ askId,
1087
1169
  idempotent: true,
1088
- decision: o.decision,
1089
- decidedAtMs: o.decidedAtMs,
1090
- ...(typeof o.decisionNote === 'string' && o.decisionNote !== '' ? { decisionNote: o.decisionNote } : {}),
1091
- ...(o.rememberApplied === false ? { rememberApplied: false } : {}),
1170
+ decision,
1171
+ decidedAtMs,
1172
+ ...(typeof decisionNote === 'string' && decisionNote !== '' ? { decisionNote } : {}),
1173
+ ...(slotValueOf(s.rememberApplied) === false ? { rememberApplied: false } : {}),
1092
1174
  };
1093
1175
  }
1094
- function readParkedRedeemedAck(o) {
1095
- if (slotReadOf(o, 'delivery').presence !== 'absent')
1176
+ function readParkedRedeemedAck(s) {
1177
+ if (s.delivery.presence !== 'absent')
1096
1178
  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;
1179
+ const text = (slot) => {
1180
+ const v = slotValueOf(slot);
1181
+ return typeof v === 'string' && v !== '' ? v : undefined;
1100
1182
  };
1101
- const approvalId = text('approvalId');
1102
- const askId = text('askId');
1183
+ const approvalId = text(s.approvalId);
1184
+ const askId = text(s.askId);
1103
1185
  if (approvalId === undefined || askId === undefined)
1104
1186
  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');
1187
+ const replay = slotValueOf(s.idempotent) === true;
1188
+ const dec = slotValueOf(s.decision);
1110
1189
  let decision;
1111
1190
  if (replay) {
1112
- if (dec.presence !== 'present' || (dec.value !== 'allow' && dec.value !== 'deny'))
1191
+ if (dec !== 'allow' && dec !== 'deny')
1113
1192
  return undefined;
1114
- decision = dec.value === 'allow' ? 'allow' : 'deny';
1193
+ decision = dec;
1115
1194
  }
1116
1195
  else {
1117
- decision = dec.presence === 'present' && typeof dec.value === 'string' && dec.value !== '' ? dec.value : undefined;
1196
+ decision = typeof dec === 'string' && dec !== '' ? dec : undefined;
1118
1197
  }
1119
- const remember = slotReadOf(o, 'rememberApplied');
1198
+ const remember = slotValueOf(s.rememberApplied);
1120
1199
  return {
1121
1200
  approvalId,
1122
1201
  askId,
1123
1202
  accepted: 'parked_redeemed',
1124
1203
  ...(replay ? { idempotent: true } : {}),
1125
1204
  ...(decision !== undefined ? { decision } : {}),
1126
- ...(remember.presence === 'present' && typeof remember.value === 'boolean' ? { rememberApplied: remember.value } : {}),
1205
+ ...(typeof remember === 'boolean' ? { rememberApplied: remember } : {}),
1127
1206
  };
1128
1207
  }
1129
1208
  function replayedDecisionOf(first, sent, ack) {
1130
1209
  return { kind: 'decided', lane: 'respond', decision: first, ...(ack !== undefined ? { ack } : {}), settledElsewhere: toolPermissionSettledElsewhereOf(first, sent) };
1131
1210
  }
1132
1211
  function isNonEmptyStringArray(v) {
1133
- return Array.isArray(v) && v.length > 0 && v.every(x => typeof x === 'string' && x !== '');
1212
+ if (!Array.isArray(v) || v.length === 0)
1213
+ return false;
1214
+ for (let i = 0; i < v.length; i++) {
1215
+ const x = v[i];
1216
+ if (typeof x !== 'string' || x === '')
1217
+ return false;
1218
+ }
1219
+ return true;
1134
1220
  }
1135
1221
  function readPersistedRuleAnchors(v) {
1136
1222
  if (!Array.isArray(v) || v.length === 0)
@@ -1854,6 +1940,67 @@ function subagentBadgeFor(frame) {
1854
1940
  name = `${name.slice(0, 31)}…`;
1855
1941
  return { name, color: 'cyan' };
1856
1942
  }
1943
+ const APPROVAL_CARD_FACT_KEYS = [
1944
+ 'toolName', 'args', 'toolCallId', 'workerBadge', 'wireNote', 'argsUnavailable', 'inputSource', 'governanceForced', 'delegation', 'ruleOffersReadOnly',
1945
+ 'inputHasBidi', 'allowRuleShadow', 'probeCause', 'rememberRefused', 'ruleEvidence', 'requiresRealApproval', 'ruleOffersAbsence', 'denialLimitFallback',
1946
+ 'askClass', 'classes', 'agentId', 'askReasons', 'grantBinding', 'unreadableEvidence', 'message', 'approvalCard',
1947
+ 'argsRewritten', 'ruleOffers', 'probeReason', 'mandated', 'mandate', 'readRootCandidate', 'origin', 'boundGrants', 'classifierNoRuling',
1948
+ 'allowSessionCarried', 'cardPayloadUnreadable', 'cardPayloadUnreadableWhy', 'requestedBy',
1949
+ ];
1950
+ const APPROVAL_CARD_HOST_KEYS = ['callKey', 'taskId', 'signal', 'expiresInMs', 'expiresAtMs', 'serverNowMs', 'receivedAtMs', 'sourceGeneration'];
1951
+ const _pinCardRequestPartition = [true, true, true, true, true];
1952
+ void _pinCardRequestPartition;
1953
+ const FACT_KEY_SET = new Set(APPROVAL_CARD_FACT_KEYS);
1954
+ const HOST_KEY_SET = new Set(APPROVAL_CARD_HOST_KEYS);
1955
+ function hostBitInDomain(key, v) {
1956
+ switch (key) {
1957
+ case 'callKey':
1958
+ case 'taskId':
1959
+ return typeof v === 'string' && v !== '';
1960
+ case 'signal':
1961
+ return typeof v === 'object' && v !== null;
1962
+ case 'sourceGeneration':
1963
+ return typeof v === 'number' && Number.isFinite(v);
1964
+ default:
1965
+ return typeof v === 'number' && Number.isFinite(v) && v >= 0;
1966
+ }
1967
+ }
1968
+ function closedKeysListing(from) {
1969
+ try {
1970
+ return { kind: 'listed', keys: Reflect.ownKeys(from) };
1971
+ }
1972
+ catch {
1973
+ return { kind: 'unreadable' };
1974
+ }
1975
+ }
1976
+ function copyClosedKeys(into, from, keys, admit) {
1977
+ const listed = closedKeysListing(from);
1978
+ if (listed.kind === 'unreadable')
1979
+ return;
1980
+ for (let i = 0; i < listed.keys.length; i += 1) {
1981
+ const k = listed.keys[i];
1982
+ if (typeof k !== 'string' || !keys.has(k))
1983
+ continue;
1984
+ const v = guardedRead(() => ownSendableField(from, k));
1985
+ if (v === undefined || (admit !== undefined && !admit(k, v)))
1986
+ continue;
1987
+ into[k] = v;
1988
+ }
1989
+ }
1990
+ function cardRequestOf(facts, host) {
1991
+ const out = {};
1992
+ copyClosedKeys(out, facts, FACT_KEY_SET);
1993
+ copyClosedKeys(out, host, HOST_KEY_SET, (k, v) => hostBitInDomain(k, v));
1994
+ return out;
1995
+ }
1996
+ export function approvalCardRequestOf(facts, host) {
1997
+ if (typeof facts !== 'object' || facts === null || typeof host !== 'object' || host === null)
1998
+ return undefined;
1999
+ const out = cardRequestOf(facts, host);
2000
+ if (typeof out.toolName !== 'string' || typeof out.args !== 'object' || out.args === null || typeof out.callKey !== 'string')
2001
+ return undefined;
2002
+ return out;
2003
+ }
1857
2004
  function v1Bit(stamp) {
1858
2005
  try {
1859
2006
  stamp();
@@ -1899,7 +2046,7 @@ function cardFactsOf(carrier, leg, opts, liveFacts, approvalId, payloadWhy) {
1899
2046
  if (reading.from === 'stream' && typeof reading.args === 'object' && reading.args !== null) {
1900
2047
  if (blind)
1901
2048
  return { args: reading.args, argsUnavailable: true };
1902
- return { args: reading.args, wireNote: ARGS_FROM_MODEL_CALL_NOTE, ...inputSourceBitOf(reading) };
2049
+ return { args: reading.args, ...argsFromModelCallBitsOf(), ...inputSourceBitOf(reading) };
1903
2050
  }
1904
2051
  const omitted = c.argsOmitted === true || reading.shape === 'size_marker';
1905
2052
  const fallback = argsFallbackOf(c.message, omitted);
@@ -2117,7 +2264,9 @@ export async function surfaceApprovalFrameWithId(frame, approvalId, respond, str
2117
2264
  return approvalIdUnreadableRefusal();
2118
2265
  const carriers = openingFrameCarriersOf(frame);
2119
2266
  const liveRun = liveCardRunOf(frame, run);
2120
- const entry = { frame, carriers, approvalId, identity: liveCardIdentityOf(approvalId, carriers, liveRun), respond, streamArgs, signal, lane, receivedAtMs };
2267
+ const sourceGenerationRaw = guardedRead(() => readOwnDataValue(run, 'sourceGeneration'));
2268
+ const sourceGeneration = typeof sourceGenerationRaw === 'number' && Number.isFinite(sourceGenerationRaw) ? sourceGenerationRaw : undefined;
2269
+ const entry = { frame, carriers, approvalId, identity: liveCardIdentityOf(approvalId, carriers, liveRun), respond, streamArgs, signal, lane, receivedAtMs, sourceGeneration };
2121
2270
  return enterLiveCard(entry);
2122
2271
  }
2123
2272
  function openingFrameCarriersOf(frame) {
@@ -2143,7 +2292,7 @@ function enterLiveCard(e) {
2143
2292
  return joinOtherLaneHolder(e, other);
2144
2293
  return holdLiveCard(e.identity, signal, async (hold) => {
2145
2294
  const slot = {};
2146
- const out = await presentToolApprovalFrameAndRespond(e.frame, e.carriers, approvalId, e.respond, e.streamArgs, signal, e.lane, hold, slot, e.receivedAtMs, e.identity.taskId);
2295
+ const out = await presentToolApprovalFrameAndRespond(e.frame, e.carriers, approvalId, e.respond, e.streamArgs, signal, e.lane, hold, slot, e.receivedAtMs, e.identity.taskId, e.sourceGeneration);
2147
2296
  noteCallOutcome(slot, out);
2148
2297
  return out;
2149
2298
  });
@@ -2227,7 +2376,7 @@ function readApprovalCardClaimSignal(v) {
2227
2376
  export function claimApprovalCard(identity, options) {
2228
2377
  return claimApprovalCardFor(readApprovalHolderIdentity(identity), readApprovalCardClaimSignal(options));
2229
2378
  }
2230
- async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, respond, streamArgs, signal, lane, hold, ledgerSlot, receivedAtMs, cardTaskId) {
2379
+ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, respond, streamArgs, signal, lane, hold, ledgerSlot, receivedAtMs, cardTaskId, sourceGeneration) {
2231
2380
  const bodyToolCallId = carriers.body.toolCallId;
2232
2381
  const frameToolCallId = typeof bodyToolCallId === 'string' && bodyToolCallId !== '' ? bodyToolCallId : undefined;
2233
2382
  const decidedByReading = decidedByReadingSnapshotOf(lane);
@@ -2235,16 +2384,16 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
2235
2384
  const argsNotRealInput = facts.argsUnavailable === true;
2236
2385
  const editAcceptance = editedApprovalAcceptanceOf(facts);
2237
2386
  const ruleOffers = facts.ruleOffers;
2238
- if (argsNotRealInput && lane?.argsUnavailable !== true && facts.wireNote !== undefined) {
2387
+ if (argsNotRealInput && lane?.argsUnavailable !== true && facts.wireNote !== undefined && facts.inputSource !== 'stream') {
2239
2388
  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)'}`);
2240
2389
  }
2241
- const card = await surfaceCallTrackedCard(frameToolCallId, approvalId, ledgerSlot, {
2242
- ...facts,
2390
+ const card = await surfaceCallTrackedCard(frameToolCallId, approvalId, ledgerSlot, cardRequestOf(facts, {
2243
2391
  callKey: liveFrameCallKey(approvalId),
2244
2392
  ...(cardTaskId !== undefined ? { taskId: cardTaskId } : {}),
2393
+ ...sourceGenerationBit(sourceGeneration),
2245
2394
  signal: hold.cardSignal,
2246
2395
  ...approvalWindowKeysOf(frame, { windowIsCurrent: lane?.windowIsCurrent === true, receivedAtMs, ...(carriers.leg === 'generic' ? { unknownShape: true } : {}) }),
2247
- });
2396
+ }));
2248
2397
  if (hold.superseded !== undefined) {
2249
2398
  hostLog('debug', `liveToolApprovalWire: ${approvalId} was settled by the engine while its card was up${hold.superseded.parked ? ' (parked)' : ''} — card withdrawn; ` +
2250
2399
  `the card came back ${card.kind}; nothing sent`);
@@ -2263,19 +2412,27 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
2263
2412
  hostLog('debug', `liveToolApprovalWire: ${approvalId} card retracted without a decision${card.reason ? ` (${card.reason})` : ''} — nothing sent`);
2264
2413
  return { kind: 'not_sent', lane: 'respond', cause: 'retracted' };
2265
2414
  }
2415
+ const respondParkingOf = (body) => {
2416
+ const p = readToolApprovalRespondParking(body);
2417
+ return p?.kind === 'parking' ? p.view : undefined;
2418
+ };
2419
+ const deliverOnThisCard = (d, body, carrySignal, deliverySignal, ladder, onLadderStep) => deliverApprovalDecision({
2420
+ approvalId,
2421
+ body,
2422
+ send: (o, sig) => respond(approvalId, d, carrySignal && sig !== undefined ? { ...o, signal: sig } : o),
2423
+ signal: deliverySignal,
2424
+ tally: newSendTally(),
2425
+ ladder,
2426
+ ...(onLadderStep !== undefined ? { onLadderStep } : {}),
2427
+ parkingOf: respondParkingOf,
2428
+ });
2266
2429
  if (card.kind === 'aborted') {
2267
2430
  enterLiveRespondPhase(hold);
2268
2431
  const interruptOpts = lane?.approvalDecisionNoteCapable === true ? { note: INTERRUPT_DENY_REASON } : {};
2269
- let interruptDeny;
2270
- try {
2271
- interruptDeny = Promise.resolve(respond(approvalId, 'deny', interruptOpts));
2272
- }
2273
- catch (e) {
2274
- interruptDeny = Promise.reject(e);
2275
- }
2432
+ const interruptDeny = deliverOnThisCard('deny', interruptOpts, true, interruptDenyLifetime(), { lastCarried: false, dropped: false, renamed: false }).then((delivery) => (delivery.kind === 'thrown' ? Promise.reject(delivery.error) : delivery.raw));
2276
2433
  hold.trailing = interruptDeny.then((body) => readToolApprovalRespondParking(body) === undefined, () => false);
2277
2434
  observeCancelByDeny(interruptDeny, approvalId);
2278
- hostLog('debug', `liveToolApprovalWire: ${approvalId} card aborted — one tool-level deny issued to settle the pending ask`);
2435
+ hostLog('debug', `liveToolApprovalWire: ${approvalId} card aborted — a tool-level deny issued to settle the pending ask (bounded retry; at most one is accepted)`);
2279
2436
  return { kind: 'unsettled', lane: 'respond', cause: 'interrupted' };
2280
2437
  }
2281
2438
  enterLiveRespondPhase(hold);
@@ -2398,30 +2555,18 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
2398
2555
  if (basePayload !== undefined)
2399
2556
  emitAnswerCommitted(liveFrameCallKey(approvalId), 'respond', answerSnapshot, basePayload);
2400
2557
  try {
2401
- const delivery = await deliverApprovalDecision({
2402
- approvalId,
2403
- body: respondOpts,
2404
- send: (o, sig) => respond(approvalId, decision, !signalPreAborted && sig !== undefined ? { ...o, signal: sig } : o),
2405
- signal,
2406
- tally: newSendTally(),
2407
- ladder,
2408
- onLadderStep: (step) => {
2409
- hostLog('debug', step === 'renamed'
2410
- ? `liveToolApprovalWire: respond(deny) for ${approvalId} was refused because the settlement note was sent under a name ` +
2411
- 'this engine has retired — re-sending the SAME decision exactly once with that one key renamed to the name the refusal points to ' +
2558
+ const delivery = await deliverOnThisCard(decision, respondOpts, !signalPreAborted, signal, ladder, (step) => {
2559
+ hostLog('debug', step === 'renamed'
2560
+ ? `liveToolApprovalWire: respond(deny) for ${approvalId} was refused because the settlement note was sent under a name ` +
2561
+ 'this engine has retired — re-sending the SAME decision exactly once with that one key renamed to the name the refusal points to ' +
2562
+ '(the refusal happened before the approval was judged, so nothing was consumed and this is a re-delivery, not a second act)'
2563
+ : step === 'dropped'
2564
+ ? `liveToolApprovalWire: respond(deny) for ${approvalId} was refused because the settlement note is not part of ` +
2565
+ 'what this deployment signs — re-sending the SAME decision exactly once with that one key removed ' +
2412
2566
  '(the refusal happened before the approval was judged, so nothing was consumed and this is a re-delivery, not a second act)'
2413
- : step === 'dropped'
2414
- ? `liveToolApprovalWire: respond(deny) for ${approvalId} was refused because the settlement note is not part of ` +
2415
- 'what this deployment signs — re-sending the SAME decision exactly once with that one key removed ' +
2416
- '(the refusal happened before the approval was judged, so nothing was consumed and this is a re-delivery, not a second act)'
2417
- : `liveToolApprovalWire: respond(deny) for ${approvalId} was refused again because the settlement note is not part of ` +
2418
- 'what this deployment signs — re-sending the SAME decision exactly once more with that key removed ' +
2419
- '(still before the approval was judged)');
2420
- },
2421
- parkingOf: (body) => {
2422
- const p = readToolApprovalRespondParking(body);
2423
- return p?.kind === 'parking' ? p.view : undefined;
2424
- },
2567
+ : `liveToolApprovalWire: respond(deny) for ${approvalId} was refused again because the settlement note is not part of ` +
2568
+ 'what this deployment signs — re-sending the SAME decision exactly once more with that key removed ' +
2569
+ '(still before the approval was judged)');
2425
2570
  });
2426
2571
  if (delivery.kind === 'thrown') {
2427
2572
  deliveryFailure = delivery;
@@ -2450,15 +2595,13 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
2450
2595
  return { kind: 'unsettled', lane: 'respond', cause: 'unreadable' };
2451
2596
  }
2452
2597
  const parsed = settlementAckOf(readToolApprovalRespondAck(raw));
2453
- const replayedForThisCard = parsed !== undefined && isToolApprovalRespondReplayed(parsed) && parsed.approvalId === approvalId;
2454
- const claimsReplay = ownIdempotentTrue(raw) || replayedFirstDecisionOf(parsed) !== undefined;
2455
- if (claimsReplay && !replayedForThisCard) {
2456
- const claimed = replayClaimOf(raw);
2457
- if (claimed.approvalId === approvalId && claimed.decision !== undefined && !claimed.carriesDelivery) {
2458
- hostLog('debug', `liveToolApprovalWire: respond(${decision}) for ${approvalId} answered with a replay (body not in the full replay shape) — the approval was already decided ` +
2459
- `(${claimed.decision}); this answer was not delivered, reporting the earlier decision`);
2460
- return replayedDecisionOf(claimed.decision, decision, parsed !== undefined && isToolApprovalRespondParkedRedeemed(parsed) && parsed.approvalId === approvalId ? parsed : undefined);
2461
- }
2598
+ const replayVerdict = replayVerdictFrom(raw, parsed, approvalId);
2599
+ if (replayVerdict.kind === 'replayed' && replayVerdict.via === 'claim') {
2600
+ hostLog('debug', `liveToolApprovalWire: respond(${decision}) for ${approvalId} answered with a replay (body not in the full replay shape) — the approval was already decided ` +
2601
+ `(${replayVerdict.firstDecision}); this answer was not delivered, reporting the earlier decision`);
2602
+ return replayedDecisionOf(replayVerdict.firstDecision, decision, parsed !== undefined && isToolApprovalRespondParkedRedeemed(parsed) && parsed.approvalId === approvalId ? parsed : undefined);
2603
+ }
2604
+ if (replayVerdict.kind === 'unreadable') {
2462
2605
  hostLog('error', `liveToolApprovalWire: respond(${decision}) for ${approvalId} answered with a replay of an earlier decision that cannot be read or names another approval — ` +
2463
2606
  'reporting the answer as NOT settled (never as the decision this client sent); not re-sent');
2464
2607
  return { kind: 'unsettled', lane: 'respond', cause: 'unreadable' };
@@ -1,6 +1,6 @@
1
1
  import { engineVersionTier } from './supportFloor.js';
2
2
  const HOOKS_READER_GENERATIONS = Object.freeze([
3
- Object.freeze({ from: '7.139.0', below: '7.147.0', notRead: Object.freeze(['onFailure']) }),
3
+ Object.freeze({ from: '7.139.0', below: '7.147.0', notRead: Object.freeze(['onFailure', 'rewakeMessage', 'rewakeSummary', 'cloud', 'continueOnBlock']) }),
4
4
  ]);
5
5
  const HOOKS_READER_FAIL_CLOSED = Object.freeze([...new Set(HOOKS_READER_GENERATIONS.flatMap((g) => g.notRead))]);
6
6
  export function hooksReaderNotReadKeys(serverVersion) {