@sema-agent/core 7.33.8 → 7.35.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.
Files changed (228) hide show
  1. package/CHANGELOG.md +462 -3
  2. package/dist/agents/cross-session-judge.d.ts +16 -7
  3. package/dist/agents/cross-session-judge.js +18 -15
  4. package/dist/agents/peer-session-drain.d.ts +4 -0
  5. package/dist/agents/peer-session-drain.js +5 -2
  6. package/dist/agents/repair-loop.d.ts +1 -1
  7. package/dist/agents/subagent.d.ts +3 -0
  8. package/dist/agents/subagent.js +12 -3
  9. package/dist/brain/anthropic.js +1 -0
  10. package/dist/brain/errors.d.ts +23 -1
  11. package/dist/brain/errors.js +19 -2
  12. package/dist/brain/open-responses.js +1 -0
  13. package/dist/brain/openai.js +1 -0
  14. package/dist/brain/status-sink.d.ts +7 -1
  15. package/dist/brain/stream-engine.d.ts +3 -0
  16. package/dist/brain/stream-engine.js +2 -1
  17. package/dist/brain/stream-shared.d.ts +3 -1
  18. package/dist/brain/stream-shared.js +16 -4
  19. package/dist/core/a2a.d.ts +3 -1
  20. package/dist/core/a2a.js +1 -1
  21. package/dist/core/ask-origin.d.ts +379 -154
  22. package/dist/core/ask-origin.js +224 -45
  23. package/dist/core/ask-question.js +2 -1
  24. package/dist/core/ask-unresolvable-notice.d.ts +5 -2
  25. package/dist/core/ask-unresolvable-notice.js +4 -3
  26. package/dist/core/auto-mode-arming.d.ts +17 -4
  27. package/dist/core/auto-mode-arming.js +31 -6
  28. package/dist/core/auto-mode-defaults.d.ts +16 -7
  29. package/dist/core/auto-mode-defaults.js +2 -1
  30. package/dist/core/auto-mode-directive.d.ts +18 -30
  31. package/dist/core/auto-mode-directive.js +9 -18
  32. package/dist/core/auto-mode-prompt.d.ts +62 -1
  33. package/dist/core/auto-mode-prompt.js +42 -4
  34. package/dist/core/auto-mode-rebuild.d.ts +2 -1
  35. package/dist/core/auto-mode-rebuild.js +1 -0
  36. package/dist/core/auto-mode.d.ts +32 -3
  37. package/dist/core/auto-mode.js +80 -41
  38. package/dist/core/checkpoint-store.d.ts +54 -35
  39. package/dist/core/checkpoint-store.js +58 -3
  40. package/dist/core/child-clamp-seats.js +1 -0
  41. package/dist/core/classifier-unavailable-arm.d.ts +57 -0
  42. package/dist/core/classifier-unavailable-arm.js +17 -0
  43. package/dist/core/effective-path-target.d.ts +12 -0
  44. package/dist/core/effective-path-target.js +18 -7
  45. package/dist/core/engine-notice.d.ts +53 -2
  46. package/dist/core/fs-write-gate-policy.d.ts +5 -1
  47. package/dist/core/fs-write-gate-policy.js +4 -1
  48. package/dist/core/gate-fold.js +19 -3
  49. package/dist/core/gate-lanes.js +116 -50
  50. package/dist/core/gate-outcome.d.ts +40 -7
  51. package/dist/core/gate-outcome.js +26 -4
  52. package/dist/core/governance-codes.d.ts +18 -2
  53. package/dist/core/governance-codes.js +23 -1
  54. package/dist/core/hooks.d.ts +53 -29
  55. package/dist/core/hooks.js +1 -3
  56. package/dist/core/mcp.js +1 -1
  57. package/dist/core/message-utils.d.ts +2 -1
  58. package/dist/core/message-utils.js +2 -1
  59. package/dist/core/mode-policy.d.ts +185 -0
  60. package/dist/core/mode-policy.js +184 -0
  61. package/dist/core/oracle-isolation.d.ts +3 -3
  62. package/dist/core/permission-rule-model.d.ts +20 -3
  63. package/dist/core/permission-rule-model.js +40 -3
  64. package/dist/core/permission-rule-provider.d.ts +22 -11
  65. package/dist/core/permission-rule-provider.js +17 -7
  66. package/dist/core/permission-rules.d.ts +23 -1
  67. package/dist/core/permission-rules.js +56 -9
  68. package/dist/core/persisted-rule-arms.d.ts +14 -10
  69. package/dist/core/persisted-rule-arms.js +13 -6
  70. package/dist/core/present-plan-tool.d.ts +1 -1
  71. package/dist/core/present-plan-tool.js +3 -3
  72. package/dist/core/read-only-shell.d.ts +19 -19
  73. package/dist/core/read-only-shell.js +38 -12
  74. package/dist/core/retired-keys.d.ts +9 -3
  75. package/dist/core/retired-keys.js +5 -1
  76. package/dist/core/runner/active-skill-scope.js +5 -4
  77. package/dist/core/runner/assemble-result.js +2 -2
  78. package/dist/core/runner/classifier-ladder.d.ts +43 -1
  79. package/dist/core/runner/classifier-ladder.js +29 -0
  80. package/dist/core/runner/contracts.d.ts +62 -38
  81. package/dist/core/runner/denial-limit-arms.d.ts +35 -7
  82. package/dist/core/runner/denial-limit-arms.js +15 -9
  83. package/dist/core/runner/env-capability-census.js +1 -1
  84. package/dist/core/runner/file-history-request.d.ts +26 -0
  85. package/dist/core/runner/file-history-request.js +90 -0
  86. package/dist/core/runner/gate-exit.d.ts +30 -4
  87. package/dist/core/runner/gate-exit.js +28 -7
  88. package/dist/core/runner/permission-rule-lanes.d.ts +11 -6
  89. package/dist/core/runner/permission-rule-lanes.js +55 -48
  90. package/dist/core/runner/persisted-path-rows.d.ts +64 -0
  91. package/dist/core/runner/persisted-path-rows.js +89 -0
  92. package/dist/core/runner/prepare-artifact.d.ts +5 -1
  93. package/dist/core/runner/prepare-artifact.js +9 -3
  94. package/dist/core/runner/prepare-ask-lane.d.ts +6 -4
  95. package/dist/core/runner/prepare-ask-lane.js +3 -3
  96. package/dist/core/runner/prepare-caps-and-workflow.d.ts +39 -13
  97. package/dist/core/runner/prepare-caps-and-workflow.js +58 -29
  98. package/dist/core/runner/prepare-file-history.d.ts +9 -3
  99. package/dist/core/runner/prepare-file-history.js +4 -90
  100. package/dist/core/runner/prepare-gate-stations.d.ts +37 -9
  101. package/dist/core/runner/prepare-gate-stations.js +46 -29
  102. package/dist/core/runner/prepare-hands-readface.d.ts +40 -17
  103. package/dist/core/runner/prepare-hands-readface.js +64 -53
  104. package/dist/core/runner/prepare-inherited-gate.d.ts +30 -23
  105. package/dist/core/runner/prepare-inherited-gate.js +45 -25
  106. package/dist/core/runner/prepare-park-ask.d.ts +6 -4
  107. package/dist/core/runner/prepare-park-ask.js +7 -5
  108. package/dist/core/runner/prepare-policy-chain.d.ts +25 -4
  109. package/dist/core/runner/prepare-policy-chain.js +203 -180
  110. package/dist/core/runner/prepare-protocol-tools.d.ts +28 -0
  111. package/dist/core/runner/prepare-protocol-tools.js +13 -3
  112. package/dist/core/runner/prepare-run-refs.d.ts +6 -6
  113. package/dist/core/runner/prepare-run-refs.js +9 -4
  114. package/dist/core/runner/prepare-safety-scan.d.ts +5 -0
  115. package/dist/core/runner/prepare-safety-scan.js +19 -3
  116. package/dist/core/runner/prepare-suspend-saga.d.ts +5 -5
  117. package/dist/core/runner/prepare-suspend-saga.js +6 -6
  118. package/dist/core/runner/prepare-task.js +56 -24
  119. package/dist/core/runner/prepare-wiring-manifest.d.ts +10 -6
  120. package/dist/core/runner/prepare-wiring-manifest.js +5 -3
  121. package/dist/core/runner/read-root-grant.d.ts +9 -0
  122. package/dist/core/runner/read-root-grant.js +12 -0
  123. package/dist/core/runner/retired-runner-deps.js +1 -0
  124. package/dist/core/runner/run-brain-sinks.js +3 -1
  125. package/dist/core/runner/run-identity-wiring.js +1 -1
  126. package/dist/core/runner/run-leg.js +29 -18
  127. package/dist/core/runner/run-notification-lane.d.ts +3 -0
  128. package/dist/core/runner/run-notification-lane.js +3 -1
  129. package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +2 -2
  130. package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
  131. package/dist/core/runner/run-turn-boundary.js +1 -1
  132. package/dist/core/runner/runtask.d.ts +1 -0
  133. package/dist/core/runner/runtask.js +8 -11
  134. package/dist/core/runner/session-mode-seats.d.ts +48 -0
  135. package/dist/core/runner/session-mode-seats.js +73 -0
  136. package/dist/core/runner/session-rule-policy.js +3 -2
  137. package/dist/core/runner/stream-mode-verb.d.ts +27 -0
  138. package/dist/core/runner/stream-mode-verb.js +19 -0
  139. package/dist/core/runner/turn-attachments.d.ts +3 -3
  140. package/dist/core/runner/turn-attachments.js +1 -1
  141. package/dist/core/runner/write-protection-station.d.ts +7 -1
  142. package/dist/core/runner/write-protection-station.js +6 -3
  143. package/dist/core/runner-deps.d.ts +31 -34
  144. package/dist/core/runtime-caps.d.ts +12 -3
  145. package/dist/core/safety-axis-vocab.d.ts +2 -2
  146. package/dist/core/safety-axis-vocab.js +1 -1
  147. package/dist/core/secret-env.d.ts +30 -58
  148. package/dist/core/secret-env.js +149 -586
  149. package/dist/core/sensitive-path-policy.d.ts +4 -2
  150. package/dist/core/sensitive-path-policy.js +41 -31
  151. package/dist/core/store-contracts/checkpoint-store-contract.js +2 -1
  152. package/dist/core/task-event.d.ts +1 -1
  153. package/dist/core/task-result.d.ts +1 -1
  154. package/dist/core/task-spec.d.ts +41 -89
  155. package/dist/core/task-stream.d.ts +16 -0
  156. package/dist/core/terminal-cause.js +1 -0
  157. package/dist/core/tighten-task-spec.d.ts +2 -2
  158. package/dist/core/tighten-task-spec.js +12 -14
  159. package/dist/core/tool-catalog-entries.js +4 -3
  160. package/dist/core/tool-policy.d.ts +84 -30
  161. package/dist/core/tool-policy.js +76 -16
  162. package/dist/core/tool-registry.d.ts +38 -0
  163. package/dist/core/tool-registry.js +25 -1
  164. package/dist/core/tool-roster.d.ts +17 -2
  165. package/dist/core/tool-roster.js +11 -1
  166. package/dist/core/tool-spec.d.ts +8 -9
  167. package/dist/core/trace.d.ts +18 -6
  168. package/dist/core/types.d.ts +2 -1
  169. package/dist/core/wiring-manifest.d.ts +31 -5
  170. package/dist/core/wiring-manifest.js +28 -1
  171. package/dist/core/write-protect.d.ts +11 -1
  172. package/dist/core/write-protect.js +26 -15
  173. package/dist/engine/execution-env/node-execution-env.d.ts +6 -1
  174. package/dist/engine/execution-env/node-execution-env.js +16 -3
  175. package/dist/engine/harness/agent-harness.js +2 -1
  176. package/dist/engine/harness/types.d.ts +6 -7
  177. package/dist/engine/llm/types.d.ts +2 -4
  178. package/dist/engine/loop/types.d.ts +7 -0
  179. package/dist/engine/lsp/node-lsp-manager.js +1 -1
  180. package/dist/index.d.ts +18 -8
  181. package/dist/index.js +15 -6
  182. package/dist/orchestration/workflow-governance.js +1 -1
  183. package/dist/orchestration/workflow-primitives.d.ts +1 -1
  184. package/dist/orchestration/workflow-size-guideline.js +2 -2
  185. package/dist/stores/file/index.d.ts +5 -3
  186. package/dist/stores/file/session-store.d.ts +8 -2
  187. package/dist/stores/file/session-store.js +5 -5
  188. package/dist/tools/artifact/artifact-tool.d.ts +17 -0
  189. package/dist/tools/artifact/artifact-tool.js +16 -1
  190. package/dist/tools/fs/bash-readonly-classifier.d.ts +28 -7
  191. package/dist/tools/fs/bash-readonly-classifier.js +88 -0
  192. package/dist/tools/fs/containment-face.d.ts +9 -3
  193. package/dist/tools/fs/containment-face.js +2 -0
  194. package/dist/tools/fs/file-read-check.d.ts +50 -0
  195. package/dist/tools/fs/file-read-check.js +79 -0
  196. package/dist/tools/fs/fs-bash.d.ts +3 -3
  197. package/dist/tools/fs/fs-read.d.ts +1 -0
  198. package/dist/tools/fs/fs-search-tools.d.ts +2 -2
  199. package/dist/tools/fs/fs-search-tools.js +4 -4
  200. package/dist/tools/fs/fs-shared.js +20 -6
  201. package/dist/tools/fs/fs-write.d.ts +4 -3
  202. package/dist/tools/fs/fs-write.js +9 -9
  203. package/dist/tools/fs/index.d.ts +39 -3
  204. package/dist/tools/fs/index.js +38 -15
  205. package/dist/tools/fs/read-deny-home.d.ts +93 -0
  206. package/dist/tools/fs/read-deny-home.js +225 -0
  207. package/dist/tools/fs/read-deny.d.ts +176 -34
  208. package/dist/tools/fs/read-deny.js +268 -61
  209. package/dist/tools/fs/safety.d.ts +6 -1
  210. package/dist/tools/fs/safety.js +18 -5
  211. package/dist/tools/fs/search.d.ts +3 -0
  212. package/dist/tools/fs/search.js +47 -9
  213. package/dist/tools/fs/shell-read-check.d.ts +52 -13
  214. package/dist/tools/fs/shell-read-check.js +199 -20
  215. package/dist/tools/fs/shell-read-establish.d.ts +7 -3
  216. package/dist/tools/fs/shell-read-establish.js +134 -21
  217. package/dist/tools/fs/shell-read-identity.d.ts +7 -0
  218. package/dist/tools/fs/shell-read-identity.js +21 -0
  219. package/dist/tools/fs/shell-read-judge.d.ts +92 -32
  220. package/dist/tools/fs/shell-read-judge.js +43 -18
  221. package/dist/tools/fs/shell-read-plan.d.ts +4 -0
  222. package/dist/tools/fs/shell-read-plan.js +26 -4
  223. package/dist/tools/fs/shell-read-write-targets.d.ts +73 -0
  224. package/dist/tools/fs/shell-read-write-targets.js +173 -0
  225. package/package.json +1 -1
  226. package/test/export-surface.snapshot.json +117 -11
  227. package/wire-changes/core@7.34.0.json +2621 -0
  228. package/wire-changes/core@7.35.0.json +584 -0
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The ORIGIN of a surviving `ask` — WHICH AUTHORITY raised it, or took it over — as one word from a
3
- * closed set, and the per-lane tables that say what an automatic decider may do with an ask of that
4
- * origin.
3
+ * closed set; and, below it, the ask's CLASS SET, the mode × class arbitration table and the one predicate a
4
+ * permission mode is read through.
5
5
  *
6
6
  * Why an axis of its own. The tool gate has several automatic ask-resolution lanes (the auto-mode
7
7
  * classifier today; the persisted-rule lane and the sandbox-admission leg are the same shape), and each
@@ -12,11 +12,11 @@
12
12
  * one was a silent loosening (the new ask fell into whichever lane nobody had excluded it from).
13
13
  *
14
14
  * The replacement: the gate derives the origin ONCE from the facts its layers established
15
- * ({@link askOriginOf}), stamps it on the surviving ask, and each lane asks one question — "may this
16
- * lane answer an ask of this origin?" — against a table that MUST name every member of the set
17
- * ({@link AssertAllKeysHandled}). Adding a kind of ask is then: one member here, one arm in the
18
- * derivation, one row per table — and the compiler refuses the build until the row exists, so the
19
- * default for an unconsidered origin is a red build, never a silent allow.
15
+ * ({@link askOriginOf}) and stamps it on the surviving ask as the DISCLOSED word; the lanes read the ask's
16
+ * class SET ({@link classifyAsk}) folded onto one row of a table that MUST name every class
17
+ * ({@link MODE_ARBITRATION}, fenced by {@link AssertAllKeysHandled}). Adding a kind of ask is then: one
18
+ * class here, one arm in the derivation, one row in the table — and the compiler refuses the build until
19
+ * the row exists, so the default for an unconsidered class is a red build, never a silent allow.
20
20
  *
21
21
  * What is and is not an origin. An origin is WHO raised the question. Two facts that ride beside it
22
22
  * are deliberately not origins: `requiresRealApproval` says what may CLEAR the question (a governance
@@ -42,14 +42,13 @@ import type { PermissionResult } from "./tool-policy.js";
42
42
  * lane may answer it).
43
43
  * - `org_rule` — an organization policy rule asked (or stamped an existing ask): "no configuration
44
44
  * clears this, a person nods".
45
- * - `rule_store_unavailable` — the deployment wired a persisted-rule store and could not READ it for
46
- * this call (a read failure, a timeout), OR could not read the CALL against the person's standing
47
- * deny/ask rows (the tightening lexer's `unreadable` word: an expansion where a rule reads a word, an
48
- * unterminated quote, a syntax error — the answer's `reason`): the person's own deny/ask rows cannot
49
- * be enforced for this call, so it fails closed the way an unreadable org snapshot does — an allow
50
- * tightens to an ask a person must clear, and no automatic lane may answer ("does one of my rules
51
- * forbid this?" is unanswered). One word for both, deliberately: the AUTHORITY semantics (who may
52
- * answer, what clears it, what the evidence records) are identical, and only the mechanism differs.
45
+ * - `rule_store_unavailable` — the person's rule store WAS read, but the CALL could not be read against
46
+ * their standing deny/ask rows (the tightening lexer's `unreadable` word: an expansion where a rule
47
+ * reads a word, an unterminated quote, a syntax error — the answer's `reason`): whether one of those
48
+ * rows forbids this call is unknown, so an allow tightens to an ask a person must clear and no automatic
49
+ * lane may answer. A store that could not be READ is not this word: its rows take no part in the
50
+ * decision (the call is judged as if the person had no persisted rows) and the run carries one
51
+ * `permission.rule_store_unavailable` notice instead.
53
52
  * - `hook` — a deployment's PreToolUse screening face raised or co-raised the ask; the word is
54
53
  * engine-stamped at the fold and is the deployment's own per-call adjudication.
55
54
  * - `ask_rule` — an EXPLICIT `ask` permission rule matched: a person's standing "ask me each time",
@@ -57,7 +56,7 @@ import type { PermissionResult } from "./tool-policy.js";
57
56
  * - `denial_limit_fallback` — the auto-mode classifier reached its denial bound and handed the call
58
57
  * to a person; the classifier stands BEFORE this ask, never after it.
59
58
  * - `shell_gate_tighten` — the gate's own irreversibility tighten raised the ask over a tier the COARSE
60
- * `shellGate` doctrine installed (a shell command under `shellGate: "classify"`/`"always"`), not an
59
+ * shell seat installed (the shape tier on every full shell, or the `shellGate: "always"` floor), not an
61
60
  * explicit per-tool mark. The gate records that its own tighten spoke; a policy stamping
62
61
  * `decisionReason: "safety"` on its own ask does not become one.
63
62
  * - `safety_tighten` — the gate's own post-fold tightens over an EXPLICIT fact of the call: the tool's
@@ -84,23 +83,6 @@ export declare function isAskOrigin(v: unknown): v is AskOrigin;
84
83
  * other direction (a row for a word that is not in the set).
85
84
  */
86
85
  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;
104
86
  /** The facts about one call that only the gate holds — the derivation's inputs beyond the decision
105
87
  * itself. Every member is a plain boolean/word read ONCE by the gate, so the derivation is a pure
106
88
  * function that a test can drive arm by arm. */
@@ -113,10 +95,11 @@ export interface AskOriginFacts {
113
95
  * read-back off the decision (a policy can put `decisionReason: "org_rule"` on its own ask; the
114
96
  * gate's cell cannot be written by a policy). */
115
97
  readonly org: "rule" | "unavailable" | undefined;
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;
98
+ /** The gate's own record of its persisted-rule lane's READ: the store was read, but THIS CALL could not be read
99
+ * against the person's deny/ask rows (the lane's answer carried the lexer's reason) — the origin
100
+ * `rule_store_unavailable`. Absent: the lane read the call, or its store could not be read and its rows took no
101
+ * part. Written only by the gate. */
102
+ readonly ruleCallUnreadable?: boolean;
120
103
  /** Which of the gate's OWN post-fold tightens minted the standing ask, if one did — again the gate's
121
104
  * record of its own layer (a tighten replaces an `allow` wholesale, so at most one fires per pass),
122
105
  * never a read-back of `decisionReason: "safety"` off a decision a policy could have composed. */
@@ -144,7 +127,7 @@ export declare function askOriginOf(decision: Extract<PermissionResult, {
144
127
  * Stamp the ask's origin word — and withdraw the disclosures that speak for the TIGHTEN alone when some
145
128
  * layer above it is the reason this call is being asked about. Today that is one member: the read
146
129
  * boundary's directory offer, whose claim holds only while the tighten is the whole reason. Every higher
147
- * rung is a layer with a reason of its own — a standing `ask` row, an unreadable rule store, an org
130
+ * rung is a layer with a reason of its own — a standing `ask` row, a call unreadable against the rows, an org
148
131
  * verdict, a hook, the denial-limit fallback — which no directory grant answers, so the ask would stand
149
132
  * after the grant and the offer would have promised a clearing it cannot deliver (measured: `cat
150
133
  * <out-of-root>` under a standing `Bash(cat:*)` ask rule offered the directory and kept asking after it).
@@ -222,6 +205,8 @@ export interface RuleClearanceFacts {
222
205
  /** An EXPLICIT `ask` permission rule matched this call (DSL, stamped at the rule policy's three
223
206
  * matched-ask exits — bare, covering and param). */
224
207
  matchedAskRule?: string;
208
+ /** The ask was minted by the deployment's own governance layer (see {@link import("./tool-policy.js").PermissionResult}). */
209
+ authoredBy?: "deployment";
225
210
  /** The engine-stamped probe mandate (the reversibility probe declared this call's demotion
226
211
  * structural — for the built-in shell probe, a read outside the session's allowed directories). */
227
212
  probeMandated?: boolean;
@@ -230,6 +215,9 @@ export interface RuleClearanceFacts {
230
215
  /** The ask is being resolved at an ANCESTOR's frozen approver (the three inherited-lane mint sites
231
216
  * pass it literally) — this task's rule lane never adjudicates it. */
232
217
  ancestorResolved?: boolean;
218
+ /** The classes of the contributors the policy fold carried under this ask (see {@link import("./tool-policy.js").PermissionResult});
219
+ * a member whose row no rule may clear keeps the question a person's. */
220
+ foldedAskClasses?: readonly AskClass[];
233
221
  }
234
222
  /** The ask FACE's mandate members — the bit and its table word, spread at the four mint stations and the
235
223
  * park row. The stations hand it the SAME facts object they hand the rule-offer factory, so the card's word
@@ -239,6 +227,7 @@ export interface RuleClearanceFacts {
239
227
  export declare function askMandateMember(ask: RuleClearanceFacts | undefined): {
240
228
  mandated?: true;
241
229
  mandate?: PersistedRuleMandate;
230
+ authoredBy?: "deployment";
242
231
  };
243
232
  /** The clearance facts of an ask the engine did not construct (a policy's verdict), each member read ONCE into
244
233
  * an engine-owned value — for a station that keeps the answer past its own side effects, where the verdict's
@@ -280,64 +269,13 @@ export declare const ORIGIN_IMPLIES_REAL_APPROVAL: {
280
269
  };
281
270
  /** The fence over the consistency table: `never` while every origin has a row. */
282
271
  export type RealApprovalTableCoversEveryOrigin = AssertAllKeysHandled<Exclude<AskOrigin, keyof typeof ORIGIN_IMPLIES_REAL_APPROVAL>>;
283
- /**
284
- * The auto-mode CLASSIFIER's table: may a live classifier verdict resolve an ask of this origin?
285
- *
286
- * The classifier is the deployment's delegate for CLASSIFY-doctrine hesitation — the `policy` family,
287
- * and ONLY it. Every other origin is a question the classifier is structurally the wrong party to
288
- * answer, each for its own reason (kept beside its row so the reason travels with the fact):
289
- * - `content_question`: a permission decider's verdict is neither an answer nor a park — letting it
290
- * speak would skip the durable mandate, the park and the content route in one step.
291
- * - `ancestor_marked`: a marked call must reach the park with no synchronous decision-maker between.
292
- * - `org_unavailable` / `org_rule`: judgment may clear a `requiresRealApproval` bit a POLICY minted,
293
- * but not the org's — while adjudication is unavailable the org's answer is unknown, and an org
294
- * ask carries the org's own "a person nods" semantic.
295
- * - `rule_store_unavailable`: the person's own deny/ask rows are unreadable — whether one forbids this
296
- * call is unknown, and a classifier verdict would answer that question in the person's stead.
297
- * - `hook`: the deployment's own per-call adjudication; the classifier is its delegate for
298
- * hesitation, not an override for its screening face.
299
- * - `ask_rule`: a person's standing "ask me each time" — the classifier answering it would decide
300
- * whether the person is asked at all, which is the rule's whole content.
301
- * - `denial_limit_fallback`: the classifier already spoke (its bound is what minted this ask); an
302
- * allow here would un-say the fallback, a block would count it twice.
303
- * - `shell_gate_tighten` / `safety_tighten`: YES — the engine's own tightens are hesitation the
304
- * deployment armed the classifier to resolve (the classify doctrine's whole point for the shell
305
- * tier; the safety marks make the ask NON-BUDGETABLE at the durable park, a different axis from who
306
- * may answer it live).
307
- * A PROBE mandate riding the same `shell_gate_tighten` word (a read-boundary / out-of-root /
308
- * recursive-read probe verdict, or a probe that did not answer) is NOT this table's to admit: the
309
- * gate's mandate table excludes it at both classifier stations, the way the allow layer
310
- * excludes it from a standing rule. This table says which QUESTIONS are the classifier's; the probe
311
- * words say which asks are nobody's but a person's.
312
- * - `policy`: YES — including a safety policy's `requiresRealApproval` ask (a live verdict is
313
- * judgment, and arming auto mode is the deployment's explicit choice to let the classifier be the
314
- * explicit ask-resolution for those classes).
315
- * Exclusion is skip-not-deny: the ask flows the original chain (park / approver / headless deny) —
316
- * narrower autonomy, never a lost ask.
317
- */
318
- declare const CLASSIFIER_MAY_ANSWER: {
319
- readonly content_question: false;
320
- readonly ancestor_marked: false;
321
- readonly org_unavailable: false;
322
- readonly org_rule: false;
323
- readonly rule_store_unavailable: false;
324
- readonly hook: false;
325
- readonly ask_rule: false;
326
- readonly denial_limit_fallback: false;
327
- readonly shell_gate_tighten: true;
328
- readonly safety_tighten: true;
329
- readonly policy: true;
330
- };
331
- /** The fence over the classifier table: `never` while every origin has a row (pinned by a type test). */
332
- export type ClassifierTableCoversEveryOrigin = AssertAllKeysHandled<Exclude<AskOrigin, keyof typeof CLASSIFIER_MAY_ANSWER>>;
333
- /** Whether the auto-mode classifier may resolve an ask of this origin (see the table's contract). */
334
- export declare function classifierMayAnswer(origin: AskOrigin): boolean;
335
272
  /**
336
273
  * The MANDATE family — the closed set of words for "this ask stands by STRUCTURE, so a standing allow
337
- * rule may not retire it". TWO AXES, not one word each: EVERY member binds the persisted-rule lane
338
- * (membership IS that answer), and the table below says, per word, whether a LIVE decider may answer.
274
+ * rule may not retire it". A DISCLOSURE vocabulary: the word rides the approval card and the park row
275
+ * ({@link persistedRuleMandateOf} picks one), while what a live lane may do with the ask is decided by
276
+ * the ask's CLASS SET ({@link classifyAsk}, {@link MODE_ARBITRATION}) — never by this one word.
339
277
  *
340
- * - `operator_always` — the coarse doctrine's per-call confirmation for shell commands.
278
+ * - `operator_always` — the operator's `always` floor: per-call confirmation for shell commands.
341
279
  * - `tool_marks` — the tool's own egress / irreversibility declaration.
342
280
  * - `probe_mandate` — this call's reversibility probe declared the demotion STRUCTURAL.
343
281
  * - `probe_unanswered` — the probe was consulted and did not answer: the boundary is UNKNOWN.
@@ -350,53 +288,6 @@ export declare const PERSISTED_RULE_MANDATES: readonly ["operator_always", "tool
350
288
  export type PersistedRuleMandate = (typeof PERSISTED_RULE_MANDATES)[number];
351
289
  /** Membership test for {@link PersistedRuleMandate} — the screen a row reader applies to a stored word. */
352
290
  export declare function isPersistedRuleMandate(v: unknown): v is PersistedRuleMandate;
353
- /**
354
- * May a LIVE automatic lane answer an ask carrying this word? (The persisted-rule lane is not among
355
- * them — every word binds it.) TWO COLUMNS, because the two lanes are not asking one question: the
356
- * sandbox-admission leg asks whether CONTAINMENT already holds what this call would do, while the
357
- * classifier asks whether the question itself is one a model verdict may settle. Five of the six words
358
- * happen to answer both the same way today; that is a coincidence of those words, not an invariant, and
359
- * the columns exist so the sixth does not have to lie in one of them. Each row's reason:
360
- * - `write_protection`: yes — upstream parity (that judge runs BEFORE the general allow rules and marks
361
- * its ask classifier-approvable); what is refused is a standing rule answering "may this agent rewrite
362
- * its own configuration?" once, for good.
363
- * - `write_protection_unresolved`: CLASSIFIER no — the table's answer for this call is unknown, and a
364
- * verdict clearing it would answer a question the engine could not put. SANDBOX yes — containment
365
- * holds the effect whether or not the target is on the table, which is the leg's whole doctrine, and
366
- * an isolated environment that cannot resolve a path is the ordinary reason this word appears.
367
- */
368
- declare const MANDATE_LANE_ANSWERS: {
369
- readonly operator_always: {
370
- readonly classifier: true;
371
- readonly sandboxAdmission: true;
372
- };
373
- readonly tool_marks: {
374
- readonly classifier: true;
375
- readonly sandboxAdmission: true;
376
- };
377
- readonly probe_mandate: {
378
- readonly classifier: false;
379
- readonly sandboxAdmission: false;
380
- };
381
- readonly probe_unanswered: {
382
- readonly classifier: false;
383
- readonly sandboxAdmission: false;
384
- };
385
- readonly write_protection: {
386
- readonly classifier: true;
387
- readonly sandboxAdmission: true;
388
- };
389
- readonly write_protection_unresolved: {
390
- readonly classifier: false;
391
- readonly sandboxAdmission: true;
392
- };
393
- };
394
- /** The fence over the mandate table: `never` while every word has a row. */
395
- export type MandateTableCoversEveryMandate = AssertAllKeysHandled<Exclude<PersistedRuleMandate, keyof typeof MANDATE_LANE_ANSWERS>>;
396
- /** Whether the auto-mode CLASSIFIER may answer an ask carrying this word; `undefined` (no mandate) admits it. */
397
- export declare function classifierMayAnswerMandate(mandate: PersistedRuleMandate | undefined): boolean;
398
- /** Whether the SANDBOX-ADMISSION leg may admit an ask carrying this word — the other column. */
399
- export declare function sandboxMayAdmitMandate(mandate: PersistedRuleMandate | undefined): boolean;
400
291
  /** WHY a matching persisted allow rule did not clear the ask, in the sentence a PERSON reads — one row per
401
292
  * word (the ladder this replaces ended in a catch-all arm). Display prose; nothing reads it back to decide. */
402
293
  declare const MANDATE_DISCLOSURE: {
@@ -423,11 +314,11 @@ export declare function mandateDisclosureOf(mandate: PersistedRuleMandate | unde
423
314
  * are properties of the TOOL and are true of every call on the seat, so a mandate that is true of
424
315
  * this one call must not be shadowed by the tier that happens to carry it (#502: the built-in
425
316
  * shell probe raises it for a listed reader naming a path outside the session's roots — a boundary
426
- * the deployment declared, which is exactly what the classify tier alone cannot say);
317
+ * the deployment declared, which is exactly what the shape tier alone cannot say);
427
318
  * · `egress` — the tool's own external-write mark, judged next: it is the tool's declaration even
428
- * when the coarse doctrine also installed a shell tier on the same seat;
429
- * · `shellGated` + tier `"always"` — the operator's per-call confirmation doctrine
430
- * (`"operator_always"`); the shell seat installs `"maybe"` under the off and classify doctrines,
319
+ * when the shell seat also installed a tier on the same name;
320
+ * · `shellGated` + tier `"always"` — the operator's `always` floor, a per-call confirmation
321
+ * (`"operator_always"`); without the floor the shell seat installs the shape tier's `"maybe"`,
431
322
  * and THOSE asks stay the rule lane's home turf (`undefined`) — that is the don't-ask-again main case, and the per-call member
432
323
  * above is deliberately the ONLY thing that carves a mandate out of it;
433
324
  * · a tool's OWN `"always"`/`"maybe"` irreversibility tier without the doctrine (`"tool_marks"`).
@@ -455,8 +346,9 @@ export interface MandateMarks {
455
346
  * {@link import("./types.js").ReversibilityVerdict.mandated}. */
456
347
  probeMandated?: boolean;
457
348
  /** The gate's own record that the write-protection judge covered this call and its table MATCHED
458
- * (`GatePass.writeProtected`, written at the fourth post-fold tighten and there alone). A GATE fact
459
- * like the org words: it rides the pass, not the decision, so no layer outside the engine declares it. */
349
+ * (`GatePass.writeProtected`, written at the fourth post-fold tighten for a write tool's target and by the read station
350
+ * for a shell command's written targets). A GATE fact like the org words: it rides the pass, not the decision, so no
351
+ * layer outside the engine declares it. */
460
352
  writeProtected?: boolean;
461
353
  /** The same record for the judge's other non-clear verdict — consulted, could not RESOLVE the target.
462
354
  * The pair is the write face's twin of `probeMandated` / `probeUnanswered`, mutually exclusive. */
@@ -478,7 +370,7 @@ export interface MandateMarks {
478
370
  * probe judged THIS command not reversible). A policy ask on a shell-gated tool that the doctrine's probe
479
371
  * did not tighten and did not mandate is a plain ask: the tier was the probe's instrument, not a risk
480
372
  * label, and the park stays the budgetable kind. Before this derivation the static tier alone set the bit,
481
- * so every policy ask on Bash under `shellGate:"classify"` parked non-budgetable.
373
+ * so every policy ask on the full shell face parked non-budgetable.
482
374
  *
483
375
  * Deliberately NOT the rule-lane predicate verbatim: a shell tighten's ask is rule-clearable (a person's
484
376
  * past yes to this command shape stands) yet non-budgetable (a budget's mechanical yes is not a person's).
@@ -491,11 +383,344 @@ export declare function safetyAxisOf(marks: MandateMarks & {
491
383
  irreversible: boolean;
492
384
  shell?: boolean;
493
385
  } | undefined;
494
- /** An ASK that carries its probe's mandate — the per-call member the gate stamped (`probeMandated`), read
495
- * through the same family word and lane table, so its three consumers (the inherited classifier station,
496
- * the two ancestor sandbox-admission arms) are one predicate. A word the table ADMITS reads here exactly
497
- * as no mandate does, which is the answer those lanes already gave it. */
498
- export declare function probeMandatedAsk(ask: {
499
- probeMandated?: boolean;
500
- }): boolean;
386
+ /**
387
+ * The permission-mode closed set — the ONE key a caller sets (`TaskSpec.permissionMode`), spelled as the wire and
388
+ * the reference implementation spell it. A root task's absent key reads `default`; a child's absent key inherits
389
+ * its parent's effective mode ({@link clampPermissionMode}).
390
+ */
391
+ export declare const PERMISSION_MODES: readonly ["default", "acceptEdits", "plan", "auto", "bypassPermissions", "dontAsk"];
392
+ export type PermissionMode = (typeof PERMISSION_MODES)[number];
393
+ /** Membership test for {@link PermissionMode} — the word crosses process boundaries (a request body, a checkpoint row). */
394
+ export declare function isPermissionMode(v: unknown): v is PermissionMode;
395
+ /**
396
+ * The reference implementation's mode RANK, used for one thing only: a child's declared mode may not outrank
397
+ * the ceiling its parent hands down (a declaration is adopted iff `rank[declared] <= rank[ceiling]`, and
398
+ * `acceptEdits` / `auto` are incomparable). It is a clamping relation, not a per-class strictness order —
399
+ * `default` and `dontAsk` share a rank, and whether a mode releases a given ask is {@link MODE_ARBITRATION}'s.
400
+ */
401
+ export declare const PERMISSION_MODE_RANK: {
402
+ readonly plan: 0;
403
+ readonly default: 1;
404
+ readonly dontAsk: 1;
405
+ readonly acceptEdits: 2;
406
+ readonly auto: 3;
407
+ readonly bypassPermissions: 4;
408
+ };
409
+ /** The fence over the rank table: `never` while every mode has a rank. */
410
+ export type RankTableCoversEveryMode = AssertAllKeysHandled<Exclude<PermissionMode, keyof typeof PERMISSION_MODE_RANK>>;
411
+ /**
412
+ * Clamp a child's DECLARED mode under its parent's ceiling. An absent declaration inherits the ceiling; a
413
+ * declaration the rank table does not admit under the ceiling is folded back to the ceiling (`clamped: true`
414
+ * — the caller discloses it, never silently). `bypassPermissions` is adopted only under a `bypassPermissions`
415
+ * parent, and the incomparable pair (`acceptEdits` ↔ `auto`) is never adopted across.
416
+ */
417
+ export declare function clampPermissionMode(declared: PermissionMode | undefined, ceiling: PermissionMode): {
418
+ effective: PermissionMode;
419
+ clamped: boolean;
420
+ };
421
+ /** WHO put a tool's egress / irreversibility mark on the seat — the deployment's own declaration (`spec.tools`),
422
+ * a protocol server's self-report (MCP annotations), or the A2A default (every peer skill is an external write). */
423
+ export type ToolMarkSource = "deployment" | "mcp_annotation" | "a2a_default";
424
+ /**
425
+ * The ask CLASS set — WHY a surviving ask exists, as the set of authorities that stand behind it. One ask can
426
+ * belong to several classes at once (a hook door and an org verdict on one call); a class is derived from the
427
+ * FACTS the gate's layers established ({@link classifyAsk}), never from the disclosed `origin` / `mandate`
428
+ * words, which are single-winner projections and hide the members behind them. The array ORDER decides one
429
+ * thing only: which member is the DISCLOSED word (`askClass`) when several hold — the door-before-word,
430
+ * most-immune-first order; every lane reads the folded row ({@link foldArbitrationRow}), never the word.
431
+ */
432
+ export declare const ASK_CLASSES: readonly ["content_question", "hook", "ancestor", "unverifiable_delete", "transcript_write", "org_rule", "governance_unavailable", "rule_unreadable", "ask_rule", "denial_limit_fallback", "operator_forced", "write_protection_unresolved", "probe", "write_protection", "tool_marks_mcp", "tool_marks_a2a", "policy_rra", "artifact_shared_read", "mode", "ordinary"];
433
+ export type AskClass = (typeof ASK_CLASSES)[number];
434
+ /** Membership test for {@link AskClass} — the word crosses the wire on `tool_end.gate.disposition`. */
435
+ export declare function isAskClass(v: unknown): v is AskClass;
436
+ /** The four switches a class carries, one row per class ({@link MODE_ARBITRATION}). */
437
+ export interface ModeArbitrationRow {
438
+ /** The ask still reaches a person under `bypassPermissions` (the reference implementation's `bypassImmune`). */
439
+ readonly bypassImmune: boolean;
440
+ /** The auto-mode classifier may answer it. */
441
+ readonly classifierEligible: boolean;
442
+ /** The sandbox-admission leg may admit it (containment holds the effect). */
443
+ readonly sandboxAdmission: boolean;
444
+ /** A persisted allow rule may clear it. */
445
+ readonly ruleMayClear: boolean;
446
+ /** The reference implementation's rule / safety check answers `ask` for it, so a hook's ask beside it is not the hook's
447
+ * forced decision: the call runs the full permission pipeline (the reference's `hookAskFloor`) — under `dontAsk`, a
448
+ * refusal rather than a person's question. */
449
+ readonly hookAskFloor: boolean;
450
+ }
451
+ /**
452
+ * The mode × class table. `bypassImmune` is the one new column (nothing said it before); the classifier and
453
+ * sandbox columns are the fold of the two former per-word lane tables (only `probe` moved: the classifier may
454
+ * now answer it — the read boundary's unestablishable spelling is fed to it as a deny-table row instead), and
455
+ * `ruleMayClear` restates {@link ruleClearanceOf}'s conclusion per class (a real-approval bit is never rule-clearable).
456
+ * `mode` is the permission mode's OWN question (`plan`'s two sentences, `decisionReason: "mode"`): the reference
457
+ * implementation puts it to a person past every allow rule and never to an automatic lane, and its bypass conversion
458
+ * releases it like any other non-immune ask. `hookAskFloor` marks the classes the reference's rule / safety check answers
459
+ * `ask` for — an ask rule, a question the tool needs a person for, a dangerous removal, a protected or unresolvable write
460
+ * target, the session transcript, another's shared artifact.
461
+ */
462
+ export declare const MODE_ARBITRATION: {
463
+ readonly content_question: {
464
+ readonly bypassImmune: true;
465
+ readonly classifierEligible: false;
466
+ readonly sandboxAdmission: false;
467
+ readonly ruleMayClear: false;
468
+ readonly hookAskFloor: true;
469
+ };
470
+ readonly hook: {
471
+ readonly bypassImmune: true;
472
+ readonly classifierEligible: false;
473
+ readonly sandboxAdmission: false;
474
+ readonly ruleMayClear: false;
475
+ readonly hookAskFloor: false;
476
+ };
477
+ readonly ancestor: {
478
+ readonly bypassImmune: true;
479
+ readonly classifierEligible: false;
480
+ readonly sandboxAdmission: false;
481
+ readonly ruleMayClear: false;
482
+ readonly hookAskFloor: false;
483
+ };
484
+ readonly unverifiable_delete: {
485
+ readonly bypassImmune: true;
486
+ readonly classifierEligible: true;
487
+ readonly sandboxAdmission: false;
488
+ readonly ruleMayClear: false;
489
+ readonly hookAskFloor: true;
490
+ };
491
+ readonly transcript_write: {
492
+ readonly bypassImmune: false;
493
+ readonly classifierEligible: true;
494
+ readonly sandboxAdmission: false;
495
+ readonly ruleMayClear: false;
496
+ readonly hookAskFloor: true;
497
+ };
498
+ readonly org_rule: {
499
+ readonly bypassImmune: true;
500
+ readonly classifierEligible: false;
501
+ readonly sandboxAdmission: false;
502
+ readonly ruleMayClear: false;
503
+ readonly hookAskFloor: false;
504
+ };
505
+ readonly governance_unavailable: {
506
+ readonly bypassImmune: true;
507
+ readonly classifierEligible: false;
508
+ readonly sandboxAdmission: false;
509
+ readonly ruleMayClear: false;
510
+ readonly hookAskFloor: false;
511
+ };
512
+ readonly rule_unreadable: {
513
+ readonly bypassImmune: false;
514
+ readonly classifierEligible: false;
515
+ readonly sandboxAdmission: false;
516
+ readonly ruleMayClear: false;
517
+ readonly hookAskFloor: false;
518
+ };
519
+ readonly ask_rule: {
520
+ readonly bypassImmune: true;
521
+ readonly classifierEligible: false;
522
+ readonly sandboxAdmission: false;
523
+ readonly ruleMayClear: false;
524
+ readonly hookAskFloor: true;
525
+ };
526
+ readonly denial_limit_fallback: {
527
+ readonly bypassImmune: true;
528
+ readonly classifierEligible: false;
529
+ readonly sandboxAdmission: false;
530
+ readonly ruleMayClear: false;
531
+ readonly hookAskFloor: false;
532
+ };
533
+ readonly operator_forced: {
534
+ readonly bypassImmune: true;
535
+ readonly classifierEligible: true;
536
+ readonly sandboxAdmission: true;
537
+ readonly ruleMayClear: false;
538
+ readonly hookAskFloor: false;
539
+ };
540
+ readonly write_protection_unresolved: {
541
+ readonly bypassImmune: true;
542
+ readonly classifierEligible: false;
543
+ readonly sandboxAdmission: true;
544
+ readonly ruleMayClear: false;
545
+ readonly hookAskFloor: true;
546
+ };
547
+ readonly probe: {
548
+ readonly bypassImmune: false;
549
+ readonly classifierEligible: true;
550
+ readonly sandboxAdmission: false;
551
+ readonly ruleMayClear: false;
552
+ readonly hookAskFloor: false;
553
+ };
554
+ readonly write_protection: {
555
+ readonly bypassImmune: false;
556
+ readonly classifierEligible: true;
557
+ readonly sandboxAdmission: true;
558
+ readonly ruleMayClear: false;
559
+ readonly hookAskFloor: true;
560
+ };
561
+ readonly tool_marks_mcp: {
562
+ readonly bypassImmune: false;
563
+ readonly classifierEligible: true;
564
+ readonly sandboxAdmission: true;
565
+ readonly ruleMayClear: false;
566
+ readonly hookAskFloor: false;
567
+ };
568
+ readonly tool_marks_a2a: {
569
+ readonly bypassImmune: false;
570
+ readonly classifierEligible: true;
571
+ readonly sandboxAdmission: true;
572
+ readonly ruleMayClear: false;
573
+ readonly hookAskFloor: false;
574
+ };
575
+ readonly policy_rra: {
576
+ readonly bypassImmune: true;
577
+ readonly classifierEligible: true;
578
+ readonly sandboxAdmission: false;
579
+ readonly ruleMayClear: false;
580
+ readonly hookAskFloor: false;
581
+ };
582
+ readonly artifact_shared_read: {
583
+ readonly bypassImmune: false;
584
+ readonly classifierEligible: false;
585
+ readonly sandboxAdmission: false;
586
+ readonly ruleMayClear: false;
587
+ readonly hookAskFloor: true;
588
+ };
589
+ readonly mode: {
590
+ readonly bypassImmune: false;
591
+ readonly classifierEligible: false;
592
+ readonly sandboxAdmission: false;
593
+ readonly ruleMayClear: false;
594
+ readonly hookAskFloor: false;
595
+ };
596
+ readonly ordinary: {
597
+ readonly bypassImmune: false;
598
+ readonly classifierEligible: true;
599
+ readonly sandboxAdmission: true;
600
+ readonly ruleMayClear: true;
601
+ readonly hookAskFloor: false;
602
+ };
603
+ };
604
+ /** The fence over the arbitration table: `never` while every class has a row. */
605
+ export type ArbitrationTableCoversEveryClass = AssertAllKeysHandled<Exclude<AskClass, keyof typeof MODE_ARBITRATION>>;
606
+ /** The classes whose own mint puts the `requiresRealApproval` bit on the ask — a bit one of them explains is not
607
+ * the bare bit `policy_rra` names. The mark classes (probe / write protection / tool marks / operator forced)
608
+ * mint no bit and explain none. */
609
+ export declare const RRA_EXPLAINERS: ReadonlySet<AskClass>;
610
+ /** The classes a permission mode can RELEASE (the `bypassImmune: false` rows) — the only words that can appear on
611
+ * `GateDisposition.released.askClass`; every other class reaches a person under every mode. */
612
+ export declare const RELEASABLE_ASK_CLASSES: readonly AskClass[];
613
+ /**
614
+ * The facts the class derivation reads beside the decision: the origin facts the gate holds, plus the tool
615
+ * seat's mark PROVENANCE ({@link ToolMarkSource}; a mark with no source reads as the deployment's, fail-closed),
616
+ * the A2A isolation switch (a set switch turns the A2A default into an operator's mandate), and — at an
617
+ * ancestor station — the classes the ancestor's own ask carries.
618
+ */
619
+ export interface AskClassFacts extends AskOriginFacts {
620
+ readonly toolMarkSources?: ReadonlySet<ToolMarkSource>;
621
+ readonly a2aIsolatePeers?: boolean;
622
+ readonly ancestorClasses?: ReadonlySet<AskClass>;
623
+ }
624
+ /** The classification the arbitration reads: the whole set, the disclosed word (the set's first member in
625
+ * {@link ASK_CLASSES} order) and the row folded across the set. */
626
+ export interface AskClassification {
627
+ readonly classes: ReadonlySet<AskClass>;
628
+ readonly askClass: AskClass;
629
+ readonly row: ModeArbitrationRow;
630
+ }
631
+ /**
632
+ * The DECISION half of the class derivation — what ONE ask says about itself through its own members, read
633
+ * per contributing ask at the policy fold so a member the fold does not copy (a guard mark, the unreadable-rule
634
+ * fact) is not lost behind the ask that won the slot. The bare-bit rules are applied over THIS ask's own set:
635
+ * `requiresRealApproval` with no explaining class is `policy_rra`; a self-declared `mandated` with no other
636
+ * class is `operator_forced` (a deployment probe's own mandate, read conservatively). Returns the specific
637
+ * classes only — an empty set is "nothing but hesitation", which the caller reads as `ordinary`.
638
+ */
639
+ export declare function decisionAskClassesOf(d: Extract<PermissionResult, {
640
+ action: "ask";
641
+ }>): Set<AskClass>;
642
+ /** Fold a class set onto one row: `bypassImmune` and `hookAskFloor` by OR (any immune member keeps the ask; any floored
643
+ * member floors a hook's ask), the three permissive switches by AND (one refusing member withholds the lane). An empty
644
+ * set is `ordinary`. */
645
+ export declare function foldArbitrationRow(classes: ReadonlySet<AskClass>): ModeArbitrationRow;
646
+ /**
647
+ * The ONE class derivation: the decision half ({@link decisionAskClassesOf}) joined with the gate's own facts —
648
+ * the question tool, an ancestor's mark, the org layer's two arms, the persisted lane's unreadable call, the tool
649
+ * seat's marks with their provenance, the read probe and the write-protection judge's records — then the bare
650
+ * real-approval rule re-read over the WHOLE set (an org verdict explains a bit the policy did not mint). The
651
+ * derivation reads facts and members, never the `origin` / `mandate` words.
652
+ */
653
+ export declare function classifyAsk(d: Extract<PermissionResult, {
654
+ action: "ask";
655
+ }>, facts: AskClassFacts): AskClassification;
656
+ /** The refusal the model reads when an ask reaches a run with no approver: the reference implementation's sentence
657
+ * (2.1.280) — the call did NOT run because this session has no approval surface — with the run's own fact beside it
658
+ * and the ask's prompt as what was requested. The gate appends the caller-side remedy. */
659
+ export declare function headlessDenialMessage(toolName: string, askMessage: string): string;
660
+ /**
661
+ * The ONE sentence a headless auto-deny (an ask that reached its final deny because no approver is wired) adds
662
+ * after its refusal: the caller-side change that would have let this call run. Read off the effective mode, the
663
+ * ask's folded class row and whether the call is a covered write (the mode write gate's own question):
664
+ * · a class no permission mode releases (`bypassImmune`) — only a person can answer it: wire an approver;
665
+ * · the plan mode's own question (`mode`) — leave plan (steer the mode, or approve the plan) or wire an approver;
666
+ * · the write gate's own ask under `default` / `auto` — `acceptEdits` lets writes inside the working
667
+ * directories through without asking;
668
+ * · the same ask under `acceptEdits` — the target lies outside the working directories: add its directory to
669
+ * `additionalDirectories`;
670
+ * · any other releasable ask — `bypassPermissions` releases it (disclosed on the call).
671
+ * Every arm also names the approver seat. The refusal's tool text and the `delegation.ask_unresolvable` notice
672
+ * both carry this sentence — they call this function, neither spells it.
673
+ */
674
+ export declare function headlessApprovalRemedy(input: {
675
+ readonly mode: PermissionMode | undefined;
676
+ readonly classification: AskClassification | undefined;
677
+ readonly coveredWrite: boolean;
678
+ readonly unplacedOptions?: {
679
+ readonly program: "cp" | "mv";
680
+ };
681
+ }): string;
682
+ /** The reference implementation's sentence (2.1.280) for a `cp` / `mv` the mode will not answer because it carries option
683
+ * words — the approval card's message under `acceptEdits` and the head of the headless remedy. */
684
+ export declare function fileCommandOptionsSentence(program: "cp" | "mv"): string;
685
+ /** What the mode arbitration decided for one surviving ask. `ask` hands it on unchanged (park / approver); `accepted` is
686
+ * the mode answering an ordinary question itself (`acceptEdits` on one of its file commands — an allow of the mode's own
687
+ * policy, like its in-root write gate, and no release: nothing is disclosed as released);
688
+ * `released` is an allow the mode granted (disclosed on `tool_end.gate.disposition.released`); `denied_by_mode`
689
+ * is a refusal the mode made (`deniedBy: "mode"`). */
690
+ export type Arbitration = {
691
+ kind: "ask";
692
+ } | {
693
+ kind: "accepted";
694
+ mode: "acceptEdits";
695
+ } | {
696
+ kind: "released";
697
+ mode: PermissionMode;
698
+ askClass: AskClass;
699
+ classes: readonly AskClass[];
700
+ origin?: AskOrigin;
701
+ mandate?: PersistedRuleMandate;
702
+ reason?: "rule_unreadable";
703
+ } | {
704
+ kind: "denied_by_mode";
705
+ mode: "bypassPermissions" | "dontAsk";
706
+ askClass: AskClass;
707
+ classes: readonly AskClass[];
708
+ };
709
+ /**
710
+ * The ONE mode read point. `dontAsk` refuses every ask but an operator authority's (an org rule, an operator's forced
711
+ * confirmation, unreadable governance — a mode stance may not settle an operator-mandated gate) and a hook's that no
712
+ * member of the set floors (`hookAskFloor`: a hook's ask beside a rule's or a safety check's ask is refused, as the
713
+ * reference's full pipeline refuses it); `bypassPermissions` refuses a write whose protection could not be judged (a person cannot be asked, and
714
+ * releasing would be looser than the allow the judge already refuses), keeps every immune class and releases the
715
+ * rest; `acceptEdits` answers an ORDINARY ask itself on a call the caller vouches is one of the mode's file commands
716
+ * (`call.fileCommand`, `accepted`); `plan`, `default` and `auto` hand every ask on (plan's own questions were raised by
717
+ * its write gate; the reference implementation refuses nothing at this point under plan — auto's classifier reads the
718
+ * row at its own station). Reads the class SET and the folded row — never the disclosed word.
719
+ */
720
+ export declare function arbitrateByMode(mode: PermissionMode, c: AskClassification, disclosure?: {
721
+ origin?: AskOrigin;
722
+ mandate?: PersistedRuleMandate;
723
+ }, call?: {
724
+ readonly fileCommand?: boolean;
725
+ }): Arbitration;
501
726
  export {};