Merge origin/main into customer fleets
Brings PR #63 up to date with main (934414c), which has since landed the
console redesign (#68), the app pages rework (#89), release versioning,
`carlos deploy`, the instances API go-live, exec-instance metrics (#121)
and the #69/#70 db-path fixes.
Seven files conflicted; every one resolves to BOTH sides composed, never
either side picked:
- main.go — main's three-role usage rewrite kept, with the branch's
`fleets` verb added under "Your deployment" and `apps` regaining its
place/-place lines. The dispatch table auto-merged with `fleets` intact.
- apps.go — apps create keeps the branch's `place2` argument and adopts
main's `printUsing` helper.
- internal/console/server.go — fleets routes sit beside the new app
Settings routes; the fleet page struct fields sit beside Overview /
InstanceRows / Confirm / Settings; both `provision` and `registry`
imported. main's new `claimReserved` return updated for the branch's
two-value claimApp signature.
- internal/console/apiinstances.go — instance create now runs main's
sibling-apex refusal FIRST (cheap, refuses a bad host before any store
read), then the branch's fleet-placement lookup, which still overrides
the request body's region.
- internal/registry/registry.go — the route table gains BOTH new columns
(`unit` from main, `fleet_box` from the branch): 33 in routeCols,
scanRoute, the placeholder row and the Upsert argument list, with both
keep-existing-on-zero CASE arms and the doc comment updated to seven
such columns.
- internal/host/agent.go — main's adoptLoop(reg, svc) / fastConvergeLoop
(canaryAdoptLoop's new name) with the branch's startup
publishResidentFleetBindings pass kept ahead of them.
- internal/host/metrics_loop.go — metricsLoop takes main's activator
service for the exec-children probe while resolving its box label
through the branch's metricsBoxLabel.
Fingerprint is the one place both sides rewrote the same function, so it
is composed rather than merged: main's content-accurate sha256 over the
actual column VALUES (which subsumes the branch's rev-counter trick — a
rotated 64-char token hash is visible because its bytes changed, not
because a counter moved) now also hashes `db_path` (#69), `region` and
`fleet_box`, and folds the fleets and fleet_boxes tables in under their
own section markers. Every invariant both sides bought survives: a
same-length version bump, a token rotation, a detach and an unattended
failover restamp all move the fingerprint, and the poll's payload is
fixed-size no matter how many routes are fleet-placed.
TestFingerprintStableWithoutFleetRoutes asserted the OLD aggregate's
string shape (a trailing ':' proving the placement projection was scoped).
There is no projection to scope now, so the assertion is ported to what
still carries its intent: the digest is "<count>:<64 hex>" regardless of
table size, which closes the unbounded-payload hole structurally.
templates/fleetdetail.html auto-merged silently but was written against
the pre-#68 layout, so it is ported by hand to current conventions: flash
banners first, a .pagehead block (eyebrow / h1 / lede) in place of the
bare h1, the placed-app link moved from {{.Base}} to {{.Nav}} like every
other app link on main, and Detach given the `linkish danger` class the
redesign uses for destructive row actions. Form actions stay on
{{.Base}}, which is already the convention. No other fleets template
exists; the handler already builds its page through main's accountPage
helper. Existing fleet-page render tests cover the result.
go build / go vet / go test ./... -count=1: all 21 packages green.
Co-Authored-By: Claude <noreply@anthropic.com>
.github/workflows/ci.yml+107 −0CLAUDE.md+57 −3README.md+14 −3accounts.go+37 −30apimode.go+325 −5apimode_test.go+191 −24appconfig_cli.go+24 −25apps.go+15 −13auth.go+17 −14cli.go+625 −85cli_test.go+493 −8cmd/console/main.go+56 −10color.go+222 −0color_test.go+128 −0deploy.go+475 −0deploy_e2e_test.go+439 −0deploy_test.go+400 −0docs/superpowers/plans/2026-08-06-console-redesign.md+1342 −0docs/superpowers/plans/2026-08-06-issues-69-70-db-path.md+380 −0docs/superpowers/plans/2026-08-08-carlos-deploy.md+894 −0docs/superpowers/plans/2026-08-08-release-versioning.md+1592 −0docs/superpowers/specs/2026-08-04-instance-provisioning-design.md+98 −0docs/superpowers/specs/2026-08-06-console-redesign-design.md+184 −0docs/superpowers/specs/2026-08-07-console-app-pages-design.md+144 −0docs/superpowers/specs/2026-08-08-carlos-deploy-design.md+310 −0docs/superpowers/specs/2026-08-08-exec-instance-metrics-design.md+152 −0docs/superpowers/specs/2026-08-08-instance-socket-consumers-design.md+161 −0docs/superpowers/specs/2026-08-08-release-versioning-design.md+130 −0e2e_test.go+133 −1go.mod+1 −1instances_cli.go+206 −26instances_e2e_test.go+142 −0internal/activator/activator.go+29 −0internal/activator/activator_test.go+271 −1internal/activator/backend_exec.go+36 −0internal/appconfig/sync.go+7 −7internal/caps/converge.go+1 −1internal/console/apicli.go+211 −9internal/console/apicli_test.go+225 −0internal/console/apiconfig.go+12 −0internal/console/apiinstances.go+255 −4internal/console/apiinstances_test.go+83 −0internal/console/apiinstancesenable_test.go+293 −0internal/console/apirestart_test.go+177 −0internal/console/apiversion.go+230 −0internal/console/apiversion_test.go+339 −0internal/console/appsettings.go+450 −0internal/console/appsettings_test.go+657 −0internal/console/attachhint_test.go+132 −0internal/console/authcli.go+26 −5internal/console/authcli_test.go+33 −4internal/console/bakecontrols_test.go+6 −6internal/console/confirm.go+233 −0internal/console/confirm_test.go+314 −0internal/console/deletion_test.go+8 −0internal/console/icons.go+13 −0internal/console/ladder_test.go+44 −32internal/console/metricsview.go+121 −29internal/console/metricsview_test.go+162 −0internal/console/overview.go+192 −0internal/console/overview_test.go+317 −0internal/console/ownership.go+23 −7internal/console/serialbump.go+40 −0internal/console/serialbump_test.go+506 −0internal/console/server.go+551 −62internal/console/server_account_test.go+63 −8internal/console/server_test.go+744 −78internal/console/store.go+91 −0internal/console/templates/account_settings.html+32 −0internal/console/templates/app.html+0 −207internal/console/templates/app_activity.html+18 −0internal/console/templates/app_instances.html+53 −0internal/console/templates/app_new.html+17 −0internal/console/templates/app_overview.html+79 −0internal/console/templates/app_releases.html+147 −0internal/console/templates/app_settings.html+101 −0internal/console/templates/appnav.html+13 −0internal/console/templates/apps.html+1 −74internal/console/templates/cli_approve.html+2 −2internal/console/templates/confirm_action.html+23 −0internal/console/templates/fleetdetail.html+8 −4internal/console/templates/home.html+6 −2internal/console/templates/ladder.html+14 −26internal/console/templates/layout.html+103 −25internal/console/templates/{cli_tokens.html => settings.html}+10 −5internal/console/templates/team.html+64 −0internal/console/view.go+72 −1internal/edge/edge.go+45 −0internal/edge/edge_test.go+63 −0internal/edge/static.go+39 −13internal/edge/static_test.go+222 −0internal/host/agent.go+687 −68internal/host/agent_test.go+812 −0internal/host/bootstrap.go+151 −37internal/host/host_test.go+144 −7internal/host/metrics_loop.go+19 −6internal/host/metrics_probes.go+75 −4internal/host/metrics_probes_test.go+58 −0internal/host/probes.go+20 −1internal/host/restart.go+650 −0internal/host/restart_test.go+706 −0internal/host/stage_relay_test.go+79 −0internal/host/units/carlos-restart.path+27 −0internal/host/units/carlos-restart.service+53 −0internal/host/units/carlos-stage.path+26 −0internal/host/units/carlos-stage.service+52 −0internal/lease/endpoint.go+130 −0internal/lease/endpoint_test.go+263 −0internal/lease/lease.go+19 −19internal/lease/lease_test.go+7 −3internal/metrics/pidparse.go+101 −0internal/metrics/pidparse_test.go+83 −0internal/provision/provision.go+31 −5internal/provision/provision_test.go+40 −0internal/registry/fleets_test.go+19 −10internal/registry/registry.go+236 −87internal/registry/registry_test.go+293 −1internal/release/adopt.go+185 −47internal/release/adopt_test.go+135 −5internal/release/golden_test.go+201 −0internal/release/ladder_test.go+284 −0internal/release/materialize.go+66 −0internal/release/materialize_test.go+181 −0internal/release/release.go+72 −0internal/release/release_test.go+51 −0internal/release/restartgen.go+107 −0internal/release/restartgen_test.go+135 −0internal/release/semver.go+105 −0internal/release/semver_test.go+57 −0internal/release/serial.go+74 −0internal/release/serial_test.go+56 −0internal/release/stage_blocked_test.go+60 −0internal/release/store.go+12 −9internal/release/store_rgw_test.go+169 −0internal/release/tag.go+187 −0internal/release/tag_test.go+202 −0internal/release/target.go+151 −0internal/release/target_test.go+153 −0internal/release/versions.go+22 −0internal/release/versions_test.go+41 −0internal/s3compat/s3compat.go+181 −0internal/s3compat/s3compat_test.go+235 −0internal/status/contract_test.go+43 −15internal/status/dryrun.go+71 −14internal/status/fleet.go+14 −8internal/status/snapshot.go+60 −16internal/status/status_test.go+113 −0main.go+84 −79restart.go+86 −0restart_test.go+153 −0testdata/echoapp/main.go+21 −0
.github/workflows/ci.ymlLoading diff…
CLAUDE.mdLoading diff…
README.mdLoading diff…
accounts.goLoading diff…
apimode.goLoading diff…
apimode_test.goLoading diff…
appconfig_cli.goLoading diff…
apps.goLoading diff…
auth.goLoading diff…
cli.goLoading diff…
cli_test.goLoading diff…
cmd/console/main.goLoading diff…
color.goLoading diff…
color_test.goLoading diff…
deploy.goLoading diff…
deploy_e2e_test.goLoading diff…
deploy_test.goLoading diff…
docs/superpowers/plans/2026-08-06-console-redesign.mdLoading diff…
docs/superpowers/plans/2026-08-06-issues-69-70-db-path.mdLoading diff…
docs/superpowers/plans/2026-08-08-carlos-deploy.mdLoading diff…
docs/superpowers/plans/2026-08-08-release-versioning.mdLoading diff…
docs/superpowers/specs/2026-08-04-instance-provisioning-design.mdLoading diff…
docs/superpowers/specs/2026-08-06-console-redesign-design.mdLoading diff…
docs/superpowers/specs/2026-08-07-console-app-pages-design.mdLoading diff…
docs/superpowers/specs/2026-08-08-carlos-deploy-design.mdLoading diff…
docs/superpowers/specs/2026-08-08-exec-instance-metrics-design.mdLoading diff…
docs/superpowers/specs/2026-08-08-instance-socket-consumers-design.mdLoading diff…
docs/superpowers/specs/2026-08-08-release-versioning-design.mdLoading diff…
e2e_test.goLoading diff…
go.modLoading diff…
instances_cli.goLoading diff…
instances_e2e_test.goLoading diff…
internal/activator/activator.goLoading diff…
internal/activator/activator_test.goLoading diff…
internal/activator/backend_exec.goLoading diff…
internal/appconfig/sync.goLoading diff…
internal/caps/converge.goLoading diff…
internal/console/apicli.goLoading diff…
internal/console/apicli_test.goLoading diff…
internal/console/apiconfig.goLoading diff…
internal/console/apiinstances.goLoading diff…
internal/console/apiinstances_test.goLoading diff…
internal/console/apiinstancesenable_test.goLoading diff…
internal/console/apirestart_test.goLoading diff…
internal/console/apiversion.goLoading diff…
internal/console/apiversion_test.goLoading diff…
internal/console/appsettings.goLoading diff…
internal/console/appsettings_test.goLoading diff…
internal/console/attachhint_test.goLoading diff…
internal/console/authcli.goLoading diff…
internal/console/authcli_test.goLoading diff…
internal/console/bakecontrols_test.goLoading diff…
internal/console/confirm.goLoading diff…
internal/console/confirm_test.goLoading diff…
internal/console/deletion_test.goLoading diff…
internal/console/icons.goLoading diff…
internal/console/ladder_test.goLoading diff…
internal/console/metricsview.goLoading diff…
internal/console/metricsview_test.goLoading diff…
internal/console/overview.goLoading diff…
internal/console/overview_test.goLoading diff…
internal/console/ownership.goLoading diff…
internal/console/serialbump.goLoading diff…
internal/console/serialbump_test.goLoading diff…
internal/console/server.goLoading diff…
internal/console/server_account_test.goLoading diff…
internal/console/server_test.goLoading diff…
internal/console/store.goLoading diff…
internal/console/templates/account_settings.htmlLoading diff…
internal/console/templates/app.htmlLoading diff…
internal/console/templates/app_activity.htmlLoading diff…
internal/console/templates/app_instances.htmlLoading diff…
internal/console/templates/app_new.htmlLoading diff…
internal/console/templates/app_overview.htmlLoading diff…
internal/console/templates/app_releases.htmlLoading diff…
internal/console/templates/app_settings.htmlLoading diff…
internal/console/templates/appnav.htmlLoading diff…
internal/console/templates/apps.htmlLoading diff…
internal/console/templates/cli_approve.htmlLoading diff…
internal/console/templates/confirm_action.htmlLoading diff…
internal/console/templates/fleetdetail.htmlLoading diff…
internal/console/templates/home.htmlLoading diff…
internal/console/templates/ladder.htmlLoading diff…
internal/console/templates/layout.htmlLoading diff…
internal/console/templates/{cli_tokens.html => settings.html}Loading diff…
internal/console/templates/team.htmlLoading diff…
internal/console/view.goLoading diff…
internal/edge/edge.goLoading diff…
internal/edge/edge_test.goLoading diff…
internal/edge/static.goLoading diff…
internal/edge/static_test.goLoading diff…
internal/host/agent.goLoading diff…
internal/host/agent_test.goLoading diff…
internal/host/bootstrap.goLoading diff…
internal/host/host_test.goLoading diff…
internal/host/metrics_loop.goLoading diff…
internal/host/metrics_probes.goLoading diff…
internal/host/metrics_probes_test.goLoading diff…
internal/host/probes.goLoading diff…
internal/host/restart.goLoading diff…
internal/host/restart_test.goLoading diff…
internal/host/stage_relay_test.goLoading diff…
internal/host/units/carlos-restart.pathLoading diff…
internal/host/units/carlos-restart.serviceLoading diff…
internal/host/units/carlos-stage.pathLoading diff…
internal/host/units/carlos-stage.serviceLoading diff…
internal/lease/endpoint.goLoading diff…
internal/lease/endpoint_test.goLoading diff…
internal/lease/lease.goLoading diff…
internal/lease/lease_test.goLoading diff…
internal/metrics/pidparse.goLoading diff…
internal/metrics/pidparse_test.goLoading diff…
internal/provision/provision.goLoading diff…
internal/provision/provision_test.goLoading diff…
internal/registry/fleets_test.goLoading diff…
internal/registry/registry.goLoading diff…
internal/registry/registry_test.goLoading diff…
internal/release/adopt.goLoading diff…
internal/release/adopt_test.goLoading diff…
internal/release/golden_test.goLoading diff…
internal/release/ladder_test.goLoading diff…
internal/release/materialize.goLoading diff…
internal/release/materialize_test.goLoading diff…
internal/release/release.goLoading diff…
internal/release/release_test.goLoading diff…
internal/release/restartgen.goLoading diff…
internal/release/restartgen_test.goLoading diff…
internal/release/semver.goLoading diff…
internal/release/semver_test.goLoading diff…
internal/release/serial.goLoading diff…
internal/release/serial_test.goLoading diff…
internal/release/stage_blocked_test.goLoading diff…
internal/release/store.goLoading diff…
internal/release/store_rgw_test.goLoading diff…
internal/release/tag.goLoading diff…
internal/release/tag_test.goLoading diff…
internal/release/target.goLoading diff…
internal/release/target_test.goLoading diff…
internal/release/versions.goLoading diff…
internal/release/versions_test.goLoading diff…
internal/s3compat/s3compat.goLoading diff…
internal/s3compat/s3compat_test.goLoading diff…
internal/status/contract_test.goLoading diff…
internal/status/dryrun.goLoading diff…
internal/status/fleet.goLoading diff…
internal/status/snapshot.goLoading diff…
internal/status/status_test.goLoading diff…
main.goLoading diff…
restart.goLoading diff…
restart_test.goLoading diff…
testdata/echoapp/main.goLoading diff…