The v1.0.1 tag claimed this work but did not contain it: the edits were still
in the working copy when main was moved and pushed. This is that change.
The run against v1.0.1 reached the registry and failed with 'unauthorized'.
The automatic token cannot write packages without the job asking for it, so
the job now requests packages: write and nothing wider.
actions/checkout is pinned to a commit rather than a tag, at v4.4.0 rather than
the current v7.0.1, which declares node24 that act_runner does not provide.
regctl is pinned to a release instead of tracking latest. Every expansion moves
into env so nothing interpolates into a shell body.
Clean under actionlint and zizmor --persona=auditor. .shush.toml preserves the
comments those linters require, which the comment hook was otherwise removing.
ubuntu-latest matches no runner on this forge, so both the main push and the
v1.0.0 tag queued nothing at all. The runner is labelled linux.
actions/checkout is pinned to a commit rather than a tag, and to v4.4.0 rather
than the current v7.0.1: v7 declares node24, which act_runner does not provide.
regctl moves out of /usr/local/bin, which a self-hosted runner cannot write to
without sudo, and is pinned to a release rather than tracking latest.
Clean under actionlint and zizmor --persona=auditor. Every expansion moves into
env so nothing interpolates into a shell body. secrets-outside-env is suppressed
deliberately: Gitea has no deployment environment protection rules, so a
dedicated environment would add ceremony without a security boundary.
Carries CLAUDE.md, AGENTS.md, hooks and skills verbatim from the host, plus a
manifest of the 10 marketplaces and 17 plugins to reinstall at build time. The
plugin directories themselves are not committed: ~/.claude/plugins is 831 MB and
sits alongside credentials and transcripts, so the image is reproduced from the
manifest instead and the build needs no access to the host.
The Gitea registry is behind Cloudflare, which rejects request bodies over 100 MB
against a base image with a 325 MB layer, so the workflow pushes chunked through
regctl rather than docker push.
sbx v0.37.0 and v0.37.1 cannot consume the result: layers stacked on the base are
silently dropped (docker/sbx-releases#366). The image builds and pushes correctly
and is a no-op at runtime until that is fixed, so README points at
'ai:sbx setup' as the mechanism that works today.