Repository navigation
feat(cloud): send FTW Cloud 48 hours of history tiles (C6) - #1817
Merged
Merged
Conversation
A tiles body is the app protocol's hist.chunk with the common header: closed tiles match the box's Noise answer byte for byte, and the trailing tile travels whole or as appends that Lay puts back together. cloud-tile-vectors.json freezes one of each shape for FTW Cloud and the phone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With ftw.history.read in the owner's grant and NTP time, the box sends the trailing 5-minute tile as its buckets close (an append, whole once an hour), each tile as it closes, and at connect or a resync the tiles of the last 48 hours that hello_ok's have lacks. Closed tiles are packed from the same ledger read as the app's Noise history, so they are the same bytes. Tiles go last in a tick and count against the byte budget. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n seq seq starts again when the box does, and a phone may still hold pieces from before the restart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 50bb116904
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The box sends a closed tile again when its ledger changed under it, as in the hourly pass. Lay kept the first, so a receiver drew the old gap. Only a piece of a closed tile is ignored now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
frahlg
added a commit
to srcfl/ftw-app
that referenced
this pull request
Oct 23, 2026
… the first After a relaunch with the box still away, the tiles file already held the copy's tiles, FTW Cloud's answer brought nothing new, and the date line went. Until the box answers, an answer that holds the tiles shown now dates them as the copy. lay and the tile store kept the first closed tile they saw. The box sends a closed tile again when its ledger changed under it, so the later one now replaces it, as srcfl/ftw#1817's Lay does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…back in the grant - Check takes the four series and no other, from the registry's names, and TileEnvelopeMax bounds an envelope, so a box cannot pad its tiles. - When history leaves the grant the link forgets what it sent; when it comes back every tile goes again on the same link. - The ledger is read at most once a tick, one closed tile at a time, and the grant is checked again before each tile goes. - cloudlink.PackTile is the one packing path; a test holds it to the Noise tile through appproto's buildTile. - The doc says what a phone really gets: tiles until the roster runs out while the box is away, and when FTW Cloud sends resync for tiles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
frahlg
added a commit
to srcfl/ftw-app
that referenced
this pull request
Oct 23, 2026
…e box wins - check takes the four series and no other, as srcfl/ftw#1817's Check. - The tile store keeps a closed tile the box sent later over one it sent before, whatever order they come in. - A closed tile from FTW Cloud never replaces one the box sent itself, only an earlier one from the copy. - After a relaunch, what is shown is dated as the copy only when the copy reaches as far; the box's own cached history is not labelled as it. - A test ties HistoryModel.series to CloudWire.tileSeries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
frahlg
added a commit
to srcfl/ftw-app
that referenced
this pull request
Oct 23, 2026
#98) * feat(cloud): draw FTW Cloud's history tiles while the box is away FTW Cloud keeps the box's signed 5-minute tiles of the last 48 hours (srcfl/ftw docs/protocol-cloud.md, tiles). The phone checks each with the key the box gave it over Noise, lays the pieces back together as Go's cloudwire.Lay does, and asks with tiles.get once per cloud session while the box session cannot answer. Closed tiles are the box's bytes, so they share the tiles file. The line under the chart dates the copy ("From FTW Cloud · up to 17:15"); the box's own answer replaces it the moment it comes. cloud-tile-vectors.json from srcfl/ftw replays here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(demo): a box that goes away, its history from FTW Cloud's copy -FTWDemoBoxAway YES (Debug only): the demo box names its cloud key in hello, streams for three seconds without answering hist.query, then goes. SimulatedCloud runs the app session over loopback with the real Noise handshake and answers tiles.get with tiles the demo box signed, so the picture shows the real path: verify, lay, draw, dated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cloud): date FTW Cloud's history before its sum A long sum under the chart wraps into the second reserved line. With the date first, that cuts the sum, never the line that says the history is a copy and how old it is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cloud): the time after FTW Cloud's copy ends is not a hole The sum under the chart counted every step after the copy's last bucket as "not recorded": at 16:25 with a copy up to 16:20 it said "10 min not recorded", though the box may well have recorded them. The copy says nothing about that time, so the history leaves it out; holes inside the copy still count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cloud): stay dated after a relaunch; a later closed tile replaces the first After a relaunch with the box still away, the tiles file already held the copy's tiles, FTW Cloud's answer brought nothing new, and the date line went. Until the box answers, an answer that holds the tiles shown now dates them as the copy. lay and the tile store kept the first closed tile they saw. The box sends a closed tile again when its ledger changed under it, so the later one now replaces it, as srcfl/ftw#1817's Lay does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cloud): tiles after review: four series, ordered closed tiles, the box wins - check takes the four series and no other, as srcfl/ftw#1817's Check. - The tile store keeps a closed tile the box sent later over one it sent before, whatever order they come in. - A closed tile from FTW Cloud never replaces one the box sent itself, only an earlier one from the copy. - After a relaunch, what is shown is dated as the copy only when the copy reaches as far; the box's own cached history is not labelled as it. - A test ties HistoryModel.series to CloudWire.tileSeries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step C6 of ADR 0008. FTW Cloud keeps the last 48 hours of 5-minute history for each home whose owner turned it on. The iPhone app can then draw a node's history while the box cannot answer.
Paired with srcfl/ftw-cloud#48 (the service) and srcfl/ftw-app#98 (the app). Merge this first. ftw-cloud pins
go/protocolat this branch'sb10a6939and then moves the pin to the merge commit.What changes
Wire:
go/protocol/cloudwireanddocs/protocol-cloud.mdtilesis the app protocol'shist.chunkplus the common header, at 5 minutes and stride 1. It carriesgrid_w,pv_w,battery_wandload_w, in the order the app asks for them over Noise. A closed tile therefore has the same tile id, etag and bytes as the box serves over Noise.A tile has one of three shapes:
Tiles.Checkenforces the shapes,Piececuts a piece andLayputs pieces back together.A phone sends
tiles.get {have}. The service answers with the box's envelopes the phone lacks, thentiles.end {n}.cloud-tile-vectors.jsonholds:Layresults;tiles.getandtiles.endbytes.ftw-cloud and the app replay these vectors.
docs/protocol-cloud.mdnow covers:tiles, soTestFieldsMatchTheProtocolDocumentchecks it;hello_ok.have;resync {what: tiles};ADR 0008's store table gets a row for tiles.
Core:
internal/cloudlinkandcmd/ftwftw.history.readin the grant and NTP time. It counts a bucket closed 30 s after it ends, once the history writer has committed it.hello_ok.havelacks goes too, newest first.appHistory.Windowandprotocol.PackTileas the Noise path.hello.capsliststileswhen the grant allows them.Decisions to look at
history_querynow says so and says when FTW Cloud last heard from it (feat: hold 48 hours of history tiles and answer tiles.get (C6) ftw-cloud#48). Should it instead answer from these tiles? That would change the rule, and the box would not see the read. It is not built; it is the owner's call.ev_worbattery_soc. The box's history serves four series today. The old text said C2 adds the other two, but C2 did not.Tests
make verifypassed: tests, vet and build.go test ./cloudwirecovers the shapes, Noise equality, whatCheckrefuses,Layand the vectors.go test -race ./internal/cloudlinkcovers these cases:havesaves the service's tiles;feat/c6-tiles. At connect the box sent the filling tile whole and the four closed tiles of the last 48 hours. They were empty, since that box's ledger was new. At 14:25:30 UTC it sent a one-point append for 14:20–14:25 with the measured values. A small checker read what the service held from/dev/held. Every tile verified with the box key and passedCheck, andLayrebuilt the filling tile through 14:25. Nothing touched the home box, the FTW Cloud host or AWS.After review
Checktakes the four series and no other, derived from the registry's names.TileEnvelopeMax(4 KiB) bounds an envelope, so a box cannot pad its tiles.ftw.history.readleaves the grant, the link forgets what it sent. When history comes back, every tile goes again on the same link (TestHistoryTakenOutAndPutBackSendsEveryTileAgain).Lay.cloudlink.PackTileis the one packing path.TestACloudTileIsTheNoiseTileholds it to the Noise tile through appproto's realbuildTile.resyncfor tiles when a roster gives history back or room frees.make verifypasses again.🤖 Generated with Claude Code