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
آخر نشاط في المصدر
٨ أكتوبر ٢٠٢٦ في ٠١:٥٢
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٥
التفرعات
١

خيارات التثبيت

يُحدَّد 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 `jaw-dev` §0.0 Work Classifier + §0.1 Patch Fast-Path before reading references. > **`jaw-dev` is canonical:** `jaw-dev` §0.2 Rule Classes, §3 Verification Gate, and §5 Safety Rules apply to all work governed by this skill. > **Always read `jaw-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 describes impact only when backed by a concrete failure. Style, coupling, and size heuristics follow `jaw-dev` §0.2 DEFAULT exceptions; uppercase severity alone does not make a structural preference a safety gate. ## 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 `jaw-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 Files over 400 LOC trigger a cohesion review (DEFAULT). Split by responsibility when useful; document a justified exception instead of blocking by size alone. | Signal | Action | |--------|--------| | File exceeds 400 LOC | Review cohesion; split by responsibility or explain the exception | | 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:** Parse untrusted shape once at trust ingress; do not repeat shape validation within a trusted typed boundary. Enforce domain ranges, state transitions, and relational invariants in their domain owner, including for in-process callers. Preserve authorization and assertions for reachable invalid states. This section distinguishes ingress parsing from domain invariants. `jaw-dev-security` owns security validation and authorization policy; placement must not erase a business invariant or required defense in depth. ### 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 repeated shape parsing; domain constraints may apply | Types prove shape, not every business invariant | Domain owner checks start <= end | | **Private method args** | No repeated shape parsing; invariants may apply | Types do not prove every valid state | Enforce real domain constraints | | **Service-to-service in same process** | No repeated trusted shape parsing; enforce domain/security rules | In-process is no waiver for invariants or authorization | Check the actual constraint | ### 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 | | Repeated shape checks on validated trusted values | Adds noise without a new boundary | Trust the parsed shape; retain domain invariants and reachable-state checks | | Assertions on states proven impossible by the actual contract | Distract from reachable failures | Fix types where sufficient; retain assertions for real state constraints | | Repeating ingress shape parsing in each domain constructor | Duplicates a trusted parser | Parse shape once; enforce entity/value-object invariants in the domain owner | | 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 (jaw-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 | | Utility folder (`utils/index.ts`) | NO | Creates coupling magnet | | Component folder re-exporting siblings | NO | Direct imports are clearer | | Monorepo package boundary (`@org/shared/index.ts`) | YES | Cross-package contract |
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub