@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
@@ -4,8 +4,8 @@ import { hostLog } from '../host.js';
4
4
  import { invokeHostCallbackIsolated } from '../hostCallbackGuard.js';
5
5
  import { abortableSleep } from '../abortableSleep.js';
6
6
  import { ownDataField, readOwnDataValue } from '../ownKey.js';
7
- import { THROWN_SLOT_UNREADABLE, readBlockedBy, readThrownSlot, thrownIsInstanceOf, wireFailureTextsOf } from '../wireFailureShape.js';
8
- import { RESUME_POLICY_FOLD_CODE } from '../engineErrorCodes.js';
7
+ import { PROTOCOL_ERROR_NAME, THROWN_SLOT_UNREADABLE, protocolErrorNameReading, readBlockedBy, readThrownSlot, thrownIsInstanceOf, wireFailureTextsOf } from '../wireFailureShape.js';
8
+ import { APPROVAL_BINDING_MISMATCH, CHECKPOINT_INVALID_OUTCOME, RESUME_POLICY_FOLD_CODE } from '../engineErrorCodes.js';
9
9
  import { suspendedReopenOf } from './suspendedReopen.js';
10
10
  export const DEFAULT_DENY_REASON = 'The user rejected this tool use';
11
11
  const MAX_DENY_REASON_CHARS = 4096;
@@ -46,8 +46,8 @@ export function isNoDecisionSurfaceReason(reason) {
46
46
  }
47
47
  export class HitlSafetyError extends Error {
48
48
  code;
49
- constructor(message, code) {
50
- super(message);
49
+ constructor(message, code, options) {
50
+ super(message, options);
51
51
  this.code = code;
52
52
  this.name = 'HitlSafetyError';
53
53
  }
@@ -455,7 +455,7 @@ export class HitlBridge {
455
455
  catch (e) {
456
456
  const binding = bindingMismatchReading(e);
457
457
  if (binding === 'mismatch') {
458
- throw new HitlSafetyError('approval_binding_mismatch — the pending action changed under the human; refetch + re-present', 'binding_mismatch');
458
+ throw new HitlSafetyError('approval_binding_mismatch — the pending action changed under the human; refetch + re-present', 'binding_mismatch', { cause: e });
459
459
  }
460
460
  if (binding === 'unreadable')
461
461
  throw e;
@@ -532,10 +532,13 @@ function bindingMismatchReading(e) {
532
532
  if (!e || typeof e !== 'object')
533
533
  return 'not';
534
534
  const code = readWireErrorCodeReading(e);
535
- const name = readThrownSlot(e, 'name');
536
- const family = (code.state === 'code' && code.code === 'approval_binding_mismatch') || name === 'ApprovalBindingMismatchError';
535
+ const nameReading = protocolErrorNameReading(e);
536
+ const family = (code.state === 'code' && (code.code === APPROVAL_BINDING_MISMATCH || code.code === CHECKPOINT_INVALID_OUTCOME)) ||
537
+ (nameReading.state === 'named' && nameReading.name === PROTOCOL_ERROR_NAME.ApprovalBindingMismatchError);
537
538
  if (family)
538
539
  return 'mismatch';
540
+ if (nameReading.state === 'sdk-instance' && code.state !== 'code')
541
+ return 'unreadable';
539
542
  if (code.state === 'unreadable')
540
543
  return 'unreadable';
541
544
  return 'not';
@@ -1,5 +1,6 @@
1
+ import type { ApprovalResolution } from './approvalResolution.js';
1
2
  import type { ApprovalsFeedEmission } from './approvalsFeed.js';
2
- import { type RespondToolApprovalFn, type ToolApprovalFrame, type ToolApprovalFrameLaneOpts, type ToolApprovalFrameOutcome } from './toolApprovalWire.js';
3
+ import { type RespondToolApprovalFn, type ToolApprovalFrame, type ToolApprovalFrameLaneOpts } from './toolApprovalWire.js';
3
4
  export interface LivePendingAskView {
4
5
  approvalId: string;
5
6
  toolName: string;
@@ -43,11 +44,10 @@ export interface ApprovalsAwaitingDecisionCount {
43
44
  }
44
45
  export declare function countApprovalsAwaitingDecision(snapshot: ApprovalsFeedEmission | null | undefined, filter: SuspendedAskFilter): ApprovalsAwaitingDecisionCount;
45
46
  export declare function livePendingRowToApprovalFrame(row: LivePendingAskView): ToolApprovalFrame;
46
- export declare function surfaceSuspendedAskAndRespond(row: LivePendingAskView, respond: RespondToolApprovalFn, signal?: AbortSignal, lane?: ToolApprovalFrameLaneOpts): Promise<ToolApprovalFrameOutcome>;
47
+ export declare function surfaceSuspendedAskAndRespond(row: LivePendingAskView, respond: RespondToolApprovalFn, signal?: AbortSignal, lane?: ToolApprovalFrameLaneOpts): Promise<ApprovalResolution>;
47
48
  export interface SuspendedAskDelta {
48
49
  appeared: LivePendingAskView[];
49
50
  gone: string[];
50
- upgraded: LivePendingAskView[];
51
51
  }
52
52
  export interface SuspendedAskTracker {
53
53
  ingest(snapshot: ApprovalsFeedEmission | null | undefined): SuspendedAskDelta;
@@ -1,3 +1,4 @@
1
+ import { readRequiresRealApproval } from './approvalCardReading.js';
1
2
  import { THROWN_SLOT_UNREADABLE, readThrownSlot } from '../wireFailureShape.js';
2
3
  import { isToolApprovalFrame, surfaceToolApprovalFrameAndRespond, } from './toolApprovalWire.js';
3
4
  function nonEmptyString(v) {
@@ -59,7 +60,7 @@ export function readLivePendingRows(body) {
59
60
  ts: o.ts,
60
61
  expiresAtMs: o.expiresAtMs,
61
62
  ...(nonEmptyString(o.sessionId) ? { sessionId: o.sessionId } : {}),
62
- ...(o.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
63
+ ...(readRequiresRealApproval(o) ? { requiresRealApproval: true } : {}),
63
64
  ...(o.governanceForced === true ? { governanceForced: true } : {}),
64
65
  ...(o.fromSubagent === true ? { fromSubagent: true } : {}),
65
66
  ...(nonEmptyString(o.originTaskId) ? { originTaskId: o.originTaskId } : {}),
@@ -128,7 +129,7 @@ export function livePendingRowToApprovalFrame(row) {
128
129
  ...(row.fromSubagent === true ? { fromSubagent: true } : {}),
129
130
  ...(row.originTaskId !== undefined ? { sourceTaskId: row.originTaskId } : {}),
130
131
  ...(row.governanceForced === true ? { governanceForced: true } : {}),
131
- ...(row.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
132
+ ...(readRequiresRealApproval(row) ? { requiresRealApproval: true } : {}),
132
133
  };
133
134
  }
134
135
  export function surfaceSuspendedAskAndRespond(row, respond, signal, lane) {
@@ -144,7 +145,6 @@ const TRACKER_UNSEEN_CLAIMS_MAX = 512;
144
145
  export function createSuspendedAskTracker(filter) {
145
146
  const scope = suspendedAskScopeOf(filter);
146
147
  const shown = new Set();
147
- const shownWithFrame = new Set();
148
148
  const claimed = new Map();
149
149
  const claim = (id) => {
150
150
  if (claimed.has(id))
@@ -166,28 +166,20 @@ export function createSuspendedAskTracker(filter) {
166
166
  return {
167
167
  ingest(snapshot) {
168
168
  if (snapshot?.kind === 'unknown')
169
- return { appeared: [], gone: [], upgraded: [] };
169
+ return { appeared: [], gone: [] };
170
170
  if (scope.kind === 'identity_pending')
171
- return { appeared: [], gone: [], upgraded: [] };
171
+ return { appeared: [], gone: [] };
172
172
  const rows = subagentAsksIn(snapshot, scope);
173
173
  const present = new Set(rows.map(r => r.approvalId));
174
174
  const appeared = [];
175
- const upgraded = [];
176
175
  for (const r of rows) {
177
176
  if (claimed.has(r.approvalId)) {
178
177
  claimed.set(r.approvalId, true);
179
178
  continue;
180
179
  }
181
- if (shown.has(r.approvalId)) {
182
- if (r.frame !== undefined && !shownWithFrame.has(r.approvalId)) {
183
- shownWithFrame.add(r.approvalId);
184
- upgraded.push(r);
185
- }
180
+ if (shown.has(r.approvalId))
186
181
  continue;
187
- }
188
182
  shown.add(r.approvalId);
189
- if (r.frame !== undefined)
190
- shownWithFrame.add(r.approvalId);
191
183
  appeared.push(r);
192
184
  }
193
185
  const incomplete = snapshot !== null && snapshot !== undefined && (snapshot.livePendingDropped ?? 0) > 0;
@@ -197,14 +189,13 @@ export function createSuspendedAskTracker(filter) {
197
189
  if (present.has(id))
198
190
  continue;
199
191
  shown.delete(id);
200
- shownWithFrame.delete(id);
201
192
  gone.push(id);
202
193
  }
203
194
  for (const [id, seen] of [...claimed])
204
195
  if (seen && !present.has(id))
205
196
  claimed.delete(id);
206
197
  }
207
- return { appeared, gone, upgraded };
198
+ return { appeared, gone };
208
199
  },
209
200
  noteSurfacedByStream(approvalId) {
210
201
  if (typeof approvalId !== 'string' || approvalId === '')
@@ -217,7 +208,6 @@ export function createSuspendedAskTracker(filter) {
217
208
  noteDecided(approvalId) {
218
209
  if (typeof approvalId !== 'string' || approvalId === '')
219
210
  return;
220
- shownWithFrame.delete(approvalId);
221
211
  const wasShown = shown.delete(approvalId);
222
212
  if (wasShown)
223
213
  claimed.set(approvalId, true);
@@ -228,7 +218,6 @@ export function createSuspendedAskTracker(filter) {
228
218
  if (typeof approvalId !== 'string' || approvalId === '')
229
219
  return;
230
220
  shown.delete(approvalId);
231
- shownWithFrame.delete(approvalId);
232
221
  claimed.delete(approvalId);
233
222
  },
234
223
  };
@@ -1,9 +1,8 @@
1
1
  import type { AgentEvent } from '@sema-agent/sdk';
2
- import { type GateCurrentPending, type HitlFailureStage, type HitlSafetyCode } from './hitlBridge.js';
2
+ import { type HitlSafetyCode } from './hitlBridge.js';
3
3
  import { type QuestionAnswer } from '../liveQuestionStore.js';
4
4
  import type { AskAnsweredOutput, GateLedger } from './gateLedger.js';
5
5
  import { type AskGateWireDeps, type GatePark } from './frameRouter.js';
6
- import { type DecideReceiptView } from '../decideReceipt.js';
7
6
  export declare const MAX_GATE_HOPS = 2;
8
7
  export type HopRound = 'progress' | 'stalled';
9
8
  export interface HopBudget {
@@ -13,30 +12,9 @@ export interface HopBudget {
13
12
  export declare function nextHopBudget(prev: HopBudget | undefined, round: HopRound): HopBudget;
14
13
  export declare const MAX_TOTAL_PARKS = 64;
15
14
  export type GateFailureCode = HitlSafetyCode;
16
- export type GateOutcome = {
17
- kind: 'decided';
18
- gatedCallId?: string | undefined;
19
- answered?: AskAnsweredOutput | undefined;
20
- receipt?: DecideReceiptView | undefined;
21
- } | {
22
- kind: 'aborted';
23
- gatedCallId?: string | undefined;
24
- } | {
25
- kind: 'failed';
26
- stage: HitlFailureStage;
27
- gatedCallId?: string | undefined;
28
- reason: string;
29
- code?: GateFailureCode | undefined;
30
- errorCode?: string | undefined;
31
- blockedBy?: string | undefined;
32
- retriable?: true;
33
- retryExhausted?: true;
34
- currentPending?: GateCurrentPending | undefined;
35
- };
36
15
  export declare function isAlreadyResolvedGateReason(reason: unknown): boolean;
37
16
  export declare function isAlreadyResolvedFailure(failure: unknown): boolean;
38
- export declare function isGateStandingErrorCode(code: string | null | undefined, retriable?: boolean): boolean;
39
- export declare function isCodeClassifiedGateFailure(code: string | null | undefined, retriable?: boolean): boolean;
17
+ export { isGateStandingErrorCode, isCodeClassifiedGateFailure } from '../gateFailureCodes.js';
40
18
  export declare function toAnsweredOutput(questions: unknown[], answer: QuestionAnswer): AskAnsweredOutput;
41
19
  export type ParkResolution = {
42
20
  kind: 'reattach';
@@ -1,17 +1,17 @@
1
1
  import { putOwnKey, readOwnDataValue } from '../ownKey.js';
2
- import { DecideTransportRetryExhaustedError, GATE_FAILURE_CODES, HitlBridge, NO_QUESTION_OVERLAY_REASON, findPendingForTask, hitlSafetyCodeOf, isNoDecisionSurfaceReason, readDecideCurrentPending, readWireCodes, } from './hitlBridge.js';
3
- import { DECIDE_WORKFLOW_PARK_FORKED, DECIDE_WORKFLOW_PARKS_UNREADABLE, PARKED_RESUME_STARTUP_FAILED, RESUME_POLICY_FOLD_CODE, RESUME_REOPEN_CODES, RESUME_RETRY_LATER_CODES, isRefusedParkCode, refusalSaysStillPending } from '../engineErrorCodes.js';
4
- import { RESUME_REFUSAL_CODES } from '../resumeRefusalCopy.js';
2
+ import { HitlBridge, NO_QUESTION_OVERLAY_REASON, findPendingForTask, isNoDecisionSurfaceReason, } from './hitlBridge.js';
3
+ import { approvalResolutionDetail, resolutionOfDecisionFailure } from './approvalResolution.js';
5
4
  import { readDecisionRefusalAsk } from './decisionRefusal.js';
6
5
  import { publishQuestionFrame, registerLocalQuestionResponder, hasQuestionOverlay, } from '../liveQuestionStore.js';
7
6
  import { hostLog } from '../host.js';
8
7
  import { surfaceFsApprovalAndDecide } from './toolApprovalWire.js';
9
8
  import { INTERRUPT_DENY_REASON, observeCancelByDeny } from './hitlHostSurface.js';
10
9
  import { flushHeldWithInterruptRewrite, isAskTool } from './frameRouter.js';
10
+ import { inheritFrameBinding } from '../frameBinding.js';
11
11
  import { approvalCallKey, askGateQuestionId } from './gateIdentity.js';
12
12
  import { readDecideReceipt } from '../decideReceipt.js';
13
13
  import { decideFailureNote } from '../decideFailureNote.js';
14
- import { thrownIsInstanceOf, wireFailureTextsOf } from '../wireFailureShape.js';
14
+ import { wireFailureTextsOf } from '../wireFailureShape.js';
15
15
  export const MAX_GATE_HOPS = 2;
16
16
  export function nextHopBudget(prev, round) {
17
17
  const total = (prev?.total ?? 0) + 1;
@@ -20,9 +20,6 @@ export function nextHopBudget(prev, round) {
20
20
  const MAX_TRANSPORT_REATTACHES = 2;
21
21
  export const MAX_TOTAL_PARKS = 64;
22
22
  const MAX_ALREADY_RESOLVED_REATTACHES = 1;
23
- function isGateFailureCode(v) {
24
- return typeof v === 'string' && GATE_FAILURE_CODES.includes(v);
25
- }
26
23
  export function isAlreadyResolvedGateReason(reason) {
27
24
  return alreadyResolvedReasonToken(reason) !== undefined;
28
25
  }
@@ -42,19 +39,7 @@ export function isAlreadyResolvedFailure(failure) {
42
39
  return false;
43
40
  }
44
41
  }
45
- export function isGateStandingErrorCode(code, retriable) {
46
- return (code === RESUME_POLICY_FOLD_CODE ||
47
- code === 'corrupt' ||
48
- (isRefusedParkCode(code) && retriable === true) ||
49
- (typeof code === 'string' && RESUME_REOPEN_CODES.includes(code) && retriable === true) ||
50
- code === DECIDE_WORKFLOW_PARKS_UNREADABLE ||
51
- code === DECIDE_WORKFLOW_PARK_FORKED);
52
- }
53
- export function isCodeClassifiedGateFailure(code, retriable) {
54
- return (isGateStandingErrorCode(code, retriable) ||
55
- code === PARKED_RESUME_STARTUP_FAILED ||
56
- (typeof code === 'string' && (RESUME_RETRY_LATER_CODES.includes(code) || RESUME_REFUSAL_CODES.includes(code))));
57
- }
42
+ export { isGateStandingErrorCode, isCodeClassifiedGateFailure } from '../gateFailureCodes.js';
58
43
  export function toAnsweredOutput(questions, answer) {
59
44
  const answers = {};
60
45
  const annotations = {};
@@ -74,12 +59,13 @@ export function toAnsweredOutput(questions, answer) {
74
59
  }
75
60
  async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGatedCallId, onPresented) {
76
61
  if (!hasQuestionOverlay()) {
77
- return { kind: 'failed', stage: 'card', reason: NO_QUESTION_OVERLAY_REASON };
62
+ return { kind: 'not_sent', lane: 'ask', cause: 'card_unavailable', detail: NO_QUESTION_OVERLAY_REASON };
78
63
  }
79
64
  const found = await findPendingForTask(deps.client, taskId, isAskTool, signal ? { signal } : undefined, parkGatedCallId, (row) => isAskTool(typeof row.toolName === 'string' ? row.toolName : undefined));
80
65
  if (!found.ok)
81
- return { kind: 'failed', stage: 'fetch', reason: found.reason, ...(found.code !== undefined ? { code: found.code } : {}) };
66
+ return { kind: 'not_sent', lane: 'ask', cause: found.code ?? 'fetch_failed', ...(found.reason !== '' ? { detail: found.reason } : {}) };
82
67
  const { pending, gatedCallId } = found;
68
+ const at = { lane: 'ask', ...(gatedCallId !== undefined ? { gatedCallId } : {}) };
83
69
  const fromArgs = gatedCallId
84
70
  ? askArgsByCall.get(gatedCallId)?.questions
85
71
  : undefined;
@@ -88,10 +74,10 @@ async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGat
88
74
  if (!Array.isArray(questions) || questions.length === 0) {
89
75
  const truncated = pending.input?.truncated === true;
90
76
  return {
91
- kind: 'failed',
92
- stage: 'input',
93
- gatedCallId,
94
- reason: truncated
77
+ kind: 'not_sent',
78
+ ...at,
79
+ cause: 'no_input',
80
+ detail: truncated
95
81
  ? 'question payload exceeded the engine input cap (input={truncated:true}) — dialog cannot be re-rendered; run stays suspended for out-of-band decide'
96
82
  : 'gate has no question payload (pre-CHANNEL[56] engine?)',
97
83
  };
@@ -123,7 +109,7 @@ async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGat
123
109
  const bridge = new HitlBridge(deps.client, taskId, deps.onDecideOperation ? { onDecideOperation: deps.onDecideOperation } : undefined);
124
110
  if (answer === null) {
125
111
  observeCancelByDeny(bridge.decideTool({ decision: 'deny', reason: INTERRUPT_DENY_REASON }, gatedCallId, undefined, pending), taskId);
126
- return { kind: 'aborted', gatedCallId };
112
+ return { kind: 'unsettled', ...at, cause: 'interrupted' };
127
113
  }
128
114
  let declinedReceipt;
129
115
  let attemptedDecision;
@@ -136,7 +122,8 @@ async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGat
136
122
  const receipt = readDecideReceipt(raw);
137
123
  return {
138
124
  kind: 'decided',
139
- gatedCallId,
125
+ ...at,
126
+ decision: 'allow',
140
127
  answered: toAnsweredOutput(questions, answer),
141
128
  ...(receipt !== undefined ? { receipt } : {}),
142
129
  };
@@ -146,26 +133,12 @@ async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGat
146
133
  const raw = await bridge.decideTool({ decision: 'deny', reason: 'User declined to answer' }, gatedCallId, signal ? { signal } : undefined, pending);
147
134
  declinedReceipt = readDecideReceipt(raw);
148
135
  }
149
- return { kind: 'decided', gatedCallId, ...(declinedReceipt !== undefined ? { receipt: declinedReceipt } : {}) };
136
+ return { kind: 'decided', ...at, decision: 'deny', ...(declinedReceipt !== undefined ? { receipt: declinedReceipt } : {}) };
150
137
  }
151
138
  catch (e) {
152
- const code = hitlSafetyCodeOf(e);
153
- const currentPending = readDecideCurrentPending(e);
154
- const wireCodes = readWireCodes(e);
155
- const wireRetriable = typeof e === 'object' && e !== null && refusalSaysStillPending(e);
156
139
  const failureTexts = wireFailureTextsOf(e);
157
140
  hostLog('debug', `liveHitlAskWire: decide failed: ${failureTexts.log}`);
158
- return {
159
- kind: 'failed',
160
- stage: 'decide',
161
- gatedCallId,
162
- reason: `decide failed: ${failureTexts.reason}${decideFailureNote(e, attemptedDecision)}`,
163
- ...(code !== undefined ? { code } : {}),
164
- ...(thrownIsInstanceOf(e, DecideTransportRetryExhaustedError) ? { retryExhausted: true } : {}),
165
- ...(currentPending !== undefined ? { currentPending } : {}),
166
- ...wireCodes,
167
- ...(wireRetriable ? { retriable: true } : {}),
168
- };
141
+ return resolutionOfDecisionFailure(e, { lane: 'ask', route: 'ask_decide', gatedCallId, detail: `decide failed: ${failureTexts.reason}${decideFailureNote(e, attemptedDecision)}` });
169
142
  }
170
143
  }
171
144
  function argsByCallOf(led) {
@@ -175,8 +148,18 @@ function alreadyResolvedStreakKey(byDecidedIdOnly) {
175
148
  return byDecidedIdOnly ? 'decided-id-match' : 'already-resolved';
176
149
  }
177
150
  function isFetchStepNoPending(outcome) {
178
- const code = 'code' in outcome && isGateFailureCode(outcome.code) ? outcome.code : undefined;
179
- return code === 'no_pending' && outcome.gatedCallId === undefined;
151
+ return outcome.kind === 'not_sent' && outcome.cause === 'no_pending' && outcome.gatedCallId === undefined;
152
+ }
153
+ function isHumanDisposition(r) {
154
+ return r.kind === 'decided' || (r.kind === 'unsettled' && r.cause === 'interrupted') || (r.kind === 'not_sent' && r.cause === 'retracted');
155
+ }
156
+ function failureReasonOf(r) {
157
+ if (r.kind === 'decided')
158
+ return '';
159
+ return r.detail ?? approvalResolutionDetail(r) ?? r.cause;
160
+ }
161
+ function orchestrationEnd(park, gatedCallId, detail) {
162
+ return { kind: 'unsettled', lane: park.gate === 'fs' ? 'decide' : 'ask', cause: 'orchestration', ...(gatedCallId !== undefined ? { gatedCallId } : {}), detail };
180
163
  }
181
164
  async function surfaceParkGate(park, ctx, gatedCallId, onPresented) {
182
165
  const { deps, led, taskId } = ctx;
@@ -194,13 +177,10 @@ async function surfaceParkGate(park, ctx, gatedCallId, onPresented) {
194
177
  ...(deps.onDecideOperation ? { onDecideOperation: deps.onDecideOperation } : {}),
195
178
  ...(decidedByReading !== undefined ? { approvalDecidedBy: decidedByReading } : {}),
196
179
  }, taskId, argsByCallOf(led), ctx.signal, gatedCallId, park.toolName);
197
- const outcomeDenied = 'denied' in outcome ? outcome.denied : undefined;
198
- if (outcome.kind === 'decided' && outcomeDenied === true && outcome.gatedCallId) {
199
- const denySettledBy = 'denySettledBy' in outcome ? outcome.denySettledBy : undefined;
200
- const denyReason = 'denyReason' in outcome ? outcome.denyReason : undefined;
180
+ if (outcome.kind === 'decided' && outcome.decision === 'deny' && outcome.gatedCallId) {
201
181
  led.markDenied(outcome.gatedCallId, {
202
- ...(denySettledBy !== undefined ? { settledBy: denySettledBy } : {}),
203
- ...(denyReason !== undefined ? { reason: denyReason } : {}),
182
+ ...(outcome.deny?.settledBy !== undefined ? { settledBy: outcome.deny.settledBy } : {}),
183
+ ...(outcome.deny?.reason !== undefined ? { reason: outcome.deny.reason } : {}),
204
184
  });
205
185
  }
206
186
  return outcome;
@@ -225,25 +205,18 @@ export async function resolvePark(park, ctx) {
225
205
  };
226
206
  if ((ctx.unverifiableParks ?? 0) > MAX_TOTAL_PARKS) {
227
207
  closingCardTried = true;
228
- outcome = {
229
- kind: 'failed',
230
- stage: 'orchestration',
231
- reason: `${ctx.unverifiableParks ?? 0} parks in this single turn resolved to no identifiable approval (hard cap ${MAX_TOTAL_PARKS}; last: ${ctx.lastStallReason ?? 'the engine kept parking'})`,
232
- };
208
+ outcome = orchestrationEnd(park, undefined, `${ctx.unverifiableParks ?? 0} parks in this single turn resolved to no identifiable approval (hard cap ${MAX_TOTAL_PARKS}; last: ${ctx.lastStallReason ?? 'the engine kept parking'})`);
233
209
  }
234
210
  else if (stalledRounds > MAX_GATE_HOPS) {
235
211
  closingCardTried = true;
236
212
  const stalledReason = `the run stayed parked across ${stalledRounds} consecutive re-attach rounds without any host progress ` +
237
213
  `(last: ${ctx.lastStallReason ?? 'unknown'})`;
238
214
  if (ctx.lastRoundPresentedCard === true) {
239
- outcome = { kind: 'failed', stage: 'orchestration', reason: stalledReason };
215
+ outcome = orchestrationEnd(park, undefined, stalledReason);
240
216
  }
241
217
  else {
242
218
  const closing = await surfaceParkGate(park, ctx, park.gatedCallId, witness);
243
- outcome =
244
- closing.kind === 'decided' || closing.kind === 'aborted' || closing.kind === 'retracted'
245
- ? closing
246
- : { kind: 'failed', stage: 'orchestration', reason: `${stalledReason}; closing re-read: ${closing.reason}` };
219
+ outcome = isHumanDisposition(closing) ? closing : orchestrationEnd(park, undefined, `${stalledReason}; closing re-read: ${failureReasonOf(closing)}`);
247
220
  }
248
221
  }
249
222
  else {
@@ -251,21 +224,20 @@ export async function resolvePark(park, ctx) {
251
224
  candidateGatedCallId = decidedIdentityCandidate(led, park);
252
225
  outcome = await surfaceParkGate(park, ctx, park.gatedCallId, witness);
253
226
  }
254
- const alreadyDecidedById = outcome.kind === 'failed' &&
227
+ const failed = !isHumanDisposition(outcome);
228
+ const alreadyDecidedById = failed &&
255
229
  candidateGatedCallId !== undefined &&
256
230
  led.takeDecided(candidateGatedCallId);
257
- if (!closingCardTried && outcome.kind === 'failed' && (isAlreadyResolvedFailure(outcome) || alreadyDecidedById)) {
258
- const firstReason = outcome.reason;
231
+ if (!closingCardTried && failed && (isAlreadyResolvedFailure(outcome) || alreadyDecidedById)) {
232
+ const firstReason = failureReasonOf(outcome);
259
233
  const streakKey = alreadyResolvedStreakKey(!isAlreadyResolvedFailure(outcome) && alreadyDecidedById);
260
- const reasonToken = alreadyResolvedReasonToken(outcome.reason);
234
+ const reasonToken = alreadyResolvedReasonToken(firstReason);
261
235
  const rescan = isFetchStepNoPending(outcome) && stalledRounds <= MAX_GATE_HOPS
262
236
  ? await surfaceParkGate(park, ctx, park.gatedCallId, witness)
263
237
  : undefined;
264
238
  if (rescan !== undefined &&
265
- (rescan.kind === 'decided' ||
266
- rescan.kind === 'aborted' ||
267
- rescan.kind === 'retracted' ||
268
- (rescan.kind === 'failed' && rescan.retryExhausted === true))) {
239
+ (isHumanDisposition(rescan) ||
240
+ (rescan.kind === 'unsettled' && rescan.cause === 'transport_exhausted'))) {
269
241
  hostLog('debug', `liveHitlAskWire: gate reported already-resolved (${firstReason}) but a fresh approvals re-read for run ` +
270
242
  `${taskId} surfaced a decidable row under the current coordinates — re-presented it (rescan: ${rescan.kind}) ` +
271
243
  `instead of re-attaching on the stale park identity`);
@@ -286,48 +258,40 @@ export async function resolvePark(park, ctx) {
286
258
  `(last gate reason: ${firstReason})`;
287
259
  hostLog('warn', `liveHitlAskWire: refusing to re-attach runs.events(${taskId}) again — ${stalled} ` +
288
260
  `[criterion: ${streakKey}${reasonToken !== undefined ? ` via reason token "${reasonToken}"` : ''}]`);
289
- outcome = {
290
- kind: 'failed',
291
- stage: 'orchestration',
292
- ...(outcome.gatedCallId !== undefined ? { gatedCallId: outcome.gatedCallId } : {}),
293
- reason: stalled,
294
- };
261
+ outcome = orchestrationEnd(park, outcome.gatedCallId, stalled);
295
262
  }
296
263
  }
297
- if (outcome.kind === 'failed' && outcome.retryExhausted === true && !closingCardTried) {
298
- const token = transportReasonToken(outcome.reason);
264
+ if (outcome.kind === 'unsettled' && outcome.cause === 'transport_exhausted' && !closingCardTried) {
265
+ const transportReason = failureReasonOf(outcome);
266
+ const token = transportReasonToken(transportReason);
299
267
  const streak = led.noteAlreadyResolvedGate(`transport:${token}`);
300
268
  if (streak <= MAX_TRANSPORT_REATTACHES) {
301
269
  const seq = led.lastSeq();
302
270
  notifyParkReattach(ctx, streak, MAX_TRANSPORT_REATTACHES, `decide transport failed: ${token}`);
303
- hostLog('debug', `liveHitlAskWire: decide transport retries exhausted (${outcome.reason}) — re-presenting the gate via ` +
271
+ hostLog('debug', `liveHitlAskWire: decide transport retries exhausted (${transportReason}) — re-presenting the gate via ` +
304
272
  `re-attach runs.events(${taskId})${seq ? ` from seq ${seq}` : ''} instead of failing the turn (the run is still parked and the pending row is still decidable) [${streak}/${MAX_TRANSPORT_REATTACHES}]`);
305
273
  return { kind: 'reattach', progress: false, reason: `decide transport failed: ${token}`, presented: presentedThisRound, gatedCallId: outcome.gatedCallId };
306
274
  }
307
- outcome = {
308
- kind: 'failed',
309
- stage: 'orchestration',
310
- ...(outcome.gatedCallId !== undefined ? { gatedCallId: outcome.gatedCallId } : {}),
311
- reason: `the decide call failed on transport ${streak} times in a row while the run stayed parked (${outcome.reason})`,
312
- };
275
+ outcome = orchestrationEnd(park, outcome.gatedCallId, `the decide call failed on transport ${streak} times in a row while the run stayed parked (${transportReason})`);
313
276
  }
314
277
  if (outcome.kind !== 'decided') {
315
- hostLog('debug', `liveHitlAskWire: gate not decided (${outcome.kind}${'reason' in outcome ? `: ${outcome.reason}` : ''}) — fail-soft to suspended terminal`);
316
- const failedReason = outcome.kind === 'failed'
317
- ? outcome.reason
318
- : outcome.kind === 'retracted'
278
+ hostLog('debug', `liveHitlAskWire: gate not decided (${outcome.kind}/${outcome.cause}: ${failureReasonOf(outcome)}) — fail-soft to suspended terminal`);
279
+ const interrupted = outcome.kind === 'unsettled' && outcome.cause === 'interrupted';
280
+ const failedReason = interrupted
281
+ ? undefined
282
+ : outcome.kind === 'not_sent' && outcome.cause === 'retracted'
319
283
  ? 'the approval card was retracted by the host without a decision (nothing was sent; the run stays parked and remains decidable elsewhere)'
320
- : undefined;
321
- const noDecisionSurface = outcome.kind === 'failed' && outcome.stage === 'card' && isNoDecisionSurfaceReason(outcome.reason);
322
- return { kind: 'failsoft', events: failsoftEvents(park, ctx, outcome.kind === 'aborted', failedReason, undefined, noDecisionSurface) };
284
+ : failureReasonOf(outcome);
285
+ const noDecisionSurface = outcome.kind === 'not_sent' && outcome.cause === 'card_unavailable' && outcome.detail !== undefined && isNoDecisionSurfaceReason(outcome.detail);
286
+ return { kind: 'failsoft', events: failsoftEvents(park, ctx, interrupted, failedReason, undefined, noDecisionSurface) };
323
287
  }
324
288
  led.dropHeldForDecidedPark(outcome.gatedCallId, park.gatedCallId);
325
289
  if (outcome.gatedCallId) {
326
290
  led.markDecided(outcome.gatedCallId);
327
- if ('answered' in outcome && outcome.answered)
291
+ if (outcome.answered)
328
292
  led.rememberAnswer(outcome.gatedCallId, outcome.answered);
329
293
  }
330
- const handoffTaskId = 'receipt' in outcome && outcome.receipt?.handoffTaskId !== undefined && outcome.receipt.handoffTaskId !== taskId
294
+ const handoffTaskId = outcome.receipt?.handoffTaskId !== undefined && outcome.receipt.handoffTaskId !== taskId
331
295
  ? outcome.receipt.handoffTaskId
332
296
  : undefined;
333
297
  const seq = led.lastSeq();
@@ -360,13 +324,13 @@ function failsoftEvents(park, ctx, gateAbortedByUser, failedReason, terminal, no
360
324
  ];
361
325
  const reason = failsoftReasonSentence(park, failedReason, terminal);
362
326
  if (park.pendingDone) {
363
- events.push(reason === undefined || noDecisionSurface ? park.pendingDone : { ...park.pendingDone, _sema_park_failed_reason: reason });
327
+ events.push(reason === undefined || noDecisionSurface ? park.pendingDone : inheritFrameBinding(park.pendingDone, { ...park.pendingDone, _sema_park_failed_reason: reason }));
364
328
  }
365
329
  else if (terminal !== undefined) {
366
- events.push({ type: 'failed', ...terminal });
330
+ events.push(inheritFrameBinding(park.parkFrame, { type: 'failed', ...terminal }));
367
331
  }
368
332
  else if (reason !== undefined) {
369
- events.push({ type: 'failed', errorCode: 'hitl_unanswered', errorMessage: reason });
333
+ events.push(inheritFrameBinding(park.parkFrame, { type: 'failed', errorCode: 'hitl_unanswered', errorMessage: reason }));
370
334
  }
371
335
  return events;
372
336
  }
@@ -88,6 +88,30 @@ export declare const PERSISTED_RULE_BEHAVIORS: readonly RuleBehavior[];
88
88
  export declare function persistedRuleBehaviorOf(rule: unknown): RuleBehavior | undefined;
89
89
  export declare const PERSISTED_RULE_BEHAVIOR_UNKNOWN = "(unknown)";
90
90
  export declare function persistedRuleBehaviorLabel(rule: unknown): string;
91
+ export interface PersistedRuleOriginsRow {
92
+ readonly adds?: readonly {
93
+ readonly origin?: string | undefined;
94
+ }[] | undefined;
95
+ }
96
+ export declare function persistedRuleAddOriginLabel(origin: string | undefined): string;
97
+ export declare function persistedRuleOriginsLabel(rule: PersistedRuleOriginsRow): string;
98
+ export declare function persistedRuleScopeLabel(scope: string | undefined): string;
99
+ export type PersistedRuleRevokeOutcomeWord = 'removed' | 'nothing-written' | 'unknown-status';
100
+ export interface PersistedRuleRevokeResultBody {
101
+ readonly status?: string | undefined;
102
+ readonly stillLive?: string | undefined;
103
+ }
104
+ export interface PersistedRuleRevokeOutcome {
105
+ readonly outcome: PersistedRuleRevokeOutcomeWord;
106
+ readonly liveness: PersistedRuleLiveness;
107
+ readonly notice: string;
108
+ readonly change: string;
109
+ }
110
+ export declare function persistedRuleRevokeOutcome(ruleText: string | undefined, result: PersistedRuleRevokeResultBody | undefined): PersistedRuleRevokeOutcome;
111
+ export interface PersistedRuleMatchRow {
112
+ readonly match?: string | undefined;
113
+ }
114
+ export declare function persistedRuleMatchLabel(ruleOrMatch: string | PersistedRuleMatchRow | undefined): string;
91
115
  export declare function revokeTargetFromPersistedRule(rule: unknown, opts?: {
92
116
  principal?: string;
93
117
  }): RuleRevokeRequest | undefined;