ci: typecheck the extension and run the Android unit tests - #282
Merged
Merged
Conversation
`tsc --noEmit` never ran in CI (#152) and did not pass: the ambient asset declarations in global.d.ts sat in a file that a top-level `import type` had turned into a module, so every scss/svg/mp3 import failed to resolve, and without skipLibCheck third-party typings failed too. That noise hid a handful of real errors: a timer id typed as NodeJS.Timeout in a browser file, a manifest override read off an untyped JSON import, and the background message listener's implicitly-any parameters. - keep global.d.ts a script (import() types instead of a top-level import) - tsconfig: skipLibCheck, resolveJsonModule, explicit include - fix the four real errors; the listener now narrows its message - add `npm run typecheck` and a CI step for it - run the Android JVM unit test suite as its own CI job (#151) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vfDHpx2YT8CkxPPATgigc
…#196) The fresh intervention already opens on the clock-matched loading sky with the native sun blooming on it; what was left of #118 were the two sibling overlays. The sleep wind-down window still fell back to the flat dark ground, faded in over the blocked app for 300ms, forced a hardware layer on its WebView (the very thing that makes an overlay WebView skip its first composite), and had none of the first-frame nudges or the failed- WebView teardown. The success sun window never opted out of system-bar insets, so its gradient could leave an uncovered strip under the gesture bar. - CommonWindow: the initial shield is painted before addView through an overridable hook; the first-frame hardening (alpha nudge, invalidate pump) and the failed-WebView teardown move here so every WebView overlay shares one copy instead of re-deriving it. - LoadingSky: the sky backdrop composable and the local-hour helper are shared rather than private to the intervention window. - SleepWindDownOverlayWindow: instantly-opaque loading-sky shield, transparent WebView over it, no forced hardware layer, the shared hardening, full-screen insets. - SuccessSunWindow: layout under the system bars and the cutout like its siblings. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vfDHpx2YT8CkxPPATgigc
Detection lives inside the accessibility service and dies with it. The permission checks catch the service being switched off, but not the failure that actually happens in the field: the toggle still shows on after an OEM kill or an update, nothing is bound, no intervention ever fires, and a local-only app has no other way to tell the user it has gone quiet. - the service keeps a connected flag across onServiceConnected / onUnbind / onDestroy - the main bridge exposes it with the settings state as DetectionHealth (JSON shape covered by a JVM test) - the Android shell reads it on every refresh and shows one calm line when enabled-but-unbound; the tap opens the accessibility settings, where switching the service off and on re-binds it. A missing or malformed read counts as watching, so the line can only ever appear on a known fact - never on event silence, which an idle phone produces too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vfDHpx2YT8CkxPPATgigc
All data is local and every platform is an island: the extension's sync storage is small and prunes the oldest answers when it fills, a lost phone takes its answers with it, and nothing moves between the extension and the app. The answer journal is the most personal thing minded holds, so it gets a way out that doesn't depend on us - a plain JSON file the user keeps, restorable on any platform. - journalBackup.ts: the file format (answers + custom questions), tolerant parsing, and an additive merge by id that never overwrites an existing entry and is idempotent; unit-tested - fileTransfer.ts: Blob download on the extension; on Android the bridge opens the system "save as" sheet (ACTION_CREATE_DOCUMENT), and a plain <input type="file"> is routed to the document picker through WebChromeClient.onShowFileChooser - one "Your answers" section on both settings pages: Save a copy / Bring a copy back, with a single result line Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vfDHpx2YT8CkxPPATgigc
InteractionCommon.tsx and Sun.tsx are the files every audit flags as too large, and both kept growing anyway - each polish pass landed inside them. This moves the pieces that don't need the component into tested modules next to them, and adds a ratchet test that pins both files at their new size so a change can't quietly add to either. - interactionCommonHelpers.ts: the widget-line match and the two DOM probes that were module-level in InteractionCommon - interactionCornerSettle.ts: the Little Sun corner settle (arriving / departing, per platform, honouring Android's dragged rest centre) and the platform-sized phase settle - sun/sunGeometry.ts: anchor point for a settle, rest scale, and the rendered-translate parse - sun/sunGlow.ts: the rest/hover glow constants with their reasoning, the glow-axis temperature read, and the pointer-feedback scale - the interaction's cleanup lists its frames and timeouts instead of eleven copies of the same if-block Behaviour is unchanged; the extracted functions are covered by unit tests, and the full suite, typecheck, and production build pass. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vfDHpx2YT8CkxPPATgigc
…lays From an adversarial and a normal review of the branch: - journal import on the extension: answers live in one browser sync item of a few kilobytes, so a phone's journal was rejected wholesale. The import now brings back the most recent imported answers that fit, never touching the device's own, and says so plainly; a non-quota failure gets a neutral message instead of a guessed cause. The quota check moves to a platform-neutral module so the app bundles don't pull in the extension's storage code. - journal entries are rebuilt from known fields only; oversized picks are refused before parsing - Android "save a copy": the export is staged in a cache file, so a process reclaimed behind the system picker can no longer leave the chosen document empty; a second tap while the sheet is up is ignored - detection line: sits above the optional-permissions invite (which says "minded already works"), and the state is re-read shortly after mount so a cold-start bind race can't leave a stale line standing - CommonWindow owns the loading-sky shield behind one flag instead of two copies in the intervention and wind-down windows - Play internal and release builds run the Android unit suite before bundleRelease (#151) - copy: drop the "stays on this device" claim (untrue on the extension); the size ratchet gets a few lines of headroom; README lists the new checks and no longer names a landing-page directory that isn't here Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vfDHpx2YT8CkxPPATgigc
The review-fix edit that staged the export in a cache file replaced the whole span between saveTextFile and onCreate, taking the companion object (widget intent extras, fade constants) and the intent-route helpers with it. CI's first Kotlin compile of the branch caught it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vfDHpx2YT8CkxPPATgigc
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.
tsc --noEmitnever ran in CI (#152) and did not pass: the ambient assetdeclarations in global.d.ts sat in a file that a top-level
import typehad turned into a module, so every scss/svg/mp3 import failed to resolve,
and without skipLibCheck third-party typings failed too. That noise hid a
handful of real errors: a timer id typed as NodeJS.Timeout in a browser
file, a manifest override read off an untyped JSON import, and the
background message listener's implicitly-any parameters.
npm run typecheckand a CI step for itCo-Authored-By: Claude Fable 5.1 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_012vfDHpx2YT8CkxPPATgigc