architecture
Skill2 starsChanged 9 days agoMITView on GitHub
Design, audit, or refactor software into predictable, low-entropy domain modules with one manifest-like entry per domain, explicit application composition, readable API definitions, one canonical owner and name for every shared concept, pure cross-runtime contracts, complete request context, boundary wrappers that validate and narrow, meaningful persistence vocabulary, declarative boundary policy, and correctness-first defaults. Use when asked to simplify architecture, establish domain boundaries, modularize a backend or monorepo, split a large feature, create a common package, consolidate duplicated types, constants, enums, permissions, roles, or mappings across app, server, worker, and schema layers, reduce registration or dependency plumbing, make a codebase easier to navigate, compare architecture quality, or review whether a proposed abstraction improves human comprehension.
139 other projects use a version of this.
Adopted by
Most recently taken up by
- rajdeepbhattacharyya25-pixel/agents-for-antigravity-their own version, first seen Nov 15, 2026
- scolladon/crafttheir own version, first seen Nov 15, 2026
- thistleknot/skillstheir own version, first seen Nov 8, 2026
- lklimek/claudiustheir own version, first seen Nov 8, 2026
- nisarth/claude-skills-storetheir own version, first seen Nov 8, 2026
- DnsQueen/orcinus-skillstheir own version, first seen Nov 8, 2026
Used with
Projects with it also use intelligent-routing, bash-linux and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
SKB3002Skillintelligent-routing
Automatic agent selection and intelligent task routing. Analyzes user requests and automatically selects the best specialist agent(s) without requiring explicit user mentions.
Also in 6 projects that use this
xenitV1Skillbash-linux
Bash/Linux terminal patterns. Critical commands, piping, error handling, scripting. Use when working on macOS or Linux systems.
Also in 8 projects that use this
xenitV1Skillred-team-tactics
Red team tactics principles based on MITRE ATT&CK. Attack phases, detection evasion, reporting.
Also in 8 projects that use this
SKB3002Skillnextjs-react-expert
React and Next.js performance optimization from Vercel Engineering. Use when building React components, optimizing performance, eliminating waterfalls, reducing bundle size, reviewing code for performance issues, or implementing server/client-side optimizations.
Also in 3 projects that use this
- +8 more from xenitV1
Other versions139 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 139
- anthropics/knowledge-work-plugins★ 36ksame name
- iOfficeAI/AionUi★ 34ksame name
- vudovn/ag-kit★ 8.2ksame name
- vudovn/antigravity-kit★ 8.2ksame name
- nativewind/nativewind★ 8.1ksame name
- PaulWoitaschek/Voice★ 3.3ksame name
- wellwelwel/poku★ 1.2ksame name
- Alwurts/simple-ai★ 755same name
- patrickjaja/claude-desktop-extra★ 734same name
- ktnyt/cclsp★ 673same name
129 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository12 other files it gives its agents.
- analyticsSkill
- audit-codeSkill
- audit-productSkill
- auditSkill
- cross-examineSkill
- fix-typoSkill
- fun-checkSkill
- roastSkill
- tighten-copySkill
- untangleSkill
- ux-reviewSkill
- visualizeSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
64 rules. 0 are common, 60 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 121 edited versions we read keep these.
60
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 17
Do not chase the smallest total line count.
- Distinctive: line 24
Never rebuild routes, events, commands, fields, or jobs in a second hand-maintained registry just so telemetry, authorization, deprecation, …
- Distinctive: line 47
Read principles.md for architecture analysis, tradeoff explanations, and the human factors behind the method.
- Distinctive: line 49
Read patterns.md when designing or implementing module entries, GraphQL composition, persistence scopes, authorization, context, common …
- Distinctive: line 52
Read migration-playbook.md before restructuring an existing codebase, moving runtime roots, or changing domain boundaries.
- Distinctive: line 55
Do not load every reference automatically when one is sufficient.
- Distinctive: line 61
Read the nearest AGENTS.md, CLAUDE.md, package manifests, path aliases, build scripts, test configuration, and composition roots before …
- Distinctive: line 75
Prefer current code, tests, and build configuration over stale architecture documents.
- Distinctive: line 135
Write the smallest repeated grammar that answers the navigation questions consistently.
- Distinctive: line 136
Start from the best existing exemplar when one exists.
- Distinctive: line 138
Prefer this conceptual shape:
- Distinctive: line 164
Prefer an explicit typed list over filesystem discovery or decorator magic.
- Distinctive: line 167
Do not add speculative lifecycle machinery.
- Distinctive: line 180
test setup and rollback
- Very specific: line 184
Do not create a LEGACY_FOLLOWS_ROUTES matcher table in telemetry code: that duplicates the router, is limited to one domain, and will drift.
- Distinctive: line 203
Put the canonical type, values, pure mappings, validation, and event contract in the owning domain's pure shared entry when multiple …
- Distinctive: line 205
Keep database access, caches, side effects, framework integration, and runtime policy in the owning domain of the relevant runtime.
- Very specific: line 216
Keep domain behavior readable at the call site.
- Distinctive: line 220
Prefer direct domain flow over mandatory controller, use-case, service, repository, and adapter layers for every operation.
- Distinctive: line 249
Use shared authorization and request context.
- Distinctive: line 253
Use the pilot to refine the grammar.
- Distinctive: line 257
Keep a large capability as one conceptual module when it shares lifecycle, persistence, API ownership, and operational responsibility.
- Distinctive: line 268
Create a separate domain only when the capability has a sufficiently independent lifecycle, persistence model, public API, or operational …
- Distinctive: line 274
After implementation or proposal, answer these questions:
- Distinctive: line 283
Do UI, API, database schema, and worker code consume the same name rather than define layer-specific aliases?
- Distinctive: line 287
Do guarded implementations receive the prepared, non-null principal directly, without an inline setup preamble or hidden reload?
- Distinctive: line 291
Do normal integration tests clean themselves up?
- Distinctive: line 295
If several answers are no, the architecture is not yet simpler even if the files moved.
- Distinctive: line 301
One runtime and one domain: Keep vocabulary and implementation in that domain.
- Distinctive: line 303
Several runtimes: Put the pure type, values, mappings, validation, calculations, or event payload in the common entry for the owning domain.
- Distinctive: line 305
Runtime implementation: Keep persistence, I/O, caches, side effects, and framework adapters in the owning domain of that runtime.
- Distinctive: line 313
Use one name when the meaning is the same.
- Distinctive: line 322
Static API requirement: Use the framework's declarative field or route authorization.
- Distinctive: line 323
Dynamic API requirement: Use one generic guard with the computed requirement.
- Distinctive: line 324
Soft visibility decision: Use a boolean permission predicate.
- Distinctive: line 325
Entity rule: Keep ownership, membership, and visibility policy in the entity's domain.
- Very specific: line 331
Use UNAUTHENTICATED for a missing or invalid identity and FORBIDDEN for an authenticated identity lacking authority.
- Distinctive: line 337
Put stable request-wide facts in the typed protocol context: the authenticated principal, its request-relevant roles and capabilities, …
- Distinctive: line 347
Keep entity-specific loading and policy in the owning domain.
- Distinctive: line 349
Leave intentionally public operations unwrapped.
- Distinctive: line 352
Avoid this repeated shape:
- Distinctive: line 361
Prefer a boundary guarantee and a direct domain body:
- Distinctive: line 379
Do not use a common package as a neutral dumping ground.
- Distinctive: line 390
Keep direct code when similarity is incidental, tiny, or likely to diverge.
- Distinctive: line 394
Keep each route path, event shape, job schedule, API field, and command declaration in one executable source of truth.
- Distinctive: line 396
Add generic middleware, an enhancer, or typed metadata directly beside that declaration when telemetry, authorization, deprecation, …
- Distinctive: line 401
If another runtime needs the complete catalog, derive or generate it from the owning declarations.
- Distinctive: line 421
Do not copy framework choices merely because the reference architecture used them.
- Distinctive: line 422
Do not replace the ORM solely to obtain named domain policies.
- Very specific: line 423
Do not turn index.ts into a maintenance-heavy export inventory.
- Distinctive: line 424
Do not introduce auto-discovery when one explicit registry is clearer.
- Distinctive: line 425
Do not force browser, API, and worker code through one physical module entry.
- Distinctive: line 426
Do not centralize domain-specific behavior into generic infrastructure.
- Distinctive: line 427
Do not create domain-specific shadow registries in generic infrastructure.
- Distinctive: line 429
Do not mirror shared domain types, constants, validation, or mappings by runtime or layer.
- Distinctive: line 430
Do not let a database table, GraphQL schema, or UI component own vocabulary that belongs to the domain.
- Distinctive: line 432
Do not keep authorization types in an admin or feature domain when they describe application-wide authority.
- Distinctive: line 434
Do not stack an imperative permission guard under an equivalent declarative field scope.
- Distinctive: line 435
Do not make a guard, resolver, route handler, or domain service reload a stable principal or other request fact that context construction …
- Distinctive: line 437
Do not add no-op wrappers to public operations merely for visual uniformity.
- Distinctive: line 438
Do not use documentation to compensate for inconsistent executable structure.
- Distinctive: line 439
Do not claim simplicity from file movement alone.
- Distinctive: line 473
Use this as the decisive test:
- Distinctive: line 478
If yes, the architecture is working.
“Common” is measured: kept by at least 6 in 10 of the 121 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CIL Architecture
Core principle
Spend complexity once in stable foundations so ordinary domain code remains direct, predictable, and boring.
Optimize for recognition over recall. After learning one domain, a developer should be able to predict where the API, persistence, authorization, jobs, routes, tests, and registration of another domain live.
Do not chase the smallest total line count. Reduce the number of architectural shapes, places to search, decisions to repeat, and exceptions to remember.
Give every shared concept one canonical owner, one name, and one public path. Other runtimes and domains consume that definition; they do not mirror or rename it.
Attach cross-cutting behavior to the declaration that already owns the fact it observes. Never rebuild routes, events, commands, fields, or jobs in a second hand-maintained registry just so telemetry, authorization, deprecation, or another platform concern can recognize them.
Build stable request-wide facts once at the protocol boundary. Let small boundary wrappers validate preconditions and narrow types before domain code runs. A domain body should consume the prepared context and express the happy path, not rebuild identity, permissions, locale, tenant, transaction, or other request prerequisites field by field.
Select the operating mode
- Design: Define a coherent architecture for a new system or major capability.
- Audit: Explain why an existing codebase is difficult to follow and identify its sources of cognitive entropy.
- Refactor: Move an existing system toward a stable domain grammar without changing behavior or public contracts.
- Review: Judge a proposed structure, abstraction, package, or module contract before implementation.
State the selected mode and scope. For implementation work, preserve the user's requested pace and stopping points.
Load the relevant references
- Read principles.md for architecture analysis, tradeoff explanations, and the human factors behind the method.
- Read patterns.md when designing or implementing module entries, GraphQL composition, persistence scopes, authorization, context, common packages, or test isolation.
- Read migration-playbook.md before restructuring an existing codebase, moving runtime roots, or changing domain boundaries.
Do not load every reference automatically when one is sufficient.
Workflow
1. Read executable truth first
Read the nearest AGENTS.md, CLAUDE.md, package manifests, path aliases, build scripts,
test configuration, and composition roots before proposing a structure.
Identify:
- runtimes and deployment units
- current domain or feature directories
- application entry points and registration files
- public API surfaces and shipped consumers
- database and transaction boundaries
- background jobs, queues, and event payloads
- shared packages and their dependency direction
- existing architecture exemplars that are easier to follow than their neighbors
Prefer current code, tests, and build configuration over stale architecture documents.
2. Map the current grammar
For representative domains, record:
| Question | Current answer |
| Where does the domain live? | path or several paths |
| What is its public entry? | file, registry, or none |
| Where is its API visible? | SDL, builders, routes, or scattered calls |
| Where is business persistence logic? | models, services, handlers, or inline queries |
| How is authorization expressed? | permission, role, specialized guard, or inline check |
| How are jobs and events registered? | domain entry, worker root, or several registries |
| How are tests isolated? | rollback, cleanup, reset, or shared state |
| How many roots must change to add one capability? | concrete count and files |
Compare at least one small domain and one large domain. Do not infer the architecture from the tidiest example alone.
3. Diagnose cognitive entropy
Report concrete sources of friction, not aesthetic preferences. Look for:
- one concept with several homes
- one extension requiring edits in several unrelated roots
- a cross-cutting concern maintaining its own domain-specific copy of routes, events, jobs, permissions, or other declarations it could instrument at their source
- inconsistent folder and resolver shapes between sibling domains
- public entry points that are catch-all barrels instead of module manifests
- infrastructure names leaking into business code
- domain vocabulary mirrored or renamed across app, server, worker, API, and schema
- a consuming layer owning a shared concept merely because it was the first consumer
- database or transport schemas accidentally becoming the source of domain vocabulary
- consumers reaching through the owning domain to inspect storage or runtime representation
- specialized authorization helpers encoding the same permission check
- static field authorization implemented through manual resolver checks when the API framework already supports declarative scopes
- consumers loading raw permission sets and calling
.has()instead of using the authorization boundary - resolvers repeating setup preambles such as
const user = await guard(context)before reaching domain behavior - guards or helpers that secretly hydrate request identity, permissions, tenant, locale, or transaction state after domain execution has already begun
- wrappers that validate a nullable context but fail to expose the validated, narrowed type to the wrapped code
- stable request facts reloaded independently by sibling resolvers
- repeated query policy expressed as slightly different SQL
- dependencies passed through layers that could read one request context
- ordinary tests managing cleanup manually
- shared packages importing runtime-specific code
- large domains split by technical layer without a stable conceptual module
- architecture that can only be reconstructed through documentation archaeology
Distinguish essential complexity from accidental complexity. Multiple runtimes, durable queues, native-client compatibility, geospatial SQL, concurrency, and external contracts may be load-bearing. Organize them clearly instead of pretending they do not exist.
4. Define the target grammar
Write the smallest repeated grammar that answers the navigation questions consistently. Start from the best existing exemplar when one exists.
Prefer this conceptual shape:
<runtime>/domains/<domain>/
index.ts # manifest and intentional public API
graphql/ # SDL and resolver maps, split by capability when needed
models/ # domain entities and meaningful persistence vocabulary
services/ # orchestration with real branching or side effects
policies/ # authorization and domain rules
routes/ # compatibility or protocol-specific routes
jobs/ # domain-owned background registrations and handlers
__tests__/Adapt names to the repository's established language. Do not reorganize files merely to match this exact spelling.
Define a minimal module contract from capabilities already needed. A public domain entry should answer what the domain contributes to the runtime. It should not re-export every internal file.
5. Keep composition explicit
Register each domain once in an obvious composition root. Let generic composers gather its GraphQL, routes, jobs, loaders, or lifecycle hooks.
Prefer an explicit typed list over filesystem discovery or decorator magic. Ordering and dependencies should be visible when they matter.
Do not add speculative lifecycle machinery. Add a capability to the module contract only when at least one real domain needs it.
6. Abstract repeated mechanics, preserve domain meaning
Centralize stable mechanics such as:
- schema composition
- request transaction selection
- data-loader construction
- permission evaluation and guards
- validation execution
- timestamps and serialization
- test setup and rollback
Attach those mechanics at the owning declaration. For example, mark a legacy route with a
generic legacyRoute('follows.counts') middleware beside its one Express path declaration.
Do not create a LEGACY_FOLLOWS_ROUTES matcher table in telemetry code: that duplicates the
router, is limited to one domain, and will drift. The mechanism is generic; the stable name
and lifecycle remain visible in the owning domain.
For repeated boundary preconditions, use the three-part pattern across every domain:
- Hydrate once: Build a complete, typed request context before dispatching domain code.
- Validate once: Apply a small protocol wrapper or declarative scope at the field, route, job, or command boundary.
- Narrow inside: Let the wrapped implementation receive the stronger context type and read its prepared values directly.
The wrapper must not be a hidden data loader. If it repeatedly fetches stable request-wide state, move that hydration to context construction. Do not eagerly put rare entity data or every possible service into context; completeness means complete for shared request facts, not a global service locator.
For every shared concept, separate vocabulary from runtime mechanics:
- Put the canonical type, values, pure mappings, validation, and event contract in the owning domain's pure shared entry when multiple runtimes consume them.
- Keep database access, caches, side effects, framework integration, and runtime policy in the owning domain of the relevant runtime.
- Make schemas, transports, UI, and workers consume the canonical vocabulary. Do not let each layer create a local alias or mirror.
- Expose a narrow domain operation or policy instead of making consumers inspect storage, caches, raw sets, or database rows.
Authorization is one application of this rule: common owns pure capability and role vocabulary, server auth owns grant evaluation, protocol scopes own static rejection, and entity domains own membership or visibility rules.
Keep domain behavior readable at the call site. Extract a named policy when the name conveys
meaning such as visibleTo(viewer) or openForRegistration(now). Do not wrap a one-line ORM
expression merely to hide the ORM.
Prefer direct domain flow over mandatory controller, use-case, service, repository, and adapter layers for every operation. Introduce a layer only when it owns a real boundary, policy, or orchestration concern.
7. Make correctness the default path
Design defaults so ordinary feature code does the safe thing without ceremony:
- automatic transaction rollback in integration tests
- complete request principals and stable request facts before domain dispatch
- boundary wrappers that validate and type-narrow without reloading context
- declarative permission scopes for static API fields
- generic guards for SDL boundaries and genuinely dynamic requirements
- boolean permission checks for soft visibility decisions
- request-scoped loaders for list fields
- typed module registration
- schema and resolver validation during composition
- pure shared packages with enforced dependency direction
Make exceptions explicit and rare, such as disableIsolation() for tests that genuinely
require independent committed connections.
8. Pilot before generalizing
Choose one small, coherent, representative domain. Convert it end to end:
- Give it one manifest-like entry.
- Move its registration behind generic composition.
- Make its API readable in one predictable location.
- Use shared authorization and request context.
- Preserve public behavior and compatibility.
- Validate types, tests, and runtime startup.
Use the pilot to refine the grammar. Do not begin with the largest or most coupled domain.
9. Scale large domains internally
Keep a large capability as one conceptual module when it shares lifecycle, persistence, API ownership, and operational responsibility. Split its internals by recognizable facets:
graphql/queries.ts
graphql/mutations.ts
graphql/membership.ts
graphql/milestones.ts
graphql/admin.tsCreate a separate domain only when the capability has a sufficiently independent lifecycle, persistence model, public API, or operational owner. Do not create artificial micro-domains to make directories look small.
10. Verify the result as a human system
After implementation or proposal, answer these questions:
- Can a newcomer identify the domain's home without repository-wide search?
- Does
index.tsreveal what the domain contributes without exposing internals? - Can the public API be understood before reading implementation details?
- Does adding a domain require one registration change rather than several manual edits?
- Are authorization and persistence policies named in domain language?
- Is each shared concept defined once under its real owner, with runtime mechanics kept out of the pure contract?
- Do UI, API, database schema, and worker code consume the same name rather than define layer-specific aliases?
- Can a reviewer distinguish static rejection, dynamic rejection, soft visibility, and entity policy from the call site?
- Do guarded implementations receive the prepared, non-null principal directly, without an inline setup preamble or hidden reload?
- Are public operations visibly public instead of wrapped in no-op ceremony?
- Are cross-runtime contracts pure and intentionally shared?
- Do normal integration tests clean themselves up?
- Can a developer predict the structure of the next domain?
- Did the change reduce architectural shapes and exceptions?
If several answers are no, the architecture is not yet simpler even if the files moved.
Decision rules
Give every shared concept one canonical owner
- One runtime and one domain: Keep vocabulary and implementation in that domain. Do not move code to common merely for neatness.
- Several runtimes: Put the pure type, values, mappings, validation, calculations, or event payload in the common entry for the owning domain.
- Runtime implementation: Keep persistence, I/O, caches, side effects, and framework adapters in the owning domain of that runtime.
- Database and transport schemas: Consume canonical domain vocabulary. Do not redefine
it with layer suffixes such as
Name,RowType,ApiType, orAssignableunless the meaning is genuinely different. - Consumers: Depend on the public contract or narrow domain operation, not an internal representation.
Use one name when the meaning is the same. Introduce a second type only when it represents a real semantic boundary, and make the conversion explicit at that boundary.
Apply canonical ownership to authorization
- Shared vocabulary: Pure capability and role types, constants, and mappings used by more than one runtime belong in a common auth contract.
- Runtime enforcement: Grant queries, caches, superuser behavior, and permission evaluation belong in the runtime's auth domain.
- Static API requirement: Use the framework's declarative field or route authorization.
- Dynamic API requirement: Use one generic guard with the computed requirement.
- Soft visibility decision: Use a boolean permission predicate.
- Entity rule: Keep ownership, membership, and visibility policy in the entity's domain.
For example, do not create aliases such as AssignableRole and AdminRoleName for the same
role in different layers. Do not export raw permission loaders for ordinary consumers.
Reserve a full permission list for serialization boundaries or auth internals.
Use UNAUTHENTICATED for a missing or invalid identity and FORBIDDEN for an authenticated
identity lacking authority. Use NOT_FOUND only for an intentional resource-concealment
contract, not as the default permission error.
Hydrate once, validate at the boundary, narrow inside
- Put stable request-wide facts in the typed protocol context: the authenticated principal, its request-relevant roles and capabilities, tenant, locale, transaction, request id, and similarly universal values actually used by the application.
- Construct that context before dispatch. Use a request cache or external cache only when it has a clear invalidation policy; caching is an implementation choice, not permission for resolvers to reload the same principal.
- Express repeated preconditions through the protocol's declarative scope or one small resolver, route, job, or command enhancer.
- Make the enhancer expose a stronger input type. After an authentication wrapper succeeds,
wrapped code should see a non-null user and use
context.userdirectly. - Keep entity-specific loading and policy in the owning domain. A complete request context does not contain every project, team, or record the request might touch.
- Leave intentionally public operations unwrapped. The absence of a boundary wrapper is a useful signal when public access is deliberate.
Avoid this repeated shape:
resolve: async (_root, args, context) => {
const user = await guard(context);
return performDomainWork(user.id, args);
}Prefer a boundary guarantee and a direct domain body:
resolve: guard(async (_root, args, { user }) =>
performDomainWork(user.id, args)
)This is not specific to authorization. Apply the same reasoning whenever domain bodies reconstruct stable protocol context or repeat a cross-cutting precondition.
Put code in a common package only when
- at least two runtimes consume it now
- it is pure domain contract, validation, calculation, or event data
- it imports no UI framework, ORM, database, server, worker, or platform runtime
- its ownership and compatibility obligations are clear
Do not use a common package as a neutral dumping ground. Prefer explicit subpath exports over
a catch-all source barrel. Prefer one public subpath per shared domain, such as
@company/common/projects or @company/common/auth, over one export for every source file.
Create an abstraction only when
- repetition is stable and meaningful
- the abstraction removes mechanics from several call sites
- its name communicates domain or platform policy
- a change to the policy should intentionally affect every caller
Keep direct code when similarity is incidental, tiny, or likely to diverge.
Attach cross-cutting behavior without shadow registries
- Keep each route path, event shape, job schedule, API field, and command declaration in one executable source of truth.
- Add generic middleware, an enhancer, or typed metadata directly beside that declaration when telemetry, authorization, deprecation, tracing, or policy must observe it.
- Pass a stable semantic identifier from the owner, not raw domain details reconstructed by generic infrastructure.
- Make the cross-cutting mechanism reusable by every domain from its first implementation.
- If another runtime needs the complete catalog, derive or generate it from the owning declarations. Do not hand-maintain a parallel list.
Reject a design when adding or renaming one route, event, field, or job requires editing its owner plus a second classifier or registry for the cross-cutting concern.
Create a separate domain only when
- it has an independent lifecycle or state machine
- it owns distinct persistence or external contracts
- it can be reasoned about without importing most of its parent domain
- its operational or product ownership is meaningfully separate
Otherwise, create an internal facet of the existing module.
Guardrails
- Preserve public APIs by default. Treat GraphQL, REST, event payloads, package exports, and database contracts as compatibility surfaces.
- Separate runtime moves from domain refactors.
- Do not copy framework choices merely because the reference architecture used them.
- Do not replace the ORM solely to obtain named domain policies.
- Do not turn
index.tsinto a maintenance-heavy export inventory. - Do not introduce auto-discovery when one explicit registry is clearer.
- Do not force browser, API, and worker code through one physical module entry.
- Do not centralize domain-specific behavior into generic infrastructure.
- Do not create domain-specific shadow registries in generic infrastructure. Instrument the owning declaration with a generic mechanism instead.
- Do not mirror shared domain types, constants, validation, or mappings by runtime or layer.
- Do not let a database table, GraphQL schema, or UI component own vocabulary that belongs to the domain.
- Do not keep authorization types in an admin or feature domain when they describe application-wide authority.
- Do not stack an imperative permission guard under an equivalent declarative field scope.
- Do not make a guard, resolver, route handler, or domain service reload a stable principal or other request fact that context construction should already own.
- Do not add no-op wrappers to public operations merely for visual uniformity.
- Do not use documentation to compensate for inconsistent executable structure.
- Do not claim simplicity from file movement alone. Show the removed decisions and seams.
Output contracts
Architecture analysis
Provide:
- the current grammar and its exceptions
- evidence-backed cognitive entropy sources
- essential complexity that must remain
- the target grammar
- a small pilot recommendation
- an incremental migration order
- explicit non-goals
Architecture proposal
Show the proposed directory grammar, module contract, composition root, dependency direction, and one representative domain example. Explain which repeated decisions disappear.
Implementation
Make one reviewable structural step at a time. Validate after each behaviorally meaningful step. Keep mechanical moves, public contract changes, and domain rewrites in separate commits.
Review
Lead with whether the proposal reduces or increases cognitive entropy. Identify unnecessary layers, hidden registration, leaky boundaries, speculative generality, and compatibility risk. Recommend the smallest correction that restores a predictable grammar.
Final standard
Use this as the decisive test:
After learning one domain, can a developer predict where every important part of another domain will be?
If yes, the architecture is working. If no, reduce variance before adding abstraction.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

