@sema-agent/core 7.17.5 → 7.17.7

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.
@@ -1,7 +1,7 @@
1
1
  import { emitTrace } from "../trace.js";
2
2
  import { StubExecutionEnv } from "../stub-env.js";
3
3
  import { hasBackgroundShell } from "../background-shell.js";
4
- import { isRemoteExecutionEnv } from "../remote-env.js";
4
+ import { boundaryIsTheSandbox } from "../remote-env.js";
5
5
  import { defaultTaskRegistry } from "../task-registry.js";
6
6
  import { bashReadBoundaryProbe, bashReversibilityProbe, compileReadDeny, createHandsToolkit, deploymentReadFaceClampNotice, pdfModelCapabilitiesOf, resolveReadDenyBuiltins, inheritSessionReadFileState, resolveReadFace, seedReadFileStateFromContext, seedReadFileStateFromTranscript, } from "../../tools/fs/index.js";
7
7
  import { resolveKey, sha256 } from "../../tools/fs/safety.js";
@@ -355,7 +355,7 @@ export async function prepareHandsMount(input) {
355
355
  if (!(executionEnv instanceof StubExecutionEnv) && spec.handsReadOnly !== true) {
356
356
  if (shellGate === "off") {
357
357
  deps.onError?.(new Error(`shell gate doctrine is "off" while a real writable shell (Bash) is mounted — the read boundary is ` +
358
- `still judged on every command (a deny-listed or out-of-root read asks; the ask is mandated${isRemoteExecutionEnv(executionEnv) ? "" : "; a read that only leaves the roots after symlink resolution is refused before it runs"}), but no ` +
358
+ `still judged on every command (a deny-listed or out-of-root read asks; the ask is mandated${boundaryIsTheSandbox(executionEnv) ? "" : "; a read that only leaves the roots after symlink resolution is refused before it runs"}), but no ` +
359
359
  `residual shell-risk classifier is installed: writes, egress and unknown commands are adjudicated by ` +
360
360
  `the ordinary policy/hook chain only. Set spec.shellGate to "classify" or "always" if this deployment ` +
361
361
  `expects doctrine-gated shell behavior.`), { phase: "config", sessionId, classification: "shell-gate-off" });
@@ -327,6 +327,20 @@ export interface CompoundReadonlyVerdict {
327
327
  * and miss the other.
328
328
  */
329
329
  undecidedPaths?: readonly string[];
330
+ /** The KERNEL spellings of the {@link checkedPaths} / {@link undecidedPaths} entries whose operand
331
+ * traverses `..`: the same absolute path, `..` UNCOLLAPSED ({@link OperandSpellings.spelled}). A fold
332
+ * names a different file whenever a parent step follows a symlink — `<root>/link/../x` is
333
+ * `dirname(realpath(link))/x` to the kernel, `<root>/x` to the text. Absent when nothing traverses
334
+ * `..`, and never a replacement: a resolving caller judges these BESIDE the folded entries, list for
335
+ * list. Containment, deny judgment and every `reason` here stay decided on the FOLDED form — this file
336
+ * is zero-I/O, and only a caller holding the filesystem can tell the two apart. */
337
+ checkedSpellings?: readonly string[];
338
+ /** The kernel spellings of {@link undecidedPaths} — see {@link checkedSpellings}. */
339
+ undecidedSpellings?: readonly string[];
340
+ /** The kernel spellings of {@link outOfRootPaths} — see {@link checkedSpellings}. A caller GRANTING
341
+ * anything off a resolved out-of-root path judges this beside it: the two can disagree about whether
342
+ * the target is back inside. */
343
+ outOfRootSpellings?: readonly string[];
330
344
  /**
331
345
  * Operands (written spellings) the walk could NOT resolve at all — a `~user` form, a `~` under no declared
332
346
  * home, an argument the shell rewrites (brace/variable/command expansion), a `cd` target it cannot follow
@@ -401,6 +415,20 @@ export declare function formatOutOfRootReadApprovalOption(directory: string): st
401
415
  * has no filesystem and stays lexical, and a REMOTE env keeps the lexical behaviour (its
402
416
  * `canonicalPath` is an RPC per candidate). */
403
417
  export declare function resolveOperandLexically(base: string | undefined, operand: string, homeDir: string | undefined): string | undefined;
418
+ /** One operand's two absolute spellings. `folded` has its `..` collapsed in the TEXT and is the
419
+ * containment answer — every root comparison, deny judgment and verdict field here is built from it.
420
+ * `spelled` keeps those segments, the walk the KERNEL performs: each prefix resolves (symlinks included)
421
+ * BEFORE a parent step applies, so `<root>/link/../x` names `dirname(realpath(link))/x`. Present ONLY
422
+ * when the operand traverses `..`; a filesystem-resolving caller judges it BESIDE the folded form. */
423
+ export interface OperandSpellings {
424
+ /** The `..`-collapsed absolute path — what containment is decided on. */
425
+ folded: string;
426
+ /** The uncollapsed absolute path, when the operand traverses `..`. */
427
+ spelled?: string;
428
+ }
429
+ /** Resolve one operand into {@link OperandSpellings}, or `undefined` on the same unresolvable operands
430
+ * {@link resolveOperandLexically} reports (it is this function's folded half). */
431
+ export declare function resolveOperandSpellings(base: string | undefined, operand: string, homeDir: string | undefined): OperandSpellings | undefined;
404
432
  /** Whether a command the grammar gate REFUSED WHOLE may READ a file the boundary never judged. The answer is the
405
433
  * complement of a WHITELIST: the command is exempt only when every part of it is a shape the scan fully understands
406
434
  * and none of those shapes reads a file outside the walk's reach — everything else is read evidence, so a token the