pumuki 6.3.174 → 6.3.176

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/VERSION CHANGED
@@ -1 +1 @@
1
- v6.3.174
1
+ v6.3.176
@@ -27,6 +27,7 @@ import {
27
27
  hasSwiftModernizableXCTestSuiteUsage,
28
28
  hasSwiftAssumeIsolatedUsage,
29
29
  hasSwiftCoreDataLayerLeakUsage,
30
+ hasSwiftSwiftDataLayerLeakUsage,
30
31
  hasSwiftNonisolatedUnsafeUsage,
31
32
  hasSwiftNSManagedObjectAsyncBoundaryUsage,
32
33
  hasSwiftNSManagedObjectBoundaryUsage,
@@ -618,6 +619,44 @@ struct DetailView: View {
618
619
  assert.equal(hasSwiftCoreDataLayerLeakUsage(ignored), false);
619
620
  });
620
621
 
622
+ test('hasSwiftSwiftDataLayerLeakUsage detecta SwiftData fuera de infraestructura', () => {
623
+ const source = `
624
+ import SwiftData
625
+
626
+ struct DetailView: View {
627
+ @Environment(\\.modelContext) private var modelContext
628
+ @Query(sort: \\TodoModel.title) private var todos: [TodoModel]
629
+ }
630
+
631
+ final class DetailUseCase {
632
+ private let container: ModelContainer
633
+ private let context: ModelContext
634
+ private let descriptor = FetchDescriptor<TodoModel>()
635
+ }
636
+
637
+ @Model
638
+ final class TodoModel {
639
+ var title: String
640
+ }
641
+ `;
642
+ const ignored = `
643
+ import Foundation
644
+
645
+ struct DetailView: View {
646
+ let selectedID: Todo.ID?
647
+ }
648
+
649
+ final class DetailUseCase {
650
+ func execute() async throws -> [Todo] { [] }
651
+ private let predicate: Predicate<Todo>?
652
+ private let sort = SortDescriptor(\\Todo.title)
653
+ }
654
+ `;
655
+
656
+ assert.equal(hasSwiftSwiftDataLayerLeakUsage(source), true);
657
+ assert.equal(hasSwiftSwiftDataLayerLeakUsage(ignored), false);
658
+ });
659
+
621
660
  test('hasSwiftNSManagedObjectStateLeakUsage detecta fugas a SwiftUI state y ViewModels', () => {
622
661
  const source = `
623
662
  final class TodoEntity: NSManagedObject {}
@@ -800,6 +800,13 @@ export const hasSwiftCoreDataLayerLeakUsage = (source: string): boolean => {
800
800
  );
801
801
  };
802
802
 
803
+ export const hasSwiftSwiftDataLayerLeakUsage = (source: string): boolean => {
804
+ return hasSwiftSanitizedRegexMatch(
805
+ source,
806
+ /\bimport\s+SwiftData\b|@\s*Query\b|@\s*Model\b|\b(?:ModelContext|ModelContainer|FetchDescriptor)\b|\.modelContext\b/g
807
+ );
808
+ };
809
+
803
810
  export const hasSwiftNSManagedObjectStateLeakUsage = (source: string): boolean => {
804
811
  const typeDeclarations = parseSwiftTypeDeclarations(source);
805
812
  if (typeDeclarations.length === 0) {
@@ -630,6 +630,7 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
630
630
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftNSManagedObjectBoundaryUsage, ruleId: 'heuristics.ios.core-data.nsmanagedobject-boundary.ast', code: 'HEURISTICS_IOS_CORE_DATA_NSMANAGEDOBJECT_BOUNDARY_AST', message: 'AST heuristic detected NSManagedObject in a shared boundary.' },
631
631
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftNSManagedObjectAsyncBoundaryUsage, ruleId: 'heuristics.ios.core-data.nsmanagedobject-async-boundary.ast', code: 'HEURISTICS_IOS_CORE_DATA_NSMANAGEDOBJECT_ASYNC_BOUNDARY_AST', message: 'AST heuristic detected NSManagedObject in an async boundary.' },
632
632
  { platform: 'ios', pathCheck: isIOSApplicationOrPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftCoreDataLayerLeakUsage, ruleId: 'heuristics.ios.core-data.layer-leak.ast', code: 'HEURISTICS_IOS_CORE_DATA_LAYER_LEAK_AST', message: 'AST heuristic detected Core Data APIs leaking into application/presentation code.' },
633
+ { platform: 'ios', pathCheck: isIOSApplicationOrPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftSwiftDataLayerLeakUsage, ruleId: 'heuristics.ios.swiftdata.layer-leak.ast', code: 'HEURISTICS_IOS_SWIFTDATA_LAYER_LEAK_AST', message: 'AST heuristic detected SwiftData APIs leaking into application/presentation code.' },
633
634
  { platform: 'ios', pathCheck: isIOSApplicationOrPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftNSManagedObjectStateLeakUsage, ruleId: 'heuristics.ios.core-data.nsmanagedobject-state-leak.ast', code: 'HEURISTICS_IOS_CORE_DATA_NSMANAGEDOBJECT_STATE_LEAK_AST', message: 'AST heuristic detected NSManagedObject leaking into SwiftUI state or a ViewModel.' },
634
635
 
635
636
  // Android
@@ -3,7 +3,7 @@ import test from 'node:test';
3
3
  import { iosRules } from './ios';
4
4
 
5
5
  test('iosRules define reglas heurísticas locked para plataforma ios', () => {
6
- assert.equal(iosRules.length, 42);
6
+ assert.equal(iosRules.length, 43);
7
7
 
8
8
  const ids = iosRules.map((rule) => rule.id);
9
9
  assert.deepEqual(ids, [
@@ -48,6 +48,7 @@ test('iosRules define reglas heurísticas locked para plataforma ios', () => {
48
48
  'heuristics.ios.core-data.nsmanagedobject-boundary.ast',
49
49
  'heuristics.ios.core-data.nsmanagedobject-async-boundary.ast',
50
50
  'heuristics.ios.core-data.layer-leak.ast',
51
+ 'heuristics.ios.swiftdata.layer-leak.ast',
51
52
  'heuristics.ios.core-data.nsmanagedobject-state-leak.ast',
52
53
  ]);
53
54
 
@@ -137,6 +138,10 @@ test('iosRules define reglas heurísticas locked para plataforma ios', () => {
137
138
  byId.get('heuristics.ios.core-data.layer-leak.ast')?.then.code,
138
139
  'HEURISTICS_IOS_CORE_DATA_LAYER_LEAK_AST'
139
140
  );
141
+ assert.equal(
142
+ byId.get('heuristics.ios.swiftdata.layer-leak.ast')?.then.code,
143
+ 'HEURISTICS_IOS_SWIFTDATA_LAYER_LEAK_AST'
144
+ );
140
145
  assert.equal(
141
146
  byId.get('heuristics.ios.core-data.nsmanagedobject-state-leak.ast')?.then.code,
142
147
  'HEURISTICS_IOS_CORE_DATA_NSMANAGEDOBJECT_STATE_LEAK_AST'
@@ -743,6 +743,24 @@ export const iosRules: RuleSet = [
743
743
  code: 'HEURISTICS_IOS_CORE_DATA_LAYER_LEAK_AST',
744
744
  },
745
745
  },
746
+ {
747
+ id: 'heuristics.ios.swiftdata.layer-leak.ast',
748
+ description: 'Detects SwiftData APIs leaking into iOS application or presentation layers.',
749
+ severity: 'WARN',
750
+ platform: 'ios',
751
+ locked: true,
752
+ when: {
753
+ kind: 'Heuristic',
754
+ where: {
755
+ ruleId: 'heuristics.ios.swiftdata.layer-leak.ast',
756
+ },
757
+ },
758
+ then: {
759
+ kind: 'Finding',
760
+ message: 'AST heuristic detected SwiftData APIs leaking into application/presentation code.',
761
+ code: 'HEURISTICS_IOS_SWIFTDATA_LAYER_LEAK_AST',
762
+ },
763
+ },
746
764
  {
747
765
  id: 'heuristics.ios.core-data.nsmanagedobject-state-leak.ast',
748
766
  description: 'Detects NSManagedObject leaking into SwiftUI state or ViewModel state.',
@@ -1,12 +1,13 @@
1
- # Core Data Expert
1
+ # Core Data + SwiftData Expert
2
2
 
3
- Use this skill when auditing or implementing Core Data code that must remain safe across contexts, layers, and async boundaries.
3
+ Use this skill when auditing or implementing Core Data or SwiftData code that must remain safe across contexts, layers, and async boundaries.
4
4
 
5
5
  ## Focus areas
6
6
 
7
7
  - ✅ Prefer `NSManagedObjectID` or mapped DTO/domain models over passing `NSManagedObject` across boundaries.
8
8
  - ✅ Avoid returning or accepting `NSManagedObject` in async APIs that cross actor or context boundaries.
9
9
  - ✅ Keep Core Data orchestration inside infrastructure or repository layers instead of presentation or application code.
10
+ - ✅ Keep SwiftData orchestration (`ModelContext`, `ModelContainer`, `@Query`, `@Model`) inside infrastructure or repository layers instead of application or presentation code in enterprise Clean Architecture.
10
11
  - ✅ Make context ownership explicit and keep merge boundaries controlled.
11
12
  - ✅ Treat managed objects as context-scoped references, not as portable domain entities.
12
13
 
@@ -21,4 +22,5 @@ Use this skill when auditing or implementing Core Data code that must remain saf
21
22
  - ❌ Passing `NSManagedObject` through service, use-case, or presentation boundaries.
22
23
  - ❌ Async APIs that return `NSManagedObject` directly.
23
24
  - ❌ Using `CoreData`, `@FetchRequest`, `managedObjectContext`, or persistence containers directly in application/presentation code.
25
+ - ❌ Using SwiftData contexts, containers, queries, or persistence models directly in application or presentation code when the repo requires Clean Architecture boundaries.
24
26
  - ❌ Leaking context-scoped managed objects into SwiftUI state or view models.
@@ -49,4 +49,4 @@
49
49
  - No XCTest-only `XCTestCase` suites that are directly modernizable to `import Testing` + `@Test`, and no mixed `XCTestCase`/`Testing` suites without explicit compatibility reason
50
50
  - No `String(format:)` and no `UIScreen.main.bounds` in SwiftUI presentation/layout paths
51
51
  - No `ForEach(...indices...)`, no user-facing `contains()` filters instead of `localizedStandardContains()`, and no avoidable `GeometryReader` / `fontWeight(.bold)` patterns in modern SwiftUI paths
52
- - No Core Data APIs in iOS `Application` / `Presentation` paths, and no `NSManagedObject` escaping into SwiftUI state or ViewModels
52
+ - No Core Data or SwiftData APIs in iOS `Application` / `Presentation` paths, and no `NSManagedObject` escaping into SwiftUI state or ViewModels
@@ -22,7 +22,7 @@ Artefacto contractual de `phase10-avdlee-parity-closure`.
22
22
  | `swift-concurrency` | `ios-concurrency-guidelines` | `skills.ios.no-dispatchqueue`, `skills.ios.no-dispatchgroup`, `skills.ios.no-dispatchsemaphore`, `skills.ios.no-operation-queue`, `skills.ios.no-task-detached`, `skills.ios.no-unchecked-sendable`, `skills.ios.no-preconcurrency`, `skills.ios.no-nonisolated-unsafe`, `skills.ios.no-assume-isolated` | `integrations/config/__tests__/iosAvdleeParity.test.ts`, `core/facts/detectors/text/ios.test.ts`, `core/facts/__tests__/extractHeuristicFacts.test.ts`, `core/rules/presets/heuristics/ios.test.ts`, `integrations/config/__tests__/skillsDetectorRegistry.test.ts`, `integrations/config/__tests__/skillsMarkdownRules.test.ts` | `skills.sources.json`, `skills.lock.json`, `integrations/config/skillsCompilerTemplates.ts`, `integrations/config/skillsDetectorRegistry.ts`, `integrations/evidence/buildEvidence.ts` |
23
23
  | `swiftui-expert-skill` | `ios-swiftui-expert-guidelines` | `skills.ios.no-observable-object`, `skills.ios.no-legacy-swiftui-observable-wrapper`, `skills.ios.no-passed-value-state-wrapper`, `skills.ios.no-navigation-view`, `skills.ios.no-foreground-color`, `skills.ios.no-corner-radius`, `skills.ios.no-tab-item`, `skills.ios.no-on-tap-gesture`, `skills.ios.no-string-format`, `skills.ios.no-foreach-indices`, `skills.ios.no-contains-user-filter`, `skills.ios.no-geometryreader`, `skills.ios.no-font-weight-bold`, `skills.ios.no-scrollview-shows-indicators`, `skills.ios.no-sheet-is-presented`, `skills.ios.no-legacy-onchange`, `skills.ios.no-uiscreen-main-bounds` | `integrations/config/__tests__/iosAvdleeParity.test.ts`, `core/facts/detectors/text/ios.test.ts`, `core/facts/detectors/text/iosSwiftUiModernizationSnapshot.test.ts`, `core/facts/__tests__/extractHeuristicFacts.test.ts`, `core/rules/presets/heuristics/ios.test.ts`, `integrations/config/__tests__/skillsDetectorRegistry.test.ts`, `integrations/config/__tests__/skillsMarkdownRules.test.ts` | `skills.sources.json`, `skills.lock.json`, `assets/rule-packs/ios-swiftui-modernization-v1.json`, `assets/rule-packs/ios-swiftui-modernization-v2.json`, `integrations/config/skillsCompilerTemplates.ts`, `integrations/config/skillsDetectorRegistry.ts`, `integrations/evidence/buildEvidence.ts` |
24
24
  | `swift-testing-expert` | `ios-swift-testing-guidelines` | `skills.ios.prefer-swift-testing`, `skills.ios.no-xctassert`, `skills.ios.no-xctunwrap`, `skills.ios.no-wait-for-expectations`, `skills.ios.no-legacy-expectation-description`, `skills.ios.no-mixed-testing-frameworks` | `integrations/config/__tests__/iosAvdleeParity.test.ts`, `core/facts/detectors/text/ios.test.ts`, `core/facts/__tests__/extractHeuristicFacts.test.ts`, `core/rules/presets/heuristics/ios.test.ts`, `integrations/config/__tests__/skillsDetectorRegistry.test.ts`, `integrations/config/__tests__/skillsMarkdownRules.test.ts` | `skills.sources.json`, `skills.lock.json`, `integrations/config/skillsCompilerTemplates.ts`, `integrations/config/skillsDetectorRegistry.ts`, `integrations/evidence/buildEvidence.ts` |
25
- | `core-data-expert` | `ios-core-data-guidelines` | `skills.ios.no-nsmanagedobject-boundary`, `skills.ios.no-nsmanagedobject-async-boundary`, `skills.ios.no-core-data-layer-leak`, `skills.ios.no-nsmanagedobject-state-leak` | `integrations/config/__tests__/iosAvdleeParity.test.ts`, `core/facts/detectors/text/ios.test.ts`, `core/facts/__tests__/extractHeuristicFacts.test.ts`, `core/rules/presets/heuristics/ios.test.ts`, `integrations/config/__tests__/skillsDetectorRegistry.test.ts`, `integrations/config/__tests__/skillsMarkdownRules.test.ts` | `skills.sources.json`, `skills.lock.json`, `integrations/config/skillsCompilerTemplates.ts`, `integrations/config/skillsDetectorRegistry.ts`, `integrations/evidence/buildEvidence.ts` |
25
+ | `core-data-expert` | `ios-core-data-guidelines` | `skills.ios.no-nsmanagedobject-boundary`, `skills.ios.no-nsmanagedobject-async-boundary`, `skills.ios.no-core-data-layer-leak`, `skills.ios.no-nsmanagedobject-state-leak`, `skills.ios.no-swiftdata-layer-leak` | `integrations/config/__tests__/iosAvdleeParity.test.ts`, `core/facts/detectors/text/ios.test.ts`, `core/facts/__tests__/extractHeuristicFacts.test.ts`, `core/rules/presets/heuristics/ios.test.ts`, `integrations/config/__tests__/skillsDetectorRegistry.test.ts`, `integrations/config/__tests__/skillsMarkdownRules.test.ts` | `skills.sources.json`, `skills.lock.json`, `integrations/config/skillsCompilerTemplates.ts`, `integrations/config/skillsDetectorRegistry.ts`, `integrations/evidence/buildEvidence.ts` |
26
26
 
27
27
  ## Skill absorbida por snapshot
28
28
 
@@ -143,6 +143,9 @@ const registryByRuleId: Record<string, SkillsDetectorBinding> = {
143
143
  'skills.ios.no-core-data-layer-leak': heuristicDetector('ios.core-data.layer-leak', [
144
144
  'heuristics.ios.core-data.layer-leak.ast',
145
145
  ]),
146
+ 'skills.ios.no-swiftdata-layer-leak': heuristicDetector('ios.swiftdata.layer-leak', [
147
+ 'heuristics.ios.swiftdata.layer-leak.ast',
148
+ ]),
146
149
  'skills.ios.no-nsmanagedobject-state-leak': heuristicDetector(
147
150
  'ios.core-data.nsmanagedobject-state-leak',
148
151
  ['heuristics.ios.core-data.nsmanagedobject-state-leak.ast']
@@ -117,6 +117,9 @@ const tryApplyPolicyAutofix = (params: {
117
117
  }
118
118
 
119
119
  const preWriteStage = params.report.stages.PRE_WRITE;
120
+ const preCommitStage = params.report.stages.PRE_COMMIT;
121
+ const prePushStage = params.report.stages.PRE_PUSH;
122
+ const ciStage = params.report.stages.CI;
120
123
  const signatures = {
121
124
  PRE_WRITE: createPolicyAsCodeSignature({
122
125
  stage: 'PRE_COMMIT',
@@ -125,9 +128,27 @@ const tryApplyPolicyAutofix = (params: {
125
128
  hash: preWriteStage.hash,
126
129
  version: '1.0',
127
130
  }),
128
- PRE_COMMIT: params.report.stages.PRE_COMMIT.signature,
129
- PRE_PUSH: params.report.stages.PRE_PUSH.signature,
130
- CI: params.report.stages.CI.signature,
131
+ PRE_COMMIT: createPolicyAsCodeSignature({
132
+ stage: 'PRE_COMMIT',
133
+ source: toContractSource(preCommitStage.source),
134
+ bundle: preCommitStage.bundle,
135
+ hash: preCommitStage.hash,
136
+ version: '1.0',
137
+ }),
138
+ PRE_PUSH: createPolicyAsCodeSignature({
139
+ stage: 'PRE_PUSH',
140
+ source: toContractSource(prePushStage.source),
141
+ bundle: prePushStage.bundle,
142
+ hash: prePushStage.hash,
143
+ version: '1.0',
144
+ }),
145
+ CI: createPolicyAsCodeSignature({
146
+ stage: 'CI',
147
+ source: toContractSource(ciStage.source),
148
+ bundle: ciStage.bundle,
149
+ hash: ciStage.hash,
150
+ version: '1.0',
151
+ }),
131
152
  };
132
153
  if (!signatures.PRE_COMMIT || !signatures.PRE_PUSH || !signatures.CI) {
133
154
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.174",
3
+ "version": "6.3.176",
4
4
  "description": "Enterprise-grade AST Intelligence System with multi-platform support (iOS, Android, Backend, Frontend) and Feature-First + DDD + Clean Architecture enforcement. Includes dynamic violations API for intelligent querying.",
5
5
  "main": "index.js",
6
6
  "bin": {
package/skills.lock.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "1.0",
3
3
  "compilerVersion": "1.0.0",
4
- "generatedAt": "2026-05-12T18:32:01.654Z",
4
+ "generatedAt": "2026-05-12T19:46:23.268Z",
5
5
  "bundles": [
6
6
  {
7
7
  "name": "android-guidelines",
@@ -5644,8 +5644,20 @@
5644
5644
  "name": "ios-core-data-guidelines",
5645
5645
  "version": "1.0.0",
5646
5646
  "source": "file:vendor/skills/core-data-expert/SKILL.md",
5647
- "hash": "0f4f9e67e60990dea6f946d09b8d7314d759d8cb03a0a3806a172818e84cc31e",
5647
+ "hash": "d91f2cad6499310a4299b39593d47f40a507299a0562c21bc64aad9b5d27c66f",
5648
5648
  "rules": [
5649
+ {
5650
+ "id": "skills.ios.guideline.ios-core-data.keep-swiftdata-orchestration-modelcontext-modelcontainer-query-model-i",
5651
+ "description": "Keep SwiftData orchestration (ModelContext, ModelContainer, @Query, @Model) inside infrastructure or repository layers instead of application or presentation code in enterprise Clean Architecture.",
5652
+ "severity": "WARN",
5653
+ "platform": "ios",
5654
+ "sourceSkill": "ios-core-data-guidelines",
5655
+ "sourcePath": "vendor/skills/core-data-expert/SKILL.md",
5656
+ "confidence": "MEDIUM",
5657
+ "locked": true,
5658
+ "evaluationMode": "DECLARATIVE",
5659
+ "origin": "core"
5660
+ },
5649
5661
  {
5650
5662
  "id": "skills.ios.guideline.ios-core-data.make-context-ownership-explicit-and-keep-merge-boundaries-controlled",
5651
5663
  "description": "Make context ownership explicit and keep merge boundaries controlled.",
@@ -5694,6 +5706,18 @@
5694
5706
  "evaluationMode": "DECLARATIVE",
5695
5707
  "origin": "core"
5696
5708
  },
5709
+ {
5710
+ "id": "skills.ios.guideline.ios-core-data.using-swiftdata-contexts-containers-queries-or-persistence-models-dire",
5711
+ "description": "Using SwiftData contexts, containers, queries, or persistence models directly in application or presentation code when the repo requires Clean Architecture boundaries.",
5712
+ "severity": "ERROR",
5713
+ "platform": "ios",
5714
+ "sourceSkill": "ios-core-data-guidelines",
5715
+ "sourcePath": "vendor/skills/core-data-expert/SKILL.md",
5716
+ "confidence": "HIGH",
5717
+ "locked": true,
5718
+ "evaluationMode": "DECLARATIVE",
5719
+ "origin": "core"
5720
+ },
5697
5721
  {
5698
5722
  "id": "skills.ios.no-core-data-layer-leak",
5699
5723
  "description": "Keep Core Data orchestration inside infrastructure or repository layers; avoid Core Data APIs in application or presentation code.",
@@ -1,12 +1,13 @@
1
- # Core Data Expert
1
+ # Core Data + SwiftData Expert
2
2
 
3
- Use this skill when auditing or implementing Core Data code that must remain safe across contexts, layers, and async boundaries.
3
+ Use this skill when auditing or implementing Core Data or SwiftData code that must remain safe across contexts, layers, and async boundaries.
4
4
 
5
5
  ## Focus areas
6
6
 
7
7
  - ✅ Prefer `NSManagedObjectID` or mapped DTO/domain models over passing `NSManagedObject` across boundaries.
8
8
  - ✅ Avoid returning or accepting `NSManagedObject` in async APIs that cross actor or context boundaries.
9
9
  - ✅ Keep Core Data orchestration inside infrastructure or repository layers instead of presentation code.
10
+ - ✅ Keep SwiftData orchestration (`ModelContext`, `ModelContainer`, `@Query`, `@Model`) inside infrastructure or repository layers instead of application or presentation code in enterprise Clean Architecture.
10
11
  - ✅ Make context ownership explicit and keep merge boundaries controlled.
11
12
  - ✅ Treat managed objects as context-scoped references, not as portable domain entities.
12
13
 
@@ -21,3 +22,4 @@ Use this skill when auditing or implementing Core Data code that must remain saf
21
22
  - ❌ Passing `NSManagedObject` through service, use-case, or presentation boundaries.
22
23
  - ❌ Async APIs that return `NSManagedObject` directly.
23
24
  - ❌ Leaking context-scoped managed objects into SwiftUI state or view models.
25
+ - ❌ Using SwiftData contexts, containers, queries, or persistence models directly in application or presentation code when the repo requires Clean Architecture boundaries.