carlos / platform Public

S3 change index spec rev 3: close Astra round 2 cost gaps (#336)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev c50ad7c9448c1e2bb92a5cfbdc098b40fadfaba9 parent ca12962
1 file changed, +26 −3
  • docs/superpowers/specs/2026-10-21-s3-change-index-design.md +26 −3

CI cancelled — superseded by a newer push — run details

CI log
=== gate ===
cd launchctx && go vet ./... && go test ./... -count=1
ok  	amadan.net/carlos/platform.git/launchctx	0.012s
?   	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

amadan: job cancelled — a newer push superseded it
diff --git a/docs/superpowers/specs/2026-10-21-s3-change-index-design.md b/docs/superpowers/specs/2026-10-21-s3-change-index-design.md
index fc52fb64e..104c094dc 100644
--- a/docs/superpowers/specs/2026-10-21-s3-change-index-design.md
+++ b/docs/superpowers/specs/2026-10-21-s3-change-index-design.md
@@ -1,9 +1,9 @@
# S3 change index: stop re-walking the deployment bucket
Amadan discussion: carlos/platform #336. Branch `s3-polling-336`.
-Status: draft rev 2, 2026-10-21. Rev 2 answers Astra round 1
-(`CODEX-FINDINGS-S3-CHANGE-INDEX-R1.md`); accepted findings are marked
-**(codex N)**, and all eleven were accepted.
+Status: rev 3, 2026-10-21. Astra accepted rev 2 at spec level (round 2);
+rev 3 closes round 2's two cost gaps, marked **(codex R2-N)**. Round 1
+findings are marked **(codex N)**; all were accepted.
## 0. Problem and evidence
@@ -316,6 +316,16 @@ failures and old binaries wait for the backstop.
- The backstop (§4.4) ends with today's unrestricted full pass, so every
leg is re-run over everything at least every 30 minutes.
+**Known limit (codex R2-10).** Serial-triggered passes keep adopt and
+config sync over every hosted route, because the serial also signals
+changes outside the index's scopes and there is no inventory of those yet.
+That fan-out is bounded by the routes a box hosts, not by every app in the
+deployment, and runs at the serial's rate (about once a minute on
+flagship): roughly 0.35M GETs a day across the fleet, ~$4 a month. Scoping
+those passes needs the console to mark serial bumps whose effects the
+index fully covers; that is a follow-up, measured after rollout before it
+is designed.
+
### 4.6 Console sweeps
- **Run sweep** (30s): keeps its interval and reads the console's own
@@ -323,6 +333,15 @@ failures and old binaries wait for the backstop.
(`SetRecordRun`) is an instance-record write and bumps the app's scope
once the boxes run this code. Minutes-stale is already safe here
(`KeepFor` 24h, CAS on every change).
+- **Orphan-run housekeeping** (every twentieth sweep,
+ `internal/console/runsweep.go:39,110,232`) today lists `runs/` for every
+ app with an instance record. It now lists only apps with a `run-start`
+ activity row (`internal/console/apiruns.go:315`) in the last 48 hours,
+ the window in which a run's objects can still be live or awaiting
+ cleanup, and does today's all-app sweep once a day as the backstop.
+ Orphans are still found by time (a stray's newest object a day old), not
+ by index movement, since `runs/` is outside every scope
+ **(codex R2-1)**.
- **Seed sweep** (5 min): keeps its strict walk, because its snapshot
deletes are proved by absence and must see records listed after the
snapshot listing (`seedsweep.go:126-131`). It now skips the walk
@@ -469,3 +488,7 @@ litestream ~$26, requests ~$10–25), flat as apps are added.
5 (manifests, §4.1), 6 (hostops order, §3.3–3.4), 7 (fleet door,
§3.4), 8 (mesh keys and heartbeat, §5), 9 (telemetry age, §5),
10 (per-app fan-out, §4.5), 11 (box publication, §3.3, §7).
+- Round 2 (Astra, ca129623): accept at spec level. Round 1 dispositions:
+ ten resolved, 10 partly (serial-triggered fan-out). New: R2-1 (orphan
+ housekeeping). Rev 3 closes R2-1 (§4.6) and records R2-10 as a measured
+ known limit (§4.5).