@sema-agent/server 7.122.0 → 7.124.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/MIGRATION.md +209 -0
- package/README.md +7 -2
- package/README.zh-CN.md +5 -2
- package/USAGE.md +76 -56
- package/dist/approval-ask-audit-store.d.ts +27 -32
- package/dist/approval-ask-audit-store.js +10 -9
- package/dist/approval-crash-convergence.d.ts +2 -2
- package/dist/approval-crash-convergence.js +5 -5
- package/dist/approval-deny-reasons.d.ts +163 -51
- package/dist/approval-deny-reasons.js +79 -8
- package/dist/approval-policy-settlement.d.ts +4 -1
- package/dist/approval-policy-settlement.js +3 -2
- package/dist/approval-reconciler.d.ts +3 -3
- package/dist/approval-reconciler.js +10 -10
- package/dist/approval.d.ts +1 -1
- package/dist/approval.js +1 -1
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +53 -23
- package/dist/auth-bridge.d.ts +8 -8
- package/dist/auth-bridge.js +6 -6
- package/dist/auth-keys.d.ts +2 -2
- package/dist/auto-mode-face.d.ts +13 -9
- package/dist/auto-mode-face.js +8 -7
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/execution-env.js +1 -0
- package/dist/boot/leader.d.ts +1 -1
- package/dist/boot/memory-consolidation.d.ts +4 -4
- package/dist/boot/org-memory.d.ts +3 -3
- package/dist/boot/org-memory.js +5 -5
- package/dist/boot/resolve-spec.js +7 -7
- package/dist/boot/runner-deps.d.ts +1 -1
- package/dist/boot/runtime-caps.d.ts +1 -1
- package/dist/boot/runtime-caps.js +10 -10
- package/dist/boot/shutdown.d.ts +2 -2
- package/dist/boot/shutdown.js +2 -2
- package/dist/boot/side-query-lane.d.ts +3 -3
- package/dist/boot/{stage-02-registry-pull.d.ts → stage-02-web-admin-pull.d.ts} +2 -2
- package/dist/boot/{stage-02-registry-pull.js → stage-02-web-admin-pull.js} +4 -4
- package/dist/boot/stage-03-store-backend.d.ts +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +1 -1
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +6 -6
- package/dist/boot/stage-07-capability-layer.d.ts +2 -2
- package/dist/boot/stage-07-capability-layer.js +6 -5
- package/dist/boot/stage-08-reapers.d.ts +3 -3
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +3 -3
- package/dist/boot/stage-09-leader.js +7 -7
- package/dist/boot/stage-10-http-server.d.ts +3 -3
- package/dist/boot/stage-10-http-server.js +19 -19
- package/dist/boot/unpriced-ceiling-verdict.d.ts +1 -1
- package/dist/boot/{config-center.d.ts → web-admin.d.ts} +11 -11
- package/dist/boot/{config-center.js → web-admin.js} +39 -20
- package/dist/boot/webfetch-summarize-lane.d.ts +2 -2
- package/dist/brain.d.ts +1 -1
- package/dist/brain.js +1 -1
- package/dist/budget.d.ts +3 -3
- package/dist/canonical-json.d.ts +2 -2
- package/dist/capabilities/center-plugins.d.ts +1 -1
- package/dist/capabilities/center-wiring.d.ts +12 -5
- package/dist/capabilities/center-wiring.js +11 -2
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capabilities/team.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/center-credential-renewer.d.ts +1 -1
- package/dist/center-credential-renewer.js +7 -7
- package/dist/center-credential.d.ts +9 -9
- package/dist/center-credential.js +6 -6
- package/dist/config-catalog.d.ts +7 -10
- package/dist/config-catalog.js +16 -16
- package/dist/config-d-migration.d.ts +32 -0
- package/dist/config-d-migration.js +59 -0
- package/dist/config-invariants.d.ts +14 -4
- package/dist/config-invariants.js +31 -2
- package/dist/config-lkg.d.ts +34 -11
- package/dist/config-lkg.js +76 -48
- package/dist/config-provider.d.ts +26 -21
- package/dist/config-provider.js +25 -27
- package/dist/config-types.d.ts +59 -50
- package/dist/config.d.ts +17 -54
- package/dist/config.js +99 -181
- package/dist/execution-lane-caps.d.ts +1 -1
- package/dist/fleet/drain-entry.d.ts +1 -1
- package/dist/fleet/engine-signal.d.ts +61 -30
- package/dist/fleet/engine-signal.js +29 -5
- package/dist/fleet/fleet-bus.d.ts +12 -3
- package/dist/fleet/fleet-bus.js +13 -9
- package/dist/fleet/serving-lease.d.ts +3 -3
- package/dist/fleet/serving-lease.js +1 -1
- package/dist/fleet-client.d.ts +15 -13
- package/dist/fleet-client.js +9 -7
- package/dist/fleet-lease.d.ts +3 -3
- package/dist/fleet-lease.js +2 -2
- package/dist/host-lsp-manager.d.ts +1 -1
- package/dist/hosted-posture.d.ts +4 -4
- package/dist/http/admission.js +4 -4
- package/dist/http/checkpoint-ctx.d.ts +20 -3
- package/dist/http/checkpoint-ctx.js +13 -5
- package/dist/http/dispatch.js +7 -16
- package/dist/http/durable-run-leg.js +2 -1
- package/dist/http/health-self-report.d.ts +7 -4
- package/dist/http/health-self-report.js +3 -3
- package/dist/http/idempotency.d.ts +1 -1
- package/dist/http/resume-legs.d.ts +4 -3
- package/dist/http/resume-legs.js +31 -18
- package/dist/http/route-ctx.d.ts +8 -0
- package/dist/http/routes/admin-config-refresh.d.ts +1 -1
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.d.ts +1 -1
- package/dist/http/routes/admin-drain.js +5 -4
- package/dist/http/routes/approvals-assistant.js +4 -4
- package/dist/http/routes/capabilities.js +6 -5
- package/dist/http/routes/config-catalog.js +2 -3
- package/dist/http/routes/diagnostics.js +1 -1
- package/dist/http/routes/runs.js +8 -4
- package/dist/http/routes/sessions-list.js +2 -1
- package/dist/http/routes/sessions.js +2 -5
- package/dist/http/routes/side-query.js +3 -3
- package/dist/http/routes/tasks.js +3 -2
- package/dist/http/run-meta.d.ts +1 -1
- package/dist/http/run-meta.js +2 -2
- package/dist/http/server.d.ts +7 -7
- package/dist/http/server.js +1 -1
- package/dist/http/stored-body-replay.d.ts +4 -3
- package/dist/http/stored-body-replay.js +5 -5
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/key-resolver.d.ts +1 -1
- package/dist/leader/leader.d.ts +7 -6
- package/dist/leader/leader.js +3 -1
- package/dist/leader/run-entry.d.ts +2 -2
- package/dist/leader/run-entry.js +3 -3
- package/dist/leader/wire.d.ts +4 -4
- package/dist/leader/wire.js +2 -1
- package/dist/main.js +1 -1
- package/dist/mcp-tool-faces.d.ts +2 -2
- package/dist/model-entry-refusal.d.ts +20 -11
- package/dist/model-entry-refusal.js +22 -17
- package/dist/model-provider.d.ts +2 -2
- package/dist/model-route-endpoint.d.ts +22 -2
- package/dist/model-route-endpoint.js +9 -3
- package/dist/model-route-gap.d.ts +103 -0
- package/dist/model-route-gap.js +80 -0
- package/dist/model-route-url.d.ts +1 -1
- package/dist/model-route-url.js +2 -1
- package/dist/model-select.d.ts +24 -21
- package/dist/model-select.js +22 -17
- package/dist/namespaced-rule-name.d.ts +16 -30
- package/dist/namespaced-rule-name.js +2 -20
- package/dist/observability/fail-open.d.ts +0 -4
- package/dist/observability/fail-open.js +0 -4
- package/dist/observability/metrics.d.ts +1 -1
- package/dist/org-memory-admission.d.ts +1 -1
- package/dist/plugins/approval-ask-store-file.d.ts +4 -2
- package/dist/plugins/approval-ask-store-file.js +3 -3
- package/dist/plugins/approval-ask-store-memory.d.ts +4 -3
- package/dist/plugins/approval-ask-store-memory.js +10 -4
- package/dist/plugins/approval-ask-store-sql.d.ts +16 -2
- package/dist/plugins/approval-ask-store-sql.js +20 -13
- package/dist/plugins/caching-session-store.d.ts +0 -10
- package/dist/plugins/caching-session-store.js +0 -3
- package/dist/plugins/file-run-store.js +9 -3
- package/dist/plugins/leader-run-store-sql.d.ts +3 -2
- package/dist/plugins/leader-run-store-sql.js +3 -2
- package/dist/plugins/local-session-store.d.ts +20 -27
- package/dist/plugins/local-session-store.js +19 -17
- package/dist/plugins/memory-run-store.js +9 -3
- package/dist/plugins/one-time-migrations.js +51 -0
- package/dist/plugins/scheduler-support.d.ts +26 -7
- package/dist/plugins/scheduler-support.js +96 -53
- package/dist/plugins/session-policy-store-sql.js +1 -2
- package/dist/plugins/store-backend.js +1 -1
- package/dist/plugins/store-contracts.d.ts +20 -4
- package/dist/plugins/web-search.d.ts +1 -1
- package/dist/plugins/web-search.js +2 -1
- package/dist/plugins/workflow-run-store-sql.d.ts +4 -2
- package/dist/posture-source.d.ts +1 -1
- package/dist/read-face-posture.d.ts +3 -3
- package/dist/read-face-posture.js +1 -1
- package/dist/rule-entry-list.d.ts +3 -13
- package/dist/rule-entry-list.js +1 -12
- package/dist/run-local.js +10 -7
- package/dist/runtime-caps-resolver.d.ts +4 -4
- package/dist/runtime-caps-resolver.js +2 -2
- package/dist/runtime-governance.d.ts +36 -13
- package/dist/runtime-governance.js +7 -2
- package/dist/sealed-key.d.ts +4 -4
- package/dist/sealed-key.js +3 -2
- package/dist/security.d.ts +3 -3
- package/dist/service-version.d.ts +1 -1
- package/dist/service-version.js +5 -0
- package/dist/session-policy-wire.d.ts +47 -49
- package/dist/session-policy-wire.js +41 -36
- package/dist/session-sync.d.ts +5 -1
- package/dist/session-sync.js +2 -1
- package/dist/session-titler.d.ts +0 -11
- package/dist/session-titler.js +3 -5
- package/dist/shared-memory-scope-authorizer.d.ts +4 -4
- package/dist/spec-fields.d.ts +4 -4
- package/dist/spec-fields.js +1 -4
- package/dist/task-a2a.d.ts +1 -1
- package/dist/task-settings.d.ts +4 -5
- package/dist/task-settings.js +5 -8
- package/dist/tool-approval.d.ts +43 -4
- package/dist/tool-approval.js +147 -98
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/project.d.ts +3 -3
- package/dist/trace/redact.d.ts +2 -23
- package/dist/trace/redact.js +1 -6
- package/dist/trace/self-minted-wire.d.ts +147 -3
- package/dist/trace/self-minted-wire.js +50 -9
- package/dist/unattended-permission-mode.d.ts +3 -3
- package/dist/unattended-permission-mode.js +2 -2
- package/dist/url-refusal.d.ts +35 -0
- package/dist/url-refusal.js +15 -0
- package/dist/user-authored-text.d.ts +31 -0
- package/dist/user-authored-text.js +18 -0
- package/dist/{config-center → web-admin-client}/apply-effective.d.ts +13 -70
- package/dist/{config-center → web-admin-client}/apply-effective.js +104 -121
- package/dist/{config-center → web-admin-client}/apply-ledger.d.ts +2 -2
- package/dist/{config-center → web-admin-client}/center-request.d.ts +7 -7
- package/dist/{config-center → web-admin-client}/center-request.js +5 -4
- package/dist/{config-center → web-admin-client}/effective-keys.d.ts +1 -3
- package/dist/{config-center → web-admin-client}/effective-keys.js +0 -9
- package/dist/{config-center → web-admin-client}/facade.d.ts +6 -6
- package/dist/{config-center → web-admin-client}/facade.js +2 -2
- package/dist/{config-center → web-admin-client}/http-client.d.ts +6 -10
- package/dist/{config-center → web-admin-client}/http-client.js +15 -15
- package/dist/{config-center → web-admin-client}/pull-state.d.ts +1 -1
- package/dist/{config-center → web-admin-client}/read-face.js +4 -4
- package/dist/web-admin-client/read-warnings.d.ts +137 -0
- package/dist/web-admin-client/read-warnings.js +168 -0
- package/dist/{config-center → web-admin-client}/restart-signal.d.ts +5 -3
- package/dist/{config-center → web-admin-client}/restart-signal.js +3 -4
- package/dist/{config-center → web-admin-client}/skills-mcp.d.ts +1 -1
- package/dist/{config-center → web-admin-client}/skills-mcp.js +13 -13
- package/dist/{config-center → web-admin-client}/stage-limits.d.ts +1 -7
- package/dist/{config-center → web-admin-client}/stage-limits.js +6 -7
- package/dist/{config-center → web-admin-client}/types.d.ts +19 -47
- package/package.json +3 -3
- package/skills/find-skills.md +2 -2
- package/dist/config-center/read-warnings.d.ts +0 -109
- package/dist/config-center/read-warnings.js +0 -110
- package/dist/url-shape.d.ts +0 -31
- package/dist/url-shape.js +0 -41
- /package/dist/{config-center → web-admin-client}/apply-ledger.js +0 -0
- /package/dist/{config-center → web-admin-client}/hot-keys-registry.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/hot-keys-registry.js +0 -0
- /package/dist/{config-center → web-admin-client}/mcp-revocation.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/mcp-revocation.js +0 -0
- /package/dist/{config-center → web-admin-client}/pull-state.js +0 -0
- /package/dist/{config-center → web-admin-client}/read-face.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/types.js +0 -0
package/dist/tool-approval.js
CHANGED
|
@@ -11,6 +11,7 @@ import { recordFailOpen } from "./observability/fail-open.js";
|
|
|
11
11
|
import { deriveAskId, deriveAskScopedBatchId, deriveBatchId, MAX_DECISION_NOTE_CHARS } from "./approval-ask-machine.js";
|
|
12
12
|
import { ApprovalCardEnvelopeSchema, MAX_RULE_OFFERS, buildApprovalCard, buildApprovalCardEnvelope, buildApprovalRequestFrame, buildRevokeFrame, readDenialLimitFallback, readProbeCause, readProbeReason, readReadRootCandidate, readRuleEvidence, readAllowRuleShadowed, readRuleOffersAbsence, readRuleOffersAbsenceSeat, readParkRowTrueSeat, readAskClassPair, readClosedWordSeat, RuleOfferRawSchema, backfillLegacyBatchMemberKind, screenUncoveredDetailSeat, } from "./approval-card.js";
|
|
13
13
|
import { POLICY_REFUSAL_DECISION, projectAskTerminalClaimTruth } from "./plugins/approval-ask-store-sql.js";
|
|
14
|
+
import { APPROVAL_ENDING_CAUSES, SETTLE_OUTCOME, causeOfAskRow } from "./approval-deny-reasons.js";
|
|
14
15
|
import { settleByPolicy } from "./approval-policy-settlement.js";
|
|
15
16
|
import { governanceAskMarksFor, runWithGovernanceAskScope } from "./governance-ask-marks.js";
|
|
16
17
|
import { governanceOriginOf } from "./runtime-governance.js";
|
|
@@ -31,7 +32,6 @@ const SUSPENDED_POLL_BUDGET_MS = 5_000;
|
|
|
31
32
|
const EDITED_DECISION_MARK_CAP_MS = 10_000;
|
|
32
33
|
const DEFAULT_WINDOW_MARGIN_MS = 10_000;
|
|
33
34
|
const SHUTDOWN_DRAIN_POLL_MS = 50;
|
|
34
|
-
const SHUTDOWN_BEFORE_PARK = "shutdown_before_park";
|
|
35
35
|
const MAX_ALLOW_SESSIONS = 4096;
|
|
36
36
|
const DEFAULT_ADMIT_MAX_PER_TASK = 32;
|
|
37
37
|
const DEFAULT_ADMIT_MAX_PER_OWNER = 256;
|
|
@@ -59,6 +59,7 @@ function durableRuleMaterial(material) {
|
|
|
59
59
|
}
|
|
60
60
|
return { ruleCommand: material.command, ruleScopeRoot: material.scopeRoot ?? null };
|
|
61
61
|
}
|
|
62
|
+
export const NOT_PENDING_UNKNOWN_CAUSE = "unknown_or_other_replica";
|
|
62
63
|
export const ASK_DECISION_CONSUMER_ABSENT = "absent";
|
|
63
64
|
const MAX_INFLIGHT_TERMINAL_CLAIMS = 2;
|
|
64
65
|
const DURABLE_CONVERGE_BACKOFF_MS = [50, 100, 200, 400, 800, 1600];
|
|
@@ -366,6 +367,14 @@ function settleArgsOfDecided(outcome) {
|
|
|
366
367
|
...(outcome.settledBy !== undefined ? { settledBy: outcome.settledBy } : {}),
|
|
367
368
|
};
|
|
368
369
|
}
|
|
370
|
+
function verdictOfDecided(args) {
|
|
371
|
+
return {
|
|
372
|
+
by: "human",
|
|
373
|
+
allowed: args.allowed,
|
|
374
|
+
...(args.updatedInput !== undefined ? { updatedInput: args.updatedInput } : {}),
|
|
375
|
+
...(args.settledBy !== undefined ? { hostSettledBy: args.settledBy } : {}),
|
|
376
|
+
};
|
|
377
|
+
}
|
|
369
378
|
function settleArgsOf(outcome) {
|
|
370
379
|
return outcome === "unavailable" ? "unavailable" : settleArgsOfDecided(outcome);
|
|
371
380
|
}
|
|
@@ -499,16 +508,16 @@ export class ToolApprovalCoordinator {
|
|
|
499
508
|
return outcome;
|
|
500
509
|
const dispatch = (res, where) => {
|
|
501
510
|
if (res.claimed) {
|
|
502
|
-
this.settleSameAskIdParkRoute(row.askId);
|
|
511
|
+
this.settleSameAskIdParkRoute(row.askId, APPROVAL_ENDING_CAUSES.UNDELIVERABLE);
|
|
503
512
|
return undefined;
|
|
504
513
|
}
|
|
505
514
|
const read = this.classifyClaimLoss(row.askId, res.current, where);
|
|
506
|
-
this.dispatchClaimTruth(row.askId, read);
|
|
515
|
+
this.dispatchClaimTruth(row.askId, read, APPROVAL_ENDING_CAUSES.UNDELIVERABLE);
|
|
507
516
|
return read;
|
|
508
517
|
};
|
|
509
518
|
let res;
|
|
510
519
|
try {
|
|
511
|
-
res = await this.withStoreDeadline(settleByPolicy(store, row, this.unattendedPolicy), "claimTerminal(unattended-fallback)", DURABLE_CALL_TIMEOUT_MS, (late) => {
|
|
520
|
+
res = await this.withStoreDeadline(settleByPolicy(store, row, this.unattendedPolicy, APPROVAL_ENDING_CAUSES.UNDELIVERABLE), "claimTerminal(unattended-fallback)", DURABLE_CALL_TIMEOUT_MS, (late) => {
|
|
512
521
|
dispatch(late, "late:unattended-fallback");
|
|
513
522
|
});
|
|
514
523
|
}
|
|
@@ -707,7 +716,7 @@ export class ToolApprovalCoordinator {
|
|
|
707
716
|
let n = 0;
|
|
708
717
|
for (const e of this.pending.values()) {
|
|
709
718
|
if (e.ctxTaskId === wireTaskId && e.settledOutcome === undefined) {
|
|
710
|
-
e.forceParkNow();
|
|
719
|
+
e.forceParkNow(APPROVAL_ENDING_CAUSES.STREAM_DISCONNECTED);
|
|
711
720
|
n++;
|
|
712
721
|
}
|
|
713
722
|
}
|
|
@@ -717,7 +726,7 @@ export class ToolApprovalCoordinator {
|
|
|
717
726
|
this.shutdownDraining = true;
|
|
718
727
|
for (const e of [...this.pending.values()])
|
|
719
728
|
if (e.settledOutcome === undefined)
|
|
720
|
-
e.forceParkNow();
|
|
729
|
+
e.forceParkNow(APPROVAL_ENDING_CAUSES.SHUTDOWN_BEFORE_PARK);
|
|
721
730
|
}
|
|
722
731
|
async drainForShutdown(deadlineMs) {
|
|
723
732
|
this.beginDrain();
|
|
@@ -789,13 +798,13 @@ export class ToolApprovalCoordinator {
|
|
|
789
798
|
storeErrorCount() {
|
|
790
799
|
return this.storeErrorTally;
|
|
791
800
|
}
|
|
792
|
-
settleVoidedSiblings(askIds) {
|
|
801
|
+
settleVoidedSiblings(askIds, cause) {
|
|
793
802
|
for (const askId of askIds) {
|
|
794
803
|
const entries = this.pendingByAskId.get(askId);
|
|
795
804
|
if (!entries)
|
|
796
805
|
continue;
|
|
797
806
|
for (const entry of [...entries])
|
|
798
|
-
entry.settle(
|
|
807
|
+
entry.settle({ by: "system", cause });
|
|
799
808
|
}
|
|
800
809
|
}
|
|
801
810
|
governanceForcedOf(origin, req) {
|
|
@@ -884,9 +893,13 @@ export class ToolApprovalCoordinator {
|
|
|
884
893
|
classifyClaimLoss(askId, current, _where) {
|
|
885
894
|
if (current.state === "absent")
|
|
886
895
|
return { kind: "absent" };
|
|
896
|
+
const rowCause = current.cause;
|
|
897
|
+
if (rowCause?.kind === "ending")
|
|
898
|
+
return { kind: "ended", cause: rowCause.cause };
|
|
887
899
|
const replayedOutcome = replayTerminalAskRow(current);
|
|
888
|
-
if (replayedOutcome === "unavailable")
|
|
889
|
-
return { kind: "parked" };
|
|
900
|
+
if (replayedOutcome === "unavailable") {
|
|
901
|
+
return rowCause?.kind === "park_trigger" ? { kind: "parked", cause: rowCause.cause } : { kind: "parked" };
|
|
902
|
+
}
|
|
890
903
|
const replayed = settleArgsOfDecided(replayedOutcome);
|
|
891
904
|
if (!replayed.allowed)
|
|
892
905
|
return { kind: "decided", outcome: replayedOutcome };
|
|
@@ -905,20 +918,23 @@ export class ToolApprovalCoordinator {
|
|
|
905
918
|
}
|
|
906
919
|
return false;
|
|
907
920
|
}
|
|
908
|
-
settleSameAskIdParkRoute(askId) {
|
|
921
|
+
settleSameAskIdParkRoute(askId, cause) {
|
|
909
922
|
const entries = this.pendingByAskId.get(askId);
|
|
910
923
|
if (!entries)
|
|
911
924
|
return;
|
|
912
925
|
for (const entry of [...entries])
|
|
913
|
-
entry.settleParkRoute();
|
|
926
|
+
entry.settleParkRoute(cause);
|
|
914
927
|
}
|
|
915
|
-
dispatchClaimTruth(askId, read) {
|
|
928
|
+
dispatchClaimTruth(askId, read, parkedCause) {
|
|
916
929
|
switch (read.kind) {
|
|
917
930
|
case "decided":
|
|
918
931
|
this.notifyExternalDecision(askId, read.outcome);
|
|
919
932
|
return;
|
|
933
|
+
case "ended":
|
|
934
|
+
this.settleVoidedSiblings([askId], read.cause);
|
|
935
|
+
return;
|
|
920
936
|
case "parked":
|
|
921
|
-
this.settleSameAskIdParkRoute(askId);
|
|
937
|
+
this.settleSameAskIdParkRoute(askId, read.cause ?? parkedCause);
|
|
922
938
|
return;
|
|
923
939
|
case "absent":
|
|
924
940
|
case "edit-in-flight":
|
|
@@ -1006,7 +1022,7 @@ export class ToolApprovalCoordinator {
|
|
|
1006
1022
|
const args = settleArgsOfDecided(outcome);
|
|
1007
1023
|
let settled = 0;
|
|
1008
1024
|
for (const entry of [...entries]) {
|
|
1009
|
-
entry.settle(args
|
|
1025
|
+
entry.settle(verdictOfDecided(args));
|
|
1010
1026
|
settled += 1;
|
|
1011
1027
|
}
|
|
1012
1028
|
return { settled };
|
|
@@ -1058,7 +1074,7 @@ export class ToolApprovalCoordinator {
|
|
|
1058
1074
|
this.streams.delete(key);
|
|
1059
1075
|
for (const [, p] of [...this.pending]) {
|
|
1060
1076
|
if (p.targetCtxs?.has(ctx))
|
|
1061
|
-
p.onTargetGone?.(ctx);
|
|
1077
|
+
p.onTargetGone?.(ctx, APPROVAL_ENDING_CAUSES.RUN_EXITED);
|
|
1062
1078
|
}
|
|
1063
1079
|
this.settleParksAwaitingCommit((p) => p.carrierLeg === ctx, "leg-closed");
|
|
1064
1080
|
this.askAudit?.noteLegClosed(ctx.taskId);
|
|
@@ -1240,7 +1256,7 @@ export class ToolApprovalCoordinator {
|
|
|
1240
1256
|
}), "ensureAsk", DURABLE_CALL_TIMEOUT_MS, (late) => {
|
|
1241
1257
|
if (late.row.state !== "STREAM_PENDING") {
|
|
1242
1258
|
lateTerminalRow = late.row;
|
|
1243
|
-
this.dispatchClaimTruth(late.row.askId, this.classifyClaimLoss(late.row.askId, projectAskTerminalClaimTruth(late.row), "late:ensureAsk"));
|
|
1259
|
+
this.dispatchClaimTruth(late.row.askId, this.classifyClaimLoss(late.row.askId, projectAskTerminalClaimTruth(late.row), "late:ensureAsk"), APPROVAL_ENDING_CAUSES.UNDELIVERABLE);
|
|
1244
1260
|
return;
|
|
1245
1261
|
}
|
|
1246
1262
|
lateEnsuredRow = late.inserted ? { askId: late.row.askId, batchId: late.row.batchId } : undefined;
|
|
@@ -1351,7 +1367,8 @@ export class ToolApprovalCoordinator {
|
|
|
1351
1367
|
let timer;
|
|
1352
1368
|
let resolveAllowed;
|
|
1353
1369
|
const allowedP = new Promise((resolve) => { resolveAllowed = resolve; });
|
|
1354
|
-
let lastOutcome =
|
|
1370
|
+
let lastOutcome = SETTLE_OUTCOME.EXPIRED;
|
|
1371
|
+
let lastCause;
|
|
1355
1372
|
const abortListeners = [];
|
|
1356
1373
|
let selfEntry;
|
|
1357
1374
|
let hostSettled;
|
|
@@ -1383,12 +1400,17 @@ export class ToolApprovalCoordinator {
|
|
|
1383
1400
|
}
|
|
1384
1401
|
return shapeDeny(false);
|
|
1385
1402
|
};
|
|
1386
|
-
const settle = (
|
|
1403
|
+
const settle = (verdict) => {
|
|
1387
1404
|
if (done)
|
|
1388
1405
|
return;
|
|
1389
1406
|
done = true;
|
|
1407
|
+
const allowed = verdict.by === "human" && verdict.allowed;
|
|
1408
|
+
const outcome = verdict.by === "system" ? SETTLE_OUTCOME.EXPIRED : verdict.allowed ? SETTLE_OUTCOME.ALLOWED : SETTLE_OUTCOME.DENIED;
|
|
1409
|
+
const hostSettledBy = verdict.hostSettledBy;
|
|
1410
|
+
const updatedInput = verdict.by === "human" ? verdict.updatedInput : undefined;
|
|
1411
|
+
const readRootGrant = verdict.by === "human" ? verdict.readRootGrant : undefined;
|
|
1390
1412
|
hostSettled = hostSettledBy;
|
|
1391
|
-
denyReasonSettled = allowed ?
|
|
1413
|
+
denyReasonSettled = verdict.by === "human" && !verdict.allowed ? verdict.denyReason : undefined;
|
|
1392
1414
|
if (timer)
|
|
1393
1415
|
clearTimeout(timer);
|
|
1394
1416
|
for (const [sig, fn] of abortListeners)
|
|
@@ -1407,19 +1429,23 @@ export class ToolApprovalCoordinator {
|
|
|
1407
1429
|
}
|
|
1408
1430
|
}
|
|
1409
1431
|
lastOutcome = outcome;
|
|
1432
|
+
lastCause = verdict.by === "system" ? verdict.cause : undefined;
|
|
1410
1433
|
releaseAdmission();
|
|
1411
1434
|
if (selfEntry)
|
|
1412
1435
|
selfEntry.settledOutcome = outcome;
|
|
1413
|
-
const
|
|
1414
|
-
const settleRecord = () =>
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1436
|
+
const endedWhileDraining = this.shutdownDraining && verdict.by === "system";
|
|
1437
|
+
const settleRecord = () => {
|
|
1438
|
+
const common = {
|
|
1439
|
+
approvalId: wireApprovalId,
|
|
1440
|
+
...(windowRouteUnavailable ? { parkRouted: true } : {}),
|
|
1441
|
+
...(hostSettledBy !== undefined ? { settledBy: hostSettledBy } : {}),
|
|
1442
|
+
settledAtMs: Date.now(),
|
|
1443
|
+
};
|
|
1444
|
+
return verdict.by === "system"
|
|
1445
|
+
? { ...common, outcome: SETTLE_OUTCOME.EXPIRED, cause: verdict.cause }
|
|
1446
|
+
: { ...common, outcome: verdict.allowed ? SETTLE_OUTCOME.ALLOWED : SETTLE_OUTCOME.DENIED };
|
|
1447
|
+
};
|
|
1448
|
+
if (endedWhileDraining && windowRouteUnavailable && this.unattendedRoutesToPark && this.parkCommits !== undefined) {
|
|
1423
1449
|
this.parksAwaitingCommit.add({
|
|
1424
1450
|
approvalId: wireApprovalId,
|
|
1425
1451
|
taskId: origin.taskId,
|
|
@@ -1434,23 +1460,26 @@ export class ToolApprovalCoordinator {
|
|
|
1434
1460
|
}
|
|
1435
1461
|
resolveAllowed({ allowed, ...(allowed && updatedInput !== undefined ? { updatedInput } : {}), ...(allowed && readRootGrant !== undefined ? { readRootGrant } : {}) });
|
|
1436
1462
|
};
|
|
1437
|
-
const broadcastClaimTruth = (read) => {
|
|
1463
|
+
const broadcastClaimTruth = (read, armCause) => {
|
|
1438
1464
|
if (askId === undefined)
|
|
1439
1465
|
return;
|
|
1440
|
-
this.dispatchClaimTruth(askId, read);
|
|
1466
|
+
this.dispatchClaimTruth(askId, read, armCause);
|
|
1441
1467
|
};
|
|
1442
|
-
const settleFromClaimLoss = (read) => {
|
|
1468
|
+
const settleFromClaimLoss = (read, armCause) => {
|
|
1443
1469
|
switch (read.kind) {
|
|
1444
1470
|
case "decided": {
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
broadcastClaimTruth(read);
|
|
1471
|
+
settle(verdictOfDecided(settleArgsOfDecided(read.outcome)));
|
|
1472
|
+
broadcastClaimTruth(read, armCause);
|
|
1448
1473
|
return true;
|
|
1449
1474
|
}
|
|
1475
|
+
case "ended":
|
|
1476
|
+
settle({ by: "system", cause: read.cause });
|
|
1477
|
+
broadcastClaimTruth(read, armCause);
|
|
1478
|
+
return true;
|
|
1450
1479
|
case "parked":
|
|
1451
1480
|
windowRouteUnavailable = true;
|
|
1452
|
-
settle(
|
|
1453
|
-
broadcastClaimTruth(read);
|
|
1481
|
+
settle({ by: "system", cause: read.cause ?? armCause });
|
|
1482
|
+
broadcastClaimTruth(read, armCause);
|
|
1454
1483
|
return true;
|
|
1455
1484
|
case "absent":
|
|
1456
1485
|
case "edit-in-flight":
|
|
@@ -1461,15 +1490,15 @@ export class ToolApprovalCoordinator {
|
|
|
1461
1490
|
}
|
|
1462
1491
|
}
|
|
1463
1492
|
};
|
|
1464
|
-
const lateClaimLossSettle = (current, intent) => {
|
|
1493
|
+
const lateClaimLossSettle = (current, intent, armCause) => {
|
|
1465
1494
|
if (askId === undefined)
|
|
1466
1495
|
return;
|
|
1467
1496
|
const read = this.classifyClaimLoss(askId, current, `late:${intent}`);
|
|
1468
1497
|
if (done) {
|
|
1469
|
-
broadcastClaimTruth(read);
|
|
1498
|
+
broadcastClaimTruth(read, armCause);
|
|
1470
1499
|
return;
|
|
1471
1500
|
}
|
|
1472
|
-
settleFromClaimLoss(read);
|
|
1501
|
+
settleFromClaimLoss(read, armCause);
|
|
1473
1502
|
};
|
|
1474
1503
|
const boundedClaim = (mk, label, timeoutMs, late) => {
|
|
1475
1504
|
const release = this.admitTerminalClaim(askId ?? wireApprovalId);
|
|
@@ -1510,7 +1539,7 @@ export class ToolApprovalCoordinator {
|
|
|
1510
1539
|
}
|
|
1511
1540
|
if (probed.kind === "row") {
|
|
1512
1541
|
const read = this.classifyClaimLoss(pinnedAskId, probed.current, `yield-probe:${arm.intent}`);
|
|
1513
|
-
if (settleFromClaimLoss(read))
|
|
1542
|
+
if (settleFromClaimLoss(read, arm.cause))
|
|
1514
1543
|
return;
|
|
1515
1544
|
if (read.kind === "edit-in-flight")
|
|
1516
1545
|
lastLoss = probed.current;
|
|
@@ -1547,10 +1576,10 @@ export class ToolApprovalCoordinator {
|
|
|
1547
1576
|
arm.onLostTruth?.(outcome.current);
|
|
1548
1577
|
const read = this.classifyClaimLoss(pinnedAskId, outcome.current, `claim:${arm.intent}`);
|
|
1549
1578
|
if (done) {
|
|
1550
|
-
broadcastClaimTruth(read);
|
|
1579
|
+
broadcastClaimTruth(read, arm.cause);
|
|
1551
1580
|
return;
|
|
1552
1581
|
}
|
|
1553
|
-
if (settleFromClaimLoss(read))
|
|
1582
|
+
if (settleFromClaimLoss(read, arm.cause))
|
|
1554
1583
|
return;
|
|
1555
1584
|
if (read.kind === "absent") {
|
|
1556
1585
|
arm.settleByIntent();
|
|
@@ -1564,24 +1593,24 @@ export class ToolApprovalCoordinator {
|
|
|
1564
1593
|
return;
|
|
1565
1594
|
if (this.editedDecisionInFlight(pinnedAskId)) {
|
|
1566
1595
|
windowRouteUnavailable = true;
|
|
1567
|
-
settle(
|
|
1596
|
+
settle({ by: "system", cause: arm.cause });
|
|
1568
1597
|
return;
|
|
1569
1598
|
}
|
|
1570
|
-
if (lastLoss !== undefined && settleFromClaimLoss(this.classifyClaimLoss(pinnedAskId, lastLoss, `claim-tail:${arm.intent}`)))
|
|
1599
|
+
if (lastLoss !== undefined && settleFromClaimLoss(this.classifyClaimLoss(pinnedAskId, lastLoss, `claim-tail:${arm.intent}`), arm.cause))
|
|
1571
1600
|
return;
|
|
1572
1601
|
recordFailOpen(ambiguousCasFailOpenTag(arm.intent), `askId=${pinnedAskId} attempts=${attempt} claims=${claimsIssued} rejects=${rejects} elapsedMs=${Date.now() - ladderStartedAt}`);
|
|
1573
1602
|
arm.settleByIntent();
|
|
1574
1603
|
};
|
|
1575
|
-
const settleParkRouteIfUnsettled = (hostSettledBy) => {
|
|
1604
|
+
const settleParkRouteIfUnsettled = (hostSettledBy, cause) => {
|
|
1576
1605
|
if (done)
|
|
1577
1606
|
return;
|
|
1578
1607
|
windowRouteUnavailable = true;
|
|
1579
|
-
settle(
|
|
1608
|
+
settle({ by: "system", cause, ...(hostSettledBy !== undefined ? { hostSettledBy } : {}) });
|
|
1580
1609
|
};
|
|
1581
|
-
const windowExpired = (hostSelfReport) => {
|
|
1610
|
+
const windowExpired = (hostSelfReport, cause) => {
|
|
1582
1611
|
void (async () => {
|
|
1583
1612
|
if (!this.askStore || askId === undefined || batchId === undefined) {
|
|
1584
|
-
settleParkRouteIfUnsettled(hostSelfReport);
|
|
1613
|
+
settleParkRouteIfUnsettled(hostSelfReport, cause);
|
|
1585
1614
|
return;
|
|
1586
1615
|
}
|
|
1587
1616
|
const store = this.askStore;
|
|
@@ -1589,45 +1618,46 @@ export class ToolApprovalCoordinator {
|
|
|
1589
1618
|
const pinnedBatchId = batchId;
|
|
1590
1619
|
await resolveLocalOutcome({
|
|
1591
1620
|
intent: "expire",
|
|
1621
|
+
cause,
|
|
1592
1622
|
storeLabel: "claimTerminal(window)",
|
|
1593
|
-
claim: (timeoutMs) => boundedClaim(() => settleByPolicy(store, { askId: pinnedAskId, batchId: pinnedBatchId }, this.unattendedPolicy), "claimTerminal(window)", timeoutMs, (late) => {
|
|
1623
|
+
claim: (timeoutMs) => boundedClaim(() => settleByPolicy(store, { askId: pinnedAskId, batchId: pinnedBatchId }, this.unattendedPolicy, cause), "claimTerminal(window)", timeoutMs, (late) => {
|
|
1594
1624
|
if (!late.claimed) {
|
|
1595
|
-
lateClaimLossSettle(late.current, "expire");
|
|
1625
|
+
lateClaimLossSettle(late.current, "expire", cause);
|
|
1596
1626
|
return;
|
|
1597
1627
|
}
|
|
1598
|
-
this.settleSameAskIdParkRoute(pinnedAskId);
|
|
1599
|
-
this.settleVoidedSiblings(late.voidedSiblings);
|
|
1628
|
+
this.settleSameAskIdParkRoute(pinnedAskId, cause);
|
|
1629
|
+
this.settleVoidedSiblings(late.voidedSiblings, APPROVAL_ENDING_CAUSES.BATCH_SIBLING_WITHDRAWN);
|
|
1600
1630
|
this.emitRevokeTo(aliveCtxs, buildRevokeFrame(pinnedBatchId, late.voidedSiblings, "superseded_by_park", Date.now(), origin.taskId));
|
|
1601
1631
|
}),
|
|
1602
1632
|
onWon: (res) => {
|
|
1603
1633
|
windowRouteUnavailable = true;
|
|
1604
|
-
settle(
|
|
1605
|
-
this.settleSameAskIdParkRoute(pinnedAskId);
|
|
1606
|
-
this.settleVoidedSiblings(res.voidedSiblings);
|
|
1634
|
+
settle({ by: "system", cause });
|
|
1635
|
+
this.settleSameAskIdParkRoute(pinnedAskId, cause);
|
|
1636
|
+
this.settleVoidedSiblings(res.voidedSiblings, APPROVAL_ENDING_CAUSES.BATCH_SIBLING_WITHDRAWN);
|
|
1607
1637
|
this.emitRevokeTo(aliveCtxs, buildRevokeFrame(pinnedBatchId, res.voidedSiblings, "superseded_by_park", Date.now(), origin.taskId));
|
|
1608
1638
|
},
|
|
1609
|
-
settleByIntent: () => settleParkRouteIfUnsettled(hostSelfReport),
|
|
1639
|
+
settleByIntent: () => settleParkRouteIfUnsettled(hostSelfReport, cause),
|
|
1610
1640
|
});
|
|
1611
1641
|
})();
|
|
1612
1642
|
};
|
|
1613
|
-
const forceParkNow = () => {
|
|
1643
|
+
const forceParkNow = (cause) => {
|
|
1614
1644
|
if (done)
|
|
1615
1645
|
return;
|
|
1616
1646
|
if (!this.askStore || askId === undefined || batchId === undefined) {
|
|
1617
|
-
settleParkRouteIfUnsettled(undefined);
|
|
1647
|
+
settleParkRouteIfUnsettled(undefined, cause);
|
|
1618
1648
|
return;
|
|
1619
1649
|
}
|
|
1620
|
-
windowExpired(undefined);
|
|
1650
|
+
windowExpired(undefined, cause);
|
|
1621
1651
|
};
|
|
1622
|
-
timer = setTimeout(() => windowExpired("timeout"), this.askStore ? Math.max(0, persistedExpiresAtMs - Date.now()) : effectiveWindowMs);
|
|
1652
|
+
timer = setTimeout(() => windowExpired("timeout", APPROVAL_ENDING_CAUSES.TTL_EXPIRED), this.askStore ? Math.max(0, persistedExpiresAtMs - Date.now()) : effectiveWindowMs);
|
|
1623
1653
|
timer.unref?.();
|
|
1624
|
-
const runCancel = async () => {
|
|
1654
|
+
const runCancel = async (cause) => {
|
|
1625
1655
|
if (!this.askStore || askId === undefined || batchId === undefined) {
|
|
1626
|
-
settle(
|
|
1656
|
+
settle({ by: "system", cause });
|
|
1627
1657
|
return;
|
|
1628
1658
|
}
|
|
1629
1659
|
if (this.hasOtherSuspendedOwner(askId, selfEntry)) {
|
|
1630
|
-
settle(
|
|
1660
|
+
settle({ by: "system", cause });
|
|
1631
1661
|
return;
|
|
1632
1662
|
}
|
|
1633
1663
|
const store = this.askStore;
|
|
@@ -1640,52 +1670,53 @@ export class ToolApprovalCoordinator {
|
|
|
1640
1670
|
};
|
|
1641
1671
|
await resolveLocalOutcome({
|
|
1642
1672
|
intent: "cancel",
|
|
1673
|
+
cause,
|
|
1643
1674
|
storeLabel: "claimTerminal(cancel)",
|
|
1644
|
-
claim: (timeoutMs) => boundedClaim(() => store.claimTerminal(pinnedAskId, pinnedBatchId, "cancel"), "claimTerminal(cancel)", timeoutMs, (late) => {
|
|
1675
|
+
claim: (timeoutMs) => boundedClaim(() => store.claimTerminal(pinnedAskId, pinnedBatchId, "cancel", { cause }), "claimTerminal(cancel)", timeoutMs, (late) => {
|
|
1645
1676
|
if (!late.claimed) {
|
|
1646
1677
|
cancelLostTruth(late.current);
|
|
1647
|
-
lateClaimLossSettle(late.current, "cancel");
|
|
1678
|
+
lateClaimLossSettle(late.current, "cancel", cause);
|
|
1648
1679
|
return;
|
|
1649
1680
|
}
|
|
1650
|
-
this.settleVoidedSiblings([pinnedAskId]);
|
|
1681
|
+
this.settleVoidedSiblings([pinnedAskId], cause);
|
|
1651
1682
|
this.recordParkTombstone(wireApprovalId, { kind: "voidBridge", askId: pinnedAskId, batchId: pinnedBatchId, owner: origin.owner, parkedAtMs: Date.now() });
|
|
1652
1683
|
this.emitRevokeTo(aliveCtxs, buildRevokeFrame(pinnedBatchId, [pinnedAskId], "aborted", Date.now(), origin.taskId));
|
|
1653
1684
|
}),
|
|
1654
1685
|
onWon: () => {
|
|
1655
|
-
settle(
|
|
1656
|
-
this.settleVoidedSiblings([pinnedAskId]);
|
|
1686
|
+
settle({ by: "system", cause });
|
|
1687
|
+
this.settleVoidedSiblings([pinnedAskId], cause);
|
|
1657
1688
|
this.recordParkTombstone(wireApprovalId, { kind: "voidBridge", askId: pinnedAskId, batchId: pinnedBatchId, owner: origin.owner, parkedAtMs: Date.now() });
|
|
1658
1689
|
this.emitRevokeTo(aliveCtxs, buildRevokeFrame(pinnedBatchId, [pinnedAskId], "aborted", Date.now(), origin.taskId));
|
|
1659
1690
|
},
|
|
1660
1691
|
onLostTruth: cancelLostTruth,
|
|
1661
|
-
settleByIntent: () => settle(
|
|
1692
|
+
settleByIntent: () => settle({ by: "system", cause }),
|
|
1662
1693
|
});
|
|
1663
1694
|
};
|
|
1664
1695
|
if (signal) {
|
|
1665
|
-
const onTaskAbort = () => void runCancel();
|
|
1696
|
+
const onTaskAbort = () => void runCancel(APPROVAL_ENDING_CAUSES.RUN_CANCELLED);
|
|
1666
1697
|
signal.addEventListener("abort", onTaskAbort, { once: true });
|
|
1667
1698
|
abortListeners.push([signal, onTaskAbort]);
|
|
1668
1699
|
}
|
|
1669
1700
|
let liveConnections = aliveCtxs.length;
|
|
1670
1701
|
const goneCtxs = new Set();
|
|
1671
|
-
const onTargetGone = (c) => {
|
|
1702
|
+
const onTargetGone = (c, cause) => {
|
|
1672
1703
|
if (goneCtxs.has(c))
|
|
1673
1704
|
return;
|
|
1674
1705
|
goneCtxs.add(c);
|
|
1675
1706
|
liveConnections--;
|
|
1676
1707
|
if (liveConnections <= 0)
|
|
1677
|
-
void runCancel();
|
|
1708
|
+
void runCancel(cause);
|
|
1678
1709
|
};
|
|
1679
1710
|
for (const c of aliveCtxs) {
|
|
1680
1711
|
if (!c.abortSignal)
|
|
1681
1712
|
continue;
|
|
1682
|
-
const onCtxAbort = () => onTargetGone(c);
|
|
1713
|
+
const onCtxAbort = () => onTargetGone(c, APPROVAL_ENDING_CAUSES.RUN_CANCELLED);
|
|
1683
1714
|
c.abortSignal.addEventListener("abort", onCtxAbort, { once: true });
|
|
1684
1715
|
abortListeners.push([c.abortSignal, onCtxAbort]);
|
|
1685
1716
|
}
|
|
1686
1717
|
const earlyAbortDuringEnsure = signal?.aborted === true || aliveCtxs.some((c) => c.abortSignal?.aborted === true);
|
|
1687
1718
|
if (earlyAbortDuringEnsure) {
|
|
1688
|
-
await runCancel();
|
|
1719
|
+
await runCancel(APPROVAL_ENDING_CAUSES.RUN_CANCELLED);
|
|
1689
1720
|
if (done) {
|
|
1690
1721
|
return shapeOutcome(await allowedP);
|
|
1691
1722
|
}
|
|
@@ -1712,7 +1743,7 @@ export class ToolApprovalCoordinator {
|
|
|
1712
1743
|
const pendingEntry = {
|
|
1713
1744
|
settle,
|
|
1714
1745
|
forceParkNow,
|
|
1715
|
-
settleParkRoute: () => settleParkRouteIfUnsettled(),
|
|
1746
|
+
settleParkRoute: (cause) => settleParkRouteIfUnsettled(undefined, cause),
|
|
1716
1747
|
owner: origin.owner,
|
|
1717
1748
|
...(primary ? { ctxTaskId: primary.taskId, originCtx: primary } : {}),
|
|
1718
1749
|
...(reachability === "unreached" ? { suspended: true } : {}),
|
|
@@ -1756,7 +1787,7 @@ export class ToolApprovalCoordinator {
|
|
|
1756
1787
|
mintedAtMs: Date.now(),
|
|
1757
1788
|
});
|
|
1758
1789
|
if (this.shutdownDraining)
|
|
1759
|
-
forceParkNow();
|
|
1790
|
+
forceParkNow(APPROVAL_ENDING_CAUSES.SHUTDOWN_BEFORE_PARK);
|
|
1760
1791
|
const cardFrame = askId !== undefined && cardForFrame !== undefined
|
|
1761
1792
|
? buildApprovalRequestFrame({ askId, taskId: origin.taskId, approvalId: wireApprovalId, card: cardForFrame, expiresAtMs: persistedExpiresAtMs, nowMs: Date.now() })
|
|
1762
1793
|
: undefined;
|
|
@@ -1799,30 +1830,31 @@ export class ToolApprovalCoordinator {
|
|
|
1799
1830
|
if (done)
|
|
1800
1831
|
return;
|
|
1801
1832
|
emitFailed = true;
|
|
1802
|
-
settle(
|
|
1833
|
+
settle({ by: "system", cause: APPROVAL_ENDING_CAUSES.BROADCAST_LOST });
|
|
1803
1834
|
};
|
|
1804
1835
|
await resolveLocalOutcome({
|
|
1805
1836
|
intent: "unreachable",
|
|
1837
|
+
cause: APPROVAL_ENDING_CAUSES.BROADCAST_LOST,
|
|
1806
1838
|
storeLabel: "claimTerminal(emit-failed)",
|
|
1807
|
-
claim: (timeoutMs) => boundedClaim(() => settleByPolicy(store, { askId: pinnedAskId, batchId: pinnedBatchId }, this.unattendedPolicy), "claimTerminal(emit-failed)", timeoutMs, (late) => {
|
|
1839
|
+
claim: (timeoutMs) => boundedClaim(() => settleByPolicy(store, { askId: pinnedAskId, batchId: pinnedBatchId }, this.unattendedPolicy, APPROVAL_ENDING_CAUSES.BROADCAST_LOST), "claimTerminal(emit-failed)", timeoutMs, (late) => {
|
|
1808
1840
|
if (!late.claimed) {
|
|
1809
|
-
lateClaimLossSettle(late.current, "unreachable");
|
|
1841
|
+
lateClaimLossSettle(late.current, "unreachable", APPROVAL_ENDING_CAUSES.BROADCAST_LOST);
|
|
1810
1842
|
return;
|
|
1811
1843
|
}
|
|
1812
|
-
this.settleSameAskIdParkRoute(pinnedAskId);
|
|
1813
|
-
this.settleVoidedSiblings(late.voidedSiblings);
|
|
1844
|
+
this.settleSameAskIdParkRoute(pinnedAskId, APPROVAL_ENDING_CAUSES.BROADCAST_LOST);
|
|
1845
|
+
this.settleVoidedSiblings(late.voidedSiblings, APPROVAL_ENDING_CAUSES.BATCH_SIBLING_WITHDRAWN);
|
|
1814
1846
|
}),
|
|
1815
1847
|
onWon: (res) => {
|
|
1816
1848
|
settleUnreachable();
|
|
1817
|
-
this.settleSameAskIdParkRoute(pinnedAskId);
|
|
1818
|
-
this.settleVoidedSiblings(res.voidedSiblings);
|
|
1849
|
+
this.settleSameAskIdParkRoute(pinnedAskId, APPROVAL_ENDING_CAUSES.BROADCAST_LOST);
|
|
1850
|
+
this.settleVoidedSiblings(res.voidedSiblings, APPROVAL_ENDING_CAUSES.BATCH_SIBLING_WITHDRAWN);
|
|
1819
1851
|
},
|
|
1820
1852
|
settleByIntent: settleUnreachable,
|
|
1821
1853
|
});
|
|
1822
1854
|
}
|
|
1823
1855
|
else if (!done) {
|
|
1824
1856
|
emitFailed = true;
|
|
1825
|
-
settle(
|
|
1857
|
+
settle({ by: "system", cause: APPROVAL_ENDING_CAUSES.BROADCAST_LOST });
|
|
1826
1858
|
}
|
|
1827
1859
|
}
|
|
1828
1860
|
})();
|
|
@@ -1836,6 +1868,7 @@ export class ToolApprovalCoordinator {
|
|
|
1836
1868
|
type: "tool_approval_complete",
|
|
1837
1869
|
approvalId: wireApprovalId,
|
|
1838
1870
|
outcome: lastOutcome,
|
|
1871
|
+
...(lastCause !== undefined ? { cause: lastCause } : {}),
|
|
1839
1872
|
...(parkRouted ? { parked: true } : {}),
|
|
1840
1873
|
})
|
|
1841
1874
|
: undefined)
|
|
@@ -1845,7 +1878,7 @@ export class ToolApprovalCoordinator {
|
|
|
1845
1878
|
return this.unattendedOutcome({ arm: "emit_failed", taskId: origin.taskId, ...(origin.owner !== null ? { owner: origin.owner } : {}), toolName: req.toolName, reachability });
|
|
1846
1879
|
if (windowRouteUnavailable)
|
|
1847
1880
|
return shapeOutcome(settled);
|
|
1848
|
-
if (!emitSettled && lastOutcome ===
|
|
1881
|
+
if (!emitSettled && lastOutcome === SETTLE_OUTCOME.EXPIRED)
|
|
1849
1882
|
return this.unattendedOutcome({ arm: "emit_unsettled", taskId: origin.taskId, ...(origin.owner !== null ? { owner: origin.owner } : {}), toolName: req.toolName, reachability });
|
|
1850
1883
|
return shapeOutcome(settled);
|
|
1851
1884
|
}
|
|
@@ -1941,7 +1974,7 @@ export class ToolApprovalCoordinator {
|
|
|
1941
1974
|
return this.notPending();
|
|
1942
1975
|
const tomb = this.lookupParkTombstone(id);
|
|
1943
1976
|
if (tomb === undefined || (tomb.owner !== null && tomb.owner !== principal)) {
|
|
1944
|
-
return this.notPending(
|
|
1977
|
+
return this.notPending(NOT_PENDING_UNKNOWN_CAUSE);
|
|
1945
1978
|
}
|
|
1946
1979
|
return this.dispatchLateByRow(store, tomb, id, parsed, httpReq, principal);
|
|
1947
1980
|
}
|
|
@@ -1952,13 +1985,13 @@ export class ToolApprovalCoordinator {
|
|
|
1952
1985
|
}
|
|
1953
1986
|
catch (err) {
|
|
1954
1987
|
this.noteStoreError(err, "getAsk(respond-late)");
|
|
1955
|
-
return this.notPending(
|
|
1988
|
+
return this.notPending(NOT_PENDING_UNKNOWN_CAUSE);
|
|
1956
1989
|
}
|
|
1957
1990
|
if (row === null)
|
|
1958
|
-
return this.notPending(
|
|
1991
|
+
return this.notPending(NOT_PENDING_UNKNOWN_CAUSE);
|
|
1959
1992
|
if (row.owner !== null && row.owner !== principal) {
|
|
1960
1993
|
defaultLogger.warn("tool approval late decision rejected: the ask row changed owner since it parked", { askId: row.askId });
|
|
1961
|
-
return this.notPending(
|
|
1994
|
+
return this.notPending(NOT_PENDING_UNKNOWN_CAUSE);
|
|
1962
1995
|
}
|
|
1963
1996
|
if (tomb.redeemed !== undefined)
|
|
1964
1997
|
return this.replayRedeemReceipt(id, tomb, row, tomb.redeemed, parsed);
|
|
@@ -1985,11 +2018,12 @@ export class ToolApprovalCoordinator {
|
|
|
1985
2018
|
};
|
|
1986
2019
|
}
|
|
1987
2020
|
case "DENIED":
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
return this.notPending("
|
|
2021
|
+
case "VOID": {
|
|
2022
|
+
const rowCause = causeOfAskRow(row);
|
|
2023
|
+
return this.notPending(rowCause?.kind === "ending" ? rowCause.cause : undefined);
|
|
2024
|
+
}
|
|
1991
2025
|
case "STREAM_PENDING":
|
|
1992
|
-
return this.notPending(
|
|
2026
|
+
return this.notPending(NOT_PENDING_UNKNOWN_CAUSE);
|
|
1993
2027
|
default: {
|
|
1994
2028
|
const unhandled = row.state;
|
|
1995
2029
|
defaultLogger.error("tool approval respond hit an unknown ask state", { askId: tomb.askId, state: unhandled });
|
|
@@ -2326,7 +2360,7 @@ export class ToolApprovalCoordinator {
|
|
|
2326
2360
|
if (this.pending.get(id) !== entry) {
|
|
2327
2361
|
if (winnerRow !== undefined)
|
|
2328
2362
|
this.notifyExternalDecision(askId, outcomeOfDecidedRow(winnerRow));
|
|
2329
|
-
const converged = decidedWon && entry.settledOutcome === (wantAllowed ?
|
|
2363
|
+
const converged = decidedWon && entry.settledOutcome === (wantAllowed ? SETTLE_OUTCOME.ALLOWED : SETTLE_OUTCOME.DENIED);
|
|
2330
2364
|
if (!converged) {
|
|
2331
2365
|
return this.notPending();
|
|
2332
2366
|
}
|
|
@@ -2373,7 +2407,14 @@ export class ToolApprovalCoordinator {
|
|
|
2373
2407
|
const allowed = parsed.value !== "deny";
|
|
2374
2408
|
const settleArgs = opts?.settleOutcome !== undefined ? settleArgsOfDecided(opts.settleOutcome) : { allowed, updatedInput: parsed.updatedInput, settledBy: liveSettledBy(parsed.decidedBy) };
|
|
2375
2409
|
const readRootGrant = opts?.settleOutcome === undefined || opts.settleOutcomeIsThisRequest === true ? parsed.readRootGrant : undefined;
|
|
2376
|
-
entry.settle(
|
|
2410
|
+
entry.settle({
|
|
2411
|
+
by: "human",
|
|
2412
|
+
allowed: settleArgs.allowed,
|
|
2413
|
+
updatedInput: settleArgs.updatedInput,
|
|
2414
|
+
...(settleArgs.settledBy !== undefined ? { hostSettledBy: settleArgs.settledBy } : {}),
|
|
2415
|
+
...(!settleArgs.allowed && parsed.note !== undefined ? { denyReason: parsed.note } : {}),
|
|
2416
|
+
...(readRootGrant !== undefined ? { readRootGrant } : {}),
|
|
2417
|
+
});
|
|
2377
2418
|
const updatedInputDelivered = opts?.updatedInputDelivered ?? true;
|
|
2378
2419
|
const noteRecorded = opts?.noteRecorded ?? false;
|
|
2379
2420
|
return {
|
|
@@ -2456,10 +2497,18 @@ export class ToolApprovalCoordinator {
|
|
|
2456
2497
|
continue;
|
|
2457
2498
|
if (this.editedDecisionInFlight(askId))
|
|
2458
2499
|
continue;
|
|
2500
|
+
const rowCause = causeOfAskRow(row);
|
|
2501
|
+
if (rowCause?.kind === "ending") {
|
|
2502
|
+
const before = this.pendingByAskId.get(askId)?.size ?? 0;
|
|
2503
|
+
this.settleVoidedSiblings([askId], rowCause.cause);
|
|
2504
|
+
settled += before;
|
|
2505
|
+
continue;
|
|
2506
|
+
}
|
|
2459
2507
|
const outcome = replayTerminalAskRow(row);
|
|
2460
2508
|
if (outcome === "unavailable") {
|
|
2461
2509
|
const before = this.pendingByAskId.get(askId)?.size ?? 0;
|
|
2462
|
-
|
|
2510
|
+
const parkCause = (rowCause?.kind === "park_trigger" ? rowCause.cause : undefined) ?? (Date.now() >= row.expiresAtMs ? APPROVAL_ENDING_CAUSES.TTL_EXPIRED : APPROVAL_ENDING_CAUSES.SHUTDOWN_BEFORE_PARK);
|
|
2511
|
+
this.settleSameAskIdParkRoute(askId, parkCause);
|
|
2463
2512
|
settled += before;
|
|
2464
2513
|
continue;
|
|
2465
2514
|
}
|
|
@@ -47,7 +47,7 @@ type AskProjected = "toolName" | "toolCallId" | "args" | "message" | "sourceTask
|
|
|
47
47
|
type AskExcluded = "preview" | "principal" | "riskAxes" | "boundInputHash" | "isDelegatedChild" | "hasBidiControls" | "previewWithheld" | "execCwd" | "authoredBy";
|
|
48
48
|
type _GuardAsk = AssertAllKeysHandled<Exclude<keyof AskRequest, AskProjected | AskExcluded>>;
|
|
49
49
|
type _GuardAskReverse = AssertAllKeysHandled<Exclude<AskProjected | AskExcluded, keyof AskRequest>>;
|
|
50
|
-
type AskFrameServerMinted = "type" | "approvalId" | "argsOmitted" | "outcome" | "governanceForced" | "expiresAtMs" | "expiresInMs" | "serverNowMs" | "parked" | "inputHasBidi" | "rememberRefused";
|
|
50
|
+
type AskFrameServerMinted = "type" | "approvalId" | "argsOmitted" | "outcome" | "governanceForced" | "expiresAtMs" | "expiresInMs" | "serverNowMs" | "parked" | "cause" | "inputHasBidi" | "rememberRefused";
|
|
51
51
|
type _GuardAskFrame = AssertAllKeysHandled<Exclude<keyof ToolApprovalFrame, AskProjected | AskFrameServerMinted>>;
|
|
52
52
|
type _GuardAskFrameReverse = AssertAllKeysHandled<Exclude<AskProjected | AskFrameServerMinted, keyof ToolApprovalFrame>>;
|
|
53
53
|
type TaskEventHandled = "text_delta" | "reasoning_delta" | "tool_start" | "tool_end" | "turn_end" | "compacted" | "diagnostics" | "message_committed" | "status" | "task_notification" | "task_progress" | "steering_injected" | "workspace_changed" | "done" | "context_usage" | "compaction_outcome" | "human_input" | "wiring_manifest" | "text_end" | "tool_roster_delta" | "tool_progress" | "tool_disclosure";
|
package/dist/trace/project.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Task Trace projection (S1): the durable run event log →
|
|
2
|
+
* Task Trace projection (S1): the durable run event log → web-admin's `TraceTurn[]` contract.
|
|
3
3
|
*
|
|
4
4
|
* The event log (src/runs.ts) is a flat per-task seq stream: reasoning / text / tool_start / tool_end /
|
|
5
|
-
* turn_end / compacted / done / suspended / failed.
|
|
5
|
+
* turn_end / compacted / done / suspended / failed. web-admin renders an ORDERED `blocks[]` transcript
|
|
6
6
|
* (CC-style thinking↔tool interleave), grouped into turns. This is pure presentation/projection = the
|
|
7
7
|
* SERVICE layer (core [R57] cross-review: do NOT push this shape into core — different consumer, different shape).
|
|
8
8
|
*
|
|
@@ -1031,7 +1031,7 @@ export declare function taskSummary(run: RunRecord, latestEventType?: string): T
|
|
|
1031
1031
|
* 🔴 刻意**只**认这一个键,不做成映射表:帧名归一是历史包袱的一次性偿还,不是一条可以长胖的兼容层。
|
|
1032
1032
|
* 再有第二个名字对不齐,应当在源头修,而不是往这里加一行。 */
|
|
1033
1033
|
export declare function normalizeRunEventType(type: string): string;
|
|
1034
|
-
/** Map one durable event → a
|
|
1034
|
+
/** Map one durable event → a web-admin SSE trace event (contract 2.3). null = not a client event. The
|
|
1035
1035
|
* durable log is block-grained, so each block ships as one "delta" the client appends (stream mode = "delta"). */
|
|
1036
1036
|
export declare function mapTraceEvent(type: string, seq: number, data: Record<string, unknown>): {
|
|
1037
1037
|
event: string;
|