Files
pikasTech-agentrun/docs/reference/spec-v01-runtime-assembly.md
T
2026-05-29 20:52:22 +08:00

230 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# v0.1 Runtime Assembly 规格
本文定义 AgentRun `v0.1` runner Job 启动前的四要素装配模型。`RuntimeAssembly` 是 manager 侧把 run intent 转换成可执行 runner/backend runtime 的权威视图;它只表达引用、hash、路径、权限、生命周期和脱敏策略,不携带 Secret value 或大文件正文。
## 设计目标
- 把 backend 镜像、provider profile、会话持久化和初始资源注入收敛为四个一等要素。
- 避免 runner 从隐式环境、host path、默认 home、可变 tag 或用户 payload 猜测运行时输入。
- 让 CI/CD、Secret、session、workspace 和 resource 注入各自有边界,但统一进入同一个装配计划。
- 把 identity、network、observability、GC、failureKind、provenance 等横切能力归并为四要素上的 policy、metadata、status 或 lifecycle 子项,不扩成并列的一等对象。
## 四要素模型
`RuntimeAssembly` 的一等要素固定为:
| 要素 | 职责 | v0.1 P0 边界 | 权威/引用 |
| --- | --- | --- | --- |
| `BackendImageRef` | 决定用什么 backend runtime image 和 command 能力。 | 使用 CI/CD 产出的 digest-pinned image;当前可复用 agentrun runner image,后续可拆独立 backend image。 | [spec-v01-cicd.md](spec-v01-cicd.md) |
| `ProfileRef` | 决定 provider/profile 配置和 API KEY SecretRef。 | `codex``deepseek` 使用 profile-scoped Kubernetes SecretRefSecret value 不进 run payload。 | [spec-v01-secret-distribution.md](spec-v01-secret-distribution.md) |
| `SessionRef` | 决定是否恢复或保存 backend 会话状态。 | P0 可以为 `null`;只定义边界,不把完整 `CODEX_HOME` 持久化。 | 本文 |
| `ResourceBundleRef` | 决定 backend 启动前 materialize 哪份代码和非敏感 repo 文件。 | P0 收敛为 Git-only,由 Git URL、full commit id 和 checkout policy 决定内容身份。 | 本文 |
`executionPolicy``observabilityPolicy` 是装配规则,不是新的 runtime material。它们可以约束四要素如何被装配、观察和清理,但不得替代四要素本身。
最小形态:
```json
{
"backendImageRef": {},
"profileRef": {},
"sessionRef": null,
"resourceBundleRef": {},
"executionPolicy": {},
"observabilityPolicy": {}
}
```
## 装配顺序
Manager 创建或触发 runner Job 前必须按固定顺序解析装配计划:
1. 根据 run 的 `backendProfile` 解析 `backendKind``ProfileRef`
2. 根据 `backendKind` 和 lane catalog 解析 `BackendImageRef`,得到 digest-pinned image。
3. 根据 run/session intent 解析 `SessionRef`P0 无持久 session 时显式为 `null`
4. 根据 run 的 workspace/resource intent 解析 `ResourceBundleRef`P0 必须是 Git-only。
5. 合并 `executionPolicy` 与 allowlist,生成 Kubernetes Job 的 env、volume、init/prepare intent 和 resource limit。
6. 生成可写 runtime home、workspace 和可选 session mountSecret projection 始终只读。
7. runner/backend 启动后把 image digest、profile name、SecretRef 名称/key、session id、resource commit/hash 和 redaction 状态写入 event metadata,但不写入 Secret value。
Runner 不得自行选择不同 image、Secret、PVC、host path 或 Git ref;任何缺失或不匹配都应按对应要素失败,而不是 fallback 到默认值。
## BackendImageRef
`BackendImageRef` 表达 backend runtime 能力和镜像身份。P0 允许 manager 和 runner/backend 共用同一镜像;即使共用,也必须在装配计划中把实际 image digest 作为 backend image identity 记录。
建议字段:
```json
{
"backendKind": "codex-app-server-stdio",
"image": "127.0.0.1:5000/agentrun/agentrun-mgr@sha256:...",
"sourceCommit": "<40-char source commit>",
"command": ["bun", "src/runner/main.ts"],
"backendCommand": ["codex", "app-server", "--listen", "stdio://"],
"resourceProfile": { "cpu": "2", "memory": "4Gi" },
"provenance": { "catalog": "deploy/artifact-catalog.v01.json" }
}
```
规则:
- image 必须来自 Tekton artifact catalog 或 manager allowlist;客户端 run payload 不得直接提供任意 image。
- 正式 runtime manifest 必须使用 digest pin,不以 mutable tag 作为执行身份。
- 镜像只表达 runtime 能力,不包含 API KEY、profile config、session 文件或用户 code。
- image pull、digest 缺失或 capability 不匹配应归类为 image/infra failure,不得被记录为 provider auth failure。
## ProfileRef
`ProfileRef` 表达 provider/profile 配置和 credential 边界。P0 中 `codex``deepseek` 都是 `codex-app-server-stdio` backend kind 的 profile/config/SecretRef 选择。
建议字段:
```json
{
"profile": "deepseek",
"backendKind": "codex-app-server-stdio",
"secretRefs": [
{ "name": "agentrun-v01-provider-deepseek", "keys": ["auth.json", "config.toml"] }
],
"runtimeHome": "/home/agentrun/.codex-deepseek",
"redactionPolicy": "provider-credential-v1"
}
```
规则:
- API KEY、Codex `auth.json`、Codex `config.toml` 和 provider token 只通过 SecretRef 注入。
- 非敏感 provider config 可以保存在 profile registry、ConfigMap 或 Postgres capability 中;credential value 不得进入 ConfigMap。
- Secret projection 是只读 credential source;需要 writable home 的 backend 必须复制到 per-run/profile runtime home。
- profile 缺失或 SecretRef 不匹配必须 `secret-unavailable``deepseek` 不得 fallback 到 `codex`
- network、proxy、NO_PROXY、rate limit 和 provider readiness 默认归并到 `ProfileRef` 的 policy/status 子项。
## SessionRef
`SessionRef` 表达可恢复的 backend 会话状态,不等同于 Postgres durable facts。Postgres 保存 run、command、event、terminal status、lease 和 session metadatabackend session 文件应保存到 PVC 或后续对象存储。
P0 允许无持久 session
```json
{
"sessionRef": null,
"persistence": "none"
}
```
后续建议字段:
```json
{
"sessionId": "sess_...",
"tenantId": "unidesk",
"projectId": "pikasTech/unidesk",
"backendKind": "codex-app-server-stdio",
"backendProfile": "codex",
"pvcRef": { "namespace": "agentrun-v01", "name": "agentrun-session-sess-..." },
"schemaVersion": "codex-stdio-session-v1",
"retentionPolicy": "debug-short"
}
```
规则:
- `SessionRef` 不保存 API KEY;每次 run 的 credential 仍从 `ProfileRef` 重新投影。
- 不直接持久化完整 `CODEX_HOME`,因为该目录可能混合 credential、config、session/cache。
- session 文件、workspace、profile credential 必须是不同目录或 volume。
- local-path/RWO PVC 会限制恢复节点;跨节点恢复需要 RWX 存储或对象存储,必须在后续 spec 中明确。
- session 挂载失败、版本不兼容或 restore 失败应归类为 session failure,不得归为 provider failure。
## ResourceBundleRef
`ResourceBundleRef` 表达 backend 启动前注入哪份代码和非敏感 repo 文件。P0 收敛为 Git-only,不支持上传文件、对象存储 artifact、inline env 或任意 ConfigMap/Secret 文件袋。
P0 字段:
```json
{
"type": "git",
"repoUrl": "git@github.com:pikasTech/unidesk.git",
"commitId": "<full commit sha>",
"subdir": ".",
"checkoutPolicy": {
"submodules": false,
"lfs": false,
"sparsePaths": []
},
"credentialRef": null,
"materializedTreeHash": null
}
```
规则:
- 内容身份由 `repoUrl + commitId + subdir + sparsePaths` 决定;commit id 必须是不可变 full commit sha。
- `credentialRef` 只用于拉取私有仓库,不参与内容身份,也不得暴露给 backend。
- `submodules``lfs` 默认 false;启用时必须进入验收和凭据边界。
- checkout 后应记录 `materializedTreeHash` 或等价摘要,确认实际 workspace 与期望 commit/subdir 一致。
- API KEY、provider token、Codex auth/config 属于 `ProfileRef`,不得放进 Git-only bundle。
- backend session/cache 属于 `SessionRef`,不得放进 Git-only bundle。
- 动态用户 env 属于 `executionPolicy` 的 allowlisted overlay,不作为 ResourceBundle 内容身份。
- 大型外部 artifact、上传文件、对象存储和任意 ConfigMap 文件注入都 deferred;后续必须显式扩展,不得把 P0 Git-only 模型变成万能资源袋。
## 横切能力归并
横切能力必须挂到四要素或 run policy 上:
| 横切能力 | 归并位置 |
| --- | --- |
| identity/tenant | run、session、resource 和 profile 的 owner/scope/grant 字段。 |
| scheduling/resource | `BackendImageRef.resourceProfile``executionPolicy`。 |
| network/egress | 主要属于 `ProfileRef`,少量属于 `ResourceBundleRef` fetch policy。 |
| observability | 四要素 materialization 的 event/status metadata。 |
| lifecycle/GC | session、resource、run/job 和 image artifact 各自的 retention policy。 |
| failureKind | 按失败发生在哪个要素归类。 |
| provenance | image digest、profile config hash、session snapshot version、resource commit/tree hash。 |
## FailureKind 归属
| 失败位置 | 建议 failureKind | 说明 |
| --- | --- | --- |
| Backend image pull/capability | `infra-failed` 或后续 `image-unavailable` | 镜像不存在、digest 不可拉取、backendKind 不匹配。 |
| Profile SecretRef | `secret-unavailable` | Secret 缺失、RBAC 拒绝、缺 `auth.json`/`config.toml`。 |
| Provider auth/upstream | `provider-auth-failed``provider-unavailable` | 已成功 materialize profile,但上游拒绝或不可用。 |
| Session mount/restore | `infra-failed` 或后续 `session-unavailable` | PVC 不可挂载、schema 不兼容、restore 失败。 |
| Resource checkout/materialization | `schema-invalid``infra-failed` 或后续 `resource-unavailable` | Git URL/commit 非法、checkout 失败、tree hash 不匹配。 |
新增细分 failureKind 前必须同步 manager、runner、backend、CLI、self-test 和 validation specP0 可以先用现有 failureKind 并在 event payload 中标明 `assemblyElement`
## 测试规格
### T1 RuntimeAssembly 字段完整性
阅读本文和 [spec-v01-services.md](spec-v01-services.md),然后检查 run/runner Job 创建路径是否能明确追溯 `BackendImageRef``ProfileRef``SessionRef``ResourceBundleRef`。P0 中尚未实现的 `SessionRef` 和 Git-only `ResourceBundleRef` 必须显式为 `null` 或 deferred 状态,而不是由 runner 隐式猜测。
### T2 BackendImageRef digest 固定
阅读本文和 [spec-v01-cicd.md](spec-v01-cicd.md),然后检查 Tekton artifact catalog、GitOps runtime manifest 和实际 Deployment/Job image,确认 runner/backend 使用 digest-pinned image,并能追溯 source commit。
### T3 ProfileRef Secret 隔离
阅读本文、[spec-v01-secret-distribution.md](spec-v01-secret-distribution.md) 和 [spec-v01-backend-codex.md](spec-v01-backend-codex.md),然后分别执行 `backendProfile=codex``backendProfile=deepseek` 的真实 runner Job。确认当前 run 只挂载匹配 profile 的 SecretRefruntime home 独立,缺失 profile SecretRef 不 fallback。
### T4 SessionRef 与 credential 分离
阅读本文,然后在引入 session 持久化前确认 P0 runner Job 不把完整 `CODEX_HOME` 持久化到 PVC 或 hostPath。后续实现 session PVC 时,必须证明 session 目录不包含 API KEY、Codex auth/config 或 provider token。
### T5 Git-only ResourceBundle
阅读本文,然后用 Git URL、full commit id 和 subdir 创建资源装配计划。确认 checkout 发生在允许 workspace 前缀内,记录 materialized tree 摘要,且 run payload 不携带文件正文、Secret value 或任意 env dump。
## 规格的实现情况
| 规格项 | 状态 | 说明 |
| --- | --- | --- |
| RuntimeAssembly 四要素模型 | 已定义 | 本文作为四要素装配模型权威;其他 spec 只引用,不重复定义。 |
| `BackendImageRef` | 部分实现 | 当前 runner/backend 复用 agentrun 镜像,CI/CD 已使用 digest-pinned runtime manifest;尚未拆独立 backend image registry。 |
| `ProfileRef` | 已实现/已通过主闭环 | `codex``deepseek` profile 已通过 Kubernetes SecretRef、writable runtime home 和真实 Codex stdio turn 验证。 |
| `SessionRef` | 已定义/P0 未持久化 | 当前 v0.1 只持久化 run facts,不持久化 backend session 文件;后续实现 PVC 或对象存储前必须保持 credential 分离。 |
| Git-only `ResourceBundleRef` | 已定义/待实现 | P0 规格收敛为 Git-only,尚未进入 runner Job materialization。 |
| 横切能力归并 | 已定义 | identity、network、observability、GC、failure 和 provenance 归并为四要素 policy/metadata/status/lifecycle 子项。 |