dev-architecture/SKILL.md
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, 모듈 경계, 순환 참조.
npx skillsauth add lidge-jun/cli-jaw-skills dev-architectureInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
C0/C1 work (small local patches): See
dev§0.0 Work Classifier + §0.1 Patch Fast-Path before reading references.
devis canonical:dev§0.2 Rule Classes, §3 Verification Gate, and §5 Safety Rules apply to all work governed by this skill. Always readdev/SKILL.mdfirst 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.
| 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 |
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.
| 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 |
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 | 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 |
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 |
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.
Severity: CRITICAL Rule: No circular dependency may exist between modules. Every detected cycle MUST be resolved before merge.
| 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 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__/ |
| 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 |
Severity: CRITICAL Rule: Every coupling instance in a code review MUST be classified by type. Coupling severity determines whether the code can merge.
| # | 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.
| 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 |
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.
| 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 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 |
| 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 |
| 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 |
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.
| 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 |
| 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 |
See references/barrel-discipline.md for import examples, tree-shaking
details, ESLint enforcement, and the safe barrel template.
When reviewing any PR that adds/modifies module structure, verify:
madge --circular or equivalentrequire() inside function body to hide circular deps| Check | Tool | CI Command |
|-------|------|------------|
| Layer/dependency rules (preferred CI gate) | dependency-cruiser | npx depcruise --validate .dependency-cruiser.cjs src/ |
| Import boundaries | eslint-plugin-boundaries | ESLint with boundaries config |
| Circular deps (quick visualization) | madge | npx madge --circular --extensions ts,tsx src/ && echo "OK" |
| Barrel abuse | Biome noBarrelFile or ESLint no-restricted-imports | pattern for internal index files |
| Dead files/exports/deps | knip | npx knip |
| Monorepo package consistency | sherif | npx sherif |
| Module size | custom script | find src -name '*.ts' -exec wc -l {} + \| awk '$1 > 400' |
Tool roles verified 2026-07-02 (Sources: references/circular-dependencies.md).
dev-backend/references/core/observability.md for the canonical OTel setup.dev-security/SKILL.md for input validation and auth patterns.Does the code serve a distinct responsibility?
NO -> Keep in existing module
YES -> Is it used by 3+ other modules?
NO -> Co-locate with primary consumer
YES -> Create dedicated module with clear interface
What type? (see taxonomy above)
Content/Common -> BLOCK, refactor now
Control/Stamp/External -> BLOCK unless tech-debt ticket created
Temporal -> ALLOW with documentation
Sequential/Functional -> ALLOW
Is the data source external (HTTP, file, queue, DB, user input)?
YES -> Validate here (boundary)
NO -> Is this a security-critical path?
YES -> Validate (defense in depth)
NO -> Trust the type system, no validation needed
dev-code-reviewer.dev-debugging.dev-devops.Source: sol research (wednesday-solutions/ai-agent-skills AST dependency graph).
Instead of reconstructing a module map for every task, maintain a lightweight structural index that agents can query:
cxc map <dir> for on-demand symbol-level maps (already shipped).dependency-cruiser JSON, Nx project graph, or a custom SQLite index).This is a guidance concept, not a shipped tool. The agent should check for existing index artifacts before running ad-hoc scans.
Source: sol research (HoangNguyen0403/agent-skills-standard compliance auditing).
Architecture rules that exist only as prose are invisible to CI. For C3+ work where boundary violations would cause real harm:
depguard).tools
Use only on the Codex CLI for native image generation or image editing without an API key. Save final PNG files under ~/.cli-jaw/uploads, report web-ready absolute-path markdown, and send to Telegram or Discord only when explicitly requested.
tools
Ranked repository structure map via `cli-jaw map`. Use for codebase overview, structure map, symbol overview, unfamiliar codebase exploration, architecture orientation. Triggers: repo map, structure map, codebase overview, 와꾸, project structure, unfamiliar code.
tools
cli-jaw Design workspace: create, preview, run, and export design pages from the right sidebar. Covers panel UX, direct-write workflow, artifact lifecycle, wireframe generation, design system, and Open Design adapter.
development
MUST USE for infrastructure and delivery work — container builds, deploy pipelines, Kubernetes, Infrastructure as Code, SRE foundations, edge/serverless, ML infrastructure. Triggers: Dockerfile, K8s manifests, CI/CD pipeline, Terraform/IaC, release/deploy, devops/infra/deploy or release_cd task_tags.