feat(live-activity): add shared content-state contract and reconciler helpers - #420
Open
RonenMars wants to merge 1 commit into
Open
feat(live-activity): add shared content-state contract and reconciler helpers#420RonenMars wants to merge 1 commit into
RonenMars wants to merge 1 commit into
Conversation
… helpers Adds types/live-activity.ts, the content-state shape both the iOS widget and the later APNs sender read from. It stays flat primitives because the state crosses a native bridge and will eventually ride a 4 KB APNs payload. startedAt is epoch ms and elapsedMs is deliberately absent: the server's elapsedMs is a snapshot nothing in the app ticks, so a surface rendering it would freeze between updates. Handing the OS a start time lets it run its own timer and removes any reason to push per-second updates. services/live-activity.ts holds the pure half of the reconciler — terminal detection, session-to-state mapping, and the cap/eviction policy — so all the branching is testable with no device and no native module. isTerminal checks three signals because managed servers set completedAt, external ones report processLiveness, and older servers do neither. Eviction is by least-recently-updated rather than oldest-started, so a long session still producing output outranks a newer silent one. lastOutput is stripped of ANSI escapes and box drawing through the existing utils and truncated to 90 chars, since the Dynamic Island compact slots are narrow. A word boundary is only honored when it retains over half the budget, otherwise a single long token would collapse the line. widgets/ is registered in ci-paths.txt and docs/ci-significant-paths.md ahead of the directory landing, so the first commit that adds a layout cannot be mis-tagged [skip-ci].
RonenMars
force-pushed
the
feat/live-activity-contract
branch
from
July 25, 2026 21:22
e60be12 to
2f763ed
Compare
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.
Stacked on #419.
Adds
types/live-activity.ts, the content-state shape both the iOS widget and the later APNs sender read from, plus the pure half of the reconciler.Why the contract looks like this
Flat primitives only: the state crosses a native bridge and will eventually ride a 4 KB APNs payload.
startedAtis epoch ms andelapsedMsis deliberately absent.The server's
elapsedMsis a snapshot that nothing in the app ticks, so a surface rendering it would sit frozen between updates.Handing the OS a start time lets it run its own timer, which also removes any reason to push per-second updates once APNs is in play.
Cap is 3 against an iOS ceiling of 5, leaving headroom.
Helpers
isTerminalchecks three signals because the fleet is not uniform: managed servers setcompletedAt, external ones reportprocessLiveness, and older servers do neither, leaving the legacy idle-without-a-PTY heuristic as the only tell.decideActionsevicts by least-recently-updated rather than oldest-started, so a long-running session still producing output outranks a newer silent one.Keeping it pure is what makes the cap and eviction policy testable with no device and no native module.
lastOutputis stripped of ANSI escapes and box drawing through the existingutils/stripAnsi+utils/stripBoxDrawingrather than a new stripper, then truncated to 90 chars for the narrow Dynamic Island compact slots.A word boundary is only honored when it retains over half the budget — otherwise a single long token would collapse the line to a few characters.
Notes
widgets/is registered inci-paths.txtanddocs/ci-significant-paths.mdhere, ahead of the directory landing in the next PR, so the commit that adds a layout cannot be mis-tagged[skip-ci].Verification
15 new unit tests covering each terminal signal independently, truncation behavior, and the eviction/slot-reuse cases.
npm run lint0 errors;npm run typecheckunchanged from baseline.