@sema-agent/client-core 0.77.0 → 0.77.2
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.
- package/CHANGELOG.md +23 -1
- package/README.md +5 -4
- package/dist/abortableSleep.d.ts +0 -28
- package/dist/abortableSleep.js +0 -28
- package/dist/adapt/arms.d.ts +0 -46
- package/dist/adapt/arms.js +9 -544
- package/dist/adapt/ids.d.ts +0 -58
- package/dist/adapt/ids.js +0 -63
- package/dist/adapt/instanceLedger.d.ts +0 -25
- package/dist/adapt/instanceLedger.js +0 -20
- package/dist/adapt/panelTasks.d.ts +0 -69
- package/dist/adapt/panelTasks.js +0 -95
- package/dist/adapt/textSegmentAuthority.d.ts +1 -137
- package/dist/adapt/textSegmentAuthority.js +0 -54
- package/dist/adapt/textStream.d.ts +0 -252
- package/dist/adapt/textStream.js +2 -281
- package/dist/adapt/toolCards.d.ts +0 -46
- package/dist/adapt/toolCards.js +0 -23
- package/dist/adapt/turnFlags.d.ts +0 -54
- package/dist/adapt/turnFlags.js +1 -17
- package/dist/adapt/wireShapes.d.ts +0 -92
- package/dist/adapt/wireShapes.js +0 -83
- package/dist/adapt.d.ts +0 -55
- package/dist/adapt.js +1 -120
- package/dist/adapter/activeRunSelfHeal.d.ts +22 -515
- package/dist/adapter/activeRunSelfHeal.js +10 -625
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -305
- package/dist/adapter/downstream/eventToSdkMessage.js +2 -867
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +2 -314
- package/dist/adapter/downstream/terminalToSdkResult.js +13 -560
- package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +0 -95
- package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -31
- package/dist/adapter/runStream.d.ts +0 -206
- package/dist/adapter/runStream.js +6 -596
- package/dist/adapter/types.d.ts +0 -111
- package/dist/adapter/types.js +0 -29
- package/dist/agentSession/backgroundView.d.ts +0 -106
- package/dist/agentSession/backgroundView.js +3 -49
- package/dist/agentSession/contract.d.ts +0 -98
- package/dist/agentSession/contract.js +0 -12
- package/dist/agentsWireCaps.d.ts +0 -72
- package/dist/agentsWireCaps.js +4 -72
- package/dist/approvalsStreamLiveCapability.d.ts +0 -25
- package/dist/approvalsStreamLiveCapability.js +0 -31
- package/dist/argvFlagValue.d.ts +0 -33
- package/dist/argvFlagValue.js +3 -35
- package/dist/attachmentsWireCaps.d.ts +0 -127
- package/dist/attachmentsWireCaps.js +0 -144
- package/dist/autoModeUnavailable.d.ts +0 -120
- package/dist/autoModeUnavailable.js +0 -144
- package/dist/classifierStatus.d.ts +0 -72
- package/dist/classifierStatus.js +0 -167
- package/dist/classifierVerdictWire.d.ts +0 -54
- package/dist/classifierVerdictWire.js +0 -133
- package/dist/clientContextWireCaps.d.ts +0 -37
- package/dist/clientContextWireCaps.js +0 -36
- package/dist/clientSlice.d.ts +0 -63
- package/dist/clientSlice.js +0 -45
- package/dist/cloudConfigWireCaps.d.ts +0 -86
- package/dist/cloudConfigWireCaps.js +2 -65
- package/dist/compensations.d.ts +0 -52
- package/dist/compensations.js +2 -63
- package/dist/controlRouter.d.ts +2 -208
- package/dist/controlRouter.js +1 -129
- package/dist/coreValuePorts.d.ts +0 -84
- package/dist/coreValuePorts.js +0 -29
- package/dist/decideReceipt.d.ts +0 -110
- package/dist/decideReceipt.js +0 -84
- package/dist/detachWire.d.ts +0 -130
- package/dist/detachWire.js +1 -130
- package/dist/deviceExecutorManagementCapability.d.ts +2 -35
- package/dist/deviceExecutorManagementCapability.js +1 -37
- package/dist/diagnostics.d.ts +0 -8
- package/dist/diagnostics.js +0 -8
- package/dist/diff/patch.d.ts +0 -17
- package/dist/diff/patch.js +0 -19
- package/dist/effectiveFacts.d.ts +0 -40
- package/dist/effectiveFacts.js +0 -22
- package/dist/effortWire.d.ts +0 -11
- package/dist/effortWire.js +0 -12
- package/dist/engineAgentPanelStore.d.ts +0 -169
- package/dist/engineAgentPanelStore.js +13 -293
- package/dist/engineCapReader.d.ts +0 -62
- package/dist/engineCapReader.js +1 -43
- package/dist/engineCapsCache.d.ts +0 -177
- package/dist/engineCapsCache.js +0 -199
- package/dist/engineCapsGenerationGuard.d.ts +0 -2
- package/dist/engineCapsGenerationGuard.js +0 -11
- package/dist/engineErrorCodes.d.ts +1 -316
- package/dist/engineErrorCodes.js +0 -427
- package/dist/engineHttpTools.d.ts +0 -29
- package/dist/engineHttpTools.js +0 -29
- package/dist/engineIdentity.d.ts +0 -83
- package/dist/engineIdentity.js +0 -88
- package/dist/engineInlineTaskStats.d.ts +0 -57
- package/dist/engineInlineTaskStats.js +1 -42
- package/dist/engineNoticeCodes.d.ts +0 -190
- package/dist/engineNoticeCodes.js +0 -182
- package/dist/engineSessionParam.d.ts +0 -30
- package/dist/engineSessionParam.js +0 -52
- package/dist/engineToolLabelStore.d.ts +0 -29
- package/dist/engineToolLabelStore.js +0 -31
- package/dist/engineWireSdk.d.ts +0 -90
- package/dist/engineWireSdk.js +0 -74
- package/dist/engineWireTarget.d.ts +0 -14
- package/dist/engineWireTarget.js +0 -39
- package/dist/env/localeGeo.d.ts +0 -12
- package/dist/env/localeGeo.js +2 -77
- package/dist/env/localeTag.d.ts +0 -34
- package/dist/env/localeTag.js +0 -32
- package/dist/env/uiLanguage.d.ts +0 -13
- package/dist/env/uiLanguage.js +0 -25
- package/dist/envFlag.d.ts +0 -37
- package/dist/envFlag.js +0 -40
- package/dist/executionLaneCapability.d.ts +0 -48
- package/dist/executionLaneCapability.js +0 -54
- package/dist/finalVerifyWire.d.ts +0 -67
- package/dist/finalVerifyWire.js +3 -43
- package/dist/fleet/fleetLedger.d.ts +0 -308
- package/dist/fleet/fleetLedger.js +10 -429
- package/dist/fleet/fleetProjection.d.ts +0 -240
- package/dist/fleet/fleetProjection.js +0 -189
- package/dist/fleet/fleetRowAgentType.d.ts +0 -6
- package/dist/fleet/fleetRowAgentType.js +1 -32
- package/dist/fleet/workflowSizeWarning.d.ts +0 -47
- package/dist/fleet/workflowSizeWarning.js +1 -46
- package/dist/fleetAgentPanelProjection.d.ts +0 -48
- package/dist/fleetAgentPanelProjection.js +8 -173
- package/dist/fleetTaskDesc.d.ts +0 -39
- package/dist/fleetTaskDesc.js +0 -69
- package/dist/forkWireCaps.d.ts +0 -23
- package/dist/forkWireCaps.js +1 -24
- package/dist/gateOutcome.d.ts +0 -140
- package/dist/gateOutcome.js +0 -85
- package/dist/gateVocabulary.d.ts +0 -114
- package/dist/gateVocabulary.js +1 -161
- package/dist/goalStopHook.d.ts +0 -127
- package/dist/goalStopHook.js +0 -178
- package/dist/headlessPermissionModeWire.d.ts +0 -76
- package/dist/headlessPermissionModeWire.js +1 -155
- package/dist/headlessReconnectWire.d.ts +0 -84
- package/dist/headlessReconnectWire.js +13 -67
- package/dist/hitl/approvalDecisionNoteAudit.d.ts +0 -49
- package/dist/hitl/approvalDecisionNoteAudit.js +0 -56
- package/dist/hitl/approvalOutcomeNote.d.ts +0 -2
- package/dist/hitl/approvalOutcomeNote.js +0 -20
- package/dist/hitl/approvalResolution.d.ts +0 -113
- package/dist/hitl/approvalResolution.js +0 -66
- package/dist/hitl/approvalsFeed.d.ts +0 -183
- package/dist/hitl/approvalsFeed.js +12 -243
- package/dist/hitl/armedGateRegistry.d.ts +0 -55
- package/dist/hitl/armedGateRegistry.js +0 -146
- package/dist/hitl/askGateWire.d.ts +0 -86
- package/dist/hitl/askGateWire.js +1 -95
- package/dist/hitl/askParkRowRouting.d.ts +0 -123
- package/dist/hitl/askParkRowRouting.js +1 -89
- package/dist/hitl/crashConverged.d.ts +0 -148
- package/dist/hitl/crashConverged.js +0 -214
- package/dist/hitl/editedRuleTextPrecheck.d.ts +0 -109
- package/dist/hitl/editedRuleTextPrecheck.js +0 -71
- package/dist/hitl/frameRouter.d.ts +0 -134
- package/dist/hitl/frameRouter.js +6 -378
- package/dist/hitl/gateIdentity.d.ts +0 -39
- package/dist/hitl/gateIdentity.js +0 -41
- package/dist/hitl/gateLedger.d.ts +0 -267
- package/dist/hitl/gateLedger.js +0 -121
- package/dist/hitl/hitlBridge.d.ts +7 -431
- package/dist/hitl/hitlBridge.js +7 -476
- package/dist/hitl/hitlHostSurface.d.ts +0 -150
- package/dist/hitl/hitlHostSurface.js +0 -169
- package/dist/hitl/livePendingAsk.d.ts +0 -91
- package/dist/hitl/livePendingAsk.js +0 -74
- package/dist/hitl/localAllowRule.d.ts +0 -62
- package/dist/hitl/localAllowRule.js +1 -33
- package/dist/hitl/parkOwnership.d.ts +0 -56
- package/dist/hitl/parkOwnership.js +0 -22
- package/dist/hitl/parkResolver.d.ts +3 -88
- package/dist/hitl/parkResolver.js +8 -349
- package/dist/hitl/parkRowBirthWait.d.ts +2 -26
- package/dist/hitl/parkRowBirthWait.js +3 -93
- package/dist/hitl/persistedRulesWire.d.ts +13 -358
- package/dist/hitl/persistedRulesWire.js +0 -310
- package/dist/hitl/planReviewWire.d.ts +4 -176
- package/dist/hitl/planReviewWire.js +9 -312
- package/dist/hitl/resumeRunningCard.d.ts +0 -105
- package/dist/hitl/resumeRunningCard.js +0 -105
- package/dist/hitl/sessionPolicyWire.d.ts +11 -191
- package/dist/hitl/sessionPolicyWire.js +0 -149
- package/dist/hitl/suspendedReopen.d.ts +3 -24
- package/dist/hitl/suspendedReopen.js +0 -14
- package/dist/hitl/toolApprovalWire.d.ts +5 -1308
- package/dist/hitl/toolApprovalWire.js +5 -945
- package/dist/hooksWireCaps.d.ts +0 -38
- package/dist/hooksWireCaps.js +0 -190
- package/dist/host.d.ts +0 -105
- package/dist/host.js +0 -33
- package/dist/hostEnv.d.ts +0 -14
- package/dist/hostEnv.js +0 -13
- package/dist/imagesWireCaps.d.ts +0 -21
- package/dist/imagesWireCaps.js +0 -22
- package/dist/index.d.ts +0 -134
- package/dist/index.js +0 -476
- package/dist/interactiveHalt.d.ts +5 -153
- package/dist/interactiveHalt.js +0 -111
- package/dist/interactiveToolsWire.d.ts +0 -62
- package/dist/interactiveToolsWire.js +1 -67
- package/dist/leaderConflict.d.ts +0 -59
- package/dist/leaderConflict.js +0 -48
- package/dist/limitsWire.d.ts +0 -125
- package/dist/limitsWire.js +2 -120
- package/dist/liveInitToolFace.d.ts +0 -77
- package/dist/liveInitToolFace.js +1 -109
- package/dist/liveModelCatalog.d.ts +0 -52
- package/dist/liveModelCatalog.js +0 -48
- package/dist/liveQuestionStore.d.ts +0 -87
- package/dist/liveQuestionStore.js +1 -56
- package/dist/mcpLiveness.d.ts +0 -151
- package/dist/mcpLiveness.js +0 -122
- package/dist/mcpPanel.d.ts +0 -104
- package/dist/mcpPanel.js +0 -49
- package/dist/mcpReconnect.d.ts +0 -58
- package/dist/mcpReconnect.js +1 -69
- package/dist/mcpWireCaps.d.ts +0 -55
- package/dist/mcpWireCaps.js +1 -13
- package/dist/memoryComplianceCapability.d.ts +3 -57
- package/dist/memoryComplianceCapability.js +0 -57
- package/dist/memoryEntriesWire.d.ts +6 -198
- package/dist/memoryEntriesWire.js +0 -144
- package/dist/memoryOriginCapability.d.ts +3 -53
- package/dist/memoryOriginCapability.js +0 -50
- package/dist/memorySpecWire.d.ts +0 -116
- package/dist/memorySpecWire.js +0 -150
- package/dist/model/catalog.d.ts +0 -111
- package/dist/model/catalog.js +0 -87
- package/dist/model/catalogLoader.d.ts +0 -114
- package/dist/model/catalogLoader.js +2 -139
- package/dist/model/modelSupplyRules.d.ts +1 -55
- package/dist/model/modelSupplyRules.js +0 -62
- package/dist/model/providerAuth.d.ts +0 -103
- package/dist/model/providerAuth.js +2 -38
- package/dist/model/providerCatalog.d.ts +0 -45
- package/dist/model/providerCatalog.js +0 -37
- package/dist/model/providerPresets.d.ts +0 -33
- package/dist/model/providerPresets.js +2 -91
- package/dist/model/tierVocabulary.d.ts +0 -31
- package/dist/model/tierVocabulary.js +0 -27
- package/dist/modelBudgetRule.d.ts +0 -39
- package/dist/modelBudgetRule.js +0 -39
- package/dist/modelCapabilityProbe.d.ts +0 -175
- package/dist/modelCapabilityProbe.js +0 -147
- package/dist/modelWireCaps.d.ts +0 -13
- package/dist/modelWireCaps.js +0 -13
- package/dist/notifications.d.ts +0 -233
- package/dist/notifications.js +14 -492
- package/dist/oneShotWireCaps.d.ts +0 -34
- package/dist/oneShotWireCaps.js +0 -35
- package/dist/ownKey.d.ts +0 -33
- package/dist/ownKey.js +0 -33
- package/dist/panelRunningHistory.d.ts +0 -28
- package/dist/panelRunningHistory.js +0 -43
- package/dist/peerFrames.d.ts +0 -71
- package/dist/peerFrames.js +0 -168
- package/dist/peerLaneCapability.d.ts +0 -44
- package/dist/peerLaneCapability.js +0 -52
- package/dist/permissionRuleIssue.d.ts +0 -30
- package/dist/permissionRuleIssue.js +0 -78
- package/dist/permissionRulesWriteCapability.d.ts +0 -46
- package/dist/permissionRulesWriteCapability.js +0 -54
- package/dist/permissionWireCaps.d.ts +0 -37
- package/dist/permissionWireCaps.js +0 -37
- package/dist/postureKnob.d.ts +0 -71
- package/dist/postureKnob.js +0 -86
- package/dist/principalWire.d.ts +0 -17
- package/dist/principalWire.js +0 -17
- package/dist/printToolResultFrame.d.ts +0 -100
- package/dist/printToolResultFrame.js +0 -33
- package/dist/promptProfileWireCaps.d.ts +0 -13
- package/dist/promptProfileWireCaps.js +0 -13
- package/dist/readFacePosture.d.ts +0 -43
- package/dist/readFacePosture.js +0 -46
- package/dist/request/printNotification.d.ts +0 -20
- package/dist/request/printNotification.js +0 -55
- package/dist/request/taskRequest.d.ts +0 -249
- package/dist/request/taskRequest.js +10 -496
- package/dist/resumeRefusalCopy.d.ts +0 -136
- package/dist/resumeRefusalCopy.js +1 -117
- package/dist/retainBackgroundWireCaps.d.ts +0 -48
- package/dist/retainBackgroundWireCaps.js +0 -48
- package/dist/retryStatus.d.ts +2 -221
- package/dist/retryStatus.js +0 -107
- package/dist/rewindWireCaps.d.ts +0 -27
- package/dist/rewindWireCaps.js +0 -24
- package/dist/runCancelContext.d.ts +1 -20
- package/dist/runCancelContext.js +0 -34
- package/dist/runTerminal.d.ts +0 -273
- package/dist/runTerminal.js +0 -177
- package/dist/sandboxWire.d.ts +0 -38
- package/dist/sandboxWire.js +0 -82
- package/dist/scenarioWire.d.ts +0 -60
- package/dist/scenarioWire.js +0 -68
- package/dist/scratchpadWireCaps.d.ts +0 -11
- package/dist/scratchpadWireCaps.js +0 -32
- package/dist/sdkWireTransit.d.ts +0 -38
- package/dist/sdkWireTransit.js +0 -30
- package/dist/seam.d.ts +18 -853
- package/dist/seam.js +0 -52
- package/dist/seatContract.d.ts +0 -555
- package/dist/seatContract.js +5 -304
- package/dist/selfOrchestrationDenial.d.ts +0 -189
- package/dist/selfOrchestrationDenial.js +0 -162
- package/dist/selfOrchestrationWireCaps.d.ts +0 -38
- package/dist/selfOrchestrationWireCaps.js +0 -38
- package/dist/sessionMap.d.ts +0 -60
- package/dist/sessionMap.js +0 -37
- package/dist/sessionMemoryStatus.d.ts +11 -114
- package/dist/sessionMemoryStatus.js +0 -112
- package/dist/sessionModelLatch.d.ts +0 -29
- package/dist/sessionModelLatch.js +0 -40
- package/dist/sessionPolicyCapability.d.ts +3 -53
- package/dist/sessionPolicyCapability.js +0 -52
- package/dist/sessionSlot.d.ts +0 -26
- package/dist/sessionSlot.js +0 -17
- package/dist/skillsWireCaps.d.ts +0 -87
- package/dist/skillsWireCaps.js +0 -38
- package/dist/sqlEngineCapability.d.ts +0 -118
- package/dist/sqlEngineCapability.js +0 -134
- package/dist/sseIdleTriage.d.ts +0 -79
- package/dist/sseIdleTriage.js +1 -80
- package/dist/steering.d.ts +0 -54
- package/dist/steering.js +0 -63
- package/dist/subagent/engineCompactWire.d.ts +0 -34
- package/dist/subagent/engineCompactWire.js +4 -134
- package/dist/subagent/engineDelegatedPrompt.d.ts +0 -31
- package/dist/subagent/engineDelegatedPrompt.js +1 -103
- package/dist/subagent/engineRowStopGate.d.ts +0 -20
- package/dist/subagent/engineRowStopGate.js +0 -49
- package/dist/subagent/engineSubagentOutput.d.ts +0 -7
- package/dist/subagent/engineSubagentOutput.js +1 -51
- package/dist/subagent/engineSubagentResume.d.ts +2 -279
- package/dist/subagent/engineSubagentResume.js +2 -129
- package/dist/subagent/engineSubagentSteer.d.ts +0 -26
- package/dist/subagent/engineSubagentSteer.js +0 -63
- package/dist/subagent/engineSubagentTail.d.ts +0 -38
- package/dist/subagent/engineSubagentTail.js +2 -110
- package/dist/subagent/engineTaskHandleWire.d.ts +11 -65
- package/dist/subagent/engineTaskHandleWire.js +20 -131
- package/dist/subagent/subagentOwnerAbsence.d.ts +0 -2
- package/dist/subagent/subagentOwnerAbsence.js +0 -25
- package/dist/subagentContentStore.d.ts +3 -260
- package/dist/subagentContentStore.js +7 -540
- package/dist/systemReminderTag.d.ts +0 -49
- package/dist/systemReminderTag.js +0 -61
- package/dist/toolResult.d.ts +1 -211
- package/dist/toolResult.js +1 -358
- package/dist/toolRoster.d.ts +0 -140
- package/dist/toolRoster.js +0 -66
- package/dist/typePins.d.ts +0 -46
- package/dist/types/engineState.d.ts +0 -71
- package/dist/types/engineState.js +0 -16
- package/dist/ultracodeWireCaps.d.ts +0 -75
- package/dist/ultracodeWireCaps.js +0 -92
- package/dist/unrefTimer.d.ts +0 -27
- package/dist/webSearchBackendCapability.d.ts +0 -72
- package/dist/webSearchBackendCapability.js +0 -79
- package/dist/webSearchWireCaps.d.ts +0 -37
- package/dist/webSearchWireCaps.js +0 -34
- package/dist/websearch/searchProviderPresets.d.ts +0 -81
- package/dist/websearch/searchProviderPresets.js +0 -27
- package/dist/wireErrorTriage.d.ts +4 -160
- package/dist/wireErrorTriage.js +0 -171
- package/dist/wireRefusalCopy.d.ts +0 -28
- package/dist/wireRefusalCopy.js +0 -28
- package/dist/workflow.d.ts +0 -40
- package/dist/workflow.js +0 -52
- package/dist/workflowClient.d.ts +0 -122
- package/dist/workflowClient.js +8 -360
- package/dist/workflowMonitor.d.ts +2 -72
- package/dist/workflowMonitor.js +0 -26
- package/dist/writeProtectionCapability.d.ts +0 -112
- package/dist/writeProtectionCapability.js +0 -109
- package/docs/INTEGRATION-CLIENTS.md +62 -1
- package/package.json +1 -1
|
@@ -1,152 +1,29 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* hitl/askParkRowRouting.ts — ask park(`suspended`)重开链的**纯判定层**(#265 上收件,
|
|
3
|
-
* 2026-08-14;源形 = cli `src/sema/askParkReopen.ts` 的判据半场,该文件的呈现/决断编排留在端上)。
|
|
4
|
-
*
|
|
5
|
-
* 三端(cli / desktop / web)重开一张 ask park 的卡时,要按同一套判据回答四个问题;本文件是这
|
|
6
|
-
* 四问的唯一真源,**一个渲染面都不碰**(帧/卡口/HitlBridge 全在调用方):
|
|
7
|
-
* ① 「此刻队列里有没有一行**该由本臂决**的行?」 → {@link classifyAskParkRows}(三态)
|
|
8
|
-
* ② 「这一行的身份键是什么?」 → {@link askParkRowIdentity}
|
|
9
|
-
* ③ 「这一行该走问答臂还是工具门臂?」 → {@link askParkRowArm}
|
|
10
|
-
* ④ 「链跑砸了、而行已不在表 —— 这是已决还是没轮到?」 → {@link classifyAskParkChainFailure}
|
|
11
|
-
* 外加一件构造保证:同一行的并发重开**合流**成一次({@link createRowArmSingleFlight})。
|
|
12
|
-
*
|
|
13
|
-
* ── ① 三态与证据纪律(cli #269 的整个要点)────────────────────────────────────────────────────
|
|
14
|
-
* `/v1/approvals` 是 **scope 级全量单队列**:child 委派的 park 行 `taskId` = child 自己的 run id,
|
|
15
|
-
* 所以「按 busy 信号点名的 taskId 单键过滤」会结构性漏看。发现面 = 全量取回 → 先找点名行 →
|
|
16
|
-
* 没有时**在队列无歧义(恰一行)且该行归属可正向证明**的前提下兜底。
|
|
17
|
-
* 🔴 分态只有一条纪律:**只有正面证据才配 `settled`**。
|
|
18
|
-
* · 空表 / 多行无点名行 / 唯一行归属证明不了 ⇒ 一律 `unborn`(缺席证明不了任何事;这三种形都
|
|
19
|
-
* 可能在下一拍变成「我的那一行出生了」——引擎正在跑那次决定 Write 参数的模型调用);
|
|
20
|
-
* · 行在、但门种不属 ask 门族 ⇒ 也只给 `unborn`。「看得见的这一行不属本臂」与「这里已经没有本臂
|
|
21
|
-
* 该决的事」是两件事,而门换代窗恰恰会短暂两者同形(plan_review 行在 decide 落地后还能被读到
|
|
22
|
-
* 一小会儿,接替它的 human/tool_approval 行尚未出生)。把这一拍读成终判 = 把失败形换个姿势
|
|
23
|
-
* 原样复现。代价(如实记):真·走错臂时要等满有界窗才说那句诚实话。
|
|
24
|
-
* ⇒ 本函数**今天一条 `settled` 都不产**,这是成文结论不是遗漏:队列读面给得出的一切都只是缺席类
|
|
25
|
-
* 证据。`settled` 留在 {@link ParkRowProbe} 契约里给**读面更强**的宿主(注入 gate 实例态/wire
|
|
26
|
-
* 直供门身份)用 —— 那时「已了结」才是拿得出正面证据的判决。
|
|
27
|
-
*
|
|
28
|
-
* ── ③ 行路由:锚在**决定量**上,不锚门种的名字 ───────────────────────────────────────────────
|
|
29
|
-
* 🔴 `gateKind === 'human'` **不是**「这是 AskUserQuestion」的证据(engine 7.18.0 真 wire 直证):
|
|
30
|
-
* plan 批准之后铸出的 **Write** 审批行带的就是 `gateKind:"human" · toolName:"Write" ·
|
|
31
|
-
* input:{file_path,content}`。`human` 在引擎侧是**泛化的「要人来决定」**(本包 `hitlBridge.observe`
|
|
32
|
-
* 对 `gate:null` 的补形同样是 `{kind:'human'}`),它与 `tool_approval` 是「粗粒度 / 细粒度」的关系,
|
|
33
|
-
* 不是「问答 / 工具」的二分。把 `human` 单义化成问答臂,那一行就会被送进没有问句 payload 的臂 ⇒
|
|
34
|
-
* 静默失败 ⇒ write 卡永不呈现。问答臂要的东西是**问句**,那就问「这行到底有没有问句」。
|
|
35
|
-
*
|
|
36
|
-
* ── 归层 ────────────────────────────────────────────────────────────────────────────────────
|
|
37
|
-
* 本文件值级 import 全在包内(gateIdentity / parkOwnership / frameRouter / activeRunSelfHeal 词表),
|
|
38
|
-
* SDK 只 type-only;零宿主端口、零模块级状态(单活闸是**工厂**,寿命归调用方 —— 包不替宿主决定
|
|
39
|
-
* 那张表活多久)。
|
|
40
|
-
*/
|
|
41
1
|
import type { PendingCheckpoint } from '@sema-agent/sdk';
|
|
42
2
|
import type { ParkRowProbe } from './parkRowBirthWait.js';
|
|
43
3
|
import { type ParkOwnershipDeps } from './parkOwnership.js';
|
|
44
|
-
/**
|
|
45
|
-
* 待决行有界等待窗的**建议上限**(端可覆盖;`waitForParkRowBirth` 自己不带缺省)。
|
|
46
|
-
* 实测锚:plan 批准之后引擎要跑**一次真实模型调用**才算得出 Write 的参数、才把审批行落库 ——
|
|
47
|
-
* t+2500ms 读到的仍是空表,t+3000ms 行才出生。15s = 实测 3s 的 5 倍余量(慢模型/负载下的头部
|
|
48
|
-
* 延迟);超限如实收口 —— 到那一刻降级话是真话,这正是有界的意义。
|
|
49
|
-
* 🔴 代价如实记:真孤儿 park(座位占着、确实没有任何待决行)要等满这个窗才说那句诚实的失败话。
|
|
50
|
-
* 方向取舍 = 让**常见且可修**的那一态(行未出生)真的被接住,代价是**罕见且本就已坏**的那一态
|
|
51
|
-
* 多等一个有界窗;等待全程可被中断(signal 直通重查环)。
|
|
52
|
-
*/
|
|
53
4
|
export declare const ASK_PARK_ROW_WAIT_MS = 15000;
|
|
54
|
-
/** 重查节奏建议值。500ms 级:比行出生的量级(秒)细一个数量级,又不至于把本地引擎打成轮询风暴。 */
|
|
55
5
|
export declare const ASK_PARK_ROW_POLL_MS = 500;
|
|
56
|
-
/** {@link classifyAskParkRows} 的注入口(缺省 = 包内归属判据)。 */
|
|
57
6
|
export interface AskParkRowScanDeps {
|
|
58
|
-
/** 归属判据(缺省 = `pendingRowIsOwnedByThisSession`)。fail-CLOSED:证不出 = 不采信。 */
|
|
59
7
|
isOwned?: (row: PendingCheckpoint) => boolean;
|
|
60
|
-
/** 缺省归属判据的注入位(多会话宿主传 sessionKey / 自己的 currentSessionId)。 */
|
|
61
8
|
ownership?: ParkOwnershipDeps;
|
|
62
9
|
}
|
|
63
|
-
/**
|
|
64
|
-
* ① 「本臂此刻有没有一行可决断的行」——三态判决(见文件头)。**纯函数**:行由调用方读面取回,
|
|
65
|
-
* 本函数只判;绝不抛。
|
|
66
|
-
*
|
|
67
|
-
* @param rows `/v1/approvals` 全量 pending 行(scope 级单队列原样)
|
|
68
|
-
* @param taskId busy 信号点名的 run id(优先匹配它;匹配不到才谈兜底)
|
|
69
|
-
*/
|
|
70
10
|
export declare function classifyAskParkRows(rows: readonly PendingCheckpoint[], taskId: string, deps?: AskParkRowScanDeps): ParkRowProbe<PendingCheckpoint>;
|
|
71
|
-
/** ② 行身份三件套(重开链的一切键都从这里出;两处各算一遍必漂)。 */
|
|
72
11
|
export interface AskParkRowIdentity {
|
|
73
|
-
/** 🔴 行内身份绑定:decide 腿一律按**该行自己的** taskId 走,绝不绑请求者的 —— 兜底腿把别的行
|
|
74
|
-
* 解到请求者名下时,按请求者的 id 去决断就是决了另一件事。 */
|
|
75
12
|
rowTaskId: string;
|
|
76
13
|
gatedCallId: string | undefined;
|
|
77
|
-
/** 首见/复见 + 呈现回执的台账键(`gateIdentity.approvalCallKey` 单源,端零手抄字面)。 */
|
|
78
14
|
armedKey: string;
|
|
79
15
|
}
|
|
80
|
-
/** ② 算一行的身份三件套。`taskId` = 请求者点名的 id(行自己没带 taskId 时的回退)。 */
|
|
81
16
|
export declare function askParkRowIdentity(taskId: string, row: PendingCheckpoint): AskParkRowIdentity;
|
|
82
|
-
/**
|
|
83
|
-
* ③ 这一行该走哪条臂。判据锚在**决定量**(这行到底有没有问句)上,不锚门种的名字 —— 理由见文件头。
|
|
84
|
-
* · **toolName 明说是 ask 工具 ⇒ 问答臂,门种一律不再看**(0.60.0 补的**最先**一条,理由见函数体内注:
|
|
85
|
-
* 工具臂对这样一行会弹一张没有问句的卡、并送出不带 answer 的 approve —— 一次静默的错动作);
|
|
86
|
-
* · kind 缺席(pre-3.0.0 旧行)⇒ 维持 toolName 判据(旧行没有别的信号);
|
|
87
|
-
* · kind 是 ask 门族里 `human` 之外的词(tool_approval / irreversible_ask / policy_ask)⇒ 工具臂;
|
|
88
|
-
* · kind = `human` ⇒ 三选一命中即问答臂:toolName 明说是 ask 工具 / 行真带问句 payload /
|
|
89
|
-
* 行**连 toolName 都没有**(没有工具可渲,问答臂是唯一可能的形,且它自己会对空 payload 诚实收口)。
|
|
90
|
-
* 🔴 `toolName` 是 UNTRUSTED wire 位且 `/v1/approvals` 行不经工具名归一 —— 用包的规范判据
|
|
91
|
-
* {@link isAskTool}(空白/下划线/大小写不敏感),严格串比会把小写形误路由进工具臂。
|
|
92
|
-
*/
|
|
93
17
|
export declare function askParkRowArm(row: PendingCheckpoint): 'question' | 'tool-gate';
|
|
94
|
-
/**
|
|
95
|
-
* ④ 「这一行还在不在待决表里」——回读判据(键取法与 {@link askParkRowIdentity} 同源)。
|
|
96
|
-
* 🔴 调用方读面失败时**必须**当「还在」(保守:照走重试/上屏;重复 decide 由 server 侧 checkpoint
|
|
97
|
-
* 一次性消费挡住,二发只会得到 stale/no_pending 拒绝,不会 double-act)。
|
|
98
|
-
*/
|
|
99
18
|
export declare function askParkRowStillPending(rows: readonly PendingCheckpoint[], identity: AskParkRowIdentity): boolean;
|
|
100
|
-
/**
|
|
101
|
-
* ④ 链失败之后「行已不在 pending 表」的**两义分臂**判决。
|
|
102
|
-
* · `retry` —— 行还在表上 ⇒ 这就是一次真失败:照走重试 / 如实上屏;
|
|
103
|
-
* · `row-gone-after-card` —— 行没了 **且卡呈现过** ⇒ **静默收口**:零重试、零失败话、零成功断言。
|
|
104
|
-
* 🔴 名字刻意只说**可观察事实**(二次评审两轮处置):它不叫「已在别处决了」,因为呈现只证明卡
|
|
105
|
-
* 渲出来过,证明不了有人做过决定 —— 一个带决断语义的判决值会诱导宿主替引擎宣布成功。它成立的
|
|
106
|
-
* 判据是两件可观察事实的合取:队列回读说这一行已不在待决表(一次真读数,不是缺席推断),且本链
|
|
107
|
-
* 确实把卡交到过渲染面。处置的理由也只由这两件事推出:重试 = 对一个不在待决表的行再决一次
|
|
108
|
-
* (server 侧 checkpoint 一次性消费会拒),上屏「the session is still held」= 对一个已不在队列的
|
|
109
|
-
* 行说它还占着。🔴 宿主**不许**据此对用户断言「你的决定已生效」。残余(如实记):行在呈现窗里
|
|
110
|
-
* 被换代/过期而恰好没人决过时,这一格会把它按已收口处理 —— 代价是这一轮不再重开(用户下一条
|
|
111
|
-
* 消息会再撞 409,自愈腿重跑);要真的分出「已决」只能靠决断回执 / typed stale·conflict 应答那类
|
|
112
|
-
* **正面证据**,而那属于决断腿的供给面,不在本读面。
|
|
113
|
-
* 🔴 为什么不干脆退回 `row-unborn` 继续重查(二次评审 R3 [medium] 提议,**未采纳**,理由对称):
|
|
114
|
-
* 那会把**最常见的良性时序**(决断真落地 → 座位释放 → 队列从此空表)变成「白等满一个窗,然后
|
|
115
|
-
* 对用户说『没能重开那张卡』」—— 一句同样为假的话,而且它出现在事情**本来就成了**的那一格。
|
|
116
|
-
* 两个方向各有一次谎报风险,取舍按代价:本格的代价是这一轮不重开(下一条消息自愈腿重跑,可收敛),
|
|
117
|
-
* 对面的代价是每一次成功决断都附赠一句假失败 + 一个满窗停顿(每次都发生,不可收敛)。
|
|
118
|
-
* · `row-unborn` —— 行没了 **且一张卡都没呈上** ⇒ 没有任何人决过任何事,行消失只可能是
|
|
119
|
-
* 「刚才那一行换代了 / 下一只门的行还没铸出来」。此时按成功收口 = 对一件从没发生过的决断下
|
|
120
|
-
* 断言,而呈现回执永远等不到 ⇒ 用户拿到降级话,三秒后真的出生的那张卡再没人去接。这一格
|
|
121
|
-
* **不是失败**(不上失败话、不重试),交回有界重查环。
|
|
122
|
-
*
|
|
123
|
-
* 🔴 `cardPresented` 必须是**无窗的事实**(整条链寿命里的呈现事件订阅),不能拿带看门狗的呈现回执
|
|
124
|
-
* 近似:迟到卡会让带窗的那只回 false,于是一次真呈现被误判成「行从未出生」,重查环再铸一张卡 ⇒
|
|
125
|
-
* 同一个待决项两张可按的卡。
|
|
126
|
-
*/
|
|
127
19
|
export type AskParkChainFailureDisposition = 'retry' | 'row-gone-after-card' | 'row-unborn';
|
|
128
20
|
export declare function classifyAskParkChainFailure(i: {
|
|
129
21
|
rowStillPending: boolean;
|
|
130
22
|
cardPresented: boolean;
|
|
131
23
|
}): AskParkChainFailureDisposition;
|
|
132
|
-
/**
|
|
133
|
-
* **行级重开单活闸**:同一行(键 = {@link AskParkRowIdentity.armedKey})的第二个调用方**合流**到
|
|
134
|
-
* 在飞的那一次(拿逐字相同的判决),不另起一条链 —— 「一个待决项至多一张卡」由此是构造保证。
|
|
135
|
-
*
|
|
136
|
-
* 🔴 为什么按**行键**而不是请求者的 taskId:发现面的兜底腿会把**不同** taskId 的两个调用方解到
|
|
137
|
-
* **同一行**,那时两条链会各铸一张身份不同、都能按的卡 —— 同一个待决项两张卡,先按的决断、后按的
|
|
138
|
-
* 变成 stale 误导面。而重开臂的寿命一旦从毫秒级拉到一个秒级的有界重查窗,「结构上不容易撞上」就
|
|
139
|
-
* 不再是防线([paired-mechanisms]:两半各持「对方会兜底」的假设 = 零结果),必须在源头收掉。
|
|
140
|
-
*
|
|
141
|
-
* 🔴 **工厂,不是模块级台账**:这张表的寿命 = 宿主一个会话的重开面,由装配点持有;包不替宿主决定
|
|
142
|
-
* 它活多久,多会话宿主天然一会话一只(单例化反而会让两个会话互相合流)。
|
|
143
|
-
*/
|
|
144
24
|
export interface RowArmSingleFlight<T> {
|
|
145
|
-
/** 有在飞的同键链 ⇒ 返回它(第二个调用方零副作用);否则起一条并登记(结束后自动清账)。 */
|
|
146
25
|
join: (key: string, start: () => Promise<T>) => Promise<T>;
|
|
147
|
-
/** 当前在飞条数(诊断/测试用)。 */
|
|
148
26
|
size: () => number;
|
|
149
|
-
/** 清空(套件之间不许互相串态)。 */
|
|
150
27
|
clear: () => void;
|
|
151
28
|
}
|
|
152
29
|
export declare function createRowArmSingleFlight<T>(): RowArmSingleFlight<T>;
|
|
@@ -2,31 +2,11 @@ import { askParkForeignGateKind } 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';
|
|
5
|
-
/**
|
|
6
|
-
* 待决行有界等待窗的**建议上限**(端可覆盖;`waitForParkRowBirth` 自己不带缺省)。
|
|
7
|
-
* 实测锚:plan 批准之后引擎要跑**一次真实模型调用**才算得出 Write 的参数、才把审批行落库 ——
|
|
8
|
-
* t+2500ms 读到的仍是空表,t+3000ms 行才出生。15s = 实测 3s 的 5 倍余量(慢模型/负载下的头部
|
|
9
|
-
* 延迟);超限如实收口 —— 到那一刻降级话是真话,这正是有界的意义。
|
|
10
|
-
* 🔴 代价如实记:真孤儿 park(座位占着、确实没有任何待决行)要等满这个窗才说那句诚实的失败话。
|
|
11
|
-
* 方向取舍 = 让**常见且可修**的那一态(行未出生)真的被接住,代价是**罕见且本就已坏**的那一态
|
|
12
|
-
* 多等一个有界窗;等待全程可被中断(signal 直通重查环)。
|
|
13
|
-
*/
|
|
14
5
|
export const ASK_PARK_ROW_WAIT_MS = 15000;
|
|
15
|
-
/** 重查节奏建议值。500ms 级:比行出生的量级(秒)细一个数量级,又不至于把本地引擎打成轮询风暴。 */
|
|
16
6
|
export const ASK_PARK_ROW_POLL_MS = 500;
|
|
17
|
-
/**
|
|
18
|
-
* ① 「本臂此刻有没有一行可决断的行」——三态判决(见文件头)。**纯函数**:行由调用方读面取回,
|
|
19
|
-
* 本函数只判;绝不抛。
|
|
20
|
-
*
|
|
21
|
-
* @param rows `/v1/approvals` 全量 pending 行(scope 级单队列原样)
|
|
22
|
-
* @param taskId busy 信号点名的 run id(优先匹配它;匹配不到才谈兜底)
|
|
23
|
-
*/
|
|
24
7
|
export function classifyAskParkRows(rows, taskId, deps) {
|
|
25
8
|
const isOwned = deps?.isOwned ?? ((row) => pendingRowIsOwnedByThisSession(row, deps?.ownership));
|
|
26
9
|
const own = rows.find(r => r.taskId === taskId);
|
|
27
|
-
// 🔴 兜底纪律:只在**队列无歧义**(恰一行 pending)时才兜底 —— scope 级单队列上可能还躺着别的
|
|
28
|
-
// 会话/别的后台 lane 的行,多行并存时挑任何一行都证明不了归属,展示并决它 = 把无关审批递到这个
|
|
29
|
-
// 用户手上。歧义 ⇒ 本拍无行(交回有界重查环,窗尽才诚实失败)。
|
|
30
10
|
const sole = rows.length === 1 ? rows[0] : undefined;
|
|
31
11
|
const soleUnowned = sole !== undefined && !isOwned(sole);
|
|
32
12
|
const pending = own ?? (soleUnowned ? undefined : sole);
|
|
@@ -34,17 +14,13 @@ export function classifyAskParkRows(rows, taskId, deps) {
|
|
|
34
14
|
return {
|
|
35
15
|
kind: 'unborn',
|
|
36
16
|
reason: rows.length === 0
|
|
37
|
-
?
|
|
38
|
-
// 铸出来。两义分不开 ⇒ 按可修的那一义有界重查,窗尽才按前者如实收口。
|
|
17
|
+
?
|
|
39
18
|
`no pending row at all for task ${taskId} — either an orphan park (a seat held with no decision outstanding) or the next gate's row is not minted yet`
|
|
40
19
|
: soleUnowned
|
|
41
20
|
? `the only pending row (task ${String(sole?.taskId)} / session ${String(sole?.sessionId)}) could not be proven to belong to this client (not in its own-run ledger, session id absent or different) — refusing to surface an approval that may be another session's`
|
|
42
21
|
: `${String(rows.length)} pending rows but none for task ${taskId} — ambiguous queue, refusing to surface an unrelated row`,
|
|
43
22
|
};
|
|
44
23
|
}
|
|
45
|
-
// 行路由的门种闸:kind 在场但不在 ask 门族(plan_review / resource_limit / 未来新词)⇒ 拒绝入臂
|
|
46
|
-
// —— 对语义不属本臂的门驱动 `/decide` 比不重开更坏。判为 `unborn` 而非 `settled`,理由见文件头。
|
|
47
|
-
// 判据 = 包内单源 {@link askParkForeignGateKind}(`findPendingForTask` 的行过滤同一只,P-30)。
|
|
48
24
|
const foreignKind = askParkForeignGateKind(pending);
|
|
49
25
|
if (foreignKind !== null) {
|
|
50
26
|
return {
|
|
@@ -54,38 +30,17 @@ export function classifyAskParkRows(rows, taskId, deps) {
|
|
|
54
30
|
}
|
|
55
31
|
return { kind: 'row', row: pending };
|
|
56
32
|
}
|
|
57
|
-
/** 行上的门种(空串按缺席归一;缺席 = pre-`gate_kind` 的历史行,别当 `"human"`)。 */
|
|
58
33
|
function askParkRowGateKind(row) {
|
|
59
34
|
return typeof row.gateKind === 'string' && row.gateKind.length > 0 ? row.gateKind : null;
|
|
60
35
|
}
|
|
61
|
-
/** ② 算一行的身份三件套。`taskId` = 请求者点名的 id(行自己没带 taskId 时的回退)。 */
|
|
62
36
|
export function askParkRowIdentity(taskId, row) {
|
|
63
37
|
const rowTaskId = typeof row.taskId === 'string' && row.taskId.length > 0 ? row.taskId : taskId;
|
|
64
38
|
const gatedCallId = row.toolCallId ?? row.boundCallId ?? undefined;
|
|
65
39
|
return { rowTaskId, gatedCallId, armedKey: approvalCallKey(gatedCallId, rowTaskId) };
|
|
66
40
|
}
|
|
67
|
-
/**
|
|
68
|
-
* ③ 这一行该走哪条臂。判据锚在**决定量**(这行到底有没有问句)上,不锚门种的名字 —— 理由见文件头。
|
|
69
|
-
* · **toolName 明说是 ask 工具 ⇒ 问答臂,门种一律不再看**(0.60.0 补的**最先**一条,理由见函数体内注:
|
|
70
|
-
* 工具臂对这样一行会弹一张没有问句的卡、并送出不带 answer 的 approve —— 一次静默的错动作);
|
|
71
|
-
* · kind 缺席(pre-3.0.0 旧行)⇒ 维持 toolName 判据(旧行没有别的信号);
|
|
72
|
-
* · kind 是 ask 门族里 `human` 之外的词(tool_approval / irreversible_ask / policy_ask)⇒ 工具臂;
|
|
73
|
-
* · kind = `human` ⇒ 三选一命中即问答臂:toolName 明说是 ask 工具 / 行真带问句 payload /
|
|
74
|
-
* 行**连 toolName 都没有**(没有工具可渲,问答臂是唯一可能的形,且它自己会对空 payload 诚实收口)。
|
|
75
|
-
* 🔴 `toolName` 是 UNTRUSTED wire 位且 `/v1/approvals` 行不经工具名归一 —— 用包的规范判据
|
|
76
|
-
* {@link isAskTool}(空白/下划线/大小写不敏感),严格串比会把小写形误路由进工具臂。
|
|
77
|
-
*/
|
|
78
41
|
export function askParkRowArm(row) {
|
|
79
42
|
const rowGateKind = askParkRowGateKind(row);
|
|
80
43
|
const toolNameIsAsk = isAskTool(row.toolName ?? undefined);
|
|
81
|
-
// 🔴 **ask 工具身份优先于门种**(0.60.0,异源对抗复审 [medium] 采纳,真病):此前 `human` /
|
|
82
|
-
// `policy_ask` 之外的门种在读 toolName 之前就早退成工具臂,于是一行
|
|
83
|
-
// `gateKind:"irreversible_ask"` + `toolName:"AskUserQuestion"` 会被送进工具臂 —— 那条臂铸的卡
|
|
84
|
-
// **没有问句**、decide 送的是**不带 answer 的 approve**:一次静默的错动作(用户从没被问过,
|
|
85
|
-
// 引擎却收到了「批准」)。而本函数自己的判据就写着「问答臂要的东西是**问句**」——
|
|
86
|
-
// 一行 toolName 明说是 ask 工具时,那件事已经确定,门种再说什么都改不了它。
|
|
87
|
-
// ⚠️ 这也是与 `frameRouter` 那条 park 分流**同一个次序**(那里也是 ask 恒先判);两处次序一旦
|
|
88
|
-
// 不同,同一行在「谁来接」和「怎么决」两层上会得到相反的答案。
|
|
89
44
|
if (toolNameIsAsk)
|
|
90
45
|
return 'question';
|
|
91
46
|
if (rowGateKind === null)
|
|
@@ -95,29 +50,7 @@ export function askParkRowArm(row) {
|
|
|
95
50
|
const rowHasToolName = typeof row.toolName === 'string' && row.toolName.trim().length > 0;
|
|
96
51
|
return askQuestionsFromPending(row) !== null || !rowHasToolName ? 'question' : 'tool-gate';
|
|
97
52
|
}
|
|
98
|
-
/**
|
|
99
|
-
* 「泛化的**要人来决定**」那一族 kind —— 它们**不自带**「这是工具 / 这是问句」的答案,所以必须按
|
|
100
|
-
* 决定量(这行到底有没有问句)判臂;别的 ask 族 kind 自带答案,直接进工具臂。
|
|
101
|
-
*
|
|
102
|
-
* 逐条证据(engine 侧类型直读,不靠名字猜):
|
|
103
|
-
* · `human` —— core `CheckpointGate` 的 `{kind:'human', reason, toolName}`,而实测真 wire 上它同时
|
|
104
|
-
* 承载「Write 审批行」与「AskUserQuestion 行」两形(#269 的第二病就是把它单义化成问句)。
|
|
105
|
-
* · `policy_ask` —— 它是**决断信封**那一侧的名字:core `ResumeOutcome` 的
|
|
106
|
-
* `{gate:'policy_ask', boundCallId, boundInputHash, decision:'allow'|'deny', answer?: QuestionAnswer}`
|
|
107
|
-
* —— 那个 `answer?` 位就是**问句门也走这个信封**的直证。所以一行报 `policy_ask` 时同样两形皆可能,
|
|
108
|
-
* 按名字硬判工具臂 = `human` 那一病换个 kind 复发(二次评审 R3 [high] 命中)。
|
|
109
|
-
* · `irreversible_ask` 的 core 形是 `{kind, reason, toolName}`(toolName **必填**)、`tool_approval`
|
|
110
|
-
* 按定义就是工具审批 ⇒ 两者不进这张表,直接工具臂。
|
|
111
|
-
* ⚠️ **本表不再是路由的第一道判据**(0.60.0):`askParkRowArm` 现在**先**看 toolName 是不是 ask 工具。
|
|
112
|
-
* 本表回答的仍是「这个门种自不自带『工具/问句』的答案」,只是它在一行**明说自己是 ask 工具**时
|
|
113
|
-
* 已经不需要被问到了。
|
|
114
|
-
*/
|
|
115
53
|
const GENERIC_DECISION_GATE_KINDS = ['human', 'policy_ask'];
|
|
116
|
-
/**
|
|
117
|
-
* ④ 「这一行还在不在待决表里」——回读判据(键取法与 {@link askParkRowIdentity} 同源)。
|
|
118
|
-
* 🔴 调用方读面失败时**必须**当「还在」(保守:照走重试/上屏;重复 decide 由 server 侧 checkpoint
|
|
119
|
-
* 一次性消费挡住,二发只会得到 stale/no_pending 拒绝,不会 double-act)。
|
|
120
|
-
*/
|
|
121
54
|
export function askParkRowStillPending(rows, identity) {
|
|
122
55
|
return rows.some(r => identity.gatedCallId !== undefined
|
|
123
56
|
? (r.toolCallId ?? r.boundCallId ?? undefined) === identity.gatedCallId
|
|
@@ -130,25 +63,15 @@ export function classifyAskParkChainFailure(i) {
|
|
|
130
63
|
}
|
|
131
64
|
export function createRowArmSingleFlight() {
|
|
132
65
|
const inFlight = new Map();
|
|
133
|
-
/**
|
|
134
|
-
* 正在跑 `start()` 的键(只覆盖 start 的**同步执行窗**)。
|
|
135
|
-
* 🔴 它封的是最常见的那一形自依赖:`async () => { const v = await join(同键, …) ; … }` —— async
|
|
136
|
-
* 函数体在第一个 await 之前是**同步**跑的,那次 `join(同键)` 恰好落在这个窗里。不封它的话,外层
|
|
137
|
-
* run 会 settle 到一个反过来等 run 的 promise ⇒ 永不 settle,而这一行之后每一次重开都合流到它。
|
|
138
|
-
*/
|
|
139
66
|
const starting = new Set();
|
|
140
67
|
return {
|
|
141
68
|
join: (key, start) => {
|
|
142
69
|
if (starting.has(key)) {
|
|
143
|
-
// 前置条件被破(`start` 不许 join 自己的键)⇒ 当场拒绝,绝不交出一只会永久 pending 的 promise。
|
|
144
70
|
return Promise.reject(new Error(`row-arm single flight: start() re-entered join() for its own key while starting (${key})`));
|
|
145
71
|
}
|
|
146
72
|
const joined = inFlight.get(key);
|
|
147
73
|
if (joined !== undefined)
|
|
148
74
|
return joined;
|
|
149
|
-
// 🔴 **占位先于 start()**:直接 `const run = start()` 会让键在 start 跑完之前是空的,start
|
|
150
|
-
// 内部(或它同步触发的任何回调)再入同键就会另起第二条链 —— 同一个待决项两张卡,正是本闸
|
|
151
|
-
// 要封的那件事。先铸一只空 promise 占键,再把 start 的结果接进去。
|
|
152
75
|
let settle;
|
|
153
76
|
let fail;
|
|
154
77
|
const run = new Promise((resolve, reject) => {
|
|
@@ -156,8 +79,6 @@ export function createRowArmSingleFlight() {
|
|
|
156
79
|
fail = reject;
|
|
157
80
|
});
|
|
158
81
|
inFlight.set(key, run);
|
|
159
|
-
// 🔴 清账**认身份不认键**:`clear()` 之后同键可能已经起了新的一条,而旧链落地时那句无条件
|
|
160
|
-
// `delete(key)` 会把新链的登记抹掉 ⇒ 第三个调用方又能起一条,闸形同虚设。
|
|
161
82
|
const release = () => {
|
|
162
83
|
if (inFlight.get(key) === run)
|
|
163
84
|
inFlight.delete(key);
|
|
@@ -167,13 +88,6 @@ export function createRowArmSingleFlight() {
|
|
|
167
88
|
try {
|
|
168
89
|
const started = start();
|
|
169
90
|
if (started === run) {
|
|
170
|
-
// 🔴 自依赖 fail-fast(二次评审 R2 [high]):`start` 把占位 promise 原样交回来(典型形 = 它
|
|
171
|
-
// 自己又 join 了同一个键)⇒ run 会 resolve 到它自己,**永不 settle**,而这一行的后续每一次
|
|
172
|
-
// 重开都会合流到那只永久 pending 的 promise —— 死锁比多铸一张卡坏得多。
|
|
173
|
-
// 与它配对的另一半在 join 入口:`starting` 集合封住 `start` **同步执行窗**内的同键再入
|
|
174
|
-
// (async 函数体第一个 await 之前那段,正是 `await join(同键)` 的落点)。
|
|
175
|
-
// 残余(如实记):`start` 在**更晚的 tick**(已经 await 过别的东西之后)才 join 自己的键,
|
|
176
|
-
// 两道闸都判不出来 —— 那条只能靠调用协议:**`start` 不许 join 自己的键**。
|
|
177
91
|
fail?.(new Error('row-arm single flight: start() returned the in-flight placeholder for the same key'));
|
|
178
92
|
}
|
|
179
93
|
else {
|
|
@@ -181,8 +95,6 @@ export function createRowArmSingleFlight() {
|
|
|
181
95
|
}
|
|
182
96
|
}
|
|
183
97
|
catch (e) {
|
|
184
|
-
// start 同步抛 ⇒ 判决走**拒绝的 promise**(签名承诺的就是 Promise<T>),不是同步抛给调用方
|
|
185
|
-
// ——后者会让合流者与首发者拿到两种不同的失败形。
|
|
186
98
|
fail?.(e);
|
|
187
99
|
}
|
|
188
100
|
finally {
|
|
@@ -1,177 +1,29 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* crashConverged.ts — `GET /v1/approvals` 的 additive 键 `crashConverged` 的**三端公共读面**
|
|
3
|
-
* (L-38;server 7.55.0 起在场,fixture 直证坐标 `dist/boot/coordinators.js` 的 `GET /v1/approvals`
|
|
4
|
-
* 分支 + `dist/approval-ask-audit-store.d.ts` 的 `CrashConvergedRow`)。
|
|
5
|
-
*
|
|
6
|
-
* ## 这一格是什么(先把语义说准,文案才有得写)
|
|
7
|
-
* local 引擎在**人还挂在审批门上**的时候崩了:那一条 ask 既没被批也没被拒,进程一死就成了孤儿。
|
|
8
|
-
* server 重启后把这些孤儿**收敛成 DENIED 同码**(`decision:'denied'` + `cause:'crashed_before_park'`),
|
|
9
|
-
* 并把收敛结果作为一条 `crashConverged` 行挂在同一个 `/v1/approvals` 信封上。
|
|
10
|
-
* 对端(TUI / web / desktop)而言这是**上一条命的残留**:重连 / `--resume` 之后,人有权知道
|
|
11
|
-
* 「上次那次崩溃,把哪些审批替我拒掉了、其中哪几件可能已经落了一半副作用」。
|
|
12
|
-
*
|
|
13
|
-
* ## 两个桶的语义(端**唯一**需要分的那一刀)
|
|
14
|
-
* · `orphanState === 'pending'` = 崩的时候**工具一步都没执行**(还停在门上)。这一档配
|
|
15
|
-
* `resumeSafe === true` 时,重跑同一件事是安全的 ⇒ **resumeSafe 桶**。
|
|
16
|
-
* · `orphanState === 'decided'` = 人**当时已经批了 approve**,收敛把它翻成了 denied ——
|
|
17
|
-
* 可能有半截副作用落地了(文件写了一半 / 命令跑了一半)。⇒ **needsHuman 桶**,人工确认。
|
|
18
|
-
* · 其余一切(`resumeSafe === false`、字段自相矛盾、说不清的组合)一律进 **needsHuman**:
|
|
19
|
-
* 判**不**安全的代价是多问人一句(可恢复);判**错**安全的代价是让人闭眼重跑一件已经落过
|
|
20
|
-
* 副作用的事(不可恢复)。凡证不出来一律落保守侧。
|
|
21
|
-
*
|
|
22
|
-
* ## 🔴 caveat(DEBTS L-38 收执逐字,写文案前必读)
|
|
23
|
-
* `resumeSafe` 是**以账本完整为前提**算出来的**缺省值**,不是铁证 —— 崩溃现场本来就是账本最可能
|
|
24
|
-
* 缺页的时刻。⇒ 端的文案只许写「按记录看可以重跑」,**绝不**写「已确认没有副作用」。
|
|
25
|
-
* 同理:**键在场 ≠ 流内协议上场**。`crashConverged` 只是这一次 `list()` 回体上的一个 additive 键,
|
|
26
|
-
* 它既不宣示引擎具备什么能力,也不代表有一条推送通道会再告诉端第二次。别拿它当能力位读。
|
|
27
|
-
*
|
|
28
|
-
* ## 🔴 非目标与已知边界(对手模型成文,详见 `docs/INTEGRATION-CLIENTS.md` §12e)
|
|
29
|
-
* 真供给 = server JSON → SDK `JSON.parse` → 端:每一位都是**自有数据属性**,无代理、无 accessor、
|
|
30
|
-
* 原型恒 `Object.prototype`。**被中间层合成的非 JSON 载荷 / 敌意 `Proxy` / 原型注射**这一族**不在
|
|
31
|
-
* 射程内**:本件对它们只承诺三件 —— **不抛**、**不同步阻塞**、**绝不产出「可安全重跑」这个判决**
|
|
32
|
-
* (一律落 needsHuman 或 dropped);**不承诺**还原出「真实内容到底是什么」。一只代理在它唯一那次
|
|
33
|
-
* 被观察时就能给出假答案,而那与「宿主注入了一个会撒谎的传输层」是同一件事 —— 那种进程里每个对象
|
|
34
|
-
* 都不可信,本件不是能修好它的那一层。下面那一串防御的**唯一**目的是把这一族挡在「安全」判决之外
|
|
35
|
-
* 并保住线程,不是为了在敌意宿主上还原真相。
|
|
36
|
-
*
|
|
37
|
-
* ## 分工(与仓内既有形同款)
|
|
38
|
-
* **纯投影,零 IO、零 module 级可变态、零文案**:本件不构造 client、不认 baseUrl、不碰凭据,
|
|
39
|
-
* 也**一句面向用户的话都不铸** —— 措辞、是否上屏、排序与折叠全归端。
|
|
40
|
-
* 取件仍走既有的权威 `client.approvals.list()`(见 `hitlBridge.ts` 的 `ApprovalsResourceLike`),
|
|
41
|
-
* 本件只吃它的回体。
|
|
42
|
-
*/
|
|
43
1
|
import type { PendingCheckpoint } from '@sema-agent/sdk';
|
|
44
|
-
/** 孤儿行在崩溃那一刻的状态。`'pending'` = 工具零执行;`'decided'` = 人已批,可能有半截副作用。 */
|
|
45
2
|
export type CrashConvergedOrphanState = 'pending' | 'decided';
|
|
46
|
-
/**
|
|
47
|
-
* `GET /v1/approvals` 回体 `crashConverged[]` 的**逐形镜像**(server `CrashConvergedRow`)。
|
|
48
|
-
*
|
|
49
|
-
* 🔴 **本包刻意不从引擎侧 re-export 这个形**(与 `editedRuleTextPrecheck.ts` 头注同一条硬约束):
|
|
50
|
-
* `scripts/run-client-core-portability-test.mjs` 的 `EXPECTED_PACKAGES_INDEX` 是**等值门**,
|
|
51
|
-
* 包总入口闭包的外部包集合恒等于 `{diff, @sema-agent/sdk}`,多一个当场红;同门还拿 esbuild
|
|
52
|
-
* `--platform=browser` 真打一次包。为一个纯数据形把引擎焊进每一个装本包的端,代价与收益不成比例。
|
|
53
|
-
*
|
|
54
|
-
* 🔴 `decision` / `cause` 是**闭集字面量**,不是开集词表:这两位是本族行的**判别式** ——
|
|
55
|
-
* 收敛出来的行按定义就是「因为崩在 park 之前所以被判 denied」那一种。别的 `decision`/`cause`
|
|
56
|
-
* 组合不是「本族的新成员」,而是「这不是本族的行」⇒ 投影侧丢弃(见 {@link projectCrashConverged})。
|
|
57
|
-
* (对比:`engineErrorCodes` 那批 `ReadonlySet` 是**识别表**、开集纪律相反 —— 两者刻意不同族。)
|
|
58
|
-
*/
|
|
59
3
|
export interface CrashConvergedRow {
|
|
60
|
-
/** 被收敛的那条 ask 的审批 id(端的行身份;去重/引用都按它)。 */
|
|
61
4
|
readonly approvalId: string;
|
|
62
|
-
/** 崩溃时挂在门上的工具名(展示用;UNTRUSTED-for-display,端自己消毒控制字符)。 */
|
|
63
5
|
readonly toolName: string;
|
|
64
|
-
/** 归属的 task。 */
|
|
65
6
|
readonly taskId: string;
|
|
66
|
-
/** 归属的会话(server 在场才发)。 */
|
|
67
7
|
readonly sessionId?: string;
|
|
68
|
-
/** 原 ask 铸出的时刻(epoch ms)。 */
|
|
69
8
|
readonly ts: number;
|
|
70
|
-
/** 原 ask 的到期时刻(epoch ms)。 */
|
|
71
9
|
readonly expiresAtMs: number;
|
|
72
|
-
/** 收敛结果恒为 denied(闭集判别式,见本 interface 头注)。 */
|
|
73
10
|
readonly decision: 'denied';
|
|
74
|
-
/** 收敛原因恒为「崩在 park 之前」(闭集判别式)。 */
|
|
75
11
|
readonly cause: 'crashed_before_park';
|
|
76
|
-
/** 崩溃那一刻的状态 —— 分桶的**主判据**。 */
|
|
77
12
|
readonly orphanState: CrashConvergedOrphanState;
|
|
78
|
-
/** `orphanState==='decided'` 时人当时按下的那一下(server 在场才发)。 */
|
|
79
13
|
readonly originalDecision?: 'approve';
|
|
80
|
-
/** 人按下那一下的时刻(epoch ms;server 在场才发)。 */
|
|
81
14
|
readonly decidedAtMs?: number;
|
|
82
|
-
/** 收敛动作自己发生的时刻(epoch ms)。 */
|
|
83
15
|
readonly convergedAtMs: number;
|
|
84
|
-
/** 🔴 **缺省值不是铁证**(见文件头 caveat):以账本完整为前提算出来的「重跑安全」缺省。 */
|
|
85
16
|
readonly resumeSafe: boolean;
|
|
86
17
|
}
|
|
87
|
-
/**
|
|
88
|
-
* `GET /v1/approvals` 的**信封**形。`pending` 是老形的全部;后两键 additive
|
|
89
|
-
* (server 按 deps 在场才发)⇒ **老形 `{ pending }` 仍然可赋值到本型**,现有消费点一个字节不用改。
|
|
90
|
-
*
|
|
91
|
-
* 🔴 `livePending` 在**本型上**留 `unknown[]`(0.72.14 起它有了包内读器 `readLivePendingRows`,按结构窄读;
|
|
92
|
-
* 下面 ① 说的「零消费点」自那版起不再成立,② 仍然成立,也是读器按结构读而不引类型的原因):
|
|
93
|
-
* ① 本包对它零消费点,在这里手抄一份结构 = 手抄一份会漂的上游形(与 `ToolApprovalFrame.probeCause`
|
|
94
|
-
* 同一条理由);
|
|
95
|
-
* ② **SDK barrel 根本没把 `LivePendingRow` 导出**(实证:`@sema-agent/sdk` 7.4.0 的 `dist/index.d.ts`
|
|
96
|
-
* 那张 `export type { … } from "./types.js"` 名单里没有它)⇒ 想「用单一真源」也拿不到,
|
|
97
|
-
* 剩下的选项只有深路径 import(不是公面)或手抄(①)。
|
|
98
|
-
* ⇒ 想读它的端自己窄读,别指望本包替它断言形状。
|
|
99
|
-
* ⚠️ 方向是安全的:SDK 真实回体的 `livePending?: LivePendingRow[]` **可赋值**到 `unknown[]`,
|
|
100
|
-
* 所以真 `AgentClient.approvals` 仍然可赋值到 {@link ApprovalsResourceLike}(G7 段真跑 tsc 证)。
|
|
101
|
-
*/
|
|
102
18
|
export interface ApprovalsListEnvelope {
|
|
103
19
|
pending: PendingCheckpoint[];
|
|
104
20
|
livePending?: unknown[];
|
|
105
21
|
crashConverged?: CrashConvergedRow[];
|
|
106
22
|
}
|
|
107
|
-
/**
|
|
108
|
-
* {@link projectCrashConverged} 的产出。**分桶 + 计数,零文案**。
|
|
109
|
-
*
|
|
110
|
-
* 🔴 `total` 只数**读得出来的**行(= `resumeSafe.length + needsHuman.length`)。供给总行数 =
|
|
111
|
-
* `total + dropped` —— 两个数刻意分开,免得端把「读不出来的行」算进「上次崩溃影响了 N 件」。
|
|
112
|
-
*/
|
|
113
23
|
export interface CrashConvergedProjection {
|
|
114
|
-
/** 读得出来的行数(不含 `dropped`)。 */
|
|
115
24
|
readonly total: number;
|
|
116
|
-
/** `orphanState==='pending'` **且** `resumeSafe===true` 的行(按记录看重跑安全)。 */
|
|
117
25
|
readonly resumeSafe: readonly CrashConvergedRow[];
|
|
118
|
-
/** 其余一切(decided 臂 / `resumeSafe!==true` / 字段矛盾)—— 留人工确认。 */
|
|
119
26
|
readonly needsHuman: readonly CrashConvergedRow[];
|
|
120
|
-
/**
|
|
121
|
-
* 供给里**读不出来**的行数(缺必填位 / 判别式对不上 / 取属性就抛)。
|
|
122
|
-
* 🔴 `dropped > 0` 本身是**一条要显形的事实**:那是上游形漂了或载体坏了,端不许把它静默吃掉
|
|
123
|
-
* (至少留一条 debug 痕;真行被丢掉的方向,代价是人不知道有一件孤儿审批在)。
|
|
124
|
-
*/
|
|
125
27
|
readonly dropped: number;
|
|
126
28
|
}
|
|
127
|
-
/**
|
|
128
|
-
* `GET /v1/approvals` 回体 → `crashConverged` 的**分桶投影**。纯函数,**永不抛**。
|
|
129
|
-
*
|
|
130
|
-
* ## 🔴 缺席 vs 空数组:两件不同的事,判据不许合流
|
|
131
|
-
* · **键缺席**(老 server / deps 不在场 / 读不动)⇒ 返回 `undefined` ——「本部署没告诉我这件事」。
|
|
132
|
-
* 端此时**零渲染**:绝不渲「0 个」「本次无崩溃遗留」之类的话,那是替 server 下一个它没说过的
|
|
133
|
-
* 断言([honest-absence-not-fabricated-zero])。
|
|
134
|
-
* · **键在场且是空数组** ⇒ 返回 `{ total: 0, resumeSafe: [], needsHuman: [], dropped: 0 }` ——
|
|
135
|
-
* 「server 明说:一条都没有」。这一档端**可以**渲「没有崩溃遗留」。
|
|
136
|
-
* ⇒ 两档的**返回形不同**(`undefined` vs 对象),端拿 `=== undefined` 一刀分开,不必读计数。
|
|
137
|
-
*
|
|
138
|
-
* ## 🔴 载体在场却不是数组 ⇒ 同样 `undefined`(**不**折成 `total:0`)
|
|
139
|
-
* 那是形漂了或中间层改写了,本包**读不出**这次的供给。折成 `{total:0}` 会让端渲出
|
|
140
|
-
* 「没有崩溃遗留」——在一条给人判断「能不能闭眼重跑」的面上,这是最坏方向的假断言。
|
|
141
|
-
* 两档合流的代价只是「都零渲染」,而分错的代价是一句用户会照着去操作的谎。
|
|
142
|
-
*
|
|
143
|
-
* ## 🔴 三处不可信读取只认**自有数据位**
|
|
144
|
-
* 信封的 `crashConverged`、载体的 `length`、载体的每个数字下标 —— 三处都走 `ownDataValue`:
|
|
145
|
-
* accessor / 缺席 / 只挂在原型上的东西一律**当缺席**,一次别人的代码都不执行(`catch` 接得住
|
|
146
|
-
* 「抛」,接不住「不返回」)。真供给来自 `JSON.parse`,每一位都是自有数据位 ⇒ 对真行零影响。
|
|
147
|
-
*
|
|
148
|
-
* ## 🔴 载体**读不出**(已撤销 `Proxy` / `length` 或描述符取值抛)⇒ 也是 `undefined`
|
|
149
|
-
* 触碰载体的每一处都在保护内 —— 连 `Array.isArray()` 自己都是(对已撤销的 `Proxy` 调用它直接抛)。
|
|
150
|
-
* 走到一半炸掉时刻意**不交还半程结果**:一个自己都知道不全的计数,拿去渲「上次崩溃影响了 N 件」
|
|
151
|
-
* 比不说话更坏。
|
|
152
|
-
* 🔴 遍历**按数字下标**,不用载体自己的迭代协议:自带 `Symbol.iterator` 覆盖的数组能一条都不产出
|
|
153
|
-
* (于是真孤儿被伪造成「server 明说一条都没有」),也能把危险行替换成安全行。下标读不问载体
|
|
154
|
-
* 「有哪些行」这个问题。⚠️ 边界:代理仍能在 `length`/下标 trap 上撒谎 —— 那等同于「宿主注入了
|
|
155
|
-
* 会撒谎的传输层」,本包挡不住也不假装挡得住;本条守的是协议面。
|
|
156
|
-
*
|
|
157
|
-
* ## 🔴 进 resumeSafe 桶的合取有**五项**(两项主判据 + 两项跨位自洽 + 一项载体自证)
|
|
158
|
-
* `orphanState==='pending'`(工具零执行)∧ `resumeSafe===true` ∧ `originalDecision` 缺席 ∧
|
|
159
|
-
* `decidedAtMs` 缺席 ∧ 这一行**不带 accessor**。中间两项是**矛盾闸**:`pending` 说「一步都没执行」,
|
|
160
|
-
* 而那两位是「人已经按下过 approve」的证据 —— 同时在场 = 自相矛盾的载荷。最后一项是**顺序重入闸**:
|
|
161
|
-
* 带 getter 的行能在展开过程中把证据位删掉(见行读口头注的实测)。三者都**只挡「安全」这一侧**,
|
|
162
|
-
* 一律落 needsHuman 而**不丢** —— 它们可能是真孤儿,而且恰恰是最该给人看的那几条。
|
|
163
|
-
*
|
|
164
|
-
* ## 🔴 行数硬上限
|
|
165
|
-
* `length` 超过 100000 ⇒ 与「载体读不出」同一档(`undefined`)。判在遍历**之前**,所以一个谎报
|
|
166
|
-
* 十亿的 `length` trap 连一次下标读都触发不了 —— 否则同步空转会把启动/`--resume` 路的主线程冻住。
|
|
167
|
-
*
|
|
168
|
-
* ## 🔴 入参是 `unknown`,不是「带一个可选 `crashConverged` 的对象」
|
|
169
|
-
* 写成 `{ crashConverged?: unknown }` 会造出一个 TypeScript **弱类型**(成员全可选):把真
|
|
170
|
-
* `client.approvals.list()` 的回体喂进来时,SDK 7.4.0 声明的 `{ pending; livePending? }` 与它
|
|
171
|
-
* **一个共同属性都没有** ⇒ TS2559「has no properties in common」,文档里那句最主要的用法当场编不过
|
|
172
|
-
* (而只用本包自己的 `ApprovalsListEnvelope` 去测发现不了 —— 那个形恰好声明了 `crashConverged`)。
|
|
173
|
-
* 收 `unknown` 也更诚实:本函数对入参的全部工作**就是**窄化它,形状是运行期才知道的事。
|
|
174
|
-
*
|
|
175
|
-
* @param env 任意 `/v1/approvals` 回体(只读 `crashConverged` 一键;非对象 / `null` ⇒ `undefined`)。
|
|
176
|
-
*/
|
|
177
29
|
export declare function projectCrashConverged(env: unknown): CrashConvergedProjection | undefined;
|