# Module Boundary Design

> Design a new module or split a large code area into coherent modules with explicit boundaries. Trigger when the user wants to introduce a module, carve out a subsystem, split a large component, reduce coupling, clarify ownership, or phrases like "выдели модуль", "разрежь это на модули", "спроектируй границы", "как правильно выделить новый модуль", or similar. Define responsibilities, boundaries, ownership, input/output contracts, state model, extension points, anti-coupling rules, test strategy, and phased adoption plan. Keep the design concrete and implementation-oriented. Prevent vague helper, service, or utils architectures by making responsibilities and dependency directions explicit. Do not use for broad architecture option comparison, full implementation planning, or generic code cleanup.

- Skill: `kirillklem/module-boundary-design` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add kirillklem/module-boundary-design`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kirillklem/module-boundary-design/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: KirillKlem (https://skillmd.com/u/kirillklem)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/kirillklem/module-boundary-design

---


# Module Boundary Design

## Purpose

Design a module boundary that is strong enough to survive implementation pressure.

This skill is for:
- introducing a new module
- splitting a large module into smaller ones
- isolating a subsystem
- clarifying ownership and dependency direction
- reducing accidental coupling
- replacing "helper/service/utils" sprawl with explicit structure

The goal is not to rename folders.
The goal is to define a module that has:
- a clear job
- explicit contracts
- controlled state
- bounded dependencies
- a realistic adoption path

## Use when

Use this skill when:
- one code area is too large or too mixed in responsibility
- boundaries between concerns are blurry
- multiple parts of the system depend on internals they should not touch
- a new module must be introduced cleanly
- the user wants to split a subsystem into coherent parts
- the user wants to stop architecture from collapsing into generic shared code

Typical trigger phrases:
- "выдели новый модуль"
- "разрежь это на модули"
- "спроектируй границы модуля"
- "как вынести это в отдельный модуль"
- "we need clearer module boundaries"
- "split this subsystem"
- "reduce coupling here"

## Do not use when

Do not use this skill for:
- broad architecture option comparison
- full system design docs
- milestone planning
- generic refactoring with no structural boundary question
- bug fixing
- naming-only cleanups
- "just move files around" tasks with no design intent

If the user has not yet chosen an overall architecture direction, use an architecture-options-analysis skill first.
If the module design is fixed and execution steps are needed, use an implementation-plan skill next.

## Inputs

Expected inputs:
- current code area or subsystem
- target reason for modularization
- known pain points
- existing dependencies, call paths, or ownership issues

Optional inputs:
- performance constraints
- compatibility constraints
- deployment boundaries
- test constraints
- organizational ownership
- migration constraints

## Outputs

Always produce:
1. current state summary
2. proposed module boundary
3. module responsibilities
4. explicit non-responsibilities
5. ownership and dependency direction
6. input/output contracts
7. state model
8. extension points
9. anti-coupling rules
10. testing strategy
11. phased adoption plan

## Core principles

- A module must have one coherent responsibility envelope.
- Boundaries must be explicit enough that future code can respect them.
- Shared code is not a virtue by itself.
- "helper", "service", and "utils" are warning signs unless they describe a real boundary.
- A module should expose contracts, not internals.
- Coupling must be controlled by direction, not by convention alone.

## Constraints

- Focus on the boundary, not just file placement.
- Non-responsibilities are mandatory.
- Anti-coupling rules are mandatory.
- Contracts must be strong enough that consumers do not need internal knowledge.
- State ownership must be explicit.
- Prefer incremental extraction over big-bang moves when possible.

## Procedure

1. Summarize the current state.
   First identify:
   - what code exists now
   - what responsibilities are currently mixed together
   - what pain points exist
   - what dependencies flow in and out
   - which internal details are leaking across boundaries

2. Identify why modularization is needed.
   Be explicit about the actual pressure:
   - too many responsibilities in one place
   - unstable dependencies
   - unclear ownership
   - poor testability
   - repeated logic with hidden coupling
   - migration pressure
   - scaling or performance isolation
   - interface confusion

3. Define the proposed module goal.
   State what the module is meant to encapsulate.
   The goal must be operational, for example:
   - coordinate ingestion of tracking frames
   - expose touch-candidate extraction
   - manage persistence for event snapshots
   - evaluate business rules for rollout gating

   Avoid vague goals like:
   - "shared helpers"
   - "common utilities"
   - "support logic"

4. Define responsibilities.
   List what the module is responsible for.
   Responsibilities should be concrete and bounded.

5. Define non-responsibilities.
   Explicitly state what the module does not own.
   This is mandatory.
   Examples:
   - does not manage persistence
   - does not own orchestration
   - does not call external services directly
   - does not render user-facing outputs
   - does not perform training

   A module without explicit non-responsibilities will expand until it becomes a junk drawer.

6. Define ownership.
   Clarify:
   - who owns the module conceptually
   - what other modules may depend on it
   - whether it is a leaf module, domain module, adapter module, or orchestration module
   - what direction dependencies are allowed to flow

7. Define input/output contracts.
   For every important entry point, specify:
   - input shape, type, or schema
   - output shape, type, or schema
   - sync/async expectations
   - error surface
   - idempotency or ordering expectations if relevant

   The contract must be strong enough that consumers do not need to know internals.

8. Define the state model.
   Specify:
   - whether the module is stateless or stateful
   - what state it owns
   - what state it only reads
   - what state transitions matter
   - whether state is mutable, append-only, cached, derived, or externally sourced
   - what invariants must hold

9. Define extension points.
   Identify where future variation is legitimate.
   Good extension points are narrow and intentional:
   - strategy interface for one policy choice
   - registry for one known family of handlers
   - pluggable storage backend under a stable contract

   Do not create generic extension points "just in case".

10. Define anti-coupling rules.
    State the rules that protect the boundary, for example:
   - consumers may only use public interfaces
   - no cross-module access to internal state
   - dependency direction is one-way
   - orchestration stays outside the module
   - persistence adapters do not import domain logic
   - feature flags do not leak into domain primitives

    These rules should be specific enough to review against.

11. Define testing strategy.
    The module test strategy should include:
   - unit tests for internal logic where appropriate
   - contract tests for public interfaces
   - state transition tests for stateful modules
   - narrow integration tests for boundary interactions
   - anti-regression checks for phased adoption

    Testing must align with the boundary, not just the file structure.

12. Define phased adoption.
    Explain how the module can be introduced safely:
   - wrap existing behavior behind the new boundary
   - migrate one call site or responsibility slice at a time
   - maintain compatibility shims if needed
   - stop once the old path is no longer required
   - remove temporary bridges deliberately

    The adoption plan must minimize simultaneous rewrites.

13. Check for boundary smell.
    Before finalizing, ask:
   - is the module too broad?
   - is it just a renamed utils package?
   - does it own behavior or only collect helpers?
   - are inputs/outputs explicit?
   - is dependency direction enforceable?
   - can the module be tested as a unit of responsibility?

## Decision rules

### Responsibility rule

If the module cannot be described by one coherent responsibility envelope, the boundary is probably wrong.

### Non-responsibility rule

If the design cannot clearly state what the module does not own, it is too vague.

### Contract rule

If consumers still need to know internal behavior to use the module safely, the contract is too weak.

### State rule

If state ownership is unclear, bugs and leakage will follow.
State must be assigned explicitly.

### Extension-point rule

Only define extension points for realistic variation.
Do not create framework-like abstractions by default.

### Coupling rule

If the design relies on "developers being careful" instead of explicit dependency direction, the boundary is weak.

### Testing rule

If the module cannot be tested through its public surface, the boundary is likely not real.

### Adoption rule

Prefer designs that support incremental extraction over big-bang moves.

## Optional subagent use

For larger or messier systems, explicitly spawn bounded subagents before finalizing the module design:
- one subagent to map current responsibilities and coupling
- one subagent to inspect public/private usage patterns
- one subagent to identify the cheapest phased extraction path

Wait for their memos, then synthesize the final boundary design.
Do not spawn subagents for a small local extraction.

## References

Use the supporting references when needed:
- `references/module-boundary-template.md`
- `references/contracts-and-state-checklist.md`
- `references/anti-coupling-and-adoption-checklist.md`

## Definition of done

- The proposed module has a clear responsibility envelope.
- Non-responsibilities are explicit.
- Contracts and state ownership are concrete.
- Anti-coupling rules are specific enough to review against.
- The testing strategy matches the boundary.
- The adoption path is incremental and realistic.

## Final response format

Return the result in this structure:

- Current state
- Why modularization is needed
- Proposed module
- Responsibilities
- Non-responsibilities
- Ownership and dependency direction
- Input/output contracts
- State model
- Extension points
- Anti-coupling rules
- Testing strategy
- Phased adoption plan

## Positive examples

Use this skill for:
- "выдели это в отдельный модуль"
- "разрежь этот кусок системы на модули"
- "спроектируй границы нового модуля"
- "как перестать тащить это в utils"
- "design a proper boundary for this subsystem"
- "split this large module cleanly"

## Negative examples

Do not use this skill for:
- "сравни варианты архитектуры"
- "сделай план реализации"
- "напиши design doc на всю систему"
- "почини баг"
- "ускорь этот модуль"

