Commit Graph
3 Commits
Author SHA1 Message Date
Paul HittandClaude Opus 4.8 edd53bc771 Tell somebody when their disappearing message is screenshotted
Android half of ios#36, spec §6.27. `shot` joins the control kinds, so a
build that does not know it stays quiet rather than rendering JSON.

🔴 The care is in refusing to let the absence of a notice mean anything.
The device that took the screenshot reports it, so a modified build, a
second phone, or a screen recorder produce nothing. A notice means one
was probably taken; no notice means NOTHING, and nothing counts them.

⚠️ Android's half of the asymmetry is stated rather than hidden. There is
no screenshot callback at all before API 34, and the one added there does
not cover screen recording — so the disclaimer says that, in those words.
Claiming a symmetry with iOS that does not exist would be worse than the
gap, because somebody would rely on it.

⚠️ Only where a timer is set, and the timer check comes before the
rate-limit check so a suppression window cannot make an untimed
conversation start reporting.

⚠️ Last-notice times are in memory. Persisting them would store who
screenshotted whom on disk to enforce a five-second window.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-03 19:08:44 -04:00
Paul Hitt aebf41ed95 Put the app back to the last state that worked
Tonight's merges left sign-in, messages, calls and stories broken. Restores
app, engine and client to fa92581 — the tree that shipped as v8 and works.

Why they broke: those features are not independent. A message, a call
signal, a story and a story reply are the same content envelope with a
different kind, so they run through the same few functions in Content.kt.
Twenty-three MRs, each written against an older main and green on its own
branch, had never existed together until they were merged in one evening.

The conflicts that produced were resolved mechanically — union a parameter
list, merge a condition — and that produces code which compiles and passes
while being wrong: a field on the wrong struct, an argument in the wrong
order, a term in the wrong condition. Three were caught by the compiler.
The ones the compiler cannot see are why calls stopped connecting.

And the gate could not see any of it. 489 unit tests stayed green through
every break, because they test units: "assemble produces this JSON" is a
unit test, "Android shows what iOS sent" is not.

versionCode 10 so it installs over the broken v9.

Nothing is lost — every MR is still a merged commit with its branch on the
remote, and re-lands in small batches once there is a test that actually
sends a message between two devices.
2026-09-02 19:03:30 -04:00
Paul HittandClaude Opus 4.8 a43f8a6feb Tell somebody when their disappearing message is screenshotted
Android half of ios#36, spec §6.27. `shot` joins the control kinds, so a
build that does not know it stays quiet rather than rendering JSON.

🔴 The care is in refusing to let the absence of a notice mean anything.
The device that took the screenshot reports it, so a modified build, a
second phone, or a screen recorder produce nothing. A notice means one
was probably taken; no notice means NOTHING, and nothing counts them.

⚠️ Android's half of the asymmetry is stated rather than hidden. There is
no screenshot callback at all before API 34, and the one added there does
not cover screen recording — so the disclaimer says that, in those words.
Claiming a symmetry with iOS that does not exist would be worse than the
gap, because somebody would rely on it.

⚠️ Only where a timer is set, and the timer check comes before the
rate-limit check so a suppression window cannot make an untimed
conversation start reporting.

⚠️ Last-notice times are in memory. Persisting them would store who
screenshotted whom on disk to enforce a five-second window.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 15:50:52 -04:00