@sema-agent/core 7.15.0 → 7.16.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 +29 -0
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/memory-engine/delegation-settlement.d.ts +37 -12
- package/dist/core/memory-engine/delegation-settlement.js +128 -39
- package/dist/core/memory-engine/engine.d.ts +9 -8
- package/dist/core/memory-engine/engine.js +115 -120
- package/dist/core/memory-engine/file-backend.d.ts +17 -5
- package/dist/core/memory-engine/file-backend.js +78 -34
- package/dist/core/memory-engine/index.d.ts +2 -2
- package/dist/core/memory-engine/index.js +2 -2
- package/dist/core/memory-engine/layout.d.ts +152 -54
- package/dist/core/memory-engine/layout.js +441 -104
- package/dist/core/memory-engine/types.d.ts +8 -3
- package/dist/core/memory-engine/types.js +5 -0
- package/dist/core/runner/abort-race.d.ts +3 -3
- package/dist/core/runner/active-skill-scope.d.ts +2 -2
- package/dist/core/runner/assemble-result.d.ts +29 -29
- package/dist/core/runner/checkpoint-scope.d.ts +4 -4
- package/dist/core/runner/clock-and-limits.d.ts +3 -3
- package/dist/core/runner/compaction-call-options.d.ts +11 -11
- package/dist/core/runner/compaction-knobs.d.ts +4 -4
- package/dist/core/runner/compaction-seams.d.ts +5 -5
- package/dist/core/runner/contracts.d.ts +222 -224
- package/dist/core/runner/decide-continuation.d.ts +6 -6
- package/dist/core/runner/denial-limit-arms.d.ts +8 -8
- package/dist/core/runner/derived-route-fallback.d.ts +2 -2
- package/dist/core/runner/gate-exit.d.ts +6 -6
- package/dist/core/runner/git-status-frame.d.ts +7 -7
- package/dist/core/runner/inherited-ask-grants.d.ts +6 -6
- package/dist/core/runner/memory-capture-optout.d.ts +1 -1
- package/dist/core/runner/memory-consolidation-driver.d.ts +4 -4
- package/dist/core/runner/memory-consolidation.d.ts +6 -6
- package/dist/core/runner/park-commit.d.ts +6 -6
- package/dist/core/runner/permission-rule-lanes.d.ts +19 -19
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +4 -4
- package/dist/core/runner/prepare-ask-lane.d.ts +3 -3
- package/dist/core/runner/prepare-boundary-parks.d.ts +3 -3
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +5 -5
- package/dist/core/runner/prepare-config-doors.d.ts +21 -21
- package/dist/core/runner/prepare-context-lane.d.ts +6 -6
- package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
- package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
- package/dist/core/runner/prepare-file-history.d.ts +2 -2
- package/dist/core/runner/prepare-gate-stations.d.ts +5 -5
- package/dist/core/runner/prepare-hands-readface.d.ts +33 -33
- package/dist/core/runner/prepare-inherited-gate.d.ts +4 -4
- package/dist/core/runner/prepare-listings.d.ts +3 -3
- package/dist/core/runner/prepare-lsp.d.ts +3 -3
- package/dist/core/runner/prepare-memory-engine-session.d.ts +5 -5
- package/dist/core/runner/prepare-memory.js +6 -7
- package/dist/core/runner/prepare-offload-wrappers.d.ts +2 -2
- package/dist/core/runner/prepare-park-ask.d.ts +6 -6
- package/dist/core/runner/prepare-policy-chain.d.ts +4 -4
- package/dist/core/runner/prepare-prompt-inputs.d.ts +5 -5
- package/dist/core/runner/prepare-protocol-tools.d.ts +1 -1
- package/dist/core/runner/prepare-question-face.d.ts +4 -4
- package/dist/core/runner/prepare-run-refs.d.ts +11 -11
- package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
- package/dist/core/runner/prepare-suspend-saga.d.ts +4 -4
- package/dist/core/runner/prepare-task.d.ts +12 -12
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +2 -3
- package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -4
- package/dist/core/runner/prepare-workspace-restore.d.ts +1 -1
- package/dist/core/runner/remote-env-retry.d.ts +3 -3
- package/dist/core/runner/resume-admission.d.ts +1 -1
- package/dist/core/runner/resume-claim.d.ts +1 -1
- package/dist/core/runner/resume-internals-and-config.d.ts +1 -1
- package/dist/core/runner/resume-policy-outcome.d.ts +1 -1
- package/dist/core/runner/resume-preflight.d.ts +1 -1
- package/dist/core/runner/resume-review-outcome.d.ts +1 -1
- package/dist/core/runner/run-brain-sinks.d.ts +1 -1
- package/dist/core/runner/run-clock-and-content.d.ts +4 -4
- package/dist/core/runner/run-compaction-machinery.d.ts +3 -3
- package/dist/core/runner/run-git-lane.d.ts +1 -1
- package/dist/core/runner/run-harness-handlers.d.ts +2 -2
- package/dist/core/runner/run-identity-wiring.d.ts +4 -4
- package/dist/core/runner/run-leg.d.ts +3 -3
- package/dist/core/runner/run-notification-lane.d.ts +2 -2
- package/dist/core/runner/run-reasoning-seat.d.ts +2 -2
- package/dist/core/runner/run-settle-and-teardown.d.ts +4 -4
- package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +2 -2
- package/dist/core/runner/run-terminal-adoption.d.ts +5 -5
- package/dist/core/runner/runtask.d.ts +14 -14
- package/dist/core/runner/session-file-state-replay.d.ts +3 -3
- package/dist/core/runner/session-rule-policy.d.ts +2 -2
- package/dist/core/runner/steer-admission.d.ts +2 -2
- package/dist/core/runner/stream-halt-verbs.d.ts +1 -1
- package/dist/core/runner/stream-reap.d.ts +1 -1
- package/dist/core/runner/synthetic-tools.d.ts +8 -8
- package/dist/core/runner/teardown-bounded.d.ts +2 -2
- package/dist/core/runner/tool-defer-gate.d.ts +1 -1
- package/dist/core/runner/tool-disclosure.d.ts +33 -33
- package/dist/core/runner/tool-end-body.d.ts +3 -3
- package/dist/core/runner/tool-face-overlay.d.ts +2 -2
- package/dist/core/runner/tool-output-projection.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +53 -53
- package/dist/core/runner/usage-accounting.d.ts +4 -4
- package/dist/core/runner/workspace-path.d.ts +1 -1
- package/dist/engine/llm/types.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/tools/fs/bash-readonly-classifier.d.ts +40 -40
- package/dist/tools/fs/encoding.d.ts +31 -40
- package/dist/tools/fs/fs-bash.d.ts +35 -35
- package/dist/tools/fs/fs-pdf.d.ts +8 -8
- package/dist/tools/fs/fs-search-tools.d.ts +4 -4
- package/dist/tools/fs/fs-shared.d.ts +144 -158
- package/dist/tools/fs/fs-write.d.ts +8 -8
- package/dist/tools/fs/gh-rate-limit.d.ts +13 -14
- package/dist/tools/fs/index.d.ts +74 -78
- package/dist/tools/fs/notebook.d.ts +24 -25
- package/dist/tools/fs/pdf.d.ts +3 -3
- package/dist/tools/fs/read-deny.d.ts +22 -22
- package/dist/tools/fs/read-face.d.ts +21 -24
- package/dist/tools/fs/repo-map.d.ts +8 -8
- package/dist/tools/fs/safety.d.ts +116 -129
- package/dist/tools/fs/search.d.ts +63 -71
- package/package.json +5 -2
- package/test/export-surface.snapshot.json +5 -1
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Bare command names `bash_readonly` permits out of the box, ALSO the default reversible set for the
|
|
3
|
-
*
|
|
3
|
+
* The {@link import("./fs-bash.js").bashReversibilityProbe} classifier. **Coarse first filter, NOT a security
|
|
4
4
|
* boundary**: {@link coarseReadonlyCheck} matches only the command NAME, so a listed command with a
|
|
5
5
|
* writing flag (e.g. `find -delete`, `sort -o`, `tee`) would still write. Such commands are therefore
|
|
6
6
|
* kept OFF this default — the list is curated to commands with NO write/mutation mode under ANY args, so
|
|
7
7
|
* the `effect:"read"` declaration (relied on by wake/resume reconcile + the verifier read-only boundary)
|
|
8
8
|
* AND the classifier's "reversible" promise both stay truthful. The deployment's tool-policy gate is the
|
|
9
|
-
* authoritative control (
|
|
9
|
+
* authoritative control (council blocker #1); anything that can mutate state or run arbitrary
|
|
10
10
|
* code belongs on the full `bash` (effect:write, gated), not here. A deployment may widen this list,
|
|
11
11
|
* accepting that responsibility.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
13
|
+
* Deliberately ABSENT: `date` (`-s`/`--set` → CLOCK_SETTIME), `hostname` (`<name>` → kernel
|
|
14
14
|
* hostname), and `file` (`-C -m` → compiles/writes a magic file) were REMOVED — each is read-only by NAME
|
|
15
15
|
* but state-MUTATING with args, which an argv[0]-only filter cannot tell apart. Leaving them in defeated
|
|
16
16
|
* both the `effect:read` truthfulness here and the classifier's irreversibility promise (a `date -s` would
|
|
17
17
|
* auto-allow an irreversible clock jump under `shellGate:"classify"`).
|
|
18
18
|
*
|
|
19
|
-
*
|
|
19
|
+
* Rows 3-4 are the CC-anchored expansion — the members of CC's safe-command
|
|
20
20
|
* set (pretty223.js:420513-420565 `e6s`; identical in the 220 corpus; the 220→245 campaign diff records
|
|
21
21
|
* no change on this face) that satisfy THIS list's curation bar (no write/mutation mode under any args)
|
|
22
22
|
* without new stdin-floor/option-value modeling: pure status/computation printers (`cal`…`sleep` — none
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* `uniq` (second positional is an OUTPUT file; CC allows a flags-only regex form this filter cannot
|
|
28
28
|
* express), `printf` (builtin `-v var` assigns), `find` (CC allows only a regex excluding
|
|
29
29
|
* `-delete`/`-exec`/…), and the bare-stdin text filters (`od`/`strings`/`nl`/`tsort`/`pr`/…) whose
|
|
30
|
-
* value-taking options defeat the stdin-floor operand count without a per-verb option-value model
|
|
30
|
+
* value-taking options defeat the stdin-floor operand count without a per-verb option-value model
|
|
31
31
|
* — those are a follow-on slice, not a silent drop.
|
|
32
32
|
*/
|
|
33
33
|
/** The verdict every unresolvable / out-of-root / unbounded finding ends on. The findings differ in what
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
export declare const NOT_AUTO_ALLOWED = "\u2014 not auto-allowed";
|
|
36
36
|
export declare const BASH_READONLY_DEFAULT_ALLOW: readonly string[];
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
38
|
+
* The CLASSIFY face's default allow set: the shared list PLUS the verbs that are
|
|
39
39
|
* admissible only where the compound classifier's per-verb judgment runs, and NOT on the shared list's
|
|
40
40
|
* other consumer faces:
|
|
41
41
|
* · `find` — read-only only when no CC `aCy` dangerous predicate token is present (guard arm);
|
|
@@ -123,13 +123,13 @@ export declare function parseLeadingCommandName(command: string, options?: Leadi
|
|
|
123
123
|
* with no shell operators. It validates the NAME only (+ blocks operators/path-prefix/env-assignment); it
|
|
124
124
|
* does NOT inspect arguments for write flags — keeping the allowlist free of write-capable commands and
|
|
125
125
|
* the policy gate are what make `effect:"read"` truthful. Returns a reason when rejected, else undefined.
|
|
126
|
-
*
|
|
126
|
+
* This `effect:"read"` DECLARATION face deliberately stays strict-single-command; only the
|
|
127
127
|
* classify face ({@link classifyCompoundReadonly} via {@link import("./fs-bash.js").bashReversibilityProbe}) segments compounds. */
|
|
128
128
|
export declare function coarseReadonlyCheck(command: string, allow: ReadonlySet<string>, options?: LeadingCommandNameOptions): string | undefined;
|
|
129
129
|
/**
|
|
130
130
|
* Does this text carry a bare redirection operator — the ONE metacharacter family
|
|
131
|
-
* {@link splitShellCompoundSegments} can be asked to tolerate at its whole-string gate
|
|
132
|
-
* `redirection: "tolerate"`)?
|
|
131
|
+
* {@link splitShellCompoundSegments} can be asked to tolerate at its whole-string gate
|
|
132
|
+
* (`redirection: "tolerate"`)?
|
|
133
133
|
*
|
|
134
134
|
* Exported because the tolerating caller owes a PER-SEGMENT judgement in its place, and that judgement
|
|
135
135
|
* must read the same character class this module tolerated — two hand-kept lists would drift, and a
|
|
@@ -162,7 +162,7 @@ export interface ShellCompoundSegments {
|
|
|
162
162
|
* bash's quoted regions and the unquoted connectors are exactly bash's command boundaries. Callers
|
|
163
163
|
* that tolerate a narrow redirection subset (the read-only classify face and its two data-free
|
|
164
164
|
* spellings) remove those words BEFORE calling; nothing here restores them. `redirection:
|
|
165
|
-
* "tolerate"`
|
|
165
|
+
* "tolerate"` narrows this step to {@link rejectedSansRedirection} — the mask argument
|
|
166
166
|
* is untouched (`<`/`>` neither quote nor bound) and the refusal moves to the caller's per-segment
|
|
167
167
|
* vetting via {@link carriesShellRedirection}. The default refuses the whole string as it always did.
|
|
168
168
|
* 2. one trailing `;` is stripped — a no-op terminator, not an empty command. OPTIONAL, because it is
|
|
@@ -189,7 +189,7 @@ export declare function splitShellCompoundSegments(source: string, options?: {
|
|
|
189
189
|
reject: string;
|
|
190
190
|
};
|
|
191
191
|
/**
|
|
192
|
-
*
|
|
192
|
+
* The READ-BOUNDARY face of the read-only classification (opt-in).
|
|
193
193
|
*
|
|
194
194
|
* The allowlist vets `argv[0]` only, so until this face existed every listed reader could name ANY
|
|
195
195
|
* path: `ls /etc` and `cat /etc/passwd` classified read-only, and a deployment whose manual-mode shell
|
|
@@ -198,7 +198,7 @@ export declare function splitShellCompoundSegments(source: string, options?: {
|
|
|
198
198
|
* pretty220 @457568) and renders an approval option naming the directory (@905642 (cli250.js:66007)).
|
|
199
199
|
*
|
|
200
200
|
* Supplying this object turns the check ON; omitting it leaves the classifier byte-identical to its
|
|
201
|
-
*
|
|
201
|
+
* name-only behaviour, so a consumer pinned to an older calling convention is unaffected.
|
|
202
202
|
*/
|
|
203
203
|
export interface BashReadonlyRootBoundary {
|
|
204
204
|
/** Canonical containment roots — the primary root plus any additional allowed directories. An EMPTY
|
|
@@ -213,13 +213,13 @@ export interface BashReadonlyRootBoundary {
|
|
|
213
213
|
* out-of-root signal — the classifier does not know where it points, which is a different verdict
|
|
214
214
|
* from knowing it points outside). */
|
|
215
215
|
homeDir?: string;
|
|
216
|
-
/**
|
|
216
|
+
/** The sensitive-path read deny judge over LEXICALLY RESOLVED operands: a hit
|
|
217
217
|
* demotes the command (ask, never auto-allow), independently of the roots — in-root operands are
|
|
218
218
|
* judged too. Returns the matched pattern, or null. TWO named residuals, both inherited from this
|
|
219
|
-
* classifier's declared purity (synchronous, zero I/O —
|
|
219
|
+
* classifier's declared purity (synchronous, zero I/O — the same scope stated for the
|
|
220
220
|
* containment half): ① operand TARGET matching only — no ancestor intersection: the judge sees
|
|
221
221
|
* the operand's own resolved spelling, never its subtree. The RECURSIVE-reach half of that
|
|
222
|
-
* residual has since been narrowed
|
|
222
|
+
* residual has since been narrowed: a listed recursive/expanding verb's path
|
|
223
223
|
* operand under this wired seat rides {@link CompoundReadonlyVerdict.recursiveReadPaths}
|
|
224
224
|
* (⊂ undecidedPaths), so `grep -r x ~/` no longer auto-allows — it demotes to ask through the
|
|
225
225
|
* undecided contract. What REMAINS of ① is the form table's stated open set (see the KNOWN OPEN
|
|
@@ -230,19 +230,19 @@ export interface BashReadonlyRootBoundary {
|
|
|
230
230
|
* (the enforcing/canonicalizing recheck is the bash_readonly leg's job via checkedPaths; the
|
|
231
231
|
* classify auto-allow lane has no I/O seat by contract). The structured read faces judge BOTH
|
|
232
232
|
* views (canonical + lexical) — this seat is the shell lane's honest-friction floor, not its
|
|
233
|
-
* security boundary
|
|
233
|
+
* security boundary. The `bash_readonly` face deliberately does NOT wire this seat (its
|
|
234
234
|
* roots containment + command allowlist double gate is the deployment's own read-safety
|
|
235
235
|
* declaration — v1 ruling). */
|
|
236
236
|
denyMatch?: (resolvedPath: string) => string | null;
|
|
237
|
-
/**
|
|
237
|
+
/** The resolved read-face containment state. Under "open" the CONTAINMENT half of
|
|
238
238
|
* this boundary is structurally satisfied (an out-of-roots operand is not a demotion; it reports
|
|
239
|
-
* as a checked candidate instead), while the deny half above keeps judging in both faces
|
|
239
|
+
* as a checked candidate instead), while the deny half above keeps judging in both faces.
|
|
240
240
|
* Absent ⇒ "roots" (byte-compat). The `bash_readonly` face never passes this seat — its
|
|
241
241
|
* containment is load-bearing and never opens. */
|
|
242
242
|
face?: "open" | "roots";
|
|
243
243
|
}
|
|
244
244
|
/**
|
|
245
|
-
*
|
|
245
|
+
* The structured verdict of {@link classifyCompoundReadonlyDetailed}. `reason === undefined`
|
|
246
246
|
* is the read-only verdict; everything else is a demotion.
|
|
247
247
|
*/
|
|
248
248
|
export interface CompoundReadonlyVerdict {
|
|
@@ -262,7 +262,7 @@ export interface CompoundReadonlyVerdict {
|
|
|
262
262
|
* tier question, never one the read face itself asked. Structural sibling of `outOfRootRead`. */
|
|
263
263
|
readDenied?: true;
|
|
264
264
|
/**
|
|
265
|
-
*
|
|
265
|
+
* The paths this scan resolved INSIDE the roots (de-duplicated, first-seen order), i.e. the
|
|
266
266
|
* candidates a caller holding a filesystem should re-check with symlinks resolved. Absent when there
|
|
267
267
|
* are none.
|
|
268
268
|
*
|
|
@@ -287,7 +287,7 @@ export interface CompoundReadonlyVerdict {
|
|
|
287
287
|
*/
|
|
288
288
|
checkedPaths?: readonly string[];
|
|
289
289
|
/**
|
|
290
|
-
*
|
|
290
|
+
* Operands whose spelling carries an UNEXPANDED glob (`*`, `?`, `[…]`, unquoted). Lexical
|
|
291
291
|
* containment is not decidable for them: the shell expands the pattern AFTER this verdict is made, and
|
|
292
292
|
* inside a root an expansion can land on a symlink that points out of it (`cat *` where the directory
|
|
293
293
|
* holds a link to an out-of-root file — reproduced end-to-end, not a theoretical shape).
|
|
@@ -333,8 +333,8 @@ export interface CompoundReadonlyVerdict {
|
|
|
333
333
|
recursiveReadPaths?: readonly string[];
|
|
334
334
|
}
|
|
335
335
|
/**
|
|
336
|
-
*
|
|
337
|
-
* the prompt and any other consumer cannot drift apart. Shape follows CC
|
|
336
|
+
* The single minting point for the out-of-root-read approval option text, so a gate rendering
|
|
337
|
+
* the prompt and any other consumer cannot drift apart. Shape follows CC: the option
|
|
338
338
|
* shows the LAST segment of the grantable directory followed by a separator, not the full path.
|
|
339
339
|
*
|
|
340
340
|
* `directory` is the directory to be granted — a caller holding a filesystem (this classifier does not)
|
|
@@ -344,13 +344,13 @@ export interface CompoundReadonlyVerdict {
|
|
|
344
344
|
*/
|
|
345
345
|
export declare function formatOutOfRootReadApprovalOption(directory: string): string;
|
|
346
346
|
/**
|
|
347
|
-
*
|
|
347
|
+
* {@link classifyCompoundReadonly} with the structured verdict. The name/operator/blocking arms
|
|
348
348
|
* run FIRST and unchanged, so an existing demotion keeps its exact reason and never acquires the
|
|
349
349
|
* out-of-root signal; the boundary scan below only ever converts a would-be READ-ONLY verdict into a
|
|
350
|
-
* demotion, which is why omitting `boundary` reproduces the
|
|
350
|
+
* demotion, which is why omitting `boundary` reproduces the name-only behaviour exactly.
|
|
351
351
|
*/
|
|
352
352
|
export declare function classifyCompoundReadonlyDetailed(command: string, allow: ReadonlySet<string>, boundary?: BashReadonlyRootBoundary,
|
|
353
|
-
/**
|
|
353
|
+
/** The poll-loop face passes `iterated:true` over a body REPLICATED
|
|
354
354
|
* `beats` times — a single cd repeated per iteration is a legitimate accumulating shift, not the
|
|
355
355
|
* ">1 cd = ask for clarity" compound CC refuses (a `for` loop is a sema-only face; CC asks for any
|
|
356
356
|
* loop). It suppresses ONLY that multi-cd refuse; every read is still threaded + boundary-judged
|
|
@@ -359,7 +359,7 @@ opts?: {
|
|
|
359
359
|
readonly iterated?: boolean;
|
|
360
360
|
}): CompoundReadonlyVerdict;
|
|
361
361
|
/**
|
|
362
|
-
*
|
|
362
|
+
* The read boundary ALONE, for the `bash_readonly` face.
|
|
363
363
|
*
|
|
364
364
|
* `bash_readonly` declares `effect:"read"` and is admitted by {@link coarseReadonlyCheck}, an argv[0]-NAME
|
|
365
365
|
* filter: path operands were invisible to it, so an allowlisted reader could name any file on the host
|
|
@@ -379,16 +379,16 @@ opts?: {
|
|
|
379
379
|
* kinds — resolved-and-outside (`outOfRootRead`, with `outOfRootPaths`) and could-not-resolve (reason
|
|
380
380
|
* only) — as a refusal; there is nowhere to degrade to.
|
|
381
381
|
*
|
|
382
|
-
* SCOPE OF THE GUARANTEE (
|
|
382
|
+
* SCOPE OF THE GUARANTEE (both directions): "inside the roots" is LEXICAL containment — see
|
|
383
383
|
* {@link resolveOperandLexically}. A symlink inside a root that points out of it reads as in-root here,
|
|
384
384
|
* so this face bounds where a command may NAME a file, not where the kernel will ultimately take it.
|
|
385
|
-
*
|
|
385
|
+
* A deployment that needs filesystem-true containment resolves the operands itself, and this
|
|
386
386
|
* verdict hands it the list to resolve ({@link CompoundReadonlyVerdict.checkedPaths}, on both arms).
|
|
387
387
|
* `createBashReadonlyTool` is that caller for the `bash_readonly` leg and does it on a local env.
|
|
388
388
|
*/
|
|
389
389
|
export declare function classifySimpleCommandReadBoundary(command: string, boundary: BashReadonlyRootBoundary): CompoundReadonlyVerdict;
|
|
390
390
|
/**
|
|
391
|
-
*
|
|
391
|
+
* What {@link classifyOutOfRootReadGate} answers. Two members and one rule between them:
|
|
392
392
|
* `paths` is EVIDENCE for a `gated` answer, never the answer itself. A caller decides on `gated`.
|
|
393
393
|
*/
|
|
394
394
|
export interface OutOfRootReadGateVerdict {
|
|
@@ -404,7 +404,7 @@ export interface OutOfRootReadGateVerdict {
|
|
|
404
404
|
* Exported for that one assertion — production code reads the constant directly. */
|
|
405
405
|
export declare const COMMAND_LAUNCHERS_FOR_TEST: ReadonlySet<string>;
|
|
406
406
|
/**
|
|
407
|
-
*
|
|
407
|
+
* The OUT-OF-ROOT READ GATE asked as its OWN question: does any listed reader in this command
|
|
408
408
|
* name a path outside the allowed directories?
|
|
409
409
|
*
|
|
410
410
|
* {@link classifyCompoundReadonlyDetailed} answers a different question — "is this whole command
|
|
@@ -435,7 +435,7 @@ export declare const COMMAND_LAUNCHERS_FOR_TEST: ReadonlySet<string>;
|
|
|
435
435
|
* unchanged on the full face, and this one keeps answering its own question underneath it.
|
|
436
436
|
* · `face: "open"` is honoured: under the open read face containment is structurally satisfied, an
|
|
437
437
|
* out-of-roots operand is not a finding, and this gate is silent — a full-read deployment sees no
|
|
438
|
-
* gate here, by the same one mechanism
|
|
438
|
+
* gate here, by the same one mechanism the face already defines.
|
|
439
439
|
*
|
|
440
440
|
* Answers `gated` with the resolved paths behind it, and NOT gated for every whole-string refusal (an
|
|
441
441
|
* unparseable grammar, a substitution, a redirection) and for an operand that cannot be resolved
|
|
@@ -456,12 +456,12 @@ export declare const COMMAND_LAUNCHERS_FOR_TEST: ReadonlySet<string>;
|
|
|
456
456
|
*/
|
|
457
457
|
export declare function classifyOutOfRootReadGate(command: string, allow: ReadonlySet<string>, boundary: BashReadonlyRootBoundary): OutOfRootReadGateVerdict;
|
|
458
458
|
/**
|
|
459
|
-
*
|
|
459
|
+
* Compound read-only classification, reason-only face. Returns the demotion reason, or
|
|
460
460
|
* undefined when the command classifies read-only. ⚠️ `undefined` is NOT "safe to auto-execute":
|
|
461
461
|
* the detailed verdict may still carry `undecidedPaths` (operands whose unexpanded spelling — a
|
|
462
462
|
* glob — is what got checked), and this face discards that field. An auto-allow decision must read
|
|
463
463
|
* {@link classifyCompoundReadonlyDetailed} and treat a non-empty `undecidedPaths` as ask — the
|
|
464
|
-
* engine's own probe does exactly that (fs-bash.ts).
|
|
464
|
+
* engine's own probe does exactly that (fs-bash.ts). The optional `boundary`: with it,
|
|
465
465
|
* an allowlisted reader whose path arguments leave the allowed directories is demoted too (use the
|
|
466
466
|
* detailed face when the caller wants to know WHY, e.g. to offer the narrow "allow reading from
|
|
467
467
|
* <dir>" approval); without it the verdict is exactly what it always was.
|
|
@@ -477,7 +477,7 @@ export declare function classifyCompoundReadonly(command: string, allow: Readonl
|
|
|
477
477
|
export declare const POLL_LOOP_MAX_BEATS = 120;
|
|
478
478
|
/**
|
|
479
479
|
* Per-`sleep` cap (seconds) for {@link classifyBoundedReadonlyPollLoop}. A literal `sleep 99999999`
|
|
480
|
-
* is technically bounded but practically a hang — the same hazard class the
|
|
480
|
+
* is technically bounded but practically a hang — the same hazard class the availability arms
|
|
481
481
|
* demote (a green verdict that blocks until the tool timeout is green in name only).
|
|
482
482
|
*/
|
|
483
483
|
export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
|
|
@@ -497,7 +497,7 @@ export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
|
|
|
497
497
|
* maps to a test group in test/poll-loop-classifier.test.ts (G1-G6):
|
|
498
498
|
* G1 BOUNDED TERMINATION. The loop head must be one of three LITERAL forms with a computable
|
|
499
499
|
* iteration count ≤ {@link POLL_LOOP_MAX_BEATS} ({@link pollLoopBeatsOf}); `while`/`until` never
|
|
500
|
-
* match the skeleton. Every body command terminates: non-`sleep` segments inherit the
|
|
500
|
+
* match the skeleton. Every body command terminates: non-`sleep` segments inherit the availability/
|
|
501
501
|
* 108/153 availability arms via {@link classifyCompoundReadonlyDetailed} (blocking stdin, `tail
|
|
502
502
|
* -f`, unbounded devices all reject), and `sleep` must be a literal ≤
|
|
503
503
|
* {@link POLL_LOOP_MAX_SLEEP_SECONDS}. Bounded beats × terminating body ⇒ the loop halts.
|
|
@@ -512,7 +512,7 @@ export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
|
|
|
512
512
|
* the allowlist. Nothing can chain past the vetted segment heads.
|
|
513
513
|
* G4 READ BOUNDARY UNCHANGED. The reassembled body goes through the boundary scan of
|
|
514
514
|
* {@link classifyCompoundReadonlyDetailed} with the caller's boundary — out-of-root operands
|
|
515
|
-
* reject exactly as on the plain face (
|
|
515
|
+
* reject exactly as on the plain face (not relaxed by one rule). STRICTER here: a
|
|
516
516
|
* verdict carrying {@link CompoundReadonlyVerdict.undecidedPaths} (an unexpanded glob) rejects,
|
|
517
517
|
* because the probe face is reason-only and a repeated read of a runtime-decided target must not
|
|
518
518
|
* auto-allow.
|
|
@@ -534,7 +534,7 @@ export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
|
|
|
534
534
|
* so the counter is write-only and inert.
|
|
535
535
|
*
|
|
536
536
|
* ACCEPTED-COST NOTES (the residuals, recorded rather than silently tolerated — same posture as the
|
|
537
|
-
*
|
|
537
|
+
* `head` note above):
|
|
538
538
|
* · `$(seq …)` RESOLVES A COMMAND. This is the ONE command-substitution form the ruling exempts, and
|
|
539
539
|
* it does run whatever `seq` resolves to on PATH (or a shell function/alias of that name). Two
|
|
540
540
|
* facts bound the exposure. FIRST, the trust assumption is ISOMORPHIC to the allowlist itself:
|
|
@@ -547,8 +547,8 @@ export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
|
|
|
547
547
|
* no-egress envelope — every beat still runs allowlisted readers + literal `sleep`), and the
|
|
548
548
|
* walltime axis cascades a hard kill regardless. A deployment wanting NO command-substitution at
|
|
549
549
|
* all can prefer `{<lo>..<hi>}` or a literal list, which bash expands internally with no command
|
|
550
|
-
* run. (
|
|
551
|
-
*
|
|
550
|
+
* run. (The substitution is a flagged, high-severity shape kept per the ruling that names
|
|
551
|
+
* `$(seq <int> <int>)` as the one exemption — recorded for a
|
|
552
552
|
* tightening decision, since the brace form is a drop-in equivalent.)
|
|
553
553
|
* · STDIN-BLOCKING BODY (an availability residual, not a safety one). CLOSED for the shape this note
|
|
554
554
|
* used to record: a quoted multiword operand like `grep "x y"` read, to the then whitespace-blind
|
|
@@ -1,25 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* is lossy:
|
|
2
|
+
* File encoding + line-ending detection for the Read/Edit/Write band, ported from CC's
|
|
3
|
+
* `utils/fileRead.ts` mechanism and hardened where CC is lossy:
|
|
5
4
|
*
|
|
6
|
-
* - BOM detection: `FF FE` → utf16le, `EF BB BF` → utf8-with-BOM, else plain utf8.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* - BOM detection: `FF FE` → utf16le, `EF BB BF` → utf8-with-BOM, else plain utf8. Detection is
|
|
6
|
+
* BOM-only; UTF-16BE / heuristic sniffing is deliberately NOT done — a wrong guess silently
|
|
7
|
+
* corrupts, and the BOM-less case stays a refusal at the Read layer.
|
|
9
8
|
* - The MODEL-FACING text is BOM-stripped and CRLF-normalized (what the model quotes in `old_string`
|
|
10
|
-
* must match what Read showed it).
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* hash coordinate cannot drift apart — an improvement over CC's split, recorded as such rather
|
|
19
|
-
* than claimed as parity.
|
|
20
|
-
* - Write-back re-encodes with the ORIGINAL encoding, PRESERVES the BOM (CC drops it on Write — its
|
|
21
|
-
* lossy face, dynamic-verified W1; we keep it, recorded as a deliberate improvement), and restores
|
|
22
|
-
* the file's dominant line endings for Edit (Write keeps the model's endings as-is, CC decision).
|
|
9
|
+
* must match what Read showed it). CRLF-normalize is parity on both of CC's read lanes; BOM-strip
|
|
10
|
+
* is parity on CC's READ lane only — CC's EDIT/WRITE lane hands the model text with the leading
|
|
11
|
+
* U+FEFF still in it and strips only inside its staleness/hash coordinate. sema strips in ONE
|
|
12
|
+
* shared decoder for every lane, so the model-facing view and the hash coordinate cannot drift
|
|
13
|
+
* apart: a registered delta, not parity.
|
|
14
|
+
* - Write-back re-encodes with the ORIGINAL encoding, PRESERVES the BOM (CC drops it on Write — a
|
|
15
|
+
* registered deliberate improvement), and restores the file's dominant line endings for Edit
|
|
16
|
+
* (Write keeps the model's endings as-is, CC decision).
|
|
23
17
|
*/
|
|
24
18
|
/** Detected byte-level encoding of a text file (BOM-driven; utf8 is the no-BOM default). */
|
|
25
19
|
export interface DetectedFileEncoding {
|
|
@@ -31,19 +25,17 @@ export interface DecodedTextFile {
|
|
|
31
25
|
/** Model-facing text: BOM stripped, `\r\n` normalized to `\n`. The staleness-hash coordinate. */
|
|
32
26
|
text: string;
|
|
33
27
|
encoding: DetectedFileEncoding;
|
|
34
|
-
/** Dominant line ending of the ORIGINAL bytes (majority vote
|
|
28
|
+
/** Dominant line ending of the ORIGINAL bytes (majority vote; CC's counting rule).
|
|
35
29
|
* Deliberately NOT per-line lossless: a mixed-endings file is unified to the dominant ending on
|
|
36
|
-
* the first edit (
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* the
|
|
40
|
-
*
|
|
41
|
-
* the entire file, so sampling a prefix is exactly the case where the cheap answer flips the
|
|
42
|
-
* remaining 99% of the lines. Registered as a deliberate delta, not parity. */
|
|
30
|
+
* the first edit (accepted non-goal — CC behaves the same way).
|
|
31
|
+
* The SAMPLE is a registered delta: CC votes on the first 4096 characters only, while
|
|
32
|
+
* {@link detectLineEndings} below votes on the whole file. The verdict decides what an Edit WRITES
|
|
33
|
+
* BACK across the entire file, so sampling a prefix is exactly the case where the cheap answer
|
|
34
|
+
* flips the remaining 99% of the lines. */
|
|
43
35
|
endings: DetectedLineEndings;
|
|
44
|
-
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
36
|
+
/** A utf16le body with an ODD byte count is TRUNCATED/corrupt — decoding would silently drop the
|
|
37
|
+
* dangling byte and a later write-back would destroy it permanently. Flagged so the tool layer
|
|
38
|
+
* fails closed instead of "repairing" the file. */
|
|
47
39
|
malformed?: true;
|
|
48
40
|
}
|
|
49
41
|
/** BOM-only encoding detection (CC `detectEncodingForResolvedPath` parity — no content heuristics). */
|
|
@@ -56,8 +48,8 @@ export declare function decodeTextBytes(bytes: Uint8Array): DecodedTextFile;
|
|
|
56
48
|
* @param text normalized (`\n`) text when `endings` is CRLF/LF (Edit path — restore the file's
|
|
57
49
|
* dominant endings); pass `endings:"preserve"` to write the text's OWN line endings untouched
|
|
58
50
|
* (Write path — CC decision: the model sent explicit endings in `content` and meant them).
|
|
59
|
-
* @returns a plain string for the no-BOM utf8 + LF-or-preserve fast path
|
|
60
|
-
*
|
|
51
|
+
* @returns a plain string for the no-BOM utf8 + LF-or-preserve fast path, else the exact bytes
|
|
52
|
+
* (BOM + encoded body).
|
|
61
53
|
*/
|
|
62
54
|
export declare function encodeTextForFile(text: string, encoding: DetectedFileEncoding, endings: DetectedLineEndings | "preserve"): string | Uint8Array;
|
|
63
55
|
/** Normalize model-supplied match/replacement text the same way the file text was normalized
|
|
@@ -65,16 +57,15 @@ export declare function encodeTextForFile(text: string, encoding: DetectedFileEn
|
|
|
65
57
|
* Deliberately does NOT strip a leading U+FEFF: an `old_string` starting with one may be quoting
|
|
66
58
|
* genuine file content — use {@link normalizeFileText} only where the string stands for a whole file. */
|
|
67
59
|
export declare function normalizeEditText(s: string): string;
|
|
68
|
-
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* content and must stay. */
|
|
60
|
+
/** Split a leading U+FEFF off MODEL-SUPPLIED whole-file text (CC parity). The BOM is a file-level
|
|
61
|
+
* byte marker, not text: decodeTextBytes strips it on the way in, so it can never live in the
|
|
62
|
+
* normalized coordinate. Only for strings that stand for a WHOLE file (Write `content`,
|
|
63
|
+
* readFileState seeding) — a decoded file text's leading U+FEFF is genuine content and must stay. */
|
|
73
64
|
export declare function splitLeadingBom(text: string): {
|
|
74
65
|
hadBom: boolean;
|
|
75
66
|
text: string;
|
|
76
67
|
};
|
|
77
|
-
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
68
|
+
/** CC parity (BOM-strip + CRLF-normalize): THE coordinate every readFileState hash lives in
|
|
69
|
+
* (Read/Edit/Write staleness all hash `decodeTextBytes(...).text`). A hash taken on raw model content
|
|
70
|
+
* with a leading U+FEFF can never agree with any later re-read. */
|
|
80
71
|
export declare function normalizeFileText(s: string): string;
|
|
@@ -4,11 +4,11 @@ import { type CwdRef } from "./fs-shared.js";
|
|
|
4
4
|
import type { ReversibilityVerdict } from "../../core/types.js";
|
|
5
5
|
import { type BashReadonlyRootBoundary } from "./bash-readonly-classifier.js";
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* A parsed-command classifier for the `bash` tool, exposed as a
|
|
8
8
|
* `ToolSpec.reversibilityProbe`. A full shell is treated as egress+irreversible by DEFAULT; this probe is the
|
|
9
|
-
* "real parsed classifier" that lets a deployment safely auto-allow the provably-benign subset (the
|
|
10
|
-
* doctrine: shell⇒always-gate UNLESS a parsed classifier is wired).
|
|
11
|
-
*
|
|
9
|
+
* "real parsed classifier" that lets a deployment safely auto-allow the provably-benign subset (the
|
|
10
|
+
* doctrine: shell⇒always-gate UNLESS a parsed classifier is wired). It is COMPOUND-aware
|
|
11
|
+
* ({@link classifyCompoundReadonly}): a command is reversible ONLY if every `;`/`&&`/`||`/`|`
|
|
12
12
|
* connected segment is a bare command (no redirects/substitution/subshells/escapes/`&` anywhere — those
|
|
13
13
|
* whole-string reject, so it can't chain to `curl`/`git push`/`rm` or background past TaskStop) whose
|
|
14
14
|
* `argv[0]` is in the reversible allowlist (default
|
|
@@ -23,7 +23,7 @@ import { type BashReadonlyRootBoundary } from "./bash-readonly-classifier.js";
|
|
|
23
23
|
* Wire it on the `bash` tool with `irreversibility: "maybe"` (or via `TaskSpec.shellGate: "classify"`); without
|
|
24
24
|
* a classifier a deployment should mark `bash` `irreversibility: "always"` (`shellGate: "always"`) — fail-closed.
|
|
25
25
|
*
|
|
26
|
-
*
|
|
26
|
+
* The DATA-side residual named above is closed for the read direction: pass `boundary` and a listed
|
|
27
27
|
* reader whose path arguments leave the allowed directories stops being reversible, so the gate asks
|
|
28
28
|
* instead of auto-allowing. Pass it as a FUNCTION wherever the working directory is observable (an
|
|
29
29
|
* in-task `cd` moves the base a relative operand resolves against, and the probe is called per command).
|
|
@@ -38,7 +38,7 @@ import { type BashReadonlyRootBoundary } from "./bash-readonly-classifier.js";
|
|
|
38
38
|
* safety argument lives on that function). Additive by construction: the plain verdict is tried
|
|
39
39
|
* first and is never overridden.
|
|
40
40
|
*
|
|
41
|
-
*
|
|
41
|
+
* The RECURSIVE-READ demotion returns a STRUCTURED cause alongside the verdict. That
|
|
42
42
|
* demotion is the one arm whose reason is genuinely unrecoverable downstream: a recursive read is
|
|
43
43
|
* refused for what the traversal REACHES, and the reached set is by definition not in the command text
|
|
44
44
|
* an approval card shows. The cause is minted from the SAME classification pass that produced the
|
|
@@ -98,7 +98,7 @@ export declare function bashReversibilityProbe(allow?: readonly string[], bounda
|
|
|
98
98
|
*/
|
|
99
99
|
export declare function bashReadBoundaryProbe(boundary: BashReadonlyRootBoundary | (() => BashReadonlyRootBoundary | undefined)): (args: unknown) => ReversibilityVerdict;
|
|
100
100
|
/**
|
|
101
|
-
*
|
|
101
|
+
* The FULL shell's contract id, single-sourced: both shell faces share the wire
|
|
102
102
|
* name "Bash", so this id is the ONE structural discriminator between the write-capable shell and
|
|
103
103
|
* the read-only allowlist face (`core.bash_readonly@1`). Consumed by prepare-task's
|
|
104
104
|
* fullShellReachable roster assertion (its first load-bearing consumer).
|
|
@@ -107,36 +107,36 @@ export { FULL_SHELL_CONTRACT_ID } from "../../core/tool-catalog-entries.js";
|
|
|
107
107
|
/** The CC-verbatim exit-1 interpretation for `command`, or undefined when exit 1 means a real error.
|
|
108
108
|
* Conservative parse: last `;`/`&&`/`||`/newline statement → last `|` pipeline segment → leading
|
|
109
109
|
* command name (env-assignments skipped, path prefix stripped); `git grep`/`git diff` special-cased
|
|
110
|
-
* (CC cLp). Exported for
|
|
110
|
+
* (CC `cLp`). Exported for its unit tests. */
|
|
111
111
|
export declare function bashExitOneInterpretation(command: string): string | undefined;
|
|
112
112
|
export declare function canAutoBackground(command: string, depth?: number): boolean;
|
|
113
113
|
/**
|
|
114
114
|
* `bash` (effect:write) — a full shell. ⚠️ It runs with `rootCanonical` as the initial cwd but is NOT
|
|
115
115
|
* sandboxed: a command can `cd` out, read/write/delete any path the process can reach, and use the
|
|
116
|
-
* network. `rootPath` is a file-tool guard rail, NOT a bash sandbox
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
* persists across calls
|
|
116
|
+
* network. `rootPath` is a file-tool guard rail, NOT a bash sandbox — real isolation is the
|
|
117
|
+
* deployment's job (inject a chroot/container `ExecutionEnv`). Every call still goes through the
|
|
118
|
+
* tool-policy gate, which a multi-tenant deployment MUST wire to constrain it. The cwd
|
|
119
|
+
* persists across calls: a per-task `cwdRef` starts at `rootCanonical` and is updated
|
|
120
120
|
* from the shell's final pwd after each command.
|
|
121
121
|
*/
|
|
122
122
|
export declare function createBashTool(env: ExecutionEnv, rootCanonical: string, coAuthor?: string | false, cwdRef?: CwdRef, taskOpts?: {
|
|
123
123
|
taskRegistry?: TaskRegistry;
|
|
124
124
|
taskOwner?: string;
|
|
125
125
|
taskScope?: string;
|
|
126
|
-
/** (
|
|
126
|
+
/** (mirrors MonitorToolOptions.sessionId): when the task runs INSIDE a session,
|
|
127
127
|
* a background command registers session-resident (owner = sessionId, sessionScoped flag) — it
|
|
128
128
|
* survives the run teardown like CC's bg shells and is reaped at the session terminal. Absent ⇒
|
|
129
129
|
* run-scoped registration exactly as before (killed-with-receipt at teardown). */
|
|
130
130
|
sessionId?: string;
|
|
131
|
-
/**
|
|
131
|
+
/** Completion-notification sink — a finished background command fires ONE
|
|
132
132
|
* task-notification (priority "next": boundary interrupt, CC LocalShellTask posture). */
|
|
133
133
|
onTaskNotification?: (n: import("../../core/task-notification.js").TaskNotificationPayload, opts?: {
|
|
134
134
|
priority?: "now" | "next" | "later";
|
|
135
135
|
}) => void;
|
|
136
|
-
/**
|
|
136
|
+
/** Per-tool-call detach hub — a fired signal adopts the running command as background. */
|
|
137
137
|
detachHub?: import("../../core/tool-detach.js").ToolDetachHub;
|
|
138
138
|
/**
|
|
139
|
-
*
|
|
139
|
+
* EXPLICIT deployment opt-in: on this command's own
|
|
140
140
|
* timeout, an eligible foreground command (see `canAutoBackground`'s own docstring — a
|
|
141
141
|
* DELIBERATELY simplified, narrower-than-CC classifier) is adopted as a background task instead
|
|
142
142
|
* of being killed. Defaults to `false` (the pre-existing, unconditional kill-on-timeout behavior)
|
|
@@ -151,7 +151,7 @@ export declare function createBashTool(env: ExecutionEnv, rootCanonical: string,
|
|
|
151
151
|
*/
|
|
152
152
|
autoBackgroundOnTimeout?: boolean;
|
|
153
153
|
/**
|
|
154
|
-
*
|
|
154
|
+
* Mirrors {@link import("../../core/types.js").TaskSpec.oneShot}: this run has no later
|
|
155
155
|
* turn for an async background notification to land in (a headless `-p` process exits once the
|
|
156
156
|
* turn ends). Branches the background-launch receipt's guidance toward an active block-wait
|
|
157
157
|
* instruction instead of "you will be notified — do not poll", the same failure form
|
|
@@ -160,18 +160,18 @@ export declare function createBashTool(env: ExecutionEnv, rootCanonical: string,
|
|
|
160
160
|
*/
|
|
161
161
|
oneShot?: boolean;
|
|
162
162
|
/**
|
|
163
|
-
*
|
|
163
|
+
* The EXTRA containment roots of the structured file tools (additionalDirectories,
|
|
164
164
|
* canonical) — combined with `rootCanonical` and consulted ONLY for the post-`cd` disclosure
|
|
165
165
|
* note (a committed cwd outside every root gets one trailer line saying the structured tools'
|
|
166
166
|
* relative paths now resolve there and may be refused). Bash itself stays deliberately
|
|
167
167
|
* unconfined; passing this never gates anything.
|
|
168
168
|
*/
|
|
169
169
|
additionalRoots?: readonly string[];
|
|
170
|
-
/**
|
|
170
|
+
/** Override of the `timeout` parameter's DEFAULT budget, in ms — see
|
|
171
171
|
* {@link import("./index.js").HandsToolkitOptions.bashDefaultTimeoutMs} for the resolution
|
|
172
172
|
* contract (options over env over constant; invalid values discarded). */
|
|
173
173
|
bashDefaultTimeoutMs?: number;
|
|
174
|
-
/**
|
|
174
|
+
/** Override of the `timeout` parameter's engine CEILING, in ms — only-widen
|
|
175
175
|
* vs the resolved default; see {@link import("./index.js").HandsToolkitOptions.bashMaxTimeoutMs}. */
|
|
176
176
|
bashMaxTimeoutMs?: number;
|
|
177
177
|
/** Structured sink for this leg's timeout-cap discard announcements — consumed by
|
|
@@ -179,36 +179,36 @@ export declare function createBashTool(env: ExecutionEnv, rootCanonical: string,
|
|
|
179
179
|
* {@link import("./index.js").HandsToolkitOptions.onNotice} for the replace-vs-warn contract). */
|
|
180
180
|
onNotice?: (n: import("../../core/types.js").EngineNotice) => void;
|
|
181
181
|
/**
|
|
182
|
-
*
|
|
182
|
+
* Whether the Monitor tool is on THIS run's roster (the Runner's own mount predicate is
|
|
183
183
|
* `backgroundTaskToolsActive`; it, not this tool, mounts Monitor). Read by the SR-2 gh rate-limit
|
|
184
184
|
* hint, whose closing clause teaches the Monitor tool: `false` ⇒ the clause is dropped (the sleep
|
|
185
185
|
* advice stays), absent/`true` ⇒ historic full wording (a standalone toolkit consumer may well have
|
|
186
186
|
* mounted Monitor itself — the omitted default must not silently rewrite its hint).
|
|
187
187
|
*/
|
|
188
188
|
monitorToolActive?: boolean;
|
|
189
|
-
/**
|
|
189
|
+
/** The session's reminder provenance mark: stamped on the gh rate-limit
|
|
190
190
|
* hint's open tag by the mint home (see {@link import("./index.js").HandsToolkitOptions.reminderMark}).
|
|
191
191
|
* Absent ⇒ historic bare tag. */
|
|
192
192
|
reminderMark?: string;
|
|
193
193
|
}): AgentTool;
|
|
194
194
|
/**
|
|
195
|
-
* `bash_readonly` (effect:read) — a restricted shell for the verifier read-only boundary
|
|
196
|
-
*
|
|
197
|
-
* read-only filter, but it is NOT a policy circumvention — it still goes through the
|
|
198
|
-
* a read can still be a side channel
|
|
195
|
+
* `bash_readonly` (effect:read) — a restricted shell for the verifier read-only boundary: a single
|
|
196
|
+
* allowlisted, bare command with no shell operators. effect:read lets it survive the verifier's
|
|
197
|
+
* read-only filter, but it is NOT a policy circumvention — it still goes through the tool-policy gate,
|
|
198
|
+
* because a read can still be a side channel (dumping a secret file). The allowlist is a coarse pre-filter;
|
|
199
199
|
* the policy gate is the authoritative control.
|
|
200
200
|
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
201
|
+
* Hard refusal, not a demotion: the allowlist vets argv[0] and nothing else, so without a path
|
|
202
|
+
* boundary an allowlisted reader could name ANY file on the host and get it (`cat /etc/passwd` would go
|
|
203
|
+
* straight through). The full `bash` leg carries the same boundary as a DEMOTION — that leg's verdict
|
|
204
|
+
* feeds an approval gate, so "outside the roots" can become a prompt. This face has no
|
|
205
205
|
* such channel: `effect:"read"` is precisely what lets it run where the write shell may not (the verifier's
|
|
206
206
|
* read-only band), so an out-of-root read here is not something to escalate, it is outside what the tool
|
|
207
207
|
* is. It is refused, fail-closed, before anything executes — including the conservative direction, where
|
|
208
208
|
* the operand cannot be resolved statically (there is nothing to degrade to).
|
|
209
209
|
*/
|
|
210
210
|
export declare function createBashReadonlyTool(env: ExecutionEnv, rootCanonical: string, allow: ReadonlySet<string>, opts?: {
|
|
211
|
-
/**
|
|
211
|
+
/** Same timeout-cap overrides the full `bash` leg takes — see
|
|
212
212
|
* {@link import("./index.js").HandsToolkitOptions.bashDefaultTimeoutMs} /
|
|
213
213
|
* {@link import("./index.js").HandsToolkitOptions.bashMaxTimeoutMs} (类修完整域: both foreground
|
|
214
214
|
* legs share runShell's clamp, so both must share the configurable resolution). */
|
|
@@ -217,21 +217,21 @@ export declare function createBashReadonlyTool(env: ExecutionEnv, rootCanonical:
|
|
|
217
217
|
/** Structured sink for the timeout-cap discard announcements — same seat the full `bash` leg
|
|
218
218
|
* takes (both foreground legs share the resolver, so both must share the sink). */
|
|
219
219
|
onNotice?: (n: import("../../core/types.js").EngineNotice) => void;
|
|
220
|
-
/**
|
|
220
|
+
/** The extra containment roots the structured file tools got (the CC `--add-dir` family,
|
|
221
221
|
* canonical). A read this deployment already sanctions for Read/Grep/Glob is equally sanctioned
|
|
222
222
|
* here — the two faces must not disagree about which directories exist for this session. */
|
|
223
223
|
additionalRoots?: readonly string[];
|
|
224
224
|
}): AgentTool;
|
|
225
225
|
/**
|
|
226
|
-
*
|
|
226
|
+
* `TaskOutput` — read a background shell's NEW output
|
|
227
227
|
* since the last call (cursor), by task_id. Optional legacy `filter` regex is applied BEFORE the per-poll truncation so a watched line survives even when it
|
|
228
228
|
* falls in a high-throughput middle window. Untrusted process output is fenced (delimitUntrusted) — observe-only,
|
|
229
229
|
* never re-fed as instructions.
|
|
230
230
|
*/
|
|
231
231
|
export declare function createEnvTaskOutputTool(env: ExecutionEnv): AgentTool;
|
|
232
|
-
/**
|
|
232
|
+
/** `TaskStop` — terminate a background shell by task_id.
|
|
233
233
|
*
|
|
234
|
-
*
|
|
234
|
+
* This band kills ENV-DIRECT (it mounts precisely when the toolkit has
|
|
235
235
|
* no registry — the createHandsToolkit ternary routes registry deployments to createTaskStopTool), so a
|
|
236
236
|
* row for the SAME shell in the process-local {@link defaultTaskRegistry} (a Runner-mounted run sharing
|
|
237
237
|
* this env) used to settle via the watcher's no-claimant floor as stoppedBy:"system". The tool now marks
|