Conversation
Native Kotlin + Jetpack Compose app in android/, full parity with the Mac (search, wiki links, backlinks, R2 sync with three-way merge), a local-first app-private cache, and a debug-signed sideload APK. Adds the Android row to the root Platforms table. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Scaffold android/ per docs/PRD-android-v1.md: Gradle Kotlin DSL with a version catalog (AGP 8.5, Kotlin 2.0, Compose BOM), a single-Activity Compose app module (MainActivity + Material3 DayNight theme + placeholder screen), app-private storage posture (no storage/INTERNET permissions yet), an adaptive launcher icon placeholder, and the Gradle 8.7 wrapper. Builds to an installable debug APK (com.torchcodelab.seanboy.debug). Requires JDK 17+ and SDK 34 to compile — documented in android/README.md. The :core engine port and INTERNET/sync land in Milestone 1+. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the pure-Kotlin, Android-free :core module (mirrors mac/Sources/SeanboyCore) with a faithful port of Note/NoteNaming and NoteDocument: YAML-frontmatter parse/serialize, managed-key handling (id/seanboy-id/created/modified/deleted), byte-faithful preservation of unmanaged Obsidian frontmatter, foreign-id demotion to seanboy-id, and legacy title read-but-never-write. Timestamps use java.time.Instant truncated to millis so serialize->parse round-trips exactly. Ports the full NoteDocumentTests suite (8 tests) to JUnit4. NOTE: not yet compiler-verified in this environment (needs JDK 17 + SDK 34); run `./gradlew :core:test` to confirm. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port the rest of the pure-logic engine to :core, verified on JDK 17: - WikiLinkParser: wiki-link extraction, case-insensitive dedupe, backlinks - SearchService: ranked term search (title-prefix > title > body) - SigV4: AWS request signing with javax.crypto -- matches the AWS worked examples byte-for-byte (the PRD's highest-risk port) - SyncState + SyncPlanner: the pure three-way merge (in-memory state; JSON persistence follows with sync integration) Ports the SigV4, WikiLink/Search, and SyncPlanner test suites. Full run: 40 tests, 0 failures (NoteDocument 8, SigV4 4, SyncPlanner 19, WikiLink 5, Search 4) via gradlew :core:test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port the local-first storage layer to :core, adapted for Android's app-private folder (no system Trash -- delete removes the file and records a tombstone outside the notes folder): - NoteStore: recursive scan, filename-as-title, adoption of foreign Markdown (id injection), rename-on-title-edit (with case-only hop), reload reconciliation (external edit/rename/delete matched by id), wiki-link resolution across folders, applyRemote for sync. - TombstoneStore: per-device deleted-note records with JSON persistence matching the Mac format. The Mac-only LegacyMigration (old uuid.md files) is intentionally not ported -- an Android non-goal; the phone starts fresh. Full run: 57 tests, 0 failures (adds NoteStore 14, NoteNaming 3) via gradlew :core:test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port the minimal S3 client to :core: list (continuation-token paging), get, put (If-Match / If-None-Match conditional writes), delete (idempotent), copy -- signed with the already-verified SigV4 port. OkHttp replaces URLSession (works on both JVM and Android); SAX replaces Foundation XMLParser for ListObjectsV2 and error bodies. Adds OkHttp + mockwebserver deps and 6 MockWebServer tests exercising request shape, signing headers, conditional-write failures, and XML parsing -- coverage the Mac side never had. Full run: 63 tests, 0 failures via gradlew :core:test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire the engine end-to-end in :core: - SyncEngine: UI-free port of SyncService's sync sequence -- list notes + tombstones, download unseen objects, plan via SyncPlanner, upload with copy-on-overwrite versioning (pruned to a cap), apply remote changes (stashing displaced local edits to .versions/), delete obsolete keys, retry 412-blocked uploads. Debounce/observable status are left to the Android ViewModel. - SyncState JSON persistence via kotlinx.serialization (device-local file). Adds two MockWebServer integration tests driving a real NoteStore + planner + S3Client through push and pull round-trips, plus SyncState round-trip tests. Full run: 67 tests, 0 failures via gradlew :core:test. The :core engine (document, store, tombstones, wiki links, search, SigV4, three-way planner, S3 client, sync orchestration) is now complete and test-verified. Remaining PRD work is the Compose UI + app assembly, which needs Android SDK 34 to build. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire the :core engine into a functional single-Activity Compose app: - NotesViewModel: reactive search results, selected note, backlinks, and on-demand sync over the store + SyncEngine (engine work off the main thread via coroutines). - SeanboyApp UI: searchable notes list, editor with title/body plus a Links/Backlinks row that follows [[wiki links]] (creating on dead link), and an encrypted Sync settings screen. Sync fires on resume. - CredentialStore: R2/S3 config in EncryptedSharedPreferences (Keystore). - AppContainer: manual DI over the app-private files dir. Adds INTERNET permission, coroutines, lifecycle-viewmodel-compose, security-crypto, and the Material Components theme; exposes OkHttp as api from :core (S3Client's public constructor). Verified with `./gradlew :core:test :app:assembleDebug` on JDK 17 + SDK 34: 67 tests pass and app-debug.apk builds (com.torchcodelab.seanboy.debug, ~15 MB, launchable). Docs: android/README + root Platforms row updated; remaining follow-ups (folder tree, live Markdown styling, inline link taps, QR handoff) noted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the placeholder adaptive-icon vectors with the real Tomboy note+pencil artwork extracted from mac/Resources/AppIcon.icns. Foreground PNGs generated at all five densities (padded into the 108dp adaptive canvas so the mask never clips the notebook or pencil), over a white background. Matches the macOS app icon. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Summary
Adds the Android build of Seanboy (
android/) — native Kotlin + Jetpack Compose, local-first, on-demand R2 sync — plus its PRD. Implements the plan indocs/PRD-android-v1.mdthrough a functional, sideloadable debug APK.Built and verified locally on JDK 17 + Android SDK 34:
The APK is
com.torchcodelab.seanboy.debug(~15 MB, launchable "Seanboy").The engine (
:core) — pure Kotlin, 67 passing JVM testsFaithful clean-room port of
mac/Sources/SeanboyCore(no Swift reuse path — the port is validated against the same behavior and, where they exist, the same test vectors):NoteDocument/Note— frontmatter round-trip, Obsidian preservation, adoptionNoteStore+TombstoneStore— recursive scan, rename, external-change reconciliation, app-private deletesWikiLinkParser,SearchService— links, backlinks, ranked searchSigV4— matches the AWS worked examples byte-for-byte (the PRD's flagged highest-risk port)SyncPlanner— three-way merge: conflicts, clock skew, renames, tombstones, resurrectionS3Client(OkHttp/SAX) +SyncEngine, exercised against MockWebServer with real push/pull round-trips;SyncStatepersistenceThe app (
app/)Single-Activity Compose UI wiring the engine:
[[wiki link]]navigation (creates on dead link).EncryptedSharedPreferences/ Keystore).INTERNETthe only permission.Design decisions (confirmed during PRD)
Not done yet (polish — documented in
android/README.md)None of these touch the data model or bucket format, so notes still round-trip with the Mac:
Notes for reviewers
LegacyMigration(olduuid.mdfiles) is intentionally not ported — an Android non-goal; the phone starts fresh.minSdk 26is a placeholder (open question in the PRD) pending the two target devices' floor.🤖 Generated with Claude Code