Skip to main content

jaw-dev-architecture

MUST USE for module boundary work, circular dependency detection, coupling review, barrel or re-export changes, and validation placement decisions. Triggers: circular import, module split, layer violation, dependency direction, utils growth, barrel file, re-export, boundary review, architecture refactor, 모듈 경계, 순환 참조.

ソース情報

リポジトリ
lidge-jun/cli-jaw-skills
ソースの最終更新活動
2026年9月2日 06:54
検出された SKILL.md の言語
英語
スター
5
フォーク
1

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

ファイルエクスプローラー
4 ファイル

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
jaw-dev-architecture
description
MUST USE for module boundary work, circular dependency detection, coupling review, barrel or re-export changes, and validation placement decisions. Triggers: circular import, module split, layer violation, dependency direction, utils growth, barrel file, re-export, boundary review, architecture refactor, 모듈 경계, 순환 참조.
metadata
{"short-description":"Module boundaries, circular deps, coupling taxonomy, and boundary defenses.","keywords":"module-boundary, circular-dependency, coupling, barrel-file, re-export, architecture, layered, dependency-inversion, event-driven","last-verified":"2026-07-02"}
# Dev-Architecture — Module Boundaries & Structural Integrity > **C0/C1 work (small local patches):** See `dev` §0.0 Work Classifier + §0.1 Patch Fast-Path before reading references. > **`dev` is canonical:** `dev` §0.2 Rule Classes, §3 Verification Gate, and §5 Safety Rules apply to all work governed by this skill. > **Always read `dev/SKILL.md` first** for project-wide conventions before applying architecture rules. Enforces architectural rules that prevent structural decay: circular dependencies, implicit coupling, barrel abuse, and misplaced validation. These rules are mechanical — an AI coding agent can follow them without subjective judgment. Severity mapping (dev §0.2): `Severity: CRITICAL`/`HIGH` ⇒ STRICT; `MEDIUM` ⇒ DEFAULT. ## Modular References | File | When to Read | What It Covers | |------|--------------|----------------| | `references/circular-dependencies.md` | Detecting or fixing import cycles | Detection commands (madge/pydeps/go vet), fix strategies, real examples | | `references/coupling-taxonomy.md` | Reviewing code for hidden coupling | 8 coupling types, severity matrix, refactoring patterns, banned review responses | | `references/barrel-discipline.md` | Creating/modifying index/barrel files | When barrels OK vs banned, tree-shaking impact, safe barrel template | ## External/current architecture evidence Architecture rules in this skill are local and mechanical. When an architectural decision depends on current framework guidance, cloud/provider reference architecture, package deprecation, platform limits, or public source evidence, read the active `search` skill and follow its query-rewrite, source-fetch, and evidence-status rules. Use browser verification only after candidate URLs exist. --- ## 1. Module Boundaries ### Layered Architecture Boundaries | Layer | May Import | MUST NOT Import | Example | |-------|-----------|-----------------|---------| | Presentation (UI/CLI/Controller) | Application, Domain | Infrastructure directly | React component importing DB client | | Application (Use Cases/Services) | Domain, Ports | Presentation, Infra adapters | Service importing React component | | Domain (Entities/Value Objects) | Nothing (self-contained) | Any other layer | Entity importing Express | | Infrastructure (Adapters/DB/HTTP) | Domain (implements ports) | Presentation, Application | DB adapter importing controller | ### When to Split a Module Canonical file-size rule: **>400 LOC -> split (DEFAULT)**. Deviations require a stated reason. | Signal | Action | |--------|--------| | File exceeds 400 LOC | Split by responsibility (DEFAULT) | | Module has 6+ direct dependents | Extract shared interface | | Two unrelated features share a file | Separate into own modules | | Circular import detected | Extract shared types/interfaces to a third module | | Module name contains "and" or "utils" | Split by actual concern | | 3+ apps/services import the same feature folder | Promote to a monorepo package with its own manifest + public boundary | | Package needs its own release cadence, CI matrix, or version | Split at package level, not folder level | ### Banned Patterns | Banned | Why | Fix | |--------|-----|-----| | `utils.ts` / `helpers.ts` growing unbounded | Becomes a coupling magnet | Split by domain: `date-utils.ts`, `string-format.ts` | | Cross-layer direct import | Breaks dependency direction | Use ports/adapters or event bus | | Shared mutable state between modules | Hidden temporal coupling | Pass explicitly or use event system | | God module (20+ exports) | Everything depends on it | Extract cohesive sub-modules | ### Module SSOT (Single Source of Truth) Every concept, constant, type, or configuration value MUST have exactly one canonical owner module. | Concept | Canonical Owner | Consumers Do | |---------|----------------|--------------| | Shared types / interfaces | `types/` or `contracts/` module | Import, never redefine | | Constants / magic values | Domain-specific constants module | Import the constant | | Config / env | Central config module | Import resolved values | | Validation schemas | Boundary module (API entry) | Import schema, don't recreate | | API contracts | API layer | Import types from API module | | Banned | Why | Fix | |--------|-----|-----| | Duplicating a type/constant in a consumer | Two sources of truth → drift | Import from canonical owner | | "Local copy for convenience" | Convenience becomes divergence | Import the original | | Re-deriving a value that has a canonical source | Silent inconsistency | Import the derived value or computation | ### Deep Modules and Seams Use this vocabulary when deciding whether an abstraction earns its keep: | Term | Meaning | |------|---------| | Module | A cohesive unit with a named responsibility and public interface | | Interface | The small surface consumers depend on | | Implementation | The hidden work behind that surface | | Depth | Large useful behavior hidden behind a small interface | | Seam | A boundary where alternative implementations are real or likely | | Adapter | Code translating one external shape into the module's interface | | Leverage | How much change the abstraction absorbs for its callers | | Locality | How close related behavior stays to its owning concept | Frontend depth means small props/events hiding complex rendering, state management, data transformation, or integration behavior. One adapter usually means hypothetical indirection; two adapters, or a near-term second adapter, is evidence of a real seam. Do not expose internals only for tests; test through the public interface or add a boundary-owned diagnostic hook with production value. --- ## 2. Circular Dependency Detection & Prevention **Severity: CRITICAL** **Rule:** No circular dependency may exist between modules. Every detected cycle MUST be resolved before merge. ### Required Agent Workflow | Phase | Required Action | Pass Condition | |-------|-----------------|----------------| | 1. Detect | Run ecosystem-specific detection command | Command exits clean (no cycles reported) | | 2. Classify | Identify cycle type: direct A<->B or transitive A->B->C->A | Type documented | | 3. Analyze | Determine root cause: shared type? callback? event? | Root interface identified | | 4. Fix | Apply appropriate fix strategy (see references/) | Detection command passes | | 5. Verify | Re-run detection + confirm no regressions | Zero cycles in report | Detection commands are ecosystem-specific. See `references/circular-dependencies.md` for command templates, examples, and verification details. ### Banned Patterns | Banned Pattern | Why Banned | Required Fix | |----------------|-----------|--------------| | A imports B, B imports A (direct cycle) | Compile failures, bundler issues, test fragility | Extract shared interface to C | | Type-only cycle (`import type` both ways) | Still signals wrong boundary | Move shared types to `types/` module | | Barrel re-export creating hidden cycle | Index file masks real dependency graph | Remove barrel, use direct imports | | Lazy import to "break" cycle (`require()` inside function) | Hides the problem, breaks tree-shaking | Fix the architecture, not the symptom | | "It works in runtime" as justification | Fragile, bundler-dependent, blocks refactoring | Must pass static analysis | | Circular via test file importing source that imports test helper | Test infra leaking into production graph | Isolate test helpers in `__test_utils__/` | ### Fix Guidance | Situation | Preferred Fix | |-----------|---------------| | Two modules share types | Extract `types.ts` or `contracts/` module both import | | Module A calls back into B | Dependency inversion: A defines interface, B implements | | Event producer and consumer import each other | Event bus / mediator pattern | | Circular at package level (monorepo) | Introduce `shared` or `contracts` package | | UI component imports its container | Lift shared state to context or prop drilling | | Service layer cycle | Extract orchestrator service or use events | --- ## 3. Implicit Coupling Taxonomy **Severity: CRITICAL** **Rule:** Every coupling instance in a code review MUST be classified by type. Coupling severity determines whether the code can merge. ### Coupling Types (ordered by severity, worst first) | # | Type | Definition | Severity | Fix Pattern | |---|------|-----------|----------|-------------| | 1 | **Content** | Module reaches into another's internals | CRITICAL | Expose via public API/method | | 2 | **Common** | Multiple modules share global mutable state | CRITICAL | Dependency injection, immutable config | | 3 | **Control** | Module passes flag to control another's logic | HIGH | Polymorphism, strategy pattern | | 4 | **Stamp** | Module passes large struct when only one field needed | HIGH | Pass only needed fields | | 5 | **External** | Multiple modules depend on same external format | HIGH | Single parser module, shared schema | | 6 | **Temporal** | Modules must execute in specific order | MEDIUM | Make ordering explicit (state machine, builder) | | 7 | **Sequential** | Output of A is input of B | LOW | Document the contract, validate at boundary | | 8 | **Functional** | Modules share a well-defined interface | LOW | This is GOOD coupling — the target state | See `references/coupling-taxonomy.md` for examples, detection signals, refactoring patterns, and banned review responses. ### Review Decision Matrix | Severity | Merge? | Action Required | |----------|--------|-----------------| | CRITICAL (Content, Common) | BLOCK | Must refactor before merge | | HIGH (Control, Stamp, External) | BLOCK unless justified | Require tech-debt ticket if merged | | MEDIUM (Temporal) | Allowed with documentation | Add ordering comments or state assertions | | LOW (Sequential, Functional) | ALLOWED | No action needed | --- ## 4. Boundary-Only Defensive Programming **Severity: CRITICAL** **Rule:** Validation and defensive checks belong ONLY at system boundaries. Internal module boundaries MUST trust their callers. Ownership split: **placement** (validation happens at the boundary, nowhere else) is owned by this section; **what the validation schema enforces** (content/policy) is owned by `dev-security` §1. ### Validation Location Matrix | Location | Validate? | Rationale | Example | |----------|-----------|-----------|---------| | HTTP/API controller input | YES | Untrusted external data | Zod schema, JSON schema | | CLI argument parsing | YES | Untrusted user input | yargs/commander validation | | File system reads | YES | External data, may be corrupt | Parse + validate structure | | Database query results | YES at ORM-untyped/raw-query boundaries (shape only); NO when a typed schema/ORM guarantees the shape | Untyped results may drift; typed guarantees are trusted (see Banned Patterns) | Check raw-query nulls/shape; trust typed ORM results | | Message queue consumer | YES | Cross-process boundary | Validate message schema | | **Internal function params** | **NO** | Caller is trusted code you control | Type system handles this | | **Private method args** | **NO** | Same module, same author | Redundant — types suffice | | **Service-to-service in same process** | **NO** | In-process calls share type system | Interface contracts handle this | ### Banned Patterns | Banned Pattern | Why Banned | Fix | |----------------|-----------|-----| | `if (!param) throw` at start of every internal function | Redundant with type system, clutters code | Remove — let TypeScript/types enforce | | Runtime type checks in typed language internals | Duplicates compiler work, adds noise | Trust the type system | | `assert(x !== null)` in module-internal code | If x can be null, fix the type; if it can't, the assert is noise | Fix type signature or remove assert | | Validation in domain entity constructor for in-process callers | Entities should be created from validated data | Validate at boundary, trust domain layer | | Try-catch around every internal call | Hides bugs, makes debugging harder | Let errors propagate, catch at boundary | | Null checks after DB query that schema guarantees NOT NULL | Distrusts your own schema | Trust schema, validate at migration time | ### Allowed Defensive Checks (Exceptions) | Situation | Why Allowed | Pattern | |-----------|-------------|---------| | Security-critical path (auth, crypto) | Defense in depth required by policy | Double-check even internal calls | | Data from deserialization (JSON.parse) | Runtime data, types lost | Validate with schema (Zod/io-ts) | | Plugin/extension boundary | Third-party code, untrusted | Validate at plugin interface | | Across deployment boundary (microservice call) | Network = system boundary | Full validation required | | Feature flags / A-B test paths | Runtime variation, not type-safe | Guard with runtime check | ### Fix Guidance | Smell | Diagnosis | Fix | |-------|-----------|-----| | 10+ `if (!x) throw` in one file | Over-defensive internal code | Remove guards, fix types | | Every function starts with parameter validation | Boundary confusion | Move all validation to entry point | | `try { } catch { return null }` everywhere | Error suppression | Let errors bubble, handle at boundary | | `typeof x === 'string'` in TypeScript | Distrusting compiler | Remove, or fix the type to be accurate | | Same validation in controller AND service | Duplicated boundary | Validate once at controller, service trusts | --- ## 5. Barrel/Re-export Discipline **Severity: HIGH** **Rule:** Barrel files (index.ts/index.js/__init__.py) are ONLY allowed at public boundaries — package APIs and feature public boundary exports. Internal convenience barrels are banned. ### Barrel Policy Matrix | Context | Barrel Allowed? | Rationale | |---------|-----------------|-----------| | Library/package public API (`packages/ui/index.ts`) | YES | Single entry point for consumers | | Framework plugin entry (`plugin/index.ts`) | YES | Plugin contract requires it | | Feature public boundary export (`features/auth/index.ts` as the feature's single external entry) | YES | Public Boundary Export (dev-scaffolding §1); external consumers import the boundary | | Feature internal convenience barrel (re-exporting siblings for imports inside the feature) | NO | Hides internal structure, breaks tree-shaking |
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る