domain-organization

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Domain organization

领域组织

Organize source by owner → role → module. A path should identify who owns the behavior, what responsibility it serves, and which concept or operation it contains. Models and services share an owner; they need not share a file.
Apply codebase-design when choosing boundaries: keep each capability together and split only when the split improves understanding. Role directories organize useful modules; they do not require a separate file for every helper, query, type, or step.
Apply this to the requested scope. A planning request produces a plan; an implementation request authorizes the relevant structural changes. This skill does not itself authorize installs, dependency upgrades, or changes to another repository.
按照 所有者 → 角色 → 模块 的结构组织源码。路径应当能够体现行为的归属方、承担的职责,以及包含的概念或操作。模型与服务归属于同一所有者,无需放在同一个文件中。
划分边界时请遵循 codebase-design 规范:将同一能力的代码放在一起,仅当拆分能够提升可理解性时才进行拆分。角色目录用于组织有用的模块,不需要为每个辅助函数、查询、类型或步骤单独创建文件。
在请求的范围内应用此规范。规划类请求会生成方案;实施类请求则授权进行相关的结构调整。本技能本身不授权安装依赖、升级依赖或修改其他仓库。

Ground the work

现状梳理

Read the target repository's instructions, package guidance, accepted decisions, manifests, export/import maps, and validation scripts. Inspect actual source and callers before assigning roles. Treat an existing plan as design evidence, then reconcile its inventory and execution claims with the current working tree.
Identify the existing owners, public interfaces, composition roots, test policy, generated inputs, and framework naming requirements. Distinguish verified facts from proposed paths. For whole-project work, account for every package and app, including areas intentionally left unchanged.
Preserve explicit user and repository constraints. Resolve routine layout choices from the code; ask only when an unresolved ownership or contract choice changes the requested outcome materially.
阅读目标仓库的说明文档、包管理指南、已采纳的决策、清单文件、导出/导入映射和验证脚本。在分配角色之前,检查实际源码和调用方。将现有方案视为设计依据,然后将其清单和执行声明与当前工作目录进行核对。
识别现有的所有者、公共接口、组合根、测试策略、生成的输入以及框架命名要求。区分已验证的事实与提议的路径。对于全项目范围的工作,要覆盖每个包和应用,包括有意保留不变的区域。
保留用户和仓库明确提出的约束。常规的布局选择从代码中推导;仅当未解决的所有权或契约选择会实质性影响请求的结果时,才进行询问。

Choose the owner

确定所有者

  • A focused package can be the owner:
    src/models/Invoice.ts
    and
    src/services/InvoiceStore.ts
    belong together.
  • A package with substantial domains groups by domain first:
    src/billing/models/Invoice.ts
    ,
    src/billing/services/InvoiceStore.ts
    .
  • Keep an app's screens, routes, and feature-specific behavior in the app. Reusable UI belongs in its own package; discover that package's name and alias from the workspace. Keep app routes, stores, and API clients out of it.
  • Give shared infrastructure a home based on real owners and callers. Similar names alone do not justify merging capabilities or creating another package.
  • Distinguish domain
    models/
    from AI model-provider capabilities. Use the latter's actual responsibility, such as
    inference/
    or
    providers/
    , without silently changing its public contract.
Keep packages as deep modules with small public interfaces. Avoid one package per type or service. Create role directories only when useful code belongs in them; preserve precise established roles instead of creating empty scaffolds.
  • 功能单一的包可以作为所有者:
    src/models/Invoice.ts
    和
    src/services/InvoiceStore.ts
    属于同一所有者。
  • 包含多个领域的包优先按领域分组:例如
    src/billing/models/Invoice.ts
    、
    src/billing/services/InvoiceStore.ts
    。
  • 应用的页面、路由和特定功能的行为保留在应用内。可复用的UI应放在独立的包中;从工作区中查找该包的名称和别名。应用的路由、状态存储和API客户端不要放在可复用UI包中。
  • 共享基础设施的归属应基于实际的所有者和调用方。不能仅因为名称相似就合并能力或创建新包。
  • 区分领域
    models/
    与AI模型提供商能力。后者应根据实际职责命名,例如
    inference/
    或
    providers/
    ,且不得擅自修改其公共契约。
包应设计为具有精简公共接口的深度模块。避免为每个类型或服务单独创建包。仅当角色目录中有实际有用的代码时才创建;保留已有的明确角色,不要创建空的脚手架。

Assign roles by responsibility

按职责分配角色

RoleContents and boundary
models/
Schemas, derived types, IDs, value objects, and closely related pure operations. Keep a schema and its derived type together.
services/
Named capabilities and operations against required interfaces. Receive concrete implementations through composition.
adapters/
Database, HTTP, SDK, filesystem, host, and framework implementations, including provider-specific decoding.
workflows/
Processes coordinating services; the composition root selects concrete adapters.
policies/
Business decisions and validation rules that depend on domain concepts.
mappers/
Independently useful conversions between established representations. Keep adapter-private row conversion with its operation.
utils/
Small supporting functions independent of domain contracts. Domain-aware helpers belong with their model, policy, or mapper.
Use additional roles when they explain the code:
config/
,
tools/
,
prompts/
,
components/
,
hooks/
,
state/
,
routes/
, or
runtime/
. Configuration shapes and defaults remain separate from credentials and live resource construction. Keep app entrypoints thin and put live assembly in the composition root.
Read mixed modules before moving them. A filename does not make a function pure or separate a service contract from its concrete implementation. Split coherent responsibilities while preserving behavior; design any necessary semantic change as a separate change.
Keep an operation's private helpers, queries, bindings, and decoding local when they must be understood together. Share a mapper or helper when it hides a meaningful decision or serves real callers, not to shorten another file. Retain configured line limits and document narrow exceptions for cohesive modules.
角色内容与边界
models/
Schema、派生类型、ID、值对象以及紧密相关的纯操作。Schema与其派生类型应放在一起。
services/
基于所需接口的命名能力和操作。通过组合接收具体实现。
adapters/
数据库、HTTP、SDK、文件系统、宿主和框架的实现,包括特定于提供商的解码逻辑。
workflows/
协调多个服务的流程;由组合根选择具体的适配器。
policies/
依赖领域概念的业务决策和验证规则。
mappers/
在已定义的表示形式之间进行的、可独立使用的转换。适配器私有的行转换应与其对应的操作放在一起。
utils/
独立于领域契约的小型辅助函数。感知领域的辅助函数应放在对应的模型、策略或转换器中。
当其他角色能更好地解释代码时,可以使用:
config/
、
tools/
、
prompts/
、
components/
、
hooks/
、
state/
、
routes/
或
runtime/
。配置的结构和默认值应与凭证及实时资源的构建逻辑分离。保持应用入口的精简,将实际的组装逻辑放在组合根中。
在移动混合模块之前,先仔细阅读其内容。文件名不能决定函数是否是纯函数,也不能区分服务契约与其具体实现。在保持行为不变的前提下拆分内聚的职责;任何必要的语义变更都应作为单独的变更来设计。
如果一个操作的私有辅助函数、查询、绑定和解码逻辑必须放在一起才能理解,就将它们保留在本地。仅当转换器或辅助函数封装了有意义的决策或服务于实际调用方时才将其共享,而不是为了缩短另一个文件的长度。保留已配置的行数限制,对于内聚性强的模块,可以记录少量的例外情况。

Name modules consistently

模块命名一致性

These defaults yield to explicit user choices and established repository or framework constraints. Keep owner directory casing consistent with the repo; role directories are lowercase and plural.
KindDefaultExample
Named model, schema, service, or toolkitPascalCase
Invoice.ts
,
InvoiceStore.ts
,
BillingTools.ts
Named adapterPascalCase stem, optional lowercase implementation suffix
InvoiceStore.postgres.ts
Component or JSX modulePascalCase
InvoiceTable.tsx
Function, workflow, policy, mapper, handlerkebab-case
issue-invoice.ts
,
parse-row.ts
React hookcamelCase
useInvoice.ts
Companion test or fixtureSource stem, lowercase suffix
InvoiceStore.test.ts
,
parse-row.fixture.ts
Conventional files stay recognizable and lowercase:
index
,
app
,
main
,
agent
,
cli
,
config
,
errors
,
constants
,
types
,
schemas
,
fixtures
,
testing
,
setup
, and
runtime
. Their directory should supply a narrow meaning. Split a broad
types.ts
by owned concepts when useful, not by every alias.
PascalCase identifies a named module; it implies neither a class nor a single export. Keep related schema/type pairs and useful associated exports together. Retain established exported spellings and service identities during file moves.
Lowercase dotted suffixes distinguish implementation and test roles. Preserve framework routes, configuration files, declaration files, migration numbering, SQL, scripts, and generated or registry-managed names through narrow exceptions. Move ordinary helpers out of component directories when their role differs.
When at least three sibling implementation modules repeat a prefix naming the same concept, make that concept a subdirectory and remove the prefix from the filenames:
text
composer-attachments.ts → composer/attachments.ts
composer-images.ts     → composer/images.ts
composer-text.ts       → composer/text.ts
Keep the grouping within its owner and role, such as
utils/composer/text.ts
, and apply the casing conventions above to the shorter names. Count distinct implementation modules; companion tests and fixtures follow their source. Retain descriptive operation names such as
parse-row.ts
when their words describe the operation itself.
以下默认规则需服从用户明确的选择以及已有的仓库或框架约束。所有者目录的大小写与仓库保持一致;角色目录使用小写复数形式。
类型默认规则示例
命名的模型、schema、服务或工具包PascalCase
Invoice.ts
,
InvoiceStore.ts
,
BillingTools.ts
命名的适配器PascalCase主名,可选小写实现后缀
InvoiceStore.postgres.ts
组件或JSX模块PascalCase
InvoiceTable.tsx
函数、工作流、策略、转换器、处理器kebab-case
issue-invoice.ts
,
parse-row.ts
React HookcamelCase
useInvoice.ts
配套测试或固件源文件名主名 + 小写后缀
InvoiceStore.test.ts
,
parse-row.fixture.ts
约定俗成的文件保持小写且易于识别:
index
、
app
、
main
、
agent
、
cli
、
config
、
errors
、
constants
、
types
、
schemas
、
fixtures
、
testing
、
setup
和
runtime
。它们所在的目录应提供明确的狭义含义。如果有必要,可以按所属概念拆分庞大的
types.ts
,而不是按每个别名拆分。
PascalCase 表示命名模块;它既不意味着是类,也不意味着只有单个导出。相关的schema/类型对以及有用的关联导出应放在一起。移动文件时,保留已有的导出名称和服务标识。
小写的点后缀用于区分实现和测试角色。通过少量例外,保留框架路由、配置文件、声明文件、迁移编号、SQL、脚本,以及生成的或由注册中心管理的名称。如果普通辅助函数的角色不同,应将其移出组件目录。
当至少三个同级实现模块重复使用同一个概念的前缀时,将该概念设为子目录,并从文件名中移除前缀:
text
composer-attachments.ts → composer/attachments.ts
composer-images.ts     → composer/images.ts
composer-text.ts       → composer/text.ts
分组应保留在其所有者和角色目录下,例如
utils/composer/text.ts
,并对缩短后的文件名应用上述大小写约定。统计时按独立的实现模块计数;配套测试和固件跟随其源文件。如果文件名本身能够描述操作的含义,则保留描述性的操作名称,例如
parse-row.ts
。

Preserve public boundaries

保留公共边界

Where a package has
src/
, keep implementation there and use thin, explicit public entry files consistent with the repository's export policy. Expose small interfaces instead of wildcard-exporting private trees. A model-only entry should not also pull in a concrete adapter.
The public interface should expose complete operations and own their ordering, failure, and cleanup. Thin public re-exports establish that boundary; internal forwarding chains usually add navigation. Translate external execution models and validate incoming data at the real adapter boundary.
Follow the target's compatibility policy: retain stable public specifiers where required; where obsolete paths must be removed, update all callers and remove them. Do not add blanket compatibility wrappers. Public assets and generated resources need their own export handling rather than a source-file naming rule.
In Effect projects, check the installed Effect Agent contract catalog and published upstream contracts before defining agent infrastructure types or services. Import the upstream contract when one exists; organization work does not justify duplicate sandbox, durability, approval, or workflow contracts.
如果包有
src/
目录,将实现代码放在其中,并使用符合仓库导出策略的精简、明确的公共入口文件。暴露小范围的接口,而不是通配符导出私有目录树。仅包含模型的入口不应引入具体的适配器。
公共接口应暴露完整的操作,并负责其执行顺序、失败处理和清理逻辑。精简的公共重新导出建立了这一边界;内部的转发链通常只会增加导航成本。在实际的适配器边界处转换外部执行模型并验证传入数据。
遵循目标仓库的兼容性策略:在需要的地方保留稳定的公共标识符;如果必须移除过时的路径,要更新所有调用方然后再移除。不要添加笼统的兼容性包装器。公共资源和生成的资源需要单独的导出处理,而不是通过源文件命名规则来处理。
在Effect项目中,定义Agent基础设施类型或服务之前,先检查已安装的Effect Agent契约目录和已发布的上游契约。如果存在上游契约,直接导入;组织调整工作不能成为重复创建沙箱、持久性、审批或工作流契约的理由。

Plan or implement

规划或实施

For a requested plan, project-wide reorganization, or phased rollout, read references/planning.md. Save the requested plan in the target project's
docs/
, even when reusable presets live in a shared repository. Planning ends with that artifact; proposed moves are not execution evidence.
When implementation is authorized, move one coherent owner at a time. Update its imports, public exports, private aliases, build roots, test discovery, and assets together. Match source extensions to alias targets; extension-appending maps must not turn an import into
Invoice.ts.ts
. Use an intermediate path for case-only renames where needed so Git records them reliably.
Keep runtime behavior, schemas, wire formats, persistence keys, service tags, tool names, and workflow identities stable. Use the repository's existing tests and checks to verify the moved public interfaces and runtime assets. Follow its test-placement policy rather than imposing a new test tree.
When evaluating, adding, or claiming filename/dependency enforcement, read references/enforcement.md. Run the actual selected checks and verify graph coverage before describing a scope as enforced. Report the changed paths, verified checks, remaining gaps, and unrelated failures with their exact command and first actionable diagnostic.
对于请求的方案、全项目范围的重组或分阶段推出,请阅读 references/planning.md。将请求的方案保存在目标项目的
docs/
目录下,即使可复用的预设存放在共享仓库中。规划以该产物为结束;提议的移动不能作为执行的依据。
当授权实施时,每次移动一个内聚的所有者模块。同时更新其导入、公共导出、私有别名、构建根、测试发现和资源。确保源文件扩展名与别名目标匹配;追加扩展名的映射不能导致导入变成
Invoice.ts.ts
。如果仅需重命名大小写,必要时使用中间路径,以确保Git能够可靠记录。
保持运行时行为、schemas、线格式、持久化键、服务标签、工具名称和工作流标识稳定。使用仓库现有的测试和检查来验证移动后的公共接口和运行时资源。遵循仓库的测试放置策略,而不是强加新的测试目录结构。
在评估、添加或声明文件名/依赖强制规则时,请阅读 references/enforcement.md。在将范围描述为已强制执行之前,运行实际选定的检查并验证图覆盖范围。报告变更的路径、已验证的检查、剩余的差距和无关的失败,并附上确切的命令和第一个可操作的诊断信息。