name: decompose-feature
description: Decompose a feature or app idea into independent Clef concepts and synchronizations following Daniel Jackson's methodology. Produces scaffolded .concept files and .sync files ready for refinement via the create-concept skill.
allowed-tools: Read, Grep, Glob, Edit, Write, Bash
argument-hint: ""
Decompose Feature into Clef Concepts
Break down $ARGUMENTS into independent concepts with synchronizations following Daniel Jackson's concept design methodology.
The Decomposition Principle
Jackson's key insight: software should be structured as a collection of independent concepts, each with exactly one purpose, composed through synchronizations. The decomposition process is:
- Identify the purposes the system must serve (not the features — the why)
- Map each purpose to one concept (singularity principle)
- Ensure independence — no concept references another's types or actions
- Design synchronizations to coordinate concepts into user-visible flows
Step 1: List the Purposes
Read the feature description and extract every distinct purpose the system must fulfill. A purpose answers "what value does this deliver?" — not "what does it do?"
Read references/decomposition-method.md for Jackson's full decomposition methodology.
For each purpose, write a single sentence starting with a verb:
- "Track follower relationships between users"
- "Securely store and validate user credentials"
- "Manage articles with titles, bodies, and metadata"
Key test: If two purposes can exist independently (one could be removed without breaking the other), they are separate concepts. If removing one makes the other meaningless, they might be the same concept.
Consult references/concept-catalog.md — many purposes map to well-known reusable concepts.
Step 2: Name the Concepts
For each purpose, assign a name:
- Nouns that users already understand: Password, Article, Comment, Tag
- PascalCase:
Follow,Favorite,Profile - One word when possible: prefer
TagoverArticleLabel
Step 3: Draw the Concept Map
List each concept with:
- Its purpose (one sentence)
- Its type parameter and what it represents
- Whether it's an entity concept (owns a collection) or a relation concept (decorates external entities)
- Which other concepts it will interact with via syncs
Example format:
CONCEPT MAP for "Social Blogging Platform"
User [U] — Associate identifying information with users (entity)
Password [U] — Securely store and validate credentials (relation on U)
JWT [U] — Generate and verify session tokens (relation on U)
Profile [U] — Store user profile information (relation on U)
Article [A] — Manage articles with content and metadata (entity)
Comment [C] — Manage comments on articles (entity)
Tag [T] — Manage tags and article associations (entity)
Follow [U] — Track follower relationships (relation on U)
Favorite [U] — Track article favorites per user (relation on U)
SYNCS NEEDED:
Registration: Web -> Password/validate -> User/register -> Password/set -> JWT/generate
Login: Web -> Password/check -> JWT/generate
Articles: Web -> JWT/verify -> Article/create|update|delete
Comments: Web -> JWT/verify -> Comment/create|delete
Social: Web -> JWT/verify -> Follow/follow|unfollow, Favorite/favorite|unfavorite
Cascade: Article/delete -> Comment/delete (all comments on that article)
Step 4: Validate Independence
For each concept, check:
- No type coupling: Does it reference another concept's name in its state or actions? If yes, replace with a type parameter or opaque
String. - No action coupling: Does an action need to call another concept? If yes, that's a sync, not an action.
- No getters: Are any actions there only to read state for some screen/caller (
getActiveX,listYByZ)? Drop them — reads are a QueryProgram/view (/create-view-query) or a syncwhererelation-read, never a getter action the concept must anticipate. A concept's actions are its writes; its reads are open-ended and caller-driven. (docs/prd/read-layer-unification-prd.md; theaudit:no-new-gettersratchet enforces it.) - Single purpose: Can you state the purpose in one sentence without "and"?
- Reusable: Could this concept work in a completely different app?
Apply Jackson's design moves if needed:
- Split: Concept has two purposes → break into two concepts
- Merge: Two concepts always used together and separating them adds no value → combine
- Lift: A mapping inside a concept really belongs in the sync layer → move it out
Step 5: Identify Synchronization Flows
Read references/sync-design.md for the sync language and patterns.
For each user-visible action (API endpoint, button click, form submission):
- What triggers it? (e.g., Web/request with method "login")
- What concepts are involved? List them in order
- What data flows between them? (variables bound in when, used in then)
- What are the success and failure paths?
Group syncs by flow:
- Authentication syncs: JWT/verify gates most actions
- CRUD syncs: Auth -> Action -> Response (three syncs per operation)
- Cascade syncs: Deleting parent → deleting children
- Side-effect syncs: Action on one concept triggers action on another
See examples/sync-patterns.md for reusable sync templates.
Step 6: Scaffold the Concept Files
For each concept, create a skeleton .concept file at specs/app/<name>.concept:
npx tsx -e "
import { writeFileSync, mkdirSync } from 'fs';
const concepts = [
// Fill in from your concept map:
// { name: 'ConceptName', param: 'T', file: 'concept-name', purpose: '...',
// state: ['field: T -> Type'], actions: ['actionName'], entity: true/false }
];
mkdirSync('specs/app', { recursive: true });
for (const c of concepts) {
const stateLines = c.state.map(s => ' ' + s).join('\n');
const actionLines = c.actions.map(a =>
' action ' + a + '() {\n -> ok() {\n TODO\n }\n }'
).join('\n\n');
const content = \`concept \${c.name} [\${c.param}] {
purpose {
\${c.purpose}
}
state {
\${stateLines}
}
actions {
\${actionLines}
}
}
\`;
writeFileSync('specs/app/' + c.file + '.concept', content);
console.log('Created specs/app/' + c.file + '.concept');
}
"
Then use the create-concept skill to flesh out each one with proper actions, variants, and invariants.
Step 7: Scaffold the Sync Files
For each flow, create a .sync file at syncs/app/<flow>.sync:
npx tsx -e "
import { writeFileSync, mkdirSync } from 'fs';
const flows = [
// Fill in from your sync design:
// { file: 'flow-name', comment: 'Description', syncs: [
// { name: 'SyncName', annotation: 'eager',
// when: 'Concept/action: [ field: ?var ] => [ field: ?var ]',
// then: 'Concept/action: [ field: ?var ]' }
// ]}
];
mkdirSync('syncs/app', { recursive: true });
for (const flow of flows) {
const syncBlocks = flow.syncs.map(s =>
'sync ' + s.name + ' [' + s.annotation + ']\nwhen {\n ' + s.when + '\n}\nthen {\n ' + s.then + '\n}'
).join('\n\n');
const content = '// ' + flow.comment + '\n\n' + syncBlocks + '\n';
writeFileSync('syncs/app/' + flow.file + '.sync', content);
console.log('Created syncs/app/' + flow.file + '.sync');
}
"
Step 8: Validate the Full Pipeline
Parse all concepts to verify syntax:
npx tsx cli/src/index.ts check
Compile syncs to verify they reference valid concepts and actions:
npx tsx cli/src/index.ts compile-syncs
Step 9: Hand Off to create-concept
For each scaffolded concept, use the create-concept skill to:
- Flesh out action parameters and return variants
- Write prose descriptions
- Add invariants (operational principles)
- Validate through the full pipeline
Step 10: Identify Derived Compositions
After decomposing into primitive concepts and syncs, look for clusters of concepts + syncs that form a recognizable user-facing abstraction:
- Do users think of this cluster as a single thing? ("the registration system", "the trash", "search")
- Does the cluster have an emergent purpose beyond "these concepts exist together"?
- Does it have a natural operational principle (an archetypal scenario)?
If yes, create a derived concept using /create-derived-concept. If the clusters form a hierarchy, consider the hierarchical derivation architecture using /derive-app.
Example: after decomposing a social blogging platform, you might identify:
Registration: User + Password + JWT + Profile → derived concept
Publishing: Article + Tag → derived concept
Social: Follow + Favorite → derived concept
Comments: Comment (single concept) → no derivation needed
Decomposition Checklist
Before finalizing, verify:
- Every user-visible feature maps to at least one sync flow
- Every concept has exactly one purpose
- No concept references another concept's types
- Auth-gated operations use JWT/verify syncs
- Entity deletion cascades are handled by syncs
- Success and failure response syncs exist for every flow
- Sync files are grouped by domain (login, registration, articles, etc.)
- Every concept purpose explains what/why/how concisely (1-3 sentences)
- Every action variant has a clear description (not just echoing the name)
- Every sync rule has a one-line comment explaining what it does
- Every sync file has a header comment explaining the flow it covers
- Concept clusters that form user-facing abstractions are identified as derived concept candidates
Quick Reference: Concept Categories
| Category | Examples | State Pattern | Typical Actions |
|---|---|---|---|
| Identity | User | Entity (set + relations) | register |
| Auth | Password | Relation (U -> Bytes) | set, check, validate |
| Session | JWT | Relation (U -> String) | generate, verify |
| Content | Article, Comment | Entity (set + relations) | create, get, update, delete |
| Profile | Profile | Relation (U -> String) | update, get |
| Social | Follow, Favorite | Relation (U -> set String) | add, remove, query |
| Taxonomy | Tag | Entity (set + set relation) | add, remove, list |
| Diagnostic | Echo | Entity (set + relation) | send |
Full Decomposition Example
See examples/social-blogging-platform.md for a complete worked example showing how the existing Clef app was decomposed from a "social blogging platform" feature description into 9 independent concepts with 7 sync files containing 30+ sync rules.
Related Skills
| Skill | When to Use |
|---|---|
/create-concept |
Design each concept identified during decomposition |
/create-sync |
Write the sync rules that connect decomposed concepts |
/create-suite |
Bundle the decomposed concepts into a reusable suite |
/create-derived-concept |
Name a composition of concepts + syncs that forms a user-facing abstraction |
/derive-app |
Build the full app as a hierarchy of derived concepts |
/create-implementation |
Write implementations for each decomposed concept |