ffca-cross-feature
Installation
SKILL.md
FFCA Cross-Feature
Workflow for the moment one feature needs another. The patterns live in ${CLAUDE_PLUGIN_ROOT}/references/ffca/: read the cited sections before coupling two features.
The two allowed couplings
Features couple in exactly two places, and in one direction each:
- Domain to domain. A consuming feature's domain may depend on a provider feature's domain, for example
cart_domainonproduct_domain. Readreferences/ffca/domain.md, section Composing features. - Presentation to presentation. A presentation package may use a public widget from another feature's presentation package, under the three conditions below. Read
references/ffca/presentation.md, section Sharing a widget across features.
Data layers never reach across features for data, and no layer ever depends on another feature's data package.
Sharing data
- Loose coupling by id: the Summary pattern. When a feature stores references to another feature's models, store ids only. The read model holds full objects (
CartwithList<Product>); the stored summary holds ids (CartSummarywithList<String>). The repository reads and writes summaries and only takes the full object when one is being created. Readreferences/ffca/domain.md, section Storing data, and adapt the shapes inreferences/code_templates/domain_templates.md. - Combine repositories with a Query. To assemble a populated model from two features, add a
Queryin the consuming feature's domain that takes both repository interfaces. Readreferences/ffca/domain.md, section Reading the populated object. Keep the Query in the consumer, never in the provider: the cart feature never learns how products are stored, and the product feature never learns that carts exist. - Normalize inside the repository, not a Query. When an API returns nested objects belonging to another feature, split them inside the data repository, which may depend on another feature's domain interface. Read
references/ffca/faq.md, section Dealing with nested objects. The DTO-to-domain mapping is duplicated in the consuming data package on purpose: DRY is traded for bounded contexts here deliberately.