feat(ios): Reve/Sense/Inspect tabs, mood, devices, deep-links, Face ID, widget polish, tests#128
Closed
oratis wants to merge 12 commits into
Closed
feat(ios): Reve/Sense/Inspect tabs, mood, devices, deep-links, Face ID, widget polish, tests#128oratis wants to merge 12 commits into
oratis wants to merge 12 commits into
Conversation
Settings → "Inspect Lisa" links to four GET-only screens (plan §G6,
Appendix B): Soul (identity / purpose / constitution + mood bars + values /
opinions / desires), Memory (user + memory text), Skills, Tools. A small
AsyncContent loader renders loading / error / content uniformly so each view
stays a thin wrapper over its fetch. Models mirror src/soul/types.ts and
/api/{soul,memory,skills,tools}, lenient (all-optional) so a missing field
never breaks decode.
Verified: ./build.sh -> BUILD SUCCEEDED.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New tab (plan Appendix B): a "while you were away" idle note + current desire (from /api/island/ping), an agent-activity recap over a 2h/8h/24h window (/api/agents/recap), and advisor suggestions (/api/advisor/latest) that can be dismissed — POST /api/advisor/dismiss feeds the server's down-weighting loop. Loader re-runs when the window changes or pairing flips on. Verified: ./build.sh -> BUILD SUCCEEDED. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New tab (plan §G6): per-signal consent state from /api/consent and the last ambient events from /api/sense/recent. Revoke-only by design — tightening consent is safe from anywhere, but granting a sensitive signal remotely would widen the surface, which the privacy floor (§7.2) keeps a Mac action; the footer points grants at the Mac. Revoke / revoke-all reload the list. Verified: ./build.sh -> BUILD SUCCEEDED. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A mood chip above the chat transcript, seeded from /api/island/ping and kept live via the `mood` SSE event. Honest scope: this wires the mood *data* (the unblocked part); it's a stand-in for the mood *portrait* — bundling the mac-client's portrait art is a follow-up (the iOS app has no asset catalog yet). Verified: ./build.sh -> BUILD SUCCEEDED. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Settings → "Paired devices" lists each per-device token (/api/devices) with platform + last-seen. Read-only on the phone: revoking is loopback-only on the server (a Mac-owner action), so the footer points there rather than offering a button that would 403. Verified: ./build.sh -> BUILD SUCCEEDED. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Dispatch tab's toolbar opens Lisa's own fire-and-forget dispatches (the ledger, distinct from the observed-agent roster): pid / task / alive from /api/dispatch/list, and a captured log tail per entry from /api/dispatch/status. The status endpoint is policy-gated, so a 403/404 just leaves the tail empty. Verified: ./build.sh -> BUILD SUCCEEDED. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The roster stream now reconnects on drop with exponential backoff (1→30s cap), doing a full /api/agents/sessions resync before each retry so transitions during the gap aren't lost; healthy traffic resets the backoff. On return to foreground (scenePhase → .active) it resyncs and reconnects, since iOS suspends SSE in the background. Previously a dropped stream just went silent until the next appear. Verified: ./build.sh -> BUILD SUCCEEDED. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
AgentCountWidget now also supports the lock-screen accessory families (.accessoryInline "▶ N active · ⏸ M stuck", .accessoryRectangular) alongside systemSmall/Medium, and the whole widget is a tap target via .widgetURL(lisapocket://roster). Registers the `lisapocket://` URL scheme (CFBundleURLTypes) — the app's deep-link handler (next commit) routes it; the same scheme backs the ntfy push Click URL. Verified: ./build.sh -> BUILD SUCCEEDED; CFBundleURLTypes present in the built Info.plist. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The app now handles its URL scheme (.onOpenURL): lisapocket://roster selects the Dispatch tab (the Widget's tap target); lisapocket://session?agent=&id= (the ntfy push Click) selects Dispatch and opens that session. RosterView drives a NavigationStack path and resolves the pending session once it's in the roster, tolerating either arrival order (link before or after the roster loads). Verified: ./build.sh -> BUILD SUCCEEDED. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The device token grants full control of the Mac's agents, so Settings → Security can require biometric unlock (LocalAuthentication, .deviceOwnerAuth → Face ID/Touch ID with passcode fallback). When armed + paired, the app locks at launch and re-locks on backgrounding; a full-screen LockView auto-prompts and offers a manual retry. If no auth is enrolled, it doesn't trap the user. Adds NSFaceIDUsageDescription. Verified: ./build.sh -> BUILD SUCCEEDED; NSFaceIDUsageDescription in the built Info.plist. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a hosted XCTest target (LisaPocketTests) covering the pure logic, and extracts that logic so it's testable in isolation: - rosterCounts(_:at:) — the Widget snapshot bucketing (pulled out of RosterModel.publishSnapshot). - AppState.parseDeepLink(_:) -> DeepLinkRoute — the lisapocket:// parse (pulled out of handleDeepLink), nonisolated so it runs off the main actor. Tests also cover sortRows ranking. build.sh gains a `test` action (`./build.sh test`) and project.yml a LisaPocket scheme wiring the test target. Verified: ./build.sh test -> Executed 8 tests, 0 failures (TEST SUCCEEDED) on the iOS 17 simulator. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reve / Sense tabs, mood indicator, Inspect Lisa, paired devices, Face ID lock, dispatch ledger, SSE auto-reconnect, widget accessory families + deep-links, and `./build.sh test`. Notes the remaining follow-ups (APNs Live-Activity refresh; real mood portrait art). Co-Authored-By: Claude Opus 4.8 <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.
The rest of the non-blocked iOS companion backlog (plan §G5/§G6, Appendix B). Stacked on #124 (QR scan + home Widget) — review/merge that first, or this can be retargeted to
mainonce #124 lands. Every commit is build-verified with./build.sh.New surfaces
moodSSE (a stand-in for portrait art, which needs an asset catalog — noted).Robustness / system
scenePhase..widgetURLtap target; registers thelisapocket://URL scheme..onOpenURLrouteslisapocket://roster(widget) andlisapocket://session?agent=&id=(the ntfy pushClickfrom feat(cli+push): Mac pairing QR (lisa pair) + ntfy deep-links #127) to the right session.Tests
LisaPocketTests) + extracted pure helpers (rosterCounts,AppState.parseDeepLink); covers bucketing, sort ranking, and deep-link parsing../build.sh test→ 8 tests, 0 failures on the iOS 17 simulator.Verification
./build.sh→ BUILD SUCCEEDED after every commit;./build.sh test→ TEST SUCCEEDED. Camera / Face ID usage strings, the App Group, and the URL scheme are confirmed present in the builtInfo.plist.Honest limits
APNs real-device push + Live-Activity remote refresh (Apple push key) and a real mood portrait (asset catalog) remain follow-ups; the App Group's runtime data only flows on a signed build (compile-verified on the Simulator).
🤖 Generated with Claude Code