Ida/contains the iOS app target shell (IdaApp.swift,AppIntents.swift,Info.plist, entitlements, app-level assets/strings).Modules/AppFeature/contains the main feature module (views, SQLiteData schema/migrations, reminders, feature assets/strings).- Core feature files currently include
ChildList.swift,ChildDetail.swift, andItemFormView.swift(view + model extractions). Modules/AppFeatureTests/contains unit tests forAppFeatureusing Swift Testing.Modules/Package.swiftdefines the local Swift package (AppFeature,AppFeatureTests) used by the app target.Modules/AppFeature.xctestplandefines the package test plan.Ida.xcworkspace/is the default entry point for local builds/tests and uses the shared schemes (Ida,Ida - Release,AppFeature,AppFeatureTests).Modules/.swiftpm/xcode/xcshareddata/xcschemes/AppFeatureTests.xcschemeis a committed package-level scheme for runningAppFeaturetests via XcodeBuildMCP without extra args.- If SwiftPM regenerates package schemes in
Modules/.swiftpm/xcode/xcshareddata/xcschemes/, keepAppFeatureTests.xcschemepresent alongsideAppFeature.xcscheme. ci_scripts/includes CI helper scripts used by Xcode Cloud.
Always use XcodeBuildMCP for local builds on the iPhone 17 simulator.
- Always use XcodeBuildMCP for debugging and app launching workflows (launch, log capture, screenshots, UI snapshots, stop/relaunch). Do not use non-MCP launch/debug flows.
- Boot iPhone 17 (once per session):
mcp__XcodeBuildMCP__session_set_defaultswithworkspacePath: "Ida.xcworkspace",scheme: "Ida",simulatorId: 27444936-D9E5-4E28-B81C-762DFF92FD21,configuration: "Debug",useLatestOS: truemcp__XcodeBuildMCP__boot_sim
- Build app:
mcp__XcodeBuildMCP__build_sim
- Build module scheme directly (optional):
mcp__XcodeBuildMCP__session_set_defaultswithscheme: "AppFeature"(keep same workspace/simulator defaults)mcp__XcodeBuildMCP__build_sim
- Run package tests (default):
mcp__XcodeBuildMCP__session_set_defaultswithscheme: "AppFeatureTests"(keep same workspace/simulator defaults)mcp__XcodeBuildMCP__test_sim
- Test status (current setup):
Idashared scheme is not configured with a test action.AppFeatureandAppFeatureTestsboth run the package tests when usingworkspacePath: "Ida.xcworkspace".AppFeatureTestsis the preferred MCP test scheme for clarity.
- Debug/launch/logging:
mcp__XcodeBuildMCP__launch_app_simmcp__XcodeBuildMCP__launch_app_logs_simmcp__XcodeBuildMCP__start_sim_log_capmcp__XcodeBuildMCP__stop_sim_log_capmcp__XcodeBuildMCP__screenshotmcp__XcodeBuildMCP__snapshot_uiRelease builds still use the shared scheme:
xcodebuild -workspace Ida.xcworkspace -scheme "Ida - Release" -configuration Release build
ACKNOWLEDGEMENTS.mdis a symlink toModules/AppFeature/Resources/ACKNOWLEDGEMENTS.md.- Generate acknowledgements with
tools/generate-third-party-acknowledgements.sh; by default it writesModules/AppFeature/Resources/ACKNOWLEDGEMENTS.md(accepts an optional explicit output path argument). - Regenerate acknowledgements whenever
Modules/Package.resolvedoriginHashchanges. - Keep this tracked value updated whenever acknowledgements are regenerated (the generator updates this line automatically):
- Last acknowledged
originHash:a55a115916a0d5b81ae345d4d9e79311ac88588865f26e67d55d202f90e9a06c
- Last acknowledged
- Use
tools/sourcekit-lsp-query.shfor semantic Swift inspection (symbols/hover/definition) before relying on plain text-only reads. - Run all LSP queries from repo root and set workspace to
.so paths resolve consistently. - If
sourcekit-lspcloses unexpectedly in sandboxed execution, rerun the same command outside sandbox/escalated mode. - Single-file usage:
tools/sourcekit-lsp-query.sh --workspace . symbols Modules/AppFeature/ChildList.swifttools/sourcekit-lsp-query.sh --workspace . hover Modules/AppFeature/ChildList.swift 31 8tools/sourcekit-lsp-query.sh --workspace . definition Modules/AppFeature/ChildList.swift 31 8
- Batch mode (one long-lived LSP session for many files):
tools/sourcekit-lsp-query.sh --workspace . symbols Modules/AppFeature/ChildList.swift Modules/AppFeature/ChildDetail.swift Modules/AppFeature/ItemFormView.swiftrg --files -g '*.swift' | xargs tools/sourcekit-lsp-query.sh --workspace . symbols
- Persistent cache reuse (faster repeated runs):
- Defaults already persist to
.lsp/scratchand.lsp/generated. - Optional override:
tools/sourcekit-lsp-query.sh --workspace . --scratch-path .lsp/custom-scratch --generated-files-path .lsp/custom-generated symbols Modules/AppFeature/ChildList.swift
- Defaults already persist to
- Incremental mode (changed Swift files only):
tools/sourcekit-lsp-query.sh --workspace . --changed-only symbolstools/sourcekit-lsp-query.sh --workspace . --changed-only --base-ref origin/main symbols
- JSONL output for large/batch runs:
tools/sourcekit-lsp-query.sh --workspace . --jsonl symbols Modules/AppFeature/ChildList.swift Modules/AppFeature/ChildDetail.swifttools/sourcekit-lsp-query.sh --workspace . --jsonl-path .lsp/sourcekit-results.jsonl --changed-only symbols
- Module-based parallelism (2-4 workers, long-lived LSP per worker):
tools/sourcekit-lsp-query.sh --workspace . --workers 3 symbols Ida/IdaApp.swift Modules/AppFeature/ChildList.swift Modules/AppFeatureTests/ChildListModelTests.swift- For repo-wide scans, prefer
--workers 2,--workers 3, or--workers 4based on machine load.
- Swift and SwiftUI code in
Ida/andModules/AppFeature/uses 2-space indentation; follow existing formatting. - Tests follow existing formatting.
- Types use PascalCase (e.g.,
ChildDetailView); properties and methods use camelCase. - File names usually follow feature grouping and may contain both view and model types (e.g.,
ChildList.swift,ChildDetail.swift). - Prefer keeping behavior local to the feature context, even if that means longer functions or larger files, when extracting/reusing code would increase the chance of accidental calls or unintended triggering.
- For SwiftUI controls that support tinting (for example
Toggle,Picker, and relevant control styles), always apply.tint(.accentColor)to keep interaction color consistent with the app. - Add new feature UI strings to
Modules/AppFeature/Localizable.xcstrings. - Add app-intent/app-shell strings to
Ida/Localizable.xcstrings. - In non-main targets (for example
Modules/AppFeature), always passbundle: .moduletoString(localized:).
- Always add tests for any new functionality; no feature work is complete without corresponding tests.
- Test suites must be exhaustive and prove intended behavior across happy paths, edge cases, and failure paths.
- Prioritize high assertion coverage (strong, behavior-focused assertions in each test). Treat raw code coverage as a secondary metric.
- Unit tests in
Modules/AppFeatureTests/use Swift Testing (import Testing). - There is currently no UI test target in this repo; add one if UI coverage is needed.
- Name test files
*Tests.swiftand keep test methods small and focused. - Use deterministic dependencies in suites (
.dependency(\.context, .test),.dependency(\.date.now, ...),.dependency(\.uuid, .incrementing)). - Keep tests fast: do not use
Task.sleep,sleep, run loop blocking, or other time-based waiting in tests unless absolutely unavoidable. Prefer deterministic synchronization and direct state/control over async work.
ChildListViewlogic inModules/AppFeature/ChildList.swiftis extracted intoChildListModel; keep the view focused on rendering and user-event forwarding.ChildDetailViewlogic inModules/AppFeature/ChildDetail.swiftis extracted intoChildDetailModel; keep grouped/filter/search/delete/share/reminder behavior in the model and keep presentation wiring in the view.ItemFormViewlogic inModules/AppFeature/ItemFormView.swiftis extracted intoItemFormModel; keep suggestion/emoji loading and item persistence in the model.- In
@Observablemodels that use SQLiteData, annotate@FetchAll/@FetchOne/@Fetchand@Dependencyproperties with@ObservationIgnored. - Keep model injection explicit in views (
init(model: ...)) plus convenience initializers (init(child:),init(item:)) to support targeted unit tests and call-site ergonomics. - Keep view-only environment concerns (e.g.
dismiss) in the view; model methods should handle domain behavior and persistence. - Trigger async model work from the view (
.task { await model... }) rather than creating hidden task orchestration in the view body. - For model tests, use
@Suitetraits with deterministic dependencies (.dependency(\.context, .test),.dependency(\.date.now, ...),.dependency(\.uuid, .incrementing)) and bootstrap via.dependencies { try $0.bootstrapDatabase(seedData: false) }. - Mirror behavior tests at the model level (
ChildListModelTests,ChildDetailModelTests,ItemFormModelTests) so refactors preserve UI behavior without needing UI tests. - Keep feature logic testable in the package test target (
@testable import AppFeature).
- Follow the sqlite-data Examples tests as the canonical style guide:
Examples/RemindersTests/Internal.swift(base suite + dependency setup)Examples/SyncUpTests/SyncUpFormTests.swift(database usage in tests)
- Use
DependenciesTestSupport+@Suitetraits to prepare test dependencies:.dependency(\.context, .test).dependency(\.date.now, ...).dependency(\.uuid, .incrementing).dependencies { try $0.bootstrapDatabase(seedData: true) }
- In tests, rely on
@Dependency(\.defaultDatabase)and app-layer APIs/queries rather than duplicating schema or writing low-level SQL migrations. - For empty-database scenarios, override per test with a suite/test dependency:
.dependencies { try $0.bootstrapDatabase(seedData: false) }. - If a test needs extra packages (e.g.,
DependenciesTestSupport), add the product toModules/Package.swiftunder theAppFeatureTeststarget.
- Recent commits use short, imperative summaries (e.g., “Add search suggestions to add item”).
- Keep commit subjects under ~72 characters when possible.
- PRs should include a clear description, linked issues (if any), and screenshots for UI changes.
- CloudKit and entitlements live in
Ida/Ida.entitlementsandIda/Info.plist; coordinate changes with the team. - Database/bootstrap/sync configuration lives in
Modules/AppFeature/Schema.swift. - CI scripts in
ci_scripts/adjust Xcode validation defaults; keep them in sync with CI needs.
- Docs:
https://swiftpackageindex.com/pointfreeco/sqlite-data/main/documentation/sqlitedata/(Swift Package Index DocC). - SQLiteData is a SwiftData-like API on top of SQLite (via GRDB); it uses value-type
@Tablemodels and property wrappers like@FetchAll/@FetchOneto fetch and observe data. - Initialize
defaultDatabaseearly (app entry) viaprepareDependencies, then access it with@Dependency(\.defaultDatabase)for reads/writes. - Writes go through
database.write { db in ... }which wraps changes in a transaction; useDatabaseMigrator+#sqlfor schema/migrations. - Optional CloudKit sync is configured by setting
defaultSyncEngine = SyncEngine(for:defaultDatabase, tables: ...). - SQLite knowledge (schema design, queries, indexes) is expected for effective use.
- In this repo, see
Modules/AppFeature/Schema.swiftfor migrations + sync setup andModules/AppFeature/ChildList.swift/Modules/AppFeature/ChildDetail.swift/Modules/AppFeature/ItemFormView.swiftfor fetch/write usage.