@sema-agent/client-core 0.93.1 → 0.95.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.
- package/CHANGELOG.md +554 -0
- package/README.md +89 -55
- package/dist/adapt/arms.js +13 -11
- package/dist/adapt/panelTasks.js +4 -10
- package/dist/adapt/toolCards.js +2 -2
- package/dist/adapt/wireShapes.js +3 -8
- package/dist/adapter/activeRunSelfHeal.d.ts +8 -3
- package/dist/adapter/activeRunSelfHeal.js +20 -12
- package/dist/adapter/downstream/eventToSdkMessage.js +24 -17
- package/dist/adapter/downstream/terminalToSdkResult.js +13 -6
- package/dist/adapter/runStream.js +2 -1
- package/dist/adapter/types.d.ts +7 -0
- package/dist/adapter/types.js +15 -0
- package/dist/agentSession/backgroundView.js +5 -1
- package/dist/agentSession/engineAgentRegistryRead.js +2 -1
- package/dist/agentSession/engineSessionBackgroundStop.js +5 -3
- package/dist/agentsWireCaps.d.ts +17 -0
- package/dist/agentsWireCaps.js +111 -1
- package/dist/approvalDecidedByCapability.d.ts +0 -1
- package/dist/approvalDecidedByCapability.js +2 -7
- package/dist/approvalReachWire.d.ts +18 -0
- package/dist/approvalReachWire.js +58 -0
- package/dist/approvalsStreamLiveCapability.d.ts +0 -1
- package/dist/approvalsStreamLiveCapability.js +15 -14
- package/dist/atMostOnce.d.ts +8 -0
- package/dist/atMostOnce.js +36 -0
- package/dist/attachmentSeatCapability.d.ts +0 -1
- package/dist/attachmentSeatCapability.js +0 -3
- package/dist/attachmentsWireCaps.js +11 -6
- package/dist/bashExitReading.d.ts +10 -0
- package/dist/bashExitReading.js +12 -0
- package/dist/callerCwdCapability.d.ts +15 -0
- package/dist/callerCwdCapability.js +42 -0
- package/dist/centerWiringCapability.d.ts +1 -3
- package/dist/centerWiringCapability.js +18 -21
- package/dist/classifierStatus.js +4 -4
- package/dist/cloudConfigWireCaps.js +43 -21
- package/dist/compensations.js +1 -1
- package/dist/controlRouter.js +3 -10
- package/dist/coreValuePorts.d.ts +64 -1
- package/dist/coreValuePorts.js +30 -0
- package/dist/cycleOrder.d.ts +15 -0
- package/dist/cycleOrder.js +45 -0
- package/dist/decideFailureNote.js +4 -1
- package/dist/decideReceipt.d.ts +2 -1
- package/dist/decideReceipt.js +41 -13
- package/dist/declared/supportFloorDeclared.d.ts +1 -0
- package/dist/declared/supportFloorDeclared.js +5 -0
- package/dist/detachWire.d.ts +1 -4
- package/dist/detachWire.js +1 -1
- package/dist/deviceExecutorManagementCapability.d.ts +0 -1
- package/dist/deviceExecutorManagementCapability.js +36 -40
- package/dist/deviceFlowPolling.d.ts +5 -0
- package/dist/deviceFlowPolling.js +28 -0
- package/dist/deviceRebind.d.ts +88 -0
- package/dist/deviceRebind.js +242 -0
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +963 -30
- package/dist/engineAgentAbsence.d.ts +2 -2
- package/dist/engineAgentPanelStore.d.ts +8 -18
- package/dist/engineAgentPanelStore.js +19 -537
- package/dist/engineCapReader.d.ts +6 -6
- package/dist/engineCapReader.js +30 -43
- package/dist/engineCapsCache.d.ts +7 -2
- package/dist/engineCapsCache.js +64 -26
- package/dist/engineCredentialRequirement.d.ts +9 -0
- package/dist/engineCredentialRequirement.js +23 -0
- package/dist/engineEnvSourcing.d.ts +53 -0
- package/dist/engineEnvSourcing.js +81 -0
- package/dist/engineErrorCodes.d.ts +19 -4
- package/dist/engineErrorCodes.js +39 -21
- package/dist/engineIdentity.js +2 -0
- package/dist/engineNoticeCodes.d.ts +22 -2
- package/dist/engineNoticeCodes.js +73 -6
- package/dist/engineRefusedToolName.d.ts +1 -0
- package/dist/engineRefusedToolName.js +8 -0
- package/dist/engineWireSdk.js +2 -2
- package/dist/executionLaneCapability.d.ts +2 -3
- package/dist/executionLaneCapability.js +28 -28
- package/dist/fileHistoryCaptureCapability.d.ts +0 -1
- package/dist/fileHistoryCaptureCapability.js +13 -12
- package/dist/fileHistoryLegNotice.d.ts +14 -2
- package/dist/fileHistoryLegNotice.js +101 -15
- package/dist/fleet/fleetLedger.d.ts +2 -0
- package/dist/fleet/fleetLedger.js +74 -52
- package/dist/fleet/fleetProjection.d.ts +0 -3
- package/dist/fleet/fleetProjection.js +9 -16
- package/dist/fleetAgentPanelProjection.d.ts +4 -17
- package/dist/fleetAgentPanelProjection.js +7 -197
- package/dist/fleetAgentRowLike.d.ts +16 -0
- package/dist/fleetAgentRowLike.js +1 -0
- package/dist/gateOutcome.d.ts +2 -1
- package/dist/gateOutcome.js +33 -18
- package/dist/gateVocabulary.js +1 -1
- package/dist/generated/engineAskFaceTables.d.ts +3 -0
- package/dist/generated/engineAskFaceTables.js +12 -0
- package/dist/generated/engineFactTables.d.ts +4 -2
- package/dist/generated/engineFactTables.js +13 -0
- package/dist/generated/engineNoticeTables.d.ts +5 -0
- package/dist/generated/engineNoticeTables.js +7 -0
- package/dist/generated/sdkFactTables.d.ts +5 -0
- package/dist/generated/sdkFactTables.js +34 -0
- package/dist/generated/settingsSchemaFns.d.ts +10 -0
- package/dist/generated/settingsSchemaFns.js +22 -0
- package/dist/generated/settingsSchemaTables.d.ts +3 -0
- package/dist/generated/settingsSchemaTables.js +3 -0
- package/dist/headlessPermissionModeWire.d.ts +2 -2
- package/dist/headlessPermissionModeWire.js +11 -21
- package/dist/headlessReconnectWire.js +49 -20
- package/dist/hitl/allowRuleShadow.d.ts +1 -1
- package/dist/hitl/allowRuleShadow.js +49 -8
- package/dist/hitl/approvalCompleteParked.d.ts +1 -0
- package/dist/hitl/approvalCompleteParked.js +14 -0
- package/dist/hitl/approvalEndingCause.d.ts +5 -0
- package/dist/hitl/approvalEndingCause.js +61 -0
- package/dist/hitl/approvalHolds.d.ts +46 -0
- package/dist/hitl/approvalHolds.js +140 -0
- package/dist/hitl/approvalOutcomeNote.js +2 -1
- package/dist/hitl/approvalResolution.js +9 -1
- package/dist/hitl/approvalsFeed.js +23 -6
- package/dist/hitl/askGateWire.d.ts +2 -1
- package/dist/hitl/askGateWire.js +29 -1
- package/dist/hitl/automaticAnswerVerdict.d.ts +8 -2
- package/dist/hitl/automaticAnswerVerdict.js +71 -23
- package/dist/hitl/crashConverged.js +2 -0
- package/dist/hitl/decisionConflict.d.ts +3 -0
- package/dist/hitl/decisionConflict.js +43 -0
- package/dist/hitl/decisionRefusal.d.ts +23 -0
- package/dist/hitl/decisionRefusal.js +88 -0
- package/dist/hitl/frameRouter.d.ts +10 -0
- package/dist/hitl/frameRouter.js +71 -32
- package/dist/hitl/gateLedger.d.ts +8 -0
- package/dist/hitl/gateLedger.js +38 -0
- package/dist/hitl/hitlBridge.d.ts +14 -3
- package/dist/hitl/hitlBridge.js +75 -62
- package/dist/hitl/hitlHostSurface.d.ts +3 -0
- package/dist/hitl/hitlHostSurface.js +17 -15
- package/dist/hitl/livePendingAsk.d.ts +16 -6
- package/dist/hitl/livePendingAsk.js +36 -4
- package/dist/hitl/localAllowRule.js +2 -1
- package/dist/hitl/noAllowCause.d.ts +9 -0
- package/dist/hitl/noAllowCause.js +26 -0
- package/dist/hitl/parkExpiryJudgements.d.ts +19 -0
- package/dist/hitl/parkExpiryJudgements.js +46 -0
- package/dist/hitl/parkResolver.d.ts +3 -7
- package/dist/hitl/parkResolver.js +55 -28
- package/dist/hitl/parkRowBirthWait.js +2 -1
- package/dist/hitl/persistedRulesWire.d.ts +6 -1
- package/dist/hitl/persistedRulesWire.js +16 -4
- package/dist/hitl/planReviewWire.d.ts +2 -3
- package/dist/hitl/planReviewWire.js +86 -39
- package/dist/hitl/replayedApproval.d.ts +8 -0
- package/dist/hitl/replayedApproval.js +125 -10
- package/dist/hitl/resumeRunningCard.d.ts +2 -0
- package/dist/hitl/resumeRunningCard.js +15 -4
- package/dist/hitl/sessionPolicyDeliverable.d.ts +1 -1
- package/dist/hitl/sessionPolicyDeliverable.js +3 -8
- package/dist/hitl/sessionPolicyWire.js +1 -1
- package/dist/hitl/toolApprovalWire.d.ts +50 -5
- package/dist/hitl/toolApprovalWire.js +368 -56
- package/dist/hooksWireCaps.js +38 -6
- package/dist/host.d.ts +5 -0
- package/dist/host.js +3 -1
- package/dist/hostCallbackGuard.d.ts +1 -0
- package/dist/hostCallbackGuard.js +25 -0
- package/dist/humanTurnRead.d.ts +15 -1
- package/dist/humanTurnRead.js +28 -2
- package/dist/index.d.ts +45 -14
- package/dist/index.js +33 -12
- package/dist/interactiveInterrupt.d.ts +8 -0
- package/dist/interactiveInterrupt.js +54 -0
- package/dist/limitsWire.d.ts +5 -1
- package/dist/limitsWire.js +51 -13
- package/dist/liveModelCatalog.d.ts +109 -0
- package/dist/liveModelCatalog.js +344 -18
- package/dist/mcpEngineLeg.d.ts +25 -0
- package/dist/mcpEngineLeg.js +71 -15
- package/dist/mcpPanel.js +2 -1
- package/dist/mcpProbeCapability.d.ts +0 -1
- package/dist/mcpProbeCapability.js +13 -12
- package/dist/mcpReconnect.d.ts +1 -3
- package/dist/mcpReconnect.js +20 -10
- package/dist/memoryComplianceCapability.d.ts +0 -1
- package/dist/memoryComplianceCapability.js +14 -13
- package/dist/memoryOriginCapability.d.ts +0 -1
- package/dist/memoryOriginCapability.js +14 -13
- package/dist/memoryVerbsWire.d.ts +1 -1
- package/dist/memoryVerbsWire.js +4 -0
- package/dist/model/liveCatalogShape.d.ts +14 -0
- package/dist/model/liveCatalogShape.js +71 -0
- package/dist/model/modelSupplyRules.d.ts +1 -0
- package/dist/model/modelSupplyRules.js +30 -9
- package/dist/model/modelsPolicy.d.ts +21 -0
- package/dist/model/modelsPolicy.js +90 -0
- package/dist/modelIdentityResolvability.d.ts +4 -2
- package/dist/modelIdentityResolvability.js +25 -5
- package/dist/modelSwitchFallback.d.ts +69 -0
- package/dist/modelSwitchFallback.js +206 -0
- package/dist/notifications.js +12 -11
- package/dist/outputStyleSeatCapability.d.ts +15 -0
- package/dist/outputStyleSeatCapability.js +42 -0
- package/dist/ownKey.d.ts +7 -0
- package/dist/ownKey.js +58 -0
- package/dist/panelReduce.d.ts +114 -0
- package/dist/panelReduce.js +1135 -0
- package/dist/panelStateHolder.d.ts +17 -0
- package/dist/panelStateHolder.js +201 -0
- package/dist/peerLaneCapability.d.ts +0 -1
- package/dist/peerLaneCapability.js +15 -14
- package/dist/permissionModesCapability.d.ts +0 -1
- package/dist/permissionModesCapability.js +5 -10
- package/dist/permissionRuleIssue.js +1 -1
- package/dist/permissionRulesWriteCapability.d.ts +0 -1
- package/dist/permissionRulesWriteCapability.js +15 -14
- package/dist/permissionsAllowGrantCapability.d.ts +2 -1
- package/dist/permissionsAllowGrantCapability.js +35 -19
- package/dist/permissionsDeclaration.d.ts +16 -1
- package/dist/permissionsDeclaration.js +142 -15
- package/dist/printToolResultFrame.js +2 -10
- package/dist/promptDelivery.js +0 -8
- package/dist/protocolSegment.d.ts +1 -0
- package/dist/protocolSegment.js +13 -1
- package/dist/request/taskRequest.d.ts +11 -3
- package/dist/request/taskRequest.js +13 -1
- package/dist/resultFrameKeys.d.ts +4 -0
- package/dist/resultFrameKeys.js +13 -0
- package/dist/resumeRefusalCopy.d.ts +18 -1
- package/dist/resumeRefusalCopy.js +132 -31
- package/dist/retryStatus.js +6 -4
- package/dist/rewindArchiveCapability.d.ts +2 -1
- package/dist/rewindArchiveCapability.js +28 -15
- package/dist/rewindEngineAction.d.ts +21 -0
- package/dist/rewindEngineAction.js +36 -0
- package/dist/rewindWireCaps.d.ts +2 -1
- package/dist/rewindWireCaps.js +1 -0
- package/dist/{hitl/rosterMountedNames.d.ts → rosterMountedNames.d.ts} +1 -1
- package/dist/runCancelContext.js +2 -1
- package/dist/runTerminal.d.ts +0 -11
- package/dist/runTerminal.js +4 -27
- package/dist/sdkRegistryTransit.d.ts +2 -1
- package/dist/sdkRegistryTransit.js +1 -0
- package/dist/sealedKeyCapability.d.ts +0 -1
- package/dist/sealedKeyCapability.js +19 -20
- package/dist/seatContract.d.ts +85 -28
- package/dist/seatContract.js +512 -148
- package/dist/sessionIdSegment.d.ts +1 -0
- package/dist/sessionIdSegment.js +11 -0
- package/dist/sessionMemoryErase.d.ts +1 -1
- package/dist/sessionMemoryErase.js +6 -1
- package/dist/sessionMemoryStatus.js +3 -2
- package/dist/sessionPolicyCapability.d.ts +0 -1
- package/dist/sessionPolicyCapability.js +14 -13
- package/dist/sessionReadRedactionCapability.d.ts +15 -0
- package/dist/sessionReadRedactionCapability.js +42 -0
- package/dist/sessionSyncFileHistoryCapability.d.ts +0 -1
- package/dist/sessionSyncFileHistoryCapability.js +13 -12
- package/dist/skillToolListsCapability.d.ts +0 -1
- package/dist/skillToolListsCapability.js +13 -12
- package/dist/skillsWireCaps.d.ts +4 -0
- package/dist/skillsWireCaps.js +66 -1
- package/dist/sqlEngineCapability.d.ts +0 -1
- package/dist/sqlEngineCapability.js +21 -21
- package/dist/steerPriorityCapability.d.ts +0 -1
- package/dist/steerPriorityCapability.js +18 -19
- package/dist/storePostureCapability.d.ts +1 -1
- package/dist/storePostureCapability.js +16 -16
- package/dist/streamDrainingLegs.d.ts +6 -0
- package/dist/streamDrainingLegs.js +23 -0
- package/dist/subagent/agentStateDetail.d.ts +1 -0
- package/dist/subagent/agentStateDetail.js +41 -0
- package/dist/subagent/engineCompactWire.d.ts +15 -0
- package/dist/subagent/engineCompactWire.js +82 -45
- package/dist/subagent/engineDelegatedPrompt.js +10 -6
- package/dist/subagent/engineSubagentOutput.d.ts +0 -1
- package/dist/subagent/engineSubagentOutput.js +5 -20
- package/dist/subagent/engineSubagentTail.d.ts +0 -1
- package/dist/subagent/engineSubagentTail.js +7 -32
- package/dist/subagentContentStore.js +3 -3
- package/dist/supportFloor.js +2 -5
- package/dist/taskRequestWords.d.ts +2 -4
- package/dist/taskRequestWords.js +3 -2
- package/dist/terminalStatuses.d.ts +30 -0
- package/dist/terminalStatuses.js +67 -0
- package/dist/toolResult.d.ts +5 -0
- package/dist/toolResult.js +88 -36
- package/dist/types/engineState.d.ts +2 -1
- package/dist/usageAnalytics.d.ts +146 -0
- package/dist/usageAnalytics.js +311 -0
- package/dist/userAttachmentEnvelope.d.ts +22 -1
- package/dist/userAttachmentEnvelope.js +90 -2
- package/dist/userInvokedSkillsCapability.d.ts +0 -1
- package/dist/userInvokedSkillsCapability.js +13 -12
- package/dist/webSearchBackendCapability.d.ts +0 -1
- package/dist/webSearchBackendCapability.js +20 -19
- package/dist/webSearchWireCaps.js +3 -11
- package/dist/wireErrorTriage.d.ts +11 -0
- package/dist/wireErrorTriage.js +35 -0
- package/dist/wireFailureShape.d.ts +10 -0
- package/dist/wireFailureShape.js +72 -5
- package/dist/wireRefusalCopy.d.ts +6 -1
- package/dist/wireRefusalCopy.js +23 -25
- package/dist/wiringInstructionsAttribution.d.ts +10 -0
- package/dist/wiringInstructionsAttribution.js +67 -0
- package/dist/workflowClient.js +19 -2
- package/dist/workflowsJournalCapability.d.ts +0 -1
- package/dist/workflowsJournalCapability.js +13 -12
- package/dist/writeProtectionCapability.d.ts +0 -1
- package/dist/writeProtectionCapability.js +26 -26
- package/docs/INTEGRATION-CLIENTS.md +1733 -52
- package/package.json +5 -5
- package/dist/askSurvivesStandingAnswer.d.ts +0 -13
- package/dist/askSurvivesStandingAnswer.js +0 -53
- package/dist/engineCapsGenerationGuard.d.ts +0 -4
- package/dist/engineCapsGenerationGuard.js +0 -19
- package/dist/hitl/askSurvivesPosture.d.ts +0 -20
- package/dist/hitl/askSurvivesPosture.js +0 -48
- package/dist/panelRunningHistory.d.ts +0 -22
- package/dist/panelRunningHistory.js +0 -82
- package/dist/registryConflict.d.ts +0 -3
- package/dist/registryConflict.js +0 -44
- /package/dist/{hitl/rosterMountedNames.js → rosterMountedNames.js} +0 -0
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { putOwnKey, readOwnDataValue } from '../ownKey.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { ApprovalStaleError, NotFoundError, ParkedResumeStartupError } from '@sema-agent/sdk';
|
|
3
|
+
import { DecideTransportRetryExhaustedError, GATE_FAILURE_CODES, HitlBridge, NO_QUESTION_OVERLAY_REASON, findPendingForTask, hitlSafetyCodeOf, isNoDecisionSurfaceReason, readDecideCurrentPending, readWireErrorCode, } from './hitlBridge.js';
|
|
4
|
+
import { ASK_GONE, CHECKPOINT_UNSUPPORTED_VERSION, DECIDE_WORKFLOW_PARK_FORKED, DECIDE_WORKFLOW_PARKS_UNREADABLE, PARKED_RESUME_STARTUP_FAILED, RESUME_POLICY_FOLD_CODE, isDecideAlreadyResolvedCode, isDecideParkMovedCode, refusalSaysStillPending } from '../engineErrorCodes.js';
|
|
5
|
+
import { isHitlSafetyErrorLike } from './parkOwnership.js';
|
|
4
6
|
import { publishQuestionFrame, registerLocalQuestionResponder, hasQuestionOverlay, } from '../liveQuestionStore.js';
|
|
5
7
|
import { hostLog } from '../host.js';
|
|
6
8
|
import { surfaceFsApprovalAndDecide } from './toolApprovalWire.js';
|
|
7
|
-
import { observeCancelByDeny } from './hitlHostSurface.js';
|
|
9
|
+
import { INTERRUPT_DENY_REASON, observeCancelByDeny } from './hitlHostSurface.js';
|
|
8
10
|
import { flushHeldWithInterruptRewrite, isAskTool } from './frameRouter.js';
|
|
9
11
|
import { approvalCallKey, askGateQuestionId } from './gateIdentity.js';
|
|
10
12
|
import { readDecideReceipt } from '../decideReceipt.js';
|
|
11
13
|
import { decideFailureNote } from '../decideFailureNote.js';
|
|
14
|
+
import { thrownIsInstanceOf, wireFailureTextsOf } from '../wireFailureShape.js';
|
|
12
15
|
export const MAX_GATE_HOPS = 2;
|
|
13
16
|
export function nextHopBudget(prev, round) {
|
|
14
17
|
const total = (prev?.total ?? 0) + 1;
|
|
@@ -17,16 +20,6 @@ export function nextHopBudget(prev, round) {
|
|
|
17
20
|
const MAX_TRANSPORT_REATTACHES = 2;
|
|
18
21
|
export const MAX_TOTAL_PARKS = 64;
|
|
19
22
|
const MAX_ALREADY_RESOLVED_REATTACHES = 1;
|
|
20
|
-
export const GATE_FAILURE_CODES = [
|
|
21
|
-
'no_pending',
|
|
22
|
-
'binding_mismatch',
|
|
23
|
-
'wrong_gate',
|
|
24
|
-
'bad_plan_edit',
|
|
25
|
-
'bad_plan_mode',
|
|
26
|
-
'empty_answer',
|
|
27
|
-
];
|
|
28
|
-
const _gateFailureCodePins = [true, true];
|
|
29
|
-
void _gateFailureCodePins;
|
|
30
23
|
function isGateFailureCode(v) {
|
|
31
24
|
return typeof v === 'string' && GATE_FAILURE_CODES.includes(v);
|
|
32
25
|
}
|
|
@@ -40,27 +33,59 @@ function alreadyResolvedReasonToken(reason) {
|
|
|
40
33
|
const r = reason.toLowerCase();
|
|
41
34
|
return ALREADY_RESOLVED_REASON_TOKENS.find((t) => r.includes(t));
|
|
42
35
|
}
|
|
43
|
-
export function isAlreadyResolvedFailure(
|
|
36
|
+
export function isAlreadyResolvedFailure(failure) {
|
|
44
37
|
try {
|
|
45
|
-
return alreadyResolvedFailureVerdict(
|
|
38
|
+
return alreadyResolvedFailureVerdict(failure);
|
|
46
39
|
}
|
|
47
40
|
catch {
|
|
48
41
|
return false;
|
|
49
42
|
}
|
|
50
43
|
}
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
const ALREADY_RESOLVED_TYPED_ERROR_NAMES = Object.freeze([ApprovalStaleError.name, NotFoundError.name]);
|
|
45
|
+
const PARKED_RESUME_STARTUP_TYPED_ERROR_NAME = ParkedResumeStartupError.name;
|
|
46
|
+
function decideFailureFactsOf(failure) {
|
|
47
|
+
if (typeof failure !== 'object' || failure === null)
|
|
48
|
+
return undefined;
|
|
49
|
+
const o = failure;
|
|
50
|
+
const ec = o.errorCode;
|
|
51
|
+
const errorCode = typeof ec === 'string' && ec.length > 0 ? ec : undefined;
|
|
52
|
+
const retriable = refusalSaysStillPending(failure);
|
|
53
|
+
if (Object.hasOwn(failure, 'kind') && o.kind === 'failed') {
|
|
54
|
+
const safety = isGateFailureCode(o.safetyCode) ? o.safetyCode : undefined;
|
|
55
|
+
const code = isGateFailureCode(o.code) ? o.code : safety;
|
|
56
|
+
return { code, safetySignal: safety !== undefined, errorCode, retriable, typedErrorName: undefined, reason: o.reason };
|
|
57
|
+
}
|
|
58
|
+
const name = o.name;
|
|
59
|
+
return {
|
|
60
|
+
code: isGateFailureCode(o.code) ? o.code : undefined,
|
|
61
|
+
safetySignal: isHitlSafetyErrorLike(failure),
|
|
62
|
+
errorCode,
|
|
63
|
+
retriable,
|
|
64
|
+
typedErrorName: typeof name === 'string' ? name : undefined,
|
|
65
|
+
reason: String(failure),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function alreadyResolvedFailureVerdict(failure) {
|
|
69
|
+
const f = decideFailureFactsOf(failure);
|
|
70
|
+
if (f === undefined)
|
|
53
71
|
return false;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
72
|
+
if (f.code !== undefined)
|
|
73
|
+
return f.code === 'no_pending';
|
|
74
|
+
if (f.safetySignal)
|
|
75
|
+
return false;
|
|
76
|
+
if (isDecideAlreadyResolvedCode(f.errorCode))
|
|
77
|
+
return true;
|
|
78
|
+
if (f.typedErrorName !== undefined && ALREADY_RESOLVED_TYPED_ERROR_NAMES.includes(f.typedErrorName))
|
|
79
|
+
return true;
|
|
80
|
+
if (f.typedErrorName === PARKED_RESUME_STARTUP_TYPED_ERROR_NAME && !isDecideParkMovedCode(f.errorCode))
|
|
81
|
+
return false;
|
|
82
|
+
if (isCodeClassifiedGateFailure(f.errorCode, f.retriable))
|
|
58
83
|
return false;
|
|
59
|
-
if (
|
|
84
|
+
if (isDecideParkMovedCode(f.errorCode))
|
|
60
85
|
return true;
|
|
61
|
-
if (
|
|
86
|
+
if (f.errorCode === ASK_GONE)
|
|
62
87
|
return true;
|
|
63
|
-
return isAlreadyResolvedGateReason(
|
|
88
|
+
return isAlreadyResolvedGateReason(f.reason);
|
|
64
89
|
}
|
|
65
90
|
export function isGateStandingErrorCode(code, retriable) {
|
|
66
91
|
return (code === RESUME_POLICY_FOLD_CODE ||
|
|
@@ -139,7 +164,7 @@ async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGat
|
|
|
139
164
|
});
|
|
140
165
|
const bridge = new HitlBridge(deps.client, taskId, deps.onDecideOperation ? { onDecideOperation: deps.onDecideOperation } : undefined);
|
|
141
166
|
if (answer === null) {
|
|
142
|
-
observeCancelByDeny(bridge.decideTool({ decision: 'deny', reason:
|
|
167
|
+
observeCancelByDeny(bridge.decideTool({ decision: 'deny', reason: INTERRUPT_DENY_REASON }, gatedCallId, undefined, pending), taskId);
|
|
143
168
|
return { kind: 'aborted', gatedCallId };
|
|
144
169
|
}
|
|
145
170
|
let declinedReceipt;
|
|
@@ -166,17 +191,19 @@ async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGat
|
|
|
166
191
|
return { kind: 'decided', gatedCallId, ...(declinedReceipt !== undefined ? { receipt: declinedReceipt } : {}) };
|
|
167
192
|
}
|
|
168
193
|
catch (e) {
|
|
169
|
-
const code =
|
|
194
|
+
const code = hitlSafetyCodeOf(e);
|
|
170
195
|
const currentPending = readDecideCurrentPending(e);
|
|
171
196
|
const wireCode = readWireErrorCode(e);
|
|
172
197
|
const wireRetriable = typeof e === 'object' && e !== null && refusalSaysStillPending(e);
|
|
198
|
+
const failureTexts = wireFailureTextsOf(e);
|
|
199
|
+
hostLog('debug', `liveHitlAskWire: decide failed: ${failureTexts.log}`);
|
|
173
200
|
return {
|
|
174
201
|
kind: 'failed',
|
|
175
202
|
stage: 'decide',
|
|
176
203
|
gatedCallId,
|
|
177
|
-
reason: `decide failed: ${
|
|
204
|
+
reason: `decide failed: ${failureTexts.reason}${decideFailureNote(e, attemptedDecision)}`,
|
|
178
205
|
...(code !== undefined ? { code } : {}),
|
|
179
|
-
...(e
|
|
206
|
+
...(thrownIsInstanceOf(e, DecideTransportRetryExhaustedError) ? { retryExhausted: true } : {}),
|
|
180
207
|
...(currentPending !== undefined ? { currentPending } : {}),
|
|
181
208
|
...(wireCode !== undefined ? { errorCode: wireCode } : {}),
|
|
182
209
|
...(wireRetriable ? { retriable: true } : {}),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { abortableSleep } from '../abortableSleep.js';
|
|
2
|
+
import { wireFailureTextsOf } from '../wireFailureShape.js';
|
|
2
3
|
function parkRowPollDelay(ms, signal) {
|
|
3
4
|
return abortableSleep(ms, signal ?? new AbortController().signal);
|
|
4
5
|
}
|
|
@@ -16,7 +17,7 @@ export async function waitForParkRowBirth(deps) {
|
|
|
16
17
|
return await deps.probe(attempt, signal);
|
|
17
18
|
}
|
|
18
19
|
catch (e) {
|
|
19
|
-
return { kind: 'unborn', reason: `probe threw: ${
|
|
20
|
+
return { kind: 'unborn', reason: `probe threw: ${wireFailureTextsOf(e).reason}` };
|
|
20
21
|
}
|
|
21
22
|
};
|
|
22
23
|
const probeWithinRemaining = async (attempt, remainingMs) => {
|
|
@@ -44,6 +44,9 @@ export type RulesFailure = {
|
|
|
44
44
|
} | {
|
|
45
45
|
kind: 'cursor-stale';
|
|
46
46
|
message: string;
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'query-refused';
|
|
49
|
+
message: string;
|
|
47
50
|
} | {
|
|
48
51
|
kind: 'too-many-candidates';
|
|
49
52
|
message: string;
|
|
@@ -78,7 +81,9 @@ export type RulesFailure = {
|
|
|
78
81
|
kind: 'error';
|
|
79
82
|
message: string;
|
|
80
83
|
};
|
|
81
|
-
export declare function classifyRulesFailure(e: unknown
|
|
84
|
+
export declare function classifyRulesFailure(e: unknown, context?: {
|
|
85
|
+
readonly cursorSent?: boolean;
|
|
86
|
+
}): RulesFailure;
|
|
82
87
|
export declare const PERSISTED_RULE_BEHAVIORS: readonly RuleBehavior[];
|
|
83
88
|
export declare function persistedRuleBehaviorOf(rule: unknown): RuleBehavior | undefined;
|
|
84
89
|
export declare const PERSISTED_RULE_BEHAVIOR_UNKNOWN = "(unknown)";
|
|
@@ -36,7 +36,7 @@ export function readCcImportRedeemCounts(result) {
|
|
|
36
36
|
}
|
|
37
37
|
return null;
|
|
38
38
|
}
|
|
39
|
-
export function classifyRulesFailure(e) {
|
|
39
|
+
export function classifyRulesFailure(e, context) {
|
|
40
40
|
const { status, errorCode, message, retryAfterSec, committed } = wireFailureShapeOf(e);
|
|
41
41
|
if (errorCode === 'capability.rule_store_required') {
|
|
42
42
|
return { kind: 'lane-unavailable', message };
|
|
@@ -58,8 +58,20 @@ export function classifyRulesFailure(e) {
|
|
|
58
58
|
if (errorCode === 'state.rule_write_failed') {
|
|
59
59
|
return committed === 'no' ? { kind: 'write-not-committed', message } : { kind: 'write-indeterminate', message };
|
|
60
60
|
}
|
|
61
|
-
if (status === 400 && errorCode === 'request.query_invalid')
|
|
62
|
-
|
|
61
|
+
if (status === 400 && errorCode === 'request.query_invalid') {
|
|
62
|
+
let cursorSent;
|
|
63
|
+
try {
|
|
64
|
+
cursorSent = context?.cursorSent;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
cursorSent = undefined;
|
|
68
|
+
}
|
|
69
|
+
if (cursorSent === true)
|
|
70
|
+
return { kind: 'cursor-stale', message };
|
|
71
|
+
if (cursorSent === false)
|
|
72
|
+
return { kind: 'query-refused', message };
|
|
73
|
+
return { kind: 'error', message };
|
|
74
|
+
}
|
|
63
75
|
if (status === 400 && errorCode === 'request.field_invalid')
|
|
64
76
|
return { kind: 'field-refused', message };
|
|
65
77
|
if (status === 400 && errorCode === 'request.body_shape')
|
|
@@ -144,7 +156,7 @@ export async function listAllPersistedRules(facade, params = {}, opts) {
|
|
|
144
156
|
res = await facade.list({ limit: PAGE_LIMIT, ...cleanParams, ...(cursor !== undefined ? { cursor } : {}) }, opts);
|
|
145
157
|
}
|
|
146
158
|
catch (e) {
|
|
147
|
-
const failure = classifyRulesFailure(e);
|
|
159
|
+
const failure = classifyRulesFailure(e, { cursorSent: cursor !== undefined });
|
|
148
160
|
if (failure.kind === 'cursor-stale' && cursor !== undefined && attempt === 0) {
|
|
149
161
|
hostLog('debug', 'persistedRulesWire: rule list cursor was minted on another rev/principal/scope — dropping it and re-listing from the top (never resuming a stale keyset)');
|
|
150
162
|
restart = true;
|
|
@@ -12,6 +12,7 @@ export type PlanReviewChoice = {
|
|
|
12
12
|
permissionModeAfter?: PlanReviewModeAfter;
|
|
13
13
|
} | {
|
|
14
14
|
decision: 'reject';
|
|
15
|
+
reason?: string;
|
|
15
16
|
};
|
|
16
17
|
export declare function planReviewChoiceFromAnswer(answer: QuestionAnswer | null | undefined, shownLabels?: readonly string[]): PlanReviewChoice | 'dismissed';
|
|
17
18
|
export declare function planReviewCardOptions(offerModeAfter: boolean): Array<{
|
|
@@ -48,7 +49,6 @@ export type PlanReviewWireClient = {
|
|
|
48
49
|
};
|
|
49
50
|
export interface PlanReviewWire {
|
|
50
51
|
client: PlanReviewWireClient;
|
|
51
|
-
capsBaseUrl?: string;
|
|
52
52
|
}
|
|
53
53
|
export interface PlanReviewDecisionOutcome extends PlanReviewOutcomeMeta {
|
|
54
54
|
detail: string;
|
|
@@ -77,14 +77,13 @@ export declare function __resetPlanReviewDecisionLatchForTests(): void;
|
|
|
77
77
|
export declare function decidePlanReview(taskId: string, decision: 'approve' | 'reject', permissionModeAfter?: string, opts?: DecidePlanReviewOptions): Promise<void>;
|
|
78
78
|
export interface ReopenPlanReviewOpts {
|
|
79
79
|
mintFreshQuestionId?: boolean;
|
|
80
|
-
deliverDecision?: (taskId: string, decision: 'approve' | 'reject') => void | Promise<void>;
|
|
80
|
+
deliverDecision?: (taskId: string, decision: 'approve' | 'reject', reason?: string) => void | Promise<void>;
|
|
81
81
|
sessionKey?: string;
|
|
82
82
|
wire?: PlanReviewWire;
|
|
83
83
|
onOutcome?: PlanReviewDeliveryOptions['onOutcome'];
|
|
84
84
|
presentationReceiptMs?: number;
|
|
85
85
|
trigger?: PlanReviewReopenTrigger;
|
|
86
86
|
readGateInstanceKeys?: PlanReviewGateInstanceReader;
|
|
87
|
-
decisionHandedOver?: (taskId: string) => boolean;
|
|
88
87
|
pendingReadStartedAt?: number;
|
|
89
88
|
}
|
|
90
89
|
export declare function _resetActiveReopenRespondersForTest(): void;
|
|
@@ -6,7 +6,8 @@ import { engineWireTarget } from '../engineWireTarget.js';
|
|
|
6
6
|
import { enqueuePlanReviewOutcome } from '../notifications.js';
|
|
7
7
|
import { corruptStoredRowContent, corruptStoredRowWhere } from '../wireErrorTriage.js';
|
|
8
8
|
import { decideFailureNote } from '../decideFailureNote.js';
|
|
9
|
-
import {
|
|
9
|
+
import { wireFailureTextsOf } from '../wireFailureShape.js';
|
|
10
|
+
import { checkpointUnsupportedVersionContent, checkpointUnsupportedVersionFromError, resumeContextUnavailableContent, resumeContextUnavailableFromError } from '../resumeRefusalCopy.js';
|
|
10
11
|
import { REQUEST_FIELD_CONFLICT, isUnavailableFaceCode } from '../engineErrorCodes.js';
|
|
11
12
|
import { denyReasonForWire, isPlanReviewModeAfter } from './hitlBridge.js';
|
|
12
13
|
import { planReviewQuestionId, REOPEN_ID_TAIL, taskIdFromPlanReviewQuestionId } from './gateIdentity.js';
|
|
@@ -28,31 +29,59 @@ const ALL_KNOWN_LABELS = Object.freeze([
|
|
|
28
29
|
PLAN_REVIEW_APPROVE_LABEL,
|
|
29
30
|
PLAN_REVIEW_REJECT_LABEL,
|
|
30
31
|
]);
|
|
31
|
-
export function planReviewDecisionFromAnswer(answer, shownLabels) {
|
|
32
|
-
const choice =
|
|
32
|
+
export function planReviewDecisionFromAnswer(answer, shownLabels = LEGACY_TWO_CHOICE_LABELS) {
|
|
33
|
+
const { choice } = readPlanReviewAnswer(answer, shownLabels);
|
|
33
34
|
if (choice === 'dismissed')
|
|
34
35
|
return 'dismissed';
|
|
35
36
|
return choice.decision;
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
+
function readDismissed() {
|
|
39
|
+
return { choice: 'dismissed', noteIgnoredOnApprove: false };
|
|
40
|
+
}
|
|
41
|
+
function freeTextNoteOf(entry) {
|
|
42
|
+
try {
|
|
43
|
+
const note = entry?.note;
|
|
44
|
+
return typeof note === 'string' && note.trim() !== '' ? note : undefined;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function readPlanReviewAnswer(answer, shownLabels) {
|
|
38
51
|
const answers = answer?.answers;
|
|
39
52
|
if (!Array.isArray(answers) || answers.length !== 1)
|
|
40
|
-
return
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
return readDismissed();
|
|
54
|
+
const entry = answers[0];
|
|
55
|
+
const picked = entry?.selected;
|
|
56
|
+
if (!Array.isArray(picked))
|
|
57
|
+
return readDismissed();
|
|
58
|
+
const note = freeTextNoteOf(entry);
|
|
59
|
+
if (picked.length === 0) {
|
|
60
|
+
if (note === undefined || !shownLabels.includes(REJECT_LABEL))
|
|
61
|
+
return readDismissed();
|
|
62
|
+
return { choice: { decision: 'reject', reason: note }, noteIgnoredOnApprove: false };
|
|
63
|
+
}
|
|
64
|
+
if (picked.length !== 1)
|
|
65
|
+
return readDismissed();
|
|
44
66
|
const selected = picked[0];
|
|
45
67
|
if (typeof selected !== 'string' || !shownLabels.includes(selected))
|
|
46
|
-
return
|
|
68
|
+
return readDismissed();
|
|
69
|
+
const ignored = note !== undefined;
|
|
47
70
|
if (selected === PLAN_REVIEW_APPROVE_AUTO_LABEL)
|
|
48
|
-
return { decision: 'approve', permissionModeAfter: 'acceptEdits' };
|
|
71
|
+
return { choice: { decision: 'approve', permissionModeAfter: 'acceptEdits' }, noteIgnoredOnApprove: ignored };
|
|
49
72
|
if (selected === PLAN_REVIEW_APPROVE_MANUAL_LABEL)
|
|
50
|
-
return { decision: 'approve', permissionModeAfter: 'default' };
|
|
73
|
+
return { choice: { decision: 'approve', permissionModeAfter: 'default' }, noteIgnoredOnApprove: ignored };
|
|
51
74
|
if (selected === APPROVE_LABEL)
|
|
52
|
-
return { decision: 'approve' };
|
|
75
|
+
return { choice: { decision: 'approve' }, noteIgnoredOnApprove: ignored };
|
|
53
76
|
if (selected === REJECT_LABEL)
|
|
54
|
-
return { decision: 'reject' };
|
|
55
|
-
return
|
|
77
|
+
return { choice: note === undefined ? { decision: 'reject' } : { decision: 'reject', reason: note }, noteIgnoredOnApprove: false };
|
|
78
|
+
return readDismissed();
|
|
79
|
+
}
|
|
80
|
+
export function planReviewChoiceFromAnswer(answer, shownLabels = LEGACY_TWO_CHOICE_LABELS) {
|
|
81
|
+
const { choice, noteIgnoredOnApprove } = readPlanReviewAnswer(answer, shownLabels);
|
|
82
|
+
if (noteIgnoredOnApprove)
|
|
83
|
+
hostLog('debug', 'planReviewWire: note ignored on approve — an approval carries no feedback text; the note was not sent');
|
|
84
|
+
return choice;
|
|
56
85
|
}
|
|
57
86
|
export function planReviewCardOptions(offerModeAfter) {
|
|
58
87
|
const reject = { label: REJECT_LABEL, description: 'Discard this plan and stay in plan mode to refine it' };
|
|
@@ -269,10 +298,12 @@ export function armPlanReviewApproval(result, sessionKey, opts) {
|
|
|
269
298
|
const decided = choice.decision;
|
|
270
299
|
notePlanReviewDecisiveAnswerFor(DEFAULT_SESSION_KEY, taskId);
|
|
271
300
|
const modeAfter = choice.decision === 'approve' ? choice.permissionModeAfter : undefined;
|
|
301
|
+
const cardReason = choice.decision === 'reject' ? choice.reason : undefined;
|
|
302
|
+
const cardDelivery = cardReason !== undefined ? { ...delivery, reason: cardReason } : delivery;
|
|
272
303
|
offerModeAfterByTask.delete(taskId);
|
|
273
304
|
notePlanReviewAnswered(questionId);
|
|
274
305
|
hostLog('debug', `planReviewWire: arm responder delivering ${decided} for task ${taskId} (path=arm)`);
|
|
275
|
-
void decidePlanReviewFor(taskId, decided, modeAfter,
|
|
306
|
+
void decidePlanReviewFor(taskId, decided, modeAfter, cardDelivery, gateBefore);
|
|
276
307
|
return { ok: true };
|
|
277
308
|
});
|
|
278
309
|
publishPlanReviewCard(taskId);
|
|
@@ -309,6 +340,15 @@ export function planReviewOutcomeTail(taskId, decision, effect, cause) {
|
|
|
309
340
|
return `Do not state the result as fact: tell the user the ${decision} was submitted but its effect could not be confirmed; TaskOutput("${taskId}") shows where the task stands.`;
|
|
310
341
|
}
|
|
311
342
|
}
|
|
343
|
+
function clientOnlyView(wire) {
|
|
344
|
+
if (wire === undefined || wire === null || typeof wire !== 'object')
|
|
345
|
+
return wire;
|
|
346
|
+
return {
|
|
347
|
+
get client() {
|
|
348
|
+
return wire.client;
|
|
349
|
+
},
|
|
350
|
+
};
|
|
351
|
+
}
|
|
312
352
|
function planReviewDecisionTimedOutOutcome(decision) {
|
|
313
353
|
return (`The plan_review ${decision} was sent, but no answer came back from the engine within the time limit this host allows for it — ` +
|
|
314
354
|
`it may have taken effect (${decision === 'approve' ? 'an approval keeps the engine busy until the resumed work finishes' : 'the engine may still be applying it'}).`);
|
|
@@ -492,12 +532,12 @@ async function decidePlanReviewInner(taskId, decision, permissionModeAfter, disp
|
|
|
492
532
|
let stillParkedProven = false;
|
|
493
533
|
let statusSeen;
|
|
494
534
|
const wire = opts?.wire;
|
|
495
|
-
const resolved = engineWireFor(wire, DEFAULT_SESSION_KEY, usablePlanReviewWireClient);
|
|
496
|
-
const badMode = permissionModeAfter !== undefined &&
|
|
535
|
+
const resolved = engineWireFor(clientOnlyView(wire), DEFAULT_SESSION_KEY, usablePlanReviewWireClient);
|
|
536
|
+
const badMode = permissionModeAfter !== undefined && !isPlanReviewModeAfter(permissionModeAfter);
|
|
497
537
|
if (badMode) {
|
|
498
|
-
hostLog('error', `planReviewWire: ${decision} NOT sent — permissionModeAfter
|
|
538
|
+
hostLog('error', `planReviewWire: ${decision} NOT sent — permissionModeAfter must be "default" or "acceptEdits"`);
|
|
499
539
|
effect = 'not_sent';
|
|
500
|
-
outcome = `The plan_review ${decision} could NOT be sent: the post-approval permission mode given with it is not valid
|
|
540
|
+
outcome = `The plan_review ${decision} could NOT be sent: the post-approval permission mode given with it is not valid (it must be "default" or "acceptEdits"). Tell the user plainly that the decision did not go through; the plan is still waiting.`;
|
|
501
541
|
}
|
|
502
542
|
else if (resolved.kind === 'no-target') {
|
|
503
543
|
hostLog('error', `planReviewWire: ${decision} NOT sent — engineWireTarget() unavailable`);
|
|
@@ -600,12 +640,15 @@ async function decidePlanReviewInner(taskId, decision, permissionModeAfter, disp
|
|
|
600
640
|
const refusedCode = e?.errorCode;
|
|
601
641
|
const noAnswer = typeof status === 'number' || typeof e !== 'object' ? null : noAnswerKindOf(e);
|
|
602
642
|
if (status === 400 && refusedCode === REQUEST_FIELD_CONFLICT && permissionModeAfter === 'acceptEdits') {
|
|
603
|
-
hostLog('debug',
|
|
643
|
+
hostLog('debug', `planReviewWire: ${decision} + acceptEdits refused (request.field_conflict) — NOT re-sent with a different mode`);
|
|
604
644
|
effect = 'still_parked';
|
|
605
645
|
stillParkedProven = true;
|
|
606
646
|
outcome =
|
|
607
|
-
|
|
608
|
-
'
|
|
647
|
+
decision === 'approve'
|
|
648
|
+
? 'The plan approval was NOT applied: the engine refused "auto-accept edits" for this task (it was not started read-only in plan mode, so that option does not apply). ' +
|
|
649
|
+
'Nothing changed engine-side — the plan is still waiting for review. Tell the user plainly, and that approving with "manually approve edits" will go through.'
|
|
650
|
+
: `The plan ${decision} was NOT applied: the engine refused the post-approval permission mode that was sent with it (request.field_conflict). ` +
|
|
651
|
+
'Nothing changed engine-side — the plan is still waiting for review. Tell the user plainly that the decision did not go through.';
|
|
609
652
|
}
|
|
610
653
|
else if (status === 404 && refusedCode === 'not_found.plan_review') {
|
|
611
654
|
hostLog('debug', `planReviewWire: ${decision} → 404 not_found.plan_review (no pending plan review any more — an earlier decision likely settled it)`);
|
|
@@ -622,6 +665,12 @@ async function decidePlanReviewInner(taskId, decision, permissionModeAfter, disp
|
|
|
622
665
|
stillParkedCause = 'stored_form_unsupported';
|
|
623
666
|
outcome = `This ${decision} was not applied. ${checkpointUnsupportedVersionContent(cu, { parkKind: 'plan_review', runId: taskId })}`;
|
|
624
667
|
}
|
|
668
|
+
else if (resumeContextUnavailableFromError(e) !== null) {
|
|
669
|
+
const ru = resumeContextUnavailableFromError(e);
|
|
670
|
+
hostLog('debug', `planReviewWire: ${decision} → 409 conflict.resume_context_unavailable (the session context needed to continue this run is not available)`);
|
|
671
|
+
effect = 'not_applied';
|
|
672
|
+
outcome = `This ${decision} was not applied. ${resumeContextUnavailableContent(ru)}`;
|
|
673
|
+
}
|
|
625
674
|
else if (typeof status === 'number' && corruptStoredRowWhere(e) !== undefined) {
|
|
626
675
|
const where = corruptStoredRowWhere(e);
|
|
627
676
|
hostLog('debug', `planReviewWire: ${decision} → ${String(status)} corrupt (stored resume context unreadable)`);
|
|
@@ -643,7 +692,9 @@ async function decidePlanReviewInner(taskId, decision, permissionModeAfter, disp
|
|
|
643
692
|
outcome = planReviewDecisionConnectionLostOutcome(decision);
|
|
644
693
|
}
|
|
645
694
|
else {
|
|
646
|
-
|
|
695
|
+
const failureTexts = wireFailureTextsOf(e);
|
|
696
|
+
hostLog('debug', `planReviewWire: ${decision} could not reach the engine: ${failureTexts.log}`);
|
|
697
|
+
outcome = `The plan_review decision could not reach the engine: ${failureTexts.reason}`;
|
|
647
698
|
}
|
|
648
699
|
}
|
|
649
700
|
}
|
|
@@ -800,9 +851,10 @@ function mintPlanReviewReopenCard(taskId, opts, sessionKey, receiptMs) {
|
|
|
800
851
|
? { ...(opts.wire !== undefined ? { wire: opts.wire } : {}), ...(opts.onOutcome !== undefined ? { onOutcome: opts.onOutcome } : {}) }
|
|
801
852
|
: undefined;
|
|
802
853
|
const deliver = opts?.deliverDecision ??
|
|
803
|
-
((tid, decision) => {
|
|
854
|
+
((tid, decision, reason) => {
|
|
804
855
|
hostLog('debug', `planReviewWire: reopen responder delivering ${decision} for task ${tid} (path=reopen-default)`);
|
|
805
|
-
|
|
856
|
+
const withReason = reason === undefined ? delivery : { ...delivery, reason };
|
|
857
|
+
void (withReason === undefined ? decidePlanReview(tid, decision) : decidePlanReview(tid, decision, undefined, withReason));
|
|
806
858
|
});
|
|
807
859
|
const activeKey = `${sessionKey}\u0000${canonicalId}`;
|
|
808
860
|
const unregister = registerLocalQuestionResponder(questionId, async (_id, answer) => {
|
|
@@ -810,15 +862,20 @@ function mintPlanReviewReopenCard(taskId, opts, sessionKey, receiptMs) {
|
|
|
810
862
|
if (activeReopenResponders.get(activeKey)?.questionId === questionId) {
|
|
811
863
|
activeReopenResponders.delete(activeKey);
|
|
812
864
|
}
|
|
813
|
-
const
|
|
814
|
-
if (
|
|
865
|
+
const choice = planReviewChoiceFromAnswer(answer, LEGACY_TWO_CHOICE_LABELS);
|
|
866
|
+
if (choice === 'dismissed') {
|
|
815
867
|
notePlanReviewUserDismissalFor(sessionKey, taskId, opts?.readGateInstanceKeys, questionId);
|
|
816
868
|
return { ok: true };
|
|
817
869
|
}
|
|
870
|
+
const decided = choice.decision;
|
|
871
|
+
const cardReason = choice.decision === 'reject' ? choice.reason : undefined;
|
|
818
872
|
notePlanReviewDecisiveAnswerFor(sessionKey, taskId);
|
|
819
873
|
notePlanReviewAnsweredFor(sessionKey, questionId);
|
|
820
874
|
try {
|
|
821
|
-
|
|
875
|
+
if (cardReason === undefined)
|
|
876
|
+
await deliver(taskId, decided);
|
|
877
|
+
else
|
|
878
|
+
await deliver(taskId, decided, cardReason);
|
|
822
879
|
}
|
|
823
880
|
catch (e) {
|
|
824
881
|
hostLog('error', `planReviewWire: reopen decision delivery threw for task ${taskId}: ${String(e)}`);
|
|
@@ -866,18 +923,8 @@ async function reopenAfterDismissalCheck(taskId, opts, sessionKey, receiptMs, ma
|
|
|
866
923
|
}
|
|
867
924
|
}
|
|
868
925
|
}
|
|
869
|
-
let handedOver = false;
|
|
870
926
|
const ledgerSaysInFlight = planReviewDecisionInFlight(taskId, recheckReadStart);
|
|
871
|
-
if (
|
|
872
|
-
try {
|
|
873
|
-
handedOver = opts.decisionHandedOver?.(taskId) === true;
|
|
874
|
-
}
|
|
875
|
-
catch (err) {
|
|
876
|
-
hostLog('debug', `planReviewWire: reopen for task ${taskId} refused — the host's decision hand-over check threw: ${String(err)}`);
|
|
877
|
-
return { reopened: false };
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
if (ledgerSaysInFlight || handedOver) {
|
|
927
|
+
if (ledgerSaysInFlight) {
|
|
881
928
|
hostLog('debug', `planReviewWire: reopen for task ${taskId} refused after the dismissal check — a decision for this task went out while the check was reading`);
|
|
882
929
|
return { reopened: false, _sema_decisionInFlight: true };
|
|
883
930
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ApprovalSettledHow } from './gateLedger.js';
|
|
1
2
|
import { type ApprovalsListEnvelope, type CrashConvergedRow } from './crashConverged.js';
|
|
2
3
|
export type ReplayedApprovalDisposition = {
|
|
3
4
|
readonly kind: 'live';
|
|
@@ -5,6 +6,8 @@ export type ReplayedApprovalDisposition = {
|
|
|
5
6
|
} | {
|
|
6
7
|
readonly kind: 'decided';
|
|
7
8
|
readonly cause?: CrashConvergedRow['cause'];
|
|
9
|
+
readonly needsHumanReason?: NonNullable<CrashConvergedRow['needsHumanReason']>;
|
|
10
|
+
readonly settled?: ApprovalSettledHow;
|
|
8
11
|
} | {
|
|
9
12
|
readonly kind: 'unknown';
|
|
10
13
|
readonly why: 'unreadable_frame' | 'no_approval_id' | 'not_read' | 'list_unreadable' | 'list_not_reported' | 'list_incomplete';
|
|
@@ -17,5 +20,10 @@ export interface ReplayPendingBasis {
|
|
|
17
20
|
} | {
|
|
18
21
|
readonly read: 'failed';
|
|
19
22
|
};
|
|
23
|
+
readonly settled?: ReadonlyMap<string, ApprovalSettledHow>;
|
|
20
24
|
}
|
|
25
|
+
export declare function settledApprovalDisposition(frame: object, settled: ReplayPendingBasis['settled']): ReplayedApprovalDisposition | undefined;
|
|
21
26
|
export declare function replayedApprovalDisposition(frame: object, basis: ReplayPendingBasis): ReplayedApprovalDisposition;
|
|
27
|
+
export declare function replayedApprovalSentence(disposition: ReplayedApprovalDisposition | undefined, opts?: {
|
|
28
|
+
readonly toolName?: string;
|
|
29
|
+
}): string | undefined;
|