Claiming the whole project means what's stale, not everything built here

after_moving (Pull and Update's shared machinery) gated a post-pull build
on `pulled || is_stale(None)` and then, once open, `claim(&mut inner,
None)` -- which marks every component with a build command regardless of
whether it was the one that moved. `trigger_if_needed(None, ...)` had the
same shape one level up: check is_stale, then hand off to build_now, which
is unconditional by design. So any pull that fetched anything rebuilt
every sibling beside the one that actually changed -- "it tries to update
the compose apk even if nothing was done."

`claim` now takes `only_stale`: false for build_now (a person pressed a
specific button, and staleness has no business overruling that), true for
trigger_if_needed and for the build after_moving runs after a pull.
component_is_stale was already scoped correctly per component; the bug was
building past that answer once any one component tripped it.

MismatchedPairNote also had its own word for the same "behind" freshness
freshnessNote already calls "out of date" -- "older than this build" was a
second name for one measurement, which is what "pulling says something
weird about the compose apk" turned out to be. Reused the existing word.

Regression test: a_pull_touching_one_component_does_not_rebuild_its_sibling.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Sonnet 5 committed 2026-09-06 13:45:45 -04:00
1 parent 663626345a
commit c41c36f25d
3 files changed
+194 -19

No files matched your search

+26
View File
@@ -1320,6 +1320,32 @@ mutable at runtime from the phone.
version. It follows that a build and an install landing in the same
second can briefly read as "update available"; that's inherent, not a
bug to chase.
- **Claiming "the whole project" must still mean "what's actually
stale," not "everything with a command."** `after_moving` (what Pull
and Update share) used to gate a post-pull build on
`pulled || is_stale(None)` and then, once open, `claim(&mut inner,
None)` -- which marks *every* component with a build command, stale or
not. `trigger_if_needed(None, ...)` had the same shape: check
`is_stale`, then hand off to `build_now`, which is unconditional by
design (it is also the button). So any pull that fetched anything --
a one-line fix under `server/`, say -- rebuilt the APK beside it too,
reported as "it tries to update the compose apk even if nothing was
done." `claim` now takes `only_stale`: `false` for `build_now` (a
person pressed a specific button, and staleness has no business
overruling that), `true` for `trigger_if_needed` and for the build
`after_moving` runs after a pull. `component_is_stale` was already
scoped correctly per component (`watched_paths`) -- the bug was never
in *what* counts as stale, only in building past that answer once any
one component tripped it. Regression test:
`a_pull_touching_one_component_does_not_rebuild_its_sibling`.
- **Two words for one measurement is a bug even when both are true.**
`MismatchedPairNote` said a sibling still on its old build was "older
than this build," while `freshnessNote` already has a word for that
exact freshness (`behind` → "out of date"). Same field, two names --
which is what "pulling says something weird about the compose apk"
turned out to be: not a wrong condition, a second vocabulary for a
state the reader had already been told about elsewhere on the same
card. Reuse the existing word rather than inventing an adjacent one.
## Running the server for real