build(dev-base): bring ward, aos, and agent-compose up to date #1130

Merged
coilysiren merged 3 commits from task/bump-internal-tools into main 2026-08-18 20:51:41 +00:00
Owner

Three coilyco-authored binaries in the full image were behind their release
trains.

tool pinned latest behind
ward 0.884.0 0.887.0 3 minors
aos 0.202.0 0.213.0 11 minors
agent-compose 2.22.0 2.31.0 9 minors

agent-compose is the one that matters most this week: it composes every role
bundle the sirens lanes bake, and 2.22.0 predates the work that landed this
week.

specgen is not in this PR, and the gate is why

The first push bumped SPECGEN_VERSION 0.142.0 -> 0.157.0 alongside the others
and CI refused it:

FAILED tests/test_aos_cli_release.py::test_specgen_pin_is_owned_by_the_dependency_lock

That test asserts ARG SPECGEN_VERSION=<x> equals cliGuard in
.specgen/guardfiles/specverb.lock, and separately refuses SPECGEN_VERSION
appearing in scripts/aos-release-build.sh at all. The lock owns that pin.
The Dockerfile value is downstream of it, so moving it alone is not a bump, it
is a divergence.

Moving specgen for real means regenerating guardfiles at the new umbra ref,
which produces a real diff in generated output on the aos release-build path.
That is its own change with its own review. The pin is back at 0.142.0 here.

I had already flagged the lock as out of scope and then bumped the pin anyway.
The gate caught the contradiction, which is the check doing exactly its job.

Verified against the registry, not the tag list

A tag existing proves nothing, since the build fails at the curl if the asset
is not there. For each of the three:

  • the release carries <tool>-linux-amd64, <tool>-linux-arm64, SHA256SUMS
  • every URL answered 200 with a real body (13.5MB ward, 9.8MB aos, 6.4MB
    agent-compose)
  • each SHA256SUMS was matched with the same [[:space:]]<asset>$ pattern the
    Dockerfile greps, rather than assumed to contain the name

The finding underneath

Third-party pins were checked too and are almost all current:

cli/cli                    2.97.0    = v2.97.0
mikefarah/yq               4.53.3    = v4.53.3
casey/just                 1.58.0    = 1.58.0
git-lfs/git-lfs            3.7.1     = v3.7.1
golangci/golangci-lint     2.12.2    = v2.12.2
openai/codex               0.146.0  -> rust-v0.147.0
trufflesecurity/trufflehog 3.96.0   -> 3.97.0

Something keeps the third-party set current and nothing keeps the first-party
set current. The pins we control are the ones that rot, which is worth its own
change rather than a recurring sweep.

codex and trufflehog are left alone deliberately: the ask was the
first-party set, and each wants its own changelog read.

Rollout

docker/** on main is the dev-base-publish path filter, so merging rebuilds
and republishes the image graph. No hand-run publish.

Three coilyco-authored binaries in the full image were behind their release trains. | tool | pinned | latest | behind | |---|---|---|---| | `ward` | 0.884.0 | **0.887.0** | 3 minors | | `aos` | 0.202.0 | **0.213.0** | 11 minors | | `agent-compose` | 2.22.0 | **2.31.0** | 9 minors | `agent-compose` is the one that matters most this week: it composes every role bundle the sirens lanes bake, and 2.22.0 predates the work that landed this week. ## specgen is not in this PR, and the gate is why The first push bumped `SPECGEN_VERSION` 0.142.0 -> 0.157.0 alongside the others and CI refused it: ``` FAILED tests/test_aos_cli_release.py::test_specgen_pin_is_owned_by_the_dependency_lock ``` That test asserts `ARG SPECGEN_VERSION=<x>` equals `cliGuard` in `.specgen/guardfiles/specverb.lock`, and separately refuses `SPECGEN_VERSION` appearing in `scripts/aos-release-build.sh` at all. **The lock owns that pin.** The Dockerfile value is downstream of it, so moving it alone is not a bump, it is a divergence. Moving specgen for real means regenerating guardfiles at the new umbra ref, which produces a real diff in generated output on the aos release-build path. That is its own change with its own review. The pin is back at 0.142.0 here. I had already flagged the lock as out of scope and then bumped the pin anyway. The gate caught the contradiction, which is the check doing exactly its job. ## Verified against the registry, not the tag list A tag existing proves nothing, since the build fails at the `curl` if the asset is not there. For each of the three: - the release carries `<tool>-linux-amd64`, `<tool>-linux-arm64`, `SHA256SUMS` - every URL answered **200 with a real body** (13.5MB ward, 9.8MB aos, 6.4MB agent-compose) - each `SHA256SUMS` was matched with the same `[[:space:]]<asset>$` pattern the Dockerfile greps, rather than assumed to contain the name ## The finding underneath Third-party pins were checked too and are almost all current: ``` cli/cli 2.97.0 = v2.97.0 mikefarah/yq 4.53.3 = v4.53.3 casey/just 1.58.0 = 1.58.0 git-lfs/git-lfs 3.7.1 = v3.7.1 golangci/golangci-lint 2.12.2 = v2.12.2 openai/codex 0.146.0 -> rust-v0.147.0 trufflesecurity/trufflehog 3.96.0 -> 3.97.0 ``` Something keeps the third-party set current and nothing keeps the first-party set current. The pins we control are the ones that rot, which is worth its own change rather than a recurring sweep. `codex` and `trufflehog` are left alone deliberately: the ask was the first-party set, and each wants its own changelog read. ## Rollout `docker/**` on main is the `dev-base-publish` path filter, so merging rebuilds and republishes the image graph. No hand-run publish.
build(dev-base): bring the first-party image tools up to date
Some checks failed
ci / aos-eval-tests (pull_request) Successful in 5s
ci / aos-cli-tests (pull_request) Successful in 19s
ci / ward-doctor (pull_request) Successful in 13s
ci / gate (pull_request) Failing after 29s
dev-base-pr / build (pull_request) Has been cancelled
0b56b2bb1d
Every coilyco-authored binary in the full image was behind its release train.
Nothing automates these, which is why they drifted while the third-party pins
beside them stayed current.

  ward           0.884.0 -> 0.887.0
  specgen        0.142.0 -> 0.157.0   (umbra)
  aos            0.202.0 -> 0.213.0
  agent-compose  2.22.0  -> 2.31.0

specgen is the furthest behind at fifteen minors, and agent-compose is the one
that matters most right now: it composes every role bundle the sirens lanes
bake, and 2.22.0 predates the work landing this week.

VERIFIED AGAINST THE REGISTRY, NOT THE TAG LIST. Each release was checked for
the exact assets the build pulls, every URL answered 200 with a real body, and
each SHA256SUMS was matched with the same `[[:space:]]<asset>$` pattern the
Dockerfile greps. A tag that exists with no asset would fail this build at the
curl, which is the failure this checks for.

NOT INCLUDED. .specgen/guardfiles/specverb.lock still pins the umbra library at
v0.142.0. That is the generator's own dependency rather than the shipped binary,
and moving it regenerates guardfiles with a real output diff, so it wants its
own change and a look at what changes.

Third-party pins were checked and are current, apart from codex (0.146.0
against rust-v0.147.0) and trufflehog (3.96.0 against 3.97.0). Left alone: the
ask was the first-party set, and each of those wants its own changelog read.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
build(dev-base): leave the specgen pin to the lock that owns it
Some checks failed
ci / aos-eval-tests (pull_request) Successful in 6s
ci / ward-doctor (pull_request) Successful in 13s
ci / aos-cli-tests (pull_request) Successful in 20s
ci / gate (pull_request) Successful in 53s
dev-base-pr / build (pull_request) Failing after 14m33s
5de55dd82a
The gate said so: test_specgen_pin_is_owned_by_the_dependency_lock asserts the
Dockerfile's SPECGEN_VERSION equals cliGuard in
.specgen/guardfiles/specverb.lock, and the previous commit moved one without the
other.

The lock is the owner rather than a copy. scripts/aos-release-build.sh reads
cliGuard out of it and the test refuses SPECGEN_VERSION appearing in that script
at all, so the Dockerfile pin is downstream of the lock and bumping it alone is
not a bump, it is a divergence.

Moving specgen therefore means regenerating guardfiles at the new umbra ref,
which produces a real diff in generated output on the aos release-build path.
That is its own change with its own review, not a line in a version sweep. The
previous commit called that out and then bumped the pin anyway, which was the
error.

ward, aos, and agent-compose are unaffected. Their pins are owned here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
coilyco-ops changed title from build(dev-base): bring the first-party image tools up to date to build(dev-base): bring ward, aos, and agent-compose up to date 2026-08-18 20:24:09 +00:00
build(dev-base): the roster grew to eighteen personalities
All checks were successful
ci / aos-cli-tests (pull_request) Successful in 24s
ci / aos-eval-tests (pull_request) Successful in 7s
ci / ward-doctor (pull_request) Successful in 17s
ci / gate (pull_request) Successful in 1m7s
dev-base-pr / build (pull_request) Successful in 6m52s
207dd39cea
The image build failed on the agent-compose bump, in verify-common.sh:

    aosguard version dev-base
    v2.31.0
    roster artifact: 34 files under /tmp/tmp.f1tjRfS2c2
    #56 ERROR: process "bash /tmp/verify-common.sh" did not complete
        successfully: exit code: 1

agent-compose 2.31.0 ships eighteen personalities where 2.22.0 shipped sixteen.
The two new ones are `empirical` and `outward`, and they are the same two that
moved `ai` off curious and `exec` off curious in every consumer's rebaked
bundles. source and role_order are unchanged at roster:core and eight.

So the count was right when it was written and the roster moved under it. It is
a hand-maintained number for a set the tool owns, which is the same shape as
every other pin in this image, and it has no derivation available: the check
exists to catch an empty or garbage roster, and asserting the roster equals
itself would assert nothing.

THE OPAQUE FAILURE IS THE OTHER HALF. A bare `jq -e` over three conditions exits
1 naming neither the field nor what it saw, so an image build failed with a line
number and nothing else. The conditions are now one named check each and a
mismatch prints both sides:

    roster .personalities | length = 18, expected 16

Verified by running it against a real roster at both values, so the passing case
and the failing message are both observed rather than assumed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
coilysiren deleted branch task/bump-internal-tools 2026-08-18 20:51:41 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os!1130
No description provided.