Skip to content

分包与依赖约束

代码布局的权威规格(代码是 SSOT,结构漂移时与代码同 PR 改本文件)。 配套:repository-topology.mdc(目录地图 / 解析)、 code-layers.mdc(依赖矩阵与护栏)。

包路径装什么允许依赖的 @freeanima 包
@freeanima/sharedpackages/shared/契约(Zod)、pg-shapes、rpc-contract、habitat-contract、vault-crypto、同构工具——(叶层)
@freeanima/kernelpackages/kernel/Cordis Kernel 视图、logger、config-mechanism、logging、randomshared
@freeanima/corepackages/core/drizzle schema/migrations、PG、Redis、config 段与 runtime store、llm/tool/tokenizer/tts/compresskernel, shared
@freeanima/enginepackages/engine/conversation / turn / goal / pipeline / loop-mechanismcore, kernel, shared
@freeanima/capabilitiespackages/capabilities/memory / tools / connectors / self / outpost / mcp-* / federation / llm-openaiengine, core, kernel, shared
@freeanima/featurespackages/features/<slug>/28 个服务端特性(26 个带 cordis-plugin.ts;见「特性两态」)capabilities, engine, core, kernel, shared
@freeanima/serverpackages/server/组合根:boot、habitat-api(HTTP/RPC 面)、ports、config 真实现、tlsfeatures, capabilities, engine, core, kernel, shared
@freeanima/clipackages/cli/anima / anima-client / anima-probe({anima,client,probe}/)server, features, capabilities, core, kernel, shared
@freeanima/ui-kitpackages/ui-kit/设计系统(无业务逻辑)shared
@freeanima/portal-sdkpackages/portal-sdk/SPA 运行时与数据面(typed habitat client、offline、speech、settings 原语)ui-kit, shared
@freeanima/ui-featurespackages/ui-features/<slug>/ui/<bundle>/24 个 UI 特性;ui/spa 默认 bundle,卫星窗用 ui/floatportal-sdk, ui-kit, shared
@freeanima/app-framepackages/app-frame/应用布局 chrome、路由表、设置页 chromeui-features, portal-sdk, ui-kit, shared
@freeanima/portalpackages/portal/入口宿主:app/{web,tauri} + extension(WXT MV3)app-frame, ui-features, portal-sdk, ui-kit, shared

@freeanima/site(site/)是文档站,不参与运行时 DAG。

两条链 + 一个共享叶层:

server 链: shared → kernel → core → engine → capabilities → features → server → cli
前端链: shared → ui-kit → portal-sdk → ui-features → app-frame → portal

server 与 cli 是入口/组合根,可依赖其下全部服务端包;前端链不得触碰任何服务端包 (唯一交叉点是 shared)。

  • @freeanima/features/* = 服务端特性;@freeanima/ui-features/* = UI 特性。 同名 slug(如 task)在两侧各有一份,靠包名区分——不再有「一个前缀、两棵树」的隐式解析。
  • @freeanima/features/habitat/* 是栖息地管理台的服务端(RPC + ops 面), 不是 @freeanima/ui-features/habitat/*(管理台 UI),也不是 shared/habitat-*。
  • 已退役前缀:@freeanima/habitat/*、@freeanima/frontend/*、@freeanima/client/*、 @freeanima/platform/*、@freeanima/host/*。由 scripts/check-retired-imports.ts 守护。
  • 每层 = 一组 Cordis 插件/服务;特性 = packages/features/<slug>/cordis-plugin.ts 经 createFeaturePlugin 挂到 ctx.features。
  • 组合根 context 由 server 持有:server/bootstrap/kernel.ts 的 serviceRootContext() 为 serve() 与 createServiceKernel() 提供同一份 Context;createKernel({ ctx, logger }) 只做视图与 root logger 登记。 仓库内没有进程级 context 句柄,也没有模块级全局桥 (globalThis[Symbol.for] / getRootContextOrNull / 服务定位注册表),由 scripts/check-module-globals.ts + oxlint freeanima/no-module-globals 纯禁令守护。
  • 依赖来源:调用方持有 ctx 时直接用 ctx.<service>;没有 ctx 的深层代码 把依赖作为显式参数传入,或由所属模块持有该状态(连接池、配置缓存、函数钩子等 归其 owner 包,挂载/注销时登记,例如 platformPorts()、getNotificationPort()、 getAppRuntime()、initLlmRuntime())。
  • @freeanima/capabilities/ports/ 是能力/特性回调组合根的唯一通道 (platformPorts / *-port.ts:habitat-dispatch、session-pumps、 task-reminder-schedule、runtime-deps、app-runtime-context 等)。
  • 统一测试 harness:@freeanima/kernel/testing 的 createTestContext({ logger?, mount? }) —— 装配隔离的 context/logger(与 createServiceKernel 同一条 createKernel 路径), mount() 按生产 mount 助手挂服务,dispose() 逆序卸载。放在 kernel 是为了每一层 都能 import(自身只依赖 Context + logger)。

DDL 仅 packages/core/db;存储形状的纯 Zod 经 codegen + package exports 落到 @freeanima/shared/pg-shapes;前端与协议只依赖该出口(check-frontend-no-drizzle 用 Vite 模块图抽样断言)。

脚本断言
scripts/check-package-deps.ts每个包 package.json 的 @freeanima 依赖 ⊆ DAG(无债务登记通道)
scripts/check-layer-deps.ts全仓层依赖扫描(含相对路径与测试文件);基线为空,任何违规即失败
scripts/check-package-paths.ts代码里的 packages/* 路径字面量必须指向真实目录(防退役树复活)
scripts/check-external-deps.ts包内第三方 import 已在该包 package.json 声明(拆包/搬迁不漏依赖)
scripts/check-module-globals.ts模块级全局桥/进程根句柄纯禁令(0 命中)
scripts/check-boot-plugin-parity.tscordis.yml 与 TS 侧插件清单一致
scripts/check-retired-imports.ts无残留退役前缀
oxlint freeanima/layer-deps单文件即时反馈(同一 DAG 实现)
oxlint freeanima/no-module-globals禁止新增全局桥
scripts/check-frontend-no-drizzle.tsVite 模块图无 drizzle-orm
scripts/check-shared-shapes.tspg-shapes codegen 无漂移

当前状态:文件级 0 个层对 / 0 文件(重构起点 178 文件),包级反向边 0 条。 scripts/oxlint-plugins/freeanima/lib/layer-deps-baseline.ts 为空表; scripts/check-package-deps.ts 的 REVERSE_EDGE_DEBT 机制已随债务还清一并删除—— 新出现的反向依赖(文件级或 package.json 级)一律直接失败,不再有登记通道。

构建工具链车道: vite*.config.ts / build*.ts(satellite 构建入口)不参与 DAG—— 它们只产出 bundle,不进入运行时依赖图。

跨 bundle 壳桥: 卫星窗(ui/float 等)与 portal-sdk/pomodoro-active 只能依赖 portal-sdk,因此 Tauri 壳桥(portal-sdk/shell-bridge/)与壳配置读盘器 (shared/shell-config/)放在下两层;portal/app/tauri/* 留垫片再导出,native 侧只保留 Rust/IPC 与宿主装配。

packages/features/<slug>/ 有两种形态,由 cordis-plugin.ts 是否存在区分:

  • 路由特性(26 个):cordis-plugin.ts + domain/ + habitat/(Habitat RPC 路由与 handler)+ 视需要 protocol/(method-defs 与帧类型)。经 builtinFeaturePlugins 挂到 ctx.features。
  • 工具特性(content-block、workflow):只有 domain/,通过 server/register-tools.ts 贡献工具,不占 Habitat 方法面——因此没有 cordis-plugin.ts, 也不在 cordis.yml 特性清单内。