Skip to content

Phase 2: 永続化層(SwiftData) - #2

Merged
tukuyomil032 merged 4 commits into
mainfrom
phase-2/persistence-layer
Aug 22, 2026
Merged

Phase 2: 永続化層(SwiftData)#2
tukuyomil032 merged 4 commits into
mainfrom
phase-2/persistence-layer

Conversation

@tukuyomil032

Copy link
Copy Markdown
Owner

Summary

  • CachedRepository/CachedRelease/InstalledApp の SwiftData @Model を追加(Sources/Cairn/Cache/
  • ModelContainer を保持する軽量な環境容器 CairnEnvironment を追加(on-disk / in-memory 切り替え、初期化失敗時は fatalError
  • CairnApp.swift.modelContainer(_:) を配線し、実機起動時に永続化ストアが生成されることを確認
  • GitHubClient/AuthenticationState を含む本格的な AppEnvironment への統合は今回のスコープ外(引き続き次のUI機能フェーズへ)

実装時に判明した挙動

  • SwiftDataの .unique 制約は違反時に例外を投げず、既存レコードを上書き(upsert)する。テストの期待値はこの実挙動に合わせている
  • in-memory ModelContainer はヘルパー関数が ModelContext だけを返すと CairnEnvironment インスタンスがスコープ外で解放されテストプロセスがクラッシュするため、CairnEnvironment 自体をローカル変数として保持する必要がある

Test plan

  • just build — ビルド成功
  • just test — 全51テストパス(Cache配下の新規10テスト含む)
  • just run — 実機起動、fatalErrorなし、~/Library/Application Support/default.store の生成を確認
  • just lint — 新規追加ファイルにlint違反なし

🤖 Generated with Claude Code

https://claude.ai/code/session_014bzWqvKZywe5exBTy9Y6eQ

tukuyomil032 and others added 4 commits August 22, 2026 23:37
CachedRepository/CachedRelease/InstalledApp model the GitHub cache and installed-app records from the Phase 2 plan. CairnEnvironment wraps ModelContainer creation (on-disk by default, in-memory for tests) so the schema has a single source of truth.

CachedRelease gains an explicit inverse (repository) not present in the original plan sketch, required for CachedRepository's cascade delete rule to actually take effect.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Covers insert/fetch round-trips, CachedRepository -> CachedRelease cascade delete, the inverse relationship reflecting on the repository side, and unique-constraint duplicate inserts (githubId/bundleIdentifier).

SwiftData's .unique constraint does not throw on duplicate insert; it upserts the existing record instead. Confirmed by running the tests rather than assuming, since this diverges from a naive expectation. Suites are @suite(.serialized) because parallel test execution against separately-constructed in-memory ModelContainers crashed the test process (signal 5) during verification.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The app now boots with SwiftData persistence active via .modelContainer(_:) on the WindowGroup scene. Verified with 'just run': the process launches without fatalError-ing, and a persistent store file is created on disk.

ContentView stays as the Phase 0 placeholder; Discovery UI comes in Phase 5.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@tukuyomil032
tukuyomil032 merged commit 711fe34 into main Aug 22, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant