UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

69 lines (68 loc) • 5.47 kB
/** * WRITE TARGETS — which words of a shell segment a program writes, under which names, and at which seat, read off the * plan's text alone (no filesystem): the `>`-family redirections and a `sed` script's `w` files, and the words the * segment's program writes by the program read model's ROLES (`writeReadings`: an operand or option value whose role * writes, the operands an option made edited in place, a copy's destination and its children, an in-place edit's * backups), at the seats the role and the selected options name ({@link WriteSeat}: the directory entry, or where the * path lands). The establisher (`shell-read-establish.ts`) places what this module names; the judge reads the result * on the write face (the write deny rows, then the write roots). No table of programs or options lives here: what a * program writes is its row's. */ import type { ReadCandidate, ShellReadSegment } from "./shell-read-plan.js"; import { type LineDescriptors } from "./shell-read-device.js"; import { type WriteSeat } from "./program-read-model.js"; export type { WriteSeat } from "./program-read-model.js"; /** A word of a program's argv: its raw spelling (the plan's candidates are keyed by it) and its folded spelling. */ export interface ArgWord { readonly raw: string; readonly spelled: string; } /** The words a segment hands its program — the argv after the program word (a launcher's own words are not the program's). */ export declare function programArgs(segment: ShellReadSegment): ArgWord[]; /** * The BACKUP names an in-place `sed` gives the file it knows as `name` — both readings a suffix has: GNU sed replaces every * `*` in the suffix with the name (`bak/*` on `d/f` is `bak/d/f`, `/elsewhere/*` is `/elsewhere/d/f`) and appends a suffix * without one (`d/f.bak`); the BSD and BusyBox seds append the suffix literally (`d/f` + `bak/*`). A name resolves against * the working directory like the operand itself, so a suffix carrying a separator places the backup wherever it points. */ export declare function sedBackupNames(name: string, suffix: string): string[]; /** One candidate handed to the judge. `seats`: where a write target is established ({@link WriteSeat}; absent ⇒ it lands — * every read does). `written`: the seats among `seats` the program itself WRITES the target at (absent ⇒ all of them; * `[]` ⇒ none — a copy's source, judged on the write face as a write path and read by the program); the write guards are * asked about these alone. `child`: a copy's or a move's destination child, written only where the destination is a * directory when the program runs. `followed`: an in-place edit's backup where the operand is edited where it LANDS — its * names are {@link sedBackupNames} of the operand's FOLLOWED name, which only the filesystem answers (the candidate's own * spelling is the operand's as written, the identity the pre-spawn re-check compares). `onlyIfExists`: written only under * SOME implementation's reading of the command, and only by editing an existing file — the program edits nothing that is * not there, so where the filesystem confirms this candidate missing nothing is written (a lexical establishment cannot * confirm it, and keeps the write). */ export interface JudgedCandidate { readonly candidate: ReadCandidate; readonly seats?: readonly WriteSeat[]; readonly written?: readonly WriteSeat[]; readonly child?: true; readonly followed?: { readonly operand: ReadCandidate; readonly suffix: string; }; readonly onlyIfExists?: ReadCandidate; } /** Is any of these words an option word (one starting with `-`)? The reference implementation's reading of a copy or a move: a * command with flags is not one whose paths it can validate (`--target-directory`, `--remove-destination`, a backup suffix * all change what is written where). */ export declare const anyOptionWord: (words: readonly string[]) => boolean; /** * Does this invocation write ONLY standard devices — what the shape tier reads as "writes nothing durable" for a PROGRAM (a * redirection is the reader's own)? Every word any implementation's reading of the row writes ({@link writeReadings}; a word the * reading names written at no seat, a copy's source, is read) is one the program writes THROUGH ({@link writesThrough}) and * is a standard device no redirection of the line rebinds ({@link standardDeviceUnrebound}) — the station's own predicate * (`passesUnasked`) over the same row facts, for the one entry a text-only reader has: `tee /dev/tty`, `cp a.txt /dev/stdout`. * No program is named here: which programs may ask this is the caller's. */ export declare function writesOnlyStandardDevices(program: string, args: readonly string[], line: LineDescriptors): boolean; /** Every candidate a segment hands the judge: its reads minus the write targets, plus its `cd` target (the plan already * lists it among the reads), plus its WRITE targets for the write face ({@link writeTargetsOf}), plus the deny-floor * shadow of every unplaced home word ({@link denyFloorShadowsOf}) on both faces. A word the program only writes keeps * its read copy for the read deny rows alone (`denyOnly`): whether it lands inside the write roots — or cannot be placed * at all — is the write face's question, never a read's. */ export declare function judgedCandidatesOf(segment: ShellReadSegment): readonly JudgedCandidate[];