Skip to main content

Module pathctx

Module pathctx 

Source
Expand description

The directory context the harness supplies (HP-19): the working directory a command runs in, and the project root. It exists to make relative-path classification honest — cd /etc && echo > ./x must be seen as writing /etc/x, not a worktree file.

The context is ambient for one command evaluation: a single cwd/root pair threads logically through the whole recursive verdict tree (script → pipeline → cmd → redirect → leaf). Rather than add a pass-through parameter to ~15 recursive functions across cst, handlers, and engine, it lives in a scoped thread-local, installed by enter at the top of an evaluation and read at exactly two leaves: legacy is_safe_write_target and engine classify_locus, both via resolve.

Everything is fail-open to today’s behavior: with no cwd/root (or an unresolvable path) resolve returns the path unchanged, so the classifiers behave exactly as before — the signal tightens when present, never a regression when absent.

Structs§

Guard
Restores the previous PathCtx when dropped.
LoopGuard
Pops the loop binding when dropped.
PathCtx
The working directory and project root for the command under evaluation. Both optional: a harness may supply neither (e.g. opencode), and classification falls back to the relative-is-worktree assumption.
StdinReprGuard
VarGuard

Functions§

cwd
The ambient working directory, if known.
enter
Install ctx as the ambient context for the duration of the returned guard; the previous context is restored on drop (panic-safe, so a failing test can’t leak into the next).
enter_cwd
Run f with the ambient cwd temporarily replaced (root unchanged) — used by intra-line cd tracking as it walks a chain’s statements. Restored on drop.
enter_loop_var
Bind loop variable name to its list’s representative items for the duration of the guard (the loop body’s classification). Nested loops stack; the innermost binding of a name wins.
enter_stdin_repr
Bind the representative PATH of the items arriving on stdin, for the duration of the guard — set by the pipeline walker to the previous stage’s output-path locus. An operand-injecting consumer (xargs) reads it so find / | xargs cat gates the injected operand at /, while find ./src | xargs cat gates it at the workspace (mirrors find -exec’s {} binding).
enter_var
Bind name to a CERTAIN literal value (a VAR=/path assignment, or $1 at a function call) for the duration of the guard; consulted by expand_vars AFTER loop vars, so the innermost/latest binding wins. The caller binds only values it is certain of — an uncertain value (VAR=$(cmd), VAR=$UNBOUND) is bound to the unpinnable sentinel so $VAR still fail-closes rather than resolving to a stale or dropped value.
expand_vars
Expand any bound loop variable ($name / ${name}) in path to its representative list item — the read representative when want_write is false, the write representative when true. Unbound $… is left untouched (so it still fail-closes to machine). Returns path unchanged when nothing is bound.
join_cwd
Resolve a cd target to a new absolute working directory, or None if it can’t be pinned statically (cd, cd -, cd ~…, cd $VAR) — the caller then leaves the running cwd unchanged. cur is the current cwd, needed to resolve a relative target. Used by intra-line cd tracking (HP-19 #2).
resolve
Resolve a path argument for classification against the ambient cwd/root. Returns a path the existing classifiers (classify_locus, is_safe_write_target) can score unchanged. When cwd and root are both known and absolute, a relative path is lexically joined onto cwd (no filesystem access) and an absolute path is normalized in place; then either way, if the result is inside root it comes back as a root-relative path (so the classifiers see “worktree”), and if it escaped root (e.g. cwd is /etc, or an absolute /etc/hosts) it comes back absolute (so they see machine/etc.). This makes the absolute and relative spellings of the SAME in-root file classify identically — safety on the OPERATION, not the SYNTAX. A ~ (home) or $-unpinnable path, or no context, is returned as-is.
root
The workspace ROOT (project dir), if known — falling back to cwd (the hook defaults root to cwd). Used by the adjacent-sibling classifier to find the workspace’s parent.
stdin_item_repr
The current stdin-item representative, or None when the source is unknown (no pipe / an unmodeled producer) — in which case the consumer worst-cases the injected operand.