Commit Graph
3 Commits
Author SHA1 Message Date
ducoterra a91744f390 stop the driver hanging on a terminal and on a launcher
ai-sandbox-autophase could sit forever, printing nothing, in two places
that are both before the first unit -- which is why both looked like a
script that "does nothing".

The rc probe ran `timeout 15 bash -ic` in front of the user's terminal.
An interactive bash calls tcsetpgrp() to take that terminal, is in its
background, and is stopped for trying; a stopped process does not take
SIGTERM, so the timeout waited in front of it and the driver waited on
the command substitution behind it. It now runs in its own session
(setsid), with stdin closed, under `timeout -k`, and reads the
definition from a temp file rather than a pipe, because a grandchild an
rc file leaves behind holds a pipe's EOF open long after the shell it
came from has been reaped.

A launcher is called *with* the run, and a function ending at
`--env NAME` -- the shape everyone writes for typing by hand, including
every example this repo printed -- discards the flags and the
in-container command. The container then starts the image's default
harness with no prompt and, with --no-interactive gone, the terminal
attached: an agent waiting for keystrokes behind a pipe nobody reads.
`ap_forwards_args` checks the captured definition, --status and the
preflight name it with the one-line fix, and every child now starts with
stdin on /dev/null so a launcher cannot put the sandbox back on the
keyboard. Aliases and whole command lines need no forwarding: the shell
appends the words to those.

Tests: a launcher fixture that drops its arguments, one that leaves a
process behind, and shape assertions on ap_probe_rc.

LLM-Generated: true
2026-10-29 21:07:39 -04:00
ducoterra 209f167e43 add doc-sandbox: answer from the installed program, not memory
The explainer for questions about a flag, a config key, a refusal, a
mechanism or a security boundary. ai-sandbox generates its own
Containerfile, entrypoint, squid config and netfilter rules from one
script, so the text of the program is the documentation of the version
the user will run: the skill sets a strict ground-truth order -- the
installed script and --help, then the repo docs, then the tests as the
executable spec -- and its own fact sheet last, overridden by all of
them.

scripts/locate.sh resolves that order on an arbitrary machine: the
installed script and its version, the source tree behind it (via
$AISB_REPO, the script's own parent, $PWD, the git root), the docs with
their line counts, and the config/state/cache locations.

references/source-map.md maps a question topic to the function, doc and
test that hold the answer, plus the vocabulary (split_target,
classify_allows, gate vs --no-gate vs --proxy, POL[]/P_*/OPT_*) and the
FAQ. The skill names which safe surface answers what: the --dry-run,
--print-entrypoint, --print-containerfile and --print-policy previews
build nothing and reach no registry, while inspect, doctor --deep,
build, update and gate up do change the machine and are not for an
explanation. It records the two honest exceptions rather than
overclaiming -- --print-policy ensures the home volume, and --no-gate
hits DNS.

Read-only by construction: no build, no container, no network call, and
it reads pi_config_bridge() rather than a models.json holding a live
key. Its worst failure mode is an invented flag, so the answer format
requires the real spelling, the source it came from, what the thing does
not do, and a plain "no" plus the closest real thing when the answer is
no.

LLM-Generated: true
2026-10-29 08:37:51 -04:00
ducoterra 34f94e38be add right-sandbox: write a project's own ai-sandbox policy
Turns a project directory into that project's policy, so a plain
`ai-sandbox` in the directory is the correct, reviewable invocation. It
writes the two files load_config() actually reads -- .ai-sandbox/allow
and .ai-sandbox/config -- and nothing else: no sandbox.yaml, no local
override, no invented schema, because a file nobody reads is a policy
nobody has.

scripts/survey.sh gathers the evidence read-only and prints no values:
variable NAMES, remote and registry HOSTS, service PORTS, with URL
credentials stripped before anything is printed -- the same rule
--dry-run, --print-policy and the session log hold themselves to. The
agent decides from that evidence, then verifies with --dry-run and
--print-policy rather than assuming an allowlist entry means a working
toolchain.

references/settings-map.md maps every accepted key and flag to its
default, plus per-ecosystem allowlists and the survey-to-policy cheat
sheet. references/port-and-loopback.md is the honest answer on ports:
outbound to a service on the machine via the mapped loopback address
100.64.0.1 (needs an allow entry and a client that does not hand the
request to the egress proxy), and why a port the sandbox listens on is
not reachable from the host in --net allow -- with probes, because that
half is a reading of gen_rules(), not a measurement.

Policy files only. Never builds, never starts a container, and never
writes a real credential: it writes .ai-sandbox/env.example and tells
the user what to put in the gitignored 0600 file.

LLM-Generated: true
2026-10-29 08:37:51 -04:00