fleet operations: cast diff/apply --all over the project registry #26

Closed
opened 2026-07-13 19:20:51 +00:00 by dan-claude-bot · 1 comment
dan-claude-bot commented 2026-07-13 19:20:51 +00:00 (Migrated from github.com)

Problem

Every cast verb is single-project. "Do this to the whole instance" is a shell
loop the operator writes from memory:

cast diff heavy-duty/incubator --env prod
cast diff heavy-duty/other     --env prod
# …and the one you forgot is the one that drifted

That is fine at one project. It stops being fine the moment a box hosts several
— which is precisely where this fleet is heading (the box being drained in the
current migration hosts three).

Proposal

Depends on the projects: registry (see the registry issue).

cast diff  --env prod --all      # every project in the registry
cast apply --env prod --all
  • Iterate the registry, run the existing per-project path, aggregate.
  • Report per project, and fail closed on the aggregate: a clean fleet diff
    must mean every project was actually read, not that the ones cast happened
    to look at were fine.
  • A project in the registry that cast cannot reach is an error, not a skip.
    A silently skipped project reads exactly like a clean one — the same class of
    lie as #12/#18/#22, at fleet scale.

Not urgent

One project per server today. This is the ergonomics that the registry unlocks,
not a reason to build the registry.

## Problem Every cast verb is single-project. "Do this to the whole instance" is a shell loop the operator writes from memory: ```sh cast diff heavy-duty/incubator --env prod cast diff heavy-duty/other --env prod # …and the one you forgot is the one that drifted ``` That is fine at one project. It stops being fine the moment a box hosts several — which is precisely where this fleet is heading (the box being drained in the current migration hosts three). ## Proposal Depends on the `projects:` registry (see the registry issue). ```sh cast diff --env prod --all # every project in the registry cast apply --env prod --all ``` - Iterate the registry, run the existing per-project path, aggregate. - **Report per project, and fail closed on the aggregate**: a clean fleet diff must mean *every* project was actually read, not that the ones cast happened to look at were fine. - **A project in the registry that cast cannot reach is an error, not a skip.** A silently skipped project reads exactly like a clean one — the same class of lie as #12/#18/#22, at fleet scale. ## Not urgent One project per server today. This is the ergonomics that the registry unlocks, not a reason to build the registry.
dan-claude-bot commented 2026-07-13 19:47:28 +00:00 (Migrated from github.com)

Grounded now: #28 gives this a place to iterate from.

environments.<env>.projects.<org>/<repo> exists. cast smoke already takes an optional <org>/<repo>, so the per-project entry point is established.

Two constraints this must respect, both sharpened by #28:

  1. The registry is not yet authoritative (see #25). projects: is optional, so iterating it today iterates the projects that happened to need per-project state — not the projects that exist. A project cast cannot see is not a project that is clean. --all must not ship until absence means "does not exist".
  2. Fail closed on the aggregate. A clean fleet diff must mean every project was read. A skipped project reads identically to a passing one — the same lie as #12/#18/#22, at fleet scale. An unreachable project is an error, never a skip.

And one thing --all gets for free from #28 that is worth naming: split-placement detection. diff already flags a project whose live resources sit on different destinations. Run fleet-wide, that becomes a real audit — the kind of thing nobody would ever run by hand, one project at a time.

**Grounded now: #28 gives this a place to iterate from.** `environments.<env>.projects.<org>/<repo>` exists. `cast smoke` already takes an optional `<org>/<repo>`, so the per-project entry point is established. Two constraints this must respect, both sharpened by #28: 1. **The registry is not yet authoritative** (see #25). `projects:` is optional, so iterating it today iterates the projects that happened to need per-project state — not the projects that exist. **A project cast cannot see is not a project that is clean.** `--all` must not ship until absence means "does not exist". 2. **Fail closed on the aggregate.** A clean fleet diff must mean *every* project was read. A skipped project reads identically to a passing one — the same lie as #12/#18/#22, at fleet scale. An unreachable project is an **error**, never a skip. And one thing `--all` gets for free from #28 that is worth naming: **split-placement detection**. `diff` already flags a project whose live resources sit on different destinations. Run fleet-wide, that becomes a real audit — the kind of thing nobody would ever run by hand, one project at a time.
Sign in to join this conversation.
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: heavy-duty/cast#26
No description provided.