You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* chore: 아키텍처 하네스 모듈 경계 갱신
* chore: 같은 레이어 내부 DI 제한 지침 추가
* refactor: Infra Domain 타깃 의존성 제거
* docs: Tuist 모듈 그래프 갱신
* chore: Widget 중심 위젯 브리지 소유권 지침 정리
Copy file name to clipboardExpand all lines: .hermes/skills/devlog-architecture-harness/SKILL.md
+10Lines changed: 10 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -75,8 +75,15 @@ Ask the user before editing when:
75
75
- A shared type is being moved only because multiple modules need access.
76
76
- Firebase/Auth/Firestore/Functions/Messaging-specific logic would leave Infra.
77
77
- WidgetCore would depend on Domain, Data, Infra, Persistence, Presentation, or App.
78
+
- DevLogWidget would depend on Domain, Infra, Persistence, Presentation, or App.
79
+
- DevLogWidget would use WidgetKit for anything beyond the app-side widget reload bridge.
80
+
- Widget sync ownership would move away from the preferred split: Data contracts and snapshot repositories, DevLogWidget app-side bridge/snapshot update orchestration, WidgetCore snapshot models/factories/store contracts, and WidgetExtension rendering.
81
+
- Persistence would gain widget snapshot generation, WidgetCore, WidgetKit reload, or DevLogWidget bridge ownership.
78
82
- Presentation would depend on Data, Infra, Persistence, or App.
79
83
- Data would gain concrete SDK or storage implementation details.
84
+
- Data or Presentation would expand platform SDK usage beyond the existing narrow cancellation-classification or notification-badge patterns.
85
+
- Infra would add any Domain dependency, source import, or SDK service contract coupling.
86
+
- A same-layer dependency would be injected outside a SwiftUI `View` file in `Application/DevLogPresentation`.
80
87
- The Presentation `StorePattern` flow or reducer responsibility would change.
81
88
- A compile fix requires relaxing the intended architecture.
82
89
- The change is outside the requested issue or PR scope.
@@ -118,6 +125,9 @@ After completion, report only:
118
125
119
126
- Do not infer project-specific architecture policy from generic Clean Architecture rules when DevLog already has a concrete pattern.
120
127
- Do not move domain entities to Core just because multiple modules need them.
128
+
- Do not inject same-layer dependencies except from SwiftUI `View` files in `Application/DevLogPresentation` into same-layer presentation objects for UI composition.
129
+
- Do not collapse the current DevLogWidget bridge back into Data, Persistence, App, or WidgetCore without explicit boundary approval.
130
+
- Route app-side widget bridge and snapshot update orchestration through DevLogWidget.
121
131
- Do not hide architecture decisions inside build-fix wording.
122
132
- Do not broaden a modularization task into unrelated Firestore, Messaging, or UI safety edits.
123
133
- Do not mark work complete if the diff contains unrelated project-file or lockfile churn.
|`DevLogWidgetCore`| widget data contracts and pure snapshot logic | Core | Adding Domain, Data, Infra, Persistence, Presentation, or App dependency |
124
+
|`DevLogData`| repository implementations, DTOs, mappers, data protocols, widget repository/updater/sync contracts | Domain, Core | Adding concrete Firebase, GoogleSignIn, WidgetKit, storage, WidgetCore snapshot model/factory usage, or platform implementation details; moving concrete widget handlers into Data |
125
+
|`DevLogInfra`| Firebase, social login, network, metadata, messaging implementations | Data, Core | Moving SDK-specific behavior out of Infra; adding any Domain dependency, source import, or SDK service contract coupling |
Do not inject dependencies between types that belong to the same layer.
136
+
137
+
This rule covers initializer injection, stored-property injection, environment injection, and resolving same-layer types through `DIContainer`.
138
+
139
+
The only allowed exception is a SwiftUI `View` file in `Application/DevLogPresentation` receiving same-layer presentation objects such as a ViewModel, Coordinator, or Store for UI composition.
140
+
141
+
That exception does not apply to non-View files in Presentation, and does not apply to Core, Domain, Data, Infra, Persistence, Widget, App, WidgetCore, WidgetExtension, or Firebase functions.
142
+
126
143
## Presentation StorePattern flow
127
144
128
145
```mermaid
@@ -158,8 +175,9 @@ flowchart TD
158
175
CoreDomain{"Core vs Domain ownership?"}
159
176
Shared{"Moved only because shared?"}
160
177
NewDependency{"New module dependency?"}
178
+
SameLayerDI{"Same-layer dependency injection?"}
161
179
ExternalSDK{"External SDK crosses layer?"}
162
-
WidgetBoundary{"WidgetCore sees app/domain/data?"}
180
+
WidgetBoundary{"Widget sync ownership or WidgetCore boundary changes?"}
Copy file name to clipboardExpand all lines: .hermes/skills/devlog-architecture-harness/references/devlog-workflow-rules.md
+15-1Lines changed: 15 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,6 +29,7 @@ This reference holds DevLog-specific working rules that should live with the pro
29
29
- Do not force a single `objectVersion` across projects. Treat Xcode's actual save output as the source of truth.
30
30
- For synchronized-root cleanup, verify on copied files or a narrowed rule set before touching real project files.
31
31
- When changing project structure, update the Tuist manifest first and treat generated Xcode project churn as disposable output.
32
+
- Do not promote a manifest-only target dependency to an allowed architecture direction. Check source imports and ownership before updating the layer map.
32
33
33
34
## PR and review handling
34
35
@@ -56,28 +57,41 @@ This reference holds DevLog-specific working rules that should live with the pro
56
57
- Keep project-file, lockfile, and code changes separated when the task scope requires clean review.
57
58
- Do not broaden architecture work into unrelated Firestore, Messaging, UI, or safety edits.
58
59
60
+
## Layer-internal dependency injection
61
+
62
+
- Do not inject dependencies between types that belong to the same layer.
63
+
- This includes initializer injection, stored-property injection, environment injection, and resolving same-layer types through `DIContainer`.
64
+
- The only allowed exception is a SwiftUI `View` file in `Application/DevLogPresentation` receiving same-layer presentation objects such as a ViewModel, Coordinator, or Store for UI composition.
65
+
- The exception does not apply to non-View files in Presentation, and does not apply to Core, Domain, Data, Infra, Persistence, Widget, App, WidgetCore, WidgetExtension, or Firebase functions.
66
+
59
67
## Data, Domain, and Infra boundary
60
68
61
69
- Do not move domain entities to Core only because multiple modules need them.
62
70
- Keep protocol location and implementation layer distinct when explaining or changing boundaries.
63
71
- If a Data protocol is implemented by Infra, every type in that protocol signature must be visible to Infra.
72
+
-`DevLogInfra` should depend on Data and Core, not Domain. Do not treat a manifest-only Domain target dependency as architecture permission.
64
73
- Prefer a Data-side boundary value plus repository mapping when Infra should not import Domain.
65
74
- For example, keep the app-facing Domain query separate from an Infra-facing Data query when that avoids Domain coupling in service protocols.
66
75
- Firebase-specific error detection belongs in Infra; Data should handle domain-level errors after mapping.
76
+
- Data and Presentation currently keep narrow social-login cancellation classification in `DataLayerError` and `Error+SocialLogin`. Do not expand that into concrete login implementation or broader SDK ownership without explicit approval.
- Presentation currently owns narrow notification badge side effects through `UserNotifications`. Do not expand that into push service or messaging ownership.
73
84
- Do not leave reducer-era helper methods behind after moving work into `run`.
74
85
- Before adding task cancellation or async wrappers, inspect whether the underlying operation is actually async.
75
86
76
87
## Widget flow
77
88
78
89
- Widget UI should consume snapshot data, not app/domain services.
79
90
-`DevLogWidgetCore` should stay free of Domain, Data, Infra, Persistence, Presentation, and App dependencies unless the user explicitly approves a boundary change.
80
-
- Prefer an app-driven snapshot flow: app/runtime data fetch, snapshot generation, App Group storage, WidgetCore model/factory, WidgetExtension rendering.
91
+
-`DevLogWidget` owns the app-side widget bridge: sync event bus implementation, sync event handlers, session sync handler, auth-session sync provider, snapshot generation/persistence orchestration, WidgetKit reload bridge, and `WidgetAssembler`.
92
+
-`DevLogData` owns widget-related contracts and repository implementations, including `WidgetSyncEventBus`, `WidgetSnapshotUpdater`, and `WidgetTodoSnapshotRepository`. Data should not own concrete widget handlers, WidgetCore snapshot model/factory usage, or WidgetKit reload behavior.
93
+
-`DevLogPersistence` owns local persistence, user defaults, image store, and non-widget app persistence.
94
+
- Prefer an app-driven snapshot flow: app/runtime event, DevLogWidget sync handler, Data snapshot input fetch, DevLogWidget snapshot update, App Group storage through WidgetCore contracts, WidgetExtension rendering.
81
95
-`WidgetTodoSnapshot` is a lightweight snapshot value, not a full domain `Todo`.
82
96
- Do not make `Todo.number` or `WidgetTodoSnapshot.number` non-optional without a separate saved-vs-draft model decision.
83
97
- If a widget sync flow needs one timestamp for multiple snapshots, capture `Date()` once and pass it through to avoid midnight or quarter-boundary drift.
0 commit comments