@sema-agent/client-core 0.100.0 → 0.101.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 (335) hide show
  1. package/CHANGELOG.md +395 -0
  2. package/README.md +164 -117
  3. package/dist/adapt/arms.js +51 -16
  4. package/dist/adapt/textStream.js +7 -4
  5. package/dist/adapt/toolCards.js +9 -8
  6. package/dist/adapt.js +7 -1
  7. package/dist/adapter/activeRunSelfHeal.d.ts +24 -2
  8. package/dist/adapter/activeRunSelfHeal.js +108 -6
  9. package/dist/adapter/downstream/eventToSdkMessage.js +33 -12
  10. package/dist/adapter/downstream/terminalToSdkResult.d.ts +60 -1
  11. package/dist/adapter/downstream/terminalToSdkResult.js +209 -39
  12. package/dist/adapter/runStream.d.ts +4 -4
  13. package/dist/adapter/runStream.js +158 -43
  14. package/dist/agentsWireCaps.d.ts +2 -7
  15. package/dist/agentsWireCaps.js +1 -2
  16. package/dist/approvalDecidedByCapability.js +2 -2
  17. package/dist/approvalFrameFamilies.d.ts +33 -0
  18. package/dist/approvalFrameFamilies.js +120 -0
  19. package/dist/approvalsStreamLiveCapability.js +2 -2
  20. package/dist/attachmentsWireCaps.js +41 -13
  21. package/dist/callerCwdCapability.js +2 -2
  22. package/dist/centerWiringCapability.js +2 -2
  23. package/dist/clockReading.d.ts +2 -0
  24. package/dist/clockReading.js +4 -0
  25. package/dist/cloudConfigWireCaps.d.ts +19 -5
  26. package/dist/cloudConfigWireCaps.js +193 -56
  27. package/dist/coreValuePorts.d.ts +12 -2
  28. package/dist/coreValuePorts.js +9 -0
  29. package/dist/decideFailureNote.js +5 -3
  30. package/dist/decideReceipt.js +2 -2
  31. package/dist/deviceExecutorManagementCapability.js +2 -2
  32. package/dist/deviceFlowPolling.js +1 -1
  33. package/dist/disableSkillsWire.d.ts +1 -1
  34. package/dist/disableSkillsWire.js +4 -3
  35. package/dist/displayUntrusted.d.ts +1 -0
  36. package/dist/displayUntrusted.js +65 -8
  37. package/dist/engineCapReader.js +1 -1
  38. package/dist/engineConfigDrift.js +1 -1
  39. package/dist/engineErrorCodes.d.ts +14 -5
  40. package/dist/engineErrorCodes.js +27 -6
  41. package/dist/engineGenerationConvergence.d.ts +39 -0
  42. package/dist/engineGenerationConvergence.js +95 -0
  43. package/dist/engineGenerationPort.d.ts +61 -0
  44. package/dist/engineGenerationPort.js +144 -0
  45. package/dist/engineHealthFacts.d.ts +23 -0
  46. package/dist/engineHealthFacts.js +92 -0
  47. package/dist/engineIdentity.d.ts +4 -0
  48. package/dist/engineIdentity.js +11 -0
  49. package/dist/engineNoticeCodes.d.ts +2 -5
  50. package/dist/engineRowRef.js +3 -0
  51. package/dist/engineSessionMessages.js +2 -2
  52. package/dist/engineToolDirectory.js +2 -2
  53. package/dist/engineWireFor.d.ts +99 -0
  54. package/dist/engineWireFor.js +248 -6
  55. package/dist/engineWireTarget.d.ts +1 -0
  56. package/dist/engineWireTarget.js +8 -0
  57. package/dist/env/uiLanguage.js +1 -1
  58. package/dist/errorSupplementRoles.d.ts +3 -0
  59. package/dist/errorSupplementRoles.js +37 -0
  60. package/dist/executionLaneCapability.js +2 -2
  61. package/dist/fileHistoryCaptureCapability.js +3 -3
  62. package/dist/finalVerifyWire.d.ts +6 -3
  63. package/dist/finalVerifyWire.js +6 -23
  64. package/dist/flagInput.d.ts +4 -0
  65. package/dist/flagInput.js +24 -0
  66. package/dist/fleet/fleetLedger.js +5 -2
  67. package/dist/fleet/fleetProjection.d.ts +1 -0
  68. package/dist/fleet/fleetProjection.js +15 -2
  69. package/dist/gateVocabulary.js +3 -0
  70. package/dist/generated/engineFactTables.d.ts +7 -3
  71. package/dist/generated/engineFactTables.js +52 -0
  72. package/dist/generated/engineNoticeTables.js +12 -0
  73. package/dist/generated/settingsSchemaActiveTiers.d.ts +1 -0
  74. package/dist/generated/settingsSchemaActiveTiers.js +14 -0
  75. package/dist/generated/settingsSchemaCallerTextEcho.d.ts +1 -0
  76. package/dist/generated/settingsSchemaCallerTextEcho.js +8 -0
  77. package/dist/generated/settingsSchemaControlAndBidi.d.ts +1 -0
  78. package/dist/generated/settingsSchemaControlAndBidi.js +8 -0
  79. package/dist/generated/settingsSchemaDefaultModel.d.ts +11 -0
  80. package/dist/generated/settingsSchemaDefaultModel.js +25 -0
  81. package/dist/generated/settingsSchemaFns.d.ts +54 -0
  82. package/dist/generated/settingsSchemaFns.js +26 -1
  83. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
  84. package/dist/generated/settingsSchemaMcpRequestEntry.js +1 -7
  85. package/dist/generated/settingsSchemaSafetyMergeSpec.d.ts +1 -0
  86. package/dist/generated/settingsSchemaSafetyMergeSpec.js +95 -0
  87. package/dist/generated/settingsSchemaSettingsSources.d.ts +1 -0
  88. package/dist/generated/settingsSchemaSettingsSources.js +58 -0
  89. package/dist/generated/settingsSchemaTables.d.ts +2 -0
  90. package/dist/generated/settingsSchemaTables.js +13 -0
  91. package/dist/generated/settingsSchemaUrlPattern.d.ts +1 -0
  92. package/dist/generated/settingsSchemaUrlPattern.js +183 -0
  93. package/dist/headlessPermissionModeWire.d.ts +18 -2
  94. package/dist/headlessPermissionModeWire.js +30 -19
  95. package/dist/hitl/allowRuleShadow.js +7 -5
  96. package/dist/hitl/approvalCardReading.d.ts +3 -0
  97. package/dist/hitl/approvalCardReading.js +17 -0
  98. package/dist/hitl/approvalCompleteParked.js +1 -1
  99. package/dist/hitl/approvalDelivery.d.ts +87 -0
  100. package/dist/hitl/approvalDelivery.js +193 -0
  101. package/dist/hitl/approvalResolution.d.ts +11 -0
  102. package/dist/hitl/approvalResolution.js +50 -11
  103. package/dist/hitl/askClassPair.d.ts +6 -0
  104. package/dist/hitl/askClassPair.js +30 -3
  105. package/dist/hitl/askParkAutoReopenBlock.d.ts +30 -0
  106. package/dist/hitl/askParkAutoReopenBlock.js +117 -0
  107. package/dist/hitl/askParkRowRouting.js +4 -1
  108. package/dist/hitl/attributionLadder.d.ts +42 -3
  109. package/dist/hitl/attributionLadder.js +79 -8
  110. package/dist/hitl/automaticAnswerVerdict.d.ts +6 -1
  111. package/dist/hitl/automaticAnswerVerdict.js +46 -11
  112. package/dist/hitl/crashConverged.js +2 -2
  113. package/dist/hitl/decisionConflict.d.ts +6 -2
  114. package/dist/hitl/decisionConflict.js +24 -9
  115. package/dist/hitl/decisionRefusal.d.ts +20 -10
  116. package/dist/hitl/decisionRefusal.js +99 -54
  117. package/dist/hitl/decisionSend.d.ts +3 -0
  118. package/dist/hitl/decisionSend.js +87 -103
  119. package/dist/hitl/frameRouter.d.ts +1 -0
  120. package/dist/hitl/frameRouter.js +9 -2
  121. package/dist/hitl/hitlBridge.d.ts +18 -6
  122. package/dist/hitl/hitlBridge.js +41 -37
  123. package/dist/hitl/livePendingAsk.js +4 -3
  124. package/dist/hitl/noAllowCause.js +1 -1
  125. package/dist/hitl/parkResolver.js +3 -2
  126. package/dist/hitl/persistedRulesWire.js +1 -0
  127. package/dist/hitl/planReviewWire.d.ts +4 -0
  128. package/dist/hitl/planReviewWire.js +59 -30
  129. package/dist/hitl/resumeRunningCard.d.ts +3 -2
  130. package/dist/hitl/resumeRunningCard.js +17 -11
  131. package/dist/hitl/sessionPolicyDeliverable.d.ts +5 -2
  132. package/dist/hitl/sessionPolicyDeliverable.js +62 -29
  133. package/dist/hitl/sessionPolicyWire.d.ts +13 -3
  134. package/dist/hitl/sessionPolicyWire.js +81 -16
  135. package/dist/hitl/standingRows.js +1 -1
  136. package/dist/hitl/toolApprovalWire.d.ts +9 -10
  137. package/dist/hitl/toolApprovalWire.js +72 -54
  138. package/dist/hookMatcherVerdict.d.ts +2 -0
  139. package/dist/hookMatcherVerdict.js +12 -0
  140. package/dist/hooksCompactTransition.d.ts +19 -0
  141. package/dist/hooksCompactTransition.js +41 -0
  142. package/dist/hooksWireCaps.d.ts +1 -1
  143. package/dist/hooksWireCaps.js +202 -203
  144. package/dist/host.d.ts +1 -14
  145. package/dist/host.js +0 -8
  146. package/dist/hostCallbackGuard.d.ts +1 -0
  147. package/dist/hostCallbackGuard.js +1 -1
  148. package/dist/hostSettingsSource.d.ts +172 -0
  149. package/dist/hostSettingsSource.js +675 -0
  150. package/dist/hostTurnSettings.d.ts +73 -17
  151. package/dist/hostTurnSettings.js +594 -97
  152. package/dist/httpHookPolicy.d.ts +37 -0
  153. package/dist/httpHookPolicy.js +176 -0
  154. package/dist/humanTurn.d.ts +2 -1
  155. package/dist/humanTurn.js +37 -7
  156. package/dist/humanTurnRead.js +4 -3
  157. package/dist/humanTurnSentences.d.ts +10 -0
  158. package/dist/humanTurnSentences.js +74 -0
  159. package/dist/i18n/messages.en.d.ts +184 -2
  160. package/dist/i18n/messages.en.js +187 -5
  161. package/dist/i18n/messages.zh.js +197 -5
  162. package/dist/i18n/translate.js +3 -3
  163. package/dist/index.d.ts +69 -15
  164. package/dist/index.js +45 -13
  165. package/dist/inheritEnvCapability.d.ts +3 -1
  166. package/dist/inheritEnvCapability.js +31 -17
  167. package/dist/inheritEnvWire.d.ts +2 -1
  168. package/dist/inheritEnvWire.js +11 -5
  169. package/dist/interactiveToolsWire.d.ts +4 -2
  170. package/dist/interactiveToolsWire.js +5 -5
  171. package/dist/jsonFaithful.d.ts +20 -0
  172. package/dist/jsonFaithful.js +152 -0
  173. package/dist/limitsWire.d.ts +7 -2
  174. package/dist/limitsWire.js +19 -13
  175. package/dist/liveInitToolFace.d.ts +6 -1
  176. package/dist/liveInitToolFace.js +5 -3
  177. package/dist/liveModelCatalog.d.ts +22 -0
  178. package/dist/liveModelCatalog.js +132 -18
  179. package/dist/mcpPanel.js +1 -1
  180. package/dist/mcpProbeCapability.js +2 -2
  181. package/dist/mcpStatusSupersetKeys.d.ts +24 -0
  182. package/dist/mcpStatusSupersetKeys.js +45 -0
  183. package/dist/mcpToolToggles.js +2 -1
  184. package/dist/mcpWireCaps.d.ts +39 -1
  185. package/dist/mcpWireCaps.js +254 -50
  186. package/dist/memoryComplianceCapability.js +2 -2
  187. package/dist/memoryOriginCapability.js +2 -2
  188. package/dist/model/catalogDefault.d.ts +24 -0
  189. package/dist/model/catalogDefault.js +4 -0
  190. package/dist/model/liveCatalogShape.js +5 -4
  191. package/dist/model/modelsPolicy.js +4 -3
  192. package/dist/model/onboardJudgement.d.ts +1 -0
  193. package/dist/model/onboardJudgement.js +1 -1
  194. package/dist/model/subagentModelWord.js +2 -2
  195. package/dist/modelCapabilityProbe.js +6 -6
  196. package/dist/modelIdentityResolvability.d.ts +10 -1
  197. package/dist/modelIdentityResolvability.js +62 -39
  198. package/dist/modsKernelIdentity.d.ts +10 -0
  199. package/dist/modsKernelIdentity.js +103 -0
  200. package/dist/modsKernelTransit.d.ts +8 -0
  201. package/dist/modsKernelTransit.js +6 -0
  202. package/dist/notifications.d.ts +30 -12
  203. package/dist/notifications.js +241 -53
  204. package/dist/outputStyleSeatCapability.js +2 -2
  205. package/dist/ownKey.d.ts +11 -0
  206. package/dist/ownKey.js +164 -3
  207. package/dist/panelReduce.js +1 -1
  208. package/dist/peerFrames.d.ts +1 -1
  209. package/dist/peerFrames.js +6 -2
  210. package/dist/peerLaneCapability.js +2 -2
  211. package/dist/permissionModesCapability.js +4 -4
  212. package/dist/permissionRuleIssue.js +2 -0
  213. package/dist/permissionRulesWriteCapability.js +2 -2
  214. package/dist/permissionsAllowGrantCapability.js +2 -2
  215. package/dist/permissionsDeclaration.d.ts +43 -4
  216. package/dist/permissionsDeclaration.js +102 -35
  217. package/dist/pluginHooksWire.d.ts +20 -4
  218. package/dist/pluginHooksWire.js +92 -53
  219. package/dist/prepareRefusal.d.ts +3 -2
  220. package/dist/prepareRefusal.js +27 -9
  221. package/dist/printInitToolFace.js +2 -2
  222. package/dist/printModelStatus.js +1 -1
  223. package/dist/projectMemory.d.ts +32 -0
  224. package/dist/projectMemory.js +70 -0
  225. package/dist/promptBlockedCopy.d.ts +2 -1
  226. package/dist/promptBlockedCopy.js +2 -1
  227. package/dist/promptDelivery.d.ts +23 -3
  228. package/dist/promptDelivery.js +169 -30
  229. package/dist/providerRejection.d.ts +19 -1
  230. package/dist/providerRejection.js +75 -4
  231. package/dist/queuedDelivery.d.ts +48 -0
  232. package/dist/queuedDelivery.js +233 -0
  233. package/dist/reattachWindow.d.ts +94 -0
  234. package/dist/reattachWindow.js +127 -0
  235. package/dist/request/printNotification.d.ts +1 -1
  236. package/dist/request/printNotification.js +5 -1
  237. package/dist/request/submissionIdentity.d.ts +37 -0
  238. package/dist/request/submissionIdentity.js +65 -0
  239. package/dist/request/taskRequest.d.ts +12 -4
  240. package/dist/request/taskRequest.js +221 -152
  241. package/dist/resultFrameKeys.d.ts +1 -0
  242. package/dist/resultFrameKeys.js +4 -1
  243. package/dist/retryStatus.d.ts +8 -0
  244. package/dist/retryStatus.js +57 -9
  245. package/dist/rewindArchiveCapability.js +2 -2
  246. package/dist/rewindEngineAction.d.ts +2 -0
  247. package/dist/rewindEngineAction.js +23 -1
  248. package/dist/rowKind.d.ts +36 -0
  249. package/dist/rowKind.js +97 -0
  250. package/dist/ruleCompileVerdict.d.ts +18 -0
  251. package/dist/ruleCompileVerdict.js +67 -2
  252. package/dist/ruleReadings.d.ts +58 -0
  253. package/dist/ruleReadings.js +132 -0
  254. package/dist/ruleRefusalSentence.d.ts +4 -0
  255. package/dist/ruleRefusalSentence.js +9 -3
  256. package/dist/runCancelContext.d.ts +0 -1
  257. package/dist/runCancelContext.js +1 -2
  258. package/dist/runTerminal.d.ts +5 -0
  259. package/dist/runTerminal.js +52 -17
  260. package/dist/sandboxWire.d.ts +1 -1
  261. package/dist/sandboxWire.js +4 -6
  262. package/dist/scenarioRefusal.js +1 -1
  263. package/dist/scenarioSkills.d.ts +20 -0
  264. package/dist/scenarioSkills.js +72 -0
  265. package/dist/scenarioWire.d.ts +5 -2
  266. package/dist/scenarioWire.js +9 -9
  267. package/dist/sealedKeyCapability.js +2 -2
  268. package/dist/seam.d.ts +2 -0
  269. package/dist/seam.js +2 -2
  270. package/dist/seatContract.d.ts +46 -1
  271. package/dist/seatContract.js +49 -19
  272. package/dist/selfOrchestrationDenial.js +1 -1
  273. package/dist/sessionPolicyCapability.js +2 -2
  274. package/dist/sessionRulesChildrenReadLive.d.ts +6 -0
  275. package/dist/sessionRulesChildrenReadLive.js +5 -0
  276. package/dist/sessionRulesNamespaceFormsCapability.d.ts +12 -0
  277. package/dist/sessionRulesNamespaceFormsCapability.js +29 -0
  278. package/dist/sessionSyncFileHistoryCapability.js +2 -2
  279. package/dist/settingsCredentialKeyPaths.js +60 -5
  280. package/dist/settingsHooksSalvage.d.ts +1 -0
  281. package/dist/settingsHooksSalvage.js +7 -1
  282. package/dist/settingsLayerAdmission.d.ts +4 -0
  283. package/dist/settingsLayerAdmission.js +16 -0
  284. package/dist/skillToolListsCapability.js +6 -5
  285. package/dist/skillsWireCaps.d.ts +14 -0
  286. package/dist/skillsWireCaps.js +47 -16
  287. package/dist/slashCommandGate.d.ts +24 -0
  288. package/dist/slashCommandGate.js +74 -0
  289. package/dist/slashCommandTable.d.ts +14 -0
  290. package/dist/slashCommandTable.js +99 -0
  291. package/dist/sqlEngineCapability.js +2 -2
  292. package/dist/steerPriorityCapability.js +2 -2
  293. package/dist/storePostureCapability.js +2 -2
  294. package/dist/subagent/agentStateDetail.js +1 -1
  295. package/dist/subagent/engineDelegatedPrompt.d.ts +9 -0
  296. package/dist/subagent/engineDelegatedPrompt.js +38 -7
  297. package/dist/subagent/engineRowStopGate.js +2 -2
  298. package/dist/subagent/engineSubagentResume.js +3 -3
  299. package/dist/subagent/engineTaskHandleWire.d.ts +1 -0
  300. package/dist/subagent/engineTaskHandleWire.js +10 -0
  301. package/dist/submitFailure.d.ts +8 -0
  302. package/dist/submitFailure.js +17 -0
  303. package/dist/supportFloor.d.ts +1 -0
  304. package/dist/supportFloor.js +7 -0
  305. package/dist/terminationIntent.d.ts +55 -0
  306. package/dist/terminationIntent.js +352 -0
  307. package/dist/toolHistoryMismatch.d.ts +8 -0
  308. package/dist/toolHistoryMismatch.js +37 -6
  309. package/dist/toolResult.d.ts +13 -3
  310. package/dist/toolResult.js +158 -9
  311. package/dist/toolResultContent.d.ts +13 -0
  312. package/dist/toolResultContent.js +82 -7
  313. package/dist/toolRoster.d.ts +18 -0
  314. package/dist/toolRoster.js +64 -0
  315. package/dist/turnFailurePresentation.js +27 -90
  316. package/dist/usageLimitAutoResume.d.ts +74 -0
  317. package/dist/usageLimitAutoResume.js +227 -0
  318. package/dist/userAttachmentEnvelope.js +1 -1
  319. package/dist/userAttachmentSeat.js +5 -5
  320. package/dist/userInvokedSkillsCapability.js +2 -2
  321. package/dist/webSearchBackendCapability.js +2 -2
  322. package/dist/wireErrorTriage.js +99 -50
  323. package/dist/wireFailureShape.d.ts +25 -1
  324. package/dist/wireFailureShape.js +92 -5
  325. package/dist/wireRefusalCopy.d.ts +24 -1
  326. package/dist/wireRefusalCopy.js +253 -32
  327. package/dist/wiringFleetDoctor.d.ts +3 -0
  328. package/dist/wiringFleetDoctor.js +21 -0
  329. package/dist/workflow.d.ts +2 -1
  330. package/dist/workflow.js +38 -1
  331. package/dist/workflowClient.d.ts +2 -7
  332. package/dist/workflowsJournalCapability.js +2 -2
  333. package/dist/writeProtectionCapability.js +2 -2
  334. package/docs/INTEGRATION-CLIENTS.md +607 -181
  335. package/package.json +14 -3
@@ -1,25 +1,32 @@
1
- import { ASK_GONE, ASK_GONE_PARKED, RESUME_PREFLIGHT_REJECTED, isDecideAlreadyResolvedCode, isDecideParkMovedCode, refusalRetriableReading, refusalSaysStillPending } from '../engineErrorCodes.js';
1
+ import { ASK_GONE, ASK_GONE_PARKED, RESUME_PREFLIGHT_REJECTED, isDecideAlreadyResolvedCode, isDecideParkMovedCode, isDecideRowUnrevivableCode, refusalRetriableReading, refusalSaysStillPending } from '../engineErrorCodes.js';
2
+ import { isUiLanguage } from '../env/uiLanguage.js';
3
+ import { msg, renderMessage } from '../i18n/translate.js';
2
4
  import { notPendingCauseReading, refusalCauseWordOf } from './approvalEndingCause.js';
3
- import { GATE_FAILURE_CODES, readDecideCurrentPending, readWireCodes } from './hitlBridge.js';
5
+ import { GATE_FAILURE_CODES, readDecideCurrentPending, readWireCodes, refusalCarrierOf } from './hitlBridge.js';
4
6
  import { isAlreadyResolvedGateReason, isCodeClassifiedGateFailure } from './parkResolver.js';
5
7
  import { decisionConflictOf } from './decisionConflict.js';
6
8
  import { readLivePendingRows } from './livePendingAsk.js';
7
9
  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';
10
+ import { PROTOCOL_ERROR_NAME, THROWN_SLOT_UNREADABLE, isDisplayableWireCode, isSlotCarrier, ownFoldedCodeBitsOf, protocolErrorNameReading, readErrorRecord, readRefusalField, readThrownSlot } from '../wireFailureShape.js';
11
+ import { attributionRefusalOf, carrierReadOf } from './attributionLadder.js';
12
+ import { CODE_UNREADABLE, ownReadingSlot } from '../engineWireFor.js';
10
13
  export const ASK_DECIDED_CODE = 'conflict.ask_decided';
11
14
  const TRANSIENT_STATUSES = new Set([408, 425, 429, 502, 503, 504]);
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 };
15
+ export { refusalCarrierOf } from './hitlBridge.js';
16
+ const DELIVERED_UNREADABLE = Symbol('delivered-answer-unreadable');
17
+ function deliveredAnswerOf(delivered, carrier) {
18
+ if (delivered === undefined)
19
+ return undefined;
20
+ const a = ownReadingSlot(delivered, 'answered') ?? ownReadingSlot(delivered, 'unanswered');
21
+ return a !== undefined && a.layer === carrier ? a : DELIVERED_UNREADABLE;
22
+ }
23
+ const PROTOCOL_NAME_ABSENT = Object.freeze({ state: 'absent' });
24
+ const PROTOCOL_NAME_UNREADABLE = Object.freeze({ state: 'unreadable' });
25
+ function capturedCodeOf(answer) {
26
+ return answer === undefined ? undefined : answer === DELIVERED_UNREADABLE ? CODE_UNREADABLE : answer.code;
27
+ }
28
+ export function notPendingAfterRetry(status, retried) {
29
+ return retried && (status === 404 || status === 410);
23
30
  }
24
31
  const ROUTE_WORDS = { approval_decide: true, live_respond: true, ask_decide: true, plan_review: true, compact: true };
25
32
  const REFUSAL_ROUTES = Object.freeze(Object.keys(ROUTE_WORDS));
@@ -35,17 +42,19 @@ function routeOf(context) {
35
42
  return typeof r === 'string' && REFUSAL_ROUTES.includes(r) ? r : undefined;
36
43
  }
37
44
  function carrierStatus(carrier) {
38
- const raw = typeof carrier === 'object' && carrier !== null ? guardedRead(() => readOwnDataValue(carrier, 'status')) : undefined;
45
+ const raw = isSlotCarrier(carrier) ? readThrownSlot(carrier, 'status', 'data') : undefined;
39
46
  return typeof raw === 'number' && Number.isFinite(raw) ? raw : undefined;
40
47
  }
41
- function carrierCode(carrier) {
42
- const raw = typeof carrier === 'object' && carrier !== null ? guardedRead(() => readOwnDataValue(carrier, 'errorCode')) : undefined;
48
+ function carrierCode(carrier, captured) {
49
+ if (captured !== undefined)
50
+ return captured.state === 'read' ? captured.wire : undefined;
51
+ const raw = isSlotCarrier(carrier) ? readThrownSlot(carrier, 'errorCode', 'data') : undefined;
43
52
  return typeof raw === 'string' && raw.length > 0 ? raw : undefined;
44
53
  }
45
- export function refusalDeliveryOf(err, context) {
46
- const { carrier } = refusalCarrierOf(err);
47
- const status = carrierStatus(carrier);
48
- const errorCode = carrierCode(carrier);
54
+ export function refusalDeliveryOf(err, context, answer, read) {
55
+ const { carrier } = read ?? refusalCarrierOf(err);
56
+ const status = answer === undefined ? carrierStatus(carrier) : answer === DELIVERED_UNREADABLE ? undefined : answer.status;
57
+ const errorCode = carrierCode(carrier, capturedCodeOf(answer));
49
58
  const facts = { ...(status !== undefined ? { status } : {}), ...(errorCode !== undefined ? { errorCode } : {}) };
50
59
  if (status === undefined || !Number.isInteger(status) || status < 400 || status > 599)
51
60
  return { delivery: 'no_answer', ...facts };
@@ -61,6 +70,9 @@ export function decisionRefusalSaysAskGone(err) {
61
70
  return readDecisionRefusalAsk(err).reading === 'settled';
62
71
  }
63
72
  const facts = (reading, gateMoved = false, wordingHint = false) => ({ reading, gateMoved, wordingHint });
73
+ const codeUnreadable = () => {
74
+ throw new TypeError('status or errorCode was unreadable when this failure was first read');
75
+ };
64
76
  function preflightSettledBitsPresent(carrier) {
65
77
  const detail = guardedRead(() => readErrorRecord(carrier, 'detail'));
66
78
  if (detail === undefined)
@@ -96,28 +108,31 @@ function askFactsOfResolution(r) {
96
108
  return facts('unreadable');
97
109
  }
98
110
  }
99
- export function readDecisionRefusalAsk(failure) {
100
- if (typeof failure !== 'object' || failure === null)
111
+ export function readDecisionRefusalAsk(failure, answer, read) {
112
+ if (!isSlotCarrier(failure))
101
113
  return facts('not_settled');
102
- if (isResolutionShaped(failure))
114
+ if (answer === undefined && isResolutionShaped(failure))
103
115
  return askFactsOfResolution(failure);
104
- const { local, carrier } = refusalCarrierOf(failure);
116
+ const r = read ?? refusalCarrierOf(failure);
117
+ const local = ownReadingSlot(r, 'local');
118
+ const carrier = r.carrier;
105
119
  if (local !== undefined)
106
120
  return facts(local === 'no_pending' ? 'settled' : 'not_settled');
107
- if (typeof carrier !== 'object' || carrier === null)
121
+ if (!isSlotCarrier(carrier))
108
122
  return facts('not_settled');
109
123
  let localCode, name, protocolName, errorCode, status, retriable, text;
110
124
  try {
111
125
  const slot = (key) => ownDataField(carrier, key);
112
126
  const closed = (v) => (typeof v === 'string' && GATE_FAILURE_CODES.includes(v) ? v : undefined);
113
- localCode = closed(slot('code'));
127
+ localCode = closed(answer === undefined ? slot('code') : answer === DELIVERED_UNREADABLE || answer.localCode === THROWN_SLOT_UNREADABLE ? codeUnreadable() : answer.localCode);
114
128
  name = slot('name');
115
- const pn = protocolErrorNameReading(carrier);
129
+ const pn = read !== undefined ? read.protocolName : protocolErrorNameReading(carrier);
116
130
  if (pn.state === 'unreadable')
117
131
  throw new TypeError('protocol name unreadable');
118
132
  protocolName = pn.state === 'named' ? pn.name : undefined;
119
- errorCode = slot('errorCode');
120
- status = slot('status');
133
+ const captured = capturedCodeOf(answer);
134
+ errorCode = captured === undefined ? slot('errorCode') : captured.state === 'read' ? captured.wire : codeUnreadable();
135
+ status = answer === undefined ? slot('status') : answer === DELIVERED_UNREADABLE ? codeUnreadable() : answer.status;
121
136
  retriable = refusalRetriableReading(carrier);
122
137
  text = String(carrier);
123
138
  }
@@ -152,7 +167,7 @@ export function decisionRefusalAskReading(failure) {
152
167
  }
153
168
  const USELESS_REFUSAL_TEXTS = new Set(['[object Object]', 'null', 'undefined', '']);
154
169
  function refusalTextOf(err) {
155
- const message = typeof err === 'object' && err !== null ? guardedRead(() => err.message) : undefined;
170
+ const message = isSlotCarrier(err) ? guardedRead(() => err.message) : undefined;
156
171
  if (typeof message === 'string' && message.length > 0)
157
172
  return message;
158
173
  if (typeof err === 'string' && err.length > 0)
@@ -169,27 +184,49 @@ function refusalTextOf(err) {
169
184
  function isolated(read) {
170
185
  return guardedRead(read);
171
186
  }
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);
187
+ function wireCodesOfPinned(captured) {
188
+ if (captured.state !== 'read' || captured.wire === undefined)
189
+ return {};
190
+ return { errorCode: captured.wire, ...(captured.blockedBy !== undefined ? { blockedBy: captured.blockedBy } : {}) };
191
+ }
192
+ export function mintDecisionRefusalReading(err, context, attributionCarried, delivered, carried) {
193
+ const carrierRead = carried ?? carrierReadOf(err, delivered);
194
+ const { carrier } = carrierRead;
195
+ const obj = isSlotCarrier(carrier) ? carrier : undefined;
196
+ const answer = deliveredAnswerOf(delivered, carrier);
197
+ const captured = capturedCodeOf(answer);
198
+ const status = answer === undefined ? carrierStatus(carrier) : answer === DELIVERED_UNREADABLE ? undefined : answer.status;
199
+ const wire = captured !== undefined ? wireCodesOfPinned(captured) : obj !== undefined ? isolated(() => readWireCodes(obj)) : undefined;
200
+ const wireBits = ownFoldedCodeBitsOf(wire);
201
+ const errorCode = wireBits.errorCode ?? carrierCode(carrier, captured);
202
+ const blockedBy = wireBits.blockedBy;
178
203
  const message = isolated(() => refusalTextOf(carrier));
179
204
  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;
205
+ const pn = obj !== undefined ? (isolated(() => protocolErrorNameReading(obj)) ?? PROTOCOL_NAME_UNREADABLE) : PROTOCOL_NAME_ABSENT;
206
+ const protocolName = pn.state === 'named' ? pn.name : undefined;
182
207
  const cause = obj !== undefined ? isolated(() => refusalCauseWordOf(obj)) : undefined;
183
208
  const field = obj !== undefined ? isolated(() => readRefusalField(obj)) : undefined;
184
209
  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';
210
+ const attribution = attributionCarried === undefined ? undefined : isolated(() => attributionRefusalOf(carrierRead, delivered ?? 'carrier', attributionCarried));
211
+ const ask = readDecisionRefusalAsk(err, answer, { ...carrierRead, protocolName: pn });
212
+ const delivery = refusalDeliveryOf(err, context, answer, carrierRead);
213
+ const unknownAfterRetry = guardedRead(() => (typeof context === 'object' && context !== null ? readOwnDataValue(context, 'afterRetry') : undefined)) === true && notPendingAfterRetry(status, true);
214
+ const standing = delivery.delivery === 'no_answer'
215
+ ? undefined
216
+ : unknownAfterRetry
217
+ ? 'ambiguous'
218
+ : ask.reading === 'settled'
219
+ ? 'settled-elsewhere'
220
+ : delivery.delivery === 'refused'
221
+ ? 'refused-pending'
222
+ : 'ambiguous';
189
223
  const inRange = standing !== undefined && status !== undefined;
224
+ const conflict = inRange && status === 409 && obj !== undefined ? isolated(() => decisionConflictOf(obj, captured, pn)) : undefined;
225
+ const unrecoverable = inRange && status !== undefined && Number.isInteger(status) && status >= 400 && status <= 599 && isDecideRowUnrevivableCode(errorCode);
190
226
  const transient = inRange &&
227
+ conflict !== 'grant_changed' &&
228
+ !unrecoverable &&
191
229
  (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;
193
230
  return Object.freeze({
194
231
  ...(status !== undefined ? { status } : {}),
195
232
  ...(errorCode !== undefined ? { errorCode } : {}),
@@ -197,7 +234,7 @@ export function mintDecisionRefusalReading(err, context, attributionCarried) {
197
234
  ...(retriable ? { retriable: true } : {}),
198
235
  ...(protocolName !== undefined ? { protocolName } : {}),
199
236
  ...(cause !== undefined || field !== undefined ? { extra: Object.freeze({ ...(cause !== undefined ? { cause } : {}), ...(field !== undefined ? { field } : {}) }) } : {}),
200
- ...(wire?.blockedBy !== undefined ? { blockedBy: wire.blockedBy } : {}),
237
+ ...(blockedBy !== undefined ? { blockedBy } : {}),
201
238
  ...(currentPending !== undefined ? { currentPending } : {}),
202
239
  ...(attribution !== undefined && attribution !== null ? { denyAttributionRefusal: attribution } : {}),
203
240
  ask: ask.reading,
@@ -206,6 +243,7 @@ export function mintDecisionRefusalReading(err, context, attributionCarried) {
206
243
  ...(standing !== undefined ? { standing } : {}),
207
244
  ...(transient ? { transient: true } : {}),
208
245
  ...(conflict !== undefined ? { conflict } : {}),
246
+ ...(unrecoverable ? { unrecoverable: true } : {}),
209
247
  });
210
248
  }
211
249
  export function readDecisionRefusalReading(err, context) {
@@ -223,12 +261,14 @@ function classifiedOf(reading) {
223
261
  const errorCode = typeof code === 'string' && isDisplayableWireCode(code) ? code : undefined;
224
262
  const transient = ownDataField(reading, 'transient') === true;
225
263
  const conflict = ownDataField(reading, 'conflict');
264
+ const unrecoverable = ownDataField(reading, 'unrecoverable') === true;
226
265
  return Object.freeze({
227
266
  standing,
228
267
  status,
229
268
  ...(errorCode !== undefined ? { errorCode } : {}),
230
269
  ...(transient ? { transient: true } : {}),
231
270
  ...(typeof conflict === 'string' ? { conflict: conflict } : {}),
271
+ ...(unrecoverable ? { unrecoverable: true } : {}),
232
272
  });
233
273
  }
234
274
  catch {
@@ -242,6 +282,9 @@ export function classifyDecisionRefusal(err, context) {
242
282
  }
243
283
  return classifiedOf(mintDecisionRefusalReading(err, context));
244
284
  }
285
+ export function classifyDeliveredDecisionRefusal(err, delivered) {
286
+ return classifiedOf(mintDecisionRefusalReading(err, undefined, undefined, delivered));
287
+ }
245
288
  export function liveAskPendingReading(envelope, approvalId) {
246
289
  if (typeof approvalId !== 'string' || approvalId === '')
247
290
  return 'unknown';
@@ -260,15 +303,14 @@ export function liveAskPendingReading(envelope, approvalId) {
260
303
  export function decisionRefusalClosesOut(refusal, pending) {
261
304
  if (pending !== 'pending' || typeof refusal !== 'object' || refusal === null)
262
305
  return false;
263
- try {
264
- const standing = refusal.standing;
265
- if (refusal.transient === true)
266
- return false;
267
- return standing === 'ambiguous' || standing === 'refused-pending';
268
- }
269
- catch {
306
+ const standing = readThrownSlot(refusal, 'standing', 'data');
307
+ const transient = readThrownSlot(refusal, 'transient', 'data');
308
+ if (transient === true || transient === THROWN_SLOT_UNREADABLE)
270
309
  return false;
271
- }
310
+ const conflict = readThrownSlot(refusal, 'conflict', 'data');
311
+ if (conflict === 'grant_changed' || conflict === THROWN_SLOT_UNREADABLE)
312
+ return false;
313
+ return standing === 'ambiguous' || standing === 'refused-pending';
272
314
  }
273
315
  export function undeliverableDecisionContent(facts) {
274
316
  const code = typeof facts.errorCode === 'string' && isDisplayableWireCode(facts.errorCode) ? ` ${facts.errorCode}` : '';
@@ -284,3 +326,6 @@ export function undeliverableDecisionContent(facts) {
284
326
  return `${head}; this turn was stopped instead of being left waiting. Update the client, or switch to a permission mode that shows you the approval and try again.`;
285
327
  }
286
328
  }
329
+ export function decideRowUnrevivableNotice(lang) {
330
+ return renderMessage(msg('notice.decide.rowUnrevivable'), isUiLanguage(lang) ? lang : undefined);
331
+ }
@@ -1,4 +1,5 @@
1
1
  import type { AgentClient, ElicitResponse } from '@sema-agent/sdk';
2
+ import type { UiLanguage } from '../env/uiLanguage.js';
2
3
  import { type AskGoneDetail } from '../decideReceipt.js';
3
4
  import type { ApprovalDecidedByReading } from '../approvalDecidedByCapability.js';
4
5
  import { type DecisionNoteAudit } from './approvalDecisionNoteAudit.js';
@@ -65,6 +66,7 @@ interface HitlDecisionOutcomeBase {
65
66
  readonly attributionDropped?: true;
66
67
  readonly attributionRenamed?: true;
67
68
  readonly pending?: LiveAskPendingReading;
69
+ readonly parkingRetried?: true;
68
70
  }
69
71
  export interface HitlDecisionApplied extends HitlDecisionOutcomeBase {
70
72
  readonly kind: 'applied';
@@ -110,4 +112,5 @@ export interface HitlDecisionSendTiming {
110
112
  export declare function __setHitlDecisionSendTimingForTests(t?: HitlDecisionSendTiming): void;
111
113
  export declare function hitlAskIdempotencyKey(askId: string, verdict: 'approve' | 'deny'): string;
112
114
  export declare function sendHitlDecision(request: HitlDecisionSendRequest, deps: HitlDecisionSendDeps): Promise<HitlDecisionSendOutcome>;
115
+ export declare function hitlDecisionOutcomeContent(outcome: HitlDecisionSendOutcome, lang?: UiLanguage): string | undefined;
113
116
  export {};
@@ -1,13 +1,15 @@
1
- import { abortableSleep, settleWithinDeadline } from '../abortableSleep.js';
1
+ import { settleWithinDeadline } from '../abortableSleep.js';
2
2
  import { hostLog } from '../host.js';
3
+ import { msg, renderMessage } from '../i18n/translate.js';
3
4
  import { askGoneFromError } from '../decideReceipt.js';
4
- import { guardedRead, readOwnDataNonEmptyString, readOwnDataValue } from '../ownKey.js';
5
- import { effectiveWireErrorCode, isWireTransportError } from '../wireErrorTriage.js';
5
+ import { appendOwnElement, guardedRead, readOwnDataNonEmptyString, readOwnDataValue } from '../ownKey.js';
6
+ import { effectiveCodeOf, ownReadingSlot } from '../engineWireFor.js';
6
7
  import { ASK_DECISION_LANE_DISABLED, ASK_GONE, ASK_GONE_PARKED, ASK_IDEMPOTENCY_CONFLICT, ASK_NOT_FOUND, ASK_PARKING_RETRY } from '../engineErrorCodes.js';
7
- import { readErrorNumber, readErrorString, readThrownSlot, readThrownStatusSlot, THROWN_SLOT_UNREADABLE } from '../wireFailureShape.js';
8
+ import { isSlotCarrier, readErrorNumber, readErrorString, readThrownSlot } from '../wireFailureShape.js';
8
9
  import { readDecisionNoteAudit } from './approvalDecisionNoteAudit.js';
9
- import { deliverWithAttributionLadder } from './attributionLadder.js';
10
- import { ASK_DECIDED_CODE, classifyDecisionRefusal, decisionRefusalClosesOut } from './decisionRefusal.js';
10
+ import { carrierReadOf, deliverWithAttributionLadder, isLocalSafetyStop } from './attributionLadder.js';
11
+ import { budgetSpent, deliverApprovalDecision, deliveryTiming, isAborted, newSendTally, PARKING_WAIT_CAP_MS, setDeliveryTimingForTests, sleepFor, settledTransportReadingOf, withTransportRetry, deliveryReadingOf, } from './approvalDelivery.js';
12
+ import { ASK_DECIDED_CODE, classifyDeliveredDecisionRefusal, decisionRefusalClosesOut, notPendingAfterRetry } from './decisionRefusal.js';
11
13
  import { addDecisionOpKeys, closeDecisionOp, decisionLedgerKeysOf, decisionOpsWithKey, openDecisionOp } from './decisionLedger.js';
12
14
  import { hostHoldIsActive, takeHostHoldLedgerOp, tryHoldApprovalNow } from './approvalHolds.js';
13
15
  import { answerPayloadFor, decisionAttributionKeyOf, isToolApprovalRespondReplayed, readApprovalDenySettledBy, readToolApprovalRespondAck, readToolApprovalRespondParking, } from './toolApprovalWire.js';
@@ -15,86 +17,19 @@ export const HITL_DECISION_FAMILIES = Object.freeze(['approval', 'ask', 'elicita
15
17
  export const HITL_DECISION_NOT_APPLIED_CAUSES = Object.freeze(['gone', 'parked', 'parking', 'lane_disabled', 'refused', 'idempotency_crossed']);
16
18
  export const HITL_DECISION_UNCONFIRMED_CAUSES = Object.freeze(['transport', 'server_error', 'local_error', 'aborted', 'gone_after_retry']);
17
19
  export const HITL_DECISION_NOT_SENT_CAUSES = Object.freeze(['aborted', 'duplicate_in_flight', 'invalid_request', 'no_verb', 'not_an_answer']);
18
- const RETRY_DELAYS_MS = Object.freeze([500, 1_000, 2_000]);
19
- const RETRY_BUDGET_MS = 8_000;
20
20
  const PARKING_POLL_MAX = 2;
21
21
  const PARKING_POLL_DELAY_MS = 400;
22
- const PARKING_POLL_WAIT_CAP_MS = 5_000;
23
22
  export const HITL_DECISION_READBACK_BUDGET_MS = 4_000;
24
23
  const IDEMPOTENCY_KEY_MAX = 255;
25
- let timingOverride;
26
24
  export function __setHitlDecisionSendTimingForTests(t) {
27
- timingOverride = t;
25
+ setDeliveryTimingForTests(t);
28
26
  }
29
27
  export function hitlAskIdempotencyKey(askId, verdict) {
30
28
  const key = `sema-ask:${askId}:${verdict}`;
31
29
  return key.length <= IDEMPOTENCY_KEY_MAX ? key : key.slice(0, IDEMPOTENCY_KEY_MAX);
32
30
  }
33
- function isAbortShaped(e) {
34
- const name = readThrownSlot(e, 'name');
35
- return name === 'TimeoutError' || name === 'AbortError';
36
- }
37
- function transportClassOf(e, signal) {
38
- if (signal?.aborted === true)
39
- return 'aborted';
40
- const status = typeof e === 'object' && e !== null ? readThrownStatusSlot(e) : undefined;
41
- if (status === THROWN_SLOT_UNREADABLE)
42
- return 'local_error';
43
- if (typeof status === 'number')
44
- return status === 501 ? 'verdict' : status >= 500 ? 'server_5xx' : 'verdict';
45
- return isWireTransportError(e) || isAbortShaped(e) ? 'transport' : 'local_error';
46
- }
47
- function attemptSignal(attempt, caller, startedAt, budgetMs) {
48
- if (attempt === 1)
49
- return caller;
50
- const deadline = AbortSignal.timeout(Math.max(1, budgetMs - (Date.now() - startedAt)));
51
- if (caller === undefined)
52
- return deadline;
53
- if (typeof AbortSignal.any === 'function')
54
- return AbortSignal.any([caller, deadline]);
55
- const ac = new AbortController();
56
- const abort = (s) => ac.abort(s.reason);
57
- if (caller.aborted)
58
- abort(caller);
59
- else
60
- caller.addEventListener('abort', () => abort(caller), { once: true });
61
- deadline.addEventListener('abort', () => abort(deadline), { once: true });
62
- return ac.signal;
63
- }
64
- function budgetSpent(tally, extraMs) {
65
- return Date.now() - tally.startedAt + extraMs >= (timingOverride?.budgetMs ?? RETRY_BUDGET_MS);
66
- }
67
- function isAborted(signal) {
68
- return signal?.aborted === true;
69
- }
70
- function sleepFor(ms, signal) {
71
- return abortableSleep(ms, signal ?? new AbortController().signal);
72
- }
73
- async function withTransportRetry(send, signal, tally) {
74
- const delays = timingOverride?.delays ?? RETRY_DELAYS_MS;
75
- const budgetMs = timingOverride?.budgetMs ?? RETRY_BUDGET_MS;
76
- const startedAt = tally.startedAt;
77
- for (let attempt = 1;; attempt++) {
78
- tally.attempts++;
79
- try {
80
- return await send(attemptSignal(attempt, signal, startedAt, budgetMs));
81
- }
82
- catch (e) {
83
- const cls = transportClassOf(e, signal);
84
- const delay = delays[attempt - 1] ?? 0;
85
- const retriable = cls === 'transport' || cls === 'server_5xx';
86
- const overBudget = Date.now() - startedAt + delay >= budgetMs;
87
- if (!retriable || attempt > delays.length || overBudget)
88
- throw e;
89
- tally.retried = true;
90
- await sleepFor(delay, signal);
91
- if (signal?.aborted === true)
92
- throw e;
93
- }
94
- }
95
- }
96
31
  function retryAfterMsOf(e) {
97
- if (typeof e !== 'object' || e === null)
32
+ if (!isSlotCarrier(e))
98
33
  return undefined;
99
34
  const ms = readErrorNumber(e, 'retryAfterMs');
100
35
  if (ms !== undefined && Number.isFinite(ms) && ms >= 0)
@@ -115,21 +50,32 @@ function actorLabelOf(e) {
115
50
  function verdictOf(word) {
116
51
  return word === 'approve' || word === 'allow' || word === 'allow_session' ? 'approve' : word === 'deny' ? 'deny' : undefined;
117
52
  }
118
- function outcomeOfThrown(e, family, ours, signal, tally, noteCapable) {
53
+ function outcomeOfThrown(e, family, ours, signal, tally, noteCapable, reading = settledTransportReadingOf(e, signal, tally)) {
119
54
  const base = { family, attempts: tally.attempts };
120
- const cls = transportClassOf(e, signal);
55
+ const cls = reading.cls;
121
56
  if (cls === 'aborted')
122
57
  return { ...base, kind: 'unconfirmed', cause: 'aborted' };
123
58
  if (cls === 'transport')
124
59
  return { ...base, kind: 'unconfirmed', cause: 'transport' };
125
60
  if (cls === 'local_error')
126
61
  return { ...base, kind: 'unconfirmed', cause: 'local_error' };
62
+ const answered = ownReadingSlot(reading, 'answered');
63
+ if (answered === undefined)
64
+ return { ...base, kind: 'unconfirmed', cause: 'local_error' };
65
+ return answeredOutcome(answered.layer, answered.status, reading, cls, family, ours, tally, noteCapable, base);
66
+ }
67
+ function answeredOutcome(e, status, reading, cls, family, ours, tally, noteCapable, base) {
127
68
  const obj = e;
128
- const status = readThrownStatusSlot(obj);
129
69
  if (cls === 'server_5xx')
130
70
  return { ...base, kind: 'unconfirmed', cause: 'server_error', status };
131
- const code = effectiveWireErrorCode(e);
71
+ const answeredCapture = ownReadingSlot(reading, 'answered');
72
+ const code = answeredCapture !== undefined ? effectiveCodeOf(answeredCapture.code) : undefined;
132
73
  const at = { ...base, status, ...(code !== undefined ? { errorCode: code } : {}) };
74
+ const retried = family !== 'ask' && tally.retried;
75
+ if (retried && notPendingAfterRetry(status, true))
76
+ return { ...base, kind: 'unconfirmed', cause: 'gone_after_retry', status };
77
+ if (isSafetyStopLayer(e, reading))
78
+ return { ...at, kind: 'not_applied', cause: 'refused', ...refusalOf(e, reading) };
133
79
  if (family === 'ask') {
134
80
  switch (code) {
135
81
  case ASK_DECIDED_CODE: {
@@ -148,7 +94,7 @@ function outcomeOfThrown(e, family, ours, signal, tally, noteCapable) {
148
94
  };
149
95
  }
150
96
  case ASK_IDEMPOTENCY_CONFLICT:
151
- return { ...at, kind: 'not_applied', cause: 'idempotency_crossed', ...refusalOf(e) };
97
+ return { ...at, kind: 'not_applied', cause: 'idempotency_crossed', ...refusalOf(e, reading) };
152
98
  case ASK_GONE_PARKED: {
153
99
  const sessionId = readErrorString(obj, 'sessionId');
154
100
  return { ...at, kind: 'not_applied', cause: 'parked', ...(sessionId !== undefined ? { sessionId } : {}) };
@@ -169,15 +115,17 @@ function outcomeOfThrown(e, family, ours, signal, tally, noteCapable) {
169
115
  break;
170
116
  }
171
117
  }
172
- if (status === 404 || status === 410) {
173
- return family !== 'ask' && tally.retried ? { ...base, kind: 'unconfirmed', cause: 'gone_after_retry', status } : { ...at, kind: 'not_applied', cause: 'gone' };
174
- }
118
+ if (status === 404 || status === 410)
119
+ return { ...at, kind: 'not_applied', cause: 'gone' };
175
120
  if (status === 501)
176
121
  return { ...at, kind: 'not_applied', cause: 'lane_disabled' };
177
- return { ...at, kind: 'not_applied', cause: 'refused', ...refusalOf(e) };
122
+ return { ...at, kind: 'not_applied', cause: 'refused', ...refusalOf(e, reading) };
123
+ }
124
+ function isSafetyStopLayer(layer, reading) {
125
+ return isLocalSafetyStop(carrierReadOf(layer, reading), reading);
178
126
  }
179
- function refusalOf(e) {
180
- const r = classifyDecisionRefusal(e);
127
+ function refusalOf(e, reading) {
128
+ const r = classifyDeliveredDecisionRefusal(e, reading);
181
129
  return r !== undefined ? { refusal: r } : {};
182
130
  }
183
131
  async function sendApprovalFamily(respond, approvalId, answer, ctx) {
@@ -189,19 +137,29 @@ async function sendApprovalFamily(respond, approvalId, answer, ctx) {
189
137
  const ladder = { lastCarried: false, dropped: false, renamed: false };
190
138
  const ours = verdictOf(payload.decision);
191
139
  const extras = bodyFacts(answer, payload, false);
192
- let raw;
193
- try {
194
- raw = await deliverWithAttributionLadder(body, (b) => withTransportRetry((signal) => respond(approvalId, b, signal !== undefined ? { signal } : undefined), ctx.signal, ctx.tally), ctx.signal, ladder);
195
- }
196
- catch (e) {
197
- return { ...outcomeOfThrown(e, 'approval', ours, ctx.signal, ctx.tally, ctx.noteCapable), ...extras };
198
- }
199
- const facts = { ...extras, ...(ladder.dropped ? { attributionDropped: true } : {}), ...(ladder.renamed ? { attributionRenamed: true } : {}) };
140
+ const delivery = await deliverApprovalDecision({
141
+ approvalId,
142
+ body,
143
+ send: (b, signal) => respond(approvalId, b, signal !== undefined ? { signal } : undefined),
144
+ signal: ctx.signal,
145
+ tally: ctx.tally,
146
+ ladder,
147
+ parkingOf: (raw) => {
148
+ const p = readToolApprovalRespondParking(raw);
149
+ return p?.kind === 'parking' ? p.view : undefined;
150
+ },
151
+ });
152
+ const retriedFact = ownReadingSlot(delivery, 'parkingRetried') === true ? { parkingRetried: true } : {};
153
+ if (delivery.kind === 'thrown')
154
+ return { ...outcomeOfThrown(delivery.error, 'approval', ours, ctx.signal, ctx.tally, ctx.noteCapable), ...extras, ...retriedFact };
155
+ const raw = delivery.raw;
156
+ const facts = { ...extras, ...retriedFact, ...(ladder.dropped ? { attributionDropped: true } : {}), ...(ladder.renamed ? { attributionRenamed: true } : {}) };
200
157
  const base = { family: 'approval', attempts: ctx.tally.attempts, ...facts };
201
158
  const parking = readToolApprovalRespondParking(raw);
202
159
  if (parking !== undefined) {
203
160
  const view = parking.kind === 'parking' && parking.view.approvalId === approvalId ? parking.view : undefined;
204
- return { ...base, kind: 'not_applied', cause: 'parking', ...(view !== undefined ? { parking: view, ...(view.retryAfterMs !== undefined ? { retryAfterMs: view.retryAfterMs } : {}) } : {}) };
161
+ const hint = view !== undefined ? ownReadingSlot(view, 'retryAfterMs') : undefined;
162
+ return { ...base, kind: 'not_applied', cause: 'parking', ...(view !== undefined ? { parking: view, ...(hint !== undefined ? { retryAfterMs: hint } : {}) } : {}) };
205
163
  }
206
164
  const parsed = readToolApprovalRespondAck(raw);
207
165
  if (parsed !== undefined && isToolApprovalRespondReplayed(parsed)) {
@@ -244,13 +202,13 @@ async function sendAskFamily(respondForFallback, decideAsk, req, ctx) {
244
202
  const extras = bodyFacts(req.answer, payload, true);
245
203
  const ladder = { lastCarried: false, dropped: false, renamed: false };
246
204
  let current = body;
247
- const parkingDelay = timingOverride?.parkingDelayMs ?? PARKING_POLL_DELAY_MS;
205
+ const parkingDelay = deliveryTiming().parkingDelayMs ?? PARKING_POLL_DELAY_MS;
248
206
  for (let poll = 0;; poll++) {
249
207
  try {
250
208
  const raw = await deliverWithAttributionLadder(current, (b) => {
251
209
  current = b;
252
210
  return withTransportRetry((signal) => decideAsk(req.taskId, req.askId, b, signal !== undefined ? { signal } : undefined), ctx.signal, ctx.tally);
253
- }, ctx.signal, ladder);
211
+ }, ctx.signal, ladder, undefined, { kind: 'delivered', readingOf: (thrown) => deliveryReadingOf(thrown, ctx.tally) });
254
212
  return {
255
213
  family: 'ask',
256
214
  attempts: ctx.tally.attempts,
@@ -262,14 +220,17 @@ async function sendAskFamily(respondForFallback, decideAsk, req, ctx) {
262
220
  };
263
221
  }
264
222
  catch (e) {
265
- const code = effectiveWireErrorCode(e);
266
- const wait = Math.max(parkingDelay * (poll + 1), retryAfterMsOf(e) ?? 0);
267
- if (code === ASK_PARKING_RETRY && poll < PARKING_POLL_MAX && !isAborted(ctx.signal) && wait <= PARKING_POLL_WAIT_CAP_MS && !budgetSpent(ctx.tally, wait)) {
223
+ const settled = settledTransportReadingOf(e, ctx.signal, ctx.tally);
224
+ const settledAnswer = ownReadingSlot(settled, 'answered');
225
+ const code = settledAnswer !== undefined ? effectiveCodeOf(settledAnswer.code) : undefined;
226
+ const wait = Math.max(parkingDelay * (poll + 1), retryAfterMsOf(settledAnswer?.layer ?? e) ?? 0);
227
+ const safetyStop = settledAnswer !== undefined && isSafetyStopLayer(settledAnswer.layer, settled);
228
+ if (code === ASK_PARKING_RETRY && !safetyStop && poll < PARKING_POLL_MAX && !isAborted(ctx.signal) && wait <= PARKING_WAIT_CAP_MS && !budgetSpent(ctx.tally, wait)) {
268
229
  await sleepFor(wait, ctx.signal);
269
230
  if (!isAborted(ctx.signal))
270
231
  continue;
271
232
  }
272
- const out = outcomeOfThrown(e, 'ask', verdict, ctx.signal, ctx.tally, ctx.noteCapable);
233
+ const out = outcomeOfThrown(e, 'ask', verdict, ctx.signal, ctx.tally, ctx.noteCapable, settled);
273
234
  if (out.kind === 'not_applied' && out.cause === 'lane_disabled' && code === ASK_DECISION_LANE_DISABLED && req.approvalId !== undefined) {
274
235
  if (respondForFallback !== undefined && ctx.signal?.aborted !== true) {
275
236
  const fb = await sendApprovalFamily(respondForFallback, req.approvalId, req.answer, ctx);
@@ -303,7 +264,7 @@ function validElicitResponse(r) {
303
264
  const x = readOwnDataValue(v, String(i));
304
265
  if (typeof x !== 'string')
305
266
  return undefined;
306
- copy.push(x);
267
+ appendOwnElement(copy, x);
307
268
  }
308
269
  Object.defineProperty(out, k, { value: copy, enumerable: true, writable: true, configurable: true });
309
270
  }
@@ -524,7 +485,7 @@ export async function sendHitlDecision(request, deps) {
524
485
  const decidedBy = hostField(deps, 'approvalDecidedBy');
525
486
  const ctx = {
526
487
  signal,
527
- tally: { attempts: 0, retried: false, startedAt: Date.now() },
488
+ tally: newSendTally(),
528
489
  noteCapable: hostField(deps, 'approvalDecisionNoteCapable') === true,
529
490
  decidedBy: typeof decidedBy === 'object' && decidedBy !== null ? decidedBy : undefined,
530
491
  };
@@ -577,3 +538,26 @@ export async function sendHitlDecision(request, deps) {
577
538
  ownHold.release(out.kind === 'applied' || out.kind === 'settled_elsewhere' ? 'answered' : undefined);
578
539
  return Object.freeze(out);
579
540
  }
541
+ export function hitlDecisionOutcomeContent(outcome, lang) {
542
+ try {
543
+ if (typeof outcome !== 'object' || outcome === null)
544
+ return undefined;
545
+ const kind = readOwnDataValue(outcome, 'kind');
546
+ if (kind === 'settled_elsewhere') {
547
+ if (readOwnDataValue(outcome, 'contrary') !== true)
548
+ return undefined;
549
+ const first = readOwnDataValue(outcome, 'firstDecision');
550
+ if (first === 'deny')
551
+ return renderMessage(msg('approval.decision.settledElsewhereContrary.deniedFirst'), lang);
552
+ if (first === 'approve')
553
+ return renderMessage(msg('approval.decision.settledElsewhereContrary.approvedFirst'), lang);
554
+ return undefined;
555
+ }
556
+ if (kind === 'unconfirmed' && readOwnDataValue(outcome, 'cause') === 'gone_after_retry')
557
+ return renderMessage(msg('approval.decision.unconfirmedAfterRetry'), lang);
558
+ return undefined;
559
+ }
560
+ catch {
561
+ return undefined;
562
+ }
563
+ }
@@ -70,6 +70,7 @@ export interface FrameRouterCtx {
70
70
  signal?: AbortSignal | undefined;
71
71
  }
72
72
  export declare function isAskTool(toolName: string | undefined): boolean;
73
+ export declare function questionCardVerdict(carrier: object | null | undefined): boolean | undefined;
73
74
  export declare function parkGateArmOf(gate: unknown): GateKind | null;
74
75
  export declare function isHostProgressFrame(ev: AgentEvent): boolean;
75
76
  interface HeldFlushInterruptEvidence {
@@ -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 { readApprovalCardWord } from './approvalCardReading.js';
9
+ import { guardedRead, readOwnDataValue } from '../ownKey.js';
8
10
  import { parkHeldCallIdOf } from '../engineRowRef.js';
9
11
  import { inheritFrameBinding } from '../frameBinding.js';
10
12
  import { surfaceForCurrentSession, surfaceReplayedApprovalListUnreadable } from './hitlHostSurface.js';
@@ -102,6 +104,10 @@ function parkFamilyEvidence(led, gateToolName, gatedCallId) {
102
104
  return false;
103
105
  return gatedCallId === undefined || led.isFsOrShellGatedCall(gatedCallId);
104
106
  }
107
+ export function questionCardVerdict(carrier) {
108
+ const word = readApprovalCardWord(carrier);
109
+ return word === undefined ? undefined : word === 'question';
110
+ }
105
111
  export function parkGateArmOf(gate) {
106
112
  if (gate === null || typeof gate !== 'object')
107
113
  return null;
@@ -117,7 +123,7 @@ export function parkGateArmOf(gate) {
117
123
  const leg = durableDecideLegOf(typeof kind === 'string' ? { gateKind: kind } : null);
118
124
  if (leg !== 'approval' && leg !== 'absent')
119
125
  return null;
120
- if (isAskToolLoose(toolName))
126
+ if (questionCardVerdict(gate) ?? isAskToolLoose(toolName))
121
127
  return 'ask';
122
128
  if (leg === 'approval')
123
129
  return 'fs';
@@ -147,7 +153,8 @@ function parkGateOf(result) {
147
153
  if (typeof taskId !== 'string' || taskId.length === 0)
148
154
  return null;
149
155
  const toolName = runTerminalGateToolName(read);
150
- const arm = parkGateArmOf({ kind: runTerminalGateKind(read), toolName });
156
+ const approvalCard = guardedRead(() => readOwnDataValue(read.gate, 'approvalCard'));
157
+ const arm = parkGateArmOf({ kind: runTerminalGateKind(read), toolName, approvalCard });
151
158
  return arm === null ? null : { taskId, gate: arm, toolName };
152
159
  }
153
160
  function parkGatedCallId(src) {