本文定义 Graft 面向平台化演进的项目文件组织、外部能力扩展点和渐进迁移规则。
本文是目标组织模型,不代表本次已经完成物理目录迁移。当前 live 代码继续按照现有 server/internal/**、
server/modules/** 与 server/runner/** 工作;只有完成对应迁移切片并通过验证后,目标路径才可取代旧路径。
本设计覆盖:
server的 Core、Runtime、Application、Ports、Services、Adapters、Providers、Integrations、Agents 与 Runner;- 根级
deployments/**与tests/**的部署和 conformance fixture; - 后续 Agent 的目录判定、依赖方向和迁移入口。
web 继续遵循自己的模块和壳层架构,本设计不重写 web 目录。
业务用例先表达应用能力和生命周期,再选择 Docker、Kubernetes、Vault 或其它外部实现。业务模块、Application 和 Core 不得导入供应商 SDK、读取供应商 endpoint、解析宿主机路径或持有 secret 明文。
目标依赖方向:
module / application
|
v
provider-neutral port or moduleapi capability
|
v
provider implementation -> adapter / external SDK
Provider 通过 module.Spec、module.Builder 或生成的 compile-time registry 显式注册。当前版本不引入:
- runtime filesystem scan、动态插件加载或 hot-load;
- 反射式 Provider discovery、通用 service locator 或第二套 DI;
- 第三方 Provider marketplace;
- Provider 自有 scheduler、queue、Task state machine、global health registry 或 evidence store。
Provider 生命周期必须由现有 Runtime 管理,至少能被显式校验、启动、停止,并在失败时以 capability-local 的 Unavailable/Degraded 语义返回,不得把单个 Provider 故障伪装成全局服务故障。
Provider、Agent、Runner 与 Module 的跨边界资源 ownership、capability visibility 和 cleanup declaration 由 运行时组合与资源治理设计.md 统一约束;本文继续只拥有物理组织、依赖方向和扩展点分类。
server/modules/<name>/**继续拥有业务能力、业务持久化、路由、菜单、权限、任务定义和模块私有 contract。server/internal/moduleapi/**继续拥有跨模块业务 capability、稳定 DTO 和窄稳定服务接口。server/internal/contract/**继续拥有平台级 typed contract。server/internal/app/**、internal/module/**、internal/container/**等继续拥有显式 Runtime/Core 生命周期。internal/ports/**仅作为未来外部能力端口的保留边界,不替代moduleapi,也不能成为通用 shared/common/utils 目录。
以下路径是目标落点;本次不创建空目录。
server/
├── cmd/ # 现有 CLI 与一次性命令入口
├── internal/
│ ├── core/ # 目标概念边界;仅放真正平台基础设施
│ ├── application/ # 目标概念边界;跨模块用例编排
│ ├── ports/ # 目标概念边界;外部能力端口,非业务 capability
│ ├── services/ # 目标概念边界;平台级应用服务
│ └── adapters/ # 目标概念边界;共享协议/SDK/transport adapter
├── modules/ # 当前及长期业务模块 canonical 路径
├── providers/ # compile-time Provider 实现
│ ├── runtime/ # Docker、Kubernetes、Podman 等运行时 Provider
│ ├── builder/ # Docker、BuildKit、Kaniko 等构建 Provider
│ ├── secret/ # Vault、AWS、local 等 secret Provider
│ └── certificate/ # Vault PKI、step-ca 等证书 Provider
├── integrations/ # GitHub、GitLab、Jira、Slack 等业务系统集成
├── agents/ # 独立部署/发布单元,如 builder、runtime agent
└── runner/ # 外部副作用执行器及其实现
deployments/ # 仓库级部署拓扑与发布 fixture
├── docker/
├── compose/
└── kubernetes/
tests/
└── conformance/ # Provider/Agent/Runner 的 provider-neutral 一致性 fixture
internal/core、internal/application、internal/services 和 internal/adapters 是目标概念分层。迁移前,
现有 internal/app、internal/httpx、internal/event、internal/eventbus、internal/config 等显式 Core
边界继续有效,不得为了目录外观进行批量搬迁。
Provider 提供平台运行能力,是某个 Port 的可替换实现,并参与 compile-time registration。例如:
- Docker Runtime Provider;
- Kubernetes Deployment Provider;
- Vault Secret Provider;
- BuildKit Builder Provider。
Provider 可以使用自己的 adapter,但不能把供应商类型泄露到业务 capability 或公共 API。
Adapter 是对 SDK、CLI、协议、传输或原始外部事实的窄封装。共享 adapter 只能进入明确的 Core/Adapter 边界;
供应商专属 adapter 默认放在 Provider 内部,避免同一实现同时存在于 internal/adapters 和 providers。
Integration 连接外部业务系统或协作平台,不拥有 Graft 平台运行时能力。例如 GitHub、GitLab、Jira、Slack、邮件 或 webhook 消费。Integration 可以使用 HTTP、OAuth 或 webhook adapter,但不能被命名为 Runtime Provider,也不能 改变 Graft 的 Task、权限或配置 authority。
因此,GitHub Integration 与 Docker Runtime Provider 是不同概念;前者连接外部业务系统,后者提供平台执行能力。
Agent 是独立部署单元,不是 cmd/ 下的若干参数分支。目标布局为:
server/agents/<name>/
├── cmd/main.go
├── internal/ # bootstrap、identity、transport、heartbeat 等私有实现
├── config/
└── Dockerfile
Docker 能力采用一个独立部署的 docker-runtime-agent。现有实验期仅面向构建的 Agent 直接升格并改名,
不保留并行 Builder Agent、Runtime Agent 或兼容别名。Agent 拥有独立配置、身份、传输和发布生命周期,作为
唯一常驻 Docker socket owner 承载 Container、Compose 和 Build Provider adapter;它不直接拥有业务数据库
真相,不绕过 Server 的授权、Task/Submission、审计和 Provider conformance 边界。
Agent 只能通过 Runtime Target 的 mTLS listener 拉取 Task Runtime 已冻结的 external execution lease,并用受限 日志与 receipt 回写执行事实。它不得接受 server push、创建第二套 queue/retry/state machine,或把 endpoint、 证书路径、凭据和 SDK 类型写入 TaskPlan。具体边界由 ADR-026 固定。
Application、Container 与 Build 的有限副作用分别通过 compose_execution、container_execution 和
oci-build capability 进入该 Agent。业务模块只冻结领域 action/policy;Compose 和 Build 所需 workspace、
定义文件与短时 Registry 凭据由所属 resolver 在 claim 后按 lease/fence 瞬时提供,不属于 Task 或 Agent 持久状态。
Container list/detail、stats、events、logs 与 exec 仍属于
后续 Agent-initiated snapshot/interactive transport,不得把 Agent 的 SDK adapter 反向放回业务 module 作为 fallback。
Runner 只执行受控的外部副作用,例如平台自更新、Helm 或 Terraform。它的输入应是不可变 operation snapshot, 完成结果应通过现有 Task/Submission receipt 语义返回;Build 可在 terminal receipt 前通过瞬时 result 边界 交给自己解释 Artifact/Publication,Task 仅保留结果摘要用于幂等重放。
Runner 不得自建第二套任务状态机、队列、重试策略、全局日志库或业务持久化。现有 server/runner/compose 在
迁移完成前继续作为当前实现和历史 authority,不得直接移动或复制出第二份 Compose runner。
| 当前路径 | 当前状态 | 后续规则 |
|---|---|---|
server/modules/** |
canonical/current | 继续承载业务模块 |
server/internal/moduleapi/** |
canonical/current | 继续承载跨模块业务 capability |
server/internal/app/** 等 Core 包 |
canonical/current | 继续承载显式 Runtime/Core 生命周期 |
server/runner/compose/** |
current/legacy-frozen | 只维护,不新增第二套抽象;迁移时先更新 authority |
server/providers/** |
target/reserved | 新 Provider 实现的目标路径 |
server/agents/** |
target/reserved | 新独立 Agent 的目标路径 |
server/integrations/** |
target/reserved | 新外部业务系统集成的目标路径 |
deployments/**、tests/conformance/** |
target/reserved | 部署拓扑与一致性 fixture,不进入 Core |
新代码必须先完成边界判定:业务模块、Core Runtime、Port、Provider、Adapter、Integration、Agent、Runner 或 Fixture。
无法分类时,先更新设计文档;禁止把代码临时塞进 internal/**、common、shared 或 utils。
- 文档和 authority 收敛;本阶段不改代码、不建空目录。
- 新代码直接使用目标边界,旧路径冻结。
- 以 capability 为单位迁移 Compose Runner、Docker Runtime、Builder、Secret 和 Certificate Provider。
- 将实验期仅面向构建的 Agent 直接升格为单一 Docker Runtime Agent,迁移部署拓扑与 conformance fixture。
- 完成 Provider conformance、Task/Submission recovery、权限、审计和配置验证后,再删除旧路径。
每个迁移切片必须同时说明 canonical owner、依赖方向、失败/取消/超时/recovery 语义、验证范围和可删除的旧代码。
- Core/Application 不依赖 Docker、Vault、Kubernetes 或其它供应商 SDK。
moduleapi与ports的职责没有重叠或双重 authority。- Provider 只能通过 compile-time wiring 进入 Runtime。
- Agent、Runner、Integration 都没有创建第二套启动、任务、配置或恢复流程。
- 旧路径没有被偷偷移动、复制或引入新业务实现。
- Provider-neutral conformance fixture 可以验证不同 Provider 的共同语义。