Vector operations (T2-8, T2-5)

reverse(v) and sort(v) are compiler special-cased in parse_call.

pub fn starts_with(self: text, value: text) -> boolean

Returns true if self begins with value. Use for prefix matching (e.g., protocol detection).

pub fn ends_with(self: text, value: text) -> boolean

Returns true if self ends with value. Use for suffix matching (e.g., file extension checks).

pub fn dir(self: text) -> text

Directory part of a path — strips the trailing `/<segment>`. "doc/claude/PROBLEMS.md".dir() → "doc/claude" "CLAUDE.md".dir() → "" (no `/`) "/etc/passwd".dir() → "/etc" "".dir() → ""

pub fn basename(self: text) -> text

Last segment of a path — the part after the trailing `/`. "doc/claude/PROBLEMS.md".basename() → "PROBLEMS.md" "CLAUDE.md".basename() → "CLAUDE.md" "/foo/".basename() → "" (trailing slash) "".basename() → ""

pub fn join(self: text, other: text) -> text

Join two paths — `self/other` with a single `/` separator. Special cases: - other starts with `/` (absolute) → return other unchanged - self is empty → return other - self ends with `/` → no extra separator inserted

pub fn resolve(self: text, target: text) -> text

Resolve `target` against `self` (where self is a base directory). Strips leading `./` repeatedly; each `../` segment trims the last component from `self`. Mirrors scan.loft's `resolve_link_path`. "doc/claude".resolve("../README.md") → "doc/README.md" "doc/claude".resolve("./PROBLEMS.md") → "doc/claude/PROBLEMS.md" "a/b/c".resolve("../../x") → "a/x" "".resolve("foo") → "foo"