carlos / platform Public

docs: correct the spec from what implementation found

Two corrections, both discovered by implementers reading the plan against
the real code rather than by review of the spec itself:

- §7's "under about five seconds" silently depended on a serial bump the
  spec never named. Without it the write lands in the bucket correctly and
  then waits for the hourly pass. The audit row was missing for the same
  reason, and matters independently: a prefix map decides where an
  account's traffic goes, so who moved it has to be answerable after.

- §11 gains the converge-loop check. §10's end-to-end test drives
  ReconcileAliases and Reload directly, which is right, but that means it
  proves the layers compose given that something calls them — not that the
  production host agent calls them on schedule for a live path claim. That
  is also the check that would falsify the five-second claim if it is wrong.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 00dada1434f61cd2fca4d79614705ce0c4a5e284 parent 043bc05
1 file changed, +37 −4
  • docs/superpowers/specs/2026-09-02-path-based-routing-design.md +37 −4
diff --git a/docs/superpowers/specs/2026-09-02-path-based-routing-design.md b/docs/superpowers/specs/2026-09-02-path-based-routing-design.md
index b78562bec..dbb503706 100644
--- a/docs/superpowers/specs/2026-09-02-path-based-routing-design.md
+++ b/docs/superpowers/specs/2026-09-02-path-based-routing-design.md
@@ -328,10 +328,24 @@ of a claim's Wildcard/Catchall fields"*), a single `SetClaimPaths` is the only
writer of `Paths`, so `AttachClaim`'s converge can neither invent nor strip
the map.
-**Flip latency, end to end:** `PUT` → bucket → fast-converge tick
-(`fastTickEvery = 2s` plus jitter, agent.go:1053/1504) → registry write → 2s
-fingerprint poll → live map. **Under about five seconds**, which is inside
-what a Tito admin toggle can plausibly wait on.
+**Flip latency, end to end:** `PUT` → bucket → **serial bump** →
+fast-converge tick (`fastTickEvery = 2s` plus jitter, agent.go:1053/1504) →
+registry write → 2s fingerprint poll → live map. **Under about five
+seconds**, which is inside what a Tito admin toggle can plausibly wait on.
+
+The serial bump is not incidental, and this document's first revision
+omitted it — the omission was caught during implementation. Without it the
+write lands in the bucket correctly and then waits for the *hourly* pass,
+turning a five-second flip into an hour-long one. Attach and detach already
+bump for exactly this reason, so the door must do what its siblings do:
+write, then audit, then bump, all inside the `changed` branch so a no-op
+republish costs neither an audit row nor a fleet-wide reload.
+
+The audit row matters independently of latency. A prefix map decides where
+an account's traffic goes, so "who moved this hostname's traffic, and when"
+has to be answerable afterwards. The row records actor, account, app, host
+and the prefix count — deliberately not the targets themselves, since the
+map may hold ten thousand entries.
---
@@ -403,3 +417,22 @@ any of it.
- **`ti.to` behind the CARLOS edge.** Out of scope here, but it is the
prerequisite for case 1 ever being used, and it is the largest single risk
in the whole migration. Worth its own spec when Paul is ready.
+
+- **The production converge loop actually folds a path claim on schedule.**
+ §10's end-to-end test drives `ReconcileAliases` and `Edge.Reload` directly,
+ which is the right call — the 2s tick is a latency bound, not a correctness
+ property, and polling it would make the fastest test in the plan slow and
+ flaky. But that means the test proves the layers compose *given that
+ something calls those two functions*. It does not prove that the real
+ converge loop (`internal/host/agent.go:1475` and `:1955`, the two
+ production call sites of `ReconcileAliases`) invokes them for a live path
+ claim on the real schedule.
+
+ The general fingerprint→reload mechanism is not unproven — `Edge.Watch` is
+ exercised against a live goroutine with bounded polling elsewhere in
+ `internal/edge`. What is unproven is specifically that a published `paths`
+ map traverses the real host agent's timing end to end. That is an
+ integration concern a package-level test cannot absorb, so it belongs here
+ rather than in the suite. **It is also the check that would falsify §7's
+ "under about five seconds" claim if that claim is wrong**, which makes it
+ the most load-bearing of the three items in this section.