Inline-code tool bodies (§4.5.2) could not read or write file contents
dynamically: the §13.2.1 sandbox exposes no filesystem access, so the only
sanctioned path was static file_read → inline → file_write wiring, which
cannot express a runtime-computed path, multi-file access, or a
read-modify-write cycle in one body.
Per ADR-2035, expose exactly two injected local callables in unsafe mode:
read_file(path, max_chars=None, offset=0) -> str
write_file(path, content, mode="w") -> int
Both reuse the existing file_read/file_write validated cores (now extracted
into a shared FileAccessCore + SandboxRootPolicy so containment, ADR-2033
windowing, and the §4.5.5 write modes have a single implementation) and
return raw values rather than the LLM envelope. They confine every access to
the sandbox root — rejecting `..`, `~`, and any path whose resolved real path
(symlinks followed) escapes the root — raising ValueError so inline code can
catch it with the sandbox's own vocabulary. write_file additionally requires
_unsafe_mode in the invocation context; read_file does not, preserving the
read/write privilege split. In safe mode neither name is bound (NameError),
and the §13.2.1 built-in table is unchanged. The shared realpath containment
also closes a symlink-escape gap in the built-in tools.
The Actor Configuration Standard is revised to 1.2.0 (§4.5.2, §13.2.1,
§13.2.3, §13.3) recording the sanctioned helpers, with the rationale in the
ADR.
Refs: #93
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>