@sema-agent/client-core 0.95.0 → 0.97.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 (233) hide show
  1. package/CHANGELOG.md +269 -0
  2. package/README.md +61 -31
  3. package/dist/adapt/arms.js +7 -1
  4. package/dist/adapt/toolCards.d.ts +1 -0
  5. package/dist/adapt/toolCards.js +16 -3
  6. package/dist/adapt/wireShapes.js +2 -16
  7. package/dist/adapter/activeRunSelfHeal.d.ts +4 -2
  8. package/dist/adapter/activeRunSelfHeal.js +32 -6
  9. package/dist/adapter/downstream/eventToSdkMessage.js +11 -3
  10. package/dist/adapter/downstream/terminalToSdkResult.js +14 -11
  11. package/dist/adapter/runStream.js +30 -47
  12. package/dist/agentSession/backgroundView.js +2 -15
  13. package/dist/agentSession/engineAgentRegistryRead.js +5 -4
  14. package/dist/agentSession/engineSessionBackgroundStop.js +22 -15
  15. package/dist/agentsWireCaps.d.ts +1 -1
  16. package/dist/agentsWireCaps.js +29 -12
  17. package/dist/approvalDecidedByCapability.d.ts +2 -0
  18. package/dist/approvalDecidedByCapability.js +0 -1
  19. package/dist/approvalsStreamLiveCapability.d.ts +2 -0
  20. package/dist/approvalsStreamLiveCapability.js +3 -2
  21. package/dist/attachmentSeatCapability.d.ts +2 -0
  22. package/dist/attachmentSeatCapability.js +0 -1
  23. package/dist/callerCwdCapability.d.ts +2 -4
  24. package/dist/callerCwdCapability.js +0 -7
  25. package/dist/centerWiringCapability.d.ts +2 -4
  26. package/dist/centerWiringCapability.js +4 -9
  27. package/dist/classifierVerdictWire.js +4 -16
  28. package/dist/clientSlice.js +1 -1
  29. package/dist/cloudConfigWireCaps.d.ts +4 -4
  30. package/dist/cloudConfigWireCaps.js +241 -85
  31. package/dist/coreValuePorts.d.ts +11 -7
  32. package/dist/coreValuePorts.js +5 -8
  33. package/dist/credentialProvenance.d.ts +28 -0
  34. package/dist/credentialProvenance.js +76 -0
  35. package/dist/decideFailureNote.js +3 -1
  36. package/dist/decideReceipt.js +7 -10
  37. package/dist/declared/supportFloorDeclared.js +3 -3
  38. package/dist/deviceExecutorManagementCapability.d.ts +2 -0
  39. package/dist/deviceExecutorManagementCapability.js +3 -2
  40. package/dist/displayUntrusted.d.ts +10 -3
  41. package/dist/displayUntrusted.js +371 -60
  42. package/dist/engineCapReader.d.ts +8 -2
  43. package/dist/engineCapReader.js +15 -7
  44. package/dist/engineCapsCache.d.ts +17 -3
  45. package/dist/engineCapsCache.js +268 -43
  46. package/dist/engineDirectory.d.ts +79 -0
  47. package/dist/engineDirectory.js +186 -0
  48. package/dist/engineErrorCodes.d.ts +17 -1
  49. package/dist/engineErrorCodes.js +46 -16
  50. package/dist/engineNoticeCodes.d.ts +17 -0
  51. package/dist/engineNoticeCodes.js +54 -1
  52. package/dist/executionLaneCapability.d.ts +2 -0
  53. package/dist/executionLaneCapability.js +3 -2
  54. package/dist/fileHistoryCaptureCapability.d.ts +16 -0
  55. package/dist/fileHistoryCaptureCapability.js +98 -2
  56. package/dist/fileHistoryLegNotice.js +4 -0
  57. package/dist/fleet/bgSubagentRow.d.ts +15 -0
  58. package/dist/fleet/bgSubagentRow.js +67 -0
  59. package/dist/fleet/fleetLedger.d.ts +1 -0
  60. package/dist/fleet/fleetLedger.js +164 -126
  61. package/dist/fleet/fleetProjection.d.ts +1 -0
  62. package/dist/fleet/fleetProjection.js +10 -3
  63. package/dist/fleetTaskDesc.js +4 -17
  64. package/dist/gateOutcome.d.ts +12 -1
  65. package/dist/gateOutcome.js +56 -1
  66. package/dist/gateVocabulary.d.ts +2 -2
  67. package/dist/gateVocabulary.js +4 -3
  68. package/dist/generated/engineAskFaceTables.js +1 -1
  69. package/dist/generated/engineFactTables.d.ts +5 -3
  70. package/dist/generated/engineFactTables.js +17 -4
  71. package/dist/generated/engineNoticeTables.js +12 -3
  72. package/dist/generated/sdkFactTables.d.ts +2 -0
  73. package/dist/generated/sdkFactTables.js +7 -0
  74. package/dist/generated/settingsSchemaFns.d.ts +3 -0
  75. package/dist/generated/settingsSchemaFns.js +53 -0
  76. package/dist/generated/toolNameTables.d.ts +1 -1
  77. package/dist/generated/toolNameTables.js +1 -42
  78. package/dist/hitl/approvalDecisionNoteAudit.js +2 -2
  79. package/dist/hitl/approvalEndingCause.d.ts +2 -0
  80. package/dist/hitl/approvalEndingCause.js +26 -21
  81. package/dist/hitl/approvalHolds.d.ts +16 -1
  82. package/dist/hitl/approvalHolds.js +52 -12
  83. package/dist/hitl/askGateWire.js +1 -0
  84. package/dist/hitl/askParkRowRouting.js +1 -1
  85. package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
  86. package/dist/hitl/automaticAnswerVerdict.js +13 -10
  87. package/dist/hitl/decisionConflict.js +4 -5
  88. package/dist/hitl/decisionRefusal.d.ts +8 -0
  89. package/dist/hitl/decisionRefusal.js +55 -14
  90. package/dist/hitl/frameRouter.d.ts +3 -1
  91. package/dist/hitl/frameRouter.js +58 -39
  92. package/dist/hitl/gateLedger.d.ts +0 -5
  93. package/dist/hitl/gateLedger.js +0 -21
  94. package/dist/hitl/hitlBridge.d.ts +6 -2
  95. package/dist/hitl/hitlBridge.js +46 -11
  96. package/dist/hitl/localAllowRule.d.ts +1 -0
  97. package/dist/hitl/localAllowRule.js +2 -2
  98. package/dist/hitl/noAllowCause.d.ts +2 -1
  99. package/dist/hitl/noAllowCause.js +3 -2
  100. package/dist/hitl/parkResolver.d.ts +1 -0
  101. package/dist/hitl/parkResolver.js +14 -56
  102. package/dist/hitl/parkRowBirthWait.d.ts +1 -0
  103. package/dist/hitl/parkRowBirthWait.js +2 -2
  104. package/dist/hitl/planReviewWire.d.ts +1 -0
  105. package/dist/hitl/planReviewWire.js +98 -20
  106. package/dist/hitl/replayedApproval.d.ts +3 -3
  107. package/dist/hitl/replayedApproval.js +21 -16
  108. package/dist/hitl/sessionPolicyDeliverable.d.ts +0 -1
  109. package/dist/hitl/sessionPolicyDeliverable.js +17 -17
  110. package/dist/hitl/sessionPolicyWire.d.ts +2 -0
  111. package/dist/hitl/sessionPolicyWire.js +15 -3
  112. package/dist/hitl/standingRows.d.ts +19 -0
  113. package/dist/hitl/standingRows.js +148 -0
  114. package/dist/hitl/suspendedReopen.js +2 -1
  115. package/dist/hitl/toolApprovalWire.d.ts +22 -10
  116. package/dist/hitl/toolApprovalWire.js +286 -47
  117. package/dist/hookMatcherVerdict.d.ts +1 -9
  118. package/dist/hookMatcherVerdict.js +21 -61
  119. package/dist/hooksWireCaps.js +2 -2
  120. package/dist/hostCallbackGuard.d.ts +1 -0
  121. package/dist/hostCallbackGuard.js +6 -0
  122. package/dist/index.d.ts +26 -12
  123. package/dist/index.js +20 -10
  124. package/dist/liveModelCatalog.d.ts +13 -0
  125. package/dist/liveModelCatalog.js +56 -0
  126. package/dist/mcpProbeCapability.d.ts +2 -4
  127. package/dist/mcpProbeCapability.js +3 -8
  128. package/dist/mcpWireCaps.d.ts +1 -0
  129. package/dist/mcpWireCaps.js +4 -1
  130. package/dist/memoryComplianceCapability.d.ts +2 -4
  131. package/dist/memoryComplianceCapability.js +3 -8
  132. package/dist/memoryOriginCapability.d.ts +2 -4
  133. package/dist/memoryOriginCapability.js +3 -8
  134. package/dist/memorySpecWire.js +2 -2
  135. package/dist/modelIdentityResolvability.d.ts +2 -2
  136. package/dist/modelIdentityResolvability.js +14 -5
  137. package/dist/noticePresentation.d.ts +68 -0
  138. package/dist/noticePresentation.js +247 -0
  139. package/dist/outputStyleSeatCapability.d.ts +2 -1
  140. package/dist/outputStyleSeatCapability.js +0 -4
  141. package/dist/ownKey.d.ts +2 -0
  142. package/dist/ownKey.js +18 -0
  143. package/dist/peerFrames.js +13 -9
  144. package/dist/peerLaneCapability.d.ts +2 -0
  145. package/dist/peerLaneCapability.js +3 -2
  146. package/dist/permissionModesCapability.d.ts +2 -4
  147. package/dist/permissionModesCapability.js +0 -7
  148. package/dist/permissionRuleIssue.js +0 -3
  149. package/dist/permissionRulesWriteCapability.d.ts +2 -0
  150. package/dist/permissionRulesWriteCapability.js +3 -2
  151. package/dist/permissionsAllowGrantCapability.d.ts +2 -0
  152. package/dist/permissionsAllowGrantCapability.js +4 -2
  153. package/dist/permissionsDeclaration.d.ts +2 -0
  154. package/dist/permissionsDeclaration.js +72 -59
  155. package/dist/printPermissionOutcome.d.ts +12 -0
  156. package/dist/printPermissionOutcome.js +50 -0
  157. package/dist/printToolResultFrame.d.ts +1 -0
  158. package/dist/printToolResultFrame.js +5 -9
  159. package/dist/promptBlockedCopy.d.ts +5 -0
  160. package/dist/promptBlockedCopy.js +35 -0
  161. package/dist/protocolSegment.d.ts +9 -6
  162. package/dist/protocolSegment.js +31 -21
  163. package/dist/providerRejection.d.ts +4 -0
  164. package/dist/providerRejection.js +75 -14
  165. package/dist/replayBody.d.ts +12 -0
  166. package/dist/replayBody.js +25 -0
  167. package/dist/request/taskRequest.d.ts +1 -4
  168. package/dist/request/taskRequest.js +74 -19
  169. package/dist/resumeRefusalCopy.js +9 -25
  170. package/dist/retryStatus.d.ts +9 -1
  171. package/dist/retryStatus.js +9 -2
  172. package/dist/rewindArchiveCapability.d.ts +3 -13
  173. package/dist/rewindArchiveCapability.js +12 -58
  174. package/dist/rewindArchiveReading.d.ts +17 -0
  175. package/dist/rewindArchiveReading.js +55 -0
  176. package/dist/ruleCompileVerdict.d.ts +9 -1
  177. package/dist/ruleCompileVerdict.js +29 -4
  178. package/dist/runTerminal.d.ts +48 -5
  179. package/dist/runTerminal.js +215 -12
  180. package/dist/sandboxWire.js +13 -0
  181. package/dist/sdkWireTransit.d.ts +2 -1
  182. package/dist/sdkWireTransit.js +1 -0
  183. package/dist/sealedKeyCapability.d.ts +2 -4
  184. package/dist/sealedKeyCapability.js +0 -7
  185. package/dist/seam.js +4 -2
  186. package/dist/seatContract.d.ts +76 -11
  187. package/dist/seatContract.js +222 -27
  188. package/dist/sessionPolicyCapability.d.ts +2 -0
  189. package/dist/sessionPolicyCapability.js +3 -2
  190. package/dist/sessionReadRedactionCapability.d.ts +2 -4
  191. package/dist/sessionReadRedactionCapability.js +0 -7
  192. package/dist/sessionSyncFileHistory.d.ts +4 -0
  193. package/dist/sessionSyncFileHistory.js +66 -0
  194. package/dist/sessionSyncFileHistoryCapability.d.ts +2 -1
  195. package/dist/sessionSyncFileHistoryCapability.js +3 -5
  196. package/dist/skillToolListsCapability.d.ts +2 -1
  197. package/dist/skillToolListsCapability.js +3 -5
  198. package/dist/sqlEngineCapability.d.ts +2 -0
  199. package/dist/sqlEngineCapability.js +4 -3
  200. package/dist/steerPriorityCapability.d.ts +2 -1
  201. package/dist/steerPriorityCapability.js +3 -5
  202. package/dist/storePostureCapability.d.ts +2 -4
  203. package/dist/storePostureCapability.js +4 -9
  204. package/dist/subagent/engineSubagentSteer.js +7 -5
  205. package/dist/subagentContentStore.js +4 -15
  206. package/dist/supportFloor.d.ts +1 -0
  207. package/dist/supportFloor.js +13 -9
  208. package/dist/systemReminderTag.d.ts +1 -0
  209. package/dist/systemReminderTag.js +8 -0
  210. package/dist/toolHistoryBadTurn.js +3 -2
  211. package/dist/toolHistoryMismatch.d.ts +0 -3
  212. package/dist/toolHistoryMismatch.js +3 -7
  213. package/dist/toolResult.d.ts +12 -1
  214. package/dist/toolResult.js +55 -1
  215. package/dist/toolResultContent.d.ts +2 -0
  216. package/dist/toolResultContent.js +63 -0
  217. package/dist/usageAnalytics.js +40 -16
  218. package/dist/userInvokedSkillsCapability.d.ts +2 -1
  219. package/dist/userInvokedSkillsCapability.js +3 -5
  220. package/dist/webSearchBackendCapability.d.ts +2 -0
  221. package/dist/webSearchBackendCapability.js +3 -2
  222. package/dist/wireErrorTriage.d.ts +2 -0
  223. package/dist/wireErrorTriage.js +91 -38
  224. package/dist/wireFailureShape.d.ts +20 -3
  225. package/dist/wireFailureShape.js +128 -72
  226. package/dist/workflowsJournalCapability.d.ts +2 -0
  227. package/dist/workflowsJournalCapability.js +3 -2
  228. package/dist/writeProtectionCapability.d.ts +2 -0
  229. package/dist/writeProtectionCapability.js +3 -2
  230. package/docs/INTEGRATION-CLIENTS.md +1784 -20
  231. package/package.json +5 -5
  232. package/dist/engineRefusedToolName.d.ts +0 -1
  233. package/dist/engineRefusedToolName.js +0 -8
@@ -1,31 +1,29 @@
1
- import { APPROVAL_CARD_PORT_KEY_MISMATCH_REASON, DEFAULT_DENY_REASON, DecideTransportRetryExhaustedError, HitlBridge, NO_APPROVAL_CARD_PORT_REASON, denyReasonForWire, findPendingForTask, hitlSafetyCodeOf, readDecideCurrentPending, readWireErrorCode, readWireErrorCodeReading, } from './hitlBridge.js';
1
+ import { APPROVAL_CARD_PORT_KEY_MISMATCH_REASON, DEFAULT_DENY_REASON, DecideTransportRetryExhaustedError, HitlBridge, NO_APPROVAL_CARD_PORT_REASON, denyReasonForWire, findPendingForTask, hitlSafetyCodeOf, readDecideCurrentPending, readWireCodes, readWireErrorCodeReading, } from './hitlBridge.js';
2
2
  import { askParkRowArm } from './askParkRowRouting.js';
3
+ import { parkGateArmOf } from './frameRouter.js';
4
+ import { seatSessionRowOf } from './standingRows.js';
3
5
  import { hostLog } from '../host.js';
4
- import { readAskOrigin, readOwnDataNonEmptyString, readOwnDataValue, readOwnNonEmptyString } from '../ownKey.js';
6
+ import { guardedRead, readAskOrigin, readOwnDataNonEmptyString, readOwnDataValue, readOwnNonEmptyString } from '../ownKey.js';
5
7
  import { readAskClassPair } from './askClassPair.js';
6
8
  import { readAllowRuleShadowFromWire } from './allowRuleShadow.js';
7
9
  import { createSessionSlot, DEFAULT_SESSION_KEY } from '../sessionSlot.js';
8
10
  import { readEngineActiveBgTasks } from '../fleet/fleetLedger.js';
11
+ import { CORE_SKILL_TOOL_NAME } from '../generated/toolNameTables.js';
9
12
  import { INTERRUPT_DENY_REASON, observeCancelByDeny, surfaceApprovalParking, surfaceRememberNotApplied, surfaceEditNotForwarded, surfaceEditRefusedOnBlindAsk, surfaceRuleArmNotSent, surfaceRuleArmRejected } from './hitlHostSurface.js';
10
13
  import { approvalCallKey, liveFrameCallKey } from './gateIdentity.js';
11
14
  import { displayUntrusted } from '../displayUntrusted.js';
12
- import { approvalDecisionHolds, awaitLiveCardHolder, holdLiveCard, joinLiveCard, liveCardHoldFor, liveCardHoldOf } from './approvalHolds.js';
15
+ import { approvalDecisionHolds, awaitLiveCardHolder, holdLiveCard, joinLiveCard, liveCardHoldFor, liveCardHoldOf, clearSettledApprovals, settledApprovalOf, settledForDurableLane, settledLiveCardOutcome } from './approvalHolds.js';
13
16
  import { approvalResolutionOf } from './approvalResolution.js';
14
17
  import { isApprovalMandateWord } from '../gateVocabulary.js';
15
18
  import { denyAttributionRefusalFromError } from '../wireRefusalCopy.js';
16
19
  import { approvalDecidedByAdmitted } from '../approvalDecidedByCapability.js';
17
20
  import { decideFailureNote } from '../decideFailureNote.js';
18
- import { thrownIsInstanceOf, wireFailureTextsOf } from '../wireFailureShape.js';
21
+ import { readRefusalField, thrownIsInstanceOf, wireFailureTextsOf } from '../wireFailureShape.js';
22
+ import { refusalCauseWordOf } from './approvalEndingCause.js';
23
+ import { readDecisionRefusalAsk } from './decisionRefusal.js';
19
24
  import { DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, refusalSaysStillPending } from '../engineErrorCodes.js';
20
25
  import { readDecideReceipt } from '../decideReceipt.js';
21
- import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, ASK_ORIGINS, PERSISTED_RULE_MANDATES, } from '@sema-agent/sdk';
22
- export function isFsApprovalGate(gate) {
23
- if (!gate)
24
- return false;
25
- if (gate.kind === 'tool_approval')
26
- return true;
27
- return typeof gate.toolName === 'string' && toolNameIsFsWrite(gate.toolName);
28
- }
26
+ import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, ASK_ORIGINS, TOOL_APPROVAL_CARD_WORDS, } from '@sema-agent/sdk';
29
27
  export function toolNameIsFsWrite(name) {
30
28
  const n = name.replace(/[\s_-]+/g, '').toLowerCase();
31
29
  return (n === 'write' || n === 'filewrite' || n === 'edit' || n === 'fileedit' || n === 'multiedit' || n === 'notebookedit');
@@ -34,9 +32,13 @@ export function toolNameIsShellExec(name) {
34
32
  return name.replace(/[\s_-]+/g, '').toLowerCase() === 'bash';
35
33
  }
36
34
  export function isToolApprovalGate(gate) {
37
- if (isFsApprovalGate(gate))
38
- return true;
39
- return typeof gate?.toolName === 'string' && toolNameIsShellExec(gate.toolName);
35
+ return parkGateArmOf(gate) === 'fs';
36
+ }
37
+ function fallbackRowMatcherFor(parkToolName) {
38
+ const family = (toolName) => toolName !== undefined && (toolNameIsFsWrite(toolName) || toolNameIsShellExec(toolName));
39
+ if (parkToolName === undefined || parkToolName === '' || family(parkToolName))
40
+ return family;
41
+ return (toolName) => toolName === parkToolName;
40
42
  }
41
43
  export function structurallyEqual(a, b) {
42
44
  if (a === b)
@@ -61,7 +63,6 @@ export function structurallyEqual(a, b) {
61
63
  export { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS };
62
64
  export { RULE_OFFERS_ABSENCE_REASONS };
63
65
  export const ASK_ORIGIN_WORDS = ASK_ORIGINS;
64
- export const APPROVAL_MANDATE_WORDS = PERSISTED_RULE_MANDATES;
65
66
  export const APPROVAL_DENY_SETTLED_BY_WORDS = Object.freeze(['human', 'policy']);
66
67
  export function readApprovalDenySettledBy(decision) {
67
68
  if (decision === null || typeof decision !== 'object')
@@ -111,6 +112,9 @@ export function hasApprovalCardPortFor(sessionKey) {
111
112
  export function approvalCardPortFor(sessionKey) {
112
113
  return cardPortByKey.get(sessionKey) ?? null;
113
114
  }
115
+ export function __resetSettledApprovalsForTests() {
116
+ clearSettledApprovals();
117
+ }
114
118
  export function _resetApprovalCardPortForTest() {
115
119
  cardPortByKey.clear();
116
120
  cardPortMissesByKey.clear();
@@ -166,6 +170,14 @@ const ARGS_OMITTED_PATH_RECOVERED_NOTE = 'tool arguments exceeded the wire cap a
166
170
  const ARGS_OMITTED_NOTHING_RECOVERED_NOTE = 'tool arguments exceeded the wire cap and were omitted, and nothing could be recovered from the approval question — ' +
167
171
  'you are deciding without seeing what this call will do; deny it if you are not sure. ' +
168
172
  'Edits are not accepted on this card: there is no original input to edit';
173
+ function argsFallbackOf(message, argsOmitted) {
174
+ const p = pathFromGateMessage(typeof message === 'string' ? message : undefined);
175
+ return {
176
+ args: p !== undefined ? { file_path: p } : {},
177
+ pathRecovered: p !== undefined,
178
+ ...(argsOmitted === true ? { omittedNote: p !== undefined ? ARGS_OMITTED_PATH_RECOVERED_NOTE : ARGS_OMITTED_NOTHING_RECOVERED_NOTE } : {}),
179
+ };
180
+ }
169
181
  const PARK_ROW_ARGS_ABSENT_NOTE = "this request's tool arguments are not available on this surface — neither the event stream nor the pending approval record " +
170
182
  'carries them, so you are deciding without seeing them; deny it if you are not sure what it will do. ' +
171
183
  'Edits are not accepted on this card: there is no original input to edit';
@@ -273,13 +285,13 @@ async function joinDurableDecision(hold, deps, signal) {
273
285
  }
274
286
  return { ...o, joinedInFlight: true };
275
287
  }
276
- export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signal, parkGatedCallId) {
288
+ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signal, parkGatedCallId, parkToolName) {
277
289
  const decidedByReading = decidedByReadingSnapshotOf(deps);
278
290
  const readMark = openDurableRead();
279
291
  let found;
280
292
  let held;
281
293
  try {
282
- found = await findPendingForTask(deps.client, taskId, (toolName) => toolName !== undefined && (toolNameIsFsWrite(toolName) || toolNameIsShellExec(toolName)), signal ? { signal } : undefined, parkGatedCallId, (row) => askParkRowArm(row) === 'tool-gate');
294
+ found = await findPendingForTask(deps.client, taskId, fallbackRowMatcherFor(parkToolName), signal ? { signal } : undefined, parkGatedCallId, (row) => askParkRowArm(row) === 'tool-gate');
283
295
  if (found.ok)
284
296
  held = heldDurableDecision(durableHoldKey(found.pending, approvalCallKey(found.gatedCallId, taskId)), readMark);
285
297
  }
@@ -295,7 +307,7 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
295
307
  const joined = await awaitLiveCardHolder(liveHolder, signal);
296
308
  if (joined !== undefined)
297
309
  return fsOutcomeOfJoinedLiveCard(joined, found.gatedCallId);
298
- return surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signal, parkGatedCallId);
310
+ return surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signal, parkGatedCallId, parkToolName);
299
311
  }
300
312
  const callKey = approvalCallKey(found.gatedCallId, taskId);
301
313
  const fetched = found;
@@ -357,7 +369,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
357
369
  const durableRuleOffersAbsence = pending.ruleOffersAbsence;
358
370
  hold.presented = true;
359
371
  deps.onPresented?.();
360
- const card = await surfaceCallTrackedCard(gatedCallId, undefined, ledgerSlot, {
372
+ const card = await surfaceCallTrackedCard(gatedCallId, undefined, ledgerSlot, withUnreadableEvidence(pending, 'row', {
361
373
  toolName,
362
374
  args,
363
375
  callKey,
@@ -373,6 +385,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
373
385
  ...(hasOwnStrictTrue(pending, 'mandated') ? { mandated: true } : {}),
374
386
  ...((w) => (w !== undefined ? { mandate: w } : {}))(readApprovalMandate(pending)),
375
387
  ...((o) => (o !== undefined ? { origin: o } : {}))(readAskOrigin(pending)),
388
+ ...((w) => (w !== undefined ? { approvalCard: w } : {}))(readApprovalCardWord(pending)),
376
389
  ...(readAskClassPair(pending) ?? {}),
377
390
  ...(pending.gateKind === 'irreversible_ask' ? { irreversibleParkGate: true } : {}),
378
391
  ...(pending.hasBidiControls === true ? { hasBidiControls: true } : {}),
@@ -387,7 +400,9 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
387
400
  ...(typeof pending.toolCallId === 'string' && pending.toolCallId !== ''
388
401
  ? { toolCallId: pending.toolCallId }
389
402
  : {}),
390
- });
403
+ allowSessionCarried: true,
404
+ grantBinding: readApprovalGrantBinding(pending),
405
+ }));
391
406
  if (rowArgsGap !== undefined && card.kind === 'allow' && card.updatedInput !== undefined) {
392
407
  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)`);
393
408
  surfaceEditRefusedOnBlindAsk();
@@ -441,7 +456,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
441
456
  }
442
457
  catch (e) {
443
458
  const currentPending = readDecideCurrentPending(e);
444
- const wireCode = readWireErrorCode(e);
459
+ const wireCodes = readWireCodes(e);
445
460
  const wireRetriable = typeof e === 'object' && e !== null && refusalSaysStillPending(e);
446
461
  const safetyCode = hitlSafetyCodeOf(e);
447
462
  const failureTexts = wireFailureTextsOf(e);
@@ -453,7 +468,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
453
468
  reason: `decide(approve) failed: ${failureTexts.reason}${decideFailureNote(e, 'approve')}`,
454
469
  ...(thrownIsInstanceOf(e, DecideTransportRetryExhaustedError) ? { retryExhausted: true } : {}),
455
470
  ...(currentPending !== undefined ? { currentPending } : {}),
456
- ...(wireCode !== undefined ? { errorCode: wireCode } : {}),
471
+ ...wireCodes,
457
472
  ...(wireRetriable ? { retriable: true } : {}),
458
473
  ...(safetyCode !== undefined ? { safetyCode } : {}),
459
474
  };
@@ -527,7 +542,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
527
542
  }
528
543
  catch (e) {
529
544
  const currentPending = readDecideCurrentPending(e);
530
- const wireCode = readWireErrorCode(e);
545
+ const wireCodes = readWireCodes(e);
531
546
  const wireRetriable = typeof e === 'object' && e !== null && refusalSaysStillPending(e);
532
547
  const safetyCode = hitlSafetyCodeOf(e);
533
548
  const attributionRefusal = denyAttributionRefusalFromError(e, lastSendCarriedAttribution);
@@ -540,7 +555,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
540
555
  reason: `decide(deny) failed: ${failureTexts.reason}${decideFailureNote(e, 'deny')}`,
541
556
  ...(thrownIsInstanceOf(e, DecideTransportRetryExhaustedError) ? { retryExhausted: true } : {}),
542
557
  ...(currentPending !== undefined ? { currentPending } : {}),
543
- ...(wireCode !== undefined ? { errorCode: wireCode } : {}),
558
+ ...wireCodes,
544
559
  ...(wireRetriable ? { retriable: true } : {}),
545
560
  ...(safetyCode !== undefined ? { safetyCode } : {}),
546
561
  ...(attributionRefusal !== null ? { denyAttributionRefusal: attributionRefusal } : {}),
@@ -584,6 +599,7 @@ export const TOOL_APPROVAL_FRAME_KEYS_MIRROR = [
584
599
  'mandated',
585
600
  'mandate',
586
601
  'origin',
602
+ 'approvalCard',
587
603
  'askClass',
588
604
  'classes',
589
605
  'inputHasBidi',
@@ -625,7 +641,21 @@ export function readApprovalMandate(v) {
625
641
  const raw = v.mandate;
626
642
  return isApprovalMandateWord(raw) ? raw : undefined;
627
643
  }
628
- export function toolPermissionRequestAskBits(card) {
644
+ const APPROVAL_CARD_WORD_SET = new Set(TOOL_APPROVAL_CARD_WORDS);
645
+ export function readApprovalCardWord(carrier) {
646
+ try {
647
+ if (typeof carrier !== 'object' || carrier === null)
648
+ return undefined;
649
+ const d = Object.getOwnPropertyDescriptor(carrier, 'approvalCard');
650
+ if (d === undefined || !('value' in d))
651
+ return undefined;
652
+ return APPROVAL_CARD_WORD_SET.has(d.value) ? d.value : undefined;
653
+ }
654
+ catch {
655
+ return undefined;
656
+ }
657
+ }
658
+ export function toolPermissionRequestAskBits(card, requestId) {
629
659
  if (typeof card !== 'object' || card === null)
630
660
  return {};
631
661
  const mandated = hasOwnStrictTrue(card, 'mandated');
@@ -639,6 +669,7 @@ export function toolPermissionRequestAskBits(card) {
639
669
  ...(origin !== undefined ? { origin } : {}),
640
670
  ...(ruleOffersAbsence !== undefined ? { ruleOffersAbsence } : {}),
641
671
  ...(askClassPair ?? {}),
672
+ ...(seatSessionRowOf(card, requestId) ? { sessionRow: true } : {}),
642
673
  };
643
674
  }
644
675
  function hasOwnStrictTrue(v, key) {
@@ -830,17 +861,28 @@ export function readToolApprovalRespondRefusal(err) {
830
861
  return undefined;
831
862
  }
832
863
  };
833
- const rawStatus = pick('status');
834
- const rawCode = pick('errorCode');
864
+ const pickMachine = (key) => guardedRead(() => (typeof err === 'object' && err !== null ? readOwnDataValue(err, key) : undefined));
865
+ const rawStatus = pickMachine('status');
866
+ const rawCode = pickMachine('errorCode');
835
867
  const status = typeof rawStatus === 'number' && Number.isFinite(rawStatus) ? rawStatus : undefined;
836
868
  const errorCode = typeof rawCode === 'string' && rawCode.length > 0 ? rawCode : undefined;
837
869
  const message = refusalTextOf(err, pick('message'));
838
870
  if (status === undefined && errorCode === undefined && message === undefined)
839
871
  return undefined;
872
+ const machine = typeof err === 'object' && err !== null ? err : undefined;
873
+ const retriable = machine !== undefined && refusalSaysStillPending(machine);
874
+ const cause = machine !== undefined ? refusalCauseWordOf(machine) : undefined;
875
+ const field = machine !== undefined ? readRefusalField(machine) : undefined;
876
+ const unreadable = machine !== undefined && readDecisionRefusalAsk(machine).reading === 'unreadable';
840
877
  const rest = {
841
878
  ...(status !== undefined ? { status } : {}),
842
879
  ...(errorCode !== undefined ? { errorCode } : {}),
843
880
  ...(message !== undefined ? { message } : {}),
881
+ ...(retriable ? { retriable: true } : {}),
882
+ ...(cause !== undefined || field !== undefined
883
+ ? { extra: { ...(cause !== undefined ? { cause } : {}), ...(field !== undefined ? { field } : {}) } }
884
+ : {}),
885
+ ...(unreadable ? { unreadable: true } : {}),
844
886
  };
845
887
  if (status !== undefined)
846
888
  return { ...rest, status };
@@ -906,15 +948,26 @@ function usableProbeReason(raw) {
906
948
  }
907
949
  const PROBE_CAUSE_CODE_WORD = /^[a-z][a-z0-9_]{0,31}(?:\.[a-z][a-z0-9_]{0,31}){1,3}$/;
908
950
  export function askProbeReasonDetail(card) {
909
- const reason = usableProbeReason(ownDataValue(card, 'probeReason'));
910
- if (reason !== undefined)
911
- return displayUntrusted(reason);
912
- const cause = ownDataValue(card, 'probeCause');
913
- if (!isWireRecordCarrier(cause))
951
+ const prose = usableProbeReason(ownDataValue(card, 'probeReason'));
952
+ const shown = prose === undefined ? '' : displayUntrusted(prose);
953
+ const sentence = probeCauseSentence(ownDataValue(card, 'probeCause'), shown !== '');
954
+ if (sentence === undefined)
955
+ return shown === '' ? undefined : shown;
956
+ return shown === '' ? sentence : `${sentence} ${shown}`;
957
+ }
958
+ function probeCauseSentence(cause, withProse) {
959
+ try {
960
+ if (!isWireRecordCarrier(cause))
961
+ return undefined;
962
+ const code = ownDataValue(cause, 'code');
963
+ const head = withProse
964
+ ? 'An automatic check could not clear this call, so it is asking you'
965
+ : 'An automatic check could not clear this call, so it is asking you; the engine did not say the specific reason';
966
+ return typeof code === 'string' && PROBE_CAUSE_CODE_WORD.test(code) ? `${head} (check code: ${code}).` : `${head}.`;
967
+ }
968
+ catch {
914
969
  return undefined;
915
- const code = ownDataValue(cause, 'code');
916
- const head = 'An automatic check could not clear this call, so it is asking you; the engine did not say the specific reason';
917
- return typeof code === 'string' && PROBE_CAUSE_CODE_WORD.test(code) ? `${head} (check code: ${code}).` : `${head}.`;
970
+ }
918
971
  }
919
972
  export function readApprovalRememberRefused(v) {
920
973
  try {
@@ -968,6 +1021,76 @@ export function readApprovalBoundGrants(v) {
968
1021
  return undefined;
969
1022
  return Object.freeze({ skill, allowedTools, disallowedTools });
970
1023
  }
1024
+ function readApprovalGrantBinding(carrier) {
1025
+ if (typeof carrier !== 'object' || carrier === null)
1026
+ return 'unreadable';
1027
+ try {
1028
+ if (Object.hasOwn(carrier, 'boundGrantDigest')) {
1029
+ const digest = ownDataValue(carrier, 'boundGrantDigest');
1030
+ return typeof digest === 'string' && digest.length > 0 ? 'bound' : 'unreadable';
1031
+ }
1032
+ const tool = ownDataValue(carrier, 'toolName');
1033
+ if (typeof tool !== 'string' || tool.length === 0)
1034
+ return 'unreadable';
1035
+ return tool === CORE_SKILL_TOOL_NAME ? 'unreadable' : 'none';
1036
+ }
1037
+ catch {
1038
+ return 'unreadable';
1039
+ }
1040
+ }
1041
+ const UNREADABLE_EVIDENCE_KEYS = Object.freeze({
1042
+ frame: Object.freeze([
1043
+ ['rememberRefused', 'rememberRefused'], ['governanceForced', 'governanceForced'], ['requiresRealApproval', 'requiresRealApproval'],
1044
+ ['mandated', 'mandated'], ['mandate', 'mandate'], ['origin', 'origin'], ['ruleOffersAbsence', 'ruleOffersAbsence'], ['ruleOffers', 'ruleOffers'],
1045
+ ['allowRuleShadowed', 'allowRuleShadow'], ['persistedRuleShadowed', 'allowRuleShadow'], ['askClass', 'askClass'], ['classes', 'classes'],
1046
+ ]),
1047
+ row: Object.freeze([
1048
+ ['rememberRefused', 'rememberRefused'], ['governanceForced', 'governanceForced'], ['requiresRealApproval', 'requiresRealApproval'],
1049
+ ['mandated', 'mandated'], ['mandate', 'mandate'], ['origin', 'origin'], ['ruleOffersAbsence', 'ruleOffersAbsence'], ['ruleOffers', 'ruleOffersReadOnly'],
1050
+ ['askClass', 'askClass'], ['classes', 'classes'],
1051
+ ]),
1052
+ v1: Object.freeze([
1053
+ ['rememberRefused', 'rememberRefused'], ['governanceForced', 'governanceForced'], ['ruleOffersAbsence', 'ruleOffersAbsence'], ['ruleOffers', 'ruleOffersReadOnly'],
1054
+ ['allowRuleShadowed', 'allowRuleShadow'], ['persistedRuleShadowed', 'allowRuleShadow'], ['askClass', 'askClass'], ['classes', 'classes'],
1055
+ ]),
1056
+ });
1057
+ function carrierHas(carrier, key) {
1058
+ if (typeof carrier !== 'object' || carrier === null)
1059
+ return false;
1060
+ try {
1061
+ return key in carrier;
1062
+ }
1063
+ catch {
1064
+ return true;
1065
+ }
1066
+ }
1067
+ function v1RiskUnreadable(card) {
1068
+ if (!carrierHas(card, 'risk'))
1069
+ return false;
1070
+ try {
1071
+ const risk = card.risk;
1072
+ return typeof risk !== 'object' || risk === null || typeof risk.requiresRealApproval !== 'boolean';
1073
+ }
1074
+ catch {
1075
+ return true;
1076
+ }
1077
+ }
1078
+ function withUnreadableEvidence(carrier, leg, req) {
1079
+ const keys = new Set();
1080
+ for (const [from, to] of UNREADABLE_EVIDENCE_KEYS[leg]) {
1081
+ if (carrierHas(carrier, from) && !Object.hasOwn(req, to))
1082
+ keys.add(from);
1083
+ }
1084
+ if (leg === 'row') {
1085
+ const rd = ownDataValue(carrier, 'riskDescriptor');
1086
+ for (const k of ['allowRuleShadowed', 'shadowedRule'])
1087
+ if (carrierHas(rd, k) && !Object.hasOwn(req, 'allowRuleShadow'))
1088
+ keys.add(`riskDescriptor.${k}`);
1089
+ }
1090
+ if (leg === 'v1' && v1RiskUnreadable(carrier))
1091
+ keys.add('risk');
1092
+ return keys.size === 0 ? req : { ...req, unreadableEvidence: Object.freeze([...keys].sort()) };
1093
+ }
971
1094
  const CAUSE_WORD = /^[a-z][a-z0-9_]{0,63}$/;
972
1095
  export function readApprovalClassifierNoRuling(v) {
973
1096
  const w = ownDataValue(v, 'classifierNoRuling');
@@ -1249,12 +1372,122 @@ function subagentBadgeFor(frame) {
1249
1372
  name = `${name.slice(0, 31)}…`;
1250
1373
  return { name, color: 'cyan' };
1251
1374
  }
1375
+ function v1Bit(stamp) {
1376
+ try {
1377
+ stamp();
1378
+ }
1379
+ catch {
1380
+ }
1381
+ }
1382
+ export function approvalCardFactsOfV1(card) {
1383
+ if (typeof card !== 'object' || card === null)
1384
+ return undefined;
1385
+ const c = card;
1386
+ const asFrame = card;
1387
+ const fromSubagent = (() => {
1388
+ try {
1389
+ return isFromSubagent(asFrame);
1390
+ }
1391
+ catch {
1392
+ return false;
1393
+ }
1394
+ })();
1395
+ const argsPart = (() => {
1396
+ try {
1397
+ const raw = c.args !== undefined && c.args !== null ? c.args : undefined;
1398
+ if (typeof raw === 'object' && raw !== null)
1399
+ return { args: raw };
1400
+ const fallback = argsFallbackOf(c.message, c.argsOmitted);
1401
+ return { args: fallback.args, argsUnavailable: true, ...(fallback.omittedNote !== undefined ? { wireNote: fallback.omittedNote } : {}) };
1402
+ }
1403
+ catch {
1404
+ return { args: {}, argsUnavailable: true };
1405
+ }
1406
+ })();
1407
+ const out = { toolName: '', ...argsPart };
1408
+ v1Bit(() => {
1409
+ if (typeof c.toolName === 'string')
1410
+ out.toolName = c.toolName;
1411
+ });
1412
+ v1Bit(() => {
1413
+ if (typeof c.toolCallId === 'string' && c.toolCallId !== '')
1414
+ out.toolCallId = c.toolCallId;
1415
+ });
1416
+ v1Bit(() => {
1417
+ if (fromSubagent)
1418
+ out.workerBadge = subagentBadgeFor(asFrame);
1419
+ });
1420
+ v1Bit(() => {
1421
+ if (c.governanceForced === true)
1422
+ out.governanceForced = true;
1423
+ });
1424
+ v1Bit(() => {
1425
+ const d = c.delegation;
1426
+ if (fromSubagent && isToolApprovalDelegation(d))
1427
+ out.delegation = d;
1428
+ });
1429
+ v1Bit(() => {
1430
+ const offers = readRuleOffers(c.ruleOffers);
1431
+ if (offers !== undefined)
1432
+ out.ruleOffersReadOnly = offers;
1433
+ });
1434
+ v1Bit(() => {
1435
+ const shadow = readAllowRuleShadowFromWire(card, 'frame');
1436
+ if (shadow !== undefined)
1437
+ out.allowRuleShadow = shadow;
1438
+ });
1439
+ v1Bit(() => {
1440
+ const pc = c.probeCause;
1441
+ if (isWireRecordCarrier(pc))
1442
+ out.probeCause = pc;
1443
+ });
1444
+ v1Bit(() => {
1445
+ if (readApprovalRememberRefused(card))
1446
+ out.rememberRefused = true;
1447
+ });
1448
+ v1Bit(() => {
1449
+ const re = c.ruleEvidence;
1450
+ if (isWireRecordCarrier(re))
1451
+ out.ruleEvidence = re;
1452
+ });
1453
+ v1Bit(() => {
1454
+ const risk = c.risk;
1455
+ if (typeof risk === 'object' && risk !== null && risk.requiresRealApproval === true)
1456
+ out.requiresRealApproval = true;
1457
+ });
1458
+ v1Bit(() => {
1459
+ if (c.inputHasBidi === true)
1460
+ out.inputHasBidi = true;
1461
+ });
1462
+ v1Bit(() => {
1463
+ const w = c.ruleOffersAbsence;
1464
+ if (typeof w === 'string' && w !== '')
1465
+ out.ruleOffersAbsence = w;
1466
+ });
1467
+ v1Bit(() => {
1468
+ const dlf = readDenialLimitFallback(c.denialLimitFallback);
1469
+ if (dlf !== undefined)
1470
+ out.denialLimitFallback = dlf;
1471
+ });
1472
+ v1Bit(() => {
1473
+ const pair = readAskClassPair(card);
1474
+ if (pair !== undefined) {
1475
+ out.askClass = pair.askClass;
1476
+ out.classes = pair.classes;
1477
+ }
1478
+ });
1479
+ out.grantBinding = readApprovalGrantBinding(card);
1480
+ return Object.freeze(withUnreadableEvidence(card, 'v1', out));
1481
+ }
1252
1482
  const MAX_RESPOND_NOTE_CHARS = 2048;
1253
1483
  export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamArgs, signal, lane, run) {
1254
1484
  const approvalId = frame.approvalId;
1255
1485
  const held = liveCardHoldOf(liveFrameCallKey(approvalId));
1256
1486
  if (held !== undefined)
1257
1487
  return joinLiveCard(held, signal);
1488
+ const settled = settledLiveCardOutcome(approvalId);
1489
+ if (settled !== undefined)
1490
+ return Promise.resolve(settled);
1258
1491
  return holdLiveCard(liveCardIdentityOf(approvalId, frame, run), signal, async (hold) => {
1259
1492
  const slot = {};
1260
1493
  const out = await presentToolApprovalFrameAndRespond(frame, approvalId, respond, streamArgs, signal, lane, hold, slot);
@@ -1293,9 +1526,12 @@ function readApprovalHolderIdentity(v) {
1293
1526
  return out;
1294
1527
  }
1295
1528
  export async function joinApprovalHolder(identity, signal) {
1296
- const hold = liveCardHoldFor(readApprovalHolderIdentity(identity));
1297
- if (hold === undefined)
1298
- return { kind: 'free' };
1529
+ const who = readApprovalHolderIdentity(identity);
1530
+ const hold = liveCardHoldFor(who);
1531
+ if (hold === undefined) {
1532
+ const entry = settledApprovalOf(who.approvalId);
1533
+ return settledForDurableLane(entry) && entry !== undefined ? { kind: 'joined', outcome: { ...entry.outcome, joinedInFlight: true } } : { kind: 'free' };
1534
+ }
1299
1535
  const joined = await awaitLiveCardHolder(hold, signal);
1300
1536
  return joined !== undefined ? { kind: 'joined', outcome: joined } : { kind: 'free' };
1301
1537
  }
@@ -1312,11 +1548,11 @@ async function presentToolApprovalFrameAndRespond(frame, approvalId, respond, st
1312
1548
  let argsFallback = false;
1313
1549
  if (typeof args !== 'object' || args === null) {
1314
1550
  argsFallback = true;
1315
- const p = pathFromGateMessage(frame.message);
1316
- args = p !== undefined ? { file_path: p } : {};
1317
- if (frame.argsOmitted === true) {
1318
- wireNote = p !== undefined ? ARGS_OMITTED_PATH_RECOVERED_NOTE : ARGS_OMITTED_NOTHING_RECOVERED_NOTE;
1319
- hostLog('debug', `liveToolApprovalWire: frame ${approvalId} args omitted (>16KiB wire cap) — card falls back to ${p !== undefined ? 'the message-derived path' : 'an empty input (no path could be derived from the message)'}`);
1551
+ const fallback = argsFallbackOf(frame.message, frame.argsOmitted);
1552
+ args = fallback.args;
1553
+ if (fallback.omittedNote !== undefined) {
1554
+ wireNote = fallback.omittedNote;
1555
+ hostLog('debug', `liveToolApprovalWire: frame ${approvalId} args omitted (>16KiB wire cap) — card falls back to ${fallback.pathRecovered ? 'the message-derived path' : 'an empty input (no path could be derived from the message)'}`);
1320
1556
  }
1321
1557
  if (lane?.argsUnavailable === true) {
1322
1558
  wireNote =
@@ -1329,7 +1565,7 @@ async function presentToolApprovalFrameAndRespond(frame, approvalId, respond, st
1329
1565
  const ruleOffers = readRuleOffers(frame.ruleOffers);
1330
1566
  const denialLimitFallback = readDenialLimitFallback(frame.denialLimitFallback);
1331
1567
  const frameShadow = readAllowRuleShadowFromWire(frame, 'frame');
1332
- const card = await surfaceCallTrackedCard(frameToolCallId, approvalId, ledgerSlot, {
1568
+ const card = await surfaceCallTrackedCard(frameToolCallId, approvalId, ledgerSlot, withUnreadableEvidence(frame, 'frame', {
1333
1569
  toolName,
1334
1570
  args: args,
1335
1571
  callKey: liveFrameCallKey(approvalId),
@@ -1370,10 +1606,13 @@ async function presentToolApprovalFrameAndRespond(frame, approvalId, respond, st
1370
1606
  : {}),
1371
1607
  ...(denialLimitFallback !== undefined ? { denialLimitFallback } : {}),
1372
1608
  ...((o) => (o !== undefined ? { origin: o } : {}))(readAskOrigin(frame)),
1609
+ ...((w) => (w !== undefined ? { approvalCard: w } : {}))(readApprovalCardWord(frame)),
1373
1610
  ...(readAskClassPair(frame) ?? {}),
1374
1611
  ...((g) => (g !== undefined ? { boundGrants: g } : {}))(readApprovalBoundGrants(frame)),
1375
1612
  ...((w) => (w !== undefined ? { classifierNoRuling: w } : {}))(readApprovalClassifierNoRuling(frame)),
1376
- });
1613
+ allowSessionCarried: true,
1614
+ grantBinding: readApprovalGrantBinding(frame),
1615
+ }));
1377
1616
  if (hold.superseded !== undefined) {
1378
1617
  hostLog('debug', `liveToolApprovalWire: ${approvalId} was settled by the engine while its card was up${hold.superseded.parked ? ' (parked)' : ''} — card withdrawn; ` +
1379
1618
  `the card came back ${card.kind}; nothing sent`);
@@ -1400,7 +1639,7 @@ async function presentToolApprovalFrameAndRespond(frame, approvalId, respond, st
1400
1639
  catch (e) {
1401
1640
  interruptDeny = Promise.reject(e);
1402
1641
  }
1403
- hold.trailing = interruptDeny.then(() => undefined, () => undefined);
1642
+ hold.trailing = interruptDeny.then((body) => readToolApprovalRespondParking(body) === undefined, () => false);
1404
1643
  observeCancelByDeny(interruptDeny, approvalId);
1405
1644
  hostLog('debug', `liveToolApprovalWire: ${approvalId} card aborted — one tool-level deny issued to settle the pending ask`);
1406
1645
  return { decision: 'unresolved', aborted: true };
@@ -3,15 +3,7 @@ export type HookMatcherVerdict = {
3
3
  readonly kind: 'matchesAll';
4
4
  } | {
5
5
  readonly kind: 'accepted';
6
- readonly reading: 'names';
7
- readonly names: readonly string[];
8
- readonly aliases: readonly {
9
- readonly alias: string;
10
- readonly canonical: string;
11
- }[];
12
- } | {
13
- readonly kind: 'accepted';
14
- readonly reading: 'pattern';
6
+ readonly reading: 'names' | 'pattern';
15
7
  readonly aliases: readonly {
16
8
  readonly alias: string;
17
9
  readonly canonical: string;