Say what an image build is doing, and keep saying it

A build is the slow part of a first run and the thing --install triggers: apt, a Node
tarball, an npm install. Every byte of podman's transcript used to go to a log file, so
minutes of silence looked exactly like a wedge -- and a wedge is what people interrupt,
leaving a half-built image.

One line per build step, plus a notice every AISB_BUILD_QUIET_SECS (15) that a step has
shown the terminal nothing, whether it is producing output the view drops or no output at
all. AISB_BUILD_OUTPUT=progress|full|quiet picks how much the terminal sees; the complete
transcript stays in $AISB_STATE_DIR/build-*.log in all three, because the progress view is
a filter and a failed build has to be diagnosable from the raw apt output. The first line
names the extra packages going in, which is what answers "why is this run building when
the last one did not".

podman build writes its transcript to *stdout* -- the same stdout the
$(ensure_image ...) call reads back as the image ref -- so the transcript is routed onto
stderr and the ref stays one clean line. A failed build now names the package apt could
not find instead of pointing at a file to go read, and reports the time it took.
Resolving a digest by pulling the base says so too: that is a download of the base image.

tests/unit/11_build.sh stubs podman for both heartbeat paths and checks the ref, the
failure text and that a canary credential appears nowhere.

LLM-Generated: true
This commit is contained in:
2026-10-30 22:53:57 -04:00
parent 90d98dcc9e
commit ac2f310d10
5 changed files with 353 additions and 10 deletions
+6 -1
View File
@@ -332,9 +332,14 @@ A project whose tests need something the image lacks gets it from the launcher:
sandbox-pi () {
export AI_API_TOKEN=$(pass aipi/dev-token)
ai-sandbox --allow aipi.reeseapps.com --allow pypi.org --allow files.pythonhosted.org \
--install 'python3-pip ripgrep' --env AI_API_TOKEN "$@"
--install python3-pip --install ripgrep --env AI_API_TOKEN "$@"
}
```
A new `--install` set is a new image tag, so the first run after changing it builds: that
one run says which packages are going in and reports every step until the image exists
(`AISB_BUILD_OUTPUT=quiet` if you would rather it did not talk). Every later run starts
without a word about the image, because there is nothing left to do.
`doctor`, `inspect`, `clean` and the rest of ai-sandbox work unchanged underneath it —
`--status` prints the policy the launcher will apply, without applying it.