@sema-agent/core 7.13.0 → 7.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +80 -0
- package/dist/agents/subagent.d.ts +4 -9
- package/dist/agents/subagent.js +16 -12
- package/dist/agents/teacher.js +1 -1
- package/dist/brain/reasoning.d.ts +23 -0
- package/dist/brain/reasoning.js +35 -4
- package/dist/brain/stream-engine.js +35 -17
- package/dist/brain/timeout.d.ts +25 -4
- package/dist/brain/timeout.js +1 -1
- package/dist/core/ask-origin.d.ts +28 -9
- package/dist/core/ask-origin.js +10 -5
- package/dist/core/auto-mode.d.ts +3 -3
- package/dist/core/checkpoint-seat.d.ts +18 -0
- package/dist/core/checkpoint-seat.js +6 -0
- package/dist/core/checkpoint-store.d.ts +9 -16
- package/dist/core/checkpoint-store.js +7 -4
- package/dist/core/engine-notice.d.ts +3 -1
- package/dist/core/env-knob-announce.d.ts +16 -0
- package/dist/core/env-knob-announce.js +14 -0
- package/dist/core/gate-fold.js +2 -0
- package/dist/core/gate-lanes.js +21 -12
- package/dist/core/gate-outcome.d.ts +42 -3
- package/dist/core/gate-outcome.js +22 -0
- package/dist/core/governance-codes.js +1 -1
- package/dist/core/hooks.d.ts +5 -16
- package/dist/core/hooks.js +6 -4
- package/dist/core/mcp.d.ts +3 -2
- package/dist/core/mcp.js +5 -11
- package/dist/core/memory-engine/engine.d.ts +2 -2
- package/dist/core/runner/advertised-writable-dirs.d.ts +74 -0
- package/dist/core/runner/advertised-writable-dirs.js +48 -0
- package/dist/core/runner/assemble-result.d.ts +5 -0
- package/dist/core/runner/denial-limit-arms.d.ts +7 -9
- package/dist/core/runner/denial-limit-arms.js +8 -10
- package/dist/core/runner/gate-exit.d.ts +15 -3
- package/dist/core/runner/gate-exit.js +6 -4
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +34 -4
- package/dist/core/runner/prepare-caps-and-workflow.js +47 -12
- package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +10 -4
- package/dist/core/runner/prepare-hands-readface.js +5 -14
- package/dist/core/runner/prepare-inherited-gate.d.ts +5 -3
- package/dist/core/runner/prepare-inherited-gate.js +1 -1
- package/dist/core/runner/prepare-memory.d.ts +31 -34
- package/dist/core/runner/prepare-memory.js +73 -51
- package/dist/core/runner/prepare-policy-chain.js +5 -2
- package/dist/core/runner/prepare-prompt-inputs.d.ts +4 -0
- package/dist/core/runner/prepare-prompt-inputs.js +2 -2
- package/dist/core/runner/prepare-question-face.d.ts +10 -8
- package/dist/core/runner/prepare-question-face.js +1 -3
- package/dist/core/runner/prepare-safety-scan.js +1 -1
- package/dist/core/runner/prepare-task.js +57 -48
- package/dist/core/runner/prepare-wiring-manifest.d.ts +2 -2
- package/dist/core/runner/prepare-wiring-manifest.js +1 -1
- package/dist/core/runner/run-compaction-machinery.js +2 -0
- package/dist/core/runner/run-harness-handlers.js +3 -1
- package/dist/core/runner/stream-settle-backstop.js +1 -1
- package/dist/core/runtime-caps.d.ts +21 -0
- package/dist/core/runtime-caps.js +5 -1
- package/dist/core/task-event.d.ts +11 -2
- package/dist/core/task-registry-shared.js +8 -6
- package/dist/core/task-result.d.ts +15 -0
- package/dist/core/terminal-cause.d.ts +6 -2
- package/dist/core/tool-policy.d.ts +34 -28
- package/dist/core/tool-policy.js +29 -5
- package/dist/core/tool-roster.js +2 -0
- package/dist/core/tool-spec.d.ts +13 -12
- package/dist/core/types.d.ts +2 -1
- package/dist/core/types.js +1 -0
- package/dist/core/wiring-manifest.d.ts +16 -9
- package/dist/core/wiring-manifest.js +8 -3
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -3
- package/dist/orchestration/run-workflow-tool.d.ts +8 -8
- package/dist/orchestration/run-workflow-tool.js +1 -1
- package/dist/orchestration/workflow-primitives.d.ts +4 -3
- package/dist/orchestration/workflow-primitives.js +3 -3
- package/dist/orchestration/workflow-types.d.ts +14 -0
- package/dist/orchestration/workflow.d.ts +41 -4
- package/dist/orchestration/workflow.js +23 -5
- package/dist/tools/fs/fs-shared.js +9 -3
- package/dist/tools/fs/read-deny.d.ts +24 -8
- package/dist/tools/fs/read-deny.js +20 -1
- package/package.json +2 -1
- package/test/export-surface.snapshot.json +25 -1
|
@@ -33,9 +33,10 @@ import type { PermissionResult } from "./tool-policy.js";
|
|
|
33
33
|
*
|
|
34
34
|
* - `content_question` — the reserved question tool: a content-ROUTING signal, not a permission
|
|
35
35
|
* question; it leaves the gate through the content channel, never through a permission decider.
|
|
36
|
-
* - `
|
|
36
|
+
* - `ancestor_marked` — the call is MARKED by an ancestor (an inherited approver-unavailable float, or
|
|
37
37
|
* a durable mandate floated down because this task can park it): it must reach the park with no
|
|
38
|
-
* synchronous decision-maker in between.
|
|
38
|
+
* synchronous decision-maker in between. The word names WHO raised it (an ancestor's mark), like every
|
|
39
|
+
* other member; whether the ask can be resolved is the park's business, not the origin's.
|
|
39
40
|
* - `org_unavailable` — the deployment is org-governed and could not read its snapshot: the fail-closed
|
|
40
41
|
* tighten, cleared by a person only ("does the org forbid this?" is unanswered, and no automatic
|
|
41
42
|
* lane may answer it).
|
|
@@ -69,7 +70,7 @@ import type { PermissionResult } from "./tool-policy.js";
|
|
|
69
70
|
* observer or an approval card can say WHICH engine layer raised the question, which one word
|
|
70
71
|
* could not.
|
|
71
72
|
*/
|
|
72
|
-
export declare const ASK_ORIGINS: readonly ["content_question", "
|
|
73
|
+
export declare const ASK_ORIGINS: readonly ["content_question", "ancestor_marked", "org_unavailable", "org_rule", "rule_store_unavailable", "hook", "ask_rule", "denial_limit_fallback", "shell_gate_tighten", "safety_tighten", "policy"];
|
|
73
74
|
export type AskOrigin = (typeof ASK_ORIGINS)[number];
|
|
74
75
|
/** Whether a value is a member of the closed origin set. Exported because the word crosses process
|
|
75
76
|
* boundaries: a host validating one it received must not hand-roll the set. */
|
|
@@ -83,6 +84,23 @@ export declare function isAskOrigin(v: unknown): v is AskOrigin;
|
|
|
83
84
|
* other direction (a row for a word that is not in the set).
|
|
84
85
|
*/
|
|
85
86
|
export type AssertAllKeysHandled<T extends never> = T;
|
|
87
|
+
/**
|
|
88
|
+
* WHICH mechanism left the persisted-rule lane unable to enforce the person's deny/ask rows for a call —
|
|
89
|
+
* the two-word set behind the one origin word `rule_store_unavailable` (the AUTHORITY semantics are
|
|
90
|
+
* identical; the mechanism differs, and a consumer that renders "the store is down" for a call the lexer
|
|
91
|
+
* could not read is telling the person to fix the wrong thing):
|
|
92
|
+
* - `store` — the wired store could not be READ for this call (a read failure, a timeout, a thrown adapter);
|
|
93
|
+
* - `call` — the store was read, but the CALL could not be read against the person's rows (the
|
|
94
|
+
* tightening lexer's `unreadable` word: an expansion where a rule reads a word, an unterminated quote,
|
|
95
|
+
* a syntax error — the ask's message carries the lexer's own sentence).
|
|
96
|
+
* The gate reads the lane's answer ONCE into {@link AskOriginFacts.ruleStore}, derives the origin from it and
|
|
97
|
+
* stamps the word onto the surviving ask (`ruleStoreUnreadable`), which the approval request and the durable
|
|
98
|
+
* row carry beside `origin`.
|
|
99
|
+
*/
|
|
100
|
+
export declare const RULE_STORE_UNREADABLE_KINDS: readonly ["store", "call"];
|
|
101
|
+
export type RuleStoreUnreadable = (typeof RULE_STORE_UNREADABLE_KINDS)[number];
|
|
102
|
+
/** Membership test for {@link RuleStoreUnreadable} — the screen a row reader applies to a stored word. */
|
|
103
|
+
export declare function isRuleStoreUnreadable(v: unknown): v is RuleStoreUnreadable;
|
|
86
104
|
/** The facts about one call that only the gate holds — the derivation's inputs beyond the decision
|
|
87
105
|
* itself. Every member is a plain boolean/word read ONCE by the gate, so the derivation is a pure
|
|
88
106
|
* function that a test can drive arm by arm. */
|
|
@@ -95,9 +113,10 @@ export interface AskOriginFacts {
|
|
|
95
113
|
* read-back off the decision (a policy can put `decisionReason: "org_rule"` on its own ask; the
|
|
96
114
|
* gate's cell cannot be written by a policy). */
|
|
97
115
|
readonly org: "rule" | "unavailable" | undefined;
|
|
98
|
-
/** The gate's own record of its persisted-rule lane's READ:
|
|
99
|
-
*
|
|
100
|
-
|
|
116
|
+
/** The gate's own record of its persisted-rule lane's READ: which {@link RuleStoreUnreadable} mechanism
|
|
117
|
+
* left the lane's deny/ask rows unenforceable for this call, or undefined (the lane read the store and
|
|
118
|
+
* the call). Written only by the gate. */
|
|
119
|
+
readonly ruleStore?: RuleStoreUnreadable | undefined;
|
|
101
120
|
/** Which of the gate's OWN post-fold tightens minted the standing ask, if one did — again the gate's
|
|
102
121
|
* record of its own layer (a tighten replaces an `allow` wholesale, so at most one fires per pass),
|
|
103
122
|
* never a read-back of `decisionReason: "safety"` off a decision a policy could have composed. */
|
|
@@ -135,7 +154,7 @@ export declare function askOriginOf(decision: Extract<PermissionResult, {
|
|
|
135
154
|
*/
|
|
136
155
|
export declare const ORIGIN_IMPLIES_REAL_APPROVAL: {
|
|
137
156
|
readonly content_question: false;
|
|
138
|
-
readonly
|
|
157
|
+
readonly ancestor_marked: false;
|
|
139
158
|
readonly org_unavailable: "at_derivation";
|
|
140
159
|
readonly org_rule: "at_derivation";
|
|
141
160
|
readonly rule_store_unavailable: "at_derivation";
|
|
@@ -156,7 +175,7 @@ export type RealApprovalTableCoversEveryOrigin = AssertAllKeysHandled<Exclude<As
|
|
|
156
175
|
* answer, each for its own reason (kept beside its row so the reason travels with the fact):
|
|
157
176
|
* - `content_question`: a permission decider's verdict is neither an answer nor a park — letting it
|
|
158
177
|
* speak would skip the durable mandate, the park and the content route in one step.
|
|
159
|
-
* - `
|
|
178
|
+
* - `ancestor_marked`: a marked call must reach the park with no synchronous decision-maker between.
|
|
160
179
|
* - `org_unavailable` / `org_rule`: judgment may clear a `requiresRealApproval` bit a POLICY minted,
|
|
161
180
|
* but not the org's — while adjudication is unavailable the org's answer is unknown, and an org
|
|
162
181
|
* ask carries the org's own "a person nods" semantic.
|
|
@@ -185,7 +204,7 @@ export type RealApprovalTableCoversEveryOrigin = AssertAllKeysHandled<Exclude<As
|
|
|
185
204
|
*/
|
|
186
205
|
declare const CLASSIFIER_MAY_ANSWER: {
|
|
187
206
|
readonly content_question: false;
|
|
188
|
-
readonly
|
|
207
|
+
readonly ancestor_marked: false;
|
|
189
208
|
readonly org_unavailable: false;
|
|
190
209
|
readonly org_rule: false;
|
|
191
210
|
readonly rule_store_unavailable: false;
|
package/dist/core/ask-origin.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
export const ASK_ORIGINS = ["content_question", "
|
|
1
|
+
export const ASK_ORIGINS = ["content_question", "ancestor_marked", "org_unavailable", "org_rule", "rule_store_unavailable", "hook", "ask_rule", "denial_limit_fallback", "shell_gate_tighten", "safety_tighten", "policy"];
|
|
2
2
|
const ASK_ORIGIN_SET = new Set(ASK_ORIGINS);
|
|
3
3
|
export function isAskOrigin(v) {
|
|
4
4
|
return ASK_ORIGIN_SET.has(v);
|
|
5
5
|
}
|
|
6
|
+
export const RULE_STORE_UNREADABLE_KINDS = ["store", "call"];
|
|
7
|
+
const RULE_STORE_UNREADABLE_SET = new Set(RULE_STORE_UNREADABLE_KINDS);
|
|
8
|
+
export function isRuleStoreUnreadable(v) {
|
|
9
|
+
return RULE_STORE_UNREADABLE_SET.has(v);
|
|
10
|
+
}
|
|
6
11
|
export function askOriginOf(decision, facts) {
|
|
7
12
|
const origin = originLadder(decision, facts);
|
|
8
13
|
if (ORIGIN_IMPLIES_REAL_APPROVAL[origin] === "at_derivation" && decision.requiresRealApproval !== true) {
|
|
@@ -14,12 +19,12 @@ function originLadder(decision, facts) {
|
|
|
14
19
|
if (facts.contentQuestion)
|
|
15
20
|
return "content_question";
|
|
16
21
|
if (facts.markedUnresolvable)
|
|
17
|
-
return "
|
|
22
|
+
return "ancestor_marked";
|
|
18
23
|
if (facts.org === "unavailable")
|
|
19
24
|
return "org_unavailable";
|
|
20
25
|
if (facts.org === "rule")
|
|
21
26
|
return "org_rule";
|
|
22
|
-
if (facts.ruleStore
|
|
27
|
+
if (facts.ruleStore !== undefined)
|
|
23
28
|
return "rule_store_unavailable";
|
|
24
29
|
if (decision.decisionReason === "hook")
|
|
25
30
|
return "hook";
|
|
@@ -35,7 +40,7 @@ function originLadder(decision, facts) {
|
|
|
35
40
|
}
|
|
36
41
|
export const ORIGIN_IMPLIES_REAL_APPROVAL = {
|
|
37
42
|
content_question: false,
|
|
38
|
-
|
|
43
|
+
ancestor_marked: false,
|
|
39
44
|
org_unavailable: "at_derivation",
|
|
40
45
|
org_rule: "at_derivation",
|
|
41
46
|
rule_store_unavailable: "at_derivation",
|
|
@@ -48,7 +53,7 @@ export const ORIGIN_IMPLIES_REAL_APPROVAL = {
|
|
|
48
53
|
};
|
|
49
54
|
const CLASSIFIER_MAY_ANSWER = {
|
|
50
55
|
content_question: false,
|
|
51
|
-
|
|
56
|
+
ancestor_marked: false,
|
|
52
57
|
org_unavailable: false,
|
|
53
58
|
org_rule: false,
|
|
54
59
|
rule_store_unavailable: false,
|
package/dist/core/auto-mode.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ToolCallRequest } from "./tool-policy.js";
|
|
2
2
|
/**
|
|
3
|
-
* WHY an `unavailable` verdict could not run — the closed set behind the verdict arm, the
|
|
4
|
-
*
|
|
5
|
-
* the
|
|
3
|
+
* WHY an `unavailable` verdict could not run — the closed set behind the verdict arm, the model-facing
|
|
4
|
+
* sentence's parenthetical and the `auto_mode.classified` trace frame's `cause`, so the three spell one
|
|
5
|
+
* word (the deny's structural face carries only the round's FORM, `GateDisposition.cause`). `error` = the model leg
|
|
6
6
|
* threw or rejected (a route failure at classify time reads here too — the derived-route pre-flight fell
|
|
7
7
|
* back BEFORE any decide, so there is no separate word for it); `timeout` = the round-trip cap.
|
|
8
8
|
*/
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The checkpoint SEAT a run hands its children — the projection of `resolveCheckpointStore(spec, deps)` (the store the
|
|
3
|
+
* run parks in) plus the caller's own off switch onto the one value both delegation lanes copy verbatim onto a child
|
|
4
|
+
* spec (`ToolExecuteContext.checkpointStoreForChildren` on the Task lane, `RunWorkflowToolDeps.parentCheckpointStore`
|
|
5
|
+
* on the workflow lane). Minted once per prepare by the driver; read by the lanes and by the plan-pair face.
|
|
6
|
+
*/
|
|
7
|
+
import type { CheckpointStore } from "./checkpoint-store.js";
|
|
8
|
+
/** The seat a run hands its children: the store it resolved, or the word `"disabled"` when the caller disarmed the run. */
|
|
9
|
+
export type CheckpointSeat = CheckpointStore | "disabled";
|
|
10
|
+
/** Project a run's spec + resolved store onto the seat its children inherit: `"disabled"` when the caller disarmed the
|
|
11
|
+
* run (a removal that presses on the whole subtree), else the resolved store, else NOTHING — an unset spec on a
|
|
12
|
+
* deployment without a store hands down no seat, and the child's own door resolves its runner's deployment (a split
|
|
13
|
+
* child-execution runner may carry a store the host has none of; that topology is the deployment's own author). */
|
|
14
|
+
export declare function checkpointSeatOf(spec: {
|
|
15
|
+
checkpointStore?: CheckpointStore | "disabled";
|
|
16
|
+
}, resolved: CheckpointStore | undefined): CheckpointSeat | undefined;
|
|
17
|
+
/** The store a seat names — none for `"disabled"` and for no seat. */
|
|
18
|
+
export declare function checkpointStoreOfSeat(seat: CheckpointSeat | undefined): CheckpointStore | undefined;
|
|
@@ -444,14 +444,14 @@ export declare function buildRiskDescriptor(input: {
|
|
|
444
444
|
export interface RealApprovalGateBit {
|
|
445
445
|
/** The parked ask's ORIGIN word — a projection of the same closed set the card, the observer and the
|
|
446
446
|
* `tool_end` frame carry ({@link import("./ask-origin.js").AskOrigin}), never a second vocabulary. It
|
|
447
|
-
* is the ask's ROUTING word: a marked call reads `
|
|
447
|
+
* is the ask's ROUTING word: a marked call reads `ancestor_marked` even when the org governs it, because
|
|
448
448
|
* the ladder routes a marked call to the park before anything else. Rows minted before the projection
|
|
449
449
|
* carried a three-word subset of this set (`org_rule` / `org_unavailable` / `policy`), so every stored
|
|
450
450
|
* value is still a member. */
|
|
451
451
|
origin: import("./ask-origin.js").AskOrigin;
|
|
452
452
|
/** The ORG FACT the ask was minted under (`"rule"` = an org rule asked, `"unavailable"` = org adjudication
|
|
453
453
|
* unreachable), kept beside the routing word because routing can outrank the word (a marked call reads
|
|
454
|
-
* `
|
|
454
|
+
* `ancestor_marked`) while the governance stays. The #120 governed mark and the resume belts read THIS
|
|
455
455
|
* member through {@link realApprovalOrgFact} (absent on rows minted before it: the org words imply it). */
|
|
456
456
|
org?: "rule" | "unavailable";
|
|
457
457
|
}
|
|
@@ -813,14 +813,10 @@ export type PendingAction = {
|
|
|
813
813
|
* Written only when it is a member of the set; a pre-existing row reads absent (unreported).
|
|
814
814
|
* Display metadata — the resume belts keep reading the gate's own bit. */
|
|
815
815
|
origin?: import("./ask-origin.js").AskOrigin;
|
|
816
|
-
/** #
|
|
817
|
-
*
|
|
818
|
-
*
|
|
819
|
-
|
|
820
|
-
* the classifier was unavailable" sentence) — the resume belts never read it. */
|
|
821
|
-
classifierUnavailable?: {
|
|
822
|
-
readonly cause: import("./auto-mode.js").AutoModeUnavailableCause;
|
|
823
|
-
};
|
|
816
|
+
/** #688 C3 (additive, same precedent as `origin`) — the mechanism behind an `origin: "rule_store_unavailable"`
|
|
817
|
+
* (`store` / `call`, {@link import("./ask-origin.js").RULE_STORE_UNREADABLE_KINDS}). Written only when it is a
|
|
818
|
+
* member of the set; a pre-existing row reads absent. Display metadata for the durable card. */
|
|
819
|
+
ruleStoreUnreadable?: import("./ask-origin.js").RuleStoreUnreadable;
|
|
824
820
|
/**
|
|
825
821
|
* design/80 D-1 §2 (slice 1a.2): the server-minted **opaque** boundInputHash of {@link args} — a
|
|
826
822
|
* SHA-256 (hex) via {@link import("./canonical-json.js").boundInputHashOf}, computed ONCE here at
|
|
@@ -1926,12 +1922,9 @@ export interface CheckpointSummary {
|
|
|
1926
1922
|
* value is a member of the closed set ({@link import("./ask-origin.js").isAskOrigin}) — a bad value
|
|
1927
1923
|
* reads as absent, never as a word. OMITTED when the row carries none (a pre-existing row). */
|
|
1928
1924
|
origin?: import("./ask-origin.js").AskOrigin;
|
|
1929
|
-
/** The row's `PendingAction.tool_approval.
|
|
1930
|
-
*
|
|
1931
|
-
|
|
1932
|
-
classifierUnavailable?: {
|
|
1933
|
-
readonly cause: import("./auto-mode.js").AutoModeUnavailableCause;
|
|
1934
|
-
};
|
|
1925
|
+
/** The row's `PendingAction.tool_approval.ruleStoreUnreadable` (#688 C3), echoed ONLY when the stored word is a
|
|
1926
|
+
* member of the closed set ({@link import("./ask-origin.js").isRuleStoreUnreadable}); OMITTED otherwise. */
|
|
1927
|
+
ruleStoreUnreadable?: import("./ask-origin.js").RuleStoreUnreadable;
|
|
1935
1928
|
/**
|
|
1936
1929
|
* #438: PRESENCE ONLY — this pending `tool_approval` row's payload carries at least one DIRECTIONAL
|
|
1937
1930
|
* format control (the {@link import("./tool-policy.js").AskRequest.hasBidiControls} character class;
|
|
@@ -2,8 +2,8 @@ import { randomBytes, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { uuidv7 } from "../internal/harness.js";
|
|
3
3
|
import { PROBE_CAUSE_PATH_MAX, inlineUntrusted, sanitizeUntrustedText } from "./untrusted-text.js";
|
|
4
4
|
import { carriesBidiControls } from "./tool-policy.js";
|
|
5
|
-
import {
|
|
6
|
-
import { isAskOrigin } from "./ask-origin.js";
|
|
5
|
+
import { readDenialLimitFallback } from "./auto-mode.js";
|
|
6
|
+
import { isAskOrigin, isRuleStoreUnreadable } from "./ask-origin.js";
|
|
7
7
|
import { checkpointExecutionRecorded, executionRecordDisposition, ExecutionOutcomeConflictError, } from "./checkpoint-execution-record.js";
|
|
8
8
|
import { renderUntrustedCommandText, stripFormatCharacters } from "./permission-rule-model.js";
|
|
9
9
|
import { redactSecrets } from "./untrusted-egress.js";
|
|
@@ -277,8 +277,11 @@ export function summarizeCheckpoint(cp) {
|
|
|
277
277
|
const fb = readDenialLimitFallback(tool?.denialLimitFallback);
|
|
278
278
|
return fb !== undefined ? { denialLimitFallback: fb } : {};
|
|
279
279
|
})(),
|
|
280
|
-
...(
|
|
281
|
-
|
|
280
|
+
...(() => {
|
|
281
|
+
const origin = tool?.origin;
|
|
282
|
+
const ruleStoreUnreadable = tool?.ruleStoreUnreadable;
|
|
283
|
+
return { ...(isAskOrigin(origin) ? { origin } : {}), ...(isRuleStoreUnreadable(ruleStoreUnreadable) ? { ruleStoreUnreadable } : {}) };
|
|
284
|
+
})(),
|
|
282
285
|
...(hasBidi ? { hasBidiControls: true } : {}),
|
|
283
286
|
};
|
|
284
287
|
}
|
|
@@ -430,7 +430,9 @@ export interface EngineNotice {
|
|
|
430
430
|
* consolidation run, so the CLEAN arm's authoring prompts were composed WITHOUT the marked
|
|
431
431
|
* rows: anything this run's clean products say was written without them, and their silence on a
|
|
432
432
|
* topic therefore does not mean the library is silent on it (the withheld rows still stand and
|
|
433
|
-
* are still readable).
|
|
433
|
+
* are still readable). OPERATOR audience (#692 C-a): the run happens outside any session, so
|
|
434
|
+
* there is no `sessionId` to route a user row to — the receipt's `withheldFromCleanArm` /
|
|
435
|
+
* `withheldNeverSent` are the reader-facing half. TWO counts, deliberately separate sentences and separate keys —
|
|
434
436
|
* `withheld` rows were kept out of the clean arm's prompts, and `neverSent` of those were not
|
|
435
437
|
* sent to the consolidation model AT ALL (a lone marked row has no group to fold, so it is
|
|
436
438
|
* withheld from every call). "Withheld from the clean arm" and "never left this machine" are
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Say a knob-resolution fact once per process.
|
|
3
|
+
*
|
|
4
|
+
* Swallow-guarded, the same posture as every other advisory sink here (`deliverEngineNotice`,
|
|
5
|
+
* `emitBrainStatus`, `emitBrainTelemetry`): an announcement must never become a failure. The write is
|
|
6
|
+
* not to a channel this process owns — a host is free to replace `console.warn` with its own logger,
|
|
7
|
+
* and a `Console` built with `ignoreErrors:false` throws on a full or closed stream. These resolvers
|
|
8
|
+
* sit on hot paths that have already done irreversible work (the shell's output clip runs AFTER the
|
|
9
|
+
* command ran), so an unguarded write could destroy a completed command's output and invite the caller
|
|
10
|
+
* to run it again. The line is ledgered BEFORE delivery so a throwing sink cannot turn one fact into a
|
|
11
|
+
* warning per call either.
|
|
12
|
+
*/
|
|
13
|
+
export declare function announceEnvKnob(line: string): void;
|
|
14
|
+
/** Test seam: the announcement de-dupes per process, so a test asserting the line must be able to clear
|
|
15
|
+
* the ledger. Never called by production code. */
|
|
16
|
+
export declare function __resetEnvKnobAnnouncements(): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const announcedEnvKnobLines = new Set();
|
|
2
|
+
export function announceEnvKnob(line) {
|
|
3
|
+
if (announcedEnvKnobLines.has(line))
|
|
4
|
+
return;
|
|
5
|
+
announcedEnvKnobLines.add(line);
|
|
6
|
+
try {
|
|
7
|
+
console.warn(line);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function __resetEnvKnobAnnouncements() {
|
|
13
|
+
announcedEnvKnobLines.clear();
|
|
14
|
+
}
|
package/dist/core/gate-fold.js
CHANGED
|
@@ -36,6 +36,8 @@ export async function runGateFold(pass) {
|
|
|
36
36
|
const refusedBy = ledger.fromDecision(pass.decision);
|
|
37
37
|
if (refusedBy !== undefined)
|
|
38
38
|
pass.deniedBy = refusedBy;
|
|
39
|
+
if (refusedBy !== undefined)
|
|
40
|
+
pass.denyCause = ledger.causeOf(pass.decision);
|
|
39
41
|
}
|
|
40
42
|
if ((pass.decision.action === "allow" || pass.decision.action === "ask") && pass.decision.updatedInput !== undefined) {
|
|
41
43
|
pass.policyRewrite = pass.decision.updatedInput;
|
package/dist/core/gate-lanes.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { decisionText, describeThrown } from "./tool-policy.js";
|
|
1
|
+
import { attestClassifierDenyCause, classifierDenyCauseOf, decisionText, describeThrown } from "./tool-policy.js";
|
|
2
2
|
import { askOriginOf, classifierMayAnswer, persistedRuleMandateOf, probeBoundaryMandate } from "./ask-origin.js";
|
|
3
3
|
import { CLASSIFIER_PARSE_FAILURE_DENY_MESSAGE, classifierUnavailableDenyMessage, denialLimitFallbackMessage, unarmedWindow } from "./auto-mode.js";
|
|
4
4
|
import { inlineUntrusted } from "./untrusted-text.js";
|
|
@@ -220,6 +220,7 @@ export async function runGateLanes(pass) {
|
|
|
220
220
|
if (behavior === "deny") {
|
|
221
221
|
orgTightenCount += 1;
|
|
222
222
|
pass.deniedBy = "org";
|
|
223
|
+
pass.denyCause = undefined;
|
|
223
224
|
return { decision: { action: "deny", message: `an organization policy rule (${rule}) denies this call`, decisionReason: ORG_RULE_DECISION_REASON }, org: undefined };
|
|
224
225
|
}
|
|
225
226
|
if (decided.action === "deny")
|
|
@@ -242,6 +243,7 @@ export async function runGateLanes(pass) {
|
|
|
242
243
|
};
|
|
243
244
|
const orgAnswer = await applyOrgLayer(pass.decision, pass.policyRewrite !== undefined ? pass.policyRewrite : pass.currentInput);
|
|
244
245
|
pass.decision = orgAnswer.decision;
|
|
246
|
+
const ruleStoreUnreadableOf = (lane) => lane?.unreadable === true ? (lane.reason !== undefined ? "call" : "store") : undefined;
|
|
245
247
|
const readPersistedRules = async (req) => {
|
|
246
248
|
let pendingHit;
|
|
247
249
|
try {
|
|
@@ -259,6 +261,8 @@ export async function runGateLanes(pass) {
|
|
|
259
261
|
pass.decision = tightened.decision;
|
|
260
262
|
if (tightened.tightened === "deny")
|
|
261
263
|
pass.deniedBy = "persisted_rule";
|
|
264
|
+
if (tightened.tightened === "deny")
|
|
265
|
+
pass.denyCause = undefined;
|
|
262
266
|
}
|
|
263
267
|
if (pass.decision.action === "ask") {
|
|
264
268
|
pass.decision = { ...pass.decision };
|
|
@@ -338,9 +342,10 @@ export async function runGateLanes(pass) {
|
|
|
338
342
|
};
|
|
339
343
|
}
|
|
340
344
|
}
|
|
341
|
-
const originFacts = askOriginFacts(orgAnswer.org, laneAnswer
|
|
345
|
+
const originFacts = askOriginFacts(orgAnswer.org, ruleStoreUnreadableOf(laneAnswer));
|
|
342
346
|
if (pass.decision.action === "ask") {
|
|
343
|
-
const
|
|
347
|
+
const { ruleStoreUnreadable: _selfDeclared, ...unstamped } = pass.decision;
|
|
348
|
+
const stamped = { ...unstamped, ruleEvidence: mintRuleEvidence(personalEvidence), ...(laneCoverage !== undefined ? { segmentCoverage: laneCoverage } : {}), ...(originFacts.ruleStore !== undefined ? { ruleStoreUnreadable: originFacts.ruleStore } : {}) };
|
|
344
349
|
pass.decision = { ...stamped, origin: askOriginOf(stamped, originFacts) };
|
|
345
350
|
}
|
|
346
351
|
if (allowLayerMayClear() && pass.decision.action === "ask" && persistedRuleMandate === undefined && pass.decision.matchedAskRule === undefined && pass.req.toolName === COMMAND_RULE_TOOL) {
|
|
@@ -374,12 +379,11 @@ export async function runGateLanes(pass) {
|
|
|
374
379
|
};
|
|
375
380
|
}
|
|
376
381
|
else if (verdict.kind === "unavailable") {
|
|
377
|
-
pass.decision = {
|
|
382
|
+
pass.decision = attestClassifierDenyCause({
|
|
378
383
|
action: "deny",
|
|
379
384
|
message: classifierUnavailableDenyMessage(toolName, verdict.cause),
|
|
380
385
|
decisionReason: "classifier",
|
|
381
|
-
|
|
382
|
-
};
|
|
386
|
+
}, "unavailable", pass.req);
|
|
383
387
|
}
|
|
384
388
|
else {
|
|
385
389
|
const reason = verdict.kind === "block" ? (verdict.reason ? inlineUntrusted(verdict.reason) : "") : CLASSIFIER_PARSE_FAILURE_DENY_MESSAGE;
|
|
@@ -396,15 +400,18 @@ export async function runGateLanes(pass) {
|
|
|
396
400
|
pass.decision = { ...fallbackAsk, origin: askOriginOf(fallbackAsk, originFacts) };
|
|
397
401
|
}
|
|
398
402
|
else {
|
|
399
|
-
|
|
403
|
+
const denied = {
|
|
400
404
|
action: "deny",
|
|
401
405
|
message: verdict.kind === "block" ? `auto-mode classifier blocked this call${reason ? `: ${reason}` : category ? `: [${category}]` : ""}` : reason,
|
|
402
406
|
decisionReason: "classifier",
|
|
403
407
|
};
|
|
408
|
+
pass.decision = verdict.kind === "parse_error" ? attestClassifierDenyCause(denied, "parse_error", pass.req) : denied;
|
|
404
409
|
}
|
|
405
410
|
}
|
|
406
|
-
if (pass.decision.action === "deny")
|
|
411
|
+
if (pass.decision.action === "deny") {
|
|
407
412
|
pass.deniedBy = "classifier";
|
|
413
|
+
pass.denyCause = classifierDenyCauseOf(pass.decision, pass.req);
|
|
414
|
+
}
|
|
408
415
|
}
|
|
409
416
|
if (input.sandboxAdmission !== undefined &&
|
|
410
417
|
pass.decision.action === "ask" &&
|
|
@@ -446,7 +453,7 @@ export async function runGateLanes(pass) {
|
|
|
446
453
|
...(callSignal !== undefined ? { signal: callSignal } : {}),
|
|
447
454
|
...(d.action === "ask" && d.denialLimitFallback !== undefined ? { denialLimitFallback: unarmedWindow(d.denialLimitFallback) } : {}),
|
|
448
455
|
...(d.action === "ask" && d.origin !== undefined ? { origin: d.origin } : {}),
|
|
449
|
-
...(d.action === "ask" && d.
|
|
456
|
+
...(d.action === "ask" && d.ruleStoreUnreadable !== undefined ? { ruleStoreUnreadable: d.ruleStoreUnreadable } : {}),
|
|
450
457
|
});
|
|
451
458
|
if (suspendAsk && pass.decision.action === "ask") {
|
|
452
459
|
const parkArgs = [pass.req, pass.currentInput, safety, undefined, realApprovalOf(pass.decision), pass.decision.action === "ask" ? pass.decision.persistedRuleShadowed : undefined, pass.decision.action === "ask" ? pass.decision.decisionReason : undefined, pass.decision.action === "ask" ? pass.decision.probeReason : undefined, pass.decision.action === "ask" ? pass.decision.probeCause : undefined, pass.decision.action === "ask" ? pass.decision.segmentCoverage : undefined, pass.decision.action === "ask" ? pass.decision.matchedAskRule : undefined, pass.decision.action === "ask" ? pass.decision.probeMandated : undefined];
|
|
@@ -614,6 +621,7 @@ export async function runGateLanes(pass) {
|
|
|
614
621
|
if (recheck.action === "deny" && refusedBy !== undefined) {
|
|
615
622
|
editDenied = recheck;
|
|
616
623
|
pass.deniedBy = refusedBy;
|
|
624
|
+
pass.denyCause = ledger.causeOf(recheck);
|
|
617
625
|
break;
|
|
618
626
|
}
|
|
619
627
|
}
|
|
@@ -630,7 +638,7 @@ export async function runGateLanes(pass) {
|
|
|
630
638
|
let editRuleStore;
|
|
631
639
|
if (input.persistedRules !== undefined && toolName !== ASK_USER_QUESTION_TOOL_NAME) {
|
|
632
640
|
const editLane = await readPersistedRules({ toolName, args: editArgs, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) });
|
|
633
|
-
editRuleStore = editLane
|
|
641
|
+
editRuleStore = ruleStoreUnreadableOf(editLane);
|
|
634
642
|
const editTightened = applyPersistedTightening(recheck, editLane);
|
|
635
643
|
recheck = editTightened.decision;
|
|
636
644
|
if (editTightened.tightened === "deny")
|
|
@@ -651,9 +659,10 @@ export async function runGateLanes(pass) {
|
|
|
651
659
|
editArgs = recheck.updatedInput;
|
|
652
660
|
editRewrittenSinceHuman = true;
|
|
653
661
|
}
|
|
654
|
-
const
|
|
662
|
+
const { ruleStoreUnreadable: _selfDeclaredOnEdit, ...recheckUnstamped } = recheck;
|
|
663
|
+
const editAskSnapshot = { ...recheckUnstamped, ruleEvidence: mintRuleEvidence({ dotsAbsent: "not_adjudicated" }) };
|
|
655
664
|
markedThisRound = undefined;
|
|
656
|
-
const editAskDecision = { ...editAskSnapshot, origin: askOriginOf(editAskSnapshot, askOriginFacts(editOrg.org, editRuleStore)) };
|
|
665
|
+
const editAskDecision = { ...editAskSnapshot, ...(editRuleStore !== undefined ? { ruleStoreUnreadable: editRuleStore } : {}), origin: askOriginOf(editAskSnapshot, askOriginFacts(editOrg.org, editRuleStore)) };
|
|
657
666
|
const editAskReq = { toolName, args: editArgs, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) };
|
|
658
667
|
const rr = await (callSignal !== undefined ? resolveAsk(editAskDecision, editAskReq, callSignal) : resolveAsk(editAskDecision, editAskReq));
|
|
659
668
|
ledger.fromResolved(rr, editAskDecision, toolName);
|
|
@@ -153,12 +153,49 @@ export declare const DENIED_BY_MAY_VETO: {
|
|
|
153
153
|
};
|
|
154
154
|
/** Compile-time fence: `never` while every deny layer has a veto row. */
|
|
155
155
|
export type VetoTableCoversEveryDeniedBy = AssertAllKeysHandled<Exclude<DeniedBy, keyof typeof DENIED_BY_MAY_VETO>>;
|
|
156
|
-
/**
|
|
156
|
+
/**
|
|
157
|
+
* The FORM of an auto-mode classifier deny — the one structural position a consumer branches on when a
|
|
158
|
+
* deny came through the classifier station. The classifier ends a round three ways, and until this
|
|
159
|
+
* member the wire carried the three as one layer word plus prose:
|
|
160
|
+
* - `unavailable` — the classifier could not run (the model leg threw / rejected / ran past the cap):
|
|
161
|
+
* a fail-closed refusal that SAYS SO — the call may simply be retried later (CC 2.1.250 `x1t`);
|
|
162
|
+
* - `parse_error` — the classifier answered outside its verdict contract: blocked for safety, counted by
|
|
163
|
+
* the denial limit like a ruling (CC 2.1.250 `Ure`);
|
|
164
|
+
* - ABSENT beside `deniedBy: "classifier"` — the classifier's own RULING (a `<block>yes` verdict).
|
|
165
|
+
* The WHY behind an `unavailable` (error vs timeout) is not a branching fact: the deny sentence spells it
|
|
166
|
+
* and the `auto_mode.classified` trace frame carries it (`cause: "error" | "timeout"`).
|
|
167
|
+
*/
|
|
168
|
+
export declare const CLASSIFIER_DENY_CAUSES: readonly ["unavailable", "parse_error"];
|
|
169
|
+
export type ClassifierDenyCause = (typeof CLASSIFIER_DENY_CAUSES)[number];
|
|
170
|
+
/** Membership test for {@link ClassifierDenyCause}. */
|
|
171
|
+
export declare function isClassifierDenyCause(v: unknown): v is ClassifierDenyCause;
|
|
172
|
+
/** Which deny layers a classifier cause may stand beside: the gate's own classifier station (`classifier`),
|
|
173
|
+
* and an ANCESTOR's frozen classifier reached through the inherited policy chain, whose deny the child's
|
|
174
|
+
* gate attributes to the chain (`policy`, station row 14) — the cause is attested by the station that
|
|
175
|
+
* minted the deny, so the word beside it is whichever layer word the child's ledger assigns. */
|
|
176
|
+
export declare const DENIED_BY_MAY_CARRY_CAUSE: {
|
|
177
|
+
readonly policy: true;
|
|
178
|
+
readonly hook: false;
|
|
179
|
+
readonly org: false;
|
|
180
|
+
readonly persisted_rule: false;
|
|
181
|
+
readonly classifier: true;
|
|
182
|
+
readonly plan_mode: false;
|
|
183
|
+
readonly compliance: false;
|
|
184
|
+
readonly write_protection: false;
|
|
185
|
+
readonly ask_resolution: false;
|
|
186
|
+
};
|
|
187
|
+
/** Compile-time fence: `never` while every deny layer has a cause row. */
|
|
188
|
+
export type CauseTableCoversEveryDeniedBy = AssertAllKeysHandled<Exclude<DeniedBy, keyof typeof DENIED_BY_MAY_CARRY_CAUSE>>;
|
|
189
|
+
/** The final disposition of a gate pass. `cause` is present exactly when the deny came out of an auto-mode
|
|
190
|
+
* classifier round that did not RULE ({@link ClassifierDenyCause}); a ruling block and every non-classifier
|
|
191
|
+
* deny carry none. Invariant I5 ({@link screenGateOutcome}): a cause stands only beside a layer word in
|
|
192
|
+
* {@link DENIED_BY_MAY_CARRY_CAUSE}. */
|
|
157
193
|
export type GateDisposition = {
|
|
158
194
|
kind: "allowed";
|
|
159
195
|
} | {
|
|
160
196
|
kind: "denied";
|
|
161
197
|
deniedBy: DeniedBy;
|
|
198
|
+
cause?: ClassifierDenyCause;
|
|
162
199
|
};
|
|
163
200
|
/**
|
|
164
201
|
* The WHOLE record of one tool-gate pass: the final disposition, plus — when this pass settled an ask —
|
|
@@ -173,7 +210,9 @@ export type GateDisposition = {
|
|
|
173
210
|
* I3 `settlement.kind === "human_allowed"` ∧ `disposition.kind === "denied"` ⇒ `deniedBy` is a veto
|
|
174
211
|
* layer ({@link DENIED_BY_MAY_VETO}) — a person approved, a later re-check refused; the approver stays
|
|
175
212
|
* on the settlement (it is not the approver's refusal);
|
|
176
|
-
* I4 `disposition.kind === "allowed"` ⇒ `settlement` absent or `human_allowed
|
|
213
|
+
* I4 `disposition.kind === "allowed"` ⇒ `settlement` absent or `human_allowed`;
|
|
214
|
+
* I5 `disposition.cause` present ⇒ a member of {@link CLASSIFIER_DENY_CAUSES} beside a layer word
|
|
215
|
+
* {@link DENIED_BY_MAY_CARRY_CAUSE} admits (the classifier station, or the inherited chain's `policy`).
|
|
177
216
|
* Nothing here is read out of an ABSENCE: an ordinary allow with no ask is `{ disposition: { kind: "allowed" } }`,
|
|
178
217
|
* a direct policy deny is `{ disposition: { kind: "denied", deniedBy: "policy" } }`, and neither carries a
|
|
179
218
|
* settlement because neither settled one.
|
|
@@ -184,7 +223,7 @@ export interface GateOutcome {
|
|
|
184
223
|
origin?: AskOrigin;
|
|
185
224
|
}
|
|
186
225
|
/**
|
|
187
|
-
* The one invariant screen for a {@link GateOutcome} (I1–
|
|
226
|
+
* The one invariant screen for a {@link GateOutcome} (I1–I5 above, plus the shape of each member). Runs
|
|
188
227
|
* where an outcome enters a wire face — the engine's settlement sideband before the `tool_end` frame, and
|
|
189
228
|
* the decide lane before a durable row is resolved. Returns the defects as sentences (an empty list is a
|
|
190
229
|
* clean record); the caller decides the fail-loud form (report + withhold, or refuse), never silently
|
|
@@ -47,6 +47,22 @@ export const DENIED_BY_MAY_VETO = {
|
|
|
47
47
|
write_protection: true,
|
|
48
48
|
ask_resolution: false,
|
|
49
49
|
};
|
|
50
|
+
export const CLASSIFIER_DENY_CAUSES = ["unavailable", "parse_error"];
|
|
51
|
+
const CLASSIFIER_DENY_CAUSE_SET = new Set(CLASSIFIER_DENY_CAUSES);
|
|
52
|
+
export function isClassifierDenyCause(v) {
|
|
53
|
+
return CLASSIFIER_DENY_CAUSE_SET.has(v);
|
|
54
|
+
}
|
|
55
|
+
export const DENIED_BY_MAY_CARRY_CAUSE = {
|
|
56
|
+
policy: true,
|
|
57
|
+
hook: false,
|
|
58
|
+
org: false,
|
|
59
|
+
persisted_rule: false,
|
|
60
|
+
classifier: true,
|
|
61
|
+
plan_mode: false,
|
|
62
|
+
compliance: false,
|
|
63
|
+
write_protection: false,
|
|
64
|
+
ask_resolution: false,
|
|
65
|
+
};
|
|
50
66
|
export function screenGateOutcome(g) {
|
|
51
67
|
const defects = [];
|
|
52
68
|
const d = g.disposition;
|
|
@@ -67,5 +83,11 @@ export function screenGateOutcome(g) {
|
|
|
67
83
|
}
|
|
68
84
|
if (d.kind === "allowed" && s !== undefined && s.kind !== "human_allowed")
|
|
69
85
|
defects.push(`I4: an allowed disposition cannot carry a "${s.kind}" settlement`);
|
|
86
|
+
if (d.kind === "denied" && d.cause !== undefined) {
|
|
87
|
+
if (!isClassifierDenyCause(d.cause))
|
|
88
|
+
defects.push(`disposition.cause "${String(d.cause)}" is outside the closed set`);
|
|
89
|
+
else if (isDeniedBy(d.deniedBy) && !DENIED_BY_MAY_CARRY_CAUSE[d.deniedBy])
|
|
90
|
+
defects.push(`I5: a classifier cause cannot stand beside deniedBy "${d.deniedBy}"`);
|
|
91
|
+
}
|
|
70
92
|
return defects;
|
|
71
93
|
}
|
|
@@ -164,7 +164,7 @@ const NOTICE_AUDIENCE_TABLE = {
|
|
|
164
164
|
"config.durable_gate_unavailable": "user",
|
|
165
165
|
"memory.capture_opted_out": "user",
|
|
166
166
|
"memory.capture_optout_unpersisted": "user",
|
|
167
|
-
"memory.consolidation_withheld": "
|
|
167
|
+
"memory.consolidation_withheld": "operator",
|
|
168
168
|
"delegation.ask_unresolvable": "user",
|
|
169
169
|
"config.autocompact_window_clamped": "operator",
|
|
170
170
|
"config.env_timeout_discarded": "operator",
|
package/dist/core/hooks.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { GateOutcome } from "./gate-outcome.js";
|
|
|
5
5
|
export { normalizeOrgGateVerdict, normalizePersistedRuleHit } from "./gate-lanes.js";
|
|
6
6
|
export { cloneObserverInput } from "./runner/gate-exit.js";
|
|
7
7
|
import { type AskClass } from "./ask-class.js";
|
|
8
|
-
import {
|
|
8
|
+
import type { AutoModeDenialTracker } from "./auto-mode.js";
|
|
9
9
|
export { formatHookFeedback } from "./reminder-mint.js";
|
|
10
10
|
import type { WiringLegKind } from "./wiring-manifest.js";
|
|
11
11
|
/**
|
|
@@ -411,12 +411,6 @@ export interface PermissionDeniedPayload {
|
|
|
411
411
|
* settled none.
|
|
412
412
|
*/
|
|
413
413
|
gate: GateOutcome;
|
|
414
|
-
/** #661 (additive): present ⇔ this deny is the auto-mode classifier's UNAVAILABILITY (`deniedBy: "classifier"`
|
|
415
|
-
* with the verdict's cause word) — the structured half of the deny text's "the classifier is temporarily
|
|
416
|
-
* unavailable" sentence. A classifier BLOCK or parse-failure deny carries no member here. */
|
|
417
|
-
classifierUnavailable?: {
|
|
418
|
-
readonly cause: import("./auto-mode.js").AutoModeUnavailableCause;
|
|
419
|
-
};
|
|
420
414
|
/** {@link HookSeatSignal} — this invocation's own abort signal. On an OBSERVATION seat the deny has
|
|
421
415
|
* already happened and nothing this callback does can change it, so the signal says exactly one
|
|
422
416
|
* thing: stop reading, nobody is waiting for your answer any more. */
|
|
@@ -1676,12 +1670,9 @@ export interface AskCarry {
|
|
|
1676
1670
|
/** The surviving ask's engine-stamped origin word ({@link import("./ask-origin.js").AskOrigin}), persisted
|
|
1677
1671
|
* on the row so a durable card is rendered by the same word the synchronous card is. */
|
|
1678
1672
|
readonly origin?: import("./ask-origin.js").AskOrigin;
|
|
1679
|
-
/** #
|
|
1680
|
-
*
|
|
1681
|
-
|
|
1682
|
-
readonly classifierUnavailable?: {
|
|
1683
|
-
readonly cause: import("./auto-mode.js").AutoModeUnavailableCause;
|
|
1684
|
-
};
|
|
1673
|
+
/** #688 C3: the mechanism behind an `origin: "rule_store_unavailable"` (`store` / `call`), persisted on the row
|
|
1674
|
+
* so a durable card says the same thing the synchronous card does. */
|
|
1675
|
+
readonly ruleStoreUnreadable?: import("./ask-origin.js").RuleStoreUnreadable;
|
|
1685
1676
|
}
|
|
1686
1677
|
/** What a durable row persists of an {@link AskCarry}: the fallback member COPIED (the row never aliases
|
|
1687
1678
|
* the gate's object; its window is already `0` — the gate's carry mint is the one writer of that
|
|
@@ -1690,9 +1681,7 @@ export interface AskCarry {
|
|
|
1690
1681
|
export declare function askCarryRowMembers(carry: AskCarry | undefined): {
|
|
1691
1682
|
denialLimitFallback?: import("./auto-mode.js").DenialLimitFallback;
|
|
1692
1683
|
origin?: import("./ask-origin.js").AskOrigin;
|
|
1693
|
-
|
|
1694
|
-
readonly cause: import("./auto-mode.js").AutoModeUnavailableCause;
|
|
1695
|
-
};
|
|
1684
|
+
ruleStoreUnreadable?: import("./ask-origin.js").RuleStoreUnreadable;
|
|
1696
1685
|
};
|
|
1697
1686
|
/**
|
|
1698
1687
|
* The design/37 **two-phase tool gate** — the single chokepoint that makes the load-bearing invariant
|