A runner declares the job images its box must hold, and the declaration carries them to the box #4

Closed
opened 2026-10-05 15:37:41 +00:00 by jimmy · 1 comment
Owner

What is wrong

A runner's declaration names its labels and the image each maps to, and nothing more. The images a build box must hold beyond the default one (roost-swift-ci:6.1-noble, roost-swift-ci:6.3.2-noble on the opi) are declared nowhere, so on 2026-10-04 the box's prune took two of them and nothing the box could read said they were wanted (jimmy/house#98). roost's bin/job-images.py already reads a runner.images field, and falls back to the box's own memory of what it held because the field cannot reach the box.

Jimmy ruled on 2026-10-05: plan the hatchery change. A job image is a build box resource and belongs on the runner.

The plan

  1. RunnerSpec (Sources/HatcheryKit/BuildBox.swift:8) gains images: a list of {image, recipe, registry?}. image is the local name a workflow or a label uses, recipe is the path in roost that builds it, and registry is the forge package it is pushed to and pulled from, where it has one.
  2. Declaration.Runner (Declaration.swift:66) publishes the list, and the image each label maps to, which it strips today. The box reads it from pulse's /api/declared.
  3. hatchery box runner rebuilds the spec at BuildBox.swift:157 and would drop the field: it keeps it.
  4. ~/infra-state/box/hatchery.json declares the three images on the act_runner service, and the mini's runner declares none, with its mode host.
  5. hatchery check on the box stack says when a declared image is not held, from the reader's rows on pulse, so the declaration and the box are compared in one place.

Done when

  1. A declared image reaches the box: /api/declared on the opi names each image with its recipe.
  2. job-images.py on the opi shows the two Swift images as wanted by the declaration, with no help from the box's memory.
  3. hatchery box runner leaves the list as it was.
  4. Tests hold the round trip of the field and the published form.

Not in this ticket

The push of the images to the forge registry is jimmy/house's ticket; this one only gives it a field to name the package in.

## What is wrong A runner's declaration names its labels and the image each maps to, and nothing more. The images a build box must hold beyond the default one (roost-swift-ci:6.1-noble, roost-swift-ci:6.3.2-noble on the opi) are declared nowhere, so on 2026-10-04 the box's prune took two of them and nothing the box could read said they were wanted (jimmy/house#98). roost's `bin/job-images.py` already reads a `runner.images` field, and falls back to the box's own memory of what it held because the field cannot reach the box. Jimmy ruled on 2026-10-05: plan the hatchery change. A job image is a build box resource and belongs on the runner. ## The plan 1. `RunnerSpec` (Sources/HatcheryKit/BuildBox.swift:8) gains `images`: a list of `{image, recipe, registry?}`. `image` is the local name a workflow or a label uses, `recipe` is the path in roost that builds it, and `registry` is the forge package it is pushed to and pulled from, where it has one. 2. `Declaration.Runner` (Declaration.swift:66) publishes the list, and the image each label maps to, which it strips today. The box reads it from pulse's `/api/declared`. 3. `hatchery box runner` rebuilds the spec at BuildBox.swift:157 and would drop the field: it keeps it. 4. `~/infra-state/box/hatchery.json` declares the three images on the `act_runner` service, and the mini's runner declares none, with its mode `host`. 5. `hatchery check` on the box stack says when a declared image is not held, from the reader's rows on pulse, so the declaration and the box are compared in one place. ## Done when 1. A declared image reaches the box: `/api/declared` on the opi names each image with its recipe. 2. `job-images.py` on the opi shows the two Swift images as wanted by the declaration, with no help from the box's memory. 3. `hatchery box runner` leaves the list as it was. 4. Tests hold the round trip of the field and the published form. ## Not in this ticket The push of the images to the forge registry is jimmy/house's ticket; this one only gives it a field to name the package in.
Author
Owner

Landed in hatchery 27b9c51 and infra-state 9a1c894, and proven on the opi on 2026-10-06.

  1. Met: the declaration published to pulse names the three images, each with its recipe and its registry package, and the opi fetched it at its next reconcile.
  2. Met: ~/roost/bin/job-images.py on the opi reads "the runner's block declares it" for roost-swift-ci:6.1-noble and roost-swift-ci:6.3.2-noble, where it read "nothing this host can read names it".
  3. Met: hatchery box runner act_runner -s box --check reads the three as held on opi, says "the declaration already says this; nothing to write", and exits 0.
  4. Met: eleven new tests. The full suite is 754 of 755; the one failure, includesHostsInUse, reads the Mac's own ~/.roostrc and is not of this change.

Not forced on the live box: a missing image. Its line and the exit 1 are held by tests.

Landed in hatchery 27b9c51 and infra-state 9a1c894, and proven on the opi on 2026-10-06. 1. Met: the declaration published to pulse names the three images, each with its recipe and its registry package, and the opi fetched it at its next reconcile. 2. Met: `~/roost/bin/job-images.py` on the opi reads "the runner's block declares it" for roost-swift-ci:6.1-noble and roost-swift-ci:6.3.2-noble, where it read "nothing this host can read names it". 3. Met: `hatchery box runner act_runner -s box --check` reads the three as held on opi, says "the declaration already says this; nothing to write", and exits 0. 4. Met: eleven new tests. The full suite is 754 of 755; the one failure, includesHostsInUse, reads the Mac's own ~/.roostrc and is not of this change. Not forced on the live box: a missing image. Its line and the exit 1 are held by tests.
jimmy closed this issue 2026-10-06 15:38:05 +00:00
Sign in to join this conversation.
No labels
wayfinder:task
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
jimmy/hatchery#4
No description provided.