@sema-agent/core 7.24.4 → 7.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -0
- package/dist/agents/peer-session-drain.d.ts +16 -1
- package/dist/agents/peer-session-drain.js +16 -1
- package/dist/agents/send-message-tool.d.ts +10 -2
- package/dist/agents/send-message-tool.js +18 -7
- package/dist/agents/subagent.js +13 -10
- package/dist/core/arg-summary.d.ts +0 -7
- package/dist/core/arg-summary.js +2 -1
- package/dist/core/background-agent-store.d.ts +3 -3
- package/dist/core/checkpoint-store.d.ts +1 -0
- package/dist/core/delegation-frames.d.ts +5 -0
- package/dist/core/gate-fold.js +85 -0
- package/dist/core/gate-lanes.js +23 -1
- package/dist/core/gate-outcome.d.ts +8 -2
- package/dist/core/gate-outcome.js +3 -1
- package/dist/core/hooks.d.ts +29 -0
- package/dist/core/hooks.js +2 -0
- package/dist/core/mailbox-store.d.ts +5 -0
- package/dist/core/mailbox-store.js +1 -1
- package/dist/core/parent-spec-seat.d.ts +7 -1
- package/dist/core/parent-spec-seat.js +2 -0
- package/dist/core/permission-rule-consent.js +29 -47
- package/dist/core/permission-rule-provider.js +4 -3
- package/dist/core/permission-rule-store.d.ts +143 -7
- package/dist/core/permission-rule-store.js +165 -15
- package/dist/core/runner/contracts.d.ts +36 -2
- package/dist/core/runner/gate-exit.d.ts +14 -0
- package/dist/core/runner/gate-exit.js +4 -0
- package/dist/core/runner/prepare-delegation-surface.d.ts +4 -4
- package/dist/core/runner/prepare-delegation-surface.js +2 -1
- package/dist/core/runner/prepare-gate-stations.d.ts +4 -0
- package/dist/core/runner/prepare-gate-stations.js +7 -4
- package/dist/core/runner/prepare-hands-readface.d.ts +8 -4
- package/dist/core/runner/prepare-hands-readface.js +25 -10
- package/dist/core/runner/prepare-inherited-gate.d.ts +23 -0
- package/dist/core/runner/prepare-inherited-gate.js +11 -6
- package/dist/core/runner/prepare-policy-chain.d.ts +15 -1
- package/dist/core/runner/prepare-policy-chain.js +14 -4
- package/dist/core/runner/prepare-suspend-saga.d.ts +5 -2
- package/dist/core/runner/prepare-suspend-saga.js +4 -3
- package/dist/core/runner/prepare-task.js +10 -9
- package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -4
- package/dist/core/runner/prepare-wiring-manifest.js +8 -4
- package/dist/core/runner/resume-apply.js +2 -0
- package/dist/core/runner/run-harness-handlers.js +1 -0
- package/dist/core/runner/run-identity-wiring.d.ts +2 -2
- package/dist/core/runner/run-leg.js +26 -0
- package/dist/core/runner/run-notification-lane.d.ts +2 -2
- package/dist/core/runner/run-notification-lane.js +2 -1
- package/dist/core/runner/run-settle-and-teardown.js +1 -0
- package/dist/core/runner/session-rule-policy.d.ts +3 -4
- package/dist/core/runner/session-rule-policy.js +11 -3
- package/dist/core/session-policy-store.d.ts +27 -3
- package/dist/core/session-policy-store.js +12 -4
- package/dist/core/store-contracts/background-agent-store-contract.js +10 -0
- package/dist/core/store-contracts/peer-directory-contract.d.ts +23 -0
- package/dist/core/store-contracts/peer-directory-contract.js +82 -0
- package/dist/core/task-event.d.ts +6 -0
- package/dist/core/task-notification.d.ts +79 -4
- package/dist/core/task-notification.js +90 -1
- package/dist/core/task-registry-agent.js +1 -2
- package/dist/core/task-registry-monitor.js +2 -1
- package/dist/core/task-registry-shared.d.ts +53 -5
- package/dist/core/task-registry-shared.js +13 -2
- package/dist/core/task-registry.js +8 -5
- package/dist/core/task-spec.d.ts +12 -5
- package/dist/core/tool-catalog-entries.js +1 -0
- package/dist/core/tool-policy.js +30 -23
- package/dist/core/tool-spec.d.ts +1 -1
- package/dist/core/wiring-manifest.d.ts +2 -2
- package/dist/engine/loop/agent-loop.js +1 -1
- package/dist/engine/loop/types.d.ts +4 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +4 -3
- package/dist/prompts/coordinator.d.ts +2 -1
- package/dist/stores/file/adoption/adopt.js +23 -1
- package/dist/stores/file/permission-rule-store.js +3 -1
- package/dist/stores/file/session-policy-store.d.ts +31 -0
- package/dist/stores/file/session-policy-store.js +87 -7
- package/dist/tools/fs/bash-lexer.d.ts +13 -0
- package/dist/tools/fs/bash-lexer.js +61 -0
- package/dist/tools/fs/bash-program-position.d.ts +36 -29
- package/dist/tools/fs/bash-program-position.js +33 -13
- package/dist/tools/fs/bash-readonly-classifier.d.ts +26 -313
- package/dist/tools/fs/bash-readonly-classifier.js +81 -782
- package/dist/tools/fs/fs-bash.d.ts +43 -207
- package/dist/tools/fs/fs-bash.js +20 -341
- package/dist/tools/fs/index.d.ts +12 -13
- package/dist/tools/fs/index.js +3 -4
- package/dist/tools/fs/read-deny.d.ts +25 -0
- package/dist/tools/fs/read-deny.js +19 -0
- package/dist/tools/fs/safety.js +2 -6
- package/dist/tools/fs/shell-read-check.d.ts +99 -0
- package/dist/tools/fs/shell-read-check.js +229 -0
- package/dist/tools/fs/shell-read-establish.d.ts +70 -115
- package/dist/tools/fs/shell-read-establish.js +216 -102
- package/dist/tools/fs/shell-read-judge.d.ts +231 -0
- package/dist/tools/fs/shell-read-judge.js +170 -0
- package/dist/tools/fs/shell-read-plan.d.ts +3 -0
- package/dist/tools/fs/shell-read-plan.js +88 -27
- package/dist/tools/monitor.d.ts +5 -5
- package/dist/tools/monitor.js +3 -5
- package/dist/tools/task-list.d.ts +4 -0
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +19 -3
- package/wire-changes/core@7.25.0.json +671 -0
- package/wire-changes/core@7.25.1.json +64 -0
|
@@ -2,163 +2,32 @@ import type { AgentTool, ExecutionEnv } from "../../internal/harness-types.js";
|
|
|
2
2
|
import { type TaskRegistry } from "../../core/task-registry.js";
|
|
3
3
|
import { type CwdRef } from "./fs-shared.js";
|
|
4
4
|
import type { ReversibilityVerdict } from "../../core/types.js";
|
|
5
|
-
import {
|
|
6
|
-
import { type ShellScanDecline } from "./bash-program-position.js";
|
|
7
|
-
import { type ReadDenyMatcher } from "./read-deny.js";
|
|
5
|
+
import type { ShellReadAdmission } from "./shell-read-check.js";
|
|
8
6
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* The DATA-side residual named above is closed for the read direction: pass `boundary` and a listed
|
|
29
|
-
* reader whose path arguments leave the allowed directories stops being reversible, so the gate asks
|
|
30
|
-
* instead of auto-allowing. Pass it as a FUNCTION wherever the working directory is observable (an
|
|
31
|
-
* in-task `cd` moves the base a relative operand resolves against, and the probe is called per command).
|
|
32
|
-
* Omitted ⇒ name-only classification, exactly as before.
|
|
33
|
-
*
|
|
34
|
-
* The BOUNDED READ-ONLY POLL LOOP arm: a monitoring consumer's whole idiom is `for i in $(seq 1 8);
|
|
35
|
-
* do tail -n 5 x.log; sleep 2; done`, which the compound face rejects as a class (`for` is not an
|
|
36
|
-
* allowlisted name) — making the classify gate behave like `always` for exactly the tool that polls
|
|
37
|
-
* the most. When the plain face rejects, the probe consults
|
|
38
|
-
* {@link classifyBoundedReadonlyPollLoop} — a narrow exact grammar (literal bound, `;`-separated
|
|
39
|
-
* allowlisted readers + literal `sleep`, the same read boundary, everything else banned; the full
|
|
40
|
-
* safety argument lives on that function). Additive by construction: the plain verdict is tried
|
|
41
|
-
* first and is never overridden.
|
|
42
|
-
*
|
|
43
|
-
* The RECURSIVE-READ demotion returns a STRUCTURED cause alongside the verdict. That
|
|
44
|
-
* demotion is the one arm whose reason is genuinely unrecoverable downstream: a recursive read is
|
|
45
|
-
* refused for what the traversal REACHES, and the reached set is by definition not in the command text
|
|
46
|
-
* an approval card shows. The cause is minted from the SAME classification pass that produced the
|
|
47
|
-
* verdict, so nothing re-parses the command to recover it.
|
|
48
|
-
*
|
|
49
|
-
* It is a `cause` (code + operand arrays), not a `reason` sentence, and that is a correction rather than
|
|
50
|
-
* a preference: every sentence tried here was true of one call and false of another — "a recursive read
|
|
51
|
-
* of X" is false for the zero-operand over-fire, "operand the check treated as a root" is false when the
|
|
52
|
-
* check SYNTHESIZES the root, and any of them, flattened into one length-capped string, silently dropped
|
|
53
|
-
* whichever family sorted last. The consumer now writes the sentence, from a code that cannot go stale
|
|
54
|
-
* and arrays that cannot be truncated into a lie.
|
|
55
|
-
*
|
|
56
|
-
* The other non-reversible arms stay bare on purpose — their cause is legible in the command itself (a
|
|
57
|
-
* write verb, a pipe, an unlisted name), and manufacturing an account for them would put text on a card
|
|
58
|
-
* that adds nothing the reader cannot already see.
|
|
59
|
-
*
|
|
60
|
-
* What the boundary half of this probe is — and what it is not — is stated once on the seat that owns it
|
|
61
|
-
* ({@link bashReadBoundaryProbe}, `@contract shell.read_boundary.friction_floor`); composing it with the
|
|
62
|
-
* shape classifier here changes what happens to the residual shell risk, never that reading.
|
|
63
|
-
*/
|
|
64
|
-
export declare function bashReversibilityProbe(allow?: readonly string[], boundary?: BashReadonlyRootBoundary | (() => BashReadonlyRootBoundary | undefined)): (args: unknown) => ReversibilityVerdict;
|
|
65
|
-
/**
|
|
66
|
-
* ONE rule, TWO TABLES: which {@link ShellScanDecline} a SEAT reads as read evidence. A decline names no word,
|
|
67
|
-
* so it is never the boundary DECLARING anything about a path.
|
|
68
|
-
*
|
|
69
|
-
* BOTH tables are ROW-PER-MEMBER objects behind a compile-time fence ({@link BOUNDARY_SEAT_READS_DECLINE} /
|
|
70
|
-
* {@link CLASSIFY_SEAT_READS_DECLINE}); the sets below are DERIVED from those rows and the ARGUMENT for the
|
|
71
|
-
* rows is this block. "Empty by the argument" is a row saying `false`, not a literal nobody can judge.
|
|
72
|
-
*
|
|
73
|
-
* The READ-BOUNDARY seat is what the default/off doctrine and a bypass mode mount ALONE: there "not mandated"
|
|
74
|
-
* is VOUCHED, so a decline must count as evidence or a read nobody judged runs silently (`<out-of-root> |
|
|
75
|
-
* xargs cat` at zero asks — a closed P0). It keeps both. The CLASSIFY seat composes the same boundary with the
|
|
76
|
-
* SHAPE classifier, which refuses every one of these shapes: what survives is a CARD, and the only question
|
|
77
|
-
* this table answers is who may retire it. It keeps NEITHER — an ANSWERER may (a person, the auto-mode
|
|
78
|
-
* classifier, a person's stored allow rule) — empty by the argument, not by omission.
|
|
79
|
-
*
|
|
80
|
-
* WHAT AN EMPTY TABLE DOES NOT BUY, corrected where it was once claimed: "the shape classifier refuses these
|
|
81
|
-
* shapes anyway, so the only question left is the stored answer" was true of the PROBE and false of the OUTCOME
|
|
82
|
-
* — the allow layer's other members are not that classifier, and both cleared exactly these cards at ZERO asks. An
|
|
83
|
-
* empty table says only "no MANDATE HERE"; that the boundary DECLINED is a separate fact, carried on every ask this
|
|
84
|
-
* seat raises ({@link BoundaryAnswer}'s weaker rung), standing every ANSWERLESS arm down while every answerer's lane stays open.
|
|
85
|
-
* THE COST, stated rather than mitigated: once that ask is retired BY AN ANSWERER, an out-of-root or deny-listed
|
|
86
|
-
* read HIDDEN inside such a command is not asked again. A command's words are not the argv its programs receive (a
|
|
87
|
-
* stream is re-split by its consumer, an unread option may move the working directory first, stdin text is a
|
|
88
|
-
* command line nobody parsed), so a scan of them cannot be the guarantee it was claimed to be. "A read the boundary
|
|
89
|
-
* objects to is never retired by a stored rule" does NOT hold on the classify seat for this class, and holds
|
|
90
|
-
* unchanged elsewhere. One word-level check survives on both seats and is not part of the trade: a token the scan
|
|
91
|
-
* DID read naming a path outside the roots still gates the call ({@link classifyOutOfRootReadGate}).
|
|
7
|
+
* The classify doctrine's SHAPE classifier for the `bash` tool, exposed as a `ToolSpec.reversibilityProbe`
|
|
8
|
+
* (the "maybe" tier's probe under `shellGate:"classify"`). A command is reversible ONLY if every connected
|
|
9
|
+
* segment is a bare command whose program is on the reversible allowlist (default
|
|
10
|
+
* {@link bashClassifyDefaultAllow} — curated to commands with NO write/mutation mode under ANY args) and whose
|
|
11
|
+
* SHAPE the compound classifier accepts (no redirects, substitutions, subshells, escapes or backgrounding; no
|
|
12
|
+
* blocking stdin read, follow mode or device read; a guarded verb form in its safe spelling) — or a bounded
|
|
13
|
+
* read-only poll loop of such commands ({@link classifyBoundedReadonlyPollLoop}). EVERYTHING else — a write
|
|
14
|
+
* command, an egress command, an operator, a path-prefixed or env-assigned command, a backgrounded call, a
|
|
15
|
+
* non-string arg — is NOT reversible → the gate tightens a surviving allow to an ordinary ask. Fail-closed by
|
|
16
|
+
* construction: the allowlist is the only path to `reversible: true`.
|
|
17
|
+
*
|
|
18
|
+
* WHERE a command reads is not this probe's question. The read boundary — deny rows, containment, symlinks,
|
|
19
|
+
* patterns, traversals, the working directory a `cd` moves — is the gate's shell READ STATION
|
|
20
|
+
* (`shell-read-check.ts`), judged on every shell call under every doctrine, ahead of this probe; a call the
|
|
21
|
+
* station refused never reaches it, and a call the station asks about is asked about whatever this probe
|
|
22
|
+
* says. `boundary` supplies only the environment's declared home, so the `$HOME`/`~` spellings fold here the
|
|
23
|
+
* way the station folds them; nothing else of it is read. A caller-supplied `allow` is honored verbatim, so a
|
|
24
|
+
* narrowed deployment is never widened by the default superset.
|
|
92
25
|
*/
|
|
93
|
-
export declare
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
* primitive, never a raw `slice` (a raw cut leaves half an astral code point on a card and in a durable
|
|
99
|
-
* row). Under a dozen characters the HEAD is taken. */
|
|
100
|
-
export declare function elideMiddle(s: string, budget: number): string;
|
|
101
|
-
/**
|
|
102
|
-
* The READ-BOUNDARY seat of the full shell: a `ToolSpec.reversibilityProbe` that answers exactly ONE
|
|
103
|
-
* question — does the deployment's read boundary object to where this command reads? — and nothing about
|
|
104
|
-
* the command's shape. It is the shell face of the rule every read face obeys: the structured readers
|
|
105
|
-
* (Read/Grep/Glob) refuse a deny-listed or out-of-root target; the shell reader gets a MANDATED ask for the
|
|
106
|
-
* same target. The engine installs it on Bash and Monitor whenever a real writable shell is mounted and the
|
|
107
|
-
* shellGate doctrine adds no residual-risk classifier of its own (`shellGate:"off"`, the default); under
|
|
108
|
-
* `"classify"` the doctrine installs {@link bashReversibilityProbe} instead, which composes THIS judgment
|
|
109
|
-
* with the read-only shape classifier, and under `"always"` the tier itself is the mandate and no probe runs.
|
|
110
|
-
* The boundary is therefore judged under every doctrine; the doctrine decides only what happens to the
|
|
111
|
-
* residual shell risk.
|
|
112
|
-
*
|
|
113
|
-
* The verdict, in the probe vocabulary the gate reads (`reversible` here means "the boundary raised no
|
|
114
|
-
* question — the seat vouches the call may run"):
|
|
115
|
-
* · the boundary DECLARED an objection — a deny-listed operand, a recursive walk under the deny judge, an
|
|
116
|
-
* operand outside the roots — ⇒ `{ reversible: false, mandated: true }` (+ the recursive-reach `cause`);
|
|
117
|
-
* · the boundary could NOT READ where the command reads — an unexpanded glob operand (the compound face
|
|
118
|
-
* reports it as undecided), a `~`-rooted operand under an adapter that declares no home, a working-directory
|
|
119
|
-
* move the walk cannot model — ⇒ `{ reversible: false }` (fail-closed; a plain ask, which a stored allow rule
|
|
120
|
-
* may retire — the seat did not declare anything, it declined to guess). The engine wires the environment's
|
|
121
|
-
* declared home, so `~/x`, `$HOME/x` and `${HOME}/x` RESOLVE and are judged like the absolute spelling;
|
|
122
|
-
* · otherwise ⇒ `{ reversible: true }`. This includes every command whose SHAPE the read faces refuse whole
|
|
123
|
-
* (an unlisted program, a redirection, a substitution, a segment that is not a reader): those shapes carry
|
|
124
|
-
* no read-face verdict, so this seat has no question to ask — the residual is the doctrine's, and under
|
|
125
|
-
* `"off"` the doctrine asks nothing. A listed reader refused for a PER-SEGMENT shape (follow mode, a device,
|
|
126
|
-
* a blocking stdin read) is different: the compound face still walks its operands and carries the boundary's
|
|
127
|
-
* structural findings beside the sentence, so `tail -f <denied>` is the declared ask `cat <denied>` is.
|
|
128
|
-
* `run_in_background` is likewise not this seat's question (it changes WHEN the command runs, never WHERE it
|
|
129
|
-
* reads).
|
|
130
|
-
*
|
|
131
|
-
* Reach = the read faces' reach, and nothing wider: the compound face walks the operands of a command whose
|
|
132
|
-
* every segment is a listed reader, and the bounded poll-loop face walks a loop body of listed readers. A
|
|
133
|
-
* read hidden in a shape the faces refuse whole (`cat x | <unlisted>`, `$(cat x)`, `cat $DIR/x` — a variable other
|
|
134
|
-
* than the home's own deterministic spellings — a launcher `env cat x`, a path-prefixed `/bin/cat x`) is not
|
|
135
|
-
* seen here — deny-listed or out-of-root alike — exactly
|
|
136
|
-
* the shapes the `"classify"` doctrine exists to ask about. The text-level containment gate the classify
|
|
137
|
-
* seat consults on its demotion arms is deliberately not consulted here ({@link boundaryDeclared}: it may
|
|
138
|
-
* add a mandate to an ask, never originate one). The poll-loop face's structured verdict
|
|
139
|
-
* ({@link classifyBoundedReadonlyPollLoopDetailed}) is read the same three ways as the compound face's.
|
|
140
|
-
*
|
|
141
|
-
* The reader set is the engine's classify set ({@link bashClassifyDefaultAllow}) — here it is NOT an
|
|
142
|
-
* auto-allow list but the set of programs whose operands the faces read; a wider set means more reads are
|
|
143
|
-
* judged, never that more runs are vouched.
|
|
144
|
-
*
|
|
145
|
-
* @contract shell.read_boundary.friction_floor — what this seat answers is a question about TEXT: which
|
|
146
|
-
* files the words of a command may name, resolved against the declared roots, the declared home and the
|
|
147
|
-
* observed working directory. It is not a question about what the process will open, and no amount of
|
|
148
|
-
* parsing makes it one. A deployment's containment for what a shell may reach is the `ExecutionEnv` the
|
|
149
|
-
* command runs in (a sandbox, a container, a remote adapter); everything here is the friction floor under
|
|
150
|
-
* that containment — it raises the cost of an accidental or careless read, and it is not a defence against
|
|
151
|
-
* a command written to defeat it. The floor's last cell belongs to the full shell's own execute leg: once
|
|
152
|
-
* the gate has allowed a call and before anything spawns, the candidates this seat accepted are resolved
|
|
153
|
-
* on the filesystem, and a target that leaves the roots only after a symlink is followed is REFUSED —
|
|
154
|
-
* refused rather than asked, because by then the approval step is behind the call (see `createBashTool`'s
|
|
155
|
-
* `readBoundary` option). The leg runs where an environment can resolve a link locally; a remote adapter
|
|
156
|
-
* keeps the textual answer alone. A program FILE named in the slot of a verb this floor has no row for
|
|
157
|
-
* (`awk -f prog.awk`, `jq -f filter.jq`, `python3 script.py`) is judged as the in-root operand it is, and the
|
|
158
|
-
* program inside it is text nobody here parsed — vouched as any in-root operand is, which is the floor's
|
|
159
|
-
* stated reach, not a hole in the sandbox.
|
|
160
|
-
*/
|
|
161
|
-
export declare function bashReadBoundaryProbe(boundary: BashReadonlyRootBoundary | (() => BashReadonlyRootBoundary | undefined)): (args: unknown) => ReversibilityVerdict;
|
|
26
|
+
export declare function bashReversibilityProbe(allow?: readonly string[], boundary?: {
|
|
27
|
+
readonly homeDir?: string;
|
|
28
|
+
} | (() => {
|
|
29
|
+
readonly homeDir?: string;
|
|
30
|
+
} | undefined)): (args: unknown) => ReversibilityVerdict;
|
|
162
31
|
/**
|
|
163
32
|
* The FULL shell's contract id, single-sourced: both shell faces share the wire
|
|
164
33
|
* name "Bash", so this id is the ONE structural discriminator between the write-capable shell and
|
|
@@ -267,16 +136,14 @@ export declare function createBashTool(env: ExecutionEnv, rootCanonical: string,
|
|
|
267
136
|
*/
|
|
268
137
|
additionalRoots?: readonly string[];
|
|
269
138
|
/**
|
|
270
|
-
* The
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
* Absent ⇒ no recheck and no I/O: a deployment with no read boundary declared has no roots for a
|
|
277
|
-
* read to be outside of, exactly as the seat itself reads an absent boundary.
|
|
139
|
+
* The gate's shell read station's pre-spawn ADMISSION (`ShellReadAdmission`, shell-read-check.ts): what
|
|
140
|
+
* this leg runs is what the station judged before approval, and the admission re-establishes the SAME
|
|
141
|
+
* candidates right before the spawn — a symlink re-pointed or a pattern re-matched while the approver
|
|
142
|
+
* was thinking refuses the call instead of running it. It parses nothing and judges no word the
|
|
143
|
+
* station did not. Absent ⇒ no station judged this mount (a library-direct toolkit with no gate):
|
|
144
|
+
* nothing is re-established, and the full shell runs unconfined as it always did.
|
|
278
145
|
*/
|
|
279
|
-
|
|
146
|
+
shellReadAdmission?: ShellReadAdmission;
|
|
280
147
|
/** Override of the `timeout` parameter's DEFAULT budget, in ms — see
|
|
281
148
|
* {@link import("./index.js").HandsToolkitOptions.bashDefaultTimeoutMs} for the resolution
|
|
282
149
|
* contract (options over env over constant; invalid values discarded). */
|
|
@@ -301,46 +168,16 @@ export declare function createBashTool(env: ExecutionEnv, rootCanonical: string,
|
|
|
301
168
|
* Absent ⇒ historic bare tag. */
|
|
302
169
|
reminderMark?: string;
|
|
303
170
|
}): AgentTool;
|
|
304
|
-
type ShellCanonicalRefusal = {
|
|
305
|
-
content: string;
|
|
306
|
-
isError: true;
|
|
307
|
-
details?: unknown;
|
|
308
|
-
};
|
|
309
|
-
/** What a face contributes to the shared refusal cards: the TOOL refusing, and the three prose slots. */
|
|
310
|
-
export interface ShellFaceProse {
|
|
311
|
-
readonly tool: string;
|
|
312
|
-
readonly subject: string;
|
|
313
|
-
readonly verdictPhrase: string;
|
|
314
|
-
readonly note: string;
|
|
315
|
-
}
|
|
316
|
-
export type ShellCanonicalRecheck = (command: string, signal?: AbortSignal) => Promise<ShellCanonicalRefusal | undefined>;
|
|
317
|
-
/**
|
|
318
|
-
* THE execute-time canonical recheck, mounted by every face that spawns a shell command — the full `Bash`
|
|
319
|
-
* tool and `Monitor`, whose approval-time seats judge the WRITTEN spelling while this re-judges where the
|
|
320
|
-
* kernel takes those words. The SAME leg, not a second one; the contract below is the leg's own. */
|
|
321
|
-
export declare function createShellCanonicalRecheck(env: ExecutionEnv, readBoundary: BashReadonlyRootBoundary | (() => BashReadonlyRootBoundary | undefined) | undefined, face?: ShellFaceProse): ShellCanonicalRecheck;
|
|
322
|
-
/** The `Monitor` face's prose — the full shell's with its own tool name: one leg, one finding, two tools. */
|
|
323
|
-
export declare const MONITOR_ESCAPE_PROSE: ShellFaceProse;
|
|
324
171
|
/**
|
|
325
172
|
* `bash_readonly` (effect:read) — a restricted shell for the verifier read-only boundary: a single
|
|
326
173
|
* allowlisted, bare command with no shell operators. effect:read lets it survive the verifier's
|
|
327
174
|
* read-only filter, but it is NOT a policy circumvention — it still goes through the tool-policy gate,
|
|
328
|
-
* because a read can still be a side channel (dumping a secret file). The allowlist is a coarse pre-filter
|
|
329
|
-
* the
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
* feeds an approval gate, so "outside the roots" can become a prompt. This face has no
|
|
335
|
-
* such channel: `effect:"read"` is precisely what lets it run where the write shell may not (the verifier's
|
|
336
|
-
* read-only band), so an out-of-root read here is not something to escalate, it is outside what the tool
|
|
337
|
-
* is. It is refused, fail-closed, before anything executes — including the conservative direction, where
|
|
338
|
-
* the operand cannot be resolved statically (there is nothing to degrade to).
|
|
339
|
-
*
|
|
340
|
-
* The boundary has TWO halves and this face wires both: roots answer WHERE a command may read and the
|
|
341
|
-
* allowlist WHICH verb runs, neither answers WHICH FILES are off the table (a deny row holds INSIDE the
|
|
342
|
-
* roots). The judge is the structured read faces' own, asked at both judging moments; every finding lands
|
|
343
|
-
* on the standing rule above — a demotion here is a refusal.
|
|
175
|
+
* because a read can still be a side channel (dumping a secret file). The allowlist is a coarse pre-filter
|
|
176
|
+
* over the command's SHAPE; WHERE it reads is the gate's shell read station's judgment (`shell-read-check.ts`,
|
|
177
|
+
* the `readonly` seat), which REFUSES a deny-listed read, an out-of-root read and a read it cannot establish
|
|
178
|
+
* — this face has no approval channel to degrade to, so every finding is a refusal, before anything runs.
|
|
179
|
+
* The execute leg judges nothing: it admits what the station established (`shellReadAdmission` re-establishes
|
|
180
|
+
* the same candidates right before the spawn) and runs the command.
|
|
344
181
|
*/
|
|
345
182
|
export declare function createBashReadonlyTool(env: ExecutionEnv, rootCanonical: string, allow: ReadonlySet<string>, opts?: {
|
|
346
183
|
/** Same timeout-cap overrides the full `bash` leg takes — see
|
|
@@ -352,13 +189,12 @@ export declare function createBashReadonlyTool(env: ExecutionEnv, rootCanonical:
|
|
|
352
189
|
/** Structured sink for the timeout-cap discard announcements — same seat the full `bash` leg
|
|
353
190
|
* takes (both foreground legs share the resolver, so both must share the sink). */
|
|
354
191
|
onNotice?: (n: import("../../core/types.js").EngineNotice) => void;
|
|
355
|
-
/** The
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
readDeny?: ReadDenyMatcher;
|
|
192
|
+
/** The gate's shell read station's pre-spawn ADMISSION (`ShellReadAdmission`, shell-read-check.ts): what
|
|
193
|
+
* this leg runs is what the station judged, re-established right before the spawn. Absent ⇒ no station
|
|
194
|
+
* judged this mount (a library-direct toolkit with no gate): this face then confines NOTHING — its
|
|
195
|
+
* containment IS the station, and a consumer mounting it without one must run `runToolGate` with the
|
|
196
|
+
* station's `shellReadCheck` (the Runner does). */
|
|
197
|
+
shellReadAdmission?: ShellReadAdmission;
|
|
362
198
|
/** The run's tool-progress sink — the SAME seat the full shell leg takes, for the same reason its
|
|
363
199
|
* two neighbours above are shared: both foreground legs run through `runShell`, so a long command
|
|
364
200
|
* must breathe on both or a person watching one of them is told nothing. This face has no detach
|