feat: quick notes from Siri and Shortcuts on iOS - #1096
Conversation
Plans hands-free one-liner capture on iOS: an app-target QuickNoteIntent spooling text envelopes into the existing App Group capture inbox, plus a drain refinement so consecutive text captures coalesce into one bullet list in the daily note. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughAdds the Quick Note Intent plan and implements source-aware text capture. Text captures use list-aware insertion, allow duplicates, and support the ChangesQuick Note Capture
Estimated code review effort: 3 (Moderate) | ~20 minutes Mergeability Score: ⚪ Minimal · up to The change adds iOS quick capture and bullet-list coalescing, with checks reported as passing; no actionable merge-blocking risk remains in the supplied evidence. Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
docs/plans/24-quick-note-intent.md (2)
188-200: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winAdd an
ios-intentprivate-note regression test.Test an
ios-intentenvelope against a daily note withprivate: true. Assert that only the local daily file changes and that external scraping and description calls remain unused.As per coding guidelines, notes marked
private: truemust never have their content sent to any external service.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/plans/24-quick-note-intent.md` around lines 188 - 200, Add a targeted ios-intent regression test covering an envelope routed to a daily note marked private: true. Assert that only the local daily file is modified, while external scraping and description calls are not invoked, preserving the privacy boundary for private notes.Source: Coding guidelines
163-168: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winUse
supportedModesfor background execution.Replace
openAppWhenRun = falsewithsupportedModes: IntentModes = .background. Retain the@available(iOS 16.0, *)guard for the iOS 15 deployment target.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/plans/24-quick-note-intent.md` around lines 163 - 168, Update the quick-note intent configuration to replace openAppWhenRun = false with supportedModes: IntentModes = .background, while retaining the `@available`(iOS 16.0, *) guard for the iOS 15 deployment target.Source: MCP tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/plans/24-quick-note-intent.md`:
- Around line 169-172: Update the plan’s authenticationPolicy guidance to
explicitly use .requiresLocalDeviceAuthentication rather than relying on the
default .alwaysAllowed policy, unless cross-device authentication is
intentionally supported. Require verification of Face ID and locked-device flows
before describing authentication as invisible, and ensure the stated security
contract matches the implementation.
- Around line 121-128: Update the quick-note list-joining logic described in the
plan to preserve the matched list item’s indentation and bullet marker when
appending the new line, so nested lists and transitions such as + [ ] to -
remain one list. Alternatively restrict matching to the canonical prefix, but do
not append an unchanged line that can change the list structure; add coverage
for * tails and task-to-append transitions while continuing to use
documentLineEnding.
- Around line 209-212: Update the Siri phrase wording guidance in the quick-note
intent plan to treat App Shortcut phrases as user-facing metadata: test
alternative variants, including avoiding potential Apple Notes collisions,
before finalizing and shipping the phrase list.
- Around line 149-153: Update every spoolText call site to pass the new explicit
source argument: change the existing caller in ShareState to use "ios-share" and
update QuickNoteIntent to use "ios-intent". Ensure no callers retain the old
spoolText signature.
---
Nitpick comments:
In `@docs/plans/24-quick-note-intent.md`:
- Around line 188-200: Add a targeted ios-intent regression test covering an
envelope routed to a daily note marked private: true. Assert that only the local
daily file is modified, while external scraping and description calls are not
invoked, preserving the privacy boundary for private notes.
- Around line 163-168: Update the quick-note intent configuration to replace
openAppWhenRun = false with supportedModes: IntentModes = .background, while
retaining the `@available`(iOS 16.0, *) guard for the iOS 15 deployment target.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: fb36be70-34f4-4b22-acad-efb5ba74cfe4
📒 Files selected for processing (1)
docs/plans/24-quick-note-intent.md
- appendListItem normalizes the continuation marker (CommonMark treats the marker as list structure), with the round task marker exempt - dedup scan becomes marker-insensitive to match - authenticationPolicy set explicitly (Apple's default is alwaysAllowed) - spoolText call site corrected to ShareState.swift, no default arg - App Shortcut phrases acknowledged as live-on-install metadata - private-note drain regression test added to Phase 1 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/plans/24-quick-note-intent.md`:
- Around line 192-198: Update QuickNoteIntent.authenticationPolicy to
.requiresLocalDeviceAuthentication so the intent cannot access the App Group
file until the iPhone running it is unlocked; alternatively, document and verify
the cross-device execution contract before retaining .requiresAuthentication.
- Line 123: Update the inline-code spans on the referenced list examples in
docs/plans/24-quick-note-intent.md so no code span has leading or trailing
spaces; keep the literal spaces outside the backticks while preserving the
displayed Markdown examples and meaning.
- Around line 129-136: The marker normalization rules in the quick-note
serialization must keep checkbox output distinguishable from task output. Update
checkbox normalization so it never selects “+” (or persist explicit kind
metadata), while preserving task’s “+ [ ] text” representation; add coverage for
a checkbox following a “+” list and retries that change between checkbox and
task kinds.
- Around line 124-132: Update the list-item detection described in the
quick-note append flow to parse marker indentation relative to its containing
list item, allowing valid four-space nested markers such as the final item in “-
foo”, “ - bar”, “ - baz” to coalesce instead of falling back to appendBlock.
Preserve marker normalization from the last column-0 item and add coverage for
this four-space nested-list case.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6abc634d-696a-493b-9557-b984cc29fd7d
📒 Files selected for processing (1)
docs/plans/24-quick-note-intent.md
- checkbox never adopts the + marker, keeping + [ ] unambiguously a task; kind is now recoverable from the line form, and dedup matches within a kind only - list-tail detection walks any-indent list runs anchored at a column-0 item, so four-space nested markers coalesce while indented code blocks still fall back - authenticationPolicy tightened to .requiresLocalDeviceAuthentication (requiresAuthentication permits a locked iPhone via an unlocked Watch) - MD038 code-span fixes Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- appendListItem becomes parser-based in append-list-item.ts, reusing listMark and the BulletList machinery instead of a line-regex walk; join rules collapse to marker compatibility per kind - duplicates allowed (Alex): drop the same-line dedup scan for text captures, accepting the rare crash-retry duplicate - new Phase 0 spike gating the Swift work: verify background-launching the Tauri app for an in-app intent is crash-free and fast - QuickNoteIntent return type and needsValueError spelled out Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a QuickNoteIntent App Intent (Plan 24): "Add a note in Reflect" via Siri, the Shortcuts app, a lock-screen Shortcuts widget, or the Action button spools a text envelope into the App Group capture inbox, and the app appends it to the capture-day daily note on next launch/foreground. Drain changes: text captures now coalesce into the daily note's trailing bullet list (parser-based appendListItem, adopting the list's marker; checkbox never adopts + and task never leaves it, so the Tasks projection stays unambiguous), and the same-line dedup is removed — duplicate quick notes are allowed by design. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Intent ran with the app killed, no app process lingered and the webview never booted; envelope schema-exact and drained on next launch; two captures coalesced into one bullet list (raw bytes verified). Physical device pass remains before TestFlight. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
What
Quick capture on iOS (Plan 24,
docs/plans/24-quick-note-intent.md): "Hey Siri, add a note in Reflect" — or the Shortcuts app, a lock-screen Shortcuts widget, or the Action button — appends a one-liner to the capture-day daily note. Successive quick notes grow one bullet list instead of gap-separated single-item lists.How
A new
QuickNoteIntent(app target, beside the recording intents) spools aTextCaptureEnvelopewithsource: "ios-intent"into the existing App Group capture inbox through the share extension'sCaptureInbox(now compiled into the app target too). The app relays + drains on next launch/foreground — durability, not visibility, so the Siri dialog says "Saved".authenticationPolicyis explicitly.requiresLocalDeviceAuthentication.Drain changes (all text-capture sources, deliberately):
drainTextCapturenow uses a parser-basedappendListItem(built onappend-list-item.ts's existinglistMark/BulletListmachinery): joins the note's trailing bullet list with the list's own marker.checkboxnever adopts+andtasknever leaves it, so+ [ ]stays unambiguously a task for the Tasks projection.Testing
pnpm checkpasses; 184 vitest tests green acrossappend-list-item.test.ts(new, 19 cases: markers, nesting incl. four-space, code blocks, fences, CRLF, frontmatter),capture-drain.test.ts(coalescing, duplicates-allowed, ios-intent, checkbox-vs-task, private daily),capture-envelope.test.ts, and the wire-message parity suite.xcodegen generaterun; pbxproj diff inspected and limited to the two source additions plus awake.rscatch-up.Still owed before TestFlight: the Phase 0 spike (background-launching the Tauri app for an in-app intent — crash-free, acceptable Siri latency) and the Phase 3 simulator/device pass (Siri phrase from lock screen, Action button, dev-flavor App Group isolation). The plan doc tracks these as the shipping gate.
Risks
reflect://append) and share-sheet behavior too — intended, noted in the plan.RecordingWidget's entitlement/signing path is untouched; the intent needs no new entitlements (the app already carries the App Group).🤖 Generated with Claude Code
Note
Medium Risk
Changes daily-note behavior for every text producer (share sheet, deep links, intent), not only Siri; iOS intent and App Group writes add a new capture surface though simulator validation is documented.
Overview
Adds Plan 24 quick capture on iOS: a new
QuickNoteIntentspools one-line text into the existing App Group inbox (source: "ios-intent") via sharedCaptureInbox.swiftin the app target, with Siri/Shortcuts phrases registered beside the recording intents. The intent usesopenAppWhenRun = false, returns "Saved" after durability (not visibility), and sets.requiresLocalDeviceAuthenticationuntil locked-device App Group writes are verified.Drain / schema (all text capture sources):
ios-intentis accepted on text envelopes;spoolTextnow requires an explicitsourceat every producer. Text drains use parser-basedappendListItemso successive captures join the trailing bullet list (marker rules keep+ [ ]tasks distinct from checkboxes). The same-line dedup scan is removed—identical text can appear twice;dedupedis link-capture-only.Vitest covers coalescing, duplicates,
ios-intent, and marker edge cases; the plan doc records simulator verification; physical-device Siri/Action-button pass remains before TestFlight.Reviewed by Cursor Bugbot for commit 1f4a386. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
New Features
Improvements