@sema-agent/client-core 0.97.1 → 0.98.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 (281) hide show
  1. package/CHANGELOG.md +408 -0
  2. package/README.md +74 -37
  3. package/dist/adapt/arms.d.ts +1 -0
  4. package/dist/adapt/arms.js +128 -34
  5. package/dist/adapt/ids.d.ts +12 -1
  6. package/dist/adapt/ids.js +59 -8
  7. package/dist/adapt/instanceLedger.d.ts +50 -0
  8. package/dist/adapt/instanceLedger.js +147 -0
  9. package/dist/adapt/textStream.d.ts +1 -0
  10. package/dist/adapt/textStream.js +24 -7
  11. package/dist/adapt/toolCards.d.ts +27 -5
  12. package/dist/adapt/toolCards.js +39 -6
  13. package/dist/adapt/wireShapes.js +6 -2
  14. package/dist/adapt.d.ts +2 -0
  15. package/dist/adapt.js +8 -3
  16. package/dist/adapter/activeRunSelfHeal.d.ts +5 -0
  17. package/dist/adapter/activeRunSelfHeal.js +51 -28
  18. package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -5
  19. package/dist/adapter/downstream/eventToSdkMessage.js +27 -34
  20. package/dist/adapter/downstream/terminalToSdkResult.js +11 -4
  21. package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +5 -2
  22. package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -0
  23. package/dist/adapter/runStream.js +29 -13
  24. package/dist/adapter/types.d.ts +4 -4
  25. package/dist/agentSession/backgroundView.js +2 -1
  26. package/dist/agentSession/engineAgentRegistryRead.d.ts +2 -2
  27. package/dist/agentSession/engineAgentRegistryRead.js +12 -13
  28. package/dist/agentsWireCaps.d.ts +8 -8
  29. package/dist/agentsWireCaps.js +168 -175
  30. package/dist/approvalDecidedByCapability.d.ts +0 -4
  31. package/dist/approvalDecidedByCapability.js +0 -6
  32. package/dist/approvalsStreamLiveCapability.d.ts +0 -4
  33. package/dist/approvalsStreamLiveCapability.js +0 -6
  34. package/dist/assistantInbox.d.ts +34 -0
  35. package/dist/assistantInbox.js +118 -0
  36. package/dist/centerWiringCapability.js +9 -1
  37. package/dist/clientSlice.d.ts +0 -9
  38. package/dist/clientSlice.js +0 -3
  39. package/dist/cloudConfigWireCaps.d.ts +4 -2
  40. package/dist/cloudConfigWireCaps.js +81 -61
  41. package/dist/compensations.js +1 -1
  42. package/dist/connectorStatus.d.ts +21 -0
  43. package/dist/connectorStatus.js +112 -0
  44. package/dist/controlRouter.d.ts +14 -1
  45. package/dist/controlRouter.js +68 -17
  46. package/dist/coreValuePorts.d.ts +3 -3
  47. package/dist/decideReceipt.d.ts +2 -2
  48. package/dist/decideReceipt.js +5 -2
  49. package/dist/declared/supportFloorDeclared.js +3 -3
  50. package/dist/deviceExecutorManagementCapability.d.ts +0 -4
  51. package/dist/deviceExecutorManagementCapability.js +0 -6
  52. package/dist/deviceRebind.d.ts +49 -1
  53. package/dist/deviceRebind.js +221 -3
  54. package/dist/displayUntrusted.d.ts +1 -0
  55. package/dist/displayUntrusted.js +250 -76
  56. package/dist/engineAgentAbsence.d.ts +1 -1
  57. package/dist/engineAgentPanelStore.d.ts +5 -4
  58. package/dist/engineAgentPanelStore.js +3 -12
  59. package/dist/engineCapReader.d.ts +0 -4
  60. package/dist/engineCapReader.js +1 -5
  61. package/dist/engineCapsCache.d.ts +4 -0
  62. package/dist/engineCapsCache.js +17 -12
  63. package/dist/engineClosedSets.d.ts +1 -0
  64. package/dist/engineClosedSets.js +4 -1
  65. package/dist/engineErrorCodes.d.ts +9 -2
  66. package/dist/engineErrorCodes.js +9 -1
  67. package/dist/engineIdentity.d.ts +1 -0
  68. package/dist/engineIdentity.js +8 -0
  69. package/dist/engineRowRef.d.ts +28 -0
  70. package/dist/engineRowRef.js +111 -0
  71. package/dist/engineSessionMessages.d.ts +67 -0
  72. package/dist/engineSessionMessages.js +364 -0
  73. package/dist/engineToolDirectory.d.ts +0 -9
  74. package/dist/engineToolDirectory.js +1 -94
  75. package/dist/engineUrl.d.ts +18 -0
  76. package/dist/engineUrl.js +52 -0
  77. package/dist/env/uiLanguage.d.ts +9 -0
  78. package/dist/env/uiLanguage.js +35 -0
  79. package/dist/eventLeg.d.ts +92 -0
  80. package/dist/eventLeg.js +285 -0
  81. package/dist/executionLaneCapability.d.ts +0 -4
  82. package/dist/executionLaneCapability.js +3 -16
  83. package/dist/fileHistoryCaptureCapability.d.ts +0 -4
  84. package/dist/fileHistoryCaptureCapability.js +5 -7
  85. package/dist/fleet/fleetLedger.d.ts +0 -3
  86. package/dist/fleet/fleetLedger.js +21 -36
  87. package/dist/fleet/fleetProjection.d.ts +2 -2
  88. package/dist/fleet/fleetProjection.js +10 -8
  89. package/dist/frameBinding.d.ts +5 -0
  90. package/dist/frameBinding.js +23 -0
  91. package/dist/gateFailureCodes.d.ts +2 -0
  92. package/dist/gateFailureCodes.js +15 -0
  93. package/dist/gateOutcome.d.ts +3 -1
  94. package/dist/gateOutcome.js +25 -6
  95. package/dist/gateVocabulary.d.ts +5 -0
  96. package/dist/gateVocabulary.js +64 -2
  97. package/dist/generated/engineAskFaceTables.js +2 -2
  98. package/dist/generated/engineFactTables.d.ts +6 -3
  99. package/dist/generated/engineFactTables.js +22 -4
  100. package/dist/generated/engineNoticeTables.js +9 -0
  101. package/dist/generated/toolNameTables.d.ts +1 -0
  102. package/dist/generated/toolNameTables.js +1 -0
  103. package/dist/hitl/allowRuleShadow.d.ts +6 -1
  104. package/dist/hitl/allowRuleShadow.js +21 -17
  105. package/dist/hitl/approvalCardReading.d.ts +15 -0
  106. package/dist/hitl/approvalCardReading.js +154 -0
  107. package/dist/hitl/approvalCardReasons.d.ts +13 -0
  108. package/dist/hitl/approvalCardReasons.js +120 -0
  109. package/dist/hitl/approvalHolds.d.ts +47 -15
  110. package/dist/hitl/approvalHolds.js +134 -28
  111. package/dist/hitl/approvalResolution.d.ts +51 -26
  112. package/dist/hitl/approvalResolution.js +86 -122
  113. package/dist/hitl/approvalsFeed.js +6 -18
  114. package/dist/hitl/askClassPair.d.ts +2 -0
  115. package/dist/hitl/askClassPair.js +1 -0
  116. package/dist/hitl/askGateWire.d.ts +20 -2
  117. package/dist/hitl/askGateWire.js +49 -1
  118. package/dist/hitl/askParkRowRouting.d.ts +5 -0
  119. package/dist/hitl/askParkRowRouting.js +32 -1
  120. package/dist/hitl/askSettlementLine.d.ts +18 -0
  121. package/dist/hitl/askSettlementLine.js +79 -0
  122. package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
  123. package/dist/hitl/automaticAnswerVerdict.js +21 -5
  124. package/dist/hitl/crashConverged.d.ts +11 -20
  125. package/dist/hitl/crashConverged.js +56 -0
  126. package/dist/hitl/crashConvergedNotice.d.ts +3 -1
  127. package/dist/hitl/crashConvergedNotice.js +48 -11
  128. package/dist/hitl/decisionConflict.js +3 -10
  129. package/dist/hitl/decisionRefusal.d.ts +40 -1
  130. package/dist/hitl/decisionRefusal.js +199 -42
  131. package/dist/hitl/frameRouter.d.ts +5 -2
  132. package/dist/hitl/frameRouter.js +20 -16
  133. package/dist/hitl/gateLedger.d.ts +2 -0
  134. package/dist/hitl/gateLedger.js +50 -13
  135. package/dist/hitl/hitlBridge.d.ts +1 -2
  136. package/dist/hitl/hitlBridge.js +10 -7
  137. package/dist/hitl/livePendingAsk.d.ts +3 -3
  138. package/dist/hitl/livePendingAsk.js +7 -18
  139. package/dist/hitl/parkResolver.d.ts +2 -24
  140. package/dist/hitl/parkResolver.js +61 -97
  141. package/dist/hitl/persistedRulesWire.d.ts +24 -0
  142. package/dist/hitl/persistedRulesWire.js +122 -2
  143. package/dist/hitl/planReviewWire.d.ts +26 -13
  144. package/dist/hitl/planReviewWire.js +112 -78
  145. package/dist/hitl/refusedToolNameProse.d.ts +0 -1
  146. package/dist/hitl/refusedToolNameProse.js +0 -3
  147. package/dist/hitl/replayedApproval.d.ts +4 -3
  148. package/dist/hitl/replayedApproval.js +7 -4
  149. package/dist/hitl/sessionPolicyDeliverable.js +2 -4
  150. package/dist/hitl/sessionPolicyWire.d.ts +32 -20
  151. package/dist/hitl/sessionPolicyWire.js +162 -52
  152. package/dist/hitl/standingRows.d.ts +20 -2
  153. package/dist/hitl/standingRows.js +69 -8
  154. package/dist/hitl/toolApprovalWire.d.ts +87 -152
  155. package/dist/hitl/toolApprovalWire.js +591 -380
  156. package/dist/hookMatcherVerdict.d.ts +6 -1
  157. package/dist/hookMatcherVerdict.js +14 -7
  158. package/dist/hooksWireCaps.d.ts +2 -2
  159. package/dist/hooksWireCaps.js +59 -55
  160. package/dist/i18n/messages.en.d.ts +121 -0
  161. package/dist/i18n/messages.en.js +119 -0
  162. package/dist/i18n/messages.zh.d.ts +3 -0
  163. package/dist/i18n/messages.zh.js +120 -0
  164. package/dist/i18n/translate.d.ts +25 -0
  165. package/dist/i18n/translate.js +127 -0
  166. package/dist/index.d.ts +53 -20
  167. package/dist/index.js +38 -11
  168. package/dist/inheritEnvCapability.d.ts +31 -0
  169. package/dist/inheritEnvCapability.js +104 -0
  170. package/dist/liveModelCatalog.d.ts +1 -2
  171. package/dist/liveModelCatalog.js +2 -6
  172. package/dist/liveQuestionStore.d.ts +2 -21
  173. package/dist/mcpLiveness.d.ts +2 -1
  174. package/dist/mcpProbeWire.d.ts +6 -1
  175. package/dist/mcpProbeWire.js +1 -1
  176. package/dist/mcpWireCaps.d.ts +13 -2
  177. package/dist/mcpWireCaps.js +48 -0
  178. package/dist/memoryEntriesWire.d.ts +4 -9
  179. package/dist/model/modelSupplyRules.d.ts +0 -2
  180. package/dist/model/modelSupplyRules.js +3 -12
  181. package/dist/model/modelsPolicy.d.ts +0 -5
  182. package/dist/model/modelsPolicy.js +6 -36
  183. package/dist/model/subagentModelWord.d.ts +31 -0
  184. package/dist/model/subagentModelWord.js +261 -0
  185. package/dist/notifications.d.ts +6 -0
  186. package/dist/notifications.js +71 -23
  187. package/dist/outputStyleSeatCapability.d.ts +0 -3
  188. package/dist/outputStyleSeatCapability.js +0 -3
  189. package/dist/ownKey.d.ts +15 -0
  190. package/dist/ownKey.js +60 -3
  191. package/dist/panelReduce.d.ts +15 -9
  192. package/dist/panelReduce.js +680 -549
  193. package/dist/panelStateHolder.d.ts +3 -7
  194. package/dist/panelStateHolder.js +14 -130
  195. package/dist/peerLaneCapability.d.ts +0 -4
  196. package/dist/peerLaneCapability.js +0 -6
  197. package/dist/permissionRulesWriteCapability.d.ts +0 -4
  198. package/dist/permissionRulesWriteCapability.js +0 -6
  199. package/dist/permissionWireCaps.d.ts +2 -2
  200. package/dist/permissionWireCaps.js +2 -0
  201. package/dist/permissionsAllowGrantCapability.d.ts +0 -4
  202. package/dist/permissionsAllowGrantCapability.js +0 -6
  203. package/dist/permissionsDeclaration.d.ts +0 -11
  204. package/dist/permissionsDeclaration.js +60 -53
  205. package/dist/pluginHooksWire.d.ts +1 -1
  206. package/dist/pluginHooksWire.js +3 -6
  207. package/dist/preemptWire.d.ts +44 -0
  208. package/dist/preemptWire.js +83 -0
  209. package/dist/printToolResultFrame.js +15 -4
  210. package/dist/replayBody.d.ts +3 -0
  211. package/dist/replayBody.js +14 -0
  212. package/dist/request/taskRequest.d.ts +0 -1
  213. package/dist/request/taskRequest.js +0 -3
  214. package/dist/resumeRefusalCopy.d.ts +2 -1
  215. package/dist/resumeRefusalCopy.js +38 -2
  216. package/dist/retryStatus.d.ts +8 -0
  217. package/dist/retryStatus.js +106 -1
  218. package/dist/rewindArchiveCapability.d.ts +0 -4
  219. package/dist/rewindArchiveCapability.js +2 -10
  220. package/dist/rewindArchiveReading.d.ts +0 -1
  221. package/dist/rewindArchiveReading.js +0 -3
  222. package/dist/runCancelContext.d.ts +2 -1
  223. package/dist/runCancelContext.js +4 -2
  224. package/dist/runReattachPolicy.d.ts +31 -0
  225. package/dist/runReattachPolicy.js +46 -0
  226. package/dist/runTerminal.d.ts +3 -6
  227. package/dist/runTerminal.js +8 -9
  228. package/dist/sandboxWire.d.ts +3 -1
  229. package/dist/sandboxWire.js +76 -27
  230. package/dist/scenarioWire.js +1 -1
  231. package/dist/seam.d.ts +24 -2
  232. package/dist/seam.js +15 -3
  233. package/dist/seatContract.d.ts +53 -10
  234. package/dist/seatContract.js +132 -81
  235. package/dist/sessionPolicyCapability.d.ts +0 -4
  236. package/dist/sessionPolicyCapability.js +0 -6
  237. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -3
  238. package/dist/sessionSyncFileHistoryCapability.js +0 -3
  239. package/dist/skillToolListsCapability.d.ts +0 -3
  240. package/dist/skillToolListsCapability.js +0 -3
  241. package/dist/sqlEngineCapability.d.ts +0 -4
  242. package/dist/sqlEngineCapability.js +0 -6
  243. package/dist/steerPriorityCapability.d.ts +0 -3
  244. package/dist/steerPriorityCapability.js +0 -3
  245. package/dist/streamDrainingLegs.d.ts +4 -0
  246. package/dist/streamDrainingLegs.js +6 -1
  247. package/dist/subagent/engineCompactWire.d.ts +0 -1
  248. package/dist/subagent/engineCompactWire.js +7 -5
  249. package/dist/subagent/engineTaskHandleWire.js +4 -7
  250. package/dist/subagentContentStore.js +1 -11
  251. package/dist/submitReopen.d.ts +24 -0
  252. package/dist/submitReopen.js +75 -0
  253. package/dist/terminalStatuses.d.ts +3 -0
  254. package/dist/terminalStatuses.js +10 -2
  255. package/dist/toolResult.d.ts +10 -1
  256. package/dist/toolResult.js +34 -6
  257. package/dist/toolRoster.d.ts +0 -2
  258. package/dist/toolRoster.js +0 -2
  259. package/dist/turnFailurePresentation.d.ts +28 -0
  260. package/dist/turnFailurePresentation.js +205 -0
  261. package/dist/userInvokedSkillsCapability.d.ts +0 -3
  262. package/dist/userInvokedSkillsCapability.js +0 -3
  263. package/dist/webSearchBackendCapability.d.ts +0 -4
  264. package/dist/webSearchBackendCapability.js +0 -6
  265. package/dist/wireErrorTriage.js +5 -24
  266. package/dist/wireFailureShape.d.ts +62 -5
  267. package/dist/wireFailureShape.js +105 -5
  268. package/dist/wireRefusalCopy.d.ts +12 -2
  269. package/dist/wireRefusalCopy.js +50 -52
  270. package/dist/workflowsJournalCapability.d.ts +0 -4
  271. package/dist/workflowsJournalCapability.js +0 -6
  272. package/dist/writeProtectionCapability.d.ts +0 -4
  273. package/dist/writeProtectionCapability.js +0 -6
  274. package/docs/INTEGRATION-CLIENTS.md +1253 -46
  275. package/package.json +5 -4
  276. package/dist/attachmentSeatCapability.d.ts +0 -12
  277. package/dist/attachmentSeatCapability.js +0 -23
  278. package/dist/hitl/approvalOutcomeNote.d.ts +0 -10
  279. package/dist/hitl/approvalOutcomeNote.js +0 -29
  280. package/dist/sessionReadRedactionCapability.d.ts +0 -13
  281. package/dist/sessionReadRedactionCapability.js +0 -35
@@ -1,39 +1,125 @@
1
- import { ASK_GONE, ASK_GONE_PARKED, isDecideAlreadyResolvedCode, isDecideParkMovedCode, refusalRetriableReading, refusalSaysStillPending } from '../engineErrorCodes.js';
2
- import { notPendingCauseReading } from './approvalEndingCause.js';
3
- import { GATE_FAILURE_CODES } from './hitlBridge.js';
1
+ import { ASK_GONE, ASK_GONE_PARKED, RESUME_PREFLIGHT_REJECTED, isDecideAlreadyResolvedCode, isDecideParkMovedCode, refusalRetriableReading, refusalSaysStillPending } from '../engineErrorCodes.js';
2
+ import { notPendingCauseReading, refusalCauseWordOf } from './approvalEndingCause.js';
3
+ import { GATE_FAILURE_CODES, readDecideCurrentPending, readWireCodes } from './hitlBridge.js';
4
4
  import { isAlreadyResolvedGateReason, isCodeClassifiedGateFailure } from './parkResolver.js';
5
5
  import { decisionConflictOf } from './decisionConflict.js';
6
6
  import { readLivePendingRows } from './livePendingAsk.js';
7
- import { ownDataField } from '../ownKey.js';
8
- import { readToolApprovalRespondRefusal } from './toolApprovalWire.js';
7
+ import { guardedRead, ownDataField, readOwnDataValue } from '../ownKey.js';
8
+ import { PROTOCOL_ERROR_NAME, isDisplayableWireCode, protocolErrorNameReading, readErrorRecord, readRefusalField } from '../wireFailureShape.js';
9
+ import { denyAttributionRefusalFromError } from '../wireRefusalCopy.js';
9
10
  const ASK_DECIDED_CODE = 'conflict.ask_decided';
10
11
  const TRANSIENT_STATUSES = new Set([408, 425, 429, 502, 503, 504]);
11
- const DISPLAYABLE_CODE = /^[A-Za-z0-9._:-]{1,64}$/;
12
+ export function refusalCarrierOf(err) {
13
+ if (typeof err !== 'object' || err === null)
14
+ return { carrier: err };
15
+ const name = guardedRead(() => readOwnDataValue(err, 'name'));
16
+ if (name !== 'HitlSafetyError')
17
+ return { carrier: err };
18
+ const code = guardedRead(() => readOwnDataValue(err, 'code'));
19
+ const local = typeof code === 'string' && GATE_FAILURE_CODES.includes(code) ? code : undefined;
20
+ const cause = guardedRead(() => readOwnDataValue(err, 'cause'));
21
+ const carrier = typeof cause === 'object' && cause !== null ? cause : err;
22
+ return local !== undefined ? { local, carrier } : { carrier };
23
+ }
24
+ const ROUTE_WORDS = { approval_decide: true, live_respond: true, ask_decide: true, plan_review: true, compact: true };
25
+ const REFUSAL_ROUTES = Object.freeze(Object.keys(ROUTE_WORDS));
26
+ const PRIOR_REFUSAL_EVIDENCE = Object.freeze([
27
+ Object.freeze({
28
+ errorCode: 'corrupt',
29
+ routes: Object.freeze(['plan_review', 'approval_decide', 'live_respond']),
30
+ evidence: 'server resume-legs.ts:1019 / :2752 / :2910 (resume context read, before the claim CAS at :1666 / :1457); plan_review resumePlanReview reads context before settling',
31
+ }),
32
+ ]);
33
+ function routeOf(context) {
34
+ const r = guardedRead(() => (typeof context === 'object' && context !== null ? readOwnDataValue(context, 'route') : undefined));
35
+ return typeof r === 'string' && REFUSAL_ROUTES.includes(r) ? r : undefined;
36
+ }
37
+ function carrierStatus(carrier) {
38
+ const raw = typeof carrier === 'object' && carrier !== null ? guardedRead(() => readOwnDataValue(carrier, 'status')) : undefined;
39
+ return typeof raw === 'number' && Number.isFinite(raw) ? raw : undefined;
40
+ }
41
+ function carrierCode(carrier) {
42
+ const raw = typeof carrier === 'object' && carrier !== null ? guardedRead(() => readOwnDataValue(carrier, 'errorCode')) : undefined;
43
+ return typeof raw === 'string' && raw.length > 0 ? raw : undefined;
44
+ }
45
+ export function refusalDeliveryOf(err, context) {
46
+ const { carrier } = refusalCarrierOf(err);
47
+ const status = carrierStatus(carrier);
48
+ const errorCode = carrierCode(carrier);
49
+ const facts = { ...(status !== undefined ? { status } : {}), ...(errorCode !== undefined ? { errorCode } : {}) };
50
+ if (status === undefined || !Number.isInteger(status) || status < 400 || status > 599)
51
+ return { delivery: 'no_answer', ...facts };
52
+ const route = routeOf(context);
53
+ if (route !== undefined && errorCode !== undefined && PRIOR_REFUSAL_EVIDENCE.some((p) => p.errorCode === errorCode && p.routes.includes(route))) {
54
+ return { delivery: 'refused', ...facts };
55
+ }
56
+ if (status < 500 || status === 501)
57
+ return { delivery: 'refused', ...facts };
58
+ return { delivery: 'ambiguous', ...facts };
59
+ }
12
60
  export function decisionRefusalSaysAskGone(err) {
13
61
  return readDecisionRefusalAsk(err).reading === 'settled';
14
62
  }
15
63
  const facts = (reading, gateMoved = false, wordingHint = false) => ({ reading, gateMoved, wordingHint });
16
- const PROTOCOL_ERROR_NAMES = Object.freeze({
17
- askDecided: 'AskDecidedError',
18
- approvalStale: 'ApprovalStaleError',
19
- parkedResumeStartup: 'ParkedResumeStartupError',
20
- });
64
+ function preflightSettledBitsPresent(carrier) {
65
+ const detail = guardedRead(() => readErrorRecord(carrier, 'detail'));
66
+ if (detail === undefined)
67
+ return false;
68
+ const bit = (k) => guardedRead(() => readOwnDataValue(detail, k));
69
+ const nonEmpty = (v) => typeof v === 'string' && v.length > 0;
70
+ return nonEmpty(bit('settledBy')) || nonEmpty(bit('rowStatus'));
71
+ }
72
+ const RESOLUTION_KINDS = Object.freeze(['decided', 'not_sent', 'unsettled']);
73
+ const ASK_READINGS = Object.freeze(['settled', 'not_settled', 'unreadable']);
74
+ function isResolutionShaped(v) {
75
+ if (typeof v !== 'object' || v === null)
76
+ return false;
77
+ const kind = guardedRead(() => readOwnDataValue(v, 'kind'));
78
+ return typeof kind === 'string' && RESOLUTION_KINDS.includes(kind);
79
+ }
80
+ function askFactsOfResolution(r) {
81
+ try {
82
+ const kind = ownDataField(r, 'kind');
83
+ if (kind === 'not_sent')
84
+ return facts(ownDataField(r, 'cause') === 'no_pending' ? 'settled' : 'not_settled');
85
+ if (kind !== 'unsettled')
86
+ return facts('not_settled');
87
+ const refusal = ownDataField(r, 'refusal');
88
+ if (typeof refusal !== 'object' || refusal === null)
89
+ return facts('not_settled');
90
+ const ask = ownDataField(refusal, 'ask');
91
+ if (typeof ask !== 'string' || !ASK_READINGS.includes(ask))
92
+ return facts('unreadable');
93
+ return facts(ask, ownDataField(refusal, 'gateMoved') === true, ownDataField(refusal, 'wordingHint') === true);
94
+ }
95
+ catch {
96
+ return facts('unreadable');
97
+ }
98
+ }
21
99
  export function readDecisionRefusalAsk(failure) {
22
100
  if (typeof failure !== 'object' || failure === null)
23
101
  return facts('not_settled');
24
- let flattened, localCode, name, errorCode, status, retriable, text;
102
+ if (isResolutionShaped(failure))
103
+ return askFactsOfResolution(failure);
104
+ const { local, carrier } = refusalCarrierOf(failure);
105
+ if (local !== undefined)
106
+ return facts(local === 'no_pending' ? 'settled' : 'not_settled');
107
+ if (typeof carrier !== 'object' || carrier === null)
108
+ return facts('not_settled');
109
+ let localCode, name, protocolName, errorCode, status, retriable, text;
25
110
  try {
26
- const slot = (key) => ownDataField(failure, key);
27
- if (slot('unreadable') === true)
28
- return facts('unreadable');
29
- flattened = slot('kind') === 'failed';
111
+ const slot = (key) => ownDataField(carrier, key);
30
112
  const closed = (v) => (typeof v === 'string' && GATE_FAILURE_CODES.includes(v) ? v : undefined);
31
- localCode = flattened ? (closed(slot('code')) ?? closed(slot('safetyCode'))) : closed(slot('code'));
32
- name = flattened ? undefined : slot('name');
113
+ localCode = closed(slot('code'));
114
+ name = slot('name');
115
+ const pn = protocolErrorNameReading(carrier);
116
+ if (pn.state === 'unreadable')
117
+ throw new TypeError('protocol name unreadable');
118
+ protocolName = pn.state === 'named' ? pn.name : undefined;
33
119
  errorCode = slot('errorCode');
34
120
  status = slot('status');
35
- retriable = refusalRetriableReading(failure);
36
- text = flattened ? slot('reason') : String(failure);
121
+ retriable = refusalRetriableReading(carrier);
122
+ text = String(carrier);
37
123
  }
38
124
  catch {
39
125
  return facts('unreadable');
@@ -45,46 +131,117 @@ export function readDecisionRefusalAsk(failure) {
45
131
  if (name === 'HitlSafetyError')
46
132
  return facts('not_settled');
47
133
  const code = typeof errorCode === 'string' && errorCode.length > 0 ? errorCode : undefined;
134
+ if (code === RESUME_PREFLIGHT_REJECTED && (preflightSettledBitsPresent(carrier) || retriable !== true))
135
+ return facts('not_settled', true);
48
136
  if (isCodeClassifiedGateFailure(code, retriable))
49
137
  return facts('not_settled');
50
138
  const st = typeof status === 'number' && Number.isInteger(status) && status >= 400 && status <= 599 ? status : undefined;
51
139
  if (code === ASK_DECIDED_CODE || code === ASK_GONE || (st === 410 && code !== ASK_GONE_PARKED))
52
140
  return facts('settled');
53
- if (st === 404 && notPendingCauseReading(failure) === 'ended')
141
+ if (st === 404 && notPendingCauseReading(carrier) === 'ended')
54
142
  return facts('settled');
55
- if (code === undefined && name === PROTOCOL_ERROR_NAMES.askDecided)
143
+ if (code === undefined && protocolName === PROTOCOL_ERROR_NAME.AskDecidedError)
56
144
  return facts('settled');
57
- const gateMoved = isDecideAlreadyResolvedCode(code) || isDecideParkMovedCode(code) || code === ASK_GONE_PARKED || (code === undefined && name === PROTOCOL_ERROR_NAMES.approvalStale);
58
- if (gateMoved || st !== undefined || name === PROTOCOL_ERROR_NAMES.parkedResumeStartup)
145
+ const gateMoved = isDecideAlreadyResolvedCode(code) || isDecideParkMovedCode(code) || code === ASK_GONE_PARKED || (code === undefined && protocolName === PROTOCOL_ERROR_NAME.ApprovalStaleError);
146
+ if (gateMoved || st !== undefined || protocolName === PROTOCOL_ERROR_NAME.ParkedResumeStartupError)
59
147
  return facts('not_settled', gateMoved);
60
148
  return facts('not_settled', false, isAlreadyResolvedGateReason(text));
61
149
  }
62
150
  export function decisionRefusalAskReading(failure) {
63
151
  return readDecisionRefusalAsk(failure).reading;
64
152
  }
65
- export function classifyDecisionRefusal(err) {
66
- const r = readToolApprovalRespondRefusal(err);
67
- const status = r?.status;
68
- if (status === undefined || !Number.isInteger(status) || status < 400 || status > 599)
153
+ const USELESS_REFUSAL_TEXTS = new Set(['[object Object]', 'null', 'undefined', '']);
154
+ function refusalTextOf(err) {
155
+ const message = typeof err === 'object' && err !== null ? guardedRead(() => err.message) : undefined;
156
+ if (typeof message === 'string' && message.length > 0)
157
+ return message;
158
+ if (typeof err === 'string' && err.length > 0)
159
+ return err;
160
+ let coerced;
161
+ try {
162
+ coerced = String(err);
163
+ }
164
+ catch {
69
165
  return undefined;
70
- const code = r?.errorCode;
71
- const errorCode = code !== undefined && DISPLAYABLE_CODE.test(code) ? code : undefined;
72
- const standing = readDecisionRefusalAsk(err).reading === 'settled'
73
- ? 'settled-elsewhere'
74
- : status >= 500 && status !== 501
75
- ? 'ambiguous'
76
- : 'refused-pending';
77
- const transient = TRANSIENT_STATUSES.has(status) ||
78
- (typeof err === 'object' && err !== null && (refusalSaysStillPending(err) || (status === 404 && notPendingCauseReading(err) === 'other_replica')));
79
- const conflict = status === 409 ? decisionConflictOf(err) : undefined;
166
+ }
167
+ return USELESS_REFUSAL_TEXTS.has(coerced) ? undefined : coerced;
168
+ }
169
+ function isolated(read) {
170
+ return guardedRead(read);
171
+ }
172
+ export function mintDecisionRefusalReading(err, context, attributionCarried) {
173
+ const { carrier } = refusalCarrierOf(err);
174
+ const obj = typeof carrier === 'object' && carrier !== null ? carrier : undefined;
175
+ const status = carrierStatus(carrier);
176
+ const wire = obj !== undefined ? isolated(() => readWireCodes(obj)) : undefined;
177
+ const errorCode = wire?.errorCode ?? carrierCode(carrier);
178
+ const message = isolated(() => refusalTextOf(carrier));
179
+ const retriable = obj !== undefined && isolated(() => refusalSaysStillPending(obj)) === true;
180
+ const pn = obj !== undefined ? isolated(() => protocolErrorNameReading(obj)) : undefined;
181
+ const protocolName = pn?.state === 'named' ? pn.name : undefined;
182
+ const cause = obj !== undefined ? isolated(() => refusalCauseWordOf(obj)) : undefined;
183
+ const field = obj !== undefined ? isolated(() => readRefusalField(obj)) : undefined;
184
+ const currentPending = obj !== undefined ? isolated(() => readDecideCurrentPending(obj)) : undefined;
185
+ const attribution = attributionCarried !== undefined ? isolated(() => denyAttributionRefusalFromError(carrier, attributionCarried)) : undefined;
186
+ const ask = readDecisionRefusalAsk(err);
187
+ const delivery = refusalDeliveryOf(err, context);
188
+ const standing = delivery.delivery === 'no_answer' ? undefined : ask.reading === 'settled' ? 'settled-elsewhere' : delivery.delivery === 'refused' ? 'refused-pending' : 'ambiguous';
189
+ const inRange = standing !== undefined && status !== undefined;
190
+ const transient = inRange &&
191
+ (TRANSIENT_STATUSES.has(status) || retriable || (status === 404 && obj !== undefined && isolated(() => notPendingCauseReading(obj)) === 'other_replica'));
192
+ const conflict = inRange && status === 409 && obj !== undefined ? isolated(() => decisionConflictOf(obj)) : undefined;
80
193
  return Object.freeze({
81
- standing,
82
- status,
194
+ ...(status !== undefined ? { status } : {}),
83
195
  ...(errorCode !== undefined ? { errorCode } : {}),
196
+ ...(message !== undefined ? { message } : {}),
197
+ ...(retriable ? { retriable: true } : {}),
198
+ ...(protocolName !== undefined ? { protocolName } : {}),
199
+ ...(cause !== undefined || field !== undefined ? { extra: Object.freeze({ ...(cause !== undefined ? { cause } : {}), ...(field !== undefined ? { field } : {}) }) } : {}),
200
+ ...(wire?.blockedBy !== undefined ? { blockedBy: wire.blockedBy } : {}),
201
+ ...(currentPending !== undefined ? { currentPending } : {}),
202
+ ...(attribution !== undefined && attribution !== null ? { denyAttributionRefusal: attribution } : {}),
203
+ ask: ask.reading,
204
+ ...(ask.gateMoved ? { gateMoved: true } : {}),
205
+ ...(ask.wordingHint ? { wordingHint: true } : {}),
206
+ ...(standing !== undefined ? { standing } : {}),
84
207
  ...(transient ? { transient: true } : {}),
85
208
  ...(conflict !== undefined ? { conflict } : {}),
86
209
  });
87
210
  }
211
+ export function readDecisionRefusalReading(err, context) {
212
+ return mintDecisionRefusalReading(err, context);
213
+ }
214
+ function classifiedOf(reading) {
215
+ if (typeof reading !== 'object' || reading === null)
216
+ return undefined;
217
+ try {
218
+ const standing = ownDataField(reading, 'standing');
219
+ const status = ownDataField(reading, 'status');
220
+ if ((standing !== 'settled-elsewhere' && standing !== 'ambiguous' && standing !== 'refused-pending') || typeof status !== 'number')
221
+ return undefined;
222
+ const code = ownDataField(reading, 'errorCode');
223
+ const errorCode = typeof code === 'string' && isDisplayableWireCode(code) ? code : undefined;
224
+ const transient = ownDataField(reading, 'transient') === true;
225
+ const conflict = ownDataField(reading, 'conflict');
226
+ return Object.freeze({
227
+ standing,
228
+ status,
229
+ ...(errorCode !== undefined ? { errorCode } : {}),
230
+ ...(transient ? { transient: true } : {}),
231
+ ...(typeof conflict === 'string' ? { conflict: conflict } : {}),
232
+ });
233
+ }
234
+ catch {
235
+ return undefined;
236
+ }
237
+ }
238
+ export function classifyDecisionRefusal(err, context) {
239
+ if (isResolutionShaped(err)) {
240
+ const refusal = guardedRead(() => (ownDataField(err, 'kind') === 'unsettled' ? ownDataField(err, 'refusal') : undefined));
241
+ return classifiedOf(refusal);
242
+ }
243
+ return classifiedOf(mintDecisionRefusalReading(err, context));
244
+ }
88
245
  export function liveAskPendingReading(envelope, approvalId) {
89
246
  if (typeof approvalId !== 'string' || approvalId === '')
90
247
  return 'unknown';
@@ -114,9 +271,9 @@ export function decisionRefusalClosesOut(refusal, pending) {
114
271
  }
115
272
  }
116
273
  export function undeliverableDecisionContent(facts) {
117
- const code = typeof facts.errorCode === 'string' && DISPLAYABLE_CODE.test(facts.errorCode) ? ` ${facts.errorCode}` : '';
274
+ const code = typeof facts.errorCode === 'string' && isDisplayableWireCode(facts.errorCode) ? ` ${facts.errorCode}` : '';
118
275
  const head = `The engine refused the approval decision this client sent (HTTP ${String(facts.status)}${code}), so the call it asked about could not be answered from here and did not run`;
119
- const runId = typeof facts.runId === 'string' && DISPLAYABLE_CODE.test(facts.runId) ? ` ${facts.runId}` : '';
276
+ const runId = typeof facts.runId === 'string' && isDisplayableWireCode(facts.runId) ? ` ${facts.runId}` : '';
120
277
  switch (facts.end) {
121
278
  case 'run-stopped':
122
279
  return `${head}; the run was stopped instead of being left waiting for the approval window to close. Update the client, or run the task in an interactive session and answer the approval there.`;
@@ -1,6 +1,7 @@
1
1
  import type { AgentEvent } from '@sema-agent/sdk';
2
2
  import type { DecideOperationObserver, HitlClientLike } from './hitlBridge.js';
3
- import { type RespondToolApprovalFn, type ToolApprovalFrame, type ToolApprovalFrameLaneOpts, type ToolApprovalFrameOutcome } from './toolApprovalWire.js';
3
+ import { type RespondToolApprovalFn, type ToolApprovalFrame, type ToolApprovalFrameLaneOpts } from './toolApprovalWire.js';
4
+ import type { ApprovalResolution } from './approvalResolution.js';
4
5
  import type { GateLedger } from './gateLedger.js';
5
6
  import type { NoAllowCause } from './noAllowCause.js';
6
7
  import { type ReplayedApprovalDisposition } from './replayedApproval.js';
@@ -31,13 +32,14 @@ export interface AskGateWireDeps {
31
32
  respondToolApproval?: RespondToolApprovalFn;
32
33
  onParkReattach?: (e: ParkReattachNotice) => void;
33
34
  approvalLane?: ToolApprovalFrameLaneOpts;
34
- onToolApprovalOutcome?: (frame: ToolApprovalFrame, outcome: ToolApprovalFrameOutcome) => void | Promise<void>;
35
+ onToolApprovalOutcome?: (frame: ToolApprovalFrame, resolution: ApprovalResolution) => void | Promise<void>;
35
36
  onDecideOperation?: DecideOperationObserver;
36
37
  onReplayedApproval?: (frame: ToolApprovalFrame, disposition: ReplayedApprovalDisposition) => void | Promise<void>;
37
38
  }
38
39
  type GateKind = 'ask' | 'fs';
39
40
  export interface GatePark {
40
41
  gate: GateKind;
42
+ parkFrame: AgentEvent;
41
43
  pendingDone?: AgentEvent | undefined;
42
44
  gatedCallId?: string | undefined;
43
45
  toolName?: string | undefined;
@@ -50,6 +52,7 @@ export type FrameAction = {
50
52
  } | {
51
53
  kind: 'park';
52
54
  gate: GateKind;
55
+ parkFrame: AgentEvent;
53
56
  pendingDone?: AgentEvent | undefined;
54
57
  gatedCallId?: string | undefined;
55
58
  toolName?: string | undefined;
@@ -5,6 +5,8 @@ import { classifierDenyFromToolEnd } from '../classifierVerdictWire.js';
5
5
  import { toolEndOutputText } from '../toolResultContent.js';
6
6
  import { GATE_PARKED_ERROR_CODE } from '../engineErrorCodes.js';
7
7
  import { readRunTerminal, runTerminalCode, runTerminalGateKind, runTerminalGateToolName } from '../runTerminal.js';
8
+ import { parkHeldCallIdOf } from '../engineRowRef.js';
9
+ import { inheritFrameBinding } from '../frameBinding.js';
8
10
  import { surfaceForCurrentSession, surfaceReplayedApprovalListUnreadable } from './hitlHostSurface.js';
9
11
  import { liveCardHoldOf, noteEngineClosedApproval, supersedeLiveCard } from './approvalHolds.js';
10
12
  import { approvalCompleteParked } from './approvalCompleteParked.js';
@@ -69,12 +71,12 @@ function denialKindForTranscript(attribution) {
69
71
  }
70
72
  function denyStampedEnd(ev, attribution) {
71
73
  const kind = denialKindForTranscript(attribution);
72
- return {
74
+ return inheritFrameBinding(ev, {
73
75
  ...ev,
74
76
  output: denyOutputForRender(attribution),
75
77
  structured: undefined,
76
78
  ...(kind !== undefined ? { [SEMA_DENIAL_KIND_KEY]: kind } : {}),
77
- };
79
+ });
78
80
  }
79
81
  export const HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE = '[Request interrupted by user for tool use]';
80
82
  const RUN_CANCELLED_ERROR_CODE = RUN_CANCELLED_CODE;
@@ -149,8 +151,7 @@ function parkGateOf(result) {
149
151
  return arm === null ? null : { taskId, gate: arm, toolName };
150
152
  }
151
153
  function parkGatedCallId(src) {
152
- const v = src?.toolCallId;
153
- return typeof v === 'string' && v.length > 0 ? v : undefined;
154
+ return parkHeldCallIdOf(src);
154
155
  }
155
156
  function argsOfGatedStart(led, callId) {
156
157
  if (callId === undefined)
@@ -192,7 +193,9 @@ export function* flushHeldWithInterruptRewrite(led, evidence) {
192
193
  yield ev;
193
194
  continue;
194
195
  }
195
- yield { ...ev, output: HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE };
196
+ yield inheritFrameBinding(ev, (gateAborted
197
+ ? { ...ev, output: HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE, [SEMA_DENIAL_KIND_KEY]: 'interrupted' }
198
+ : { ...ev, output: HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE }));
196
199
  }
197
200
  }
198
201
  const TOOL_END_ARM_ORDER = [
@@ -216,7 +219,7 @@ const TOOL_END_ARMS = [
216
219
  const startArgs = led.startArgs().get(callId);
217
220
  surfaceForCurrentSession()?.surfaceClassifierDeny(typeof ev.toolName === 'string' ? ev.toolName : 'tool', verdict, { toolCallId: callId, ...(startArgs !== undefined ? { args: startArgs } : {}) });
218
221
  hostLog('debug', `liveHitlAskWire: classifier deny verdict on ${callId} (${String(ev.toolName)}) — labeled render + notice`);
219
- return { kind: 'yield', events: [{ ...ev, output: verdict.message, structured: undefined }] };
222
+ return { kind: 'yield', events: [inheritFrameBinding(ev, { ...ev, output: verdict.message, structured: undefined })] };
220
223
  },
221
224
  },
222
225
  {
@@ -264,7 +267,7 @@ const TOOL_END_ARMS = [
264
267
  const answered = led.answerFor(callId);
265
268
  if (answered && ev.isError !== true && ev.structured === undefined) {
266
269
  led.dropAnswer(callId);
267
- return { kind: 'yield', events: [{ ...ev, structured: answered }] };
270
+ return { kind: 'yield', events: [inheritFrameBinding(ev, { ...ev, structured: answered })] };
268
271
  }
269
272
  return { kind: 'yield', events: [ev] };
270
273
  },
@@ -328,14 +331,13 @@ async function routeToolApprovalFrame(ev, ctx) {
328
331
  }
329
332
  function settleLiveCardOutcome(ev, outcome, ctx, fromSubagent, gatedCallId) {
330
333
  const { led, deps } = ctx;
331
- const { decision } = outcome;
332
334
  if (deps.onToolApprovalOutcome !== undefined) {
333
335
  invokeHostCallbackIsolated('liveHitlAskWire: onToolApprovalOutcome', () => deps.onToolApprovalOutcome?.(ev, outcome));
334
336
  }
335
- if (decision === 'deny' && !fromSubagent) {
337
+ if (outcome.kind === 'decided' && outcome.decision === 'deny' && !fromSubagent) {
336
338
  const attribution = {
337
- ...(outcome.denySettledBy !== undefined ? { settledBy: outcome.denySettledBy } : {}),
338
- ...(outcome.denyReason !== undefined ? { reason: outcome.denyReason } : {}),
339
+ ...(outcome.deny?.settledBy !== undefined ? { settledBy: outcome.deny.settledBy } : {}),
340
+ ...(outcome.deny?.reason !== undefined ? { reason: outcome.deny.reason } : {}),
339
341
  };
340
342
  if (gatedCallId !== undefined)
341
343
  led.markDenied(gatedCallId, attribution);
@@ -400,15 +402,16 @@ function routeSuspended(ev, ctx) {
400
402
  const gatedCallId = parkGatedCallId(ev);
401
403
  const arm = parkGateArmOf(ev.gate);
402
404
  if (arm === 'ask' && ctx.taskId.current) {
403
- ctx.led.noteParkGate({ fsOrShellFamily: false });
404
- return { kind: 'park', gate: 'ask', ...(gatedCallId !== undefined ? { gatedCallId } : {}) };
405
+ ctx.led.noteParkGate({ fsOrShellFamily: false, gatedCallId });
406
+ return { kind: 'park', gate: 'ask', parkFrame: ev, ...(gatedCallId !== undefined ? { gatedCallId } : {}) };
405
407
  }
406
408
  if (arm === 'fs' && ctx.taskId.current) {
407
409
  const gateToolName = ev.gate?.toolName;
408
- ctx.led.noteParkGate({ fsOrShellFamily: parkFamilyEvidence(ctx.led, gateToolName, gatedCallId) });
410
+ ctx.led.noteParkGate({ fsOrShellFamily: parkFamilyEvidence(ctx.led, gateToolName, gatedCallId), gatedCallId });
409
411
  return {
410
412
  kind: 'park',
411
413
  gate: 'fs',
414
+ parkFrame: ev,
412
415
  ...(gatedCallId !== undefined ? { gatedCallId } : {}),
413
416
  ...(typeof gateToolName === 'string' && gateToolName !== '' ? { toolName: gateToolName } : {}),
414
417
  };
@@ -421,10 +424,11 @@ function routeDone(ev, ctx) {
421
424
  const park = parkGateOf(ev.result);
422
425
  if (park !== null) {
423
426
  ctx.taskId.current = ctx.taskId.current ?? park.taskId;
424
- led.noteParkGate({ fsOrShellFamily: park.gate === 'fs' && parkFamilyEvidence(led, park.toolName, gatedCallId) });
427
+ led.noteParkGate({ fsOrShellFamily: park.gate === 'fs' && parkFamilyEvidence(led, park.toolName, gatedCallId), gatedCallId });
425
428
  return {
426
429
  kind: 'park',
427
430
  gate: park.gate,
431
+ parkFrame: ev,
428
432
  pendingDone: ev,
429
433
  ...(gatedCallId !== undefined ? { gatedCallId } : {}),
430
434
  ...(park.toolName !== undefined && park.toolName !== '' ? { toolName: park.toolName } : {}),
@@ -434,7 +438,7 @@ function routeDone(ev, ctx) {
434
438
  const r = ev.result;
435
439
  const realTaskId = ctx.taskId.current;
436
440
  if (realTaskId && r && r.taskId === r.sessionId && r.taskId !== realTaskId) {
437
- events.push({ ...ev, result: { ...ev.result, taskId: realTaskId } });
441
+ events.push(inheritFrameBinding(ev, { ...ev, result: { ...ev.result, taskId: realTaskId } }));
438
442
  }
439
443
  else {
440
444
  events.push(ev);
@@ -14,6 +14,7 @@ export interface AskAnsweredOutput {
14
14
  }>;
15
15
  }
16
16
  export declare function durableSeqOf(ev: object): string | undefined;
17
+ export declare const BODY_SEQ_OTHER_AXIS_EVENTS: readonly string[];
17
18
  export declare function hasLedgerPositionKey(ev: object): boolean;
18
19
  export declare const PREAMBLE_APPROVALS_MAX_ENTRIES = 4096;
19
20
  export interface GateLedger {
@@ -52,6 +53,7 @@ export interface GateLedger {
52
53
  isFsOrShellGatedCall(callId: string): boolean;
53
54
  noteParkGate(evidence: {
54
55
  fsOrShellFamily: boolean;
56
+ gatedCallId?: string | undefined;
55
57
  }): void;
56
58
  hasBatchPark(): boolean;
57
59
  rememberAnswer(callId: string, answered: AskAnsweredOutput): void;
@@ -1,13 +1,21 @@
1
+ import { parkedToolEndRoleOf } from '../engineRowRef.js';
2
+ import { inheritFrameBinding } from '../frameBinding.js';
1
3
  export const SEMA_COLLATERAL_ABORT_KEY = '_sema_collateral_abort';
2
4
  export const SEMA_DENIAL_KIND_KEY = '_sema_denial_kind';
3
5
  export function durableSeqOf(ev) {
4
- const rawSeq = ev.id ?? ev.seq;
6
+ const rec = ev;
7
+ const id = rec.id;
8
+ const rawSeq = id ?? (seqIsAnotherAxis(rec.type) ? undefined : rec.seq);
5
9
  if (typeof rawSeq === 'string' && rawSeq.length > 0)
6
10
  return rawSeq;
7
11
  if (typeof rawSeq === 'number' && Number.isFinite(rawSeq))
8
12
  return String(rawSeq);
9
13
  return undefined;
10
14
  }
15
+ export const BODY_SEQ_OTHER_AXIS_EVENTS = Object.freeze(['task_progress', 'task_notification', 'task_started']);
16
+ function seqIsAnotherAxis(type) {
17
+ return typeof type === 'string' && BODY_SEQ_OTHER_AXIS_EVENTS.includes(type);
18
+ }
11
19
  export function hasLedgerPositionKey(ev) {
12
20
  const { id, seq } = ev;
13
21
  return (id !== undefined && id !== null) || (seq !== undefined && seq !== null);
@@ -27,8 +35,8 @@ export function createGateLedger() {
27
35
  const startedCalls = new Set();
28
36
  const endedCalls = new Set();
29
37
  const heldAskEnds = new Map();
30
- const gatedStartArgsByCall = new Map();
31
38
  const startArgsByCall = new Map();
39
+ const gatedStartCalls = new Set();
32
40
  const deniedCalls = new Set();
33
41
  const denyAttributionByCall = new Map();
34
42
  const pendingFsCalls = [];
@@ -37,6 +45,7 @@ export function createGateLedger() {
37
45
  let alreadyResolvedKey;
38
46
  let alreadyResolvedStreak = 0;
39
47
  let fsOrShellFamilyGate = false;
48
+ let batchParkSubject;
40
49
  const droppedFromBatch = new Set();
41
50
  let batchParkCount = 0;
42
51
  let heldSinceLastPark = false;
@@ -45,6 +54,8 @@ export function createGateLedger() {
45
54
  const resolveGateSubjects = () => {
46
55
  if (batchParkCount !== 1)
47
56
  return undefined;
57
+ if (batchParkSubject !== undefined)
58
+ return new Set([batchParkSubject]);
48
59
  if (!fsOrShellFamilyGate)
49
60
  return undefined;
50
61
  for (const id of heldAskEnds.keys()) {
@@ -78,8 +89,16 @@ export function createGateLedger() {
78
89
  }
79
90
  return n === 1;
80
91
  };
92
+ const bystanderUnderIdentity = (ev, subject) => {
93
+ const parent = ev.parentToolCallId;
94
+ if (typeof parent === 'string' && parent !== '')
95
+ return false;
96
+ const own = ev.gatedCallId;
97
+ return !(typeof own === 'string' && own !== '' && own !== subject);
98
+ };
81
99
  const retireBatchState = () => {
82
100
  fsOrShellFamilyGate = false;
101
+ batchParkSubject = undefined;
83
102
  droppedFromBatch.clear();
84
103
  batchParkCount = 0;
85
104
  heldSinceLastPark = false;
@@ -101,8 +120,8 @@ export function createGateLedger() {
101
120
  forgetRunScopedState() {
102
121
  seq = undefined;
103
122
  startedCalls.clear();
104
- gatedStartArgsByCall.clear();
105
123
  startArgsByCall.clear();
124
+ gatedStartCalls.clear();
106
125
  },
107
126
  notePreambleApproval(approvalId) {
108
127
  if (typeof approvalId !== 'string' || approvalId === '')
@@ -144,26 +163,41 @@ export function createGateLedger() {
144
163
  return true;
145
164
  },
146
165
  noteGatedStart(callId, ev) {
147
- gatedStartArgsByCall.set(callId, ev.args);
166
+ if (!startArgsByCall.has(callId))
167
+ startArgsByCall.set(callId, ev.args);
168
+ gatedStartCalls.add(callId);
148
169
  },
149
170
  gatedStartArgs() {
150
- return gatedStartArgsByCall;
171
+ const out = new Map();
172
+ for (const id of gatedStartCalls)
173
+ if (startArgsByCall.has(id))
174
+ out.set(id, startArgsByCall.get(id));
175
+ return out;
151
176
  },
152
177
  noteStart(callId, ev) {
178
+ if (gatedStartCalls.has(callId))
179
+ return;
153
180
  startArgsByCall.delete(callId);
154
181
  startArgsByCall.set(callId, ev.args);
155
- while (startArgsByCall.size > START_ARGS_MAX_ENTRIES) {
156
- const oldest = startArgsByCall.keys().next();
157
- if (oldest.done === true)
182
+ while (startArgsByCall.size - gatedStartCalls.size > START_ARGS_MAX_ENTRIES) {
183
+ let victim;
184
+ for (const id of startArgsByCall.keys()) {
185
+ if (!gatedStartCalls.has(id)) {
186
+ victim = id;
187
+ break;
188
+ }
189
+ }
190
+ if (victim === undefined)
158
191
  break;
159
- startArgsByCall.delete(oldest.value);
192
+ startArgsByCall.delete(victim);
160
193
  }
161
194
  },
162
195
  startArgs() {
163
196
  return startArgsByCall;
164
197
  },
165
198
  dropStartArgs(callId) {
166
- startArgsByCall.delete(callId);
199
+ if (!gatedStartCalls.has(callId))
200
+ startArgsByCall.delete(callId);
167
201
  },
168
202
  isEnded(callId) {
169
203
  return endedCalls.has(callId);
@@ -195,10 +229,12 @@ export function createGateLedger() {
195
229
  },
196
230
  *flushHeld() {
197
231
  const subjects = resolveGateSubjects();
232
+ const identity = subjects !== undefined ? batchParkSubject : undefined;
198
233
  for (const [callId, ev] of heldAskEnds) {
199
- endedCalls.add(callId);
200
- yield subjects !== undefined && !subjects.has(callId)
201
- ? { ...ev, [SEMA_COLLATERAL_ABORT_KEY]: true }
234
+ if (parkedToolEndRoleOf(ev) !== 'held')
235
+ endedCalls.add(callId);
236
+ yield subjects !== undefined && !subjects.has(callId) && (identity === undefined || bystanderUnderIdentity(ev, identity))
237
+ ? inheritFrameBinding(ev, { ...ev, [SEMA_COLLATERAL_ABORT_KEY]: true })
202
238
  : ev;
203
239
  }
204
240
  heldAskEnds.clear();
@@ -260,6 +296,7 @@ export function createGateLedger() {
260
296
  return;
261
297
  batchParkCount += 1;
262
298
  fsOrShellFamilyGate = evidence.fsOrShellFamily;
299
+ batchParkSubject = typeof evidence.gatedCallId === 'string' && evidence.gatedCallId !== '' ? evidence.gatedCallId : undefined;
263
300
  heldSinceLastPark = false;
264
301
  },
265
302
  hasBatchPark() {
@@ -48,7 +48,6 @@ export type PlanReviewModeAfter = (typeof PLAN_REVIEW_MODE_AFTER_WORDS)[number];
48
48
  export declare function isPlanReviewModeAfter(v: string | undefined): v is PlanReviewModeAfter;
49
49
  export declare const GATE_FAILURE_CODES: readonly ["no_pending", "binding_mismatch", "wrong_gate", "bad_plan_edit", "bad_plan_mode", "empty_answer", "binding_missing"];
50
50
  export type HitlSafetyCode = (typeof GATE_FAILURE_CODES)[number];
51
- export type HitlFailureStage = 'fetch' | 'input' | 'card' | 'decide' | 'orchestration';
52
51
  export declare const NO_APPROVAL_CARD_PORT_REASON = "no approval card port installed (print/non-REPL mode, or host forgot installApprovalCardPort)";
53
52
  export declare const APPROVAL_CARD_PORT_KEY_MISMATCH_REASON = "no approval card port installed for the default session key, but a non-default sessionKey has one \u2014 likely a keyed-install/default-read mismatch (installApprovalCardPortFor vs the zero-arg default-key read), not a missing install";
54
53
  export declare const NO_QUESTION_OVERLAY_REASON = "no question overlay mounted (print/non-REPL mode)";
@@ -61,7 +60,7 @@ export interface HitlDecideDenyOutcome {
61
60
  }
62
61
  export declare class HitlSafetyError extends Error {
63
62
  readonly code: HitlSafetyCode;
64
- constructor(message: string, code: HitlSafetyCode);
63
+ constructor(message: string, code: HitlSafetyCode, options?: ErrorOptions);
65
64
  }
66
65
  export declare function hitlSafetyCodeOf(e: unknown): HitlSafetyCode | undefined;
67
66
  export type GateCurrentPending = Readonly<NonNullable<ApprovalStaleError['currentPending']>>;