@sema-agent/server 7.77.0 → 7.78.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/approval-card.d.ts +24 -1
  2. package/dist/approval-card.js +13 -0
  3. package/dist/boot/resolve-spec.js +3 -0
  4. package/dist/boot/runner-deps.js +3 -1
  5. package/dist/config-catalog.js +1 -0
  6. package/dist/config-center/read-warnings.d.ts +10 -1
  7. package/dist/config-center/read-warnings.js +5 -1
  8. package/dist/config-provider.js +2 -2
  9. package/dist/config-types.d.ts +13 -1
  10. package/dist/config.js +2 -1
  11. package/dist/http/routes/approvals-assistant.d.ts +22 -0
  12. package/dist/http/routes/approvals-assistant.js +4 -1
  13. package/dist/http/routes/tasks.js +14 -9
  14. package/dist/http/routes/workflows.js +7 -1
  15. package/dist/http/server.d.ts +28 -4
  16. package/dist/http/server.js +47 -13
  17. package/dist/observability/fail-open.d.ts +4 -0
  18. package/dist/observability/fail-open.js +4 -0
  19. package/dist/observability/run-terminal-log.js +1 -0
  20. package/dist/orchestration/workflow-agent-session-index.d.ts +7 -3
  21. package/dist/parked-decide.d.ts +27 -12
  22. package/dist/parked-decide.js +1 -1
  23. package/dist/plugins/workflow-run-store-sql.d.ts +7 -3
  24. package/dist/request-key-closure.d.ts +30 -0
  25. package/dist/request-key-closure.js +56 -0
  26. package/dist/runs.js +3 -1
  27. package/dist/runtime-governance.d.ts +18 -4
  28. package/dist/runtime-governance.js +2 -2
  29. package/dist/spec-fields.d.ts +3 -1
  30. package/dist/spec-fields.js +4 -5
  31. package/dist/task-settings.d.ts +18 -16
  32. package/dist/task-settings.js +17 -29
  33. package/dist/tool-approval.d.ts +35 -3
  34. package/dist/tool-approval.js +41 -19
  35. package/dist/trace/core-keyset-guard.d.ts +8 -8
  36. package/dist/trace/ledger-events.d.ts +7 -1
  37. package/dist/trace/ledger-sink.js +19 -6
  38. package/dist/trace/model-segment.d.ts +32 -2
  39. package/dist/trace/model-segment.js +16 -6
  40. package/dist/trace/project.d.ts +95 -3
  41. package/dist/trace/project.js +128 -12
  42. package/dist/trace/redact.js +159 -13
  43. package/package.json +4 -4
@@ -8,7 +8,7 @@ import { approvalPayloadFingerprint } from "./plugins/approval-payload-fingerpri
8
8
  import { createLogger } from "./observability/logger.js";
9
9
  import { recordFailOpen } from "./observability/fail-open.js";
10
10
  import { deriveAskId, deriveBatchId, MAX_DECISION_NOTE_CHARS } from "./approval-ask-machine.js";
11
- import { ApprovalCardEnvelopeSchema, MAX_RULE_OFFERS, buildApprovalCard, buildApprovalCardEnvelope, buildApprovalRequestFrame, buildRevokeFrame, readDenialLimitFallback, readProbeCause, readRuleEvidence, readRuleOffersAbsence, RuleOfferRawSchema, backfillLegacyBatchMemberKind, screenUncoveredDetailSeat, } from "./approval-card.js";
11
+ import { ApprovalCardEnvelopeSchema, MAX_RULE_OFFERS, buildApprovalCard, buildApprovalCardEnvelope, buildApprovalRequestFrame, buildRevokeFrame, readDenialLimitFallback, readProbeCause, readReadRootCandidate, readRuleEvidence, readRuleOffersAbsence, RuleOfferRawSchema, backfillLegacyBatchMemberKind, screenUncoveredDetailSeat, } from "./approval-card.js";
12
12
  import { projectAskTerminalClaimTruth } from "./plugins/approval-ask-store-sql.js";
13
13
  import { governanceAskMarksFor, runWithGovernanceAskScope } from "./governance-ask-marks.js";
14
14
  const defaultLogger = createLogger();
@@ -300,11 +300,29 @@ export class ToolApprovalCoordinator {
300
300
  this.parkTombstonePerPrincipalMax = opts?.parkTombstonePerPrincipalMax ?? DEFAULT_PARK_TOMBSTONE_PER_PRINCIPAL_MAX;
301
301
  this.askAudit = opts?.askAudit;
302
302
  }
303
- unattendedOutcome() {
304
- return this.unattendedPolicy === "deny" ? false : "unavailable";
303
+ unattendedOutcome(site) {
304
+ const outcome = this.unattendedPolicy === "deny" ? false : "unavailable";
305
+ defaultLogger.warn("approver_unavailable", {
306
+ arm: site.arm,
307
+ policy: this.unattendedPolicy,
308
+ outcome: outcome === false ? "deny" : "unavailable",
309
+ owner: site.owner ?? null,
310
+ taskId: site.taskId ?? null,
311
+ toolName: site.toolName ?? null,
312
+ reachability: site.reachability ?? null,
313
+ });
314
+ return outcome;
315
+ }
316
+ get unattendedRoutesToPark() {
317
+ return this.unattendedPolicy !== "deny";
305
318
  }
306
- unattendedAskOutcome() {
307
- return this.unattendedOutcome();
319
+ unattendedAskOutcome(site) {
320
+ return this.unattendedOutcome({
321
+ arm: "window_zero",
322
+ ...(site.taskId !== undefined ? { taskId: site.taskId } : {}),
323
+ ...(site.owner !== undefined && site.owner !== null ? { owner: site.owner } : {}),
324
+ ...(site.toolName !== undefined ? { toolName: site.toolName } : {}),
325
+ });
308
326
  }
309
327
  admit(taskId, owner) {
310
328
  if (!this.askStore)
@@ -758,7 +776,7 @@ export class ToolApprovalCoordinator {
758
776
  ask = async (req, signal) => {
759
777
  const ctx = this.als.getStore();
760
778
  if (!ctx)
761
- return this.unattendedOutcome();
779
+ return this.unattendedOutcome({ arm: "no_run_context", toolName: req.toolName });
762
780
  return this.askBroadcast({
763
781
  taskId: ctx.taskId,
764
782
  owner: ctx.owner,
@@ -786,11 +804,9 @@ export class ToolApprovalCoordinator {
786
804
  const aliveCtxs = ctxs.filter((c) => !c.abortSignal?.aborted);
787
805
  const reachability = aliveCtxs.length === 0 ? "unreached" : "reachable";
788
806
  if (reachability === "unreached") {
789
- const unattended = this.unattendedOutcome();
790
- if (unattended === false)
791
- return unattended;
792
- if (!this.askStore)
793
- return unattended;
807
+ if (!this.unattendedRoutesToPark || !this.askStore) {
808
+ return this.unattendedOutcome({ arm: "no_live_target", taskId: origin.taskId, ...(origin.owner !== null ? { owner: origin.owner } : {}), toolName: req.toolName, reachability });
809
+ }
794
810
  }
795
811
  const primary = aliveCtxs[0];
796
812
  const governanceForced = (this.governanceAskMarks ?? governanceAskMarksFor(this.streamKey(origin.owner, origin.sessionId, origin.taskId))).isMarked(req.toolCallId);
@@ -809,7 +825,7 @@ export class ToolApprovalCoordinator {
809
825
  admitMaxPerTask: this.admitMaxPerTask,
810
826
  admitMaxPerOwner: this.admitMaxPerOwner,
811
827
  });
812
- return this.unattendedOutcome();
828
+ return this.unattendedOutcome({ arm: "admission_exhausted", taskId: origin.taskId, ...(origin.owner !== null ? { owner: origin.owner } : {}), toolName: req.toolName, reachability });
813
829
  }
814
830
  const id = uuidv7();
815
831
  const child = isChildAsk(req);
@@ -848,6 +864,7 @@ export class ToolApprovalCoordinator {
848
864
  ...((a) => (a !== undefined ? { ruleOffersAbsence: a } : {}))(readRuleOffersAbsence(req)),
849
865
  ...((f) => (f !== undefined ? { denialLimitFallback: f } : {}))(readDenialLimitFallback(req)),
850
866
  ...(typeof req.ruleStoreUnreadable === "string" && req.ruleStoreUnreadable.length > 0 ? { ruleStoreUnreadable: req.ruleStoreUnreadable } : {}),
867
+ ...((g) => (g !== undefined ? { readRootCandidate: g } : {}))(readReadRootCandidate(req)),
851
868
  ...((c) => (c !== undefined ? { probeCause: c } : {}))(readProbeCause(req)),
852
869
  ...((c) => (c !== undefined ? { ruleEvidence: c } : {}))(readRuleEvidence(req)),
853
870
  ...(bounded.omitted ? { argsOmitted: true } : { args: bounded.args }),
@@ -904,7 +921,9 @@ export class ToolApprovalCoordinator {
904
921
  if (existingOrCreated.row.state !== "STREAM_PENDING") {
905
922
  releaseAdmission();
906
923
  const replayed = replayTerminalAskRow(existingOrCreated.row);
907
- return replayed === "unavailable" ? this.unattendedOutcome() : replayed;
924
+ return replayed === "unavailable"
925
+ ? this.unattendedOutcome({ arm: "replayed_parked", taskId: origin.taskId, ...(origin.owner !== null ? { owner: origin.owner } : {}), toolName: req.toolName, reachability })
926
+ : replayed;
908
927
  }
909
928
  const persistedEnvelope = ApprovalCardEnvelopeSchema.safeParse(existingOrCreated.row.cardJson);
910
929
  const maxMintableWindowMs = Math.max(effectiveWindowMs, this.unreachedTtlMs);
@@ -985,7 +1004,7 @@ export class ToolApprovalCoordinator {
985
1004
  voidAbandonedRow(lateEnsuredAskId);
986
1005
  if (reachability === "unreached") {
987
1006
  releaseAdmission();
988
- return this.unattendedOutcome();
1007
+ return this.unattendedOutcome({ arm: "unreached_no_row", taskId: origin.taskId, ...(origin.owner !== null ? { owner: origin.owner } : {}), toolName: req.toolName, reachability });
989
1008
  }
990
1009
  }
991
1010
  }
@@ -1014,8 +1033,11 @@ export class ToolApprovalCoordinator {
1014
1033
  return false;
1015
1034
  };
1016
1035
  const shapeOutcome = (settled) => {
1017
- if (windowRouteUnavailable)
1018
- return this.unattendedOutcome() === false ? shapeDeny() : "unavailable";
1036
+ if (windowRouteUnavailable) {
1037
+ return this.unattendedOutcome({ arm: "window_expired", taskId: origin.taskId, ...(origin.owner !== null ? { owner: origin.owner } : {}), toolName: req.toolName, reachability }) === false
1038
+ ? shapeDeny()
1039
+ : "unavailable";
1040
+ }
1019
1041
  if (settled.allowed) {
1020
1042
  return settled.updatedInput !== undefined ? { allow: true, updatedInput: settled.updatedInput } : true;
1021
1043
  }
@@ -1032,7 +1054,7 @@ export class ToolApprovalCoordinator {
1032
1054
  for (const [sig, fn] of abortListeners)
1033
1055
  sig.removeEventListener("abort", fn);
1034
1056
  this.pending.delete(id);
1035
- if (windowRouteUnavailable && askId !== undefined && batchId !== undefined && this.unattendedOutcome() !== false) {
1057
+ if (windowRouteUnavailable && askId !== undefined && batchId !== undefined && this.unattendedRoutesToPark) {
1036
1058
  this.recordParkTombstone(wireApprovalId, { kind: "park", askId, batchId, owner: origin.owner, parkedAtMs: Date.now() });
1037
1059
  parkRouted = true;
1038
1060
  }
@@ -1456,11 +1478,11 @@ export class ToolApprovalCoordinator {
1456
1478
  .catch(() => undefined);
1457
1479
  }
1458
1480
  if (emitFailed)
1459
- return this.unattendedOutcome();
1481
+ return this.unattendedOutcome({ arm: "emit_failed", taskId: origin.taskId, ...(origin.owner !== null ? { owner: origin.owner } : {}), toolName: req.toolName, reachability });
1460
1482
  if (windowRouteUnavailable)
1461
1483
  return shapeOutcome(settled);
1462
1484
  if (!emitSettled && lastOutcome === "expired")
1463
- return this.unattendedOutcome();
1485
+ return this.unattendedOutcome({ arm: "emit_unsettled", taskId: origin.taskId, ...(origin.owner !== null ? { owner: origin.owner } : {}), toolName: req.toolName, reachability });
1464
1486
  return shapeOutcome(settled);
1465
1487
  }
1466
1488
  respond(id, principal, body, httpReq) {
@@ -43,14 +43,14 @@ type _GuardBgNotifReverse = AssertAllKeysHandled<Exclude<BgNotifProjected | BgNo
43
43
  type RosterProjected = "name" | "agentId" | "sessionId" | "toolUseId" | "owner" | "scope" | "sessionScoped" | "rootSessionId" | "model" | "modelFallback" | "createdAt";
44
44
  type _GuardRoster = AssertAllKeysHandled<Exclude<keyof RosterEntry, RosterProjected>>;
45
45
  type _GuardRosterReverse = AssertAllKeysHandled<Exclude<RosterProjected, keyof RosterEntry>>;
46
- type AskProjected = "toolName" | "toolCallId" | "args" | "message" | "sourceTaskId" | "fromSubagent" | "sourceAgentName" | "delegation" | "ruleOffers" | "ruleOffersAbsence" | "persistedRuleShadowed" | "probeCause" | "ruleEvidence" | "requiresRealApproval" | "denialLimitFallback" | "origin" | "ruleStoreUnreadable";
46
+ type AskProjected = "toolName" | "toolCallId" | "args" | "message" | "sourceTaskId" | "fromSubagent" | "sourceAgentName" | "delegation" | "ruleOffers" | "ruleOffersAbsence" | "persistedRuleShadowed" | "probeCause" | "ruleEvidence" | "requiresRealApproval" | "denialLimitFallback" | "origin" | "ruleStoreUnreadable" | "readRootCandidate";
47
47
  type AskExcluded = "preview" | "principal" | "riskAxes" | "boundInputHash" | "isDelegatedChild" | "probeReason" | "hasBidiControls" | "previewWithheld" | "execCwd";
48
48
  type _GuardAsk = AssertAllKeysHandled<Exclude<keyof AskRequest, AskProjected | AskExcluded>>;
49
49
  type _GuardAskReverse = AssertAllKeysHandled<Exclude<AskProjected | AskExcluded, keyof AskRequest>>;
50
50
  type AskFrameServerMinted = "type" | "approvalId" | "argsOmitted" | "outcome" | "governanceForced" | "expiresAtMs" | "expiresInMs" | "serverNowMs" | "parked" | "inputHasBidi";
51
51
  type _GuardAskFrame = AssertAllKeysHandled<Exclude<keyof ToolApprovalFrame, AskProjected | AskFrameServerMinted>>;
52
52
  type _GuardAskFrameReverse = AssertAllKeysHandled<Exclude<AskProjected | AskFrameServerMinted, keyof ToolApprovalFrame>>;
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";
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";
54
54
  type _GuardTaskEvent = AssertAllKeysHandled<Exclude<TaskEvent["type"], TaskEventHandled>>;
55
55
  type _GuardTaskEventReverse = AssertAllKeysHandled<Exclude<TaskEventHandled, TaskEvent["type"]>>;
56
56
  type MailboxProjected = "seq" | "from" | "content" | "sentAt" | "hopChain" | "peerMeta";
@@ -59,7 +59,7 @@ type _GuardMailboxReverse = AssertAllKeysHandled<Exclude<MailboxProjected, keyof
59
59
  type MailboxAppendProjected = "from" | "content" | "sentAt" | "hopChain" | "peerMeta";
60
60
  type _GuardMailboxAppend = AssertAllKeysHandled<Exclude<keyof MailboxAppendMessage, MailboxAppendProjected>>;
61
61
  type _GuardMailboxAppendReverse = AssertAllKeysHandled<Exclude<MailboxAppendProjected, keyof MailboxAppendMessage>>;
62
- type WiringSectionProjected = "schemaVersion" | "leg" | "ask" | "question" | "interaction" | "elicit" | "parkLane" | "session" | "fleet" | "permissionRules" | "modelGate" | "autoMode" | "mcp" | "tools";
62
+ type WiringSectionProjected = "schemaVersion" | "leg" | "ask" | "question" | "interaction" | "elicit" | "parkLane" | "session" | "fleet" | "permissionRules" | "modelGate" | "autoMode" | "mcp" | "tools" | "hooks" | "lsp";
63
63
  type WiringSectionExcluded = "governance" | "configFingerprint";
64
64
  type _GuardWiringSections = AssertAllKeysHandled<Exclude<keyof WiringManifest, WiringSectionProjected | WiringSectionExcluded>>;
65
65
  type _GuardWiringSectionsReverse = AssertAllKeysHandled<Exclude<WiringSectionProjected | WiringSectionExcluded, keyof WiringManifest>>;
@@ -121,11 +121,11 @@ type SummaryProjected = "sessionId" | "scope" | "createdAt" | "gateKind" | "seve
121
121
  type SummaryExcluded = "token" | "toolInput" | "toolName" | "toolCallId" | "preview" | "principal" | "sourceTaskId" | "contentKind" | "restoreMode" | "checkpointId" | "previewWithheld";
122
122
  type _GuardInboxSummary = AssertAllKeysHandled<Exclude<keyof CheckpointSummary, SummaryProjected | SummaryExcluded>>;
123
123
  type _GuardInboxSummaryReverse = AssertAllKeysHandled<Exclude<SummaryProjected | SummaryExcluded, keyof CheckpointSummary>>;
124
- type TaskSpecWired = "objective" | "principal" | "images" | "sessionId" | "requireExistingSession" | "oneShot" | "clientContext" | "resumeAt" | "resumeAtMode" | "model" | "compactionModel" | "thinking" | "systemPrompt" | "appendSystemPrompt" | "promptProvider" | "memory" | "suggestNextPrompts" | "restoreFiles" | "acceptPartialRestore" | "rewindFilesTo" | "tools" | "excludeTools" | "deferTools" | "toolMaterializeStrategy" | "promptProfile" | "toolPolicy" | "onAsk" | "onQuestion" | "hooks" | "durableApproval" | "resourceSuspend" | "resilience" | "finalVerification" | "checkpointStore" | "handsReadOnly" | "memoryPersistenceCapable" | "additionalDirectories" | "additionalReadDirectories" | "enablePlanMode" | "interactiveTools" | "enableFork" | "shellGate" | "mcp" | "a2a" | "skills" | "backgroundScope" | "envFacts" | "limits" | "configOverrides" | "forwardSubagentEvents" | "retainSubagentSessions" | "retainBackgroundProcesses" | "outputSchema" | "outputRetries" | "compaction" | "attachments" | "selfOrchestration" | "getApiKeyAndHeaders" | "interactionPosture" | "agents" | "taskId" | "signal" | "preemptSignal" | "modelRole" | "enableBlockedReport" | "maxSuspends" | "autoModeRequested";
124
+ type TaskSpecWired = "objective" | "principal" | "images" | "sessionId" | "requireExistingSession" | "oneShot" | "clientContext" | "resumeAt" | "resumeAtMode" | "model" | "compactionModel" | "thinking" | "systemPrompt" | "appendSystemPrompt" | "promptProvider" | "memory" | "suggestNextPrompts" | "restoreFiles" | "acceptPartialRestore" | "rewindFilesTo" | "tools" | "excludeTools" | "deferTools" | "toolMaterializeStrategy" | "promptProfile" | "toolPolicy" | "onAsk" | "onQuestion" | "hooks" | "durableApproval" | "resourceSuspend" | "resilience" | "finalVerification" | "checkpointStore" | "handsReadOnly" | "memoryPersistenceCapable" | "additionalDirectories" | "additionalReadDirectories" | "enablePlanMode" | "interactiveTools" | "enableFork" | "shellGate" | "writeFace" | "mcp" | "a2a" | "skills" | "backgroundScope" | "envFacts" | "limits" | "configOverrides" | "forwardSubagentEvents" | "retainSubagentSessions" | "retainBackgroundProcesses" | "outputSchema" | "outputRetries" | "compaction" | "attachments" | "selfOrchestration" | "getApiKeyAndHeaders" | "interactionPosture" | "agents" | "taskId" | "signal" | "preemptSignal" | "modelRole" | "enableBlockedReport" | "maxSuspends" | "autoModeRequested" | "skillListingBudgetFraction" | "skillListingMaxDescChars";
125
125
  type TaskSpecUnwired = "excludeAllTools" | "actor" | "roles" | "lspManager" | "tracer" | "readFace" | "readDenyPatterns" | "interactiveQuestionFallback" | "alwaysLoadTools" | "restoreGatedTools" | "deferSelfResolve" | "basePolicyForResumeEdit" | "lspDiagnostics" | "streamingToolExecution" | "toolResultThresholdChars";
126
126
  type _GuardTaskSpec = AssertAllKeysHandled<Exclude<keyof TaskSpec, TaskSpecWired | TaskSpecUnwired>>;
127
127
  type _GuardTaskSpecReverse = AssertAllKeysHandled<Exclude<TaskSpecWired | TaskSpecUnwired, keyof TaskSpec>>;
128
- type TaskResultForwarded = "taskId" | "runId" | "sessionId" | "terminal" | "model" | "effectiveReasoning" | "result" | "salvagedOutput" | "remoteEnvFailures" | "apiFailure" | "retryAfterMs" | "degraded" | "structuredOutput" | "rewindNotes" | "haltedOnUserRejection" | "haltedByUser" | "strandedHumanAnswers" | "pendingApproval" | "approvalWaitedMs" | "effectiveReadFace" | "effectiveReadDenyPatterns" | "effectiveMemoryScopes" | "stats" | "editedFiles";
128
+ type TaskResultForwarded = "taskId" | "runId" | "sessionId" | "terminal" | "model" | "effectiveReasoning" | "result" | "salvagedOutput" | "remoteEnvFailures" | "apiFailure" | "retryAfterMs" | "degraded" | "structuredOutput" | "rewindNotes" | "haltedOnUserRejection" | "haltedByUser" | "strandedHumanAnswers" | "pendingApproval" | "approvalWaitedMs" | "effectiveReadFace" | "effectiveReadDenyPatterns" | "effectiveWriteFace" | "effectiveMemoryScopes" | "stats" | "editedFiles";
129
129
  type TaskResultStripped = never;
130
130
  type _GuardTaskResult = AssertAllKeysHandled<Exclude<keyof TaskResult, TaskResultForwarded | TaskResultStripped>>;
131
131
  type _GuardTaskResultReverse = AssertAllKeysHandled<Exclude<TaskResultForwarded | TaskResultStripped, keyof TaskResult>>;
@@ -139,7 +139,7 @@ type GateOutcomeProjected = "disposition" | "settlement" | "origin";
139
139
  type _GuardGateOutcome = AssertAllKeysHandled<Exclude<keyof GateOutcome, GateOutcomeProjected>>;
140
140
  type _GuardGateOutcomeReverse = AssertAllKeysHandled<Exclude<GateOutcomeProjected, keyof GateOutcome>>;
141
141
  type GateDispositionKeys = GateDisposition extends infer D ? (D extends object ? keyof D : never) : never;
142
- type GateDispositionProjected = "kind" | "deniedBy" | "cause";
142
+ type GateDispositionProjected = "kind" | "deniedBy" | "cause" | "classifier";
143
143
  type _GuardGateDisposition = AssertAllKeysHandled<Exclude<GateDispositionKeys, GateDispositionProjected>>;
144
144
  type _GuardGateDispositionReverse = AssertAllKeysHandled<Exclude<GateDispositionProjected, GateDispositionKeys>>;
145
145
  type SettlementProjected = "kind" | "who" | "when" | "note";
@@ -148,12 +148,12 @@ type _GuardSettlementReverse = AssertAllKeysHandled<Exclude<SettlementProjected,
148
148
  type SettlementWhoProjected = "party" | "approver" | "window";
149
149
  type _GuardSettlementWho = AssertAllKeysHandled<Exclude<SettlementWhoKeys, SettlementWhoProjected>>;
150
150
  type _GuardSettlementWhoReverse = AssertAllKeysHandled<Exclude<SettlementWhoProjected, SettlementWhoKeys>>;
151
- type WorkflowRunForwarded = "id" | "scope" | "status" | "startedAt" | "endedAt" | "createdAt" | "rev" | "parks" | "name" | "description" | "result" | "error" | "errorCode" | "agentFailures" | "stats" | "phases" | "agents" | "groups";
151
+ type WorkflowRunForwarded = "id" | "scope" | "status" | "startedAt" | "endedAt" | "createdAt" | "rev" | "parks" | "name" | "description" | "result" | "error" | "errorCode" | "agentFailures" | "stats" | "phases" | "agents" | "groups" | "resumeAdmissionIncomplete";
152
152
  type WorkflowRunStripped = "sourceTaskId" | "originatingSessionId" | "effectiveArgs" | "budgetOvershoot" | "timeoutInterruption" | "resultFull" | "completionId" | "resume" | "journalSkips";
153
153
  type _GuardWorkflowRun = AssertAllKeysHandled<Exclude<keyof WorkflowRun, WorkflowRunForwarded | WorkflowRunStripped>>;
154
154
  type _GuardWorkflowRunReverse = AssertAllKeysHandled<Exclude<WorkflowRunForwarded | WorkflowRunStripped, keyof WorkflowRun>>;
155
155
  type ParkRowKeys = keyof NonNullable<WorkflowRun["parks"]>[number];
156
- type ParkRowProjected = "callKey" | "sessionId" | "originRunId";
156
+ type ParkRowProjected = "callKey" | "sessionId" | "originRunId" | "originUnconfirmed";
157
157
  type ParkRowWithheld = "token";
158
158
  type _GuardParkRow = AssertAllKeysHandled<Exclude<ParkRowKeys, ParkRowProjected | ParkRowWithheld>>;
159
159
  type _NoDoubleBookParkRow = AssertAllKeysHandled<Extract<ParkRowProjected, ParkRowWithheld>>;
@@ -35,7 +35,13 @@ export type LedgerEventType = "reasoning" | "text" | "tool_start" | "tool_end" |
35
35
  /** S-212(7.71.0):运行期名册变更(core 7.8.0 [ref] ⑪)。**快照语义**——`delta.roster` 是整只
36
36
  * 变更后名册,消费端收到即整只替换,所以回放不需要任何合并;它的耐久面因此不是 `wiring_manifest.tools`
37
37
  * 的重复,而是那份开腿快照**之后**的每一次改动(修前两条 durable 腿零 case ⇒ 回放只见开头一版)。 */
38
- | "tool_roster_delta" | "human_input" | "task_progress" | "task_notification" | "turn_end"
38
+ | "tool_roster_delta"
39
+ /** [ref](core 7.18.0):本条腿的**延迟工具普查**快照(policy / thresholdPercent? / deferred[] / activated[])。
40
+ * 与 `tool_roster_delta` 同判、同理由——**快照语义**(整只替换,回放零合并),而开腿那一份住在
41
+ * `wiring_manifest` 之后的首帧、**之后每一次激活**只活在本帧上。整帧缺席 = 这条腿什么都没延迟。
42
+ * 🔴 `tool_progress`([ref])**刻意不在本表**:core 的 `tool_progress.ephemeral` 契约逐字「LIVE ONLY …
43
+ * core never persists this frame」,与 `task_progress` / `status` 同一处置(两条 durable 腿零 case)。 */
44
+ | "tool_disclosure" | "human_input" | "task_progress" | "task_notification" | "turn_end"
39
45
  /** park 行名**两个**(`appendParked(kind)` 逐字取自 `result.status`)—— 运行期闭集见
40
46
  * {@link PARK_LEDGER_EVENT_TYPES}(本联合是它的类型面,两者由下方的双向断言锁步)。 */
41
47
  | "suspended" | "needs_review" | "done" | "failed" | "suggestions" | "model_usage" | "prompt_assembled" | "config_assembled" | "file_link"
@@ -1,8 +1,8 @@
1
1
  import { terminalProjection } from "@sema-agent/core";
2
- import { modelTextEventData, toolStartEventData, toolEndEventData, taskProgressEventData, taskNotificationEventData, compactedEventData, diagnosticsEventData, brainStatusEventData, steeringInjectedEventData, compactionOutcomeEventData, workspaceChangedEventData, wiringManifestEventData, toolRosterDeltaEventData, humanInputEventData, turnEndEventData, contextUsageEventData } from "./project.js";
2
+ import { modelTextEventData, toolStartEventData, toolEndEventData, taskProgressEventData, taskNotificationEventData, compactedEventData, diagnosticsEventData, brainStatusEventData, steeringInjectedEventData, compactionOutcomeEventData, workspaceChangedEventData, wiringManifestEventData, toolRosterDeltaEventData, toolDisclosureEventData, humanInputEventData, turnEndEventData, contextUsageEventData } from "./project.js";
3
3
  import { NotifiedKeys, taskNotificationStreamKey } from "../orchestration/workflow-completion-inbox.js";
4
4
  import { isParkLedgerEventType } from "./ledger-events.js";
5
- import { isModelSegmentBoundary } from "./model-segment.js";
5
+ import { isModelSegmentBoundary, reasoningDeltaBytes, reasoningSegmentEventId } from "./model-segment.js";
6
6
  export function createSerialLedgerAppend(appendEvent, startSeq) {
7
7
  let seq = startSeq;
8
8
  let chain = Promise.resolve();
@@ -19,6 +19,7 @@ export function createLedgerSink(opts) {
19
19
  let text = "";
20
20
  let reasoning = "";
21
21
  let textEventId;
22
+ let reasoningEventId;
22
23
  const beat = (kind, statusData) => {
23
24
  try {
24
25
  opts.onActivity?.(kind, statusData);
@@ -34,8 +35,9 @@ export function createLedgerSink(opts) {
34
35
  };
35
36
  const flush = async () => {
36
37
  if (reasoning) {
37
- await append("reasoning", modelTextEventData({ text: reasoning }));
38
+ await append("reasoning", modelTextEventData({ text: reasoning, eventId: reasoningEventId }));
38
39
  reasoning = "";
40
+ reasoningEventId = undefined;
39
41
  }
40
42
  if (text) {
41
43
  await append("text", modelTextEventData({ text, eventId: textEventId }));
@@ -53,10 +55,15 @@ export function createLedgerSink(opts) {
53
55
  textEventId ??= td.eventId;
54
56
  break;
55
57
  }
56
- case "reasoning_delta":
57
- if (opts.persistThinking)
58
- reasoning += ev.delta;
58
+ case "reasoning_delta": {
59
+ const rd = ev;
60
+ const bytes = reasoningDeltaBytes(rd);
61
+ if (opts.persistThinking && bytes !== undefined) {
62
+ reasoning += bytes;
63
+ reasoningEventId ??= reasoningSegmentEventId(rd.eventId);
64
+ }
59
65
  break;
66
+ }
60
67
  case "tool_start":
61
68
  await append("tool_start", toolStartEventData(ev));
62
69
  break;
@@ -97,6 +104,12 @@ export function createLedgerSink(opts) {
97
104
  await append("tool_roster_delta", rosterDelta);
98
105
  break;
99
106
  }
107
+ case "tool_disclosure": {
108
+ const disclosure = toolDisclosureEventData(ev);
109
+ if (disclosure !== undefined)
110
+ await append("tool_disclosure", disclosure);
111
+ break;
112
+ }
100
113
  case "human_input":
101
114
  await append("human_input", humanInputEventData(ev));
102
115
  break;
@@ -1,3 +1,4 @@
1
+ import { type SegmentEndFields } from "./project.js";
1
2
  /**
2
3
  * 本帧是不是模型文本的段界。**四条消费腿共用这一只**:账本投影 switch(`trace/ledger-sink.ts`)、
3
4
  * 顶层 live 流与转发子代腿(`http/routes/tasks.ts`)、子代 tail 面(`fleet/subagent-tail-bus.ts`)。
@@ -5,8 +6,10 @@
5
6
  * (第三方 Runner 塞进来的野帧不该切走宿主的权威段)。
6
7
  */
7
8
  export declare function isModelSegmentBoundary(type: string): boolean;
8
- /** live 面的段末帧(`type` 即事件名;其余键由 `reasoningEndEventData` 白名单铸出)。 */
9
- export type ReasoningEndFrame = Record<string, unknown> & {
9
+ /** live 面的段末帧(`type` 即事件名;其余键由 `reasoningEndEventData` 白名单铸出)。
10
+ * 形是**声明**出来的、不是 `Record<string, unknown>`(S-334 门①):`eventId` 是本帧的续流游标,
11
+ * 型必须说得出口 —— live 腿的 `id:` 行取的正是它。 */
12
+ export type ReasoningEndFrame = SegmentEndFields & {
10
13
  type: "reasoning_end";
11
14
  };
12
15
  /** 登记册**读到的全部字段**,逐个写出来(不是 `Record<string, unknown>`):`TaskEvent` 与转发腿的原始帧
@@ -48,6 +51,33 @@ export interface ReasoningSegments {
48
51
  * 与账本腿 `LedgerSink.onDone → flush()` 同位同义 —— 段界表里没有终局词,终局走这扇门。 */
49
52
  cut(match?: (ident: ReasoningStreamIdent) => boolean): ReasoningEndFrame[];
50
53
  }
54
+ /**
55
+ * 一段推理的**段末事件 id** —— 唯一铸点,live 段末帧与账本 `reasoning` 行共用这一只。
56
+ *
57
+ * 🔴 **为什么段末帧不能沿用任何一块 delta 的 `eventId`**(S-334):SSE 的 `id:` 行是**续流游标**,
58
+ * 「每帧唯一」就是它的定义(消费端据它做**整帧幂等**:见过的 id 整帧丢);而本仓 live 腿的 `id:` 行
59
+ * 恰恰取自载荷的 `eventId`(`http/routes/tasks.ts` 的 `sseData`)。沿用段内某一块的锚 ⇒ 段末帧与那一块
60
+ * delta 顶着同一枚游标,消费端把**权威段**当重放帧丢弃 —— 本帧存在的唯一理由(整段脱敏后的权威副本)
61
+ * 当场结构性失效。「这段是从哪一帧开始攒的」不是游标要回答的问题,而「整段替换」这条消费律本来就
62
+ * 不需要段首锚:重连从**帧**续,不从段续。
63
+ *
64
+ * 形 = 那一枚锚 + 一个派生记号,**确定性**是它的全部要点:live 腿与账本腿各自看着同一条流、在同一个
65
+ * 段界上算出**同一枚**字符串,于是「同一份权威副本」在身份面也成立,而两条腿之间不需要任何传值通道
66
+ * ——bg / resume 两条账本腿上根本没有 live 登记册可问,靠传值就只能做成「detach 车道有、别的腿没有」
67
+ * 的两种账本行形。
68
+ *
69
+ * 输入 = 本段**第一块带锚**的 delta 的 `eventId`(不是「第一块」的:首块无锚不等于整段无锚,三条腿
70
+ * 统一用 `??=` 闩第一枚**有定义**的锚 —— 与 E18 的 `textEventId ??=` 逐字同律)。整段一块带锚的都没有
71
+ * ⇒ 段末 id 缺席(诚实的「无锚」,绝不合成占位 —— 与 `sseData` 的既有纪律同源:不可锚的位置不许
72
+ * 伪装成可锚)。
73
+ */
74
+ export declare function reasoningSegmentEventId(anchor: unknown): string | undefined;
75
+ /** 一块 `reasoning_delta` 对段的**贡献字节** —— 非空串才算。账本腿与三条 live 腿共用这一只:空/坏形
76
+ * 增量一个字节都不贡献,既不开段也不参与闩锚 ⇒ 两面结构上不可能把锚闩在不同的帧上(`reasoning_end`
77
+ * 与账本 `reasoning` 行的正文早就逐字节相等,身份面随 S-334 收进同一条规则)。 */
78
+ export declare function reasoningDeltaBytes(ev: {
79
+ delta?: unknown;
80
+ }): string | undefined;
51
81
  /** 「这条流属于这些子代 id 之一」—— 子代终态收段的匹配器(`task_id` 与 `sessionId` 是同一个子代的两个
52
82
  * id 域,取并集;`undefined` 成员自动忽略)。腿上共用这一只,免得各写一遍 id 域的并集。 */
53
83
  export declare function reasoningStreamOfTask(...ids: ReadonlyArray<string | undefined>): (ident: ReasoningStreamIdent) => boolean;
@@ -2,11 +2,18 @@ import { reasoningEndEventData } from "./project.js";
2
2
  const BOUNDARY = new Set([
3
3
  "tool_start", "tool_end", "status", "context_usage", "compacted", "diagnostics",
4
4
  "steering_injected", "compaction_outcome", "workspace_changed", "wiring_manifest",
5
- "tool_roster_delta", "human_input", "task_notification", "turn_end",
5
+ "tool_roster_delta", "human_input", "task_notification", "turn_end", "tool_disclosure",
6
6
  ]);
7
7
  export function isModelSegmentBoundary(type) {
8
8
  return BOUNDARY.has(type);
9
9
  }
10
+ const REASONING_SEGMENT_ID_MARK = "~reasoning_end";
11
+ export function reasoningSegmentEventId(anchor) {
12
+ return typeof anchor === "string" && anchor.length > 0 ? `${anchor}${REASONING_SEGMENT_ID_MARK}` : undefined;
13
+ }
14
+ export function reasoningDeltaBytes(ev) {
15
+ return typeof ev.delta === "string" && ev.delta !== "" ? ev.delta : undefined;
16
+ }
10
17
  export function reasoningStreamOfTask(...ids) {
11
18
  const set = new Set(ids.filter((v) => typeof v === "string" && v !== ""));
12
19
  return (ident) => (ident.sourceTaskId !== undefined && set.has(ident.sourceTaskId)) || (ident.bgAgentId !== undefined && set.has(ident.bgAgentId));
@@ -25,21 +32,24 @@ export function createReasoningSegments() {
25
32
  if (seg === undefined)
26
33
  return [];
27
34
  open.delete(key);
28
- const data = reasoningEndEventData({ ...seg.ident, eventId: seg.eventId, content: seg.buf });
35
+ const data = reasoningEndEventData({ ...seg.ident, eventId: seg.segmentEventId, content: seg.buf });
29
36
  return data === null ? [] : [{ type: "reasoning_end", ...data }];
30
37
  };
31
38
  return {
32
39
  onEvent: (ev) => {
33
40
  if (ev.type === "reasoning_delta") {
34
- if (typeof ev.delta !== "string" || ev.delta === "")
41
+ const bytes = reasoningDeltaBytes(ev);
42
+ if (bytes === undefined)
35
43
  return [];
36
44
  const ident = identOf(ev);
37
45
  const key = streamKeyOf(ident);
38
46
  const seg = open.get(key);
39
47
  if (seg === undefined)
40
- open.set(key, { ident, eventId: ev.eventId, buf: ev.delta });
41
- else
42
- seg.buf += ev.delta;
48
+ open.set(key, { ident, segmentEventId: reasoningSegmentEventId(ev.eventId), buf: bytes });
49
+ else {
50
+ seg.buf += bytes;
51
+ seg.segmentEventId ??= reasoningSegmentEventId(ev.eventId);
52
+ }
43
53
  return [];
44
54
  }
45
55
  return isModelSegmentBoundary(ev.type ?? "") ? cutKey(streamKeyOf(identOf(ev))) : [];
@@ -192,8 +192,42 @@ export declare function screenedStoredEventData(type: string, data: unknown): un
192
192
  * 此前三处各自逐字透传 —— 同一份文本毫秒后在 `done.result.result` 上已脱,live 面却在凭据生成瞬间明文(B-114)。
193
193
  * `text_delta` 仍逐字:跨 chunk 的凭据无法就地判,流式脱敏是独立设计件(S-270)。
194
194
  * 坏形(content 非串/空串)⇒ null(丢帧,不铸「权威空段」:core 契约明言空段不发本帧,消费端收到空段会清掉已攒 delta)。
195
- * 身份四键零字节变换(live 现状带全四键,消费端可能已依赖)。 */
196
- export declare function textEndEventData(ev: Record<string, unknown>): Record<string, unknown> | null;
195
+ * 身份**四键**随行(live 现状带全四键,消费端可能已依赖);值经 {@link identityKey} —— 非空 string 才上 wire
196
+ * (S-334 起不再逐字透传:坏形身份键会在 live 写口上铸出假游标)。 */
197
+ export declare function textEndEventData(ev: Record<string, unknown>): SegmentEndFields | null;
198
+ /**
199
+ * live 面的**身份四键**(core `TaskEventIdentity` 全集)—— 一个属主,两处共用({@link segmentEndFields}
200
+ * 与 sync 腿白名单 catch-all 的 `ident`;此前是两份手抄)。与 durable 面的 {@link identityFields} 的差别
201
+ * **只剩键集**:那边两键(durable builder 对另两键的既定排除),这边四键(live 现状,消费端已依赖);
202
+ * **值判据是同一条** —— 两只都问 {@link identityKey}(非空 `string` 才上 wire,绝不强转)。
203
+ *
204
+ * 🔴 **型必须说得出口**(S-334):`eventId` 是 live 腿 SSE `id:` 行的**唯一**来源,而 `id:` 行是续流游标
205
+ * ——一个连值的型都说不出的键不许铸成游标。非串/空串 ⇒ 键缺席(与「无锚不发 `id:` 行」同一条纪律:
206
+ * 不可锚的位置绝不伪装成可锚)。转发子代腿的帧是 UNTRUSTED RAW(§E1),这一道同时是它的形判门。
207
+ *
208
+ * 🔴 **`type` 而不是 `interface`**(它与 {@link SegmentEndFields} 两处都是,别改回去):TS 只给**类型别名**
209
+ * 隐式索引签名,interface 没有 ⇒ 写成 interface 的话,每一个把本形交给 `Record<string, unknown>` 形参
210
+ * (tail 总线帧、live 帧写口)的调用点都得手抄一次 `{ ...frame }` 展开。别名让「声明出来的形」原样流经
211
+ * 既有写口,零调用点噪声。
212
+ */
213
+ export type LiveEventIdentity = {
214
+ eventId?: string;
215
+ parentToolCallId?: string;
216
+ sourceTaskId?: string;
217
+ bgAgentId?: string;
218
+ };
219
+ /** 段末帧(`text_end` / `reasoning_end`)的载荷**形**(两只帧一个字节不差 —— 一个 wire 概念一份形,
220
+ * 消费端的读法只学一次;差别只有各自铸点的空段判据)。 */
221
+ export type SegmentEndFields = LiveEventIdentity & {
222
+ content: string;
223
+ };
224
+ /** {@link LiveEventIdentity} 的铸点。[ref] 门①:条件展开的臂逐条是直写字面量(键名对扫描器可见)。 */
225
+ export declare function liveIdentityFields(ev: {
226
+ eventId?: unknown;
227
+ parentToolCallId?: unknown;
228
+ sourceTaskId?: unknown;
229
+ bgAgentId?: unknown;
230
+ }): LiveEventIdentity;
197
231
  /**
198
232
  * `reasoning_end` 段末帧的**唯一**铸点(三条 live 腿共用:top stream / 转发子代腿 / 子代 tail 面)——
199
233
  * `text_end` 的推理面孪生({@link textEndEventData}),形逐字同(共用 {@link segmentEndFields})。
@@ -210,7 +244,7 @@ export declare function textEndEventData(ev: Record<string, unknown>): Record<st
210
244
  * 「整段替换已攒的 delta」—— 发一枚空白权威段 = 让消费端把已渲染的思考清成空白。坏形(`content` 非串)
211
245
  * 同样丢帧,理由与 `text_end` 逐字同源。
212
246
  */
213
- export declare function reasoningEndEventData(ev: Record<string, unknown>): Record<string, unknown> | null;
247
+ export declare function reasoningEndEventData(ev: Record<string, unknown>): SegmentEndFields | null;
214
248
  /** The durable `tool_end` payload (shared by both append sites). E1: the model-facing `output` is UNTRUSTED RAW
215
249
  * from core (file/shell/API bodies) — core only SIZE-bounds it (`truncated`), REDACTION is ours (same contract as
216
250
  * `tool_start.args`); never re-fed to a model. E2: identity. Absent `output` ⇒ the tool produced no content body.
@@ -236,6 +270,63 @@ export declare function toolEndEventData(ev: {
236
270
  eventId?: string;
237
271
  parentToolCallId?: string;
238
272
  }): Record<string, unknown>;
273
+ /**
274
+ * `tool_progress` 的白名单投影(core 7.18.0 [ref])—— 一只**仍在跑**的工具调用的存活 tick。
275
+ *
276
+ * ## 这一帧只上 live,不落账(判据是 core 的契约,不是本仓的偏好)
277
+ * core `@contract tool_progress.ephemeral` 逐字:「LIVE ONLY, like `task_progress`/`status`: core never
278
+ * persists this frame (no session-tree entry, no checkpoint state, no resume replay)」。本仓对
279
+ * `task_progress` / `status` 正是同一处置(两条 durable 腿零 case),本帧照抄。
280
+ * 另一条 core 契约把「不落账」从偏好抬成正确性:`@contract tool_progress.cadence` 逐字「A call that
281
+ * finishes inside one interval emits NO frame at all」⇒ **帧的缺席从来不是证据**;落账会让回放面凭空
282
+ * 多出一份「这只调用跑了多久」的账,而那件事的真源是 `tool_end`(core 明写 `elapsedTimeSeconds`
283
+ * **不等于** `tool_end` 的 duration)。
284
+ *
285
+ * ## 信任划线
286
+ * · `toolCallId` / `toolName` —— 引擎铸的 id 与名册里的工具名(与 `tool_start` 逐字同源)⇒ verbatim。
287
+ * · `elapsedTimeSeconds` —— 引擎铸的整秒,单调、一 call 一个原点 ⇒ 有限数才铸键。
288
+ * · `output` —— 🔴 **UNTRUSTED RAW**,core 逐字「exactly as `tool_end.output`: process output that may
289
+ * carry secrets, paths or PII; core bounds only its SIZE, and a consumer MUST redact before persisting
290
+ * or displaying it」⇒ 与 `tool_end.output` **同一只** `redactDeep`,一个字节的例外都不开。
291
+ * · `totalLines` / `totalBytes` —— 引擎计数;core 的缺席律逐字:三者**同进同退**(在场=「观察到了输出」,
292
+ * 缺席=「一个字节都没观察到」,**从不是**「与上一帧相比没变」)。所以本投影按 `output` 的在场判三者:
293
+ * `output` 读不出 ⇒ 三键一起缺席,不单独留下两个计数(那会把「没输出」谎报成「有输出但读不出」)。
294
+ */
295
+ export declare function toolProgressEventData(ev: {
296
+ toolCallId?: unknown;
297
+ toolName?: unknown;
298
+ elapsedTimeSeconds?: unknown;
299
+ output?: unknown;
300
+ totalLines?: unknown;
301
+ totalBytes?: unknown;
302
+ eventId?: unknown;
303
+ parentToolCallId?: unknown;
304
+ }): Record<string, unknown> | undefined;
305
+ /**
306
+ * `tool_disclosure` 的白名单投影(core 7.18.0 [ref])—— 本条腿的**延迟工具普查**:哪些挂载的工具今天只是
307
+ * 名字占位、模型已经激活了哪些、以及是哪条策略判的。
308
+ *
309
+ * ## 三腿对称(与 `tool_roster_delta` 同判、同理由)
310
+ * 开腿那一刻的快照住在 `wiring_manifest` 之后的**第一帧**,而**之后每一次激活**只活在本帧上。不落账 ⇒
311
+ * 断线重连 / 后台跑完再回来的耐久面永远停在开腿版本,而壳正是据它判「这只工具现在还是不是占位名」。
312
+ * 本帧是**整只快照**语义(`deferred` / `activated` 全量,消费端整只替换),所以回放不需要合并。
313
+ *
314
+ * ## 缺席语义(core 逐字,别读错)
315
+ * · **整帧缺席** = 「这条腿什么都没延迟」,**不是**「这个 build 没有这个面」、也不是「未知」;
316
+ * · `thresholdPercent` 缺席 = `always` / `never` 两档下**根本没查过阈值**,不许读成「取了默认百分比」;
317
+ * · 一条 resume 腿的**首帧** `activated` 可能非空(引擎重播的),**不许**读成「这条腿激活了它们」。
318
+ *
319
+ * 成员全是闭形值(策略闭词 + 数字 + 名册里的工具名)⇒ 零脱敏,与 `tool_roster_delta` 的名册行同待遇。
320
+ * `policy` **不在本仓枚举**(闭集词表属主在 core;抄一份会把 core 加的新词吞成缺席)。
321
+ */
322
+ export declare function toolDisclosureEventData(ev: {
323
+ policy?: unknown;
324
+ thresholdPercent?: unknown;
325
+ deferred?: unknown;
326
+ activated?: unknown;
327
+ eventId?: unknown;
328
+ parentToolCallId?: unknown;
329
+ }): Record<string, unknown> | undefined;
239
330
  /** The `task_progress` payload (a subagent's live progress tick) — EXPLICIT WHITELIST shared by all
240
331
  * three legs (bg runs.ts + resume append + the sync live SSE frame): taskId/parent linkage/token rollup verbatim,
241
332
  * `name` UNTRUSTED (core sanitizes for rendering, does NOT secret-redact — a taskName can be secret-shaped) →
@@ -679,6 +770,7 @@ export declare function contextUsageEventData(ev: {
679
770
  usedTokens?: unknown;
680
771
  windowTokens?: unknown;
681
772
  compactAtTokens?: unknown;
773
+ sections?: unknown;
682
774
  eventId?: unknown;
683
775
  parentToolCallId?: unknown;
684
776
  }): Record<string, unknown>;