@sema-agent/core 7.5.2 → 7.6.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 (138) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/dist/agents/agent-transcript-tool.d.ts +2 -2
  3. package/dist/agents/cascade.d.ts +4 -5
  4. package/dist/agents/cascade.js +12 -10
  5. package/dist/agents/repair-loop.d.ts +7 -5
  6. package/dist/agents/repair-loop.js +13 -15
  7. package/dist/agents/retain-ledger.d.ts +2 -3
  8. package/dist/agents/send-message-tool.d.ts +2 -2
  9. package/dist/agents/session-util.d.ts +2 -2
  10. package/dist/agents/subagent.d.ts +27 -46
  11. package/dist/agents/subagent.js +119 -105
  12. package/dist/agents/suspend-guard.d.ts +31 -19
  13. package/dist/agents/suspend-guard.js +14 -8
  14. package/dist/agents/teacher.d.ts +2 -2
  15. package/dist/agents/teacher.js +9 -9
  16. package/dist/agents/team.d.ts +6 -5
  17. package/dist/agents/team.js +10 -8
  18. package/dist/agents/verify.d.ts +8 -9
  19. package/dist/agents/verify.js +17 -17
  20. package/dist/core/a2a.js +2 -1
  21. package/dist/core/agent-definition.d.ts +172 -0
  22. package/dist/core/agent-definition.js +1 -0
  23. package/dist/core/ask-origin.d.ts +60 -7
  24. package/dist/core/ask-origin.js +26 -1
  25. package/dist/core/checkpoint-store.d.ts +78 -76
  26. package/dist/core/checkpoint-store.js +17 -1
  27. package/dist/core/delegation-frames.d.ts +298 -0
  28. package/dist/core/delegation-frames.js +21 -0
  29. package/dist/core/engine-notice.d.ts +555 -0
  30. package/dist/core/engine-notice.js +55 -0
  31. package/dist/core/gate-fold.d.ts +12 -0
  32. package/dist/core/gate-fold.js +158 -0
  33. package/dist/core/gate-lanes.d.ts +93 -0
  34. package/dist/core/gate-lanes.js +626 -0
  35. package/dist/core/gate-outcome.d.ts +189 -0
  36. package/dist/core/gate-outcome.js +70 -0
  37. package/dist/core/hands-band.d.ts +134 -0
  38. package/dist/core/hands-band.js +1 -0
  39. package/dist/core/hooks.d.ts +22 -177
  40. package/dist/core/hooks.js +53 -851
  41. package/dist/core/mcp-failure.d.ts +142 -0
  42. package/dist/core/mcp-failure.js +145 -0
  43. package/dist/core/mcp-server-spec.d.ts +217 -0
  44. package/dist/core/mcp-server-spec.js +1 -0
  45. package/dist/core/mcp.d.ts +21 -77
  46. package/dist/core/mcp.js +76 -150
  47. package/dist/core/model-seat.d.ts +99 -0
  48. package/dist/core/model-seat.js +1 -0
  49. package/dist/core/pause-registry.d.ts +131 -0
  50. package/dist/core/pause-registry.js +27 -0
  51. package/dist/core/reminder-mint.d.ts +10 -0
  52. package/dist/core/reminder-mint.js +3 -0
  53. package/dist/core/runner/assemble-result.d.ts +32 -41
  54. package/dist/core/runner/assemble-result.js +55 -74
  55. package/dist/core/runner/contracts.d.ts +427 -69
  56. package/dist/core/runner/denial-limit-arms.d.ts +1 -1
  57. package/dist/core/runner/denial-limit-arms.js +3 -3
  58. package/dist/core/runner/gate-exit.d.ts +242 -0
  59. package/dist/core/runner/gate-exit.js +124 -0
  60. package/dist/core/runner/park-commit.d.ts +17 -23
  61. package/dist/core/runner/park-commit.js +14 -15
  62. package/dist/core/runner/prepare-ask-lane.d.ts +0 -3
  63. package/dist/core/runner/prepare-ask-lane.js +3 -5
  64. package/dist/core/runner/prepare-boundary-parks.d.ts +3 -6
  65. package/dist/core/runner/prepare-boundary-parks.js +3 -3
  66. package/dist/core/runner/prepare-caps-and-workflow.d.ts +2 -7
  67. package/dist/core/runner/prepare-caps-and-workflow.js +1 -1
  68. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -7
  69. package/dist/core/runner/prepare-gate-stations.d.ts +4 -7
  70. package/dist/core/runner/prepare-gate-stations.js +29 -54
  71. package/dist/core/runner/prepare-inherited-gate.js +1 -1
  72. package/dist/core/runner/prepare-memory.d.ts +44 -26
  73. package/dist/core/runner/prepare-park-ask.d.ts +2 -4
  74. package/dist/core/runner/prepare-park-ask.js +5 -5
  75. package/dist/core/runner/prepare-task.d.ts +2 -2
  76. package/dist/core/runner/prepare-task.js +8 -9
  77. package/dist/core/runner/prepare-wiring-manifest.d.ts +7 -15
  78. package/dist/core/runner/prepare-wiring-manifest.js +9 -10
  79. package/dist/core/runner/runtask.d.ts +20 -102
  80. package/dist/core/runner/runtask.js +119 -121
  81. package/dist/core/runner/terminal-projection.d.ts +22 -0
  82. package/dist/core/runner/terminal-projection.js +28 -0
  83. package/dist/core/runner-deps.d.ts +1416 -0
  84. package/dist/core/runner-deps.js +1 -0
  85. package/dist/core/runtime-caps.d.ts +164 -0
  86. package/dist/core/runtime-caps.js +1 -0
  87. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +4 -1
  88. package/dist/core/store-contracts/checkpoint-store-contract.js +8 -2
  89. package/dist/core/task-event.d.ts +910 -0
  90. package/dist/core/task-event.js +1 -0
  91. package/dist/core/task-limits.d.ts +110 -0
  92. package/dist/core/task-limits.js +1 -0
  93. package/dist/core/task-result.d.ts +809 -0
  94. package/dist/core/task-result.js +1 -0
  95. package/dist/core/task-spec.d.ts +1370 -0
  96. package/dist/core/task-spec.js +1 -0
  97. package/dist/core/task-stream.d.ts +382 -0
  98. package/dist/core/task-stream.js +1 -0
  99. package/dist/core/terminal-cause.d.ts +137 -0
  100. package/dist/core/terminal-cause.js +9 -0
  101. package/dist/core/tool-policy.d.ts +43 -139
  102. package/dist/core/tool-policy.js +79 -112
  103. package/dist/core/tool-spec.d.ts +1174 -0
  104. package/dist/core/tool-spec.js +1 -0
  105. package/dist/core/types.d.ts +27 -7789
  106. package/dist/core/types.js +2 -76
  107. package/dist/core/warm-resume.d.ts +2 -2
  108. package/dist/core/wiring-manifest.d.ts +6 -3
  109. package/dist/core/workflow-journal-store.js +3 -4
  110. package/dist/engine/harness/agent-harness.d.ts +1 -1
  111. package/dist/index.d.ts +12 -8
  112. package/dist/index.js +9 -6
  113. package/dist/orchestration/builtin-workflows.d.ts +2 -2
  114. package/dist/orchestration/builtin-workflows.js +1 -1
  115. package/dist/orchestration/goal.d.ts +2 -2
  116. package/dist/orchestration/goal.js +8 -7
  117. package/dist/orchestration/run-spec.d.ts +2 -2
  118. package/dist/orchestration/run-spec.js +5 -3
  119. package/dist/orchestration/run-workflow-tool.d.ts +4 -4
  120. package/dist/orchestration/run-workflow-tool.js +4 -4
  121. package/dist/orchestration/workflow-governance.d.ts +4 -4
  122. package/dist/orchestration/workflow-governance.js +4 -2
  123. package/dist/orchestration/workflow-primitives.d.ts +1 -1
  124. package/dist/orchestration/workflow-primitives.js +1 -1
  125. package/dist/orchestration/workflow.d.ts +15 -4
  126. package/dist/orchestration/workflow.js +64 -39
  127. package/dist/prompts/supervisor.d.ts +1 -1
  128. package/dist/prompts/supervisor.js +3 -3
  129. package/dist/scenarios/scenario-registry.d.ts +3 -3
  130. package/dist/scenarios/scenario-registry.js +1 -1
  131. package/dist/scenarios/teacher-quickstart.d.ts +2 -2
  132. package/dist/server/http.d.ts +2 -2
  133. package/dist/stores/file/fs-atomic.d.ts +88 -12
  134. package/dist/stores/file/fs-atomic.js +184 -55
  135. package/dist/stores/file/index.d.ts +1 -0
  136. package/dist/stores/file/index.js +1 -0
  137. package/package.json +3 -1
  138. package/test/export-surface.snapshot.json +82 -22
@@ -1,3 +1,5 @@
1
+ import type { AskOrigin } from "./ask-origin.js";
2
+ import type { Settlement } from "./gate-outcome.js";
1
3
  /** A tool call presented to a policy before it executes. */
2
4
  export interface ToolCallRequest {
3
5
  toolName: string;
@@ -80,55 +82,17 @@ export interface ToolCallRequest {
80
82
  * spelling this word is minted from). */
81
83
  declare const DECISION_REASONS: readonly ["rule", "mode", "hook", "safety", "classifier", "persisted_rule", "sandbox", "org_rule", "org_unavailable"];
82
84
  export type DecisionReason = (typeof DECISION_REASONS)[number];
83
- /**
84
- * WHO (or what) ENDED an approval the machine-readable twin of a settlement's human-readable text,
85
- * so a consumer tells "a person decided this" from "nobody answered" without prose-matching a sentence.
86
- * The sibling axis of {@link DecisionReason}, which says which LAYER produced a verdict; this one says
87
- * what ended the WAIT.
88
- *
89
- * - `"human"` — a person, or the approver acting for one, returned a final verdict (allow or deny).
90
- * - `"timeout"` — an approval window elapsed with no answer.
91
- * - `"aborted"` — every other NON-HUMAN end: the task aborted, the approver threw or reported nobody
92
- * reachable, the decision arrived out of contract, a store or transport gave way, retries ran out.
93
- *
94
- * **Which windows `"timeout"` speaks for** (#114①, 2026-08-09 — the promise this note used to make was
95
- * wider than the code): the engine stamps it at the waits IT owns — `createApprovalPolicy`'s
96
- * `approvalTimeoutMs` window, the durable park's TTL, and (#548) the denial-limit fallback ask's
97
- * auto-deny window. The SYNCHRONOUS `onAsk` leg is otherwise not one of them: there the deployment owns
98
- * the window (the engine starts no timer for a callback it does not schedule), so an unanswered card and
99
- * a refused one arrive as the same `false` and the engine records
100
- * `"human"` rather than inventing a cause it did not observe. A host that DOES time its own card out
101
- * can say so — {@link AskOutcome}'s object arm carries an optional `settledBy` for exactly this — but a
102
- * host that does not is indistinguishable, by construction. Read an absent `"timeout"` as "no window
103
- * the engine owns elapsed", never as "nobody's window elapsed".
104
- *
105
- * **The one `onAsk` exception** (#548): a classifier DENIAL-LIMIT fallback ask — the ask that carries
106
- * `denialLimitFallback`, minted when the auto-mode classifier reaches its consecutive/total bound —
107
- * IS timed by the engine over the synchronous leg, because that ask exists to bound a classifier that
108
- * would otherwise deny without end, and an unbounded wait would only move the "without end" onto the
109
- * person. Its window elapsing produces an engine-stamped `settledBy: "timeout"` with
110
- * `resolution: "window_expired"` and `autoDenied: true` on the deny — that last bit is the
111
- * discriminator between core's window and a host self-report ({@link AskOutcome}'s object arm has no
112
- * `autoDenied` seat, so a host cannot claim the word).
113
- * `autoDenyAfterMs: 0` (or an ask with no fallback member) arms nothing, which is every other ask.
114
- *
115
- * The three words are exhaustive and mutually exclusive over the ways an approval can end, and the
116
- * minimum discrimination a consumer needs — someone refused vs nobody answered — is `"human"` vs the
117
- * other two.
118
- *
119
- * **Fill it AT the settlement site.** Each site knows its own cause and names it; deriving the value
120
- * afterwards from whatever outcome happens to be at hand is exactly how a window that elapsed comes to
121
- * be reported as a person's refusal.
122
- *
123
- * ABSENT means this settlement named no source: an older caller that predates the field, or a verdict
124
- * that settled no wait at all (a policy POSTURE — headless auto-deny, a blanket circumvention — where nobody
125
- * was ever asked). A consumer MUST NOT read a semantic out of the absence; render the text instead.
126
- */
127
- export type ApprovalSettledBy = "human" | "timeout" | "aborted";
128
- /** The closed set above, for runtime domain checks at the seams that accept a caller-supplied value. */
129
- export declare const APPROVAL_SETTLED_BY_VALUES: readonly ApprovalSettledBy[];
130
- /** True iff `v` is one of the three {@link ApprovalSettledBy} words. */
131
- export declare function isApprovalSettledBy(v: unknown): v is ApprovalSettledBy;
85
+ /** Read the engine-attested settlement off a funneled decision FOR the named call (the gate's exit is the
86
+ * one consumer): an attestation bound to a different call is a replayed object and answers absence.
87
+ * Exported for the gate module only deliberately NOT re-exported from `src/index.ts` (an internal seam
88
+ * between engine modules, not a facility deployments call). */
89
+ export declare function engineSettlementOf(d: unknown, call: {
90
+ toolCallId: string;
91
+ toolName: string;
92
+ }): {
93
+ settlement: Settlement;
94
+ origin: AskOrigin;
95
+ } | undefined;
132
96
  /**
133
97
  * design/252 G-7 — how long an approver-attribution identifier may be.
134
98
  *
@@ -176,10 +140,10 @@ export declare function screenApproverAttribution(v: unknown): {
176
140
  * - `deny` blocks the call.
177
141
  * Human-readable text is `message`; read it via {@link decisionText}.
178
142
  *
179
- * The two TERMINAL arms may also carry {@link ApprovalSettledBy} as `settledBy` what ended the wait,
180
- * when this verdict ended one. It is on `allow`/`deny` and deliberately NOT on `ask`: an `ask` has
181
- * settled nothing yet, so a source there would name a decider who has not decided. A layer that never
182
- * waited for anyone omits it (see the type's ABSENT clause).
143
+ * NO arm carries a settlement: what ended a wait is not a policy's to state. The engine's own settlement
144
+ * sites attest it through a module-private seat ({@link engineSettlementOf}) and the gate's exit mints the
145
+ * one settlement record ({@link import("./gate-outcome.js").GateOutcome}); a policy that puts a `settledBy`
146
+ * or `approver` member on its verdict is putting an unread property on it.
183
147
  * RB-479-B① (ruled 2026-08-02): the legacy `reason` field is REMOVED — one name for one thing.
184
148
  *
185
149
  * How far the TYPE carries that retirement (measured 2026-08-03, correcting this note's earlier claim
@@ -200,8 +164,6 @@ export type PermissionResult = {
200
164
  updatedInput?: unknown;
201
165
  message?: string;
202
166
  decisionReason?: DecisionReason;
203
- settledBy?: Extract<ApprovalSettledBy, "human">;
204
- approver?: string;
205
167
  } | {
206
168
  action: "ask";
207
169
  updatedInput?: unknown;
@@ -297,8 +259,6 @@ export type PermissionResult = {
297
259
  updatedInput?: unknown;
298
260
  message?: string;
299
261
  decisionReason?: DecisionReason;
300
- settledBy?: ApprovalSettledBy;
301
- approver?: string;
302
262
  };
303
263
  /**
304
264
  * design/252 G-2 — WHY a piece of rule-provenance evidence is not on an ask.
@@ -1204,7 +1164,7 @@ export interface AskRequest {
1204
1164
  * {@link PermissionResult} ask-arm member of the same name): the counts that tripped the bound and
1205
1165
  * this ask's own auto-deny window. Two readers: a card renders it as a countdown; {@link resolveAsk}
1206
1166
  * arms its deadline from `autoDenyAfterMs` (> 0 ⇒ an unanswered function approver auto-denies at
1207
- * that deadline — `settledBy:"timeout"`, `resolution:"window_expired"`, `autoDenied:true`). Filled
1167
+ * that deadline — the `denial_limit_window_expired` settlement on the gate record). Filled
1208
1168
  * by the gate from the decision, never a caller/worker-settable field. This is the ARMED type: the
1209
1169
  * decision's member carries the counts alone, and the only two ways to reach this one are the route
1210
1170
  * stations — `AutoModeDenialTracker.armTimedWindow` (a hand-out to a live function approver, the one
@@ -1349,9 +1309,8 @@ export type OnAsk = "deny" | "allow" | ((req: AskRequest, signal?: AbortSignal)
1349
1309
  * the fallback exists to bound a classifier that would otherwise deny without end. When it elapses
1350
1310
  * the approver's promise is DETACHED (design/384: the wait is released, not cancelled — an approver
1351
1311
  * that answers afterwards is not consulted, and an `allow` it returns late becomes the
1352
- * `task.late_approval` notice), and the engine's own deny carries `settledBy: "timeout"`,
1353
- * `resolution: "window_expired"` and `autoDenied: true`. See {@link ApprovalSettledBy} for how a
1354
- * consumer tells that window from the host's.
1312
+ * `task.late_approval` notice), and the engine's own deny settles as `denial_limit_window_expired`
1313
+ * (the host's own elapsed window settles as `approval_window_expired` with `who.party: "host"`).
1355
1314
  *
1356
1315
  * `reason` — the SYNCHRONOUS leg's seat for a model-readable reason attached to a deny, the exact
1357
1316
  * counterpart of the durable leg's `ResumeOutcome` `policy_ask` `reason` ("Model-readable reason
@@ -1387,7 +1346,7 @@ export type OnAsk = "deny" | "allow" | ((req: AskRequest, signal?: AbortSignal)
1387
1346
  export type AskOutcome = boolean | "unavailable" | {
1388
1347
  allow: boolean;
1389
1348
  updatedInput?: unknown;
1390
- settledBy?: Extract<ApprovalSettledBy, "human" | "timeout">;
1349
+ settledBy?: "human" | "timeout";
1391
1350
  reason?: string;
1392
1351
  approver?: string;
1393
1352
  };
@@ -1473,90 +1432,35 @@ export declare function tryCloneArgs<T>(v: T): {
1473
1432
  * text they let through. Not part of the package's public surface.
1474
1433
  */
1475
1434
  export declare function describeThrown(err: unknown): string;
1476
- /**
1477
- * The deny-arm classification a {@link resolveAsk} refusal carries — MINTED at the composing arm
1478
- * (the minter reports the fact; no consumer re-derives it from message text, which is exactly the
1479
- * inference this closed set exists to end). One word per family of arms:
1480
- * - `"human_refused"` — a person answered no (the boolean false fold and the object arm's
1481
- * allow-false, noted or bare — the note fact rides {@link ResolvedAsk.humanRefusalNote});
1482
- * - `"window_expired"` — the approver's own window elapsed (the timeout-settled deny);
1483
- * - `"no_approver"` — headless auto-deny (no approver wired, or the deny posture string);
1484
- * - `"blanket_allow_refused"` — a blanket allow posture met a `requiresRealApproval` ask;
1485
- * - `"approver_unavailable"` — the approver answered the ROUTING question "nobody reachable"
1486
- * (the G1 marker's fail-closed carry — the gate may re-route it to a durable park instead);
1487
- * - `"task_aborted"` — the wait's abort signal ended it (pre-wait, mid-wait and race arms). The
1488
- * signal is the run's own end AND, since design/384, any turn-level interrupt composed into the
1489
- * wait (a bare user halt, a steer-now boundary cut): one abort family, one word — a consumer
1490
- * that must tell the sources apart reads the run's own terminal facts, not this classification;
1491
- * - `"presentation_failed"` — the args/edit could not be safely presented or adopted (unclonable);
1492
- * - `"approver_error"` — the approver callback threw;
1493
- * - `"approver_contract"` — the approver returned something outside the contract (non-boolean
1494
- * allow, out-of-vocabulary settlement word, unreadable members, a timeout-settled allow, a
1495
- * non-string or unreadable reason, an out-of-contract truthy, a refused attribution).
1496
- */
1497
- export type AskDenyResolution = "human_refused" | "window_expired" | "no_approver" | "blanket_allow_refused" | "approver_unavailable" | "task_aborted" | "presentation_failed" | "approver_error" | "approver_contract";
1498
- /** The closed set above, for runtime domain checks at the seams that accept a caller-supplied value
1499
- * (the `APPROVAL_SETTLED_BY_VALUES` precedent: the word crosses process boundaries on `tool_end`,
1500
- * so a consumer enumerating or validating it must not hand-roll the vocabulary). */
1501
- export declare const ASK_DENY_RESOLUTION_VALUES: readonly AskDenyResolution[];
1502
- /** Closed-vocabulary guard for {@link AskDenyResolution} — the screen every carrier runs before it
1503
- * files or forwards the word (a policy layer could self-declare the member on its own deny; an
1504
- * out-of-vocabulary word is dropped by the carriers, never coerced or forwarded). */
1505
- export declare function isAskDenyResolution(v: unknown): v is AskDenyResolution;
1506
- /** #548: the engine-attested auto-deny marker off a funneled decision, bound to the named call like
1507
- * {@link coreMintedResolutionOf} (absent ⇒ not an attested auto-deny of THIS call). */
1508
- export declare function coreMintedAutoDeniedOf(d: unknown, call: {
1509
- toolCallId: string;
1510
- toolName: string;
1511
- }): boolean;
1512
- /** Read the engine-attested resolution off a funneled decision (the gate's single deny exit is the
1513
- * one consumer), FOR the named call: an attestation bound to a different toolCallId/toolName is a
1514
- * replayed object, not this call's settlement — the reader answers absence (the safe direction; the
1515
- * public `settledBy`/message on such an object were always the policy's own to state). A present
1516
- * word is an engine settlement site's own attestation for THIS object and THIS call — no foreign
1517
- * policy can reach the sidecar. The vocabulary screen is a belt (the typed stamp is the only
1518
- * writer). Exported for the gate module only — deliberately NOT re-exported from `src/index.ts`
1519
- * (the {@link refuseOutOfContractDecision} precedent: an internal seam between engine modules, not
1520
- * a facility deployments call). */
1521
- export declare function coreMintedResolutionOf(d: unknown, call: {
1522
- toolCallId: string;
1523
- toolName: string;
1524
- }): AskDenyResolution | undefined;
1525
1435
  /**
1526
1436
  * A {@link resolveAsk} result: always a TERMINAL `allow`/`deny` (never `ask`). `approverUnavailable`
1527
1437
  * is the out-of-band G1 three-value marker: the live approver returned `"unavailable"` for this ask —
1528
1438
  * the carried `deny` is the FAIL-CLOSED FALLBACK, and the gate may instead re-route the ask onto the
1529
1439
  * durable park leg (the only consumer; everywhere else the result reads as a plain deny).
1530
1440
  */
1531
- export type ResolvedAsk = PermissionResult & {
1532
- approverUnavailable?: true;
1533
- /** The EXACT data snapshot the approver was shown (the `structuredClone` of the
1534
- * presented args). On a plain approval (no edit) the gate EXECUTES this snapshot, not the original
1535
- * object: a stateful getter or an external alias must not be able to make the executed action
1536
- * differ from the approved one (shown == executed, by construction). Set only on the
1537
- * function-approver path (string modes present nothing). */
1441
+ export type ResolvedAsk = (Extract<PermissionResult, {
1442
+ action: "allow";
1443
+ }> & {
1444
+ /** Present exactly when a PERSON approved (`human_allowed`, with the channel's attribution when it
1445
+ * reported one); absent on the posture allows (a blanket `"allow"`, a reused grant) nobody was
1446
+ * asked, so nothing was settled. */
1447
+ settlement?: Settlement;
1448
+ /** The EXACT data snapshot the approver was shown (the `structuredClone` of the presented args). On
1449
+ * a plain approval (no edit) the gate EXECUTES this snapshot, not the original object: a stateful
1450
+ * getter or an external alias must not be able to make the executed action differ from the
1451
+ * approved one (shown == executed, by construction). Set only on the function-approver path
1452
+ * (string modes present nothing). */
1538
1453
  presentedInput?: unknown;
1539
- /** Present exactly when this deny is a PERSON's refusal (`settledBy: "human"`) that carried the
1540
- * decider's own note (the object arm's `reason`, screened and non-empty). Its ABSENCE on a human
1541
- * deny is the structural fact that the refusal was BARE — a "no" with no direction attached —
1542
- * which is the arm the runner treats as a control-flow boundary for the issuing batch (a bare
1543
- * "no" on the parent thread halts the remaining same-message tool calls; a refusal WITH a note
1544
- * gives the model direction to adapt to, so the turn continues). Never derived from message
1545
- * text; stamped only at the composing arm. Not stamped on the timeout deny (nobody answered)
1546
- * or on any engine-produced fail-closed refusal. */
1547
- humanRefusalNote?: true;
1548
- /** #548 — present exactly when this deny is the classifier denial-limit fallback's AUTO-DENY: the
1549
- * ask's own window (`AskRequest.denialLimitFallback.autoDenyAfterMs`, CC `AKe`) elapsed with no
1550
- * answer. Rides beside `settledBy:"timeout"` / `resolution:"window_expired"` (the established approval
1551
- * factory's deadline arm speaks the same two words, so a consumer classifying on them needs no new
1552
- * branch) and says WHOSE window it was: core's, not the host's. Stamped only at the composing arm. */
1553
- autoDenied?: true;
1554
- /** The deny-arm classification (see {@link AskDenyResolution}) — present on every deny this
1555
- * resolver composes, absent on every allow. Carried by the gate to its block exit, the
1556
- * permission-denied observer payload and the settlement sideband (thence the call's `tool_end`
1557
- * frame), so a consumer classifies a refusal by code instead of parsing its text. */
1558
- resolution?: AskDenyResolution;
1559
- };
1454
+ approverUnavailable?: never;
1455
+ }) | (Extract<PermissionResult, {
1456
+ action: "deny";
1457
+ }> & {
1458
+ /** What ended the wait composed at the arm that ended it, one of the refusal kinds. A deny this
1459
+ * resolver composes ALWAYS names its settlement: there is no unclassified refusal. */
1460
+ settlement: Settlement;
1461
+ presentedInput?: unknown;
1462
+ approverUnavailable?: true;
1463
+ });
1560
1464
  /**
1561
1465
  * Does any string reachable in `value` carry a {@link BIDI_CONTROL_RE} member? Bounded, cycle-safe,
1562
1466
  * and never throwing — every caller is on an approval/projection path, where a scan that failed must