Notes: one carry-across, and the built-in card taking its own update
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a8f75be190
commit
3b058f9332
1 file changed
+55
-11
@@ -605,17 +605,32 @@ mutable at runtime from the phone.
|
||||
Update is pressable. Iris's rule for it, 2026-09-02: "it should not do
|
||||
that until things actually can be updated."
|
||||
|
||||
- **What a build recorded is carried across the self row being
|
||||
re-derived, like the settings beside it.** `reconcile_self` rebuilds
|
||||
this server's own row from its declaration at every startup, and
|
||||
`built_from`/`built_mode` were not among the things carried -- so the
|
||||
commit written down by the build that produced the new binary was
|
||||
forgotten by the process that build started, and restarting is how this
|
||||
server takes an update. Its own card then had no freshness ever again:
|
||||
never behind, never current, and its Update with nothing to do, since
|
||||
both readings need a commit to compare against. `built_records` /
|
||||
`restore_built` carry it, keyed by name *and* directory like every
|
||||
other carry-across here.
|
||||
- **Two places rewrite a project's components list, and one type says
|
||||
what survives it.** `AppState::approve_declaration` and
|
||||
`registry::reconcile_self` both replace `components` wholesale with
|
||||
what the checkout declares -- right for everything the project asked
|
||||
for, wrong for the three things this machine knows: the package read
|
||||
out of an APK, the mode somebody chose here, and the commit and mode a
|
||||
build recorded. `CarriedOver` / `carried_over` / `restore_carried_over`
|
||||
hold all three, keyed by name *and* `cwd` like every other
|
||||
carry-across here, and both callers take the whole thing.
|
||||
It is one type because it was three collect-and-restore pairs
|
||||
remembered separately, and each caller forgot a different one.
|
||||
`reconcile_self` dropped `builtFrom`, so the commit written down by the
|
||||
build that produced the new binary was forgotten by the process that
|
||||
build started -- and restarting is how this server takes an update, so
|
||||
its own card had no freshness ever again: never behind, never current,
|
||||
and its Update with nothing to do, since both readings need a commit to
|
||||
compare against. Then `approve_declaration` turned out to drop the same
|
||||
field, which is worse because it hits *every* project: accepting a
|
||||
declaration told every one of that project's cards it had never been
|
||||
built here. Silent both times, because "not built here" is a true
|
||||
sentence about plenty of projects and so reads as an answer rather than
|
||||
as a loss -- it was found by making freshness say which kind of unknown
|
||||
it was and then looking at a card that had no business saying that one.
|
||||
Adding a field to a component now means adding it here once.
|
||||
`reconcile_self` sets the built-in row's package *after* the restore,
|
||||
so what is derived wins over an older row carrying something else.
|
||||
|
||||
- **One predicate decides both the "Up to date" heading and whether
|
||||
Update can be pressed** (`hasWorkWaiting` in `UpdaterScreen.kt`): they
|
||||
@@ -1220,6 +1235,35 @@ mutable at runtime from the phone.
|
||||
survive a changed CA, port or token, since those break the connection
|
||||
before any route is reached: those stay one-way doors and `--download`
|
||||
stays their answer.
|
||||
**It is also how the built-in card downloads its own APK**, not just
|
||||
how the rescue dialog does. `downloadApk` sends the built-in project to
|
||||
`/self/apk` rather than to the manifest's route, because this is the
|
||||
one download whose server changed underneath it between the build and
|
||||
the request -- so it takes the route nothing can rename. It carries no
|
||||
`component` or `variant` and does not need to: that project has one
|
||||
APK, and which build of it to serve is the mode set on the build
|
||||
machine.
|
||||
**And the card's Update installs this app itself**, rather than
|
||||
building it and leaving a dialog to offer it. Which means it waits for
|
||||
the server *twice* (`awaitServerBack`): once before fetching, and again
|
||||
before handing anything to the installer. The restart is deferred a
|
||||
couple of seconds past the build and then held off for as long as an
|
||||
APK is going down the wire, so it lands either just before the download
|
||||
or in the gap between the last byte and the install -- a download that
|
||||
dies partway reads as the update having failed at the moment it worked,
|
||||
and an install offered mid-restart replaces this app while the server
|
||||
it must talk to is down. Bounded, and it goes ahead anyway when the
|
||||
wait runs out: by the second one the APK is already here, and never
|
||||
installing it would be the worse failure.
|
||||
**The dialog is now offered only when the built-in card cannot offer
|
||||
it** -- that card missing from the list, or no list at all because this
|
||||
app is too old to read what the server now sends. `AppListScreen`
|
||||
derives that from `manifestState` and reports it up; `Loading` counts
|
||||
as present, since not having found out yet is not an answer and a
|
||||
dialog flashing up during every load is exactly the noise it exists to
|
||||
avoid. Iris's call, 2026-09-02: the card's own Update should do the
|
||||
work, "though keep the modal if the dev updater card itself is missing
|
||||
or fails to load."
|
||||
- **There is deliberately no general migration mechanism.** Iris's call:
|
||||
each app decides its own, and the updater's job is only to be able to
|
||||
get both halves of *itself* to the next version. A project that renames
|
||||
|
||||
Reference in new issue
Block a user