@sema-agent/client-core 0.97.1 → 0.99.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 (353) hide show
  1. package/CHANGELOG.md +607 -0
  2. package/README.md +96 -46
  3. package/dist/adapt/arms.d.ts +1 -0
  4. package/dist/adapt/arms.js +188 -53
  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/panelTasks.d.ts +1 -1
  10. package/dist/adapt/panelTasks.js +2 -2
  11. package/dist/adapt/textStream.d.ts +1 -0
  12. package/dist/adapt/textStream.js +24 -7
  13. package/dist/adapt/toolCards.d.ts +27 -5
  14. package/dist/adapt/toolCards.js +39 -6
  15. package/dist/adapt/wireShapes.js +6 -2
  16. package/dist/adapt.d.ts +2 -0
  17. package/dist/adapt.js +8 -3
  18. package/dist/adapter/activeRunSelfHeal.d.ts +9 -3
  19. package/dist/adapter/activeRunSelfHeal.js +205 -313
  20. package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -5
  21. package/dist/adapter/downstream/eventToSdkMessage.js +77 -36
  22. package/dist/adapter/downstream/terminalToSdkResult.js +11 -4
  23. package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +5 -2
  24. package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -0
  25. package/dist/adapter/runStream.js +79 -48
  26. package/dist/adapter/types.d.ts +4 -4
  27. package/dist/adapter/types.js +2 -1
  28. package/dist/agentSession/backgroundView.js +2 -1
  29. package/dist/agentSession/engineAgentRegistryRead.d.ts +2 -2
  30. package/dist/agentSession/engineAgentRegistryRead.js +12 -13
  31. package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
  32. package/dist/agentsWireCaps.d.ts +8 -11
  33. package/dist/agentsWireCaps.js +196 -194
  34. package/dist/approvalDecidedByCapability.d.ts +0 -4
  35. package/dist/approvalDecidedByCapability.js +0 -6
  36. package/dist/approvalsStreamLiveCapability.d.ts +0 -4
  37. package/dist/approvalsStreamLiveCapability.js +0 -6
  38. package/dist/assistantInbox.d.ts +34 -0
  39. package/dist/assistantInbox.js +118 -0
  40. package/dist/centerWiringCapability.js +9 -1
  41. package/dist/clientSlice.d.ts +0 -9
  42. package/dist/clientSlice.js +0 -3
  43. package/dist/cloudConfigWireCaps.d.ts +5 -3
  44. package/dist/cloudConfigWireCaps.js +106 -64
  45. package/dist/compensations.js +1 -1
  46. package/dist/connectorStatus.d.ts +21 -0
  47. package/dist/connectorStatus.js +112 -0
  48. package/dist/controlRouter.d.ts +18 -3
  49. package/dist/controlRouter.js +106 -67
  50. package/dist/coreValuePorts.d.ts +29 -4
  51. package/dist/coreValuePorts.js +10 -0
  52. package/dist/corruptSessionCopy.d.ts +2 -1
  53. package/dist/corruptSessionCopy.js +3 -3
  54. package/dist/decideReceipt.d.ts +2 -2
  55. package/dist/decideReceipt.js +5 -2
  56. package/dist/declared/supportFloorDeclared.js +3 -3
  57. package/dist/detachWire.js +3 -2
  58. package/dist/deviceExecutorManagementCapability.d.ts +0 -4
  59. package/dist/deviceExecutorManagementCapability.js +0 -6
  60. package/dist/deviceRebind.d.ts +49 -1
  61. package/dist/deviceRebind.js +221 -3
  62. package/dist/devicesFace.d.ts +34 -0
  63. package/dist/devicesFace.js +90 -0
  64. package/dist/displayUntrusted.d.ts +2 -0
  65. package/dist/displayUntrusted.js +253 -76
  66. package/dist/engineAgentAbsence.d.ts +1 -1
  67. package/dist/engineAgentPanelStore.d.ts +12 -4
  68. package/dist/engineAgentPanelStore.js +16 -11
  69. package/dist/engineCapReader.d.ts +2 -5
  70. package/dist/engineCapReader.js +8 -10
  71. package/dist/engineCapsCache.d.ts +12 -0
  72. package/dist/engineCapsCache.js +76 -18
  73. package/dist/engineCapsChange.d.ts +2 -0
  74. package/dist/engineCapsChange.js +9 -0
  75. package/dist/engineClosedSets.d.ts +1 -0
  76. package/dist/engineClosedSets.js +4 -1
  77. package/dist/engineErrorCodes.d.ts +11 -3
  78. package/dist/engineErrorCodes.js +11 -8
  79. package/dist/engineIdentity.d.ts +1 -0
  80. package/dist/engineIdentity.js +8 -0
  81. package/dist/engineRowRef.d.ts +28 -0
  82. package/dist/engineRowRef.js +114 -0
  83. package/dist/engineSessionMessages.d.ts +68 -0
  84. package/dist/engineSessionMessages.js +370 -0
  85. package/dist/engineTargetSeat.d.ts +27 -0
  86. package/dist/engineTargetSeat.js +199 -0
  87. package/dist/engineToolDirectory.d.ts +0 -9
  88. package/dist/engineToolDirectory.js +1 -94
  89. package/dist/engineUrl.d.ts +18 -0
  90. package/dist/engineUrl.js +52 -0
  91. package/dist/engineWireFor.js +3 -8
  92. package/dist/env/uiLanguage.d.ts +11 -1
  93. package/dist/env/uiLanguage.js +38 -2
  94. package/dist/eventLeg.d.ts +100 -0
  95. package/dist/eventLeg.js +305 -0
  96. package/dist/executionLaneCapability.d.ts +0 -4
  97. package/dist/executionLaneCapability.js +3 -16
  98. package/dist/fileHistoryCaptureCapability.d.ts +2 -5
  99. package/dist/fileHistoryCaptureCapability.js +13 -21
  100. package/dist/fileHistoryLegNotice.d.ts +2 -1
  101. package/dist/fileHistoryLegNotice.js +3 -3
  102. package/dist/fleet/fleetLedger.d.ts +0 -3
  103. package/dist/fleet/fleetLedger.js +21 -36
  104. package/dist/fleet/fleetProjection.d.ts +2 -2
  105. package/dist/fleet/fleetProjection.js +10 -8
  106. package/dist/frameBinding.d.ts +8 -0
  107. package/dist/frameBinding.js +35 -0
  108. package/dist/gateFailureCodes.d.ts +2 -0
  109. package/dist/gateFailureCodes.js +15 -0
  110. package/dist/gateOutcome.d.ts +3 -1
  111. package/dist/gateOutcome.js +41 -8
  112. package/dist/gateVocabulary.d.ts +10 -4
  113. package/dist/gateVocabulary.js +107 -47
  114. package/dist/generated/engineAskFaceTables.js +2 -2
  115. package/dist/generated/engineFactTables.d.ts +22 -3
  116. package/dist/generated/engineFactTables.js +51 -4
  117. package/dist/generated/engineNoticeTables.js +18 -3
  118. package/dist/generated/settingsSchemaFns.d.ts +6 -0
  119. package/dist/generated/settingsSchemaFns.js +57 -0
  120. package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
  121. package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
  122. package/dist/generated/settingsSchemaTables.d.ts +1 -0
  123. package/dist/generated/settingsSchemaTables.js +4 -0
  124. package/dist/generated/settingsSchemaTypes.d.ts +105 -0
  125. package/dist/generated/settingsSchemaTypes.js +1 -0
  126. package/dist/generated/toolNameTables.d.ts +1 -0
  127. package/dist/generated/toolNameTables.js +1 -0
  128. package/dist/hitl/allowRuleShadow.d.ts +8 -2
  129. package/dist/hitl/allowRuleShadow.js +36 -29
  130. package/dist/hitl/approvalCardReading.d.ts +15 -0
  131. package/dist/hitl/approvalCardReading.js +154 -0
  132. package/dist/hitl/approvalCardReasons.d.ts +14 -0
  133. package/dist/hitl/approvalCardReasons.js +119 -0
  134. package/dist/hitl/approvalHolds.d.ts +50 -15
  135. package/dist/hitl/approvalHolds.js +177 -27
  136. package/dist/hitl/approvalResolution.d.ts +51 -26
  137. package/dist/hitl/approvalResolution.js +86 -122
  138. package/dist/hitl/approvalsFeed.js +6 -18
  139. package/dist/hitl/askClassPair.d.ts +2 -0
  140. package/dist/hitl/askClassPair.js +17 -0
  141. package/dist/hitl/askGateWire.d.ts +20 -2
  142. package/dist/hitl/askGateWire.js +50 -1
  143. package/dist/hitl/askParkRowRouting.d.ts +5 -0
  144. package/dist/hitl/askParkRowRouting.js +32 -1
  145. package/dist/hitl/askSettlementLine.d.ts +28 -0
  146. package/dist/hitl/askSettlementLine.js +99 -0
  147. package/dist/hitl/automaticAnswerVerdict.d.ts +3 -2
  148. package/dist/hitl/automaticAnswerVerdict.js +29 -13
  149. package/dist/hitl/crashConverged.d.ts +11 -20
  150. package/dist/hitl/crashConverged.js +56 -0
  151. package/dist/hitl/crashConvergedNotice.d.ts +6 -3
  152. package/dist/hitl/crashConvergedNotice.js +48 -24
  153. package/dist/hitl/decisionConflict.js +3 -10
  154. package/dist/hitl/decisionRefusal.d.ts +40 -1
  155. package/dist/hitl/decisionRefusal.js +199 -42
  156. package/dist/hitl/frameRouter.d.ts +5 -2
  157. package/dist/hitl/frameRouter.js +27 -24
  158. package/dist/hitl/gateLedger.d.ts +2 -0
  159. package/dist/hitl/gateLedger.js +50 -13
  160. package/dist/hitl/hitlBridge.d.ts +2 -2
  161. package/dist/hitl/hitlBridge.js +13 -10
  162. package/dist/hitl/livePendingAsk.d.ts +3 -3
  163. package/dist/hitl/livePendingAsk.js +7 -18
  164. package/dist/hitl/parkResolver.d.ts +2 -24
  165. package/dist/hitl/parkResolver.js +61 -97
  166. package/dist/hitl/persistedRulesWire.d.ts +25 -0
  167. package/dist/hitl/persistedRulesWire.js +104 -2
  168. package/dist/hitl/planReviewWire.d.ts +31 -13
  169. package/dist/hitl/planReviewWire.js +120 -78
  170. package/dist/hitl/refusedToolNameProse.d.ts +0 -1
  171. package/dist/hitl/refusedToolNameProse.js +0 -3
  172. package/dist/hitl/replayedApproval.d.ts +4 -3
  173. package/dist/hitl/replayedApproval.js +7 -4
  174. package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
  175. package/dist/hitl/sessionPolicyDeliverable.js +48 -7
  176. package/dist/hitl/sessionPolicyWire.d.ts +34 -21
  177. package/dist/hitl/sessionPolicyWire.js +179 -70
  178. package/dist/hitl/standingRows.d.ts +20 -2
  179. package/dist/hitl/standingRows.js +69 -8
  180. package/dist/hitl/suspendedReopen.d.ts +2 -1
  181. package/dist/hitl/suspendedReopen.js +7 -10
  182. package/dist/hitl/toolApprovalWire.d.ts +103 -156
  183. package/dist/hitl/toolApprovalWire.js +661 -411
  184. package/dist/hookMatcherVerdict.d.ts +6 -1
  185. package/dist/hookMatcherVerdict.js +14 -7
  186. package/dist/hooksWireCaps.d.ts +2 -2
  187. package/dist/hooksWireCaps.js +174 -81
  188. package/dist/host.d.ts +21 -0
  189. package/dist/hostTurnSettings.d.ts +71 -0
  190. package/dist/hostTurnSettings.js +291 -0
  191. package/dist/humanTurn.d.ts +14 -1
  192. package/dist/humanTurn.js +100 -12
  193. package/dist/humanTurnRead.d.ts +2 -0
  194. package/dist/humanTurnRead.js +22 -1
  195. package/dist/i18n/messages.en.d.ts +703 -0
  196. package/dist/i18n/messages.en.js +701 -0
  197. package/dist/i18n/messages.zh.d.ts +3 -0
  198. package/dist/i18n/messages.zh.js +837 -0
  199. package/dist/i18n/translate.d.ts +25 -0
  200. package/dist/i18n/translate.js +127 -0
  201. package/dist/index.d.ts +78 -29
  202. package/dist/index.js +54 -18
  203. package/dist/inheritEnvCapability.d.ts +32 -0
  204. package/dist/inheritEnvCapability.js +104 -0
  205. package/dist/inheritEnvWire.d.ts +3 -2
  206. package/dist/inheritEnvWire.js +12 -14
  207. package/dist/interactiveHalt.js +17 -6
  208. package/dist/liveModelCatalog.d.ts +3 -3
  209. package/dist/liveModelCatalog.js +15 -13
  210. package/dist/liveQuestionStore.d.ts +2 -21
  211. package/dist/mcpLiveness.d.ts +2 -1
  212. package/dist/mcpPanel.d.ts +10 -1
  213. package/dist/mcpPanel.js +40 -13
  214. package/dist/mcpProbeCapability.d.ts +2 -1
  215. package/dist/mcpProbeCapability.js +7 -11
  216. package/dist/mcpProbeWire.d.ts +9 -2
  217. package/dist/mcpProbeWire.js +6 -1
  218. package/dist/mcpWireCaps.d.ts +47 -2
  219. package/dist/mcpWireCaps.js +164 -16
  220. package/dist/memoryEntriesWire.d.ts +4 -9
  221. package/dist/memoryEntriesWire.js +5 -10
  222. package/dist/model/modelSupplyRules.d.ts +0 -2
  223. package/dist/model/modelSupplyRules.js +3 -12
  224. package/dist/model/modelsPolicy.d.ts +0 -5
  225. package/dist/model/modelsPolicy.js +6 -36
  226. package/dist/model/onboardJudgement.d.ts +93 -0
  227. package/dist/model/onboardJudgement.js +415 -0
  228. package/dist/model/subagentModelWord.d.ts +31 -0
  229. package/dist/model/subagentModelWord.js +261 -0
  230. package/dist/model/tierVocabulary.d.ts +2 -0
  231. package/dist/model/tierVocabulary.js +17 -5
  232. package/dist/modelCapabilityProbe.d.ts +64 -0
  233. package/dist/modelCapabilityProbe.js +600 -0
  234. package/dist/modelIdentityResolvability.d.ts +3 -0
  235. package/dist/modelIdentityResolvability.js +26 -17
  236. package/dist/notifications.d.ts +6 -0
  237. package/dist/notifications.js +71 -23
  238. package/dist/outputStyleSeatCapability.d.ts +0 -3
  239. package/dist/outputStyleSeatCapability.js +0 -3
  240. package/dist/ownKey.d.ts +22 -0
  241. package/dist/ownKey.js +94 -3
  242. package/dist/panelReduce.d.ts +21 -10
  243. package/dist/panelReduce.js +728 -550
  244. package/dist/panelStateHolder.d.ts +3 -7
  245. package/dist/panelStateHolder.js +14 -130
  246. package/dist/peerLaneCapability.d.ts +0 -4
  247. package/dist/peerLaneCapability.js +0 -6
  248. package/dist/permissionRuleIssue.js +2 -0
  249. package/dist/permissionRulesWriteCapability.d.ts +2 -5
  250. package/dist/permissionRulesWriteCapability.js +8 -12
  251. package/dist/permissionWireCaps.d.ts +2 -2
  252. package/dist/permissionWireCaps.js +2 -0
  253. package/dist/permissionsAllowGrantCapability.d.ts +0 -4
  254. package/dist/permissionsAllowGrantCapability.js +0 -6
  255. package/dist/permissionsDeclaration.d.ts +0 -11
  256. package/dist/permissionsDeclaration.js +60 -53
  257. package/dist/pluginHooksWire.d.ts +46 -3
  258. package/dist/pluginHooksWire.js +219 -16
  259. package/dist/preemptWire.d.ts +44 -0
  260. package/dist/preemptWire.js +83 -0
  261. package/dist/printModelStatus.d.ts +63 -0
  262. package/dist/printModelStatus.js +155 -0
  263. package/dist/printToolResultFrame.js +15 -4
  264. package/dist/replayBody.d.ts +3 -0
  265. package/dist/replayBody.js +14 -0
  266. package/dist/request/taskRequest.d.ts +11 -6
  267. package/dist/request/taskRequest.js +112 -19
  268. package/dist/resumeRefusalCopy.d.ts +13 -9
  269. package/dist/resumeRefusalCopy.js +81 -118
  270. package/dist/retryStatus.d.ts +45 -0
  271. package/dist/retryStatus.js +185 -1
  272. package/dist/rewindArchiveCapability.d.ts +0 -4
  273. package/dist/rewindArchiveCapability.js +2 -10
  274. package/dist/rewindArchiveReading.d.ts +0 -1
  275. package/dist/rewindArchiveReading.js +0 -3
  276. package/dist/runCancelContext.d.ts +2 -1
  277. package/dist/runCancelContext.js +4 -2
  278. package/dist/runReattachPolicy.d.ts +31 -0
  279. package/dist/runReattachPolicy.js +46 -0
  280. package/dist/runTerminal.d.ts +3 -6
  281. package/dist/runTerminal.js +8 -9
  282. package/dist/sandboxWire.d.ts +3 -1
  283. package/dist/sandboxWire.js +76 -27
  284. package/dist/scenarioRefusal.d.ts +9 -0
  285. package/dist/scenarioRefusal.js +111 -0
  286. package/dist/scenarioWire.js +1 -1
  287. package/dist/seam.d.ts +48 -2
  288. package/dist/seam.js +25 -4
  289. package/dist/seatContract.d.ts +311 -18
  290. package/dist/seatContract.js +824 -100
  291. package/dist/selfOrchestrationDenial.js +7 -19
  292. package/dist/sessionIdSegment.d.ts +6 -0
  293. package/dist/sessionIdSegment.js +24 -0
  294. package/dist/sessionMemoryStatus.js +6 -11
  295. package/dist/sessionPolicyCapability.d.ts +2 -5
  296. package/dist/sessionPolicyCapability.js +8 -12
  297. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -3
  298. package/dist/sessionSyncFileHistoryCapability.js +0 -3
  299. package/dist/settingsHooksSalvage.d.ts +44 -0
  300. package/dist/settingsHooksSalvage.js +211 -0
  301. package/dist/skillToolListsCapability.d.ts +2 -4
  302. package/dist/skillToolListsCapability.js +8 -9
  303. package/dist/sqlEngineCapability.d.ts +0 -4
  304. package/dist/sqlEngineCapability.js +0 -6
  305. package/dist/sseIdleTriage.js +3 -2
  306. package/dist/steerPriorityCapability.d.ts +0 -3
  307. package/dist/steerPriorityCapability.js +0 -3
  308. package/dist/streamDrainingLegs.d.ts +4 -0
  309. package/dist/streamDrainingLegs.js +6 -1
  310. package/dist/subagent/engineCompactWire.d.ts +0 -1
  311. package/dist/subagent/engineCompactWire.js +7 -5
  312. package/dist/subagent/engineSubagentResume.js +15 -9
  313. package/dist/subagent/engineTaskHandleWire.js +4 -7
  314. package/dist/subagentContentStore.d.ts +3 -0
  315. package/dist/subagentContentStore.js +22 -10
  316. package/dist/submitReopen.d.ts +24 -0
  317. package/dist/submitReopen.js +75 -0
  318. package/dist/terminalStatuses.d.ts +3 -0
  319. package/dist/terminalStatuses.js +10 -2
  320. package/dist/toolHistoryMismatch.js +3 -2
  321. package/dist/toolResult.d.ts +10 -1
  322. package/dist/toolResult.js +34 -6
  323. package/dist/toolRoster.d.ts +3 -4
  324. package/dist/toolRoster.js +21 -22
  325. package/dist/turnFailurePresentation.d.ts +39 -0
  326. package/dist/turnFailurePresentation.js +402 -0
  327. package/dist/usageAnalytics.js +6 -11
  328. package/dist/userAttachmentEnvelope.d.ts +1 -0
  329. package/dist/userAttachmentEnvelope.js +37 -7
  330. package/dist/userAttachmentSeat.d.ts +21 -0
  331. package/dist/userAttachmentSeat.js +75 -0
  332. package/dist/userInvokedSkillsCapability.d.ts +11 -4
  333. package/dist/userInvokedSkillsCapability.js +31 -10
  334. package/dist/webSearchBackendCapability.d.ts +0 -4
  335. package/dist/webSearchBackendCapability.js +0 -6
  336. package/dist/wireErrorTriage.d.ts +7 -0
  337. package/dist/wireErrorTriage.js +26 -23
  338. package/dist/wireFailureShape.d.ts +62 -5
  339. package/dist/wireFailureShape.js +106 -5
  340. package/dist/wireRefusalCopy.d.ts +25 -3
  341. package/dist/wireRefusalCopy.js +74 -80
  342. package/dist/workflowsJournalCapability.d.ts +2 -5
  343. package/dist/workflowsJournalCapability.js +8 -12
  344. package/dist/writeProtectionCapability.d.ts +0 -4
  345. package/dist/writeProtectionCapability.js +0 -6
  346. package/docs/INTEGRATION-CLIENTS.md +1775 -56
  347. package/package.json +6 -5
  348. package/dist/attachmentSeatCapability.d.ts +0 -12
  349. package/dist/attachmentSeatCapability.js +0 -23
  350. package/dist/hitl/approvalOutcomeNote.d.ts +0 -10
  351. package/dist/hitl/approvalOutcomeNote.js +0 -29
  352. package/dist/sessionReadRedactionCapability.d.ts +0 -13
  353. package/dist/sessionReadRedactionCapability.js +0 -35
@@ -1,156 +1,120 @@
1
+ import { DecideTransportRetryExhaustedError } from './hitlBridge.js';
2
+ import { mintDecisionRefusalReading, refusalCarrierOf } from './decisionRefusal.js';
3
+ import { thrownIsInstanceOf } from '../wireFailureShape.js';
4
+ export const APPROVAL_RESOLUTION_LANES = Object.freeze(['respond', 'decide', 'ask']);
1
5
  export const APPROVAL_NOT_SENT_CAUSES = Object.freeze([
2
6
  'retracted',
3
7
  'edit_refused',
4
8
  'no_pending',
9
+ 'wrong_gate',
5
10
  'fetch_failed',
6
11
  'no_input',
7
12
  'card_unavailable',
13
+ 'safety_stop',
8
14
  ]);
9
15
  export const APPROVAL_UNSETTLED_CAUSES = Object.freeze([
10
16
  'engine_refused',
11
- 'decide_failed',
17
+ 'engine_error',
18
+ 'no_answer',
12
19
  'transport_exhausted',
13
- 'safety_stop',
14
- 'respond_failed',
15
20
  'parking_in_progress',
16
21
  'interrupted',
17
22
  'orchestration',
18
23
  'unreadable',
19
24
  ]);
20
- const FS_OUTCOME_KINDS = Object.freeze(['decided', 'aborted', 'retracted', 'failed']);
21
- function str(v) {
22
- return typeof v === 'string' && v.length > 0 ? v : undefined;
25
+ export function isApprovalDecided(r) {
26
+ return typeof r === 'object' && r !== null && r.kind === 'decided';
23
27
  }
24
- function num(v) {
25
- return typeof v === 'number' && Number.isFinite(v) ? v : undefined;
28
+ export function approvalNotSentCause(r) {
29
+ if (typeof r !== 'object' || r === null || r.kind !== 'not_sent')
30
+ return undefined;
31
+ return r.cause;
26
32
  }
27
- function pick(o, key) {
33
+ export function approvalUnsettledCause(r) {
34
+ if (typeof r !== 'object' || r === null || r.kind !== 'unsettled')
35
+ return undefined;
36
+ return r.cause;
37
+ }
38
+ export const APPROVAL_NOTE_RETRACTED_DETAIL = 'the card was retracted (this host no longer has a decision port for it)';
39
+ export const APPROVAL_NOTE_EDIT_REFUSED_DETAIL = 'edits are not accepted on this card';
40
+ const NOT_SENT_SENTENCES = Object.freeze({
41
+ retracted: APPROVAL_NOTE_RETRACTED_DETAIL,
42
+ edit_refused: APPROVAL_NOTE_EDIT_REFUSED_DETAIL,
43
+ no_pending: 'there was no pending approval to decide for this run (it may already have been decided or expired); nothing was sent',
44
+ wrong_gate: 'the pending approval is waiting at a different kind of gate than this card; nothing was sent',
45
+ fetch_failed: 'the pending approval could not be fetched; nothing was sent',
46
+ no_input: 'the approval has no tool input or question to show, so no card was shown; nothing was sent',
47
+ card_unavailable: 'no approval card could be shown on this host; nothing was sent',
48
+ safety_stop: 'the decision was stopped by a local safety check before it was sent; nothing was sent',
49
+ });
50
+ function nonEmpty(v) {
51
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
52
+ }
53
+ function ownStr(o, key) {
28
54
  try {
29
- return o?.[key];
55
+ if (typeof o !== 'object' || o === null)
56
+ return undefined;
57
+ const d = Object.getOwnPropertyDescriptor(o, key);
58
+ return d !== undefined && Object.hasOwn(d, 'value') ? nonEmpty(d.value) : undefined;
30
59
  }
31
60
  catch {
32
61
  return undefined;
33
62
  }
34
63
  }
35
- function opt(key, v) {
36
- return v === undefined ? {} : { [key]: v };
37
- }
38
- export function approvalResolutionOf(outcome) {
39
- if (typeof outcome !== 'object' || outcome === null || Array.isArray(outcome)) {
40
- return { kind: 'unsettled', cause: 'unreadable' };
64
+ export function approvalResolutionDetail(r) {
65
+ let kind;
66
+ try {
67
+ kind = typeof r === 'object' && r !== null ? r.kind : undefined;
41
68
  }
42
- const kind = pick(outcome, 'kind');
43
- if (typeof kind === 'string' && FS_OUTCOME_KINDS.includes(kind)) {
44
- return fsLegResolution(outcome, kind);
69
+ catch {
70
+ return undefined;
45
71
  }
46
- if (typeof pick(outcome, 'decision') === 'string') {
47
- return frameLegResolution(outcome);
72
+ if (kind === 'not_sent') {
73
+ const cause = ownStr(r, 'cause');
74
+ if (cause === undefined || !Object.hasOwn(NOT_SENT_SENTENCES, cause))
75
+ return undefined;
76
+ const sentence = NOT_SENT_SENTENCES[cause];
77
+ const code = cause === 'safety_stop' ? ownStr(r, 'safetyCode') : undefined;
78
+ return code !== undefined ? `${sentence} (${code})` : sentence;
48
79
  }
49
- return { kind: 'unsettled', cause: 'unreadable' };
50
- }
51
- function fsLegResolution(outcome, kind) {
52
- const gatedCallId = str(pick(outcome, 'gatedCallId'));
53
- const call = opt('gatedCallId', gatedCallId);
54
- if (kind === 'decided') {
55
- return {
56
- kind: 'decided',
57
- decision: pick(outcome, 'denied') === true ? 'deny' : 'allow',
58
- ...call,
59
- ...opt('receipt', pick(outcome, 'receipt')),
60
- };
61
- }
62
- if (kind === 'retracted')
63
- return { kind: 'not_sent', cause: 'retracted', ...call };
64
- if (kind === 'aborted')
65
- return { kind: 'unsettled', cause: 'interrupted', ...call };
66
- const detail = opt('detail', str(pick(outcome, 'reason')));
67
- const stage = pick(outcome, 'stage');
68
- if (stage === 'fetch') {
69
- const cause = pick(outcome, 'code') === 'no_pending' ? 'no_pending' : 'fetch_failed';
70
- return { kind: 'not_sent', cause, ...call, ...detail };
80
+ if (kind !== 'unsettled')
81
+ return undefined;
82
+ let refusal;
83
+ try {
84
+ const d = Object.getOwnPropertyDescriptor(r, 'refusal');
85
+ refusal = d !== undefined && Object.hasOwn(d, 'value') ? d.value : undefined;
71
86
  }
72
- if (stage === 'input')
73
- return { kind: 'not_sent', cause: 'no_input', ...call, ...detail };
74
- if (stage === 'card' && pick(outcome, 'editRefused') === true)
75
- return { kind: 'not_sent', cause: 'edit_refused', ...call, ...detail };
76
- if (stage === 'card')
77
- return { kind: 'not_sent', cause: 'card_unavailable', ...call, ...detail };
78
- if (stage === 'decide') {
79
- const safetyCode = str(pick(outcome, 'safetyCode'));
80
- const errorCode = str(pick(outcome, 'errorCode'));
81
- const engineAnswered = errorCode !== undefined || pick(outcome, 'currentPending') !== undefined;
82
- const cause = safetyCode !== undefined
83
- ? 'safety_stop'
84
- : pick(outcome, 'retryExhausted') === true
85
- ? 'transport_exhausted'
86
- : engineAnswered
87
- ? 'engine_refused'
88
- : 'decide_failed';
89
- return {
90
- kind: 'unsettled',
91
- cause,
92
- ...call,
93
- ...opt('safetyCode', safetyCode),
94
- ...opt('errorCode', errorCode),
95
- ...detail,
96
- };
87
+ catch {
88
+ refusal = undefined;
97
89
  }
98
- if (stage === 'orchestration')
99
- return { kind: 'unsettled', cause: 'orchestration', ...call, ...detail };
100
- return { kind: 'unsettled', cause: 'unreadable', ...call, ...detail };
90
+ const parts = [ownStr(refusal, 'errorCode'), ownStr(r, 'detail') ?? ownStr(refusal, 'message')].filter((x) => x !== undefined);
91
+ return parts.length > 0 ? parts.join(' · ') : undefined;
101
92
  }
102
- function parkingViewOf(v) {
103
- const approvalId = str(pick(v, 'approvalId'));
104
- if (approvalId === undefined)
105
- return undefined;
106
- const hint = pick(v, 'retryAfterMs');
107
- const retryAfterMs = typeof hint === 'number' && Number.isFinite(hint) && hint >= 0 ? hint : undefined;
108
- const decidePath = str(pick(v, 'decidePath'));
109
- const message = str(pick(v, 'message'));
110
- return {
111
- approvalId,
112
- ...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
113
- ...(decidePath !== undefined ? { decidePath } : {}),
114
- ...(message !== undefined ? { message } : {}),
115
- };
93
+ export function unsettledCauseOfReading(reading) {
94
+ if (reading.standing === 'ambiguous')
95
+ return 'engine_error';
96
+ return reading.standing === undefined ? 'no_answer' : 'engine_refused';
116
97
  }
117
- function frameLegResolution(outcome) {
118
- if (pick(outcome, 'retracted') === true)
119
- return { kind: 'not_sent', cause: 'retracted' };
120
- if (pick(outcome, 'editRefused') === true)
121
- return { kind: 'not_sent', cause: 'edit_refused' };
122
- if (pick(outcome, 'aborted') === true)
123
- return { kind: 'unsettled', cause: 'interrupted' };
124
- const parking = parkingViewOf(pick(outcome, 'parking'));
125
- if (parking !== undefined)
126
- return { kind: 'unsettled', cause: 'parking_in_progress', parking };
127
- if (pick(outcome, 'decision') === 'unresolved') {
128
- const refusal = pick(outcome, 'respondRefusal');
129
- return {
130
- kind: 'unsettled',
131
- cause: 'respond_failed',
132
- ...opt('status', num(pick(refusal, 'status'))),
133
- ...opt('errorCode', str(pick(refusal, 'errorCode'))),
134
- ...opt('detail', str(pick(refusal, 'message'))),
135
- };
136
- }
137
- const ack = pick(outcome, 'ack');
138
- return {
139
- kind: 'decided',
140
- decision: pick(outcome, 'decision'),
141
- ...(typeof ack === 'object' && ack !== null ? { ack: ack } : {}),
98
+ export function resolutionOfDecisionFailure(e, m) {
99
+ const base = {
100
+ lane: m.lane,
101
+ ...(m.gatedCallId !== undefined ? { gatedCallId: m.gatedCallId } : {}),
142
102
  };
103
+ const detail = m.detail !== undefined && m.detail.length > 0 ? { detail: m.detail } : {};
104
+ const { local } = refusalCarrierOf(e);
105
+ if (local !== undefined && local !== 'binding_mismatch') {
106
+ if (local === 'no_pending' || local === 'wrong_gate')
107
+ return { kind: 'not_sent', ...base, cause: local, ...detail };
108
+ return { kind: 'not_sent', ...base, cause: 'safety_stop', safetyCode: local, ...detail };
109
+ }
110
+ const refusal = mintDecisionRefusalReading(e, { route: m.route }, m.attributionCarried);
111
+ if (local === 'binding_mismatch')
112
+ return { kind: 'unsettled', ...base, cause: 'engine_refused', safetyCode: 'binding_mismatch', refusal, ...detail };
113
+ if (thrownIsInstanceOf(e, DecideTransportRetryExhaustedError))
114
+ return { kind: 'unsettled', ...base, cause: 'transport_exhausted', refusal, ...detail };
115
+ return { kind: 'unsettled', ...base, cause: unsettledCauseOfReading(refusal), refusal, ...detail };
143
116
  }
144
- export function isApprovalDecided(r) {
145
- return typeof r === 'object' && r !== null && r.kind === 'decided';
146
- }
147
- export function approvalNotSentCause(r) {
148
- if (typeof r !== 'object' || r === null || r.kind !== 'not_sent')
149
- return undefined;
150
- return r.cause;
151
- }
152
- export function approvalUnsettledCause(r) {
153
- if (typeof r !== 'object' || r === null || r.kind !== 'unsettled')
154
- return undefined;
155
- return r.cause;
117
+ export function joinedResolution(r, gatedCallId) {
118
+ const carry = r.gatedCallId === undefined && gatedCallId !== undefined && gatedCallId !== '' ? { gatedCallId } : {};
119
+ return { ...r, ...carry, joinedInFlight: true };
156
120
  }
@@ -24,15 +24,6 @@ function readDurablePendingRows(raw) {
24
24
  return { kind: 'malformed' };
25
25
  return { kind: 'present', rows, dropped };
26
26
  }
27
- function baselineDurableDigestThrows(raw) {
28
- try {
29
- durableDigestOf(raw);
30
- return false;
31
- }
32
- catch {
33
- return true;
34
- }
35
- }
36
27
  function durableDigestOf(rows) {
37
28
  return rows
38
29
  .map(r => [r.sessionId ?? '', r.taskId ?? '', r.toolCallId ?? '', r.boundCallId ?? '', r.boundInputHash ?? '', r.toolName ?? '']
@@ -214,17 +205,11 @@ export function startApprovalsFeed(client, onSnapshot, opts) {
214
205
  catch {
215
206
  durableRead = { kind: 'malformed' };
216
207
  }
217
- const badDurable = durableRead.kind === 'malformed' || durableRead.dropped > 0;
218
- const escapes = badDurable && baselineDurableDigestThrows(rawPending);
219
- if (durableRead.kind === 'malformed' || escapes) {
208
+ if (durableRead.kind === 'malformed') {
220
209
  hostLog('debug', `approvalsFeed: list() body has an unreadable pending section (${via} leg) — snapshot not committed`);
221
- if (!escapes)
222
- stats.listErrors++;
223
210
  noteTakeMissed(via, seq);
224
211
  publishUnknown('unreadable_payload', via, seq);
225
- if (escapes)
226
- throw new TypeError('approvalsFeed: unreadable pending section (baseline digest would have thrown)');
227
- return;
212
+ throw new TypeError('approvalsFeed: unreadable pending section');
228
213
  }
229
214
  rows = durableRead.rows;
230
215
  droppedDurable = durableRead.dropped;
@@ -246,7 +231,10 @@ export function startApprovalsFeed(client, onSnapshot, opts) {
246
231
  hostLog('debug', `approvalsFeed: dropping stale poll snapshot from leg ${leg} (current ${pollLeg}) — debt untouched`);
247
232
  return;
248
233
  }
249
- noteTakeLooked(seq);
234
+ if (dropped > 0 || droppedDurable > 0)
235
+ noteTakeMissed(via, seq);
236
+ else
237
+ noteTakeLooked(seq);
250
238
  if (seq < lastObservedSeq) {
251
239
  hostLog('debug', `approvalsFeed: dropping out-of-order take #${seq} (newest observed #${lastObservedSeq})`);
252
240
  return;
@@ -1,3 +1,5 @@
1
+ import { CORE_MODE_ARBITRATION } from '../generated/engineFactTables.js';
2
+ export declare const DEPLOYMENT_LIST_ASK_CLASSES: readonly (keyof typeof CORE_MODE_ARBITRATION)[];
1
3
  export type AskClassPairReading = {
2
4
  readonly state: 'pair';
3
5
  readonly askClass: string;
@@ -1,3 +1,5 @@
1
+ import { CORE_MODE_ARBITRATION } from '../generated/engineFactTables.js';
2
+ export const DEPLOYMENT_LIST_ASK_CLASSES = Object.freeze(['ask_rule']);
1
3
  const ABSENT = Object.freeze({ state: 'absent' });
2
4
  const MALFORMED = Object.freeze({ state: 'malformed' });
3
5
  export function readAskClassPairState(v) {
@@ -34,8 +36,23 @@ export function readAskClassPairState(v) {
34
36
  return MALFORMED;
35
37
  if (classes[0] !== askClass)
36
38
  return MALFORMED;
39
+ if (!inCanonicalOrder(classes))
40
+ return MALFORMED;
37
41
  return Object.freeze({ state: 'pair', askClass, classes: Object.freeze(classes) });
38
42
  }
43
+ function inCanonicalOrder(classes) {
44
+ const order = Object.keys(CORE_MODE_ARBITRATION);
45
+ let last = -1;
46
+ for (const c of classes) {
47
+ const rank = order.indexOf(c);
48
+ if (rank < 0)
49
+ continue;
50
+ if (rank <= last)
51
+ return false;
52
+ last = rank;
53
+ }
54
+ return true;
55
+ }
39
56
  export function readAskClassPair(v) {
40
57
  const r = readAskClassPairState(v);
41
58
  return r.state === 'pair' ? { askClass: r.askClass, classes: r.classes } : undefined;
@@ -8,11 +8,29 @@ export type { AskAnsweredOutput } from './gateLedger.js';
8
8
  export { SEMA_COLLATERAL_ABORT_KEY } from './gateLedger.js';
9
9
  export { SEMA_DENIAL_KIND_KEY } from './gateLedger.js';
10
10
  export type { GateDenyAttribution } from './gateLedger.js';
11
- export { toAnsweredOutput, isAlreadyResolvedFailure, isAlreadyResolvedGateReason, isGateStandingErrorCode, isCodeClassifiedGateFailure, nextHopBudget, MAX_GATE_HOPS, MAX_TOTAL_PARKS } from './parkResolver.js';
11
+ export { toAnsweredOutput, isAlreadyResolvedFailure, nextHopBudget, MAX_GATE_HOPS, MAX_TOTAL_PARKS } from './parkResolver.js';
12
12
  export type { HopBudget, HopRound } from './parkResolver.js';
13
- export type { GateOutcome, GateFailureCode } from './parkResolver.js';
13
+ export type { GateFailureCode } from './parkResolver.js';
14
14
  export { GATE_FAILURE_CODES } from './hitlBridge.js';
15
15
  export declare function bridgeAskUserQuestionGates(source: AsyncGenerator<AgentEvent>, deps: AskGateWireDeps, opts?: {
16
16
  signal?: AbortSignal;
17
17
  taskId?: string;
18
18
  }): AsyncGenerator<AgentEvent>;
19
+ export declare const LATE_DECIDE_OUTCOMES: readonly ["accepted-not-resolved", "resumed", "expired-reaped", "settled-elsewhere", "unknown"];
20
+ export type LateDecideOutcome = (typeof LATE_DECIDE_OUTCOMES)[number];
21
+ export interface LateDecideOutcomeReading {
22
+ readonly kind: LateDecideOutcome;
23
+ readonly taskId?: string;
24
+ readonly executed?: 'allowed' | 'denied';
25
+ readonly probeWorthy?: true;
26
+ }
27
+ export type LateDecideReply = {
28
+ readonly ok: true;
29
+ readonly body: object | null | undefined;
30
+ } | {
31
+ readonly ok: false;
32
+ readonly error: object | null | undefined;
33
+ };
34
+ export declare function lateDecideOutcomeOf(reply: LateDecideReply, opts?: {
35
+ readonly lane?: 'decide' | 'respond';
36
+ }): LateDecideOutcomeReading;
@@ -4,12 +4,20 @@ import { resolvePark, nextHopBudget, stalledTerminal, MAX_GATE_HOPS } from './pa
4
4
  import { createStreamDrainingLegs } from '../streamDrainingLegs.js';
5
5
  import { abortableSleep } from '../abortableSleep.js';
6
6
  import { hostLog } from '../host.js';
7
+ import { decideAcceptedNotResolved, readDecideReceipt } from '../decideReceipt.js';
8
+ import { APPROVAL_EXPIRED } from '../engineErrorCodes.js';
9
+ import { isNotFoundFailure } from '../wireErrorTriage.js';
10
+ import { readDecisionRefusalAsk } from './decisionRefusal.js';
11
+ import { resumeReopenFromError } from './suspendedReopen.js';
12
+ import { refusedParkFromError, resumeRefusalFromError } from '../resumeRefusalCopy.js';
13
+ import { guardedRead, readOwnDataValue } from '../ownKey.js';
14
+ import { readToolApprovalRespondParking } from './toolApprovalWire.js';
7
15
  export { HITL_REJECT_MESSAGE, ENGINE_ABORT_TOOL_RESULT } from './frameRouter.js';
8
16
  export { HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE } from './frameRouter.js';
9
17
  export { HITL_POLICY_DENY_MESSAGE } from './frameRouter.js';
10
18
  export { SEMA_COLLATERAL_ABORT_KEY } from './gateLedger.js';
11
19
  export { SEMA_DENIAL_KIND_KEY } from './gateLedger.js';
12
- export { toAnsweredOutput, isAlreadyResolvedFailure, isAlreadyResolvedGateReason, isGateStandingErrorCode, isCodeClassifiedGateFailure, nextHopBudget, MAX_GATE_HOPS, MAX_TOTAL_PARKS } from './parkResolver.js';
20
+ export { toAnsweredOutput, isAlreadyResolvedFailure, nextHopBudget, MAX_GATE_HOPS, MAX_TOTAL_PARKS } from './parkResolver.js';
13
21
  export { GATE_FAILURE_CODES } from './hitlBridge.js';
14
22
  export async function* bridgeAskUserQuestionGates(source, deps, opts) {
15
23
  const led = createGateLedger();
@@ -58,6 +66,7 @@ export async function* bridgeAskUserQuestionGates(source, deps, opts) {
58
66
  }
59
67
  park = {
60
68
  gate: action.gate,
69
+ parkFrame: action.parkFrame,
61
70
  ...(action.pendingDone !== undefined ? { pendingDone: action.pendingDone } : {}),
62
71
  ...(action.gatedCallId !== undefined ? { gatedCallId: action.gatedCallId } : {}),
63
72
  ...(action.toolName !== undefined ? { toolName: action.toolName } : {}),
@@ -152,3 +161,43 @@ export async function* bridgeAskUserQuestionGates(source, deps, opts) {
152
161
  });
153
162
  }
154
163
  }
164
+ export const LATE_DECIDE_OUTCOMES = Object.freeze(['accepted-not-resolved', 'resumed', 'expired-reaped', 'settled-elsewhere', 'unknown']);
165
+ const LATE_DECIDE_TASK_ID_MAX = 64;
166
+ export function lateDecideOutcomeOf(reply, opts) {
167
+ try {
168
+ if (reply.ok === true) {
169
+ const body = reply.body;
170
+ if (guardedRead(() => readToolApprovalRespondParking(body)) !== undefined)
171
+ return LATE_UNKNOWN;
172
+ const receipt = guardedRead(() => readDecideReceipt(body));
173
+ const handoff = receipt?.handoffTaskId;
174
+ const rawTask = typeof handoff === 'string' && handoff !== '' ? handoff : guardedRead(() => readOwnDataValue(body, 'taskId'));
175
+ const taskId = typeof rawTask === 'string' && rawTask !== '' ? rawTask.slice(0, LATE_DECIDE_TASK_ID_MAX) : undefined;
176
+ const replayed = guardedRead(() => readOwnDataValue(body, 'idempotent')) === true;
177
+ if (opts?.lane === 'respond' && replayed)
178
+ return Object.freeze({ kind: 'settled-elsewhere' });
179
+ const kind = opts?.lane === 'respond' && !decideAcceptedNotResolved(receipt) ? 'resumed' : 'accepted-not-resolved';
180
+ const disposition = receipt?.executionOutcome?.disposition?.kind;
181
+ const executed = disposition === 'allowed' || disposition === 'denied' ? disposition : undefined;
182
+ return Object.freeze({ kind, ...(taskId !== undefined ? { taskId } : {}), ...(executed !== undefined ? { executed } : {}) });
183
+ }
184
+ const e = reply.error;
185
+ if (typeof e !== 'object' || e === null)
186
+ return LATE_UNKNOWN;
187
+ const code = guardedRead(() => readOwnDataValue(e, 'errorCode'));
188
+ const status = guardedRead(() => readOwnDataValue(e, 'status'));
189
+ if (code === APPROVAL_EXPIRED)
190
+ return Object.freeze({ kind: 'expired-reaped' });
191
+ if (resumeReopenFromError(e) !== null || resumeRefusalFromError(e)?.waitable === true || refusedParkFromError(e)?.stillPending === true)
192
+ return LATE_UNKNOWN;
193
+ const r = readDecisionRefusalAsk(e);
194
+ if (r.reading !== 'settled' && !(r.reading === 'not_settled' && r.gateMoved))
195
+ return LATE_UNKNOWN;
196
+ const probeWorthy = status === 404 || status === 410 || isNotFoundFailure(e) !== false;
197
+ return Object.freeze(probeWorthy ? { kind: 'settled-elsewhere', probeWorthy: true } : { kind: 'settled-elsewhere' });
198
+ }
199
+ catch {
200
+ return LATE_UNKNOWN;
201
+ }
202
+ }
203
+ const LATE_UNKNOWN = Object.freeze({ kind: 'unknown' });
@@ -27,3 +27,8 @@ export interface RowArmSingleFlight<T> {
27
27
  clear: () => void;
28
28
  }
29
29
  export declare function createRowArmSingleFlight<T>(): RowArmSingleFlight<T>;
30
+ export declare function pendingRowIsOwnedAndDecidable(row: PendingCheckpoint, deps?: ParkOwnershipDeps): boolean;
31
+ export interface OwnedPendingListView {
32
+ readonly pending?: readonly PendingCheckpoint[] | null;
33
+ }
34
+ export declare function countOwnedPendingRows(listed: OwnedPendingListView | null | undefined, deps?: ParkOwnershipDeps): number;
@@ -1,4 +1,4 @@
1
- import { askParkForeignGateKind } from '../adapter/activeRunSelfHeal.js';
1
+ import { askParkForeignGateKind, durableDecideLegOf } from '../adapter/activeRunSelfHeal.js';
2
2
  import { isAskTool } from './frameRouter.js';
3
3
  import { approvalCallKey } from './gateIdentity.js';
4
4
  import { askQuestionsFromPending, pendingRowIsOwnedByThisSession } from './parkOwnership.js';
@@ -108,3 +108,34 @@ export function createRowArmSingleFlight() {
108
108
  },
109
109
  };
110
110
  }
111
+ export function pendingRowIsOwnedAndDecidable(row, deps) {
112
+ if (typeof row !== 'object' || row === null)
113
+ throw new TypeError('pending row is not an object — ownership cannot be judged');
114
+ if (!pendingRowIsOwnedByThisSession(row, deps))
115
+ return false;
116
+ void row.gateKind;
117
+ const leg = durableDecideLegOf(row);
118
+ if (leg === 'plan_review')
119
+ return true;
120
+ if (leg !== 'approval' && leg !== 'absent')
121
+ return false;
122
+ return askParkRowArm(row) === 'question' ? askQuestionsFromPending(row) !== null : true;
123
+ }
124
+ export function countOwnedPendingRows(listed, deps) {
125
+ if (typeof listed !== 'object' || listed === null || Array.isArray(listed)) {
126
+ throw new Error('approvals.list answered without a readable body — the owned pending count is unknown');
127
+ }
128
+ const pending = listed?.pending;
129
+ if (!Array.isArray(pending)) {
130
+ throw new Error('approvals.list answered without a readable `pending` array — the owned pending count is unknown');
131
+ }
132
+ let n = 0;
133
+ for (const row of pending) {
134
+ if (typeof row !== 'object' || row === null) {
135
+ throw new Error('approvals.list answered with a pending row that is not an object — the owned pending count is unknown');
136
+ }
137
+ if (pendingRowIsOwnedAndDecidable(row, deps))
138
+ n++;
139
+ }
140
+ return n;
141
+ }
@@ -0,0 +1,28 @@
1
+ import type { UiLanguage } from '../env/uiLanguage.js';
2
+ export declare function askEndingCauseClause(cause: string | undefined, lang?: UiLanguage): string | undefined;
3
+ export interface AskSettlementInput {
4
+ readonly cause?: string | undefined;
5
+ readonly toolName?: string | undefined;
6
+ readonly parked?: boolean | undefined;
7
+ }
8
+ export declare function askSettlementLine(settled: AskSettlementInput, lang?: UiLanguage): string | undefined;
9
+ export type AskAcceptedFollow = 'following' | 'already-following' | 'not-following';
10
+ export interface AskAcceptedInput {
11
+ readonly decision?: string | undefined;
12
+ readonly taskId?: string | undefined;
13
+ readonly late?: boolean | undefined;
14
+ readonly follow?: AskAcceptedFollow | undefined;
15
+ readonly executed?: string | undefined;
16
+ }
17
+ export declare function askAcceptedLine(accepted: AskAcceptedInput, lang?: UiLanguage): string;
18
+ export type AskParkedCardForm = 'approval' | 'question' | 'queue_no_deadline';
19
+ export declare function askParkedCardNote(form?: string | undefined, toolName?: string | undefined, lang?: UiLanguage): string;
20
+ export interface AskHumanSettledInput {
21
+ readonly kind?: string | undefined;
22
+ readonly decision?: string | undefined;
23
+ readonly taskId?: string | undefined;
24
+ readonly late?: boolean | undefined;
25
+ readonly follow?: AskAcceptedFollow | undefined;
26
+ readonly executed?: string | undefined;
27
+ }
28
+ export declare function askHumanSettlementLine(settled: AskHumanSettledInput, lang?: UiLanguage): string | undefined;
@@ -0,0 +1,99 @@
1
+ import { displayUntrusted, quoteUntrustedForSentence } from '../displayUntrusted.js';
2
+ import { msg, renderMessage } from '../i18n/translate.js';
3
+ import { guardedRead, readOwnDataValue } from '../ownKey.js';
4
+ const ENDING_CAUSE_KEYS = Object.freeze({
5
+ routing_failure_fail_closed: 'approval.settle.cause.routingFailureFailClosed',
6
+ run_cancelled: 'approval.settle.cause.runCancelled',
7
+ run_exited: 'approval.settle.cause.runExited',
8
+ batch_aborted: 'approval.settle.cause.batchAborted',
9
+ batch_sibling_withdrawn: 'approval.settle.cause.batchSiblingWithdrawn',
10
+ batch_bound_elsewhere: 'approval.settle.cause.batchBoundElsewhere',
11
+ adhoc_leg_no_durable_domain: 'approval.settle.cause.adhocLegNoDurableDomain',
12
+ orphan_ttl_exceeded: 'approval.settle.cause.orphanTtlExceeded',
13
+ crashed_before_park: 'approval.settle.cause.crashedBeforePark',
14
+ shutdown_before_park: 'approval.settle.cause.shutdownBeforePark',
15
+ ttl_expired: 'approval.settle.cause.ttlExpired',
16
+ broadcast_lost: 'approval.settle.cause.broadcastLost',
17
+ stream_disconnected: 'approval.settle.cause.streamDisconnected',
18
+ undeliverable: 'approval.settle.cause.undeliverable',
19
+ });
20
+ function endingCauseKeyOf(cause) {
21
+ return typeof cause === 'string' && Object.hasOwn(ENDING_CAUSE_KEYS, cause) ? ENDING_CAUSE_KEYS[cause] : undefined;
22
+ }
23
+ export function askEndingCauseClause(cause, lang) {
24
+ const key = endingCauseKeyOf(cause);
25
+ return key !== undefined ? renderMessage(msg(key), lang) : undefined;
26
+ }
27
+ function ownSlot(o, key) {
28
+ if (typeof o !== 'object' || o === null)
29
+ return undefined;
30
+ return guardedRead(() => readOwnDataValue(o, key));
31
+ }
32
+ function subjectOf(toolName, named, generic) {
33
+ const quoted = typeof toolName === 'string' ? guardedRead(() => quoteUntrustedForSentence(toolName, 80)) : undefined;
34
+ return quoted === undefined ? msg(generic) : msg(named, { tool: quoted });
35
+ }
36
+ export function askSettlementLine(settled, lang) {
37
+ if (ownSlot(settled, 'parked') === true)
38
+ return undefined;
39
+ const cause = ownSlot(settled, 'cause');
40
+ if (typeof cause !== 'string' || cause === '')
41
+ return undefined;
42
+ const subject = subjectOf(ownSlot(settled, 'toolName'), 'approval.settle.subject.named', 'approval.settle.subject.generic');
43
+ const clauseKey = endingCauseKeyOf(cause);
44
+ return renderMessage(clauseKey !== undefined ? msg('approval.settle.endedKnown', { subject, clause: msg(clauseKey) }) : msg('approval.settle.endedUnknown', { subject }), lang);
45
+ }
46
+ const TASK_ID_MAX = 64;
47
+ const EXECUTED_TAIL_KEYS = Object.freeze({
48
+ allowed: 'approval.settle.executed.allowed',
49
+ denied: 'approval.settle.executed.denied',
50
+ });
51
+ const FOLLOW_CLAUSE_KEYS = Object.freeze({
52
+ following: 'approval.settle.follow.following',
53
+ 'already-following': 'approval.settle.follow.alreadyFollowing',
54
+ });
55
+ export function askAcceptedLine(accepted, lang) {
56
+ const decision = ownSlot(accepted, 'decision');
57
+ const what = msg(decision === 'approve' ? 'approval.settle.what.approved' : decision === 'deny' ? 'approval.settle.what.denied' : 'approval.settle.what.answered');
58
+ const late = ownSlot(accepted, 'late') === false ? '' : msg('approval.settle.late');
59
+ const rawTask = ownSlot(accepted, 'taskId');
60
+ const shownTask = typeof rawTask === 'string' ? guardedRead(() => displayUntrusted(rawTask, { max: TASK_ID_MAX, blanks: true })) : undefined;
61
+ const where = shownTask === undefined || shownTask === '' ? '' : msg('approval.settle.where', { task: shownTask });
62
+ const follow = ownSlot(accepted, 'follow');
63
+ const executed = ownSlot(accepted, 'executed');
64
+ const tail = executed === 'allowed' || executed === 'denied' ? msg(EXECUTED_TAIL_KEYS[executed]) : '';
65
+ if (follow === 'following' || follow === 'already-following') {
66
+ return renderMessage(msg('approval.settle.acceptedFollowing', { what, late, where, follow: msg(FOLLOW_CLAUSE_KEYS[follow]), tail }), lang);
67
+ }
68
+ return renderMessage(msg('approval.settle.acceptedNotFollowing', { what, late, where, tail }), lang);
69
+ }
70
+ const PARKED_CARD_NOTE_KEYS = Object.freeze({
71
+ approval: 'approval.settle.parkedNote.approval',
72
+ question: 'approval.settle.parkedNote.question',
73
+ queue_no_deadline: 'approval.settle.parkedNote.queueNoDeadline',
74
+ });
75
+ export function askParkedCardNote(form, toolName, lang) {
76
+ const key = form === 'question' || form === 'queue_no_deadline' ? form : 'approval';
77
+ if (key !== 'queue_no_deadline')
78
+ return renderMessage(msg(PARKED_CARD_NOTE_KEYS[key]), lang);
79
+ return renderMessage(msg(PARKED_CARD_NOTE_KEYS[key], { subject: subjectOf(toolName, 'approval.settle.parkedSubject.named', 'approval.settle.parkedSubject.generic') }), lang);
80
+ }
81
+ export function askHumanSettlementLine(settled, lang) {
82
+ const kind = ownSlot(settled, 'kind');
83
+ if (kind === 'accepted-not-resolved')
84
+ return askAcceptedLine(settled, lang);
85
+ if (kind === 'expired-reaped')
86
+ return renderMessage(msg('approval.settleHuman.expiredReaped'), lang);
87
+ if (kind === 'settled-elsewhere')
88
+ return renderMessage(msg('approval.settleHuman.settledElsewhere'), lang);
89
+ if (kind !== 'resumed')
90
+ return undefined;
91
+ const decision = ownSlot(settled, 'decision');
92
+ const what = msg(decision === 'approve' ? 'approval.settle.what.approved' : decision === 'deny' ? 'approval.settle.what.denied' : 'approval.settle.what.answered');
93
+ const rawTask = ownSlot(settled, 'taskId');
94
+ const shownTask = typeof rawTask === 'string' ? guardedRead(() => displayUntrusted(rawTask, { max: TASK_ID_MAX, blanks: true })) : undefined;
95
+ const where = shownTask === undefined || shownTask === '' ? '' : msg('approval.settle.where', { task: shownTask });
96
+ const executed = ownSlot(settled, 'executed');
97
+ const tail = executed === 'allowed' || executed === 'denied' ? msg(EXECUTED_TAIL_KEYS[executed]) : '';
98
+ return renderMessage(msg(ownSlot(settled, 'late') === false ? 'approval.settleHuman.resumed' : 'approval.settleHuman.resumedLate', { what, where, tail }), lang);
99
+ }
@@ -1,5 +1,6 @@
1
1
  import { type CoreModeArbitrationRow } from '../generated/engineFactTables.js';
2
2
  import { CORE_ASK_FACES } from '../generated/engineAskFaceTables.js';
3
+ import type { UiLanguage } from '../env/uiLanguage.js';
3
4
  export type AutomaticAnswerLane = 'mode_posture' | 'standing_rule' | 'permission_request_hook';
4
5
  export type AutomaticAnswerAskFace = (typeof CORE_ASK_FACES)[number];
5
6
  export interface AutomaticAnswerFacts {
@@ -19,9 +20,9 @@ export type AutomaticAnswerVerdict = {
19
20
  readonly kind: 'unknown';
20
21
  readonly why: AutomaticAnswerUnknownWhy;
21
22
  };
22
- export declare const MODE_ARBITRATION: Readonly<Record<"hook" | "write_protection" | "mode" | "rule_unreadable" | "target_unresolved" | "content_question" | "ancestor" | "dangerous_delete" | "unverifiable_delete" | "unverifiable_shell_text" | "transcript_write" | "org_rule" | "governance_unavailable" | "ask_rule" | "denial_limit_fallback" | "classifier_no_ruling" | "requires_user_interaction" | "operator_forced" | "shell_floor" | "probe" | "tool_marks_mcp" | "tool_marks_a2a" | "policy_rra" | "artifact_shared_read" | "unstated" | "ordinary", CoreModeArbitrationRow>>;
23
+ export declare const MODE_ARBITRATION: Readonly<Record<"hook" | "write_protection" | "mode" | "target_unresolved" | "content_question" | "ancestor" | "dangerous_delete" | "unverifiable_delete" | "unverifiable_shell_text" | "transcript_write" | "org_rule" | "rule_unreadable" | "ask_rule" | "denial_limit_fallback" | "classifier_no_ruling" | "requires_user_interaction" | "operator_forced" | "shell_floor" | "probe" | "tool_marks_mcp" | "tool_marks_a2a" | "policy_rra" | "artifact_shared_read" | "unstated" | "ordinary", CoreModeArbitrationRow>>;
23
24
  export declare function foldModeArbitrationRow(classes: Iterable<string>, askFace?: AutomaticAnswerAskFace): CoreModeArbitrationRow;
24
25
  export declare function automaticAnswerVerdict(card: object | null | undefined, lane: AutomaticAnswerLane, facts?: AutomaticAnswerFacts | null): AutomaticAnswerVerdict;
25
- export declare function mandatedApprovalDetailOf(card: object | null | undefined): string;
26
+ export declare function mandatedApprovalDetailOf(card: object | null | undefined, lang?: UiLanguage): string;
26
27
  export type PermissionRequestHookScope = 'allow_or_deny' | 'deny_only' | 'skip';
27
28
  export declare function permissionRequestHookScope(verdict: AutomaticAnswerVerdict | null | undefined): PermissionRequestHookScope;