carlos / platform Public

zdd rev 19 amendment: generation sockets keep the flag-off file name

Gate F (2026-10-13) crash-looped an app whose framework takes its origin
from the --socket file name: app.3.sock read as host app.3. Each
generation now gets its own directory and keeps the flag-off base name.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev e7e9308b708f8cce50b6cb7f3be0185fd75a8119 parent 21d91fd
1 file changed, +85 −0
  • docs/superpowers/specs/2026-10-13-zero-downtime-deploys-rev19-amendment.md +85 −0

CI failed — run details

CI log
=== gate ===
cd launchctx && go vet ./... && go test ./... -count=1
ok  	amadan.net/carlos/platform.git/launchctx	0.011s
?   	amadan.net/carlos/platform.git/launchctx/controlname	[no test files]
?   	amadan.net/carlos/platform.git/launchctx/wireid	[no test files]
go vet ./...
gofmt -l .: clean
go test ./... -count=1 -timeout 30m
ok  	github.com/carlosframework/platform	331.167s
?   	github.com/carlosframework/platform/cmd/changelog	[no test files]
ok  	github.com/carlosframework/platform/cmd/console	3.209s
ok  	github.com/carlosframework/platform/cmd/moveprobe	93.245s
ok  	github.com/carlosframework/platform/cmd/zddprobe	0.382s
ok  	github.com/carlosframework/platform/internal/activator	227.226s
ok  	github.com/carlosframework/platform/internal/agentsock	0.026s
ok  	github.com/carlosframework/platform/internal/alerting	0.003s
ok  	github.com/carlosframework/platform/internal/analytics	0.019s
ok  	github.com/carlosframework/platform/internal/appconfig	2.330s
ok  	github.com/carlosframework/platform/internal/apperr	0.076s
ok  	github.com/carlosframework/platform/internal/applog	0.144s
ok  	github.com/carlosframework/platform/internal/awsinv	0.005s
ok  	github.com/carlosframework/platform/internal/boxchoice	0.004s
ok  	github.com/carlosframework/platform/internal/boxid	0.624s
?   	github.com/carlosframework/platform/internal/boxid/boxidtest	[no test files]
?   	github.com/carlosframework/platform/internal/boxid/internal/signtest	[no test files]
ok  	github.com/carlosframework/platform/internal/boxvolumes	0.009s
ok  	github.com/carlosframework/platform/internal/caps	0.015s
ok  	github.com/carlosframework/platform/internal/certwarm	0.002s
ok  	github.com/carlosframework/platform/internal/cgroup	0.707s
ok  	github.com/carlosframework/platform/internal/changelog	0.293s
ok  	github.com/carlosframework/platform/internal/clamd	0.055s
?   	github.com/carlosframework/platform/internal/cliflag	[no test files]
ok  	github.com/carlosframework/platform/internal/console	362.170s
?   	github.com/carlosframework/platform/internal/controlname	[no test files]
?   	github.com/carlosframework/platform/internal/controlsock	[no test files]
ok  	github.com/carlosframework/platform/internal/dbdoor	5.644s
ok  	github.com/carlosframework/platform/internal/dbdoor/dbdoortest	0.010s
ok  	github.com/carlosframework/platform/internal/dbverify	0.007s
ok  	github.com/carlosframework/platform/internal/dnsrec	0.003s
ok  	github.com/carlosframework/platform/internal/docsite	0.005s
ok  	github.com/carlosframework/platform/internal/domains	2.076s
ok  	github.com/carlosframework/platform/internal/doorkey	0.006s
ok  	github.com/carlosframework/platform/internal/economics	0.004s
ok  	github.com/carlosframework/platform/internal/edge	26.325s
?   	github.com/carlosframework/platform/internal/edgeproof	[no test files]
ok  	github.com/carlosframework/platform/internal/edgesfile	0.008s
ok  	github.com/carlosframework/platform/internal/fleetapi	0.121s
ok  	github.com/carlosframework/platform/internal/gate	1.656s
ok  	github.com/carlosframework/platform/internal/genselect	0.016s
ok  	github.com/carlosframework/platform/internal/geo	0.017s
ok  	github.com/carlosframework/platform/internal/geoip	0.032s
ok  	github.com/carlosframework/platform/internal/host	94.461s
ok  	github.com/carlosframework/platform/internal/hostactors	0.500s
ok  	github.com/carlosframework/platform/internal/hostbox	2.079s
ok  	github.com/carlosframework/platform/internal/hostclaim	0.494s
ok  	github.com/carlosframework/platform/internal/hostevidence	0.006s
--- FAIL: TestRenewalRequestStartAndIndependentExpiry (4.00s)
    controller_test.go:211: blocked PUT blocked watchdog
    panic.go:694: context deadline exceeded
FAIL
FAIL	github.com/carlosframework/platform/internal/hostexec	8.768s
ok  	github.com/carlosframework/platform/internal/hostfence	0.038s
ok  	github.com/carlosframework/platform/internal/hostfiles	10.595s
ok  	github.com/carlosframework/platform/internal/hostfloor	0.012s
ok  	github.com/carlosframework/platform/internal/hostguard	1.003s
ok  	github.com/carlosframework/platform/internal/hostops	1.432s
?   	github.com/carlosframework/platform/internal/hostops/fencerelease	[no test files]
ok  	github.com/carlosframework/platform/internal/hostops/internal/fencerelease	0.002s
ok  	github.com/carlosframework/platform/internal/hostquarantine	0.005s
ok  	github.com/carlosframework/platform/internal/hostrelocate	0.471s
ok  	github.com/carlosframework/platform/internal/hostresolve	0.128s
ok  	github.com/carlosframework/platform/internal/hostwrite	0.001s
ok  	github.com/carlosframework/platform/internal/infraview	0.002s
ok  	github.com/carlosframework/platform/internal/instancectl	1.820s
ok  	github.com/carlosframework/platform/internal/instanceexec	2.712s
ok  	github.com/carlosframework/platform/internal/instancefs	0.016s
ok  	github.com/carlosframework/platform/internal/instancekey	0.013s
ok  	github.com/carlosframework/platform/internal/instanceupdates	0.020s
ok  	github.com/carlosframework/platform/internal/layout	1.383s
ok  	github.com/carlosframework/platform/internal/lease	9.434s
ok  	github.com/carlosframework/platform/internal/lease/leasetest	0.016s
ok  	github.com/carlosframework/platform/internal/ledger	0.024s
ok  	github.com/carlosframework/platform/internal/mail	0.157s
ok  	github.com/carlosframework/platform/internal/maintenance	0.080s
ok  	github.com/carlosframework/platform/internal/maintenanceexec	5.594s
ok  	github.com/carlosframework/platform/internal/maintenanceguard	0.077s
ok  	github.com/carlosframework/platform/internal/metrics	0.004s
ok  	github.com/carlosframework/platform/internal/moves	20.942s
ok  	github.com/carlosframework/platform/internal/moves/archive	0.749s
ok  	github.com/carlosframework/platform/internal/objstore	0.152s
ok  	github.com/carlosframework/platform/internal/ops	0.164s
ok  	github.com/carlosframework/platform/internal/park	0.206s
ok  	github.com/carlosframework/platform/internal/privatefile	0.004s
ok  	github.com/carlosframework/platform/internal/provision	12.977s
ok  	github.com/carlosframework/platform/internal/publicrelease	0.007s
?   	github.com/carlosframework/platform/internal/regionname	[no test files]
ok  	github.com/carlosframework/platform/internal/registry	4.039s
ok  	github.com/carlosframework/platform/internal/relay	7.234s
ok  	github.com/carlosframework/platform/internal/release	20.156s
ok  	github.com/carlosframework/platform/internal/rollout	3.687s
ok  	github.com/carlosframework/platform/internal/rolloutwords	0.004s
ok  	github.com/carlosframework/platform/internal/rootaws	0.007s
ok  	github.com/carlosframework/platform/internal/rootparticipation	0.006s
ok  	github.com/carlosframework/platform/internal/rootstate	0.024s
ok  	github.com/carlosframework/platform/internal/s3compat	0.005s
ok  	github.com/carlosframework/platform/internal/safefile	0.004s
ok  	github.com/carlosframework/platform/internal/schedule	2.311s
ok  	github.com/carlosframework/platform/internal/sim/hostlife	9.495s
ok  	github.com/carlosframework/platform/internal/sim/litestreamfacts	3.792s
ok  	github.com/carlosframework/platform/internal/status	0.036s
ok  	github.com/carlosframework/platform/internal/steering	0.005s
ok  	github.com/carlosframework/platform/internal/stopevidence	0.212s
ok  	github.com/carlosframework/platform/internal/svcrole	0.002s
ok  	github.com/carlosframework/platform/internal/telemetry	0.004s
ok  	github.com/carlosframework/platform/internal/termfence	0.004s
ok  	github.com/carlosframework/platform/internal/tunnelclient	0.004s
ok  	github.com/carlosframework/platform/internal/unixdial	0.002s
ok  	github.com/carlosframework/platform/internal/updatewords	0.004s
ok  	github.com/carlosframework/platform/internal/usage	0.004s
ok  	github.com/carlosframework/platform/internal/version	0.001s
ok  	github.com/carlosframework/platform/internal/vet	1.547s
FAIL
make: *** [Makefile:18: test] Error 1

amadan: step gate failed: exit status 2

amadan: job failed at step gate — its output is above, not at the tail of this log
diff --git a/docs/superpowers/specs/2026-10-13-zero-downtime-deploys-rev19-amendment.md b/docs/superpowers/specs/2026-10-13-zero-downtime-deploys-rev19-amendment.md
new file mode 100644
index 000000000..672cad915
--- /dev/null
+++ b/docs/superpowers/specs/2026-10-13-zero-downtime-deploys-rev19-amendment.md
@@ -0,0 +1,85 @@
+# Zero-downtime deploys: rev 19 amendment (generation socket names)
+
+Status: rev 19, 2026-10-13. Paul approved the fix on 2026-10-13 after Gate F
+failed. This amends §7.1 of
+`2026-10-07-zero-downtime-deploys-design.md` (rev 17, as amended by rev 18).
+
+## What happened
+
+Gate F armed the flagship's IE box at 22:08Z on 2026-10-13. For about
+3.5 minutes every generation wake of three instances of one app crash-looped,
+until the flag was removed (amadan #272).
+
+The app's framework works out its origin from the file name of its `--socket`
+argument:
+
+- A bare `app.sock` names no host, so the framework falls back to its
+ configured origin. This is how every nested instance starts with the flag
+ off.
+- The nested generation socket `app.3.sock` parsed as the host `app.3`. That
+ disagreed with the configured origin, so the app refused to start.
+
+`CARLOS_HOST` was set on those launches, and the docs say to read it rather
+than the socket name, but deployed builds do not. A platform release must not
+break a build that starts today. The dev probe passed because `zddprobe`
+ignores its socket name.
+
+## The rule (replaces §7.1's generation paths)
+
+1. **A generation's socket file name is the flag-off one.**
+ - Nested: `app.sock`.
+ - Flat: `<host>.sock`.
+
+ Each generation gets its own directory instead:
+ - Nested: `<instance run dir>/g<n>/app.sock`, for example
+ `/run/carlos/instances/<id>/g3/app.sock`.
+ - Flat: `/run/carlos/g/<n>/<host>.sock`.
+
+ The control socket stays `<socket>.control`, beside it. Rev 15's canonical
+ link at `rt.Socket` keeps pointing at the current generation's socket by
+ absolute path. §7.1's "the hostname never appears in it" no longer holds
+ for flat generation paths. See rule 4 for the length bound that replaced
+ it.
+2. **A generation launch matches a flag-off launch.** Its argv and its
+ agent-owned environment are the same as a flag-off launch of the same
+ build, except for the directory part of `--socket`. This already holds for
+ the environment (`agentOwnedVars`). A test pins it for both layouts.
+3. **The directory's lifecycle.**
+ - Before generation n's stale-file removal and start, the agent makes its
+ directory, mode 0750 with setgid, inheriting the carlos-sockets group as
+ the run dirs do.
+ - The stale-file rule is unchanged: before the app binds, only the file at
+ this generation's own path is removed.
+ - Once the generation's termination proof holds and its socket is gone,
+ the agent removes the directory if it is empty. A sibling's directory is
+ never touched.
+ - A leftover directory from an earlier agent process is harmless, and the
+ stale-file rule clears its socket the next time n is used.
+4. **The length bound.** A unix socket path is at most 107 bytes. A flat host
+ whose generation path would exceed that has no generation path: it is
+ handled exactly as a foreign row is today, keeping its canonical socket.
+ This adds no new member-facing state and no new copy. The window is small,
+ because the flag-off path `/run/carlos/<host>.sock` is already near the
+ bound for the same host. Nested paths are bounded by the 40-byte instance
+ identifier and stay well under it.
+5. **The probe checks it.** `cmd/zddprobe` exits 1, with a clear line on
+ stderr, before it listens if either of these is wrong:
+ - the base name of `--socket` is neither `app.sock` nor
+ `$CARLOS_HOST.sock`;
+ - `CARLOS_HOST` is empty.
+
+ A dev or flagship probe then fails its health check the way the tenant
+ did, instead of passing.
+
+## Not changed
+
+- Generation numbering, the generations file, the termination proof, the
+ scheduler, the canary, and the failure book.
+- Flag-off paths. With `CARLOS_SWAP` unset, nothing in this amendment runs.
+
+## Before Gate F runs again
+
+- Release the fix, and roll it to dev and then the flagship.
+- Re-run the dev swap under load with the new probe.
+- Clear annie's stale failure record. It holds bdn/ips build `2d577ebda` on
+ canada, which is the live build. Clearing it needs Paul's approval.