Ancla — Creative Improvement Ideas Report
Generated: 2026-04-19
Scope: iOS codebase at ios/ — architecture, features, UX, testing, CI/CD, ecosystem
Repository: Microck/ancla (single commit 5889ef5)
Executive Summary
Ancla is a well-structured iOS app that combines Screen Time API (FamilyControls/ManagedSettings) with physical NFC stickers to create a hardware-enforced digital wellness lock. The architecture uses clean protocol-based dependency injection and a shared core Swift package. However, the codebase has a single 1,430-line god-object ViewModel (AppViewModel), no CI/CD pipeline, limited App Intents, and several missed opportunities to leverage its unique physical-digital lock position. Below are 8 concrete improvement ideas ranked by impact-to-effort ratio.
Idea 1: Decompose the God ViewModel into Domain-Coordinated Services
Severity: 🔴 High (architectural debt)
Estimated Effort: Large
Potential Impact: High
Problem
ios/ancla-app/app-view-model.swift (1,430 lines) handles all business logic: authorization, NFC pairing, session lifecycle, mode CRUD, schedule CRUD, preset CRUD, temporary unlock timer management, paragraph challenges, schedule sync, diagnostics, and persistence orchestration. Every view binds to a single @Bindable var viewModel: AppViewModel.
This creates:
- Merge conflict magnet — any two developers working on features touch the same file
- Test explosion — every test file imports the full dependency graph
- Cognitive overload — 80+
var/func members on one type
Recommendation
Extract domain-specific coordinators behind protocols, each owning a slice of the AppSnapshot:
| New Type |
Responsibility |
File |
SessionCoordinator |
arm, release, emergency unbrick, paragraph challenge |
ancla-app/coordinators/session-coordinator.swift |
ModeCoordinator |
CRUD for BlockMode, default selection |
ancla-app/coordinators/mode-coordinator.swift |
ScheduleCoordinator |
CRUD for ScheduledSessionPlan, sync logic |
ancla-app/coordinators/schedule-coordinator.swift |
AnchorCoordinator |
pair, rename, unpair NFC stickers |
ancla-app/coordinators/anchor-coordinator.swift |
UnlockCoordinator |
presets, temporary unlock timer, re-shield |
ancla-app/coordinators/unlock-coordinator.swift |
AppViewModel becomes a thin façade that holds the AppSnapshot and delegates to coordinators. Views receive only the coordinator they need.
Files touched:
ios/ancla-app/app-view-model.swift (refactor from 1,430 → ~200 lines)
- New:
ios/ancla-app/coordinators/*.swift (5 new files)
ios/ancla-app/content-view.swift (update bindings)
ios/ancla-app/lock-screen-view.swift (update bindings)
ios/ancla-tests/app-view-model-tests.swift (update imports/fakes)
Idea 2: Session Analytics Dashboard — "Your Anchor Report"
Severity: 🟡 Medium (feature gap)
Estimated Effort: Medium
Potential Impact: High
Problem
The app records rich SessionHistoryEntry data (mode name, anchor name, armed/released timestamps, release method) but only displays it as a flat "Recent" list (ios/ancla-app/content-view.swift, lines 499+). There's no aggregation: no weekly streak, no total hours anchored, no breakdown by mode, no visual chart. Users have no feedback loop to reinforce behavior change.
Recommendation
Add a read-only analytics view accessible from the home screen:
- Weekly/Monthly streak — consecutive days with at least one completed session
- Total anchored hours — sum of
SessionHistoryEntry.duration over time windows
- Mode breakdown — pie chart or bar chart showing time per mode
- Release method histogram — anchor vs. emergency vs. paragraph challenge vs. schedule
- Prune old history — cap
sessionHistory at 365 entries, archive older ones to a separate cold-store
Implementation approach:
- New file:
ios/ancla-app/analytics-view.swift (SwiftUI Charts)
- New file:
ios/ancla-shared/ancla-analytics.swift (pure functions for aggregation — testable in AnclaCore SPM target)
- Extend
AnclaCore with static func aggregatedStats(in snapshot:AppSnapshot, from:Date, to:Date) -> SessionStats
- Add a new tab or section in
ContentView
Files touched:
ios/ancla-shared/ancla-core.swift (add analytics functions)
- New:
ios/ancla-app/analytics-view.swift
- New:
ios/ancla-shared/ancla-analytics.swift
ios/ancla-app/content-view.swift (add navigation to analytics)
ios/ancla-core-tests/ancla-core-tests.swift (add analytics tests)
ios/ancla-shared/ancla-models.swift (add SessionStats model)
Idea 3: Live Activity & Lock Screen Widget for Active Sessions
Severity: 🟡 Medium (UX gap)
Estimated Effort: Medium
Potential Impact: High
Problem
When a session is armed, the user must open the Ancla app to see status or tap to unlock. There's no presence on the Lock Screen or Dynamic Island. This is a missed opportunity for the app's core value proposition — the lock screen is exactly where an "anchored" indicator belongs.
Recommendation
Add a ActivityKit Live Activity that displays:
- Armed duration (elapsed timer since
armedAt)
- Active mode name
- Quick-access "Scan Anchor" button (deep link into the app's NFC scan flow)
- Ending state when released (shows total duration for 30 seconds)
Implementation:
- New target:
AnclaLiveActivity (Widget Extension)
- Define
AnchorActivityAttributes with AnchorActivityContentState (mode name, armed date)
- Start the Live Activity in
AppViewModel.arm(mode:)
- End it in
completeRelease()
- Read shared state from
AppGroupStore (already shared via app group group.dev.micr.ancla)
Files touched:
- New target:
ios/ancla-live-activity/ (WidgetKit extension)
ios/project.yml (add target)
ios/ancla-app/app-view-model.swift (start/end Live Activity calls)
ios/ancla-shared/ancla-models.swift (add AnchorActivityAttributes)
ios/ancla-shared/ancla-store.swift (share activity state via app group)
Idea 4: Expand App Intents — "Arm Mode" & "Release Session" Shortcuts
Severity: 🟡 Medium (ecosystem gap)
Estimated Effort: Small
Potential Impact: Medium
Problem
ios/ancla-app/shortcuts-intents.swift currently exposes only one App Intent: CheckBlockStatusIntent (read-only boolean). The app's most valuable actions — arming a mode and releasing a session — are not available to Shortcuts automation. This means users cannot create automations like "When I arrive at work, arm Work mode" or "At bedtime, arm Sleep mode."
Recommendation
Add two new intents:
ArmModeIntent — Takes a mode name as parameter, triggers NFC scan, arms the session. Returns success/failure.
ReleaseActiveSessionIntent — Triggers NFC scan, releases the active session. Returns success/failure.
ListModesIntent — Returns the list of saved mode names (for Shortcuts UI pickers).
Also expose these as Focus Filters so a "Work" Focus can auto-arm the Work mode.
Files touched:
ios/ancla-app/shortcuts-intents.swift (add 3 new intents)
ios/ancla-shared/ancla-dependencies.swift (ensure store access for intents)
ios/project.yml (update if needed for intent definitions)
Idea 5: NFC Tag Write-Once Challenge — Anti-Cheating Anchor Binding
Severity: 🟢 Low (security hardening)
Estimated Effort: Medium
Potential Impact: Medium
Problem
Currently, StickerPairingService (in ios/ancla-shared/ancla-services.swift) only reads the NFC tag UID and hashes it. Any NFC tag with the same UID can be substituted. A determined user could clone a tag UID or use a programmable NFC tag to bypass the physical lock. The app hashes the UID with SHA-256 (TagFingerprint.hash), but this only prevents casual duplication — not active bypass.
Recommendation
Implement a challenge-response protocol using NDEF or tag-specific commands:
- During pairing: Write a random 32-byte secret to the NFC tag's user memory (NDEF record or raw block). Store
SHA256(uid + secret) as the uidHash.
- During arm/release: Read the secret back from the tag. Verify
SHA256(scannedUID + scannedSecret) == storedUidHash.
- This makes tag cloning insufficient — the attacker needs both the UID and the stored secret.
Requires:
NFCTagReaderSession → connect to tag → read/write specific NDEF or data blocks
- Only works with writable NFC tags (NTAG213/215/216 or MiFare DESFire), which is realistic for dedicated "anchor" stickers
Files touched:
ios/ancla-shared/ancla-services.swift (add write/read secret logic to StickerPairingService)
ios/ancla-shared/ancla-models.swift (extend PairedTag if needed)
ios/ancla-core-tests/ancla-core-tests.swift (verify hash logic)
ios/ancla-tests/app-view-model-tests.swift (update pairing test expectations)
Idea 6: CI/CD Pipeline with Xcode Cloud or GitHub Actions
Severity: 🔴 High (infrastructure gap)
Estimated Effort: Small
Potential Impact: Medium
Problem
There is no CI/CD configuration in the repository — no .github/workflows/, no xcode-cloud config, no Fastfile, no Makefile. The project uses XcodeGen (project.yml) but has no automated build/test pipeline. Core tests (AnclaCoreTests via Package.swift) could run on any Linux/macOS runner, but aren't wired up.
Recommendation
Add a two-tier CI pipeline:
Tier 1 — Core Tests (GitHub Actions, runs on every PR):
# .github/workflows/core-tests.yml
name: Core Tests
on: [push, pull_request]
jobs:
test:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- run: cd ios && swift test
Tier 2 — Full Build + UI Tests (Xcode Cloud):
- Add
ciserver/xcode-cloud.yml or configure via Xcode Cloud dashboard
- Build the full
Ancla scheme
- Run
AnclaTests target
- Archive and distribute to TestFlight on
main branch merges
Also add a Makefile for common developer commands:
generate: cd ios && xcodegen generate
test-core: cd ios && swift test
build: xcodebuild -scheme Ancla -destination 'platform=iOS Simulator,name=iPhone 16'
Files touched:
- New:
.github/workflows/core-tests.yml
- New:
Makefile
- Optional:
ios/ciserver/xcode-cloud.yml
Idea 7: Context-Aware Shield Extension — Dynamic Messaging
Severity: 🟢 Low (UX polish)
Estimated Effort: Small
Potential Impact: Medium
Problem
ios/ancla-shield-extension/shield-configuration-extension.swift shows a static shield UI with just the mode name and anchor name. It reads the AppSnapshot every time, but doesn't use contextual information like:
- How long the session has been active (motivational: "You've been focused for 2h 14m")
- Scheduled end time (if from a schedule: "This session ends at 5:00 PM")
- Temporary unlock cooldown (if one was just used: "Last unlock ended 3 min ago")
- Custom per-mode messages (user could set a personal reminder like "You chose this")
Recommendation
Enhance ShieldConfigurationExtension.makeConfiguration(title:) to:
- Calculate elapsed time since
armedAt and display in subtitle: "45 minutes anchored. Scan Desk anchor to release."
- If
scheduledPlanID is set, look up the plan's endMinuteOfDay and show: "Scheduled until 5:00 PM."
- Add an optional
motivationalMessage: String? field to BlockMode that users can customize per mode
- Show remaining emergency unbricks count when relevant
Files touched:
ios/ancla-shield-extension/shield-configuration-extension.swift (enhance makeConfiguration)
ios/ancla-shared/ancla-models.swift (add optional motivationalMessage to BlockMode)
ios/ancla-app/mode-editor-view.swift (add motivational message text field)
Idea 8: Anchor Proximity Awareness via Background NFC Tag Reading
Severity: 🟢 Low (advanced feature)
Estimated Effort: Large
Potential Impact: High
Problem
Currently, the user must open the Ancla app and explicitly scan NFC to arm or release. This creates friction. iOS supports background NFC tag reading — when the iPhone screen is on and the device detects an NFC tag, it can present a notification to open the associated app automatically via NDEF URI records.
Recommendation
Implement a two-phase NFC experience:
- NDEF URI on anchor tags: During pairing, write an NDEF record to the tag with a custom URL scheme like
ancla://anchor/{tagId}. iOS will show a notification when the phone is near the anchor.
- Background tag reading: Register the URL scheme in
Info.plist. When the user taps the iOS system NFC notification, Ancla opens directly to the NFC scan/release flow — reducing the steps from "unlock phone → find Ancla → tap scan" to just "tap the system notification."
- Future: CoreNFC background tag reading session — on supported hardware, detect the anchor tag without even opening the app, and surface a Lock Screen action button.
This is the app's killer differentiator: NFC stickers that the phone recognizes passively, not just active scan-to-unlock. It transforms Ancla from "app you open" to "physical environment that enforces digital boundaries."
Files touched:
ios/ancla-shared/ancla-services.swift (add NDEF write during pairing)
ios/ancla-app/Info.plist (register URL scheme)
- New:
ios/ancla-app/ancla-deep-link-handler.swift
ios/ancla-app/ancla-app.swift (handle incoming URL)
ios/ancla-lite/ancla-lite-support.swift (update LiteStickerPairingService for testing)
Priority Matrix
| # |
Idea |
Effort |
Impact |
Priority |
| 6 |
CI/CD Pipeline |
Small |
Medium |
P0 — Ship immediately |
| 4 |
Expand App Intents |
Small |
Medium |
P0 — Quick win |
| 7 |
Context-Aware Shield Extension |
Small |
Medium |
P1 — Next sprint |
| 2 |
Session Analytics Dashboard |
Medium |
High |
P1 — High value feature |
| 3 |
Live Activity & Lock Screen Widget |
Medium |
High |
P1 — Key UX improvement |
| 1 |
Decompose God ViewModel |
Large |
High |
P2 — Technical debt |
| 5 |
NFC Challenge-Response Protocol |
Medium |
Medium |
P2 — Security hardening |
| 8 |
Anchor Proximity Awareness |
Large |
High |
P3 — Strategic bet |
Quick Wins (< 1 day each)
These can be implemented immediately with minimal risk:
- Cap
sessionHistory — Add pruning in AnclaCore.recordHistory() to keep only the last 365 entries. Prevents unbounded JSON growth in ancla-snapshot.json.
- Add
swift-format configuration — The codebase is consistent but has no automated formatter. Add a .swift-format config and a git pre-commit hook.
- Error logging —
lastError is a plain String?. Add structured logging via os.Logger so crashes and errors are visible in Xcode Organizer.
- Localization preparation — All UI strings are hardcoded. Wrap in
String(localized:) or NSLocalizedString for future i18n.
- Screenshot tests — The SwiftUI views (
LockScreenView, ParagraphChallengeSheet) are perfect candidates for Xcode's screenshot testing to prevent visual regressions.
Architecture Strengths to Preserve
- Protocol-based DI (
AppSnapshotStore, Shielding, StickerPairing, AuthorizationClienting, ScheduleNotifying) — excellent testability
AnclaCore SPM package — pure Swift, no UIKit/SwiftUI dependency, runs on Linux
- Dual build variants (
full vs sideloadLite) via compilation conditions
- Backward-compatible decoding (
decodeIfPresent everywhere in AppSnapshot.init(from:))
InMemorySnapshotStore + FakeShieldingService + FakeStickerPairingService in tests — comprehensive fakes
End of report. Each idea includes specific file paths and is scoped to be actionable in a 1-4 week development cycle.
Ancla — Creative Improvement Ideas Report
Generated: 2026-04-19
Scope: iOS codebase at
ios/— architecture, features, UX, testing, CI/CD, ecosystemRepository: Microck/ancla (single commit
5889ef5)Executive Summary
Ancla is a well-structured iOS app that combines Screen Time API (
FamilyControls/ManagedSettings) with physical NFC stickers to create a hardware-enforced digital wellness lock. The architecture uses clean protocol-based dependency injection and a shared core Swift package. However, the codebase has a single 1,430-line god-object ViewModel (AppViewModel), no CI/CD pipeline, limited App Intents, and several missed opportunities to leverage its unique physical-digital lock position. Below are 8 concrete improvement ideas ranked by impact-to-effort ratio.Idea 1: Decompose the God ViewModel into Domain-Coordinated Services
Severity: 🔴 High (architectural debt)
Estimated Effort: Large
Potential Impact: High
Problem
ios/ancla-app/app-view-model.swift(1,430 lines) handles all business logic: authorization, NFC pairing, session lifecycle, mode CRUD, schedule CRUD, preset CRUD, temporary unlock timer management, paragraph challenges, schedule sync, diagnostics, and persistence orchestration. Every view binds to a single@Bindable var viewModel: AppViewModel.This creates:
var/funcmembers on one typeRecommendation
Extract domain-specific coordinators behind protocols, each owning a slice of the
AppSnapshot:SessionCoordinatorancla-app/coordinators/session-coordinator.swiftModeCoordinatorBlockMode, default selectionancla-app/coordinators/mode-coordinator.swiftScheduleCoordinatorScheduledSessionPlan, sync logicancla-app/coordinators/schedule-coordinator.swiftAnchorCoordinatorancla-app/coordinators/anchor-coordinator.swiftUnlockCoordinatorancla-app/coordinators/unlock-coordinator.swiftAppViewModelbecomes a thin façade that holds theAppSnapshotand delegates to coordinators. Views receive only the coordinator they need.Files touched:
ios/ancla-app/app-view-model.swift(refactor from 1,430 → ~200 lines)ios/ancla-app/coordinators/*.swift(5 new files)ios/ancla-app/content-view.swift(update bindings)ios/ancla-app/lock-screen-view.swift(update bindings)ios/ancla-tests/app-view-model-tests.swift(update imports/fakes)Idea 2: Session Analytics Dashboard — "Your Anchor Report"
Severity: 🟡 Medium (feature gap)
Estimated Effort: Medium
Potential Impact: High
Problem
The app records rich
SessionHistoryEntrydata (mode name, anchor name, armed/released timestamps, release method) but only displays it as a flat "Recent" list (ios/ancla-app/content-view.swift, lines 499+). There's no aggregation: no weekly streak, no total hours anchored, no breakdown by mode, no visual chart. Users have no feedback loop to reinforce behavior change.Recommendation
Add a read-only analytics view accessible from the home screen:
SessionHistoryEntry.durationover time windowssessionHistoryat 365 entries, archive older ones to a separate cold-storeImplementation approach:
ios/ancla-app/analytics-view.swift(SwiftUI Charts)ios/ancla-shared/ancla-analytics.swift(pure functions for aggregation — testable inAnclaCoreSPM target)AnclaCorewithstatic func aggregatedStats(in snapshot:AppSnapshot, from:Date, to:Date) -> SessionStatsContentViewFiles touched:
ios/ancla-shared/ancla-core.swift(add analytics functions)ios/ancla-app/analytics-view.swiftios/ancla-shared/ancla-analytics.swiftios/ancla-app/content-view.swift(add navigation to analytics)ios/ancla-core-tests/ancla-core-tests.swift(add analytics tests)ios/ancla-shared/ancla-models.swift(addSessionStatsmodel)Idea 3: Live Activity & Lock Screen Widget for Active Sessions
Severity: 🟡 Medium (UX gap)
Estimated Effort: Medium
Potential Impact: High
Problem
When a session is armed, the user must open the Ancla app to see status or tap to unlock. There's no presence on the Lock Screen or Dynamic Island. This is a missed opportunity for the app's core value proposition — the lock screen is exactly where an "anchored" indicator belongs.
Recommendation
Add a
ActivityKitLive Activity that displays:armedAt)Implementation:
AnclaLiveActivity(Widget Extension)AnchorActivityAttributeswithAnchorActivityContentState(mode name, armed date)AppViewModel.arm(mode:)completeRelease()AppGroupStore(already shared via app groupgroup.dev.micr.ancla)Files touched:
ios/ancla-live-activity/(WidgetKit extension)ios/project.yml(add target)ios/ancla-app/app-view-model.swift(start/end Live Activity calls)ios/ancla-shared/ancla-models.swift(addAnchorActivityAttributes)ios/ancla-shared/ancla-store.swift(share activity state via app group)Idea 4: Expand App Intents — "Arm Mode" & "Release Session" Shortcuts
Severity: 🟡 Medium (ecosystem gap)
Estimated Effort: Small
Potential Impact: Medium
Problem
ios/ancla-app/shortcuts-intents.swiftcurrently exposes only one App Intent:CheckBlockStatusIntent(read-only boolean). The app's most valuable actions — arming a mode and releasing a session — are not available to Shortcuts automation. This means users cannot create automations like "When I arrive at work, arm Work mode" or "At bedtime, arm Sleep mode."Recommendation
Add two new intents:
ArmModeIntent— Takes a mode name as parameter, triggers NFC scan, arms the session. Returns success/failure.ReleaseActiveSessionIntent— Triggers NFC scan, releases the active session. Returns success/failure.ListModesIntent— Returns the list of saved mode names (for Shortcuts UI pickers).Also expose these as Focus Filters so a "Work" Focus can auto-arm the Work mode.
Files touched:
ios/ancla-app/shortcuts-intents.swift(add 3 new intents)ios/ancla-shared/ancla-dependencies.swift(ensure store access for intents)ios/project.yml(update if needed for intent definitions)Idea 5: NFC Tag Write-Once Challenge — Anti-Cheating Anchor Binding
Severity: 🟢 Low (security hardening)
Estimated Effort: Medium
Potential Impact: Medium
Problem
Currently,
StickerPairingService(inios/ancla-shared/ancla-services.swift) only reads the NFC tag UID and hashes it. Any NFC tag with the same UID can be substituted. A determined user could clone a tag UID or use a programmable NFC tag to bypass the physical lock. The app hashes the UID with SHA-256 (TagFingerprint.hash), but this only prevents casual duplication — not active bypass.Recommendation
Implement a challenge-response protocol using NDEF or tag-specific commands:
SHA256(uid + secret)as theuidHash.SHA256(scannedUID + scannedSecret) == storedUidHash.Requires:
NFCTagReaderSession→ connect to tag → read/write specific NDEF or data blocksFiles touched:
ios/ancla-shared/ancla-services.swift(add write/read secret logic toStickerPairingService)ios/ancla-shared/ancla-models.swift(extendPairedTagif needed)ios/ancla-core-tests/ancla-core-tests.swift(verify hash logic)ios/ancla-tests/app-view-model-tests.swift(update pairing test expectations)Idea 6: CI/CD Pipeline with Xcode Cloud or GitHub Actions
Severity: 🔴 High (infrastructure gap)
Estimated Effort: Small
Potential Impact: Medium
Problem
There is no CI/CD configuration in the repository — no
.github/workflows/, noxcode-cloudconfig, noFastfile, no Makefile. The project uses XcodeGen (project.yml) but has no automated build/test pipeline. Core tests (AnclaCoreTestsviaPackage.swift) could run on any Linux/macOS runner, but aren't wired up.Recommendation
Add a two-tier CI pipeline:
Tier 1 — Core Tests (GitHub Actions, runs on every PR):
Tier 2 — Full Build + UI Tests (Xcode Cloud):
ciserver/xcode-cloud.ymlor configure via Xcode Cloud dashboardAnclaschemeAnclaTeststargetmainbranch mergesAlso add a
Makefilefor common developer commands:Files touched:
.github/workflows/core-tests.ymlMakefileios/ciserver/xcode-cloud.ymlIdea 7: Context-Aware Shield Extension — Dynamic Messaging
Severity: 🟢 Low (UX polish)
Estimated Effort: Small
Potential Impact: Medium
Problem
ios/ancla-shield-extension/shield-configuration-extension.swiftshows a static shield UI with just the mode name and anchor name. It reads theAppSnapshotevery time, but doesn't use contextual information like:Recommendation
Enhance
ShieldConfigurationExtension.makeConfiguration(title:)to:armedAtand display in subtitle:"45 minutes anchored. Scan Desk anchor to release."scheduledPlanIDis set, look up the plan'sendMinuteOfDayand show:"Scheduled until 5:00 PM."motivationalMessage: String?field toBlockModethat users can customize per modeFiles touched:
ios/ancla-shield-extension/shield-configuration-extension.swift(enhancemakeConfiguration)ios/ancla-shared/ancla-models.swift(add optionalmotivationalMessagetoBlockMode)ios/ancla-app/mode-editor-view.swift(add motivational message text field)Idea 8: Anchor Proximity Awareness via Background NFC Tag Reading
Severity: 🟢 Low (advanced feature)
Estimated Effort: Large
Potential Impact: High
Problem
Currently, the user must open the Ancla app and explicitly scan NFC to arm or release. This creates friction. iOS supports background NFC tag reading — when the iPhone screen is on and the device detects an NFC tag, it can present a notification to open the associated app automatically via NDEF URI records.
Recommendation
Implement a two-phase NFC experience:
ancla://anchor/{tagId}. iOS will show a notification when the phone is near the anchor.Info.plist. When the user taps the iOS system NFC notification, Ancla opens directly to the NFC scan/release flow — reducing the steps from "unlock phone → find Ancla → tap scan" to just "tap the system notification."This is the app's killer differentiator: NFC stickers that the phone recognizes passively, not just active scan-to-unlock. It transforms Ancla from "app you open" to "physical environment that enforces digital boundaries."
Files touched:
ios/ancla-shared/ancla-services.swift(add NDEF write during pairing)ios/ancla-app/Info.plist(register URL scheme)ios/ancla-app/ancla-deep-link-handler.swiftios/ancla-app/ancla-app.swift(handle incoming URL)ios/ancla-lite/ancla-lite-support.swift(updateLiteStickerPairingServicefor testing)Priority Matrix
Quick Wins (< 1 day each)
These can be implemented immediately with minimal risk:
sessionHistory— Add pruning inAnclaCore.recordHistory()to keep only the last 365 entries. Prevents unbounded JSON growth inancla-snapshot.json.swift-formatconfiguration — The codebase is consistent but has no automated formatter. Add a.swift-formatconfig and a git pre-commit hook.lastErroris a plainString?. Add structured logging viaos.Loggerso crashes and errors are visible in Xcode Organizer.String(localized:)orNSLocalizedStringfor future i18n.LockScreenView,ParagraphChallengeSheet) are perfect candidates for Xcode's screenshot testing to prevent visual regressions.Architecture Strengths to Preserve
AppSnapshotStore,Shielding,StickerPairing,AuthorizationClienting,ScheduleNotifying) — excellent testabilityAnclaCoreSPM package — pure Swift, no UIKit/SwiftUI dependency, runs on LinuxfullvssideloadLite) via compilation conditionsdecodeIfPresenteverywhere inAppSnapshot.init(from:))InMemorySnapshotStore+FakeShieldingService+FakeStickerPairingServicein tests — comprehensive fakesEnd of report. Each idea includes specific file paths and is scoped to be actionable in a 1-4 week development cycle.