@sema-agent/client-core 0.110.0 → 0.112.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 +244 -0
- package/README.md +59 -18
- package/dist/abortableSleep.d.ts +7 -0
- package/dist/abortableSleep.js +37 -0
- package/dist/adapt/arms.js +25 -4
- package/dist/adapt/toolCards.d.ts +3 -1
- package/dist/adapt/toolCards.js +4 -2
- package/dist/adapter/activeRunSelfHeal.d.ts +39 -0
- package/dist/adapter/activeRunSelfHeal.js +171 -3
- package/dist/adapter/downstream/eventToSdkMessage.js +10 -10
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +2 -0
- package/dist/adapter/downstream/terminalToSdkResult.js +11 -0
- package/dist/adapter/runStream.d.ts +5 -0
- package/dist/adapter/runStream.js +15 -3
- package/dist/agentSession/engineSessionBackgroundStop.js +2 -2
- package/dist/attachmentRoute.d.ts +20 -0
- package/dist/attachmentRoute.js +39 -0
- package/dist/attachmentsWireCaps.js +1 -1
- package/dist/builtinOutputStyles.d.ts +12 -0
- package/dist/builtinOutputStyles.js +147 -0
- package/dist/checkpointRowVerdict.d.ts +3 -0
- package/dist/checkpointRowVerdict.js +14 -1
- package/dist/compactionStatus.d.ts +9 -0
- package/dist/compactionStatus.js +29 -5
- package/dist/consoleCaPin.d.ts +136 -0
- package/dist/consoleCaPin.js +827 -0
- package/dist/controlRouter.js +2 -1
- package/dist/coreValuePorts.d.ts +39 -1
- package/dist/coreValuePorts.js +10 -0
- package/dist/decideReceipt.d.ts +2 -1
- package/dist/deviceRebind.js +3 -3
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +6 -0
- package/dist/effectiveFacts.d.ts +9 -0
- package/dist/effectiveFacts.js +33 -0
- package/dist/engineAddress.d.ts +1 -0
- package/dist/engineAddress.js +4 -1
- package/dist/engineCredentialRelease.d.ts +54 -0
- package/dist/engineCredentialRelease.js +146 -0
- package/dist/engineErrorCodes.d.ts +1 -0
- package/dist/engineErrorCodes.js +1 -0
- package/dist/engineHealthProbeVerdict.d.ts +24 -0
- package/dist/engineHealthProbeVerdict.js +123 -0
- package/dist/engineNoticeCodes.js +5 -7
- package/dist/engineRepoint.d.ts +12 -5
- package/dist/engineRepoint.js +44 -19
- package/dist/engineRowRef.d.ts +3 -0
- package/dist/engineRowRef.js +11 -1
- package/dist/engineSwapCrossing.d.ts +57 -0
- package/dist/engineSwapCrossing.js +297 -0
- package/dist/engineUnavailable.d.ts +45 -0
- package/dist/engineUnavailable.js +496 -0
- package/dist/engineUrl.js +4 -2
- package/dist/eventLeg.js +3 -3
- package/dist/gateFailureCodes.js +2 -2
- package/dist/generated/sdkFactTables.d.ts +2 -1
- package/dist/generated/sdkFactTables.js +14 -0
- package/dist/generated/settingsSchemaFns.d.ts +1 -0
- package/dist/generated/settingsSchemaFns.js +3 -0
- package/dist/generated/settingsSchemaHooksClassifier.js +38 -9
- package/dist/generated/settingsSchemaTables.d.ts +56 -0
- package/dist/generated/settingsSchemaTables.js +19 -0
- package/dist/generated/settingsSchemaTypes.d.ts +23 -13
- package/dist/generated/settingsSchemaUrlShape.d.ts +1 -0
- package/dist/generated/settingsSchemaUrlShape.js +17 -0
- package/dist/hitl/approvalDelivery.d.ts +1 -0
- package/dist/hitl/approvalDelivery.js +1 -1
- package/dist/hitl/approvalResolution.d.ts +1 -1
- package/dist/hitl/approvalResolution.js +2 -1
- package/dist/hitl/askGateWire.js +5 -6
- package/dist/hitl/decisionRefusal.d.ts +6 -0
- package/dist/hitl/decisionRefusal.js +19 -10
- package/dist/hitl/decisionRefusalCarrier.d.ts +3 -0
- package/dist/hitl/decisionRefusalCarrier.js +348 -0
- package/dist/hitl/decisionSend.d.ts +7 -0
- package/dist/hitl/decisionSend.js +34 -12
- package/dist/hitl/editedApprovalAcceptance.js +1 -1
- package/dist/hitl/elicitationRefusal.d.ts +4 -0
- package/dist/hitl/elicitationRefusal.js +23 -0
- package/dist/hitl/frameRouter.d.ts +2 -2
- package/dist/hitl/frameRouter.js +8 -15
- package/dist/hitl/gateIdentity.d.ts +5 -0
- package/dist/hitl/gateIdentity.js +23 -0
- package/dist/hitl/hitlBridge.d.ts +6 -0
- package/dist/hitl/hitlBridge.js +10 -4
- package/dist/hitl/hitlHostSurface.d.ts +2 -1
- package/dist/hitl/hitlHostSurface.js +7 -2
- package/dist/hitl/localAllowRedemption.d.ts +70 -0
- package/dist/hitl/localAllowRedemption.js +276 -0
- package/dist/hitl/parkOwnership.js +2 -1
- package/dist/hitl/parkResolver.js +14 -4
- package/dist/hitl/persistedRulesWire.d.ts +16 -0
- package/dist/hitl/persistedRulesWire.js +70 -0
- package/dist/hitl/planReviewWire.d.ts +3 -0
- package/dist/hitl/planReviewWire.js +23 -6
- package/dist/hitl/policyDenyCause.d.ts +1 -1
- package/dist/hitl/policyDenyCause.js +1 -1
- package/dist/hitl/resumeRunningCard.d.ts +1 -0
- package/dist/hitl/resumeRunningCard.js +1 -0
- package/dist/hitl/screenCardCarriers.d.ts +15 -0
- package/dist/hitl/screenCardCarriers.js +41 -0
- package/dist/hitl/screenDecisionCards.d.ts +98 -0
- package/dist/hitl/screenDecisionCards.js +363 -0
- package/dist/hitl/sessionPolicyWire.js +2 -2
- package/dist/hitl/standingRows.d.ts +6 -2
- package/dist/hitl/standingRows.js +27 -2
- package/dist/hitl/toolApprovalWire.d.ts +30 -8
- package/dist/hitl/toolApprovalWire.js +264 -121
- package/dist/hooksReaderGenerations.js +1 -1
- package/dist/hooksWireCaps.js +3 -3
- package/dist/hostSettingNoticeArm.d.ts +3 -0
- package/dist/hostSettingNoticeArm.js +12 -0
- package/dist/hostTurnSettings.d.ts +3 -0
- package/dist/hostTurnSettings.js +38 -5
- package/dist/humanTurnRead.js +11 -1
- package/dist/i18n/messages.en.d.ts +292 -0
- package/dist/i18n/messages.en.js +298 -7
- package/dist/i18n/messages.zh.js +316 -6
- package/dist/i18n/translate.d.ts +3 -0
- package/dist/i18n/translate.js +78 -10
- package/dist/i18n/zh.d.ts +1 -0
- package/dist/i18n/zh.js +1 -0
- package/dist/index.d.ts +71 -20
- package/dist/index.js +44 -13
- package/dist/interactiveHalt.js +2 -1
- package/dist/interactiveInterrupt.js +20 -2
- package/dist/liveModelCatalog.d.ts +4 -0
- package/dist/liveModelCatalog.js +12 -3
- package/dist/localConfig/documents.d.ts +61 -0
- package/dist/localConfig/documents.js +51 -0
- package/dist/localConfig/kernel.d.ts +149 -0
- package/dist/localConfig/kernel.js +597 -0
- package/dist/localConfig/mcp/edit.d.ts +161 -0
- package/dist/localConfig/mcp/edit.js +846 -0
- package/dist/localConfig/mcp/servers.d.ts +165 -0
- package/dist/localConfig/mcp/servers.js +776 -0
- package/dist/localConfig/mcp/views.d.ts +170 -0
- package/dist/localConfig/mcp/views.js +429 -0
- package/dist/localConfig/modelPool.d.ts +262 -0
- package/dist/localConfig/modelPool.js +1489 -0
- package/dist/localConfig/modelPoolWords.d.ts +13 -0
- package/dist/localConfig/modelPoolWords.js +20 -0
- package/dist/localConfig/receiptShape.d.ts +7 -0
- package/dist/localConfig/receiptShape.js +135 -0
- package/dist/localConfig/settingsWrite.d.ts +127 -0
- package/dist/localConfig/settingsWrite.js +237 -0
- package/dist/localConfig/skills.d.ts +124 -0
- package/dist/localConfig/skills.js +397 -0
- package/dist/localConfig/skillsWords.d.ts +10 -0
- package/dist/localConfig/skillsWords.js +5 -0
- package/dist/localEngineSeatReading.d.ts +2 -2
- package/dist/localEngineSeatReading.js +5 -3
- package/dist/localEngineSpawn.d.ts +0 -7
- package/dist/localEngineSpawn.js +0 -92
- package/dist/localEngineStep.d.ts +2 -2
- package/dist/localEngineStep.js +2 -0
- package/dist/mcpProbeWire.js +2 -1
- package/dist/mcpReconnect.js +3 -3
- package/dist/mcpWireCaps.js +1 -1
- package/dist/memoryVerbsWire.js +3 -2
- package/dist/model/engineModelWords.d.ts +3 -0
- package/dist/model/engineModelWords.js +13 -0
- package/dist/model/onboardJudgement.d.ts +14 -4
- package/dist/model/onboardJudgement.js +91 -139
- package/dist/model/subagentModelWord.d.ts +21 -2
- package/dist/model/subagentModelWord.js +100 -29
- package/dist/modelCapabilityProbe.js +3 -40
- package/dist/modelConfigGapNotice.d.ts +20 -0
- package/dist/modelConfigGapNotice.js +102 -0
- package/dist/modsKernelIdentity.js +2 -47
- package/dist/notifications.d.ts +19 -0
- package/dist/notifications.js +114 -12
- package/dist/ownKey.d.ts +7 -0
- package/dist/ownKey.js +71 -8
- package/dist/pendingUserRow.d.ts +4 -0
- package/dist/pendingUserRow.js +16 -0
- package/dist/permissionsDeclaration.d.ts +3 -1
- package/dist/permissionsDeclaration.js +33 -9
- package/dist/planReviewCardFacts.d.ts +3 -0
- package/dist/planReviewCardFacts.js +52 -2
- package/dist/pluginHooksWire.d.ts +9 -1
- package/dist/pluginHooksWire.js +40 -6
- package/dist/printToolResultFrame.js +4 -2
- package/dist/promptBlockedCopy.js +12 -7
- package/dist/promptSuggestionBatch.d.ts +7 -0
- package/dist/promptSuggestionBatch.js +9 -0
- package/dist/promptSuggestionsTail.d.ts +39 -0
- package/dist/promptSuggestionsTail.js +116 -0
- package/dist/request/taskRequest.js +10 -6
- package/dist/requestCoordinate.d.ts +1 -0
- package/dist/requestCoordinate.js +13 -0
- package/dist/resumeRefusalCopy.d.ts +3 -1
- package/dist/resumeRefusalCopy.js +12 -4
- package/dist/rewindArchiveReading.js +4 -4
- package/dist/runCancelContext.d.ts +2 -1
- package/dist/runCancelContext.js +1 -0
- package/dist/runLedgerSnapshot.js +3 -3
- package/dist/runPermissionModeSwitch.js +3 -4
- package/dist/scenarioRefusal.js +11 -13
- package/dist/scenarioSkills.js +11 -6
- package/dist/seam.d.ts +16 -2
- package/dist/seam.js +10 -0
- package/dist/seatContract.d.ts +259 -9
- package/dist/seatContract.js +444 -15
- package/dist/sessionCostReading.d.ts +70 -0
- package/dist/sessionCostReading.js +150 -0
- package/dist/sessionHooksRoster.d.ts +4 -0
- package/dist/sessionHooksRoster.js +158 -0
- package/dist/sessionIdSegment.d.ts +1 -0
- package/dist/sessionIdSegment.js +4 -1
- package/dist/sessionMemoryErase.js +2 -1
- package/dist/sessionMemoryStatus.js +2 -2
- package/dist/sessionReadRedaction.d.ts +7 -0
- package/dist/sessionReadRedaction.js +26 -0
- package/dist/sessionSyncFileHistory.js +8 -9
- package/dist/settingsHooksSalvage.js +2 -1
- package/dist/sha256Bytes.d.ts +1 -0
- package/dist/sha256Bytes.js +46 -0
- package/dist/skillOverrideChain.d.ts +83 -0
- package/dist/skillOverrideChain.js +378 -0
- package/dist/skillsWireCaps.d.ts +3 -0
- package/dist/skillsWireCaps.js +16 -1
- package/dist/sseIdleTriage.js +2 -1
- package/dist/storeDurabilityWord.d.ts +15 -0
- package/dist/storeDurabilityWord.js +18 -0
- package/dist/storePostureCapability.d.ts +7 -3
- package/dist/storePostureCapability.js +69 -39
- package/dist/subagent/engineSubagentResume.js +2 -2
- package/dist/subagent/engineSubagentTail.js +2 -1
- package/dist/subagentContentStore.d.ts +11 -0
- package/dist/subagentContentStore.js +28 -2
- package/dist/toolResult.d.ts +1 -0
- package/dist/toolResult.js +2 -0
- package/dist/turnFailurePresentation.js +4 -10
- package/dist/userAttachmentEnvelope.d.ts +2 -1
- package/dist/userAttachmentEnvelope.js +10 -0
- package/dist/wireErrorTriage.js +2 -1
- package/dist/wireFailureShape.d.ts +4 -0
- package/dist/wireFailureShape.js +141 -19
- package/dist/wireRefusalCopy.d.ts +6 -5
- package/dist/wireRefusalCopy.js +49 -92
- package/docs/INTEGRATION-CLIENTS.md +2718 -17
- package/package.json +7 -3
|
@@ -41,6 +41,8 @@ export interface PlanReviewCardView {
|
|
|
41
41
|
readonly note?: string;
|
|
42
42
|
}
|
|
43
43
|
export declare function planReviewCardViewOf(frame: object | null | undefined, lang?: UiLanguage): PlanReviewCardView | undefined;
|
|
44
|
+
export type PlanReviewEvidenceMove = 'same' | 'moved' | 'unknown';
|
|
45
|
+
export declare function planReviewEvidenceMovedOf(shown: object | null | undefined, latest: object | null | undefined): PlanReviewEvidenceMove;
|
|
44
46
|
export declare function notePlanReviewAnsweredIfDecisive(questionId: unknown, answer: QuestionAnswer | null | undefined): void;
|
|
45
47
|
export { isPlanReviewPark };
|
|
46
48
|
export declare function _resetArmedPlanReviewsForTest(): void;
|
|
@@ -79,6 +81,7 @@ export interface PlanReviewOutcomeMeta {
|
|
|
79
81
|
decision: 'approve' | 'reject' | 'ask_again';
|
|
80
82
|
effect: PlanReviewDecisionEffect;
|
|
81
83
|
cause?: 'stored_form_unsupported';
|
|
84
|
+
questionId?: string;
|
|
82
85
|
}
|
|
83
86
|
export declare function planReviewOutcomeTail(taskId: string, decision: 'approve' | 'reject', effect: PlanReviewDecisionEffect, cause?: 'stored_form_unsupported'): string;
|
|
84
87
|
export type PlanReviewWireClient = {
|
|
@@ -150,6 +150,22 @@ export function planReviewCardViewOf(frame, lang) {
|
|
|
150
150
|
return Object.freeze({ options: OPTIONS_BY_SHAPE.withheld, note: renderMessage(planReviewUnreadableNoteRef(), lang) });
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
+
export function planReviewEvidenceMovedOf(shown, latest) {
|
|
154
|
+
try {
|
|
155
|
+
const a = planReviewCardFactsFrom(shown);
|
|
156
|
+
const b = planReviewCardFactsFrom(latest);
|
|
157
|
+
if (a === undefined || b === undefined || a.taskId !== b.taskId)
|
|
158
|
+
return 'unknown';
|
|
159
|
+
if (a.checkpointId !== undefined && b.checkpointId !== undefined && a.checkpointId !== b.checkpointId)
|
|
160
|
+
return 'moved';
|
|
161
|
+
if (a.evidenceRevision === undefined || b.evidenceRevision === undefined)
|
|
162
|
+
return 'unknown';
|
|
163
|
+
return a.evidenceRevision === b.evidenceRevision ? 'same' : 'moved';
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return 'unknown';
|
|
167
|
+
}
|
|
168
|
+
}
|
|
153
169
|
export function notePlanReviewAnsweredIfDecisive(questionId, answer) {
|
|
154
170
|
notePlanReviewAnsweredIfDecisiveFor(DEFAULT_SESSION_KEY, questionId, answer);
|
|
155
171
|
}
|
|
@@ -524,7 +540,7 @@ export function armPlanReviewApproval(result, sessionKey, opts) {
|
|
|
524
540
|
const cardDelivery = cardReason !== undefined ? { ...delivery, reason: cardReason } : delivery;
|
|
525
541
|
notePlanReviewAnswered(questionId);
|
|
526
542
|
hostLog('debug', `planReviewWire: arm responder delivering ${decided} for task ${taskId} (path=arm)`);
|
|
527
|
-
void decidePlanReviewFor(taskId, decided, modeAfter, cardDelivery, facts);
|
|
543
|
+
void decidePlanReviewFor(taskId, decided, modeAfter, cardDelivery, facts, questionId);
|
|
528
544
|
return { ok: true };
|
|
529
545
|
};
|
|
530
546
|
unregister = registerLocalQuestionResponder(questionId, responder, onWithdraw);
|
|
@@ -725,7 +741,7 @@ function askAgainReasonOf(card, opts) {
|
|
|
725
741
|
return renderMessage(msg('approval.planReview.askAgain.unknown'), DATA_FACE_LANGUAGE);
|
|
726
742
|
}
|
|
727
743
|
}
|
|
728
|
-
async function decidePlanReviewFor(taskId, decision, permissionModeAfter, opts, card) {
|
|
744
|
+
async function decidePlanReviewFor(taskId, decision, permissionModeAfter, opts, card, cardId) {
|
|
729
745
|
if (typeof taskId === 'string' && planReviewOpsOf(taskId).some((op) => op.phase === 'posting')) {
|
|
730
746
|
hostLog('error', `planReviewWire: decidePlanReview(${decision}) for task ${taskId} REFUSED — a decision for this task is already in flight (duplicate delivery latched)`);
|
|
731
747
|
return;
|
|
@@ -758,7 +774,7 @@ async function decidePlanReviewFor(taskId, decision, permissionModeAfter, opts,
|
|
|
758
774
|
try {
|
|
759
775
|
const wireDecision = decision === 'ask_again' ? 'reject' : decision;
|
|
760
776
|
const wireOpts = decision === 'ask_again' ? { ...opts, reason: askAgainReasonOf(card, opts) } : opts;
|
|
761
|
-
await decidePlanReviewInner(taskId, wireDecision, permissionModeAfter, dispatchNo, releaseLatch, settle, wireOpts, card, decision);
|
|
777
|
+
await decidePlanReviewInner(taskId, wireDecision, permissionModeAfter, dispatchNo, releaseLatch, settle, wireOpts, card, decision, cardId);
|
|
762
778
|
}
|
|
763
779
|
finally {
|
|
764
780
|
releaseLatch();
|
|
@@ -779,7 +795,7 @@ function planReviewClientsFor(resolved) {
|
|
|
779
795
|
repull: () => resolved.make({ timeoutMs: 15_000 }),
|
|
780
796
|
};
|
|
781
797
|
}
|
|
782
|
-
async function decidePlanReviewInner(taskId, decision, permissionModeAfter, dispatchNo, releaseLatch, settle, opts, card, semanticDecision) {
|
|
798
|
+
async function decidePlanReviewInner(taskId, decision, permissionModeAfter, dispatchNo, releaseLatch, settle, opts, card, semanticDecision, cardId) {
|
|
783
799
|
let outcome;
|
|
784
800
|
let decisionReason;
|
|
785
801
|
const gateBefore = card?.checkpointId;
|
|
@@ -1019,7 +1035,7 @@ async function decidePlanReviewInner(taskId, decision, permissionModeAfter, disp
|
|
|
1019
1035
|
const onOutcome = opts?.onOutcome;
|
|
1020
1036
|
settle(effect === 'not_sent' || effect === 'still_parked');
|
|
1021
1037
|
try {
|
|
1022
|
-
const delivered = enqueuePlanReviewOutcome(prompt, { taskId, dispatchNo, decision: semanticDecision, effect, ...(effect === 'still_parked' && stillParkedCause !== undefined ? { cause: stillParkedCause } : {}) });
|
|
1038
|
+
const delivered = enqueuePlanReviewOutcome(prompt, { taskId, dispatchNo, decision: semanticDecision, effect, ...(effect === 'still_parked' && stillParkedCause !== undefined ? { cause: stillParkedCause } : {}), ...(cardId !== undefined ? { questionId: cardId } : {}) });
|
|
1023
1039
|
if (!delivered) {
|
|
1024
1040
|
if (onOutcome !== undefined) {
|
|
1025
1041
|
hostLog('debug', `planReviewWire: outcome queue port not installed for task ${taskId} — outcome handed to the host's onOutcome callback only`);
|
|
@@ -1039,6 +1055,7 @@ async function decidePlanReviewInner(taskId, decision, permissionModeAfter, disp
|
|
|
1039
1055
|
decision: semanticDecision,
|
|
1040
1056
|
effect,
|
|
1041
1057
|
...(effect === 'still_parked' && stillParkedCause !== undefined ? { cause: stillParkedCause } : {}),
|
|
1058
|
+
...(cardId !== undefined ? { questionId: cardId } : {}),
|
|
1042
1059
|
detail: outcome,
|
|
1043
1060
|
tail,
|
|
1044
1061
|
prompt,
|
|
@@ -1160,7 +1177,7 @@ function mintPlanReviewReopenCard(taskId, opts, sessionKey, receiptMs, taken) {
|
|
|
1160
1177
|
((tid, decision, reason, card) => {
|
|
1161
1178
|
hostLog('debug', `planReviewWire: reopen responder delivering ${decision} for task ${tid} (path=reopen-default)`);
|
|
1162
1179
|
const withReason = reason === undefined ? delivery : { ...delivery, reason };
|
|
1163
|
-
void decidePlanReviewFor(tid, decision, undefined, withReason, card);
|
|
1180
|
+
void decidePlanReviewFor(tid, decision, undefined, withReason, card, questionId);
|
|
1164
1181
|
});
|
|
1165
1182
|
const activeKey = `${sessionKey}\u0000${canonicalId}`;
|
|
1166
1183
|
let unregister = () => { };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const POLICY_DENY_CAUSES: readonly ["no_approval_ui", "dont_ask", "deny_rule", "engine_floor"];
|
|
1
|
+
export declare const POLICY_DENY_CAUSES: readonly ["no_approval_ui", "dont_ask", "deny_rule", "engine_floor", "hook"];
|
|
2
2
|
export type PolicyDenyCause = (typeof POLICY_DENY_CAUSES)[number];
|
|
3
3
|
export declare function readPolicyDenyCause(decision: object | null | undefined): PolicyDenyCause | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const POLICY_DENY_CAUSES = Object.freeze(['no_approval_ui', 'dont_ask', 'deny_rule', 'engine_floor']);
|
|
1
|
+
export const POLICY_DENY_CAUSES = Object.freeze(['no_approval_ui', 'dont_ask', 'deny_rule', 'engine_floor', 'hook']);
|
|
2
2
|
export function readPolicyDenyCause(decision) {
|
|
3
3
|
if (decision === null || typeof decision !== 'object')
|
|
4
4
|
return undefined;
|
|
@@ -21,6 +21,7 @@ export declare function runningAttachOffered(canAttach: boolean | undefined): bo
|
|
|
21
21
|
export declare function resumeRunningOptions(i: ResumeRunningCardInput): ResumeRunningCardOption[];
|
|
22
22
|
export declare function resumeChoiceFromLabels(selected: readonly string[] | null | undefined): ResumeRunningChoice;
|
|
23
23
|
export declare const RESUME_RUNNING_NO_UI_EXIT_CODE = 75;
|
|
24
|
+
export declare const ENGINE_UNAVAILABLE_EXIT_CODE = 69;
|
|
24
25
|
export declare const RESUME_RUNNING_GUIDANCE_TAG = "sema: resume-running:";
|
|
25
26
|
export declare function resumeRunningNoUiGuidance(i: {
|
|
26
27
|
taskId: string;
|
|
@@ -50,6 +50,7 @@ export function resumeChoiceFromLabels(selected) {
|
|
|
50
50
|
return 'background';
|
|
51
51
|
}
|
|
52
52
|
export const RESUME_RUNNING_NO_UI_EXIT_CODE = 75;
|
|
53
|
+
export const ENGINE_UNAVAILABLE_EXIT_CODE = 69;
|
|
53
54
|
export const RESUME_RUNNING_GUIDANCE_TAG = 'sema: resume-running:';
|
|
54
55
|
export function resumeRunningNoUiGuidance(i) {
|
|
55
56
|
const sid = typeof i.sessionId === 'string' && i.sessionId.length > 0 ? i.sessionId : null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const PARK_GATE_KEY = "_sema_parkGate";
|
|
2
|
+
export declare function sourceGenerationNow(deps: {
|
|
3
|
+
readonly engineGeneration?: () => number;
|
|
4
|
+
} | null | undefined): number | undefined;
|
|
5
|
+
export declare function parkQuestionFrameBits(taskId: string, gatedCallId: string | undefined, sourceGeneration: number | undefined): {
|
|
6
|
+
readonly _sema_parkGate?: {
|
|
7
|
+
readonly taskId: string;
|
|
8
|
+
readonly gatedCallId: string;
|
|
9
|
+
};
|
|
10
|
+
readonly _sema_sourceGeneration?: number;
|
|
11
|
+
};
|
|
12
|
+
export declare function sourceGenerationBit(sourceGeneration: number | undefined): {
|
|
13
|
+
readonly sourceGeneration?: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function questionFrameSourceGenerationOf(frame: object | null | undefined): number | undefined;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { slotReadOf } from '../wireFailureShape.js';
|
|
2
|
+
import { engineGenerationReadingOf } from '../engineGenerationPort.js';
|
|
3
|
+
export const PARK_GATE_KEY = '_sema_parkGate';
|
|
4
|
+
const SOURCE_GENERATION_KEY = '_sema_sourceGeneration';
|
|
5
|
+
const nonEmpty = (v) => typeof v === 'string' && v.length > 0;
|
|
6
|
+
const finite = (v) => typeof v === 'number' && Number.isFinite(v);
|
|
7
|
+
export function sourceGenerationNow(deps) {
|
|
8
|
+
try {
|
|
9
|
+
if (typeof deps !== 'object' || deps === null)
|
|
10
|
+
return undefined;
|
|
11
|
+
const read = deps.engineGeneration;
|
|
12
|
+
if (typeof read !== 'function')
|
|
13
|
+
return undefined;
|
|
14
|
+
const r = engineGenerationReadingOf(() => read.call(deps));
|
|
15
|
+
return r.known ? r.generation : undefined;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function parkQuestionFrameBits(taskId, gatedCallId, sourceGeneration) {
|
|
22
|
+
return {
|
|
23
|
+
...(nonEmpty(taskId) && nonEmpty(gatedCallId) ? { _sema_parkGate: Object.freeze({ taskId, gatedCallId }) } : {}),
|
|
24
|
+
...(finite(sourceGeneration) ? { _sema_sourceGeneration: sourceGeneration } : {}),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function sourceGenerationBit(sourceGeneration) {
|
|
28
|
+
return finite(sourceGeneration) ? { sourceGeneration } : {};
|
|
29
|
+
}
|
|
30
|
+
export function questionFrameSourceGenerationOf(frame) {
|
|
31
|
+
try {
|
|
32
|
+
if (typeof frame !== 'object' || frame === null)
|
|
33
|
+
return undefined;
|
|
34
|
+
const r = slotReadOf(frame, SOURCE_GENERATION_KEY);
|
|
35
|
+
const v = r.presence === 'present' ? r.value : undefined;
|
|
36
|
+
return finite(v) ? v : undefined;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { type ScreenCardOrigin } from './gateIdentity.js';
|
|
2
|
+
import { type EndedGenerationOpenedCall, type EndedGenerationPhaseChange, type EndedGenerationPhaseHold } from '../engineGenerationConvergence.js';
|
|
3
|
+
import type { HostWithdrawal } from './hostWithdrawal.js';
|
|
4
|
+
export type ScreenCardGate = {
|
|
5
|
+
readonly kind: 'tool';
|
|
6
|
+
readonly taskId: string;
|
|
7
|
+
readonly gatedCallId: string;
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: 'plan';
|
|
10
|
+
readonly taskId: string;
|
|
11
|
+
readonly checkpointId?: string;
|
|
12
|
+
};
|
|
13
|
+
export interface ScreenCardWindow {
|
|
14
|
+
readonly leftMs?: number;
|
|
15
|
+
readonly closedByEngine?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface ScreenDecisionCard {
|
|
18
|
+
readonly instance: string;
|
|
19
|
+
readonly origin?: ScreenCardOrigin;
|
|
20
|
+
readonly gate?: ScreenCardGate;
|
|
21
|
+
readonly sourceGeneration?: number;
|
|
22
|
+
readonly toolCallId?: string;
|
|
23
|
+
readonly window?: ScreenCardWindow;
|
|
24
|
+
}
|
|
25
|
+
export declare const SCREEN_CARD_KEEP_REASONS: readonly ["not-ready", "generation-moved", "not-withdrawable", "no-gate", "not-early", "no-row", "not-owned", "verdict-ok", "verdict-absent"];
|
|
26
|
+
export type ScreenCardKeepReason = (typeof SCREEN_CARD_KEEP_REASONS)[number];
|
|
27
|
+
export interface EngineGenerationEndedCardFacts {
|
|
28
|
+
readonly phase: 'ended';
|
|
29
|
+
readonly endedGeneration: number;
|
|
30
|
+
readonly cards: readonly ScreenDecisionCard[];
|
|
31
|
+
readonly opened: readonly EndedGenerationOpenedCall[];
|
|
32
|
+
readonly phases?: readonly EndedGenerationPhaseHold[];
|
|
33
|
+
}
|
|
34
|
+
export interface EngineGenerationReadyCardFacts<R extends object> {
|
|
35
|
+
readonly phase: 'ready';
|
|
36
|
+
readonly generation: number;
|
|
37
|
+
readonly ready: boolean;
|
|
38
|
+
readonly readGeneration: number;
|
|
39
|
+
readonly cards: readonly ScreenDecisionCard[];
|
|
40
|
+
readonly rows: readonly R[];
|
|
41
|
+
readonly isOwned: (row: R) => boolean;
|
|
42
|
+
readonly withdrawable: readonly ScreenCardOrigin[];
|
|
43
|
+
}
|
|
44
|
+
export interface EngineGenerationEndedCardPlan {
|
|
45
|
+
readonly phase: 'ended';
|
|
46
|
+
readonly retract: readonly string[];
|
|
47
|
+
readonly phases: readonly EndedGenerationPhaseChange[];
|
|
48
|
+
}
|
|
49
|
+
export interface ScreenCardWithdrawal<R extends object> {
|
|
50
|
+
readonly instance: string;
|
|
51
|
+
readonly origin: ScreenCardOrigin;
|
|
52
|
+
readonly row: R;
|
|
53
|
+
readonly withdrawal: HostWithdrawal;
|
|
54
|
+
}
|
|
55
|
+
export interface ScreenCardKeep {
|
|
56
|
+
readonly instance: string;
|
|
57
|
+
readonly why: ScreenCardKeepReason;
|
|
58
|
+
}
|
|
59
|
+
export interface EngineGenerationReadyCardPlan<R extends object> {
|
|
60
|
+
readonly phase: 'ready';
|
|
61
|
+
readonly withdraw: readonly ScreenCardWithdrawal<R>[];
|
|
62
|
+
readonly keep: readonly ScreenCardKeep[];
|
|
63
|
+
}
|
|
64
|
+
export interface EngineGenerationCardRecheckDueFacts {
|
|
65
|
+
readonly generation: number;
|
|
66
|
+
readonly ready: boolean;
|
|
67
|
+
readonly cards: readonly ScreenDecisionCard[];
|
|
68
|
+
readonly withdrawable: readonly ScreenCardOrigin[];
|
|
69
|
+
}
|
|
70
|
+
export declare function questionFrameGateOf(frame: object | null | undefined): ScreenCardGate | undefined;
|
|
71
|
+
export declare function approvalCardGateOf(card: object | null | undefined): ScreenCardGate | undefined;
|
|
72
|
+
export declare function approvalCardOriginOf(card: object | null | undefined): 'live-approval' | 'park-approval';
|
|
73
|
+
export declare function screenCardsHoldEngineDecision(cards: readonly {
|
|
74
|
+
readonly origin?: ScreenCardOrigin;
|
|
75
|
+
}[] | null | undefined): boolean;
|
|
76
|
+
export declare function engineGenerationCardPlan(facts: EngineGenerationEndedCardFacts): EngineGenerationEndedCardPlan;
|
|
77
|
+
export declare function engineGenerationCardPlan<R extends object>(facts: EngineGenerationReadyCardFacts<R>): EngineGenerationReadyCardPlan<R>;
|
|
78
|
+
export declare function engineGenerationCardRecheckDue(facts: EngineGenerationCardRecheckDueFacts): boolean;
|
|
79
|
+
export interface ScreenCardGoldenRow {
|
|
80
|
+
readonly taskId?: string;
|
|
81
|
+
readonly toolCallId?: string;
|
|
82
|
+
readonly boundCallId?: string;
|
|
83
|
+
readonly checkpointId?: string;
|
|
84
|
+
readonly rowVerdict?: ScreenCardGoldenRowVerdict;
|
|
85
|
+
readonly owned: boolean;
|
|
86
|
+
}
|
|
87
|
+
export interface ScreenCardGoldenRowVerdict {
|
|
88
|
+
readonly kind: string;
|
|
89
|
+
readonly code?: string;
|
|
90
|
+
readonly reason?: string;
|
|
91
|
+
readonly sentence?: string;
|
|
92
|
+
}
|
|
93
|
+
export interface EngineGenerationCardPlanGoldenCase {
|
|
94
|
+
readonly name: string;
|
|
95
|
+
readonly facts: EngineGenerationEndedCardFacts | Omit<EngineGenerationReadyCardFacts<ScreenCardGoldenRow>, 'isOwned'>;
|
|
96
|
+
readonly plan: EngineGenerationEndedCardPlan | EngineGenerationReadyCardPlan<ScreenCardGoldenRow>;
|
|
97
|
+
}
|
|
98
|
+
export declare const ENGINE_GENERATION_CARD_PLAN_GOLDEN: readonly EngineGenerationCardPlanGoldenCase[];
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import { SCREEN_CARD_ORIGINS } from './gateIdentity.js';
|
|
2
|
+
import { convergeEndedEngineGeneration, } from '../engineGenerationConvergence.js';
|
|
3
|
+
import { checkpointRowVerdictOf } from '../checkpointRowVerdict.js';
|
|
4
|
+
import { CHECKPOINT_INVALID_OUTCOME, CHECKPOINT_UNSUPPORTED_VERSION } from '../engineErrorCodes.js';
|
|
5
|
+
import { planReviewCardFactsFrom } from '../planReviewCardFacts.js';
|
|
6
|
+
import { slotReadOf } from '../wireFailureShape.js';
|
|
7
|
+
import { PARK_GATE_KEY } from './screenCardCarriers.js';
|
|
8
|
+
import { pendingRowAnswersCall } from './hitlBridge.js';
|
|
9
|
+
import { cardIsOnParkRow } from './toolApprovalWire.js';
|
|
10
|
+
export const SCREEN_CARD_KEEP_REASONS = Object.freeze(['not-ready', 'generation-moved', 'not-withdrawable', 'no-gate', 'not-early', 'no-row', 'not-owned', 'verdict-ok', 'verdict-absent']);
|
|
11
|
+
const nonEmpty = (v) => typeof v === 'string' && v.length > 0;
|
|
12
|
+
const finite = (v) => typeof v === 'number' && Number.isFinite(v);
|
|
13
|
+
const ORIGIN_SET = new Set(SCREEN_CARD_ORIGINS);
|
|
14
|
+
const PACKAGE_WITHDRAWABLE = new Set(['park-approval', 'park-question', 'plan-review', 'host-reopen-question']);
|
|
15
|
+
const NOT_ENGINE_DECISION = new Set(['host-choice', 'local-permission']);
|
|
16
|
+
function own(o, key) {
|
|
17
|
+
const r = slotReadOf(o, key);
|
|
18
|
+
return r.presence === 'present' ? r.value : undefined;
|
|
19
|
+
}
|
|
20
|
+
function originOf(v) {
|
|
21
|
+
return typeof v === 'string' && ORIGIN_SET.has(v) ? v : undefined;
|
|
22
|
+
}
|
|
23
|
+
function toolGateOf(v) {
|
|
24
|
+
if (typeof v !== 'object' || v === null || Array.isArray(v))
|
|
25
|
+
return undefined;
|
|
26
|
+
const taskId = own(v, 'taskId');
|
|
27
|
+
const gatedCallId = own(v, 'gatedCallId');
|
|
28
|
+
return nonEmpty(taskId) && nonEmpty(gatedCallId) ? Object.freeze({ kind: 'tool', taskId, gatedCallId }) : undefined;
|
|
29
|
+
}
|
|
30
|
+
export function questionFrameGateOf(frame) {
|
|
31
|
+
try {
|
|
32
|
+
if (typeof frame !== 'object' || frame === null)
|
|
33
|
+
return undefined;
|
|
34
|
+
const park = slotReadOf(frame, PARK_GATE_KEY);
|
|
35
|
+
const plan = slotReadOf(frame, '_sema_planReview');
|
|
36
|
+
if (park.presence === 'unreadable' || plan.presence === 'unreadable')
|
|
37
|
+
return undefined;
|
|
38
|
+
const hasPark = park.presence === 'present' && park.value !== undefined;
|
|
39
|
+
const hasPlan = plan.presence === 'present' && plan.value !== undefined;
|
|
40
|
+
if (hasPark && hasPlan)
|
|
41
|
+
return undefined;
|
|
42
|
+
if (hasPark)
|
|
43
|
+
return toolGateOf(park.value);
|
|
44
|
+
if (!hasPlan)
|
|
45
|
+
return undefined;
|
|
46
|
+
const facts = planReviewCardFactsFrom(plan.value);
|
|
47
|
+
if (facts === undefined)
|
|
48
|
+
return undefined;
|
|
49
|
+
return Object.freeze({ kind: 'plan', taskId: facts.taskId, ...(facts.checkpointId !== undefined ? { checkpointId: facts.checkpointId } : {}) });
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function approvalCardGateOf(card) {
|
|
56
|
+
try {
|
|
57
|
+
if (typeof card !== 'object' || card === null || !cardIsOnParkRow(card))
|
|
58
|
+
return undefined;
|
|
59
|
+
const taskId = own(card, 'taskId');
|
|
60
|
+
const park = own(card, 'parkRow');
|
|
61
|
+
if (!nonEmpty(taskId) || typeof park !== 'object' || park === null)
|
|
62
|
+
return undefined;
|
|
63
|
+
const gatedCallId = own(park, 'gatedCallId');
|
|
64
|
+
return nonEmpty(gatedCallId) ? Object.freeze({ kind: 'tool', taskId, gatedCallId }) : undefined;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function approvalCardOriginOf(card) {
|
|
71
|
+
try {
|
|
72
|
+
return cardIsOnParkRow(card) ? 'park-approval' : 'live-approval';
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return 'live-approval';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export function screenCardsHoldEngineDecision(cards) {
|
|
79
|
+
return engineDecisionReadingOf(cards) !== 'none';
|
|
80
|
+
}
|
|
81
|
+
function engineDecisionReadingOf(cards) {
|
|
82
|
+
try {
|
|
83
|
+
if (!Array.isArray(cards))
|
|
84
|
+
return 'none';
|
|
85
|
+
const len = own(cards, 'length');
|
|
86
|
+
if (typeof len !== 'number' || !Number.isSafeInteger(len) || len < 0)
|
|
87
|
+
return 'unreadable';
|
|
88
|
+
for (let i = 0; i < len; i++) {
|
|
89
|
+
const card = own(cards, String(i));
|
|
90
|
+
const origin = typeof card === 'object' && card !== null ? originOf(own(card, 'origin')) : undefined;
|
|
91
|
+
if (origin === undefined || !NOT_ENGINE_DECISION.has(origin))
|
|
92
|
+
return 'holds';
|
|
93
|
+
}
|
|
94
|
+
return 'none';
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return 'unreadable';
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function cardReadingOf(card) {
|
|
101
|
+
try {
|
|
102
|
+
if (typeof card !== 'object' || card === null)
|
|
103
|
+
return undefined;
|
|
104
|
+
const instance = own(card, 'instance');
|
|
105
|
+
if (!nonEmpty(instance))
|
|
106
|
+
return undefined;
|
|
107
|
+
return {
|
|
108
|
+
instance,
|
|
109
|
+
origin: originOf(own(card, 'origin')),
|
|
110
|
+
gate: own(card, 'gate'),
|
|
111
|
+
sourceGeneration: own(card, 'sourceGeneration'),
|
|
112
|
+
toolCallId: own(card, 'toolCallId'),
|
|
113
|
+
window: own(card, 'window'),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function distinctCards(cards) {
|
|
121
|
+
if (!Array.isArray(cards))
|
|
122
|
+
return [];
|
|
123
|
+
const out = [];
|
|
124
|
+
const seen = new Set();
|
|
125
|
+
for (const card of cards) {
|
|
126
|
+
const r = cardReadingOf(card);
|
|
127
|
+
if (r === undefined || seen.has(r.instance))
|
|
128
|
+
continue;
|
|
129
|
+
seen.add(r.instance);
|
|
130
|
+
out.push(r);
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
function usableGateOf(v) {
|
|
135
|
+
if (typeof v !== 'object' || v === null)
|
|
136
|
+
return undefined;
|
|
137
|
+
const kind = own(v, 'kind');
|
|
138
|
+
const taskId = own(v, 'taskId');
|
|
139
|
+
if (!nonEmpty(taskId))
|
|
140
|
+
return undefined;
|
|
141
|
+
if (kind === 'tool') {
|
|
142
|
+
const gatedCallId = own(v, 'gatedCallId');
|
|
143
|
+
return nonEmpty(gatedCallId) ? { kind: 'tool', taskId, gatedCallId } : undefined;
|
|
144
|
+
}
|
|
145
|
+
if (kind === 'plan') {
|
|
146
|
+
const checkpointId = own(v, 'checkpointId');
|
|
147
|
+
return nonEmpty(checkpointId) ? { kind: 'plan', taskId, checkpointId } : undefined;
|
|
148
|
+
}
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
function withdrawableSetOf(v) {
|
|
152
|
+
const out = new Set();
|
|
153
|
+
if (!Array.isArray(v))
|
|
154
|
+
return out;
|
|
155
|
+
for (const o of v) {
|
|
156
|
+
const origin = originOf(o);
|
|
157
|
+
if (origin !== undefined && PACKAGE_WITHDRAWABLE.has(origin))
|
|
158
|
+
out.add(origin);
|
|
159
|
+
}
|
|
160
|
+
return out;
|
|
161
|
+
}
|
|
162
|
+
function candidacyOf(card, generation, cap) {
|
|
163
|
+
if (card.origin === undefined || !cap.has(card.origin))
|
|
164
|
+
return { ok: false, why: 'not-withdrawable' };
|
|
165
|
+
const gate = usableGateOf(card.gate);
|
|
166
|
+
if (gate === undefined)
|
|
167
|
+
return { ok: false, why: 'no-gate' };
|
|
168
|
+
if (finite(card.sourceGeneration) && card.sourceGeneration >= generation)
|
|
169
|
+
return { ok: false, why: 'not-early' };
|
|
170
|
+
return { ok: true, origin: card.origin, gate };
|
|
171
|
+
}
|
|
172
|
+
function rowAnswersGate(row, gate) {
|
|
173
|
+
const r = row;
|
|
174
|
+
if (gate.kind === 'tool')
|
|
175
|
+
return pendingRowAnswersCall(r, gate.taskId, gate.gatedCallId);
|
|
176
|
+
return r.taskId === gate.taskId && r.checkpointId === gate.checkpointId;
|
|
177
|
+
}
|
|
178
|
+
function ownedSafely(isOwned, row) {
|
|
179
|
+
try {
|
|
180
|
+
return isOwned(row) === true;
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const EMPTY_ENDED = Object.freeze({ phase: 'ended', retract: Object.freeze([]), phases: Object.freeze([]) });
|
|
187
|
+
const EMPTY_READY = Object.freeze({ phase: 'ready', withdraw: Object.freeze([]), keep: Object.freeze([]) });
|
|
188
|
+
function endedPlanOf(facts) {
|
|
189
|
+
const cards = distinctCards(own(facts, 'cards')).map((c) => {
|
|
190
|
+
const w = c.window;
|
|
191
|
+
const leftMs = typeof w === 'object' && w !== null ? own(w, 'leftMs') : undefined;
|
|
192
|
+
const closedByEngine = typeof w === 'object' && w !== null ? own(w, 'closedByEngine') : undefined;
|
|
193
|
+
return {
|
|
194
|
+
callKey: c.instance,
|
|
195
|
+
parkRow: c.origin !== 'live-approval',
|
|
196
|
+
...(nonEmpty(c.toolCallId) ? { toolCallId: c.toolCallId } : {}),
|
|
197
|
+
...(finite(leftMs) ? { windowLeftMs: leftMs } : {}),
|
|
198
|
+
...(closedByEngine === true ? { closedByEngine: true } : {}),
|
|
199
|
+
};
|
|
200
|
+
});
|
|
201
|
+
const opened = own(facts, 'opened');
|
|
202
|
+
const phases = own(facts, 'phases');
|
|
203
|
+
const endedGeneration = own(facts, 'endedGeneration');
|
|
204
|
+
const plan = convergeEndedEngineGeneration({
|
|
205
|
+
cards,
|
|
206
|
+
opened: Array.isArray(opened) ? opened : [],
|
|
207
|
+
...(Array.isArray(phases) ? { phases: phases } : {}),
|
|
208
|
+
endedGeneration: finite(endedGeneration) ? endedGeneration : Number.NaN,
|
|
209
|
+
});
|
|
210
|
+
return Object.freeze({ phase: 'ended', retract: plan.retract, phases: plan.phases });
|
|
211
|
+
}
|
|
212
|
+
function readyPlanOf(facts) {
|
|
213
|
+
const cards = distinctCards(own(facts, 'cards'));
|
|
214
|
+
const generation = own(facts, 'generation');
|
|
215
|
+
const keep = [];
|
|
216
|
+
const withdraw = [];
|
|
217
|
+
const keepAll = (why) => Object.freeze({ phase: 'ready', withdraw: Object.freeze([]), keep: Object.freeze(cards.map((c) => Object.freeze({ instance: c.instance, why }))) });
|
|
218
|
+
if (own(facts, 'ready') !== true || !finite(generation))
|
|
219
|
+
return keepAll('not-ready');
|
|
220
|
+
if (own(facts, 'readGeneration') !== generation)
|
|
221
|
+
return keepAll('generation-moved');
|
|
222
|
+
const cap = withdrawableSetOf(own(facts, 'withdrawable'));
|
|
223
|
+
const rowsRaw = own(facts, 'rows');
|
|
224
|
+
const rows = Array.isArray(rowsRaw) ? rowsRaw.filter((r) => typeof r === 'object' && r !== null) : [];
|
|
225
|
+
const isOwnedRaw = own(facts, 'isOwned');
|
|
226
|
+
const isOwned = typeof isOwnedRaw === 'function' ? isOwnedRaw : () => false;
|
|
227
|
+
for (const card of cards) {
|
|
228
|
+
const c = candidacyOf(card, generation, cap);
|
|
229
|
+
if (!c.ok) {
|
|
230
|
+
keep.push(Object.freeze({ instance: card.instance, why: c.why }));
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
const matched = rows.filter((r) => rowAnswersGate(r, c.gate));
|
|
234
|
+
if (matched.length === 0) {
|
|
235
|
+
keep.push(Object.freeze({ instance: card.instance, why: 'no-row' }));
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
const row = matched.find((r) => ownedSafely(isOwned, r));
|
|
239
|
+
if (row === undefined) {
|
|
240
|
+
keep.push(Object.freeze({ instance: card.instance, why: 'not-owned' }));
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const verdict = checkpointRowVerdictOf(row);
|
|
244
|
+
if (verdict === undefined) {
|
|
245
|
+
keep.push(Object.freeze({ instance: card.instance, why: 'verdict-absent' }));
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (verdict.kind === 'ok') {
|
|
249
|
+
keep.push(Object.freeze({ instance: card.instance, why: 'verdict-ok' }));
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
const rowVerdict = verdict;
|
|
253
|
+
withdraw.push(Object.freeze({ instance: card.instance, origin: c.origin, row, withdrawal: Object.freeze({ toldBy: 'host', rowVerdict }) }));
|
|
254
|
+
}
|
|
255
|
+
return Object.freeze({ phase: 'ready', withdraw: Object.freeze(withdraw), keep: Object.freeze(keep) });
|
|
256
|
+
}
|
|
257
|
+
export function engineGenerationCardPlan(facts) {
|
|
258
|
+
let phase;
|
|
259
|
+
try {
|
|
260
|
+
if (typeof facts !== 'object' || facts === null)
|
|
261
|
+
return EMPTY_READY;
|
|
262
|
+
phase = own(facts, 'phase');
|
|
263
|
+
if (phase === 'ended')
|
|
264
|
+
return endedPlanOf(facts);
|
|
265
|
+
if (phase === 'ready')
|
|
266
|
+
return readyPlanOf(facts);
|
|
267
|
+
return EMPTY_READY;
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
return (phase === 'ended' ? EMPTY_ENDED : EMPTY_READY);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
export function engineGenerationCardRecheckDue(facts) {
|
|
274
|
+
try {
|
|
275
|
+
if (typeof facts !== 'object' || facts === null)
|
|
276
|
+
return false;
|
|
277
|
+
const generation = own(facts, 'generation');
|
|
278
|
+
if (own(facts, 'ready') !== true || !finite(generation))
|
|
279
|
+
return false;
|
|
280
|
+
const cap = withdrawableSetOf(own(facts, 'withdrawable'));
|
|
281
|
+
return distinctCards(own(facts, 'cards')).some((c) => candidacyOf(c, generation, cap).ok);
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function deepFreeze(v) {
|
|
288
|
+
if (typeof v === 'object' && v !== null && !Object.isFrozen(v)) {
|
|
289
|
+
Object.freeze(v);
|
|
290
|
+
for (const k of Object.keys(v))
|
|
291
|
+
deepFreeze(v[k]);
|
|
292
|
+
}
|
|
293
|
+
return v;
|
|
294
|
+
}
|
|
295
|
+
const GOLD_LACKING = { kind: 'lacking', code: CHECKPOINT_UNSUPPORTED_VERSION, reason: 'version_newer', sentence: 'Newer engine.' };
|
|
296
|
+
const GOLD_DAMAGED = { kind: 'damaged', code: CHECKPOINT_INVALID_OUTCOME, reason: 'requirements_damaged', sentence: 'Row damaged.' };
|
|
297
|
+
function goldenCases() {
|
|
298
|
+
const ALL = ['park-approval', 'park-question', 'plan-review', 'host-reopen-question'];
|
|
299
|
+
const ready = (name, cards, rows, pick, over = {}) => {
|
|
300
|
+
const facts = { phase: 'ready', generation: 2, ready: true, readGeneration: 2, cards, rows, withdrawable: ALL, ...over };
|
|
301
|
+
return { name, facts, plan: { phase: 'ready', ...pick(facts.rows) } };
|
|
302
|
+
};
|
|
303
|
+
const tool = (taskId, gatedCallId) => ({ kind: 'tool', taskId, gatedCallId });
|
|
304
|
+
const W = (instance, origin, row, rowVerdict) => ({ instance, origin, row, withdrawal: { toldBy: 'host', rowVerdict } });
|
|
305
|
+
const K = (instance, why) => ({ instance, why });
|
|
306
|
+
const lacking = GOLD_LACKING;
|
|
307
|
+
const damaged = GOLD_DAMAGED;
|
|
308
|
+
const cases = [
|
|
309
|
+
{
|
|
310
|
+
name: 'ended-live-window-open-only',
|
|
311
|
+
facts: {
|
|
312
|
+
phase: 'ended',
|
|
313
|
+
endedGeneration: 1,
|
|
314
|
+
cards: [
|
|
315
|
+
{ instance: 'live-open', origin: 'live-approval', toolCallId: 'call-1', window: { leftMs: 60_000 } },
|
|
316
|
+
{ instance: 'live-margin', origin: 'live-approval', toolCallId: 'call-2', window: { leftMs: 5_000 } },
|
|
317
|
+
{ instance: 'live-closed', origin: 'live-approval', toolCallId: 'call-3', window: { leftMs: 60_000, closedByEngine: true } },
|
|
318
|
+
{ instance: 'live-no-window', origin: 'live-approval', toolCallId: 'call-4' },
|
|
319
|
+
{ instance: 'parked', origin: 'park-approval', toolCallId: 'call-5', window: { leftMs: 60_000 } },
|
|
320
|
+
{ instance: 'no-origin', toolCallId: 'call-6', window: { leftMs: 60_000 } },
|
|
321
|
+
],
|
|
322
|
+
opened: [{ toolCallId: 'call-7', generation: 1 }, { toolCallId: 'call-8', generation: 0 }],
|
|
323
|
+
},
|
|
324
|
+
plan: { phase: 'ended', retract: ['live-open'], phases: [{ toolCallId: 'call-1', phase: 'engine-stopped-awaiting-approval', viaCallKey: 'live-open' }, { toolCallId: 'call-7', phase: 'engine-stopped-before-result' }] },
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
name: 'ended-live-without-call-id',
|
|
328
|
+
facts: { phase: 'ended', endedGeneration: 3, cards: [{ instance: 'live', origin: 'live-approval', window: { leftMs: 9_000 } }], opened: [] },
|
|
329
|
+
plan: { phase: 'ended', retract: ['live'], phases: [] },
|
|
330
|
+
},
|
|
331
|
+
ready('ready-park-question-withdrawn', [{ instance: 'q', origin: 'park-question', gate: tool('run-1', 'call-1'), sourceGeneration: 1 }], [{ taskId: 'run-1', toolCallId: 'call-1', rowVerdict: GOLD_LACKING, owned: true }], (rows) => ({ withdraw: [W('q', 'park-question', rows[0], lacking)], keep: [] })),
|
|
332
|
+
ready('ready-bound-call-id-matches', [{ instance: 'a', origin: 'park-approval', gate: tool('run-2', 'call-2'), sourceGeneration: 1 }], [{ taskId: 'run-2', toolCallId: 'call-x', boundCallId: 'call-2', rowVerdict: GOLD_DAMAGED, owned: true }], (rows) => ({ withdraw: [W('a', 'park-approval', rows[0], damaged)], keep: [] })),
|
|
333
|
+
ready('ready-plan-by-checkpoint', [
|
|
334
|
+
{ instance: 'plan-same', origin: 'plan-review', gate: { kind: 'plan', taskId: 'run-3', checkpointId: 'cp-1' } },
|
|
335
|
+
{ instance: 'plan-moved', origin: 'plan-review', gate: { kind: 'plan', taskId: 'run-4', checkpointId: 'cp-old' }, sourceGeneration: 1 },
|
|
336
|
+
{ instance: 'plan-no-checkpoint', origin: 'plan-review', gate: { kind: 'plan', taskId: 'run-5' }, sourceGeneration: 1 },
|
|
337
|
+
], [{ taskId: 'run-3', checkpointId: 'cp-1', rowVerdict: GOLD_LACKING, owned: true }, { taskId: 'run-4', checkpointId: 'cp-new', rowVerdict: GOLD_LACKING, owned: true }, { taskId: 'run-5', checkpointId: 'cp-5', rowVerdict: GOLD_LACKING, owned: true }], (rows) => ({ withdraw: [W('plan-same', 'plan-review', rows[0], lacking)], keep: [K('plan-moved', 'no-row'), K('plan-no-checkpoint', 'no-gate')] })),
|
|
338
|
+
ready('ready-kinds-never-withdrawn', [
|
|
339
|
+
{ instance: 'live', origin: 'live-approval', gate: tool('run-1', 'call-1'), sourceGeneration: 1 },
|
|
340
|
+
{ instance: 'choice', origin: 'host-choice', gate: tool('run-1', 'call-1'), sourceGeneration: 1 },
|
|
341
|
+
{ instance: 'unnamed', gate: tool('run-1', 'call-1'), sourceGeneration: 1 },
|
|
342
|
+
{ instance: 'reopened', origin: 'host-reopen-question', gate: tool('run-1', 'call-1'), sourceGeneration: 1 },
|
|
343
|
+
], [{ taskId: 'run-1', toolCallId: 'call-1', rowVerdict: GOLD_LACKING, owned: true }], (rows) => ({ withdraw: [W('reopened', 'host-reopen-question', rows[0], lacking)], keep: [K('live', 'not-withdrawable'), K('choice', 'not-withdrawable'), K('unnamed', 'not-withdrawable')] })),
|
|
344
|
+
ready('ready-host-withdrawable-only', [{ instance: 'q', origin: 'park-question', gate: tool('run-1', 'call-1'), sourceGeneration: 1 }, { instance: 'r', origin: 'host-reopen-question', gate: tool('run-1', 'call-1'), sourceGeneration: 1 }], [{ taskId: 'run-1', toolCallId: 'call-1', rowVerdict: GOLD_LACKING, owned: true }], (rows) => ({ withdraw: [W('r', 'host-reopen-question', rows[0], lacking)], keep: [K('q', 'not-withdrawable')] }), { withdrawable: ['host-reopen-question'] }),
|
|
345
|
+
ready('ready-current-generation-kept', [{ instance: 'q', origin: 'park-question', gate: tool('run-1', 'call-1'), sourceGeneration: 2 }], [{ taskId: 'run-1', toolCallId: 'call-1', rowVerdict: GOLD_LACKING, owned: true }], () => ({ withdraw: [], keep: [K('q', 'not-early')] })),
|
|
346
|
+
ready('ready-keep-reasons', [
|
|
347
|
+
{ instance: 'no-gate', origin: 'park-question', sourceGeneration: 1 },
|
|
348
|
+
{ instance: 'no-row', origin: 'park-question', gate: tool('run-9', 'call-9'), sourceGeneration: 1 },
|
|
349
|
+
{ instance: 'foreign', origin: 'park-question', gate: tool('run-7', 'call-7'), sourceGeneration: 1 },
|
|
350
|
+
{ instance: 'fine', origin: 'park-question', gate: tool('run-8', 'call-8'), sourceGeneration: 1 },
|
|
351
|
+
{ instance: 'no-verdict', origin: 'park-question', gate: tool('run-6', 'call-6'), sourceGeneration: 1 },
|
|
352
|
+
], [
|
|
353
|
+
{ taskId: 'run-7', toolCallId: 'call-7', rowVerdict: GOLD_LACKING, owned: false },
|
|
354
|
+
{ taskId: 'run-8', toolCallId: 'call-8', rowVerdict: { kind: 'ok' }, owned: true },
|
|
355
|
+
{ taskId: 'run-6', toolCallId: 'call-6', owned: true },
|
|
356
|
+
], () => ({ withdraw: [], keep: [K('no-gate', 'no-gate'), K('no-row', 'no-row'), K('foreign', 'not-owned'), K('fine', 'verdict-ok'), K('no-verdict', 'verdict-absent')] })),
|
|
357
|
+
ready('ready-not-ready', [{ instance: 'q', origin: 'park-question', gate: tool('run-1', 'call-1'), sourceGeneration: 1 }], [{ taskId: 'run-1', toolCallId: 'call-1', rowVerdict: GOLD_LACKING, owned: true }], () => ({ withdraw: [], keep: [K('q', 'not-ready')] }), { ready: false }),
|
|
358
|
+
ready('ready-generation-moved', [{ instance: 'q', origin: 'park-question', gate: tool('run-1', 'call-1'), sourceGeneration: 1 }], [{ taskId: 'run-1', toolCallId: 'call-1', rowVerdict: GOLD_LACKING, owned: true }], () => ({ withdraw: [], keep: [K('q', 'generation-moved')] }), { readGeneration: 1 }),
|
|
359
|
+
ready('ready-instance-judged-once', [{ instance: 'q', origin: 'park-question', gate: tool('run-8', 'call-8'), sourceGeneration: 1 }, { instance: 'q', origin: 'park-question', gate: tool('run-1', 'call-1'), sourceGeneration: 1 }], [{ taskId: 'run-1', toolCallId: 'call-1', rowVerdict: GOLD_LACKING, owned: true }, { taskId: 'run-8', toolCallId: 'call-8', rowVerdict: { kind: 'ok' }, owned: true }], () => ({ withdraw: [], keep: [K('q', 'verdict-ok')] })),
|
|
360
|
+
];
|
|
361
|
+
return deepFreeze(cases);
|
|
362
|
+
}
|
|
363
|
+
export const ENGINE_GENERATION_CARD_PLAN_GOLDEN = goldenCases();
|