diff --git a/skills/balanced-coupling/SKILL.md b/skills/balanced-coupling/SKILL.md index e2863d9..42db3e9 100644 --- a/skills/balanced-coupling/SKILL.md +++ b/skills/balanced-coupling/SKILL.md @@ -1,13 +1,11 @@ --- name: balanced-coupling description: > - The Balanced Coupling model for software design. Use when: designing modular architectures, - evaluating coupling between components, reviewing code modularity, deciding whether to split - or merge modules/services, assessing integration patterns, classifying coupling as balanced - or unbalanced, applying DDD strategic and tactical patterns, reasoning about cohesion vs - coupling trade-offs, identifying distributed monolith risks, or explaining why a system - is hard to change. Provides the three-dimensional framework (integration strength, distance, - volatility) and the balance rule for making coupling decisions. + Domain knowledge reference for the Balanced Coupling model by Vlad Khononov. + Loaded as a dependency by the review and design skills. Provides the three-dimensional + framework (integration strength, distance, volatility) and the balance rule for + making coupling decisions. Not for direct invocation — use review to analyze + existing codebases or design to create architectures from requirements. user-invocable: false --- @@ -19,43 +17,9 @@ A comprehensive reference for understanding the Balanced Coupling model as descr ## 1. Foundations: Why Coupling Matters -### 1.1 Coupling Is Not the Enemy +Coupling is not the enemy — it is a design tool. You cannot build a system from fully independent components. The question is not whether to couple but _how_. Some coupling leads to modularity; other coupling creates complexity. The balanced coupling model treats coupling as a **design tool** to wield deliberately. -The term "coupling" has long been synonymous with bad design. The balanced coupling model challenges this assumption. According to the dictionary, coupling is simply a device for connecting parts. If a system is a set of components interacting to achieve a goal, then coupling is what connects those components and makes it possible to achieve those goals. **Coupling is what makes the value of a system greater than the sum of its parts.** - -You cannot build a system out of fully independent components — that would go against the very definition of "system." The question is not whether to couple, but *how* to couple. Some forms of coupling lead to modularity; others create complexity. The balanced coupling model treats coupling not as a nuisance to eliminate but as a **design tool** to wield deliberately. - -### 1.2 Complexity (via Cynefin) - -The model adopts the Cynefin framework's definition of complexity: - -- **Clear (Simple):** You make a change and know exactly what the outcome will be. -- **Complicated:** You don't know the outcome, but an expert does and you can consult them. -- **Complex:** The only way to determine the outcome is to make the change and observe what happens. Cause and effect can only be identified in hindsight. -- **Chaotic:** No identifiable relationship between actions and outcomes, even in hindsight. - -In software design, **complexity** means a system where the outcomes of changes are unpredictable. The goal of modular design is to avoid situations where the effect of a change can only be identified in retrospect. - -Crucially, **complexity is subjective** — it is a function of both system design and our cognitive limits: - -``` -complexity = f(system design, cognitive limits) -``` - -Studies suggest humans can hold only 4 +/- 1 units of information in working memory simultaneously. When the information required to make a change exceeds this cognitive capacity, the design is complex. - -### 1.3 Modularity: The Opposite of Complexity - -If complexity makes change outcomes unpredictable, modularity is its opposite. A modular design satisfies two criteria: - -1. It is **clear what parts** of the system need to change. -2. The **outcome of the change** is clear and predictable. - -Modularity extends a system's goals into the future. It doesn't mean preemptively implementing future requirements — that's impossible. It means making the implementation of *reasonable* future changes easy by minimizing the cognitive load required. - -A system is a set of components interacting to achieve goals. Even a "big ball of mud" can achieve its current goals. Modular design extends the system's goals by ensuring it can *continue* to achieve goals as they evolve. - -### 1.4 The Shared Cause +Complexity (Cynefin definition): change outcomes are unpredictable. Modularity is the opposite — (1) clear what parts need to change, (2) outcome is predictable. Complexity is subjective: `complexity = f(system design, cognitive limits)`. Humans hold 4±1 units in working memory; exceeding this makes design complex. Complexity and modularity are contrasting concepts driven by the same fundamental cause: **coupling**. The way components are connected determines whether the system is modular or complex. @@ -71,48 +35,25 @@ Integration requires components to exchange **knowledge** about each other. The Rather than trying to "measure" knowledge quantitatively, the model **categorizes** types of knowledge. Each type involves significantly different amounts of shared knowledge. This is the **Integration Strength** model, which identifies four levels (from strongest/most knowledge to weakest/least): -#### Intrusive Coupling (Strongest) -Occurs when **private interfaces** or implementation details are used for integration — internal databases, private objects, undocumented APIs. We must assume **all knowledge** about a component's implementation is shared. Intrusive coupling is both **fragile** and **implicit** — the authors of the "intruded" component may not even know the integration exists. - -Corresponds to **content coupling** (pathological coupling) in the classic module coupling model. - -#### Functional Coupling -Shifts focus from *how* a component is implemented to *what* it implements: its **functional requirements**. Occurs when multiple components share knowledge of their business requirements and must change together when those requirements evolve. - -An extreme case is **duplicated knowledge** — the same business rule implemented in both frontend and backend. If a specification change isn't reflected in both simultaneously, the system enters an inconsistent state. - -Like intrusive coupling, functional coupling can be **implicit**: duplicated business logic in components that are not explicitly coupled yet still need to change together. - -Corresponds to **common, external, and control coupling** in the classic module coupling model. - -#### Model Coupling -Occurs when components share knowledge of a **business domain model**. If the model changes — due to new domain insights — all coupled components must change accordingly. - -Domain-driven design emphasizes working with multiple specialized models rather than one massive all-encompassing model. Model coupling arises when components share one of these models. - -Corresponds to **stamp coupling** in the classic module coupling model. +Prior coupling models (module coupling, connascence) are incorporated into this framework, not replaced. See [details.md](details.md) for the implicit-explicit spectrum and connascence degrees within each level. -#### Contract Coupling (Weakest) -The lowest level of shared knowledge. An integration contract **encapsulates** implementation details, functional requirements, and business models, making integration explicit and stable. +Four levels (strongest/most knowledge → weakest/least): -Design patterns that introduce contracts include: Facade, Open-host service / Published language (DDD), Anti-corruption layer (DDD), Data transfer objects (DTOs). +1. **Intrusive** (strongest) — uses **private interfaces** or implementation details (internal databases, private objects, undocumented APIs). All knowledge about implementation is shared. Both **fragile** and **implicit** — the authors of the intruded component may not even know the integration exists. (cf. content/pathological coupling) +2. **Functional** — shares knowledge of **business requirements**; components must change together when requirements evolve. An extreme case is **duplicated knowledge** — the same business rule in frontend and backend. If a spec change isn't reflected in both, the system enters an inconsistent state. Can be **implicit**: duplicated business logic in components not explicitly coupled yet needing to change together. (cf. common/external/control coupling) +3. **Model** — shares knowledge of a **business domain model**. If the model changes, all coupled components must change. DDD emphasizes multiple specialized models over one monolithic model; model coupling arises when components share one of these. (cf. stamp coupling) +4. **Contract** (weakest) — an integration contract **encapsulates** implementation details, functional requirements, and business models, making integration explicit and stable. Patterns: Facade, Open-host service / Published language, Anti-corruption layer, DTOs. (cf. data coupling) -Corresponds to (and refines) **data coupling** in the classic module coupling model, distinguishing between internal models and explicit integration contracts. +#### Examples -#### The Implicit-Explicit Spectrum +| Scenario | Strength | Why | +| -------------------------------------------------------------- | --------------------- | --------------------------------------------------------- | +| Service A reads Service B's internal database table | Intrusive | Private implementation detail used; B's team doesn't know | +| Frontend and backend both validate the same discount rule | Functional (implicit) | Duplicated business rule; spec change must hit both | +| Order Service and Shipping Service share a `Customer` entity | Model | Shared domain model; evolution forces both to change | +| Payment Service calls Billing API via versioned REST with DTOs | Contract | All internals encapsulated behind explicit interface | -The four levels of integration strength also reflect how **implicit or explicit** the shared knowledge is: - -- **Contract coupling** = most explicit -- **Model coupling** = explicit but broader -- **Functional coupling** = can be implicit -- **Intrusive coupling** = most implicit and fragile - -#### Degrees of Integration Strength - -Within each level, finer-grained comparisons are possible using the levels of **connascence**: -- **Static connascence** levels (name, type, meaning, algorithm, position) can compare degrees of contract and model coupling. -- **Dynamic connascence** levels (execution, timing, value, identity) can compare degrees of functional coupling. +Within each level, finer-grained comparisons use **connascence** degrees — static (name, type, meaning, algorithm, position) for contract/model coupling; dynamic (execution, timing, value, identity) for functional coupling. ### 2.2 Distance @@ -126,7 +67,7 @@ Distance is not an absolute measure — it is **relative to the level of abstrac At any given level of abstraction, the **highest distance is the boundary of that level**. If a project consists of a single service with multiple modules, then the distance between those modules is the highest distance in that context. The same principles apply: if two modules share high integration strength, that coupling is unbalanced — even though, from a system-wide perspective, they live in the same service. -You do not need microservices or distributed systems to have high-distance coupling problems. A single-person project with a single deployable unit can still suffer from tight coupling between its modules, because at the module level of abstraction, cross-module integration *is* the highest distance available. +You do not need microservices or distributed systems to have high-distance coupling problems. A single-person project with a single deployable unit can still suffer from tight coupling between its modules, because at the module level of abstraction, cross-module integration _is_ the highest distance available. #### Lifecycle Coupling (The Counterforce) @@ -161,7 +102,7 @@ Predicting the future is impossible, but domain-driven design's concept of **sub - **Core subdomains** (competitive advantage, "interesting problems") -> **highest volatility**. Companies continuously optimize and improve them. - **Supporting subdomains** (no competitive advantage, no ready-made solutions, "boring problems") -> **low volatility**. Typically CRUD data entry or ETL processes. -- **Generic subdomains** (solved problems, off-the-shelf solutions) -> **low functional volatility, variable implementation volatility**. The functionality itself is mature and rarely changes — it's a solved problem. However, the *implementation* may be volatile: switching providers, adopting a different technology, or running multiple implementations in parallel are all realistic change vectors. For example, a TTS engine (AWS Polly) is generic functionality, but switching to Google TTS, ElevenLabs, or a self-hosted solution is a reasonable expectation. In such cases, strong integration contracts are essential to encapsulate provider-specific knowledge. Conversely, some generic subdomain implementations are inherently sticky — choosing Auth0 for identity and access means switching to Clerk would be a significant event regardless of contract design. When designing boundaries for generic subdomains, evaluate the probability of switching implementations or using multiple ones simultaneously, and enforce integration contracts accordingly. +- **Generic subdomains** (solved problems, off-the-shelf solutions) -> **low functional volatility, variable implementation volatility**. The functionality itself is mature and rarely changes — it's a solved problem. However, the _implementation_ may be volatile: switching providers, adopting a different technology, or running multiple implementations in parallel are all realistic change vectors. For example, a TTS engine (AWS Polly) is generic functionality, but switching to Google TTS, ElevenLabs, or a self-hosted solution is a reasonable expectation. In such cases, strong integration contracts are essential to encapsulate provider-specific knowledge. Conversely, some generic subdomain implementations are inherently sticky — choosing Auth0 for identity and access means switching to Clerk would be a significant event regardless of contract design. When designing boundaries for generic subdomains, evaluate the probability of switching implementations or using multiple ones simultaneously, and enforce integration contracts accordingly. The **Wardley Maps** commoditization axis provides another perspective on volatility. @@ -169,27 +110,16 @@ The **Wardley Maps** commoditization axis provides another perspective on volati A critical distinction: -- **Accidental volatility**: Frequent commits don't necessarily mean the business domain is volatile. Poor design — ineffective management of integration strength and distance — can *cause* a component to change frequently. -- **Accidental involatility**: A seemingly stable component may not be inherently stable. The business may *want* to change it, but the high risk and effort of modifying a poorly designed system prevents them from doing so. +- **Accidental volatility**: Frequent commits don't necessarily mean the business domain is volatile. Poor design — ineffective management of integration strength and distance — can _cause_ a component to change frequently. +- **Accidental involatility**: A seemingly stable component may not be inherently stable. The business may _want_ to change it, but the high risk and effort of modifying a poorly designed system prevents them from doing so. Therefore, volatility should be evaluated from the **business domain perspective** (essential volatility), not from commit history alone. --- -## 3. Fractal Geometry - -Software design is fractal. You design components and their interactions at different levels of abstraction — from objects to modules to services to interactions across entire systems. The balanced coupling model applies at all of these levels. - -However, the meaning of the integration strength levels shifts depending on the level of abstraction you are working at. What constitutes an integration contract, an implementation model, or a functional requirement is different at each level. An integration contract at a lower level of abstraction (e.g., a class's public interface) may be an implementation detail at a much higher level (e.g., within a service boundary). Similarly, a model shared between two objects inside the same module is model coupling at the object level, but from the system level it is entirely internal to the module — invisible and irrelevant. - -The same applies to distance. At any given level of abstraction, the highest distance is the boundary of that level. If you are designing modules within a single service, the cross-module boundary is your highest distance — even though from a system perspective those modules are co-located. If you are designing interactions between systems, the cross-system boundary is the highest distance. +## 3. Fractal Application -Therefore, when applying the model you must always establish which level of abstraction you are operating at. This determines: - -- **Integration strength**: What counts as a contract, a model, a functional dependency, or an intrusive dependency at this level. -- **Distance**: What constitutes the lowest and highest distance at this level. - -Without this framing, the same coupling relationship can appear balanced or unbalanced depending on the observer's perspective. +The model applies at every level of abstraction — from objects to services to systems. The meaning of strength levels and distance shifts at each level: an integration contract at class level (e.g., a public interface) may be an implementation detail at service level. A model shared between objects inside one module is invisible from the system level. Always establish which level of abstraction you are analyzing — this determines what counts as contract/model/functional/intrusive and what constitutes low/high distance. Without this framing, the same coupling relationship can appear balanced or unbalanced depending on perspective. --- @@ -199,10 +129,10 @@ Without this framing, the same coupling relationship can appear balanced or unba The interplay of integration strength and distance can be understood through their extreme combinations: -| | **Low Distance** | **High Distance** | -|---|---|---| -| **Low Strength** | **Low Cohesion** (Complexity) — Unrelated components located close together. Increases cognitive load. Drifts toward big ball of mud. | **Loose Coupling** (Modularity) — Low strength minimizes cascading changes. High distance is balanced. | -| **High Strength** | **High Cohesion** (Modularity) — Components must co-evolve, but low distance makes cascading changes cheap. | **Tight Coupling** (Complexity) — Frequent cascading changes (high strength) that are expensive to implement (high distance). A step toward a distributed monolith. | +| | **Low Distance** | **High Distance** | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Low Strength** | **Low Cohesion** (Complexity) — Unrelated components located close together. Increases cognitive load. Drifts toward big ball of mud. | **Loose Coupling** (Modularity) — Low strength minimizes cascading changes. High distance is balanced. | +| **High Strength** | **High Cohesion** (Modularity) — Components must co-evolve, but low distance makes cascading changes cheap. | **Tight Coupling** (Complexity) — Frequent cascading changes (high strength) that are expensive to implement (high distance). A step toward a distributed monolith. | ### 4.2The Balance Rule @@ -230,10 +160,11 @@ BALANCE = (STRENGTH XOR DISTANCE) OR NOT VOLATILITY ``` This means coupling is balanced when either: + - Strength and distance counterbalance each other (XOR), **OR** - The component has low volatility (regardless of strength/distance relationship). -**Note**: The blog uses a simplified binary model for illustration. The book *Balancing Coupling in Software Design* contains a more elaborate mathematical model with continuous values rather than binary extremes. +**Note**: The blog uses a simplified binary model for illustration. The book _Balancing Coupling in Software Design_ contains a more elaborate mathematical model with continuous values rather than binary extremes. --- @@ -242,88 +173,22 @@ This means coupling is balanced when either: The balanced coupling model has deep connections to DDD. Many DDD patterns and practices directly relate to the dimensions of coupling: ### Strategic Design + - **Bounded contexts** define physical boundaries (medium distance, shared lifecycle) for components that share a model of the business domain (model coupling). - **Bounded context integration patterns** (shared kernel, partnership, conformist, anti-corruption layer, open-host service, separate ways) determine the level of knowledge sharing. Ad-hoc patterns allow more knowledge exchange; formal patterns reduce it. This reflects both the integration strength and the organizational aspect of distance. - Some integration patterns (anti-corruption layer, open-host service) encapsulate internal models behind integration-specific contracts (contract coupling), used when high distance exists. ### Tactical Design + - **Aggregate** and **value object** patterns co-locate (low distance) behaviors sharing transactional boundaries (high degree of functional coupling). This is balanced: high strength is offset by low distance. - Business logic implementation patterns (transaction script, active record, domain model, event-sourced domain model) are chosen based on domain complexity — which directly relates to volatility. ### Subdomains and Volatility + - **Core subdomains** = highest volatility -> require the most careful coupling management - **Supporting subdomains** = low volatility -> DDD explicitly allows pragmatic shortcuts here ("Not all of a large system will be well-designed" — Eric Evans), because low volatility neutralizes unbalanced coupling -- **Generic subdomains** = low *functional* volatility (the problem is solved), but *implementation* volatility varies. When the probability of switching providers or using multiple implementations is high (e.g., TTS engines, payment gateways, notification services), enforce strong integration contracts to encapsulate provider-specific knowledge. When switching cost is inherently high and unlikely (e.g., identity providers, core databases), pragmatic shortcuts are acceptable — but verify this assumption and brainstorm plausible change vectors before committing +- **Generic subdomains** = low _functional_ volatility (the problem is solved), but _implementation_ volatility varies. When the probability of switching providers or using multiple implementations is high (e.g., TTS engines, payment gateways, notification services), enforce strong integration contracts to encapsulate provider-specific knowledge. When switching cost is inherently high and unlikely (e.g., identity providers, core databases), pragmatic shortcuts are acceptable — but verify this assumption and brainstorm plausible change vectors before committing DDD's subdomains are the primary tool for evaluating the **volatility dimension** of components in the balanced coupling model. --- - -## 6. Summary: The Model at a Glance - -``` -+-----------------------------------------------------+ -| BALANCED COUPLING | -| | -| Three Dimensions: | -| +---------------------+ | -| | Integration Strength | -> Likelihood of cascading | -| | (Knowledge shared) | changes | -| | | | -| | Levels: | | -| | Intrusive (highest) | | -| | Functional | | -| | Model | | -| | Contract (lowest) | | -| +---------------------+ | -| +---------------------+ | -| | Distance | -> Cost of cascading | -| | (Socio-technical) | changes | -| | | | -| | Factors: | | -| | Code structure | | -| | Org structure | | -| | Runtime deps | | -| +---------------------+ | -| +---------------------+ | -| | Volatility | -> Probability of change | -| | (Rate of change) | occurring at all | -| | | | -| | Evaluated via: | | -| | DDD subdomains | | -| | Wardley Maps | | -| | (NOT commit history)| | -| +---------------------+ | -| | -| Balance Rule: | -| MODULARITY = STRENGTH XOR DISTANCE | -| BALANCE = (STRENGTH XOR DISTANCE) OR NOT VOLATILITY | -| | -| Key Insight: | -| Loose coupling and high cohesion are BOTH forms of | -| balanced coupling, not separate concepts. | -+-----------------------------------------------------+ -``` - -### The Core Principles - -1. **Coupling is not inherently bad.** It is what makes systems work. The goal is to balance it, not eliminate it. -2. **Coupling manifests in three dimensions.** Evaluating only one (e.g., number of dependencies) misses the full picture. -3. **Modularity = balanced dimensions.** When integration strength and distance counterbalance each other, the design is modular. -4. **Complexity = unbalanced dimensions.** When strength and distance are both high (tight coupling / distributed monolith) or both low (low cohesion / big ball of mud), the design is complex. -5. **Volatility adds pragmatism.** Low volatility can neutralize unbalanced coupling. Not every part of a system needs perfect design. -6. **The model is fractal.** It applies at every level of abstraction: methods, objects, packages, services, systems. -7. **The model is socio-technical.** Organizational structure affects distance as much as code structure does. -8. **Prior models are incorporated, not replaced.** Module coupling provides the foundation for integration strength levels. Connascence provides the degrees within those levels. The balanced coupling model addresses blind spots in both. - ---- - -## Communicating with the User - -Do not assume the user is familiar with domain-driven design terminology. When discussing volatility and subdomain classification, explain the concepts in plain language: - -- **Core subdomain** — the part of the system that gives the business its competitive advantage; the "interesting problems" the organization is actively investing in. Changes frequently. -- **Supporting subdomain** — something the business needs but that doesn't differentiate it, and no off-the-shelf solution exists. Typically straightforward workflows like data entry, ETL, or internal tooling. Rarely changes. -- **Generic subdomain** — a solved problem where ready-made solutions exist (authentication, payment processing, email delivery). The functionality is mature, but the specific provider or technology may change. - -Use the DDD terms, but always accompany them with a brief plain-language explanation on first use. Do not expect the user to know what "core subdomain" means without context. diff --git a/skills/balanced-coupling/details.md b/skills/balanced-coupling/details.md new file mode 100644 index 0000000..8a36ec7 --- /dev/null +++ b/skills/balanced-coupling/details.md @@ -0,0 +1,45 @@ +# Balanced Coupling — Extended Reference + +Supplementary detail for the Balanced Coupling model. Loaded on demand when deeper analysis requires connascence-level granularity or DDD pattern mapping beyond what SKILL.md provides. + +--- + +## The Implicit-Explicit Spectrum + +The four levels of integration strength also reflect how **implicit or explicit** the shared knowledge is: + +- **Contract coupling** = most explicit: the interface IS the integration point; changes are visible and versioned +- **Model coupling** = explicit but broader: shared model is known, but the blast radius of model changes spans all consumers +- **Functional coupling** = can be invisible: duplicated business logic in separate components creates a hidden coupling that only surfaces when a spec changes and one side isn't updated +- **Intrusive coupling** = most implicit and fragile: the dependent component uses private internals; the owning team may not know the dependency exists + +--- + +## Connascence Degrees + +Within each integration strength level, connascence provides finer-grained comparison. Stronger connascence = more knowledge shared = higher probability of cascading changes within that level. + +**Static connascence** (detectable at compile/parse time, weakest → strongest): + +- Name → Type → Meaning → Algorithm → Position +- Useful for comparing degrees of contract and model coupling + +**Dynamic connascence** (detectable only at runtime, weakest → strongest): + +- Execution → Timing → Value → Identity +- Useful for comparing degrees of functional coupling + +--- + +## DDD Tactical Design Connections + +- **Aggregate** and **value object** patterns co-locate (low distance) behaviors sharing transactional boundaries (high degree of functional coupling). This is balanced: high strength is offset by low distance. +- Business logic implementation patterns (transaction script, active record, domain model, event-sourced domain model) are chosen based on domain complexity — which directly relates to volatility. Event-sourced domain model is the most complex pattern, appropriate only for core subdomains with highest volatility. + +## DDD Strategic Integration Patterns + +**Bounded context integration patterns** map directly to integration strength and organizational distance: + +- **Ad-hoc patterns** (shared kernel, partnership, conformist) allow more knowledge exchange → higher integration strength. Appropriate when organizational distance is low (same team, close collaboration). +- **Formal patterns** (anti-corruption layer, open-host service/published language, separate ways) reduce knowledge sharing → lower integration strength. Appropriate when organizational distance is high (different teams, independent lifecycles). +- **ACL and OHS** specifically encapsulate internal models behind integration contracts (contract coupling) — the primary mechanism for reducing strength when high distance exists. diff --git a/skills/design/SKILL.md b/skills/design/SKILL.md index a9b1a9f..0b54022 100644 --- a/skills/design/SKILL.md +++ b/skills/design/SKILL.md @@ -1,10 +1,13 @@ --- name: design description: > - Designs modular high-level architectures from functional requirements and produces design - documents for each module. Use when designing a new system, creating architecture documentation, - or producing module-level design specs with integration contracts and test specifications. + Designs modular high-level architectures from a functional requirements document and produces + design documents for each module. Use when designing a new system from requirements, creating + architecture documentation, or producing module-level design specs with integration contracts + and test specifications. Requires a functional requirements document as input — use the + review skill to analyze existing codebases instead. argument-hint: "[path/to/functional-requirements.md]" +context: fork skills: - balanced-coupling allowed-tools: Read, Write, Edit, AskUserQuestion, TaskCreate, TaskUpdate @@ -56,19 +59,9 @@ Read the functional requirements file. Then: | {area 2} | Supporting | {why} | | {area 3} | Generic | {why} | -Then ask the user to validate using `AskUserQuestion`: +Then validate using `AskUserQuestion` — Header: "Subdomains", Options: "Approved — All correct", "Some are wrong — I'll tell you which to change", "Missing subdomains — There are areas not listed". If the user says some are wrong, ask which ones and what the correct classification should be. -| Header | Question | Options | -| ---------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | -| Subdomains | Do these subdomain classifications look right? | 1. **Approved** - All correct 2. **Some are wrong** - I'll tell you which to change 3. **Missing subdomains** - There are areas not listed | - -If the user says some are wrong, ask which ones and what the correct classification should be. - -Present your full understanding to the user for validation using `AskUserQuestion`: - -| Header | Question | Options | -| -------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Approval | Does this understanding of the requirements look correct? | 1. **Approved** - Proceed to architecture design 2. **Needs changes** - I'll explain what's wrong 3. **Missing context** - There's more I should tell you | +Present your full understanding to the user for validation using `AskUserQuestion` — Header: "Approval", Options: "Approved — Proceed to architecture design", "Needs changes — I'll explain what's wrong", "Missing context — There's more I should tell you". Do not proceed until approved. @@ -95,9 +88,7 @@ Present the coupling assessment table to the user: Work through each step with the user using `AskUserQuestion`. Each step requires user approval. Do not proceed to writing design documents until the modular architecture is fully validated by the user. -| Header | Question | Options | -| -------- | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Approval | Does this modular architecture look correct? | 1. **Approved** - Proceed to design documents 2. **Needs changes** - I'll explain what to adjust 3. **Rethink** - Let's reconsider the module boundaries | +Validate using `AskUserQuestion` — Header: "Approval", Options: "Approved — Proceed to design documents", "Needs changes — I'll explain what to adjust", "Rethink — Let's reconsider the module boundaries". ### Step 3: Write Module Design Documents @@ -134,11 +125,7 @@ Reasonable future changes that would require ONLY this module to change — the Write all module design documents without asking for individual approval. The modular architecture was already approved in Step 2 — the documents are a direct translation of that approved design. -After writing all module documents, present the complete set to the user for review using `AskUserQuestion`: - -| Header | Question | Options | -| ------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Modules | All module design documents have been written. How do they look? | 1. **Approved** - Proceed to test specifications 2. **Needs changes** - I'll explain which modules need work 3. **Revisit architecture** - The documents reveal a boundary problem | +After writing all module documents, present the complete set using `AskUserQuestion` — Header: "Modules", Options: "Approved — Proceed to test specifications", "Needs changes — I'll explain which modules need work", "Revisit architecture — The documents reveal a boundary problem". Iterate until approved. @@ -212,6 +199,8 @@ Anything the design intentionally leaves open, along with the conditions under w Write the architecture document without asking for approval. It synthesizes the already-approved module designs. +After writing, verify all expected output files exist and are non-empty: the architecture document and all module design and test specification files. + ### Step 6: Modularity Review After all documents are written, review your own design for modularity imbalances. For each integration between modules: @@ -245,3 +234,4 @@ Minor issues should be noted in the architecture document's "Unresolved Risks" s - **Distinguish essential from accidental volatility.** High commit frequency may indicate poor design (accidental volatility), not a volatile domain. - **Consider the organizational dimension of distance.** Same code structure + different teams = higher effective distance. - **Ground every recommendation in the model.** Reference the specific dimension and principle that justifies each design decision. +- **Explain DDD terms on first use.** Do not assume the user knows what "core subdomain" or "bounded context" means. Use the DDD terms but accompany each with a brief plain-language explanation: core subdomain = competitive advantage area that changes frequently; supporting = needed but not differentiating, rarely changes; generic = solved problem with off-the-shelf solutions, but provider may change. diff --git a/skills/document/SKILL.md b/skills/document/SKILL.md index d7f5394..4b05515 100644 --- a/skills/document/SKILL.md +++ b/skills/document/SKILL.md @@ -1,15 +1,16 @@ --- name: document description: > - Produces modularity review documents in both Markdown and HTML formats. - Use when writing the final review output from a modularity analysis. + Produces modularity review documents. Always generates Markdown; generates HTML + only when explicitly requested. Use when writing the final review output from + a modularity analysis. user-invocable: false allowed-tools: Read, Write --- # Document -You produce the final modularity review document in two formats: Markdown (`.md`) and HTML (`.html`). Both files contain identical content. +You produce the final modularity review document. **Markdown is always generated.** HTML is generated only when the user explicitly requests it (e.g., via argument, instruction, or when asked for a shareable report). Both formats contain identical content when HTML is produced. ## Document Structure @@ -128,12 +129,12 @@ _This analysis was performed using the [Balanced Coupling](https://coupling.dev) ## Output -Write both files to `docs/modularity-review/!`date +%Y-%m-%d`/`: +Write to `docs/modularity-review/!`date +%Y-%m-%d`/`: -1. `docs/modularity-review/!`date +%Y-%m-%d`/modularity-review.md` — the Markdown version -2. `docs/modularity-review/!`date +%Y-%m-%d`/modularity-review.html` — the HTML version +1. `docs/modularity-review/!`date +%Y-%m-%d`/modularity-review.md` — **always generated** +2. `docs/modularity-review/!`date +%Y-%m-%d`/modularity-review.html` — **only when HTML is requested** -### HTML generation +### HTML generation (when requested) **You MUST read the template file before generating HTML.** The template is at `${CLAUDE_SKILL_DIR}/assets/template.html`. Read this file, then replace: diff --git a/skills/review/SKILL.md b/skills/review/SKILL.md index ad5a4e4..0a16fe5 100644 --- a/skills/review/SKILL.md +++ b/skills/review/SKILL.md @@ -1,10 +1,12 @@ --- name: review description: > - Analyzes a codebase's modularity imbalances using the Balanced Coupling model and produces - a review of design issues. Use when reviewing existing code for coupling problems, assessing - architecture quality, identifying distributed monolith risks, or finding areas where changes - are unexpectedly expensive. + Analyzes an existing codebase for modularity imbalances using the Balanced Coupling model + and produces a review of design issues. Use when reviewing existing code for coupling + problems, assessing architecture quality, identifying distributed monolith risks, or + finding areas where changes are unexpectedly expensive. Requires an existing codebase + as input — use the design skill to create architectures from requirements instead. +context: fork skills: - balanced-coupling - document @@ -75,7 +77,7 @@ Flag every integration where coupling is **unbalanced AND volatile**: ### Step 4: Write the Review -Using the document skill (preloaded), produce the modularity review in both Markdown and HTML formats. The document skill defines the structure and output format. +Using the document skill (preloaded), produce the modularity review. The document skill defines the structure and output format. Markdown is always generated; HTML is produced only if the user requests it. ## Important Constraints @@ -86,3 +88,4 @@ Using the document skill (preloaded), produce the modularity review in both Mark - **Ground every issue in the model.** Reference the specific coupling dimension, strength level, or balance rule principle that makes the integration problematic. - **Never recommend "just decouple everything."** Decomposition increases distance. Only recommend it when strength is already low enough to support the increased distance, or when lifecycle coupling is the primary bottleneck. - **Consider the organizational dimension.** Same code structure + different teams = higher effective distance. Ask about team ownership when it affects the analysis. +- **Explain DDD terms on first use.** Do not assume the user knows what "core subdomain" or "bounded context" means. Use the DDD terms but accompany each with a brief plain-language explanation: core subdomain = competitive advantage area that changes frequently; supporting = needed but not differentiating, rarely changes; generic = solved problem with off-the-shelf solutions, but provider may change.