From 11302ee2a881e7657b6fb4aaa6690b1369e60c91 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 18 May 2026 18:30:40 +0900 Subject: [PATCH 1/6] =?UTF-8?q?docs:=20DevLog=20=EC=97=90=EC=9D=B4?= =?UTF-8?q?=EC=A0=84=ED=8A=B8=20=EA=B7=9C=EC=B9=99=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DevLog 레포 전용 AI 작업 규칙 추가 아키텍처 변경 시 확인할 모듈 경계와 모호성 게이트 정의 전역 메모리보다 레포 로컬 규칙을 우선하는 기준 명시 --- AGENTS.md | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..db210dee --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,107 @@ +# DevLog Agent Instructions + +## Scope + +These instructions apply only to `/Users/opfic/Desktop/Github/App/SwiftUI_DevLog`. + +## Logic preservation and optimization + +- Reuse the existing program logic as-is whenever possible. +- Change logic only when the new approach produces exactly the same result and strictly improves time or space complexity. +- If there is no clear complexity improvement, keep the original logic. + +## Code modification response style + +- When asked to modify code, return only the precise changed locations and the modified code for those locations. +- Do not include full files, unrelated code, or explanatory text unless explicitly requested. +- You do not need to paste code in the prompt after updating it in the repository. + +## Naming and Swift style + +- Set variables named after a type using the type's full name in camel case. +- In Swift, do not write explicit type annotations unless required. +- Use `opfic` in new Swift file headers. +- Prefer `<` and `<=` over `>` and `>=` when writing comparisons, if the condition can be expressed clearly that way. + +## DevLog Architecture Harness + +Use this harness before any task that changes module boundaries, file ownership, layer dependencies, DI assembly, repository/service contracts, widget data flow, Firebase dependency placement, or architecture documentation. + +Treat this repository as an Xcode workspace-based modular iOS app. There is no root `Package.swift`; modules are separate `.xcodeproj` entries under `DevLog.xcworkspace`. + +### Mandatory flow + +1. Read this file, `.gemini/styleguide.md`, `README.md`, and `.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md`. +2. Identify the changed layer and owning target before editing. +3. Inspect the current Swift import direction and Xcode target/framework dependency before deciding. +4. Classify the change as mechanical, architectural, or ambiguous. +5. For ambiguous architecture changes, stop and ask the user before editing. +6. Keep the diff limited to the requested architecture scope. +7. After Swift/iOS code changes, verify with Xcode Local MCP. +8. Report the changed files, architecture decision, and verification result. + +### Current layer map + +- `Application/DevLogCore`: shared app primitives such as DI, logging, query/value types, display options, and widget snapshot value types. Core is shared, but shared access alone is not enough reason to move domain entities into Core. +- `Application/DevLogDomain`: entities, repository protocols, use case protocols, and use case implementations. Domain may depend on Core. Domain must not depend on Data, Infra, Persistence, Presentation, App, Widget extension UI, Firebase SDKs, or storage implementations. +- `Application/DevLogData`: repository implementations, DTOs, mappers, data-layer protocols for external services/stores, and widget sync coordination. Data may depend on Domain and Core. Data should not gain direct Firebase, GoogleSignIn, WidgetKit, or concrete storage implementation details unless the user explicitly approves the boundary change. +- `Application/DevLogInfra`: Firebase, social login, network, link metadata, messaging, and platform service implementations. Infra may depend on Data and Core. Firebase/Auth/Firestore/Functions/Messaging-specific behavior belongs here unless the user approves another boundary. +- `Application/DevLogPersistence`: local persistence, user defaults, image store, and widget snapshot persistence/updating. Persistence may depend on Data, Core, and WidgetCore when needed for snapshot persistence. +- `Application/DevLogPresentation`: SwiftUI views, view models, coordinators, UI state structures, and presentation-only helpers. Presentation may depend on Domain and Core. It must not depend on Data, Infra, Persistence, or App. +- `Application/DevLogApp`: composition root, app lifecycle, app delegate, app-level routing, and assembler wiring. App may import concrete layers to assemble the dependency graph. +- `Widget/DevLogWidgetCore`: widget snapshot models, factories, keys, app-group constants, and widget-only pure helpers. WidgetCore may depend on Core. It must not depend on Domain, Data, Infra, Persistence, Presentation, or App without explicit user approval. +- `Widget/DevLogWidgetExtension`: WidgetKit UI, widget providers, entries, timelines, and extension resources. It should consume WidgetCore outputs rather than app/domain services directly. +- `Firebase/functions`: TypeScript Cloud Functions. Deploy updated functions one by one separately. + +### Store flow + +- Preserve the existing Presentation `Store` pattern. +- `Store` is `@MainActor` and uses `State`, `Action`, `SideEffect`, and the `send -> reduce -> run` flow. +- Reducers should compute state and return side effects. +- I/O belongs in `run` or injected services, not in reducer state computation. +- Ask before changing reducer, side-effect, or ViewModel responsibility boundaries. + +### Ambiguity gate + +Ask the user before editing when any of these are true: + +- A type could plausibly live in both Core and Domain. +- A shared type is being moved only because multiple modules need access to it. +- A new target dependency would make a lower-level module know a higher-level module. +- A build fix would be achieved by loosening an architecture boundary. +- Firebase, GoogleSignIn, AuthenticationServices, UserNotifications, LinkPresentation, Network, WidgetKit, or storage implementation details would move to another layer. +- A repository protocol, service protocol, assembler, or DI ownership boundary would change. +- WidgetCore would start depending on app/domain/data implementation concepts. +- The requested change suggests cleanup outside the current issue or PR scope. + +### Safe mechanical changes + +These may proceed after inspection when they do not change architecture meaning: + +- Removing unused imports. +- Updating import statements after an already-approved file move. +- Fixing access control needed by an already-approved module boundary. +- Updating tests to match an already-approved public contract. +- Editing docs to reflect the current verified architecture. + +## Verification + +- If iOS project code changes, test build with Xcode Local MCP. +- If Xcode Local MCP is unavailable, state that explicitly before using a fallback. +- Do not claim architecture work is complete without checking the diff scope. +- Do not spend time on unrelated lockfile churn. Keep `Package.resolved` changes only when they are part of the requested task. +- For Firebase Cloud Functions, deploy updated functions one by one separately. + +## Canonical project rules + +- DevLog-specific working rules belong in this repository, not in global agent memory. +- Treat `AGENTS.md` and `.hermes/skills/devlog-architecture-harness` as the canonical DevLog AI working rules. +- If global memory conflicts with this repository, follow this repository. +- For PR, commit, Xcode project, CI, widget, Store, localization, or release workflow details, read `.hermes/skills/devlog-architecture-harness/references/devlog-workflow-rules.md`. + +## Sub-agent use + +- Consider sub-agent use on every non-trivial task. +- Use sub-agents only for independent research, verification, or disjoint implementation work. +- Do not use sub-agents for sequential steps, overlapping file edits, or tightly coupled refactors. +- The main agent remains responsible for planning, integration, final verification, and user communication. From 409bc3656bdfa1c9d5309b2054d4aa1873fcb3eb Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 18 May 2026 18:30:49 +0900 Subject: [PATCH 2/6] =?UTF-8?q?docs:=20Hermes=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=95=88=EB=82=B4=20=EB=AC=B8=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DevLog 프로젝트에서 사용하는 Hermes Skill 위치 안내 로컬 Skill 설치 명령과 실행 방법 정리 AGENTS.md와 Hermes reference의 canonical 관계 명시 --- .hermes/README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .hermes/README.md diff --git a/.hermes/README.md b/.hermes/README.md new file mode 100644 index 00000000..623b46eb --- /dev/null +++ b/.hermes/README.md @@ -0,0 +1,33 @@ +# Hermes Setup for DevLog + +This directory stores the DevLog-specific Hermes skill source. + +## Skill + +- `skills/devlog-architecture-harness` + +Use this skill before module boundary, DI, repository, Firebase-boundary, widget-data-flow, or architecture documentation work in this repository. + +## Install into Hermes + +Hermes loads installed skills from the user's Hermes skills directory. Keep this repository copy as the project-owned source of truth, then install or copy it into your Hermes profile when needed. + +```sh +mkdir -p ~/.hermes/skills/project +cp -R .hermes/skills/devlog-architecture-harness ~/.hermes/skills/project/devlog-architecture-harness +``` + +After installing, start a new Hermes session and invoke: + +```text +/devlog-architecture-harness +``` + +## Canonical project rules + +`AGENTS.md` is the canonical repo-wide rule file. The Hermes skill should stay aligned with it. + +Detailed DevLog workflow rules live in: + +- `skills/devlog-architecture-harness/references/devlog-architecture-flow.md` +- `skills/devlog-architecture-harness/references/devlog-workflow-rules.md` From e3bcdaf235b46c08c6c4e49ff287ca31ef52b083 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 18 May 2026 18:31:00 +0900 Subject: [PATCH 3/6] =?UTF-8?q?docs:=20DevLog=20Hermes=20Skill=20=EC=A7=84?= =?UTF-8?q?=EC=9E=85=EC=A0=90=20=EB=AC=B8=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 아키텍처 작업에 적용할 Hermes Skill 메타데이터 추가 작업 분류, 모호성 게이트, 검증 절차 정의 상세 플로우와 워크플로 reference 연결 --- .../devlog-architecture-harness/SKILL.md | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 .hermes/skills/devlog-architecture-harness/SKILL.md diff --git a/.hermes/skills/devlog-architecture-harness/SKILL.md b/.hermes/skills/devlog-architecture-harness/SKILL.md new file mode 100644 index 00000000..64fc3baa --- /dev/null +++ b/.hermes/skills/devlog-architecture-harness/SKILL.md @@ -0,0 +1,124 @@ +--- +name: devlog-architecture-harness +description: Use before architecture, modularization, dependency-boundary, DI, repository, Firebase-boundary, or widget-data-flow work in the SwiftUI_DevLog repository. +version: 1.0.0 +metadata: + hermes: + tags: + - swift + - ios + - architecture + - modularization + - devlog + category: project +--- + +# DevLog Architecture Harness + +## When to use + +Use this skill in `/Users/opfic/Desktop/Github/App/SwiftUI_DevLog` when the task touches any of these areas: + +- Module boundary changes. +- File moves across `Application/DevLog*` or `Widget/DevLog*` targets. +- Import or target dependency changes. +- DI assembler wiring. +- Repository, service, store, or use case contracts. +- Firebase, social login, network, link metadata, notification, or WidgetKit dependency placement. +- Widget snapshot, App Group, or widget deep-link data flow. +- Architecture diagrams, README architecture text, or PR architecture explanation. + +This repository is an Xcode workspace-based modular iOS app. There is no root `Package.swift`; modules are separate `.xcodeproj` entries under `DevLog.xcworkspace`. + +## Required project context + +Before editing, read: + +1. `AGENTS.md` +2. `.gemini/styleguide.md` +3. `README.md` +4. `references/devlog-architecture-flow.md` +5. `references/devlog-workflow-rules.md` when the task involves PR review, commits, Xcode project files, CI, widgets, Store reducers, localization, or release/build tooling. + +Then inspect the concrete files and imports related to the requested change. Do not rely on the layer names alone. + +## Procedure + +### 1. Classify the request + +Classify the task as one of these: + +- `mechanical`: unused import cleanup, approved rename fallout, approved access-control adjustment, docs sync. +- `architectural`: module dependency, layer ownership, DI, protocol boundary, external SDK placement, widget data flow. +- `ambiguous`: more than one layer could reasonably own the type or dependency. + +If the task is `ambiguous`, stop and ask the user before editing. + +### 2. Build a boundary note + +For every architecture task, write a short internal boundary note before editing: + +- Current owner. +- Proposed owner. +- Current imports. +- Proposed imports. +- Dependency direction. +- Xcode target/framework dependency impact. +- External SDK exposure. +- Whether user confirmation is required. + +### 3. Apply the ambiguity gate + +Ask the user before editing when: + +- Core vs Domain ownership is unclear. +- A shared type is being moved only because multiple modules need access. +- Firebase/Auth/Firestore/Functions/Messaging-specific logic would leave Infra. +- WidgetCore would depend on Domain, Data, Infra, Persistence, Presentation, or App. +- Presentation would depend on Data, Infra, Persistence, or App. +- Data would gain concrete SDK or storage implementation details. +- The Presentation `Store` flow or reducer responsibility would change. +- A compile fix requires relaxing the intended architecture. +- The change is outside the requested issue or PR scope. + +### 4. Edit narrowly + +When the boundary is clear: + +- Keep the diff limited to the requested task. +- Preserve existing logic unless the user explicitly approved logic changes. +- Prefer existing DevLog naming and layer patterns. +- Preserve the existing Presentation `Store` pattern: `@MainActor`, `State`, `Action`, `SideEffect`, and `send -> reduce -> run`. +- Do not introduce unrelated cleanup. +- Do not change lockfiles unless dependency resolution is part of the task. + +### 5. Verify + +For Swift/iOS code changes: + +- Use Xcode Local MCP for the build. +- If Xcode Local MCP is unavailable, say so and ask before using another path unless the user already approved a fallback. +- Inspect the final diff for architecture-scope drift. + +For docs-only or harness-only changes: + +- Verify file presence. +- Check Markdown for obvious broken structure. +- No iOS build is required. + +## Required response shape + +After completion, report only: + +- Changed files. +- Architecture boundary decision. +- Verification result. +- Any user decisions still needed. + +## Do not do + +- Do not infer project-specific architecture policy from generic Clean Architecture rules when DevLog already has a concrete pattern. +- Do not move domain entities to Core just because multiple modules need them. +- Do not hide architecture decisions inside build-fix wording. +- Do not broaden a modularization task into unrelated Firestore, Messaging, or UI safety edits. +- Do not mark work complete if the diff contains unrelated project-file or lockfile churn. From 15869a31fcbbf9800978d09e185ac08013bf01f6 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 18 May 2026 18:31:11 +0900 Subject: [PATCH 4/6] =?UTF-8?q?docs:=20DevLog=20=EC=95=84=ED=82=A4?= =?UTF-8?q?=ED=85=8D=EC=B2=98=20=ED=94=8C=EB=A1=9C=EC=9A=B0=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AI 하네스의 요청 처리 흐름을 Mermaid로 정리 모듈 레이어 맵과 Core, Domain 판단 흐름 정의 외부 의존성, Widget 데이터, 검증 플로우 기준 추가 --- .../references/devlog-architecture-flow.md | 300 ++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 .hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md diff --git a/.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md b/.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md new file mode 100644 index 00000000..a3bb838e --- /dev/null +++ b/.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md @@ -0,0 +1,300 @@ +# DevLog Architecture Flow + +## Purpose + +This reference defines the DevLog-specific harness flow for AI-assisted architecture work. + +The goal is not to make the AI decide more architecture policy. The goal is to make the AI stop before it makes project-specific architecture decisions that should be confirmed by the user. + +Use this reference with `AGENTS.md` and `.hermes/skills/devlog-architecture-harness/SKILL.md`. + +This repository is an Xcode workspace-based modular iOS app. There is no root `Package.swift`; modules are separate `.xcodeproj` entries under `DevLog.xcworkspace`. + +## High-level harness flow + +```mermaid +flowchart TD + Request["User request"] + LoadRules["Load DevLog rules"] + LoadContext["Inspect current repository context"] + Classify["Classify change type"] + Boundary["Check layer boundary"] + Ambiguous{"Architecture boundary ambiguous?"} + Ask["Ask user before editing"] + Plan["Prepare narrow edit plan"] + Edit["Apply scoped change"] + Verify["Verify build or docs state"] + Diff["Inspect final diff scope"] + Record["Report decision and result"] + + Request --> LoadRules + LoadRules --> LoadContext + LoadContext --> Classify + Classify --> Boundary + Boundary --> Ambiguous + Ambiguous -->|Yes| Ask + Ask --> Boundary + Ambiguous -->|No| Plan + Plan --> Edit + Edit --> Verify + Verify --> Diff + Diff --> Record +``` + +## Change classification + +```mermaid +flowchart TD + Change["Requested change"] + ImportOnly{"Only import/access fallout?"} + BoundaryMove{"Moves ownership or dependency?"} + SDKPlacement{"Changes external SDK placement?"} + DIChange{"Changes assembler or DI ownership?"} + WidgetFlow{"Changes widget data flow?"} + Mechanical["Mechanical change"] + Architecture["Architecture change"] + Ambiguous["Ambiguous change"] + + Change --> ImportOnly + ImportOnly -->|Yes| Mechanical + ImportOnly -->|No| BoundaryMove + BoundaryMove -->|Yes| Architecture + BoundaryMove -->|No| SDKPlacement + SDKPlacement -->|Yes| Architecture + SDKPlacement -->|No| DIChange + DIChange -->|Yes| Architecture + DIChange -->|No| WidgetFlow + WidgetFlow -->|Yes| Architecture + WidgetFlow -->|No| Ambiguous +``` + +## DevLog layer map + +```mermaid +flowchart TD + App["DevLogApp\nComposition root\nApp lifecycle\nAssembler wiring"] + Presentation["DevLogPresentation\nSwiftUI views\nViewModels\nCoordinators\nUI state"] + Domain["DevLogDomain\nEntities\nRepository protocols\nUse cases"] + Data["DevLogData\nRepository implementations\nDTOs\nMappers\nService/store protocols"] + Infra["DevLogInfra\nFirebase\nSocial login\nNetwork\nLink metadata\nMessaging"] + Persistence["DevLogPersistence\nUserDefaults\nImage store\nWidget snapshot persistence"] + Core["DevLogCore\nDI\nLogger\nShared value/query types\nWidget snapshot values"] + WidgetCore["DevLogWidgetCore\nWidget snapshot models\nFactories\nApp Group constants"] + WidgetExtension["DevLogWidgetExtension\nWidgetKit UI\nProviders\nTimelines"] + + App --> Presentation + App --> Domain + App --> Data + App --> Infra + App --> Persistence + App --> Core + App --> WidgetCore + + Presentation --> Domain + Presentation --> Core + + Domain --> Core + + Data --> Domain + Data --> Core + + Infra --> Data + Infra --> Core + + Persistence --> Data + Persistence --> Core + Persistence --> WidgetCore + + WidgetExtension --> WidgetCore + WidgetCore --> Core +``` + +## Boundary rules + +| Layer | Owns | Allowed direction | Ask before | +| --- | --- | --- | --- | +| `DevLogCore` | DI primitives, logger, shared value/query types, widget snapshot values | No DevLog layer dependency | Moving domain entities into Core | +| `DevLogDomain` | entities, repository protocols, use cases | Core only | Adding Data, Infra, Persistence, Presentation, App, Widget UI, or SDK dependency | +| `DevLogData` | repository implementations, DTOs, mappers, data protocols | Domain, Core | Adding concrete Firebase, WidgetKit, storage, or platform implementation details | +| `DevLogInfra` | Firebase, social login, network, metadata, messaging implementations | Data, Core | Moving SDK-specific behavior out of Infra | +| `DevLogPersistence` | local stores, image cache, widget snapshot persistence | Data, Core, WidgetCore | Moving domain logic or remote SDK behavior into Persistence | +| `DevLogPresentation` | UI, view models, coordinators, presentation state | Domain, Core | Adding Data, Infra, Persistence, or App dependency | +| `DevLogApp` | composition root, lifecycle, assembler wiring | Concrete app layers | Moving feature logic into App | +| `DevLogWidgetCore` | widget data contracts and pure snapshot logic | Core | Adding Domain, Data, Infra, Persistence, Presentation, or App dependency | +| `DevLogWidgetExtension` | WidgetKit rendering and timeline plumbing | WidgetCore | Calling app/domain services directly | + +## Presentation Store flow + +```mermaid +flowchart LR + View["SwiftUI View"] + ViewModel["ViewModel / Store"] + Send["send(Action)"] + Reduce["reduce(with:)"] + State["State update"] + SideEffect["SideEffect"] + Run["run(SideEffect)"] + Service["Injected use case or service"] + + View --> ViewModel + ViewModel --> Send + Send --> Reduce + Reduce --> State + Reduce --> SideEffect + SideEffect --> Run + Run --> Service + Service --> Send +``` + +Preserve this flow unless the user explicitly asks to change the Presentation architecture. Reducers compute state and return side effects. I/O belongs in `run` or injected services. + +## Ambiguity gate + +The AI must stop and ask the user when it reaches any of these points. + +```mermaid +flowchart TD + Check["Architecture decision needed"] + CoreDomain{"Core vs Domain ownership?"} + Shared{"Moved only because shared?"} + NewDependency{"New module dependency?"} + ExternalSDK{"External SDK crosses layer?"} + WidgetBoundary{"WidgetCore sees app/domain/data?"} + BuildShortcut{"Build fix relaxes boundary?"} + ScopeDrift{"Outside current task scope?"} + Ask["Ask user before editing"] + Proceed["Proceed with scoped edit"] + + Check --> CoreDomain + CoreDomain -->|Yes| Ask + CoreDomain -->|No| Shared + Shared -->|Yes| Ask + Shared -->|No| NewDependency + NewDependency -->|Yes| Ask + NewDependency -->|No| ExternalSDK + ExternalSDK -->|Yes| Ask + ExternalSDK -->|No| WidgetBoundary + WidgetBoundary -->|Yes| Ask + WidgetBoundary -->|No| BuildShortcut + BuildShortcut -->|Yes| Ask + BuildShortcut -->|No| ScopeDrift + ScopeDrift -->|Yes| Ask + ScopeDrift -->|No| Proceed +``` + +## Core vs Domain decision flow + +Use this flow when deciding whether a type belongs in Core or Domain. + +```mermaid +flowchart TD + Type["Type under review"] + DomainMeaning{"Represents business/domain meaning?"} + QueryOrPrimitive{"Generic query, option, logger, DI, or shared primitive?"} + UsedByWidget{"Needed by WidgetCore snapshot contract?"} + OnlyShared{"Only reason is multiple modules need it?"} + Domain["Keep or place in DevLogDomain"] + Core["Keep or place in DevLogCore"] + Ask["Ask user"] + + Type --> DomainMeaning + DomainMeaning -->|Yes| Domain + DomainMeaning -->|No| QueryOrPrimitive + QueryOrPrimitive -->|Yes| Core + QueryOrPrimitive -->|No| UsedByWidget + UsedByWidget -->|Yes| Core + UsedByWidget -->|No| OnlyShared + OnlyShared -->|Yes| Ask + OnlyShared -->|No| Ask +``` + +## External dependency flow + +Use this flow before introducing or moving imports such as Firebase, GoogleSignIn, AuthenticationServices, UserNotifications, LinkPresentation, Network, or WidgetKit. + +```mermaid +flowchart TD + Import["External framework import"] + Firebase{"Firebase/Auth/Firestore/Functions/Messaging?"} + SocialLogin{"GoogleSignIn or AuthenticationServices login implementation?"} + NetworkMeta{"Network or LinkPresentation implementation?"} + WidgetKit{"WidgetKit?"} + Infra["Prefer DevLogInfra"] + Persistence["Allow only for widget snapshot update/persistence if already established"] + WidgetExtension["Allow in DevLogWidgetExtension rendering/timeline code"] + Ask["Ask user before crossing layer"] + + Import --> Firebase + Firebase -->|Yes| Infra + Firebase -->|No| SocialLogin + SocialLogin -->|Yes| Infra + SocialLogin -->|No| NetworkMeta + NetworkMeta -->|Yes| Infra + NetworkMeta -->|No| WidgetKit + WidgetKit -->|Widget UI| WidgetExtension + WidgetKit -->|Snapshot update already established| Persistence + WidgetKit -->|Other| Ask +``` + +## Widget data-flow boundary + +```mermaid +flowchart LR + App["App runtime\nDomain/Data/Infra/Persistence"] + Snapshot["Snapshot generation\nPersistence + WidgetCore"] + AppGroup["App Group storage\nShared defaults"] + WidgetCore["WidgetCore\nSnapshot models\nFactories"] + WidgetExtension["Widget extension\nWidgetKit UI"] + + App --> Snapshot + Snapshot --> AppGroup + AppGroup --> WidgetCore + WidgetCore --> WidgetExtension +``` + +Widget UI should consume snapshot data. It should not fetch app services or domain repositories directly. + +## Verification flow + +```mermaid +flowchart TD + Changed["Files changed"] + Swift{"Swift/iOS project code changed?"} + Docs{"Docs or harness only?"} + Xcode["Build with Xcode Local MCP"] + Diff["Inspect git diff scope"] + NoBuild["No iOS build required"] + Report["Report verification result"] + + Changed --> Swift + Swift -->|Yes| Xcode + Swift -->|No| Docs + Docs -->|Yes| NoBuild + Docs -->|No| Diff + Xcode --> Diff + NoBuild --> Diff + Diff --> Report +``` + +## Required working notes + +Before editing architecture code, the AI should be able to answer these questions: + +1. What layer owns the changed concept today? +2. What layer should own it after the change? +3. Which imports prove the current dependency direction? +4. Which target dependency will change? +5. Does the change expose an external SDK outside its current boundary? +6. Does the change affect WidgetCore or WidgetExtension boundaries? +7. Is this change inside the current issue or PR scope? +8. Is user confirmation required before editing? + +## Completion checklist + +- DevLog-specific rules were loaded. +- Current files and imports were inspected. +- Ambiguous architecture decisions were confirmed by the user. +- Swift logic was preserved unless explicitly approved. +- Diff scope was checked. +- Xcode Local MCP build was used for Swift/iOS code changes. +- Docs-only or harness-only changes were reported as such, without claiming app build verification. From 54f5d682f755800f9751e6d8afe1fa090ca6f3bd Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 18 May 2026 18:31:31 +0900 Subject: [PATCH 5/6] =?UTF-8?q?docs:=20DevLog=20=EC=9E=91=EC=97=85=20?= =?UTF-8?q?=EA=B7=9C=EC=B9=99=20=EB=AC=B8=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR, 커밋, Xcode 프로젝트, CI 작업 규칙 정리 Data, Domain, Infra 경계와 Presentation Store 규칙 이전 Widget, localization, release 관련 DevLog 전용 규칙을 Hermes reference로 분리 --- .../references/devlog-workflow-rules.md | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 .hermes/skills/devlog-architecture-harness/references/devlog-workflow-rules.md diff --git a/.hermes/skills/devlog-architecture-harness/references/devlog-workflow-rules.md b/.hermes/skills/devlog-architecture-harness/references/devlog-workflow-rules.md new file mode 100644 index 00000000..c72a3c8a --- /dev/null +++ b/.hermes/skills/devlog-architecture-harness/references/devlog-workflow-rules.md @@ -0,0 +1,90 @@ +# DevLog Workflow Rules + +This reference holds DevLog-specific working rules that should live with the project, not in global agent memory. + +## Canonical source + +- Treat this repository's `AGENTS.md` and `.hermes/skills/devlog-architecture-harness` as the canonical DevLog working rules. +- Use global memory only as historical context. If global memory conflicts with this repository, follow the repository. +- Before changing architecture rules, update the repository-local rules first. + +## Verification + +- Prefer Xcode Local MCP for iOS project code changes. +- If Xcode Local MCP is unavailable or fails because of session transport, state that explicitly before using a fallback. +- This repository is workspace-based. Prefer workspace/scheme context over standalone project builds when dependencies cross module projects. +- CI truth lives in `.github/workflows/build.yml`: `DevLog.xcworkspace`, scheme `DevLog`, simulator build, `-resolvePackageDependencies`, `-skipPackagePluginValidation`, and `-skipMacroValidation`. +- CI is build validation, not a full test run, unless the workflow changes. +- Avoid unrelated `Package.resolved` churn. Keep lockfile changes only when dependency resolution is the task. + +## Xcode project file work + +- Inspect Swift imports and `.xcodeproj/project.pbxproj` framework links together. +- Validate touched `project.pbxproj` files with `plutil -lint`. +- `plutil -lint` does not prove Xcode save behavior is healthy; for Xcode save crashes, inspect crash reports and project-reference call stacks. +- Do not force a single `objectVersion` across projects. Treat Xcode's actual save output as the source of truth. +- For synchronized-root cleanup, verify on copied files or a narrowed rule set before touching real project files. +- When removing project-file objects, distinguish stale product references, real target links, orphan build files, and plugin churn. + +## PR and review handling + +- Write DevLog PR and review text in Korean. +- Follow `.github/pull_request_template.md` for PR body structure. +- If the user asks for PR content only, return the Markdown directly and do not create files. +- For unresolved GitHub review threads, use thread-aware inspection such as `gh api graphql` review threads or the `gh-address-comments` skill. Flat comments are not enough. +- Handle narrowed review feedback one item at a time. +- Verify a review suggestion against the real code and diff before accepting it. +- If a cleanup is deferred to an issue, show the issue URL visibly rather than hiding it behind an inline Markdown link when the user asks for review/PR note text. + +## Commit guidance + +- If the user says they will commit or asks only for a commit message, provide commit-message guidance instead of committing. +- Before proposing a commit message, inspect the actual diff and recent `git log`. +- Match the repository's current Korean style and prefix pattern. +- If the user explicitly specifies a prefix or noun-phrase ending, follow it exactly. +- For broad architecture refactors, split commits by layer when the user asks for staged commits. + +## Architecture staging + +- For modular refactors, state the next stage before editing when the user asks what comes next. +- When the user wants explicit phases, keep phases clean even if intermediate commits temporarily break the build. +- A common DevLog modularization sequence is external dependency removal, architecture application, then reattaching removed modules by layer. +- Keep project-file, lockfile, and code changes separated when the task scope requires clean review. +- Do not broaden architecture work into unrelated Firestore, Messaging, UI, or safety edits. + +## Data, Domain, and Infra boundary + +- Do not move domain entities to Core only because multiple modules need them. +- Keep protocol location and implementation layer distinct when explaining or changing boundaries. +- If a Data protocol is implemented by Infra, every type in that protocol signature must be visible to Infra. +- Prefer a Data-side boundary value plus repository mapping when Infra should not import Domain. +- For example, keep the app-facing Domain query separate from an Infra-facing Data query when that avoids Domain coupling in service protocols. +- Firebase-specific error detection belongs in Infra; Data should handle domain-level errors after mapping. + +## Presentation Store + +- Preserve the existing `Store` shape: `@MainActor`, `State`, `Action`, `SideEffect`, `send -> reduce -> run`. +- Reducers compute state and return side effects. +- I/O belongs in `run` or injected services. +- Do not leave reducer-era helper methods behind after moving work into `run`. +- Before adding task cancellation or async wrappers, inspect whether the underlying operation is actually async. + +## Widget flow + +- Widget UI should consume snapshot data, not app/domain services. +- `DevLogWidgetCore` should stay free of Domain, Data, Infra, Persistence, Presentation, and App dependencies unless the user explicitly approves a boundary change. +- Prefer an app-driven snapshot flow: app/runtime data fetch, snapshot generation, App Group storage, WidgetCore model/factory, WidgetExtension rendering. +- `WidgetTodoSnapshot` is a lightweight snapshot value, not a full domain `Todo`. +- Do not make `Todo.number` or `WidgetTodoSnapshot.number` non-optional without a separate saved-vs-draft model decision. +- 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. + +## Localization + +- For `.xcstrings`, use `jq empty` for structural validation when `plutil -lint` reports format-related false failures. +- Keep `.xcstrings` cleanup surgical and inspect the diff first if the file is already dirty. + +## Release and private config + +- `release.yml` creates GitHub releases after merged PRs into `main` from `develop`; it does not upload to App Store/TestFlight by itself. +- TestFlight workflow private config comes from the project-specific private config action. +- Runtime/build-required private files must be restored through the documented project workflow, not guessed. From dde5385393f2fa0b884d2dba41cc6b8d2f16f3b0 Mon Sep 17 00:00:00 2001 From: opficdev Date: Tue, 19 May 2026 14:37:43 +0900 Subject: [PATCH 6/6] =?UTF-8?q?docs:=20=EC=A0=88=EB=8C=80=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EB=8C=80=EC=8B=A0=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=EC=9D=98=20=EC=83=81=EB=8C=80=20=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .hermes/skills/devlog-architecture-harness/SKILL.md | 2 +- AGENTS.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.hermes/skills/devlog-architecture-harness/SKILL.md b/.hermes/skills/devlog-architecture-harness/SKILL.md index 64fc3baa..a26d4a8e 100644 --- a/.hermes/skills/devlog-architecture-harness/SKILL.md +++ b/.hermes/skills/devlog-architecture-harness/SKILL.md @@ -17,7 +17,7 @@ metadata: ## When to use -Use this skill in `/Users/opfic/Desktop/Github/App/SwiftUI_DevLog` when the task touches any of these areas: +Use this skill in the repository root when the task touches any of these areas: - Module boundary changes. - File moves across `Application/DevLog*` or `Widget/DevLog*` targets. diff --git a/AGENTS.md b/AGENTS.md index db210dee..ffe89dec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ ## Scope -These instructions apply only to `/Users/opfic/Desktop/Github/App/SwiftUI_DevLog`. +These instructions apply only to the repository root. ## Logic preservation and optimization