# Agent App 开发规范 v2.6.1

> 本文件为本地未发布草案 v2.6.1。Canonical SysDoc 写入返回 `no permission`，未取得发布权限，不代表线上文档已更新。面向 Agent App 开发者的本地集成参考。
>
> 最后更新：2026-09-13 | 主参考：`vlcode-lite-agent-os-architecture-baseline.zh.md`、`workflow-engine-host-boundary.md`、`agent-os-control-plane-v1.md`、`agent-app-runtime-graph-upgrade-plan.zh.md`
>
> v2.1.0 变更：新增 §7.6 舰队 / 分片 fan-out 范式（Fleet / Sharded fan-out）——静态 N 路并行 Fork、父编排器 + 每分片子工作流、舰队监视面、诚实纪律。参考实现 `agent-component-expansion-lab`，批量输入契约见 `docs/component-batch-spec.zh.md`。
>
> v2.2.0 变更：Agent App 收敛为**单一 `.vflow` 文件**模型，删除独立 `.app.json` 与独立 Agent App 包类型（§1、§4、§5、§11、§12 全面更新）。
>
> v2.3.0 变更：新增 DAG Shell / Node Capsule P0 合同。Shell 负责 Agent App 的全局 DAG 外壳、参数和 Event Panel 事件；Capsule 负责单个节点的内部编辑模型。Capsule 禁止内嵌 DAG，多步逻辑必须提升为外部 Subflow / WorkflowRun。详见 `docs/dag-shell-development-spec.zh.md` 与 `docs/node-capsule-development-spec.zh.md`。
>
> v2.4.0 变更：冻结 Agent App authoring canonical。AI 生成四类东西：Shell `logic` Event Panel、整条 Workflow Spec JSON、每个节点的声明式 `contract/resources/llmRuntime/samples`、每个节点的 `logic` Event Panel。Shell 和 Node logic 必须保存 Event Panel events/AST，不能保存 VL 字符串当真相；skills 全部内联到 `resources.skills[]`，不再新增 `skillRefs` 指针；evidence/artifact/error 属于 control plane 运行态，不进入作者层。Host 写入成功态前必须 fail-closed 校验：step `in/out` 满足 `contract.schema`、toolScope 是 app permissions 子集、WorkflowDryRun + Shell/Capsule dry-run 全通过。
>
> v2.5.0 变更：冻结 Agent App 身份与远端资源绑定模型。`appId` 是便携 Agent App 包身份；`flowId` 是 workflow 定义身份；`installationId` 是本机/当前用户安装身份；`environment` 固定为 `dev` / `test` / `prod`；`runId` 是单次执行身份。VL 平台 `gid` 与部署 `nid` 只属于运行/部署/资源绑定，不再作为 Agent App 源身份。`.vflow` 只声明逻辑资源需求；真实 `gid` / `nid` / AWS ARN / endpoint / bucket / DB / secret 绑定必须存放在安装态、control plane、平台 project state 或 host resource store，并以 `appId + installationId + environment` 为绑定键。
>
> v2.6.0 变更：冻结 Agent App Studio 的 Generate / Debug / Launch 三态信息架构。默认 workspace 聚焦当前 Agent App entry workflow；元工作流定位为 Resource Center / Generate Mode 中的版本化 Workflow Factory，不默认进入文件树；生成结果通过 Generation candidate + Adopt 显式交接；provenance 分为随 .vflow 可移植的轻量 lineage 与 control-plane 本地明细；regenerate 永远产出 candidate 并走 diff/merge；Debug / Launch 的 run、artifact、review 按 environment 隔离。
>
> v2.5.2 变更：冻结 Runtime Surface envelope 路由与 workflow-first 运行主导权，并对齐 SysDoc 发布版本。节点、工具和 HumanGate 只发 `assistantCard` / `vlSurface` / `log` / `artifact` / `externalPage` 结构化 envelope；Runtime Shell 统一决定 AI Chat、Detail Log、Runtime Floating Card / Runtime Tab 或 External Browser placement。running 态下 workflow 主导调度，人对 workflow 本体只执行 `pause` / `stop`；paused / stopped 后主导权交还给人，通过 resume 或 checkpoint rerun 再次启动。
>
> 单一 `.vflow` 文件模型（flow-as-App）：Agent App 现为**单一 `.vflow` 文件**——入口 workflow 携带顶层 `app` 块，**不再有独立的 `.app.json` 文件，也不再有独立 Agent App 包类型**。Manifest 在加载时由 `manifestFromFlow` 从该 `app` 块 + flow 的 `Pause` / `Review` 步骤派生。运行时发现链路（`discoverAgentApps` / `readInstalledAppsFromRegistry` / `resolveInstalledApp`）都从 flow 派生。落盘的 `.vl-code/registry/apps/<id>.app.json` 仅是派生缓存（可选），不是手写来源；`app.metadata.source='platform-builtin'` 用来标识内置 app。

> 文档收敛说明：
> 本文已经吸收原 `agent-app-agent-os-architecture.zh.md`、`app-pack-manifest-v0.1.zh.md`、`agent-app-layout-v0.1.zh.md`、`app-host-data-model-v0.1.zh.md`、`agent-os-vlcode-lite-convergence-plan.zh.md` 的核心定义与约束。
> 如果你的目标是“生成 / 开发 / 调整 Agent App”，默认只读本文，不需要再分散阅读多篇同主题文档。

## 0. Agent App Studio 三态与工作区信息架构（v2.6.0）

> 本节冻结 Agent App Studio 的默认用户心智与 workspace 信息架构。它补齐 v2.5 的身份/资源绑定模型与 Runtime Surface envelope 之后，开发态 IDE 应如何组织 **Generate / Debug / Launch** 三种动作。
>
> 核心原则：**默认只让用户面对当前正在开发的 Agent App workflow；元工作流是后台生成能力、版本化生成器与 provenance，不是普通项目源码。**

### 0.1 三个模式：Generate 生产，Debug 验证，Launch 运行

Agent App Studio 必须区分三个模式，它们可以共享同一份 `.vflow` / entry workflow 文件，但 UI 语义不可混淆：

| 模式 | 主要对象 | 用户心智 | 主要 UI / runtime surface |
|---|---|---|---|
| **Create / Generate Mode** | Workflow Factory / Generator（元工作流）与生成候选 candidate | “我要生成或再生成一个 Agent App workflow” | Generate 面板、AI Assistant 需求收集、Generation History、candidate diff/adopt |
| **Workflow Dev / Debug Mode** | 当前 workspace 的 entry workflow + authored subflows | “我正在开发、调试这个 Agent App workflow” | DAG / workflow editor、Inspector、Manifest、Runs、Node Results、Artifacts、Detail Log |
| **Launch / Runtime Mode** | 当前 app instance 运行态 | “我要以用户/app 视角运行这个 Agent App” | Agent App Runtime、AI Assistant runtime surface、HumanGate / Review cards、runtime artifacts |

**Launch 不运行元工作流。** Launch 的语义是：把当前 workspace 选中的 Agent App entry workflow 作为 Agent App 加载到 Runtime 中运行。Debug 是开发者视角，Launch 是 app/user 视角。

### 0.2 元工作流的定位

元工作流是 **Workflow Factory / Generator**：一种可版本化、可调试、可复用的生成流程。它的价值是标准化“怎样生成一个高质量 workflow”，而不是替代普通 workflow 本身。

元工作流在普通 Agent App workspace 中默认不作为源码暴露。它的默认归属是：

- Resource Center：Meta workflows、Templates、Skills、Agent prompts、Generator versions；
- Generate Mode：作为生成 driver / wizard 被运行；
- Generation History：作为 provenance 与审计入口；
- Generator Dev Mode：当开发者明确要调试生成器本身时，才像普通 workflow 一样打开、运行、调试。

生成完成后，主角是生成出来的普通 Agent App workflow。用户的默认心智应切换为：**“我已经有了一个新的 Agent App workflow，现在我要调试它。”** 而不是“我还在元工作流里面”。

### 0.3 Generate → workspace 的显式交接契约

元工作流运行完成后，不得把生成物以“魔法跳转”的方式混入当前 workspace。必须采用显式交接：

1. 生成器先产出一个命名 **candidate**，进入 Generation 面板 / staging 区；
2. candidate 可预览、校验、diff；
3. 用户执行 **Adopt as active workflow** / **Open as workspace** 后，candidate 才成为当前 workspace 的 active Agent App workflow；
4. Adopt 之后，Debug / Launch 都针对这个普通 workflow，不再依赖元工作流继续参与。

这条契约防止 Generate tab 同时承担“运行生成器”和“打开普通 workflow”两个互相冲突的语义。

### 0.4 工作区文件树边界：source 进树，runtime-derived 进面板

左侧文件树默认只展示当前项目的 **author-maintained source files**：

- entry workflow 文件；
- authored subflows；
- workflow 引用的资源文件；
- app/source resource；
- tests / samples / expected outputs；
- 用户明确保存下来的 spec、docs、prompt、schema。

以下内容默认不进入文件树：

- 元工作流副本；
- 每次 run 产生的临时 artifacts；
- 全量 run logs；
- control-plane 状态；
- 派生 manifest 快照；
- generation session 的完整上下文；
- node result / review / checkpoint 的运行事实。

这些内容必须进入专门面板：Manifest、Runs、Artifacts、Generation History、Node Results、Reviews。只有当用户明确执行 **Promote artifact to source** / **Save artifact into workspace** 时，artifact 才成为文件树里的 source。

设计公理：**author-maintained 的东西进文件树；runtime-derived / run-generated 的东西进面板。** 隐藏文件只是迁移期手段，终态应是 runtime-derived 内容根本不写进 workspace source tree。

### 0.5 Manifest 与 Agent App 源模型

普通 Agent App workflow 的 manifest 不应散成一堆手写独立文件。规范保持 v2.2 之后的 flow-as-App 模型：

- entry workflow 自身携带顶层 `app` block；
- manifest 视图由 workflow + `app` block + Pause / Review steps 派生；
- human gate / pause / review 信息属于 workflow steps；
- 大型资源、samples、prompts、schemas 可以作为引用文件存在 workspace；
- generation 时的 manifest 输入属于 generation session，默认不成为 app source。

### 0.6 Provenance 分层：可移植引用 vs 本地运行明细

元工作流运行记录必须保留，但它是 provenance，而不是普通项目源码。Provenance 分两层：

1. **轻量 lineage 引用（随 `.vflow` 可移植）**
   - generator / meta workflow id；
   - generator version；
   - brief 摘要；
   - source runId 或 generationId；
   - generatedAt；
   - 可选 input hash / candidate id。

   推荐写入 `app.metadata.generation` 或同等 metadata 字段。

2. **重型生成明细（留在 control plane / local host）**
   - 完整 generation session；
   - run logs；
   - node results；
   - intermediate artifacts；
   - review/check rows；
   - detailed lineage edges。

导出 `.vflow` 时必须保留轻量 lineage；重型明细不默认进入 bundle。

### 0.7 Regenerate / fork 规则：永不覆盖用户手改

如果 Debug 过程中发现生成结果结构不好，可以提供高级动作：

- Regenerate from original brief；
- Open generation session；
- Improve generator；
- Fork from generated workflow。

但 regenerate 不得 in-place 覆盖当前 workflow。规则：

1. Regenerate 永远产出新的 candidate；
2. 与当前 workflow 做 diff / merge；
3. 用户明确选择 adopt / merge 后才改变 active workflow；
4. 一旦当前 workflow 被用户手改，UI 必须标记为 **diverged from generator**；
5. diverged 后的 generator 链接默认降级为信息性 provenance，不再视为可直接再生源。

### 0.8 Debug / Launch 的 environment 隔离

同一个普通 workflow 可以：

- 在 IDE 里 Debug；
- 在 Agent App Runtime 里 Launch；
- 被 AI Assistant 修改；
- 被保存为新版本。

所有 run、artifact、review、node result 必须绑定 environment：

- Debug 默认使用 `dev`；
- Launch 可使用 `dev` / `test` / `prod`；
- Runs / Artifacts / Reviews 面板必须能按 environment 过滤；
- Launch 不应混入 Debug 的临时产物，Debug 也不应污染 prod runtime history。

### 0.9 Entry workflow + authored subflows，而不是僵硬的“只能一个 workflow”

日常 workspace 的默认 focus 是当前 Agent App 的 **entry workflow**，但这不等于 workspace 只能存在一个 workflow。Agent App 可包含 authored subflows 或 `app.workflows[]` 成员。

规则：

- 默认聚焦 entry flow；
- authored subflows 是 source，可以在文件树中显示，但应分组/折叠/弱化；
- runtime-generated child runs、temporary graph patches、checkpoint-derived flows 不默认进入文件树；
- UI 标签应尽量使用 `appId` / `flowId` / `installationId`，避免只用“主工作流”这种模糊说法。

### 0.10 AI Assistant 上下文指示

AI Assistant 在三个模式下承担不同角色：

- Generate：收集需求、运行 generator、产出 candidate；
- Debug：处理 HumanGate、Pause、Review、修改建议、rerun node；
- Launch：作为 Agent App runtime 的交互入口。

同一个 chat surface 必须显式显示当前上下文，例如：

- `Generating: <candidate>`；
- `Debugging: <appId> / run <runId> / env dev`；
- `Live App: <appId> / instance <installationId> / env prod`。

上下文必须随 mode 切换和 run/instance 切换同步，避免用户不知道自己在和哪个 run 或哪个 app 对话。

### 0.11 面板收敛

右侧面板按模式收敛，不应把所有面板在所有模式下常驻：

| 模式 | 默认面板 |
|---|---|
| Generate | Generation、Brief、Candidates、Generator provenance |
| Debug | Inspector、Manifest、Runs、Node Results、Artifacts、Detail Log |
| Launch | Runtime Surface、Reviews、Runtime Artifacts、Instance status |

Manifest 和 Artifacts 可以作为 resident tabs / floating windows 复用，但显示内容必须受当前 mode、environment、selected object 限定。

### 0.12 反模式补充

以下是 Agent App Studio 信息架构层面的反模式：

- 不要把元工作流副本默认写进每个 Agent App workspace；
- 不要把 generation session 的完整上下文当作 app source；
- 不要把 run logs / node results / artifacts 混入文件树；
- 不要在 Launch 时运行 generator；
- 不要 regenerate 后直接覆盖用户已手改的 workflow；
- 不要把 Debug artifacts 和 Launch/prod artifacts 混在一个未分环境的列表里；
- 不要让 AI Assistant 缺少当前 mode/run/app 上下文；
- 不要把“隐藏内部文件”当作长期架构，终态必须减少写入，而不是写了再藏。

---

## 1. 定义与术语

### 1.1 Agent App 是什么

Agent App 是 **runtime-first 的可安装、启动、暂停、恢复、审计的应用运行时实体**。

它**不是**：
- 一堆生成的代码文件
- 一个手写的 HTML 页面
- 一个独立的 Node.js 服务

它**是**：
- 由 Manifest 定义 → Workflow Engine 执行 → Control Plane 持久化 → VL 渲染展示的完整运行时闭环
- 可以在本地运行，也可以投放到云端
- 生命周期由 Agent-OS Kernel 管理

### 1.2 与普通 VL 项目的区别

| 维度 | 普通 VL 项目 | Agent App |
|------|-------------|-----------|
| 执行模型 | compile-first（编译 → 部署） | runtime-first（安装 → 运行） |
| 入口 | 编译后的静态页面 | Workflow 定义 或 Service Runtime |
| 分发 | 编译产物（JS/CSS/HTML） | App Pack manifest + 源定义 |
| 生命周期 | 单次构建 | Pack → Release → Instance，支持升级/回滚 |
| AI Chat | 可选附加 | 一等公民，每个实例有独立 AI 控制台 |
| 状态管理 | 页面级 | Control Plane SQLite 持久化 |
| Actor 模型 | 无 | 一等公民：人/AI/子 Agent/外部 Worker 均为受控 Actor |
| 隔离 | 全局 workspace | 实例级隔离：workDir, secretScope, resourceNamespace |

### 1.3 核心术语

| 术语 | 定义 |
|------|------|
| **App Pack** | 可安装的能力包。携带顶层 `app` 块的入口 `.vflow`；manifest 由 flow 在加载时派生，无独立 `.app.json` 或独立 Agent App 包 |
| **appId** | Agent App 的便携包身份，来自入口 workflow 顶层 `app.id`。它必须稳定、英文/URL-safe，进入 catalog、bundle manifest、app home、release id 和权限边界 |
| **flowId** | workflow 定义身份。它描述“这条执行定义是谁”，和 `appId`、`entryWorkflow`、`workflow.name`、文件 stem、catalog `sourceFlow` 都不是同一件事；缺省可由 `app.flowId` / `workflow.id` / workflow key 派生，但落盘后必须稳定 |
| **installationId** | 当前用户/本机对某个 `appId` 的持久安装身份。它不进入便携 `.vflow`，用于把本地配置、云资源、secret scope、runtime namespace 和升级/卸载边界关联起来 |
| **environment** | 资源绑定维度，固定取值 `dev` / `test` / `prod`。同一 `appId + installationId` 可以在不同 environment 绑定不同平台/AWS 资源 |
| **runId** | 单次 workflow 执行身份，属于 Runtime Plane / control plane，不等于 App Instance 或 installation |
| **gid** | VL 平台 workspace/resource/work group ID，只能作为运行/部署/资源绑定事实，不是 Agent App 源身份，也不能写成“一个 Agent App = 一个 GID”的规则 |
| **nid** | VL 平台 work/deployed app ID，通常来自 `.vx` 前后端部署绑定，只能作为运行/部署事实，不是 Agent App 源身份 |
| **App Release** | 冻结的版本快照。ID = `appId@version` 或带内容哈希的 release id；release 不携带本机 installation 绑定 |
| **App Instance** | 运行中的实体。有独立 status / config / artifacts / control-plane namespace。Instance 可以引用 `installationId`，但不能替代 `installationId` |
| **entryWorkflow** | 入口工作流引用。**每个 Agent App 必须有**，用于定位 `.vl-code/workflows/<name>.json` 或 `.vflow` 内 `workflow/main.json`；它是入口路径/引用，不是 `flowId` |
| **Surface Mode** | 展示模式：headless / console / visual / hybrid |
| **ResultEnvelope** | 统一节点输出契约。含 status / artifacts / evidence / metrics |
| **HumanGate** | 人类决策节点。暂停执行 → 展示 → 等待 approve/reject/request_changes |
| **Control Plane** | 事实持久层。`.vl-code/control-plane.sqlite` |

### 1.4 与 Workflow / Chat / Run 的边界

这次口径需要再收紧一层，避免后续把 `Agent App` 简化错：

| 对象 | 它不是什么 | 它是什么 |
|------|-----------|---------|
| **Workflow Definition** | Agent App 本体 | 可复用执行定义，描述步骤、Actor、tools、review、output |
| **Workflow Run** | App Instance | 某次执行记录，属于 control plane 的事实层 |
| **AI Chat Box** | App AI 本体 | 一个可复用 UI 组件，用来承载输入、消息流和控制动作 |
| **App AI / App Chat Session** | 全局聊天页签 | 某个 `appId + instanceId` 绑定的上下文、控制台和解释层 |
| **Agent App** | 单个 workflow JSON、单次 run、单个 service | `Pack → Release → Instance` 的运行时闭环，workflow 是其执行平面 |

需要固定三条规则：

1. `Agent App ≠ Workflow Definition`
2. `Agent App ≠ Workflow Run`
3. `App 级 AI Chat ≠ 宿主级全局聊天`

因此，一个 Agent App 的最小闭环应被理解为：

> `App Pack + App Release + App Instance + entryWorkflow + app-scoped AI + control plane + optional VL/service surface`

### 1.4.0 Development Plane / Runtime Plane

Agent App 从本节开始固定为两个平面，后续生成器、Runtime Tab、Control Plane 和 VLC 接入都必须按这个边界建模：

| Plane | 中文口径 | 代表对象 | 说明 |
|------|----------|----------|------|
| **Development Plane** | 开发态 | App Pack、App Release、Manifest、entryWorkflow、VL surface template、配置 | 定义“这个应用应该如何运行”，相当于代码和发布资产 |
| **Runtime Plane** | 运行态 | App Instance、Workflow Run、Runtime Graph、Node Result、Artifact Lineage、Surface State | 表达“这个应用此刻真实运行成了什么样”，相当于活的现场状态 |

稳定规则：

1. `Workflow Definition` 属于开发态执行定义，不等于运行态现场。
2. `Workflow Runtime Graph` 是 Workflow-Engine 提供的通用运行态快照能力。
3. `Agent App Runtime Projection` 是 Agent-OS 把 engine snapshot、control-plane facts、planner/convergence state、artifact/surface 事实聚合后的宿主级快照。
4. Planner / Goal Convergence 是一种 host-owned 策略层；它可以投影成 Runtime Plane，但不等于 Runtime Plane 本身。
5. Agent App UI 和 VLC 不直接拼 ledger、SQLite 或 checkpoint；它们消费 Agent-OS projection API。

跨项目升级路线见 `docs/agent-app-runtime-graph-upgrade-plan.zh.md`。

### 1.4.1 Agent App 身份与资源绑定模型

Agent App 必须同时支持便携分发和真实云资源绑定，因此身份分为 **Source Identity**、**Install Identity**、**Runtime Identity**、**Platform Binding** 四层：

| 层 | 字段 | 存放位置 | 规则 |
|---|---|---|---|
| Source Identity | `appId`, `flowId`, `version`, `entryWorkflow` | `.vflow` / 入口 workflow 顶层 `app` 块 / 派生 manifest | 可随包分发；不得包含当前用户真实资源绑定 |
| Install Identity | `installationId`, `environment` | app home / `.vl-code/project.json` / install state / host resource store | 本机/当前用户持久；用于资源绑定、secret scope、升级/卸载边界 |
| Runtime Identity | `instanceId`, `runId`, checkpoint id | control plane / runtime projection | 单次启动或执行现场；不得反向写入 source bundle |
| Platform Binding | `gid`, `nid`, AWS ARN, endpoint, bucket, DB, service account | control plane / platform project state / host resource binding store / SecretRoot | 真实外部资源；不得作为 Agent App 源身份 |

硬规则：

1. `appId` 来自 `app.id`，是 Agent App 包身份；`flowId` 是 workflow 定义身份，推荐来自 `app.flowId`，否则由 `workflow.id` / workflow key 稳定派生。`entryWorkflow` 只是入口引用，不是 `flowId`。
2. `installationId` 是安装态身份，创建 app home 或导入 `.vflow` 时生成并持久化；升级同一安装时保持不变；另一次安装同一 `.vflow` 应得到不同 `installationId`。
3. `instanceId` 只描述某个 runtime instance，不得拿来当安装身份；旧代码中不同 namespace 的 `instanceId` 必须在投影层显式标注，不能继续扩大混用。
4. `gid` / `nid` 只能来自平台 project state、部署结果或资源绑定记录。普通 VL 项目的 `Config/project.state.json` 由 parser 维护，记录 project `gid`、backend binding、frontend `nid`；这不改变 Agent App `.vflow` 的便携身份模型。
5. 资源绑定键固定为 `appId + installationId + environment`。同一个 `appId` 可以被多个用户/机器安装；同一安装可分别绑定 `dev`、`test`、`prod` 资源。
6. `.vflow` 可以声明 `app.cloud.requirements[]` 和 `app.cloud.bindingPolicy`，描述“需要什么资源”，但不能保存真实 `gid` / `nid` / AWS ARN / endpoint / bucket / DB / secret。示例值必须明确标为 example/template，不能被运行时当成已绑定资源。
7. Host 在运行前按 `appId + installationId + environment` 解析绑定；缺绑定时应明确进入待绑定状态或交互卡片，不能静默创建、静默 fallback 到别的 GID，或把失败伪装为成功。

推荐的 `app.cloud` 作者层声明形态：

```jsonc
{
  "app": {
    "id": "expense-review-agent",
    "flowId": "expense-review-main-flow",
    "cloud": {
      "bindingPolicy": "required-before-run",
      "environments": ["dev", "test", "prod"],
      "requirements": [
        { "id": "vl-workspace", "provider": "visuallogic", "type": "workspace", "purpose": "store generated VL preview project" },
        { "id": "report-bucket", "provider": "aws", "type": "s3-bucket", "purpose": "store generated audit reports" }
      ]
    }
  }
}
```

### 1.4.2 Agent App `.vflow` 的 bundle 包含关系

Agent App 的导出、导入、安装统一使用带顶层 `app` 块的 `.vflow`，不再定义独立 Agent App 包类型：

1. Agent App `.vflow` **必须包含入口 workflow 定义和顶层 `app` 块**，因为当前 Agent App 的执行平面就是 `entryWorkflow`
2. Agent App `.vflow` **可以包含一个或多个 `.vl`**，用于：
   - app 自带卡片与 VL surface
   - app 专属组件、页面、主题或模板工程
   - app 运行时需要的 visual assets
3. `.vl` 是叶子 bundle，可以带 `.js / .py` helper，但不应反向包含 `.vflow`
4. `.vflow` 是 Flow Editor 的原生 bundle 单元，应该支持直接打开、编辑、保存和另存为。
5. 人工输入入口应建模为 manifest / runtime inputs，而不是写死在 workflow JSON 里。
6. 运行时 artifacts、checkpoint、review packet、run ledger 仍属于 control plane / snapshot 层，不应默认写回 bundle 本体。

建议理解为：

```text
.vflow
  ├─ required: workflow definition + top-level app block
  └─ optional: >= 0 x .vl
```

这里的“包含”优先指逻辑包含，不强制采用 zip 套 zip；更推荐在 `.vflow` 内用展开目录 + 子 manifest 表达内部 workflow / `.vl` 单元。

### 1.4.3 App Chat / Control Plane / VL Surface 的运行边界

有了 `VLPreviewer` 和 runtime VL surface 后，Agent App 的三层职责必须固定：

| 层 | 负责什么 | 不负责什么 |
|----|----------|------------|
| **App Chat** | 意图入口和控制器：`/surface`、`/preview`、`/inspect`、`/screenshot`、重跑、解释、提交 review | 不承载真实业务 UI，不作为数据事实层 |
| **Control Plane** | 事实和证据：run、node result、preview session、截图 artifact、review decision、lineage | 不渲染业务界面，不把临时 UI 当成源文件写回 bundle |
| **VL Surface / VLPreviewer** | App 的视觉运行面：卡片、表单、看板、审批台、业务数据页、AI 临时生成的表格/图表/页面 | 不替代 control plane 的审计、权限、运行账本 |

因此，Agent App `.vflow` 的推荐模型是：

1. `.vflow` 是执行平面，负责 workflow / actor / tool 调度。
2. `.vl` 是视觉与业务运行面，���以随 app 一起打包，也可以由 AI Chat 临时生成 runtime surface。
3. `Process/AppInstances/**/Surfaces/**` 是运行时临时 VL surface 的默认落点；只有显式 promotion 才写入 workspace 源文件。
4. `run ledger`、checkpoint、preview evidence、review packet 仍留在 control plane，不默认写回 `.vflow`。

### 1.4.4 Agent App Runtime Layout 标准

Agent App 的运行时界面必须以 workflow 为中心，VL surface 和 AI Chat 都是浮层控制/展示面，不能反过来挤占 DAG 主窗口。

标准布局由 **5 个原语** 组成（z-order 从低到高）：

| 区域 | 原语 | 角色 | 规则 |
|------|------|------|------|
| **A. 顶部 Top Bar** | `topbar` (host z=110) | Manifest 触发、`AppName + version`、少量摘要、workflow/instance 选择器、刷新、VL Preview | 高度固定 `48px`；只承载身份与全局控制，不承载业务内容；不得展示冗余 `Agent App` 标签或长 release pill |
| **B. 主体 DAG Runtime Window** | `dag-canvas` (z=1) | Agent App 的核心运行窗口 | 整个主区域默认属于 workflow DAG；节点状态、运行事件、checkpoint、rerun 高亮都进入这里；**绝不能被布局列切走** |
| **C. 左滑 Manifest Inspector** | `manifest-inspector` (host z=130) | Node-IO-first 资源图谱：外部文件、每个节点输入/输出、Meta/VL 产物、子工作流、actors/surfaces，以及 raw snapshot | 默认收起；从左侧边缘拉出；优先展示“跑这个流需要什么、节点读什么、节点写什么”；`Raw` 分组默认折叠 |
| **D. 右下 AI Chat + Detail Log** | `chat-float` (host z=120 / 119) | 意图入口、控制器、解释层、详细日志 | 可拖动 / 可收起为 AI 图标；Chat 标签页承载总结、问题、HumanGate、artifact 入口；Detail Log 标签页承载完整步骤/工具/run ledger |
| **E. VL Floating Cards / Modal** | `vl-float` (host z=25 / active=35) 浮层；`modal` (host z=150) 最高层 | manifest 预定义 VL UI、AI 运行时生成的表格/图表/表单/页面、preview evidence、HumanGate 决策窗 | 以浮层卡片出现，和 DAG 暗色底层协调；manifest 固定卡片不可永久关闭，只能收起；runtime 临时卡片可关闭并保留必要 evidence |

层级规则：

1. DAG 是底层主画布（z=1），**不应被布局列或栅格切走**。详见 §1.4.3.4 反例。
2. VL card 位于 DAG 之上（host z=25 / active=35），默认是浮层卡片，**不是主布局的一列**。
3. AI Chat / Detail Log 位于 VL card 之上（host z=120 / 119），用于控制和调试。
4. Manifest Inspector 是左侧边缘拉出面板（host z=130），独立于主区域，不挤压 DAG 宽度。详见 §1.4.3.5。
5. modal / confirmation / HumanGate 决策窗口位于最高层（host z=150）。
6. `surface.presentation.preview` 声明的 VL UI 默认生成 manifest card；`vl.surface.*` 运行时生成的 UI 默认生成 runtime card。
7. workflow 运行卡片、节点卡片、artifact 卡片和 HumanGate 卡片默认进入 Chat 对话流；需要长期占位的业务 UI、图表、表格和大表单进入 VL floating card 或 Large App Page。
8. Top Bar 或左边缘拉手是 Manifest Inspector 的触发入口；不得新增左侧常驻栏或把 Inspector 做成第二主画布。

#### 1.4.4.0 Reference Shell UI 冻结规则

从 `VL DeepSeek Training Data Factory` 这类 DAG-first Agent App 开始，后续生成器必须默认采用以下 shell UI 口径：

1. 顶栏只保留 `☰ Manifest`、`AppName + vX.Y.Z`、少量摘要 pill、workflow selector、instance selector、refresh、VL Preview。不要再单独显示 `Agent App`、长 `Release app@version`、重复 app id、重复 Cards/Floating/Pages 计数。
2. 摘要 pill 最多显示 2-3 个高价值项；推荐 `Surface: 2C / 2F / 2P` 与 `Run: <runId|none>`。更多运行事实进入 Detail Log 或 Manifest Inspector。
3. workflow selector 必须允许开发者在 entry workflow、child workflow、codegen workflow 等相关 DAG 之间切换；切换 workflow 时必须清空/关闭上一张节点详情，避免拿旧 checkpoint 或旧节点做误导性 rerun。
4. 绿色 `Run` 按钮属于 workflow editor 的视觉入口，但在 Agent App shell 中必须委托给 shell-owned run input card/modal；不要让 iframe 内部直接用空 params 静默启动。
5. 右侧节点详情抽屉用于放大被点击节点，必须显示完整输入文件/Specs、输入变量来源、输出文件/变量、child workflow、LLM messages、raw node。它是开发者排查区，不是业务页面。
6. AI Chat + Detail Log 继续作为右下浮层，不得塞进主布局栅格；Detail Log 承载完整事件，DAG 只显示状态高亮。

#### 1.4.4.1 Runtime Surface 分级与交互规范

Agent App 运行态必须把可视区域分成三类 surface，生成器和人工开发都按这个分级选择承载位置：

| Surface 类型 | 默认位置 | 标准尺寸 | 放什么 | 不放什么 |
|--------------|----------|----------|--------|----------|
| **AI Chat Card** | 右侧/右下浮层中的 Chat 对话流，最高控制层 | 展开宽 `360-520px`，高 `420-980px`；可收起到 AI 图标 | 用户意图、HumanGate 输入、审批问题、运行摘要、短节点卡、错误摘要、最终答案、artifact 入口 | 每个节点的变量 dump、完整 LLM token stream、长期业务大表单、长报表 |
| **Detail Log** | Chat 旁边的可开合浮层 | 宽 `320-380px`，高度跟随 Chat | workflow start/done/error、node start/done/error、tool input/output、file writes、变量变化、LLM usage、retry/warning、SSE relay | 新的业务 UI、普通用户必须阅读的最终结论 |
| **VL Floating Card** | DAG 上方浮层 | 默认 `560x560`，最小 `300x220`，折叠 `280x44`，最大不超过主画布 `70vw/70vh` | manifest preview、runtime 生成的表格/图表/表单、小仪表盘、preview evidence | 长时间占满主区域的大工作台、运行日志、权限确认 |
| **Large App Page** | 顶部 runtime tab / app page tab 切换 | 使用完整 DAG 下方主画布或独立 app page，不再塞进小卡片 | artifact gallery、长报告、数据表、可视化编辑器、审计台、需要持续阅读/操作的大页面 | 临时提示、一次性确认、短表单 |

交互规则：

1. AI Chat、Detail Log、VL Floating Card 都必须支持 header 拖动；点击按钮、输入框、iframe、resize handle 时不得触发拖动。
2. 浮层允许局部拖出浏览器边界，但必须至少保留约 `96px` 横向可见区域和 `56px` 纵向可见区域；顶部 header 默认不允许完全拖出，以保证可拖回。
3. `Collapse / Expand / Close` 第一次点击必须立即生效，不能先进入选中态或被 drag handler 吃掉。
4. `Run` 按钮触发 workflow 后，Chat 立即出现运行摘要卡，Detail Log 立即打开并记录请求；后续短卡片进入 Chat 对话流，节点、文件、工具、变量和 LLM 详细事件进入 Detail Log，DAG 只负责高亮状态。
5. 需要人工辅助输入时，使用 AI Chat 中的 HumanGate / InteractiveCard；不要使用浏览器 `prompt()`、新窗口或外部页面。
6. 刷新页面后，Detail Log 必须能从 run ledger / control-plane 的 `/api/workflow/run-state` 恢复最近一次运行历史；Chat 里的 transient 卡片可以随消息流滚动消失，但 control plane 事实不可丢。
7. manifest 固定 card 默认不可永久关闭，只能收起；runtime 临时 card 可以关闭，但 control plane 仍保留 evidence/resource 记录。
8. 大页面必须通过 runtime 顶部 tab 或 Agent App 内 page tab 切换，不得用多个巨大浮层堆叠遮挡 DAG。

#### 1.4.4.1A Runtime Surface 路由契约（节点只发结构化 envelope）

VL（前端或前后端一体）可以参与 Flow 运行时的全部交互——展示、表单、审批、选择、确认、回传、preview——但**节点不直接决定 UI 容器**。节点只声明一个结构化 surface envelope，由 **Runtime Shell 统一决定最终落点**。这条契约是 §1.4.4.1 分级表的底层路由规则，生成器和人工开发都必须遵守。

**Surface Envelope（节点 → Host 的唯一出口）：**

节点（workflow step / tool / human-gate）向运行时投递的内容统一是一个 envelope，字段固定为：

| 字段 | 类型 | 说明 |
|------|------|------|
| `kind` | `"assistantCard" \| "vlSurface" \| "log" \| "artifact" \| "externalPage"` | 内容类型，决定语义而不是位置 |
| `channel` | `"assistant" \| "runtime" \| "log" \| "external"` | 期望通道；只是**意图**，Runtime Shell 可按策略覆盖 |
| `placementHint` | `"assistantCard" \| "runtimeTab" \| "floatingCard" \| "detailLog" \| "externalWindow"` | 可选放置建议，非强制 |
| `surface` | object | `kind=vlSurface` 时承载 `type/bundleRef/entry/props`；其它 kind 承载对应 payload |
| `interaction` | object | 可选；声明回传需要的 `submit/action/selection/resolveInteract` 形状 |

节点**不得**直接持有 DOM、window、tab 句柄，也不得在 payload 里写死 `tab/modal/sidebar` 等容器实现。

**Runtime Shell 路由规则（Host 唯一决定 placement）：**

| envelope `kind` | 默认通道 | 默认承载位置 | 升级/降级策略 |
|-----------------|----------|--------------|----------------|
| `assistantCard` | `assistant` | AI Chat 对话流 | 仅短交互；字段/行数超阈值时 Shell 自动改投 `floatingCard` |
| `vlSurface` | `runtime` | VL Floating Card；声明 `largePage` 时进入 Runtime Tab | 永不进 AI Chat；永不被布局栅格切走 |
| `log` | `log` | Detail Log | 永不进 AI Chat 主流，除非是 `node_error/workflow_error/human_gate` 摘要（见 §6 投递表） |
| `artifact` | `runtime` | Detail Log 入口 + VL Floating/Tab 预览 | evidence 始终落 control plane |
| `externalPage` | `external` | External Browser Page（escape hatch） | 必须声明通信协议，否则校验失败 |

硬规则：

1. **节点声明意图，Host 决定位置**。`channel` / `placementHint` 是建议；最终 placement 由 Runtime Shell 按本表和 §1.4.4.1 尺寸/分级规则裁决，节点不能假定自己被渲染在哪。
2. **VL 业务运行面默认进 Runtime（Floating Card / Tab），不进 AI Assistant。** AI Assistant 不是业务 UI 容器，只承载对话型短交互（确认、审批、短表单、HumanGate、运行摘要、最终答案、artifact 入口）。
3. **Detail Log 只承载结构化日志事实**（节点/工具/变量/文件/LLM/retry/SSE），不渲染新的业务 UI，不放普通用户必须阅读的最终结论。
4. **External Browser 仅是逃生通道**：只有当完整 app 无法在 Runtime Tab 内承载时才用，且 envelope 必须声明 host↔page 通信协议（`postMessage` 通道 + 回传事件名）；否则按 `externalPage` 校验失败处理，不允许静默打开裸窗口。
5. **VL Previewer 是所有 `vlSurface` 的唯一渲染入口**，Host 不得绕过 VL 另写业务 UI。
6. 节点回传只能走 envelope 的 `interaction`（`surface.submit/action/selection/cancel/resolveInteract/requestRun`）；VL UI **不得**直接写 workflow state 或 node result，必须经 Host 治理后回灌 control plane。
7. envelope 路由结果必须可审计：每次 placement 决策、materialize、close 都进 Detail Log / control plane，Manifest Inspector 显示 declared vs materialized 差异（见 §1.4.4.5）。

最小 envelope 示例：

```jsonc
// VL 业务面 → 默认 Runtime Tab（节点不指定容器实现）
{ "kind": "vlSurface", "channel": "runtime", "placementHint": "runtimeTab",
  "surface": { "type": "vl", "bundleRef": "artifact://...", "entry": "Apps/Main.vx", "props": {} },
  "interaction": { "submit": { "fields": ["decision", "note"] } } }

// 短确认 → AI Chat
{ "kind": "assistantCard", "channel": "assistant", "title": "需要确认", "actions": ["yes", "no"] }

// 结构化日志 → Detail Log
{ "kind": "log", "channel": "log", "level": "info", "message": "VL preview rendered" }
```

#### 1.4.4.1B Workflow-first 运行时主导权

VLC、VL Agent、Agent App runtime 的核心运行逻辑统一为 **workflow-first**：

1. 人选定一个工作流让它运行；**工作流自身是完备的，是运行期的控制主导**。运行时所有调度、分支、回传请求都由工作流发起，人不在运行中途随手改流程。
2. **运行中（running）人对流本身只能 `pause` 或 `stop`。** 其它一切交互（填表、审批、选择、回传）都是在响应工作流通过 surface envelope 发起的请求，而不是人主动改流。
3. **暂停 / 停止后主导权交还给人。** 此时人可以：编辑节点数据、调整节点、设定终止条件、设置回传 / 交互信息，然后**再次启动**（resume 或从 checkpoint rerun）。
4. 人的编辑只改定义/输入与下一次运行的入参，遵循 §1.4.4.9 的 shell-owned run 与 checkpoint rerun 协议；不得在 running 态绕过工作流直接改 node result 或 control-plane 事实。
5. 运行控制命令（pause/resume/stop/rerun/状态查询）统一经 AI Assistant operator 通道或 shell 控制入口下发，事件同步到 DAG 状态、Detail Log 与 Run card（见 `docs/agent-app-operator-spec.zh.md`）。

#### 1.4.4.4 反例：禁止把 DAG 放进 2×2 栅格

**不要**把 DAG 作为 2×2 / 3×3 栅格中的一个单元格。DAG 是主画布，其他元素全部是浮层 / 滑入 / 顶栏。

错误示例（历史上曾出现过，已被本规范反对）：

```
┌────────────┬────────────┐
│ Workflow   │ Manifest   │
│ DAG        │ / Core Data│
├────────────┼────────────┤
│ AI Chat    │ Artifacts  │
│            │ / Run Log  │
└────────────┴────────────┘
```

典型后果：

1. DAG 被压缩到 1/4 视野，节点文字看不清、checkpoint / rerun 高亮失效。
2. Manifest / Core Data / Artifacts 占据半屏，但这些是调试信息，不是普通用户该持续看的内容。
3. AI Chat 固定在左下格，不能拖动、不能收起。

正确形态：

1. DAG 占满 `viewport - topbar` 的全部区域。
2. Manifest 信息收进左滑入 Manifest Inspector，默认收起。
3. Runs / Tasks / Artifacts 收进 AI Chat 的 **Detail Log** 标签页。
4. AI Chat 是右下可拖动浮层，而不是栅格单元。

#### 1.4.4.5 Manifest Inspector 规范

Manifest Inspector 是 Agent App runtime shell 的第 5 个原语，承担 **"规划 vs 实际"** 的资源图展示职责。

**默认分组顺序（自上而下）：**

| 分组 | 数据源 | 必需字段 |
|------|--------|----------|
| External Files | `metadata.executionManifest.externalFiles[] / workflowFiles[] / providerRouting / defaults.params` | SysDoc specs、workflow refs、provider/model routing；必须能看出每个 LLM 节点依赖的规范来源 |
| Node IO | loaded workflow JSON + selected workflow refs | 每个 workflow 节点的 title、input files/specs、input vars origin、outputs、child workflow；这是排查主视图 |
| Meta And VL Outputs | `metadata.executionManifest.metadataFiles[] / outputFamilies[] / dataset` | Meta 文件路径、VL 输出族路径、dataset root、project count、repair rounds、lint before compile |
| Subflows And Actors | `manifest.actors / permissions.tools / workflow child refs` | main flow、child review flow、codegen flow、actors、tools、network |
| App Pack Details | `manifest.id / version / entryWorkflow / runtimeLayout / requiredPanels / ports` | app id、title、entry workflow、DAG route、required panels、runtime ports |
| Surfaces | `surface.interactionContract.cards[] / surface.presentation.surfaceContract.*` | interaction cards、floating cards、large pages、declared/materialized surfaces |
| Raw | `manifestSnapshot / coreData / vlSource` | 默认���叠；开发者可展开查原始 JSON / VL 源文件 |

**Node-IO-first 展示规则：**

1. Manifest Inspector 的首屏目标是回答三个问题：`运行需要哪些外部文件？`、`每个节点输入什么？`、`每个节点输出什么？`
2. `Metadata Files` 和 `VL Output Families` 必须显示为路径树，不要在每一行重复 `generated artifact`、`ProjectMeta / MetaLayer contract` 这类低信息密度描述。
3. LLM 节点必须能看出 `SysDoc` 规范绑定、model/provider、messages 输入；如果 messages 很长，节点详情抽屉里展开，树上只显示摘要。
4. 子 workflow 必须显示为可跳转引用；跳转后 selector 与 DAG 同步，旧节点详情关闭。
5. 业务 app 的 Surface 信息可以往后放。Manifest Inspector 不是视觉展示页，优先级低于 Node IO 与 Meta/VL 输出。

**Lifecycle 标记规则：**

| dot | 含义 | 典型场景 |
|-----|------|----------|
| `● active` 绿色 | 资源已 materialized / 运行中 | instance 已打开对应 surface / 当前 run 正在执行 |
| `○ planned` 灰色 | manifest 声明但尚未实例化 | 冷启动 / 未触发的卡片 |
| `◐ idle` 暗灰 | 已 materialized 但当前空闲 | 关闭的 surface / 完成的 run |
| `◉ error` 红色 | 实例化失败 / run 报错 | 需要用户干预 |

**Position / Size 标记：**

1. 每个资源必须显示 `chip` 形式的 **kind + size + persist** 标签组（例：`card · 560×560 · persist`）。
2. Interaction Card 显示 `uiSurface`（modal / review / chat-card）作为 position；Floating Card 显示 `width×height`；Large Page 显示 `full-viewport`。
3. Materialized Surface 可点击打开对应 `previewUrl`；未 materialized 的卡片不可点击。

**交互规则：**

1. 默认收起。左侧边缘拉手、顶栏 `☰ Manifest` 按钮或 `M` 快捷键切换开合。
2. 展开宽度 `420px`（`max-width: 92vw`）。移动端宽度降至 `320px`。
3. 滑入动画 `220ms ease-out`。
4. `Esc` 键关闭。点击 `×` 关闭。
5. **不承载业务 UI**——Manifest Inspector 只读规划/事实，写操作（触发卡片、关闭 surface）仍走 AI Chat。

**模版冻结（Template Freeze）条款：**

Agent App 的用户体验靠"**冻结的 VL 模版 + 随机的运行时内容**"来保证一致性：

1. `surface.presentation.surfaceContract.floatingCards[]` 和 `largePages[]` 声明的 `id / kind / defaultViewport / route` 是**冻结契约**——一旦 pack 发布，runtime 只能填充内容，不能变形。
2. 同理，`surface.interactionContract.cards[]` 的 `id / kind / uiSurface / fields schema` 是冻结的；AI 只能填充字段值或决策。
3. 新增 runtime surface 必须走 `vl.surface.*` 临时生成通道，并明确标记为 `runtime-generated`；不得伪装成 manifest 声明的 surface。
4. VL Previewer 是所有 VL surface 的唯一渲染入口——host 不得另写业务 UI 绕过 VL。
5. 如果运行时内容超出模版尺寸（表格行数膨胀、图表数据增多），允许模版内部滚动，但**不得**改变外部 `defaultViewport`。
6. Manifest Inspector 必须把 declared vs materialized 的差异清楚展示——这是冻结契约的可视化审计。

#### 1.4.4.6 三层 UI 解析（ViewKit / Factory / Universal）

`surfaceContract.floatingCards[]` 和 `surfaceContract.largePages[]` 声明的是**契约**，不是最终 VL。host 在运行时按以下三层顺序解析要渲染的 UI：

| 层 | `resolver` 值 | 含义 | 速度 | 目标覆盖率 |
|----|--------------|------|------|-----------|
| 1 | `viewkit` | Manifest 预注册的 VL UI，存放在 `.vl-code/registry/viewkits/` | 即取即用 | ~80% |
| 2 | `factory` | Component Factory 按需安装的专用控件 | 秒级 | ~15% |
| 3 | `universal` | 通用 JSON→VL 兜底（`universal-json` viewkit） | 即取 | ~5% |

关键纪律：

1. **Component Factory 的速度担忧必须在工厂期解决**——P3 `TargetManifestPlan` 阶段必须把 `DependencyManifest.components[]` 里的所有条目**预解析并缓存**，不允许把 install 延迟留到运行期。
2. `resolver: "viewkit"` 时，`viewKitRef` 字段必需（形如 `"upload-simple@0.1.0"` 或 `"vl.viewkit/upload-simple"`）。
3. `resolver: "universal"` 永远可用，是所有未知形状数据的默认兜底。
4. ViewKit 查找由 `src/core/viewkit-registry.js::resolveViewKitRef(workDir, ref)` 执行。

ViewKit 条目的字段定义见 `.vl-code/registry/viewkits/_schema/viewkit-manifest.schema.json`；目录索引见 `viewkit-catalog.json`。

**当前实现状态（2026-04-25 / v1.43.1）：**

1. `resolver: "viewkit"` 的 manifest 字段校验、runtime-console 保真、Manifest Inspector 展示、waiting-human host dispatcher 已接入；dispatcher 当前使用 host 表单/上传控件承载 ViewKit contract，而不是直接 mount VL 组件。
2. `resolver: "factory"` 仍是 P1：`DependencyManifest.components[]` 的工厂期预解析/预安装尚未接入 host runtime。
3. `resolver: "universal"` 仍是 P1：`universal-json` 的真实 VL universal renderer 组件尚未落地，host 仍会退到通用表单/JSON fallback。
4. `vlSource.mode: "component-ref"` 目前是登记字段，host 尚未直接 mount `VlUpload / VlGenericForm / VlDataTable` 等组件。

#### 1.4.4.7 floatingCards / largePages 契约字段

在原有 `id / title / kind / route / mode / width / height / source / preview / metadata` 的基础上，Surface Contract 条目可声明以下**可选**字段：

| 字段 | 适用 | 类型 | 说明 |
|------|------|------|------|
| `resolver` | floatingCards | `"viewkit" \| "factory" \| "universal"` | 指定走三层解析的哪一层 |
| `viewKitRef` | floatingCards | `string` | `resolver=viewkit` 时必填 |
| `dataContract.input / output / events` | floatingCards | `object / object / string[]` | 声明进出数据的形状，用于预校验和预填 |
| `trigger.nodeId / event` | floatingCards | `string / string` | 节点级触发绑定，`event` 取自 `human-gate / tool-call / step-done / run-done / manual / startup` |
| `lifecycle.persistence` | floatingCards + largePages | `"ephemeral" \| "session" \| "pinned"` | 决定 run/session 结束后是否回收 |
| `lifecycle.closePolicy` | floatingCards + largePages | `"user" \| "on-node-done" \| "on-run-done"` | 何时允许/自动关闭 |
| `lifecycle.minimize` | floatingCards + largePages | `"hide" \| "dock" \| "collapse"` | 最小化行为 |
| `lifecycle.autoOpen` | floatingCards + largePages | `boolean` | 触发时是否自动展开 |
| `presentation` | largePages | `"tab" \| "route" \| "drawer"` | 默认 `tab`；其中 Tab 是仅有大页面才能占用的 shell 区域 |
| `tabPolicy.defaultOpen / pinned / closable` | largePages | `boolean` | `presentation=tab` 时生效 |

校验规则由 `src/core/app-manifests.js` 统一执行：`viewKitRef` 缺失、非法 `resolver`、非法 `lifecycle.*` 枚举、`presentation` 值越界都会直接 `errors`。

**humanInterface 必备规则（v1.70.0+）**：当 manifest 正向声明了人类界面（`surface.chat.enabled === true` 或非空 `surface.humanInteraction`）且声明了 `interactionContract`，却没有任何**可渲染卡片**时，`validateAppManifest` 直接 `errors`——除非显式设置 `surface.interactionContract.headless: true` 或 `surface.mode: 'headless'`。可渲染卡片 = 非空 `id`/`title` 且至少含 `fields`/`uploads`/`decisionOptions`/`actions` 之一，或 `kind ∈ {info, task}`。factory 生成器必须保证产物满足此约束（不能产出零界面的 Agent App）。运行态由共享渲染器 `public/shared/interactive-cards/`（`window.InteractiveCards` + `normalizeFieldKind`）统一渲染，IDE 与通用运行外壳 `public/app-runtime/` 共用。

#### 1.4.4.8 Tab 纪律（硬约束）

产品默认是 **DAG + AI Chat 主视图永不离场**。Tab 是**特权区域**，绝大多数交互不应占用 Tab。

| Surface | 是否允许 Tab | 落点 |
|---------|-------------|------|
| AI Chat | ❌ | 主区常驻，右/下浮层 |
| Detail Log | ❌ | 右侧可折叠抽屉 |
| Floating Card (`floatingCards[]`) | ❌ | 节点内嵌 / 侧滑 Drawer |
| Large Page (`largePages[]`) | ✅ | 必须 `presentation: "tab"` 明示；也可选 `route` 或 `drawer` |

强制检查：

1. `floatingCards[i].presentation === "tab"` → **manifest 校验失败**。
2. 未声明 `presentation` 的 `largePages[i]` 默认按 `tab` 语义处理（向后兼容）。
3. `lifecycle.persistence: "ephemeral"` 的 largePage 即使设为 `tab`，run 结束后也必须自动关闭——Tab 不是永久入口。

这条纪律保证用户主要视线永远停在 DAG + Chat 上，任何附加 UI（卡片、报表、审批）都优先走内嵌或侧滑，而不是把 Tab Bar 堆满。

#### 1.4.4.9 Shell-owned Run 与 checkpoint rerun 协议

Agent App runtime shell 必须把 workflow 的运行入口从 iframe/editor 内部提升到 App shell 层统一处理。

**Run 输入卡规范：**

1. 嵌入式 workflow editor 的绿色 `Run` 按钮应向 parent shell 发出 `workflowRunRequested` 类事件；parent shell 打开 run input card/modal。
2. Run card 至少包含：`Requirement / Seed Brief`、mode/profile selector、`targetLang`、必要数量参数、compile/lint 开关。不同 Agent App 可按 manifest 的 `defaults.params` 和 workflow `registry.params` 生成更多字段。
3. 用户输入的主需求必须写入显式 workflow param；推荐同时映射为 `factoryBrief`、`seedRequirement`、`userRequest` 或 app 自己的主输入名，确保点击 LLM 节点时能在 messages/input vars 中查到来源。
4. Run card 的 `Run Smoke` / `Run Bootstrap` / `Run Full` 等模式如果存在，必须走同一条 `/api/workflow/execute` SSE 链路，只是 params 不同；不得用前端假状态模拟运行。
5. workflow run 过程中，SSE 事件必须同步到三处：DAG 节点状态、Detail Log、Run card 日志。DAG 不显示完整日志，只显示状态。

**Checkpoint rerun 规范：**

1. 节点级 `Rerun from this node` 只有在当前 workflow view 已加载 checkpoint 后才可用；无 checkpoint 时按钮禁用并显示 `Run once first` 或等价提示。
2. checkpoint 必须绑定 workflow identity。切换到 child workflow 或其他 workflow 后，不能把上一条 workflow 的 checkpoint 用于新 workflow 的节点重跑。
3. rerun 必须走 `/api/workflow/rerun` 或等价 host route，输入为 `workflowName + checkpoint + stepID + overrides`，不是直接从某个节点“空上下文跳跑”。
4. rerun 后同样需要把节点状态、checkpoint、file_written、done/error 事件回灌给 DAG / Detail Log / Run card。
5. 如果用户从无数据节点尝试跑，shell 应明确提示缺少 checkpoint / prior outputs，而不是静默失败。

#### 1.4.4.2 稳定页面入口与端口

Agent-OS 当前只保留三类一等页面，外加一个工作流测试 Agent App。任何新增入口都必须先证明它不是已有页面的重复表达。

| 页面类型 | 标准入口 | 端口 | 稳定性规则 |
|----------|----------|------|------------|
| IDE / Agent App 开发导入页 | `http://127.0.0.1:3200/?shell=ide` | `3200` | 用于 workspace、资源树、源码、导入/开发/调试；不得替代运行时主界面 |
| Agent App 运行界面 | `http://127.0.0.1:3200/` | `3200` | Agent App workspace 默认进入该 shell；DAG 是主画布，AI Chat / Detail Log 是可拖动浮层 |
| Kernel 管理界面 | `http://127.0.0.1:4300/admin/` | `4300` | 只管理 pack、release、instance、health、usage、kernel reload；不得塞入普通 app 业务 UI |
| 工作流测试 Agent App | `http://127.0.0.1:9150/` | `9150` | 属于测试/诊断 app，可作为 Agent App 看待，但不是新的 host 页面类型 |

固定约束：

1. `3200/?shell=ide` 和 `3200/` 是同一个 host 的两个 shell，不能用随机页面替代。
2. Agent App 运行界面必须保持截图式 runtime shell：顶部工作流 strip、中间 DAG runtime window、右侧/右下 AI Chat + Detail Log 浮层。
3. AI Chat 必须支持拖动、收起/恢复，并保留实例级上下文；拖动行为绑定 header，不应通过新侧栏重新实现。
4. `9150` 这类测试服务可以单独打开，但它的存在不增加新的产品级页面分类。
5. 新增页面前必须优先判断是否只是 IDE shell、Agent App shell、Kernel Admin 或某个 Agent App 的 route。

#### 1.4.4.3 VL Theme 与 Agent App 底色

Agent App 中的 VL surface 必须跟运行壳底色协调。默认 runtime shell 的基准色为：

| Token | 值 | 用途 |
|-------|----|------|
| `--bg` | `#0d1117` | 主运行底色 |
| `--bg1` | `#0a0f14` | 深一层底色 |
| `--bg2` | `#161b22` | 面板/浮层底色 |
| `--bg3` | `#21262d` | hover / 输入框 / 次级块 |
| `--border` | `#30363d` | 边框 |
| `--text` | `#e6edf3` | 主文字 |
| `--text2` | `#8b949e` | 次级文字 |
| `--accent` | `#58a6ff` | 主要高亮 |

VL Theme 约束：

1. Agent App 专属 `Theme/Theme.vth` 应使用暗色 `surface`、`textRole` 和 `intent.inverse` token，避免 VL card 在 DAG 暗底上出现突兀白底。
2. `surface.solid/subtle/elevated/overlay/dark` 应映射到 runtime shell 的 `--bg` 系列，而不是另起一套不兼容色盘。
3. `intent.primary` 应接近 `#58a6ff`，success/warning/danger 应接近 runtime shell 的 `#3fb950/#d29922/#f85149`。
4. Theme 调整只能影响 VL surface 的视觉 token，不得改变 Agent App shell 的布局、AI Chat 交互或 workflow DAG 行为。

### 1.4.5 DAG Shell / Node Capsule 合同

Agent App 的 DAG authoring 从 v2.4.0 起明确拆成两类合同：

| 合同 | 存放位置 | 负责什么 | 不负责什么 |
|------|----------|----------|------------|
| `DAG Shell` | `app.surface.dagShell` | Shell 参数、Run 输入、顶层 `logic` Event Panel、默认面板、可调用 host capability | workflow run ledger、checkpoint、artifact、业务 UI |
| `Node Capsule` | `step.capsule` | 单个节点的 `contract/resources/llmRuntime/samples` + 一个 `logic` Event Panel | 多步 DAG、HumanGate、checkpoint、运行态 evidence/error/artifact |

固定规则：

1. Shell 和 Capsule logic 都使用 Event Panel 编辑，保存 events / AST；`compiledJs` 只是派生缓存，`vl` 字符串不能作为真相。
2. Capsule 顶层 `logic.kind` 只允许 `none / form / formula / eventPanel`；迁移期可读取旧 `internalLogic`，新生成和新保存必须写 `logic`。
3. Capsule 禁止 `dag / workflow / miniDAG / steps / children / subflows`。
4. Capsule 工具权限必须来自 `contract.toolScope` + `resources.tools`，并且是 `app.permissions.tools` 子集；不得隐藏调用 `WorkflowRun`。
5. `llmRuntime` 保持声明式，skills 只内联到 `resources.skills[]`，不新增 `skillRefs` 指针。
6. `samples[]` 是作者层示例输入；运行态 evidence / artifact / error 只进入 control plane。
7. `WorkflowDryRun` 必须同时校验外部 workflow、DAG Shell 和 Node Capsule。

设计口径：

> 外部 DAG 管“线”，Capsule 管“点”，Subflow 管“一段可复用的线”。

### 1.4.6 SysDoc 文档系统口径

整套 Agent-OS / Agent App 规范只使用 **SysDoc** 作为官方平台文档系统名称，不再使用旧文档中心命名。

固定规则：

1. `SysDoc` 存放 VL 语法、Theme、Platform APIs、架构规范、Agent App 开发规范等平台级 canonical docs。
2. `Resource Center` 存放 workflow、actor manifest、skill / prompt playbook、flow resource 等可运行或可复用开发者资产。
3. 稳定数字 path 只保留为本地兼容 slot / alias；开发、同步、发布和引用优先使用 `SysDoc key` 或 Resource Center `slug`。
4. Agent App 的 manifest / workflow / skill / tool scope 中需要官方文档能力时统一声明 `SysDoc`，不要再声明旧工具名。
5. 运行时 artifact、preview evidence、review packet、临时 VL surface 不写入 SysDoc；它们属于 control plane 或 workspace/process artifact。

### 1.5 Actor / Workflow / Agent App 的调度边界

这一层必须明确，否则后续很容易把“可复用 workflow”和“完整 Agent App runtime”混成一层。

先固定三条定义：

1. `Actor` 是父 workflow run 内部的受控执行单元。
2. `Workflow / Flow` 是可被复用、可被嵌套调度的执行定义。
3. `Agent App` 是带有 `appId + instanceId + entryWorkflow + app-scoped chat + control plane namespace` 的运行时实体。

因此，Actor 与目标对象的关系应按下面的规则建模：

| 目标 | 正确建模 | Actor 是否可直接调度 | 说明 |
|------|---------|--------------------|------|
| `3-file` / `6-file` / `9-file` / 通用生成链路 | `Workflow / Subflow / child run` | 是，默认路径 | 这是“复用执行定义”，不是“启动一个完整 App” |
| 独立的代码验证、修复、评审子流程 | `Workflow / Subflow / child run` | 是 | 继续保留在父 run 的 lineage 和 result envelope 树里 |
| 完整 `Agent App`（有独立实例、chat、secretScope、quota、trigger、service sidecar） | `App Instance Dispatch` | 可以，但不应伪装成普通 `workflow_path` | 这已经不是单纯子流程，而是 host 管理的独立 runtime 实体 |

规范结论：

1. Actor 直接调用可复用 workflow，是当前系统的**一等支持路径**，也是默认推荐路径。
2. Actor **不要**把完整 Agent App manifest 当成普通 workflow 引用来复用。
3. 当目标需要独立生命周期、独立实例隔离、独立 app chat、独立 trigger 或 sidecar service 时，应提升为 `Agent App`，并通过 host 侧的 app-dispatch 能力启动。
4. 在当前基线下，“Actor -> Agent App instance”在架构上成立，但它属于 **host/runtime orchestration**，不是 workflow spec 内部的基础原语。
5. 在一等 `AppDispatch` / `RunAgentApp` 能力完全固定前，禁止用“把 app 的 `entryWorkflow` 直接塞进普通 subflow”来偷换建模层级。

对生成类场景的默认裁定：

- `3-file`、`6-file`、`9-file`、`meta-direct`、`meta-sharded` 这类能力，默认应建模为 **可复用 workflow backend**。
- 只有当它们需要自己的 `appId / instanceId`、独立 chat console、独立 secret/quota/trigger/control-plane namespace 时，才应升级为完整 Agent App。

### 1.6 `AppDispatch` 最小接口草案

当 Actor 确实需要调用“完整 Agent App”而不是普通子流程时，推荐统一走 host 侧的 `AppDispatch` 能力。

这不是新的 workflow-engine step 语义，而是 host/runtime orchestration contract。

最小请求建议：

```json
{
  "action": "start",
  "appId": "vl-codegen-app",
  "instanceId": "optional-existing-instance",
  "releaseId": "optional-release-id",
  "input": {},
  "config": {},
  "secretScope": "optional-secret-scope",
  "quotaProfile": {},
  "title": "optional-run-title",
  "wait": "started"
}
```

最小动作建议：

1. `start`：创建或复用 instance，并启动 `entryWorkflow`
2. `resume`：恢复暂停/等待中的 instance。**Resume value 契约（v1.72.0+）**：普通 `Pause`（无 approval / `decisionOptions`）用原始值恢复时，该值原样写入 `resumeResultTarget`（如 resume `true` → `$approved === true`）；**approval** 类节点则规范化为 `{ decision, by, ... }` 再写入。因此普通 Pause 的工作流按原始值判断（`=$approved === true`），approval 工作流读 `$approved.decision`。早期把所有非对象 resume 值统一包成 `{decision: value}` 导致普通 Pause 永远走 Cancel 分支的行为已修正
3. `trigger`：触发 manifest 中声明的 trigger
4. `get`：查询当前 instance/runs/pause 状态

最小返回建议：

```json
{
  "ok": true,
  "primitive": "AppDispatch",
  "action": "start",
  "appId": "vl-codegen-app",
  "instanceId": "vl-codegen-app-1",
  "releaseId": "vl-codegen-app@0.1.0",
  "runId": "run_xxx",
  "status": "running",
  "workflowName": "vl-codegen-app-main",
  "runtimeKinds": ["workflow"],
  "chatSessionId": "app-session-vl-codegen-app-vl-codegen-app-1",
  "waitingNodeId": "",
  "waitingReason": "",
  "artifactsRoot": "Process/AppInstances/vl-codegen-app-1",
  "controlPlaneNamespace": "app:vl-codegen-app"
}
```

使用规则：

1. 需要独立 app lifecycle 时，才使用 `AppDispatch`
2. 需要独立 `appId / instanceId / app chat / trigger / secretScope / quotaProfile` 时，才使用 `AppDispatch`
3. 只为复用生成或验证能力时，不要升格到 `AppDispatch`
4. `AppDispatch` 返回的是“app runtime handle”，不是普通 child-run result
5. `AppDispatch` 应沿用 host 的 app routes / instance manager / control-plane 事实层，不应在 workflow spec 内伪装成 `Subflow`

### 1.6.1 `runtime.masterAgent` / Goal Convergence 主控 Agent

当一个 Agent App 需要不断尝试、验证、扩展、剪枝、回滚，并保留中间版本以逼近目标状态时，可以在 manifest 的 `runtime.masterAgent` 中声明一个 host-owned 主控 Agent。

这不是新的 workflow-engine step 语义，而是 Agent App / host runtime contract。它复用现有节点能力：

| 子节点形态 | 调度路径 | 说明 |
|-----------|----------|------|
| 固定 DAG / Workflow | `WorkflowRun` / child run | 稳定、可复用、低成本 |
| Agent / LLM / codegen node | 显式 tool 或 app-scoped assistant | 开放生成，但必须被 verifier / scorecard 约束 |
| Actor / Runtime node | `TeamWorkflowRuntime` / `AppDispatch` | 有状态、可持续、适合监控和长期维护 |

最小声明建议：

```json
{
  "runtime": {
    "masterAgent": {
      "enabled": true,
      "role": "PlannerEvaluatorSchedulerArbiter",
      "policy": "single-host-master",
      "goalTool": "GoalConvergence",
      "scoreThreshold": 0.86,
      "maxIterations": 12,
      "nodeAdapters": ["workflow-run", "agent-tool", "team-actor", "app-dispatch"],
      "versionRetention": "control-plane"
    }
  }
}
```

固定规则：

1. 一个 app instance 内最多只有一个 host-owned master agent；Actor / Agent worker 不得变成互相竞争的主控。
2. 子节点可以提出候选、证据、GraphPatch 或版本，但不能自行进入 mainline。
3. Promotion 必须依据 acceptance criteria、scorecard、verifier / ResultEnvelope evidence。
4. Prune / rollback 必须写入 control plane，并保留版本树，不得只在日志里消失。
5. `runtime.masterAgent` 只声明策略和边界；真正的执行仍走现有 WorkflowRun、tool、Actor、AppDispatch 与 control-plane primitive。

### 1.7 当前资源中心 workflow 资产分类（2026-04-12 快照）

为了避免资源中心里“看起来像 agent 的 workflow”被误判成 Agent App，这里固定一条当前系统规则：

1. `.vl-code/registry/workflows/*.workflow.json` 注册的是 **workflow 资源**。
2. **携带顶层 `app` 块的 flow** 即 **Agent App**（manifest 在加载时由该 `app` 块派生，无独立 `.app.json` 来源）。
3. 一个 workflow 即使是顶层、长链路、可见、多人协作、workflow-of-workflows，也**不会**因为复杂而自动变成 Agent App。
4. 只有当某个 workflow 被 app manifest 通过 `entryWorkflow` 挂成 `Pack -> Release -> Instance` 运行实体时，它才获得 Agent App 语义。

当前 registry 实际快照：

- workflow 资源总数：`113`
- app manifest 总数：`2`
- 当前已被提升为 Agent App 入口的 workflow：`2`
- 因此，当前资源中心内 **其余 111 个 workflow 都是可复用 workflow 资产，不是 Agent App**

当前已提升为 Agent App 的只有：

1. `future-agent-os-explorer-main`
   对应 app：`future-agent-os-explorer`
2. `future-agent-os-explorer-og-main`
   对应 app：`future-agent-os-explorer-og`

除上述 2 个入口 workflow 外，当前 registry 中其余 workflow 应按下面几类理解：

#### A. 可复用 codegen / adjust / repair backend（20）

这些 workflow 默认属于“生成、调整、调试、验证”后端，不是 Agent App：

- `3-file-codegen`
- `6-file-codegen`
- `9-file-codegen`
- `meta-direct-codegen`
- `meta-fast-fanout`
- `meta-sharded-codegen`
- `parallel-codegen`
- `site-clone-codegen`
- `design-reference-codegen`
- `add-page`
- `add-service`
- `theme-customize`
- `incremental-update`
- `feature-adjust`
- `data-adjust`
- `batch-adjust`
- `compile-fix`
- `debug-multi-file`
- `debug-single-file`
- `autotest-pipeline`

#### B. 可复用角色 / 阶段 backend family（80）

这些 workflow family 默认属于角色后端、阶段后端、domain backend，仍然是 workflow 资产，不是 Agent App：

- `actor-demo-*`
- `actor-media-*`
- `future-agent-os-*`
  例外：`future-agent-os-explorer-main`、`future-agent-os-explorer-og-main` 已被提升为 Agent App 入口
- `media-showcase-*`
- `mega-collab-*`
- `team-demo-video-*`
- `team-human-task-release-packet`
- `team-media-article-*`
- `team-media-enterprise-delivery`
- `team-smart-campus-{architecture-foundation,backend-fix,backend-sprint,bootstrap-product,design-system,frontend-fix,frontend-sprint,pm-plan}`
- `team-vl-{architecture-foundation,backend-fix,backend-sprint,bootstrap-product,design-system,frontend-fix,frontend-sprint,pm-plan,pm-triage,qa-round,release-board}`
- `team-vlcode-video-*`

#### C. 可复用 composite orchestration workflow（9）

这些 workflow 虽然是“顶层编排”或“交付总流程”，但当前仍然只是 workflow，不是 Agent App：

1. `code-evolution-main`
2. `code-evolution-actor-round`
3. `team-actor-enterprise-demo`
4. `team-actor-mega-collab-demo`
5. `team-game-studio-prototype`
6. `team-medium-project-delivery`
7. `team-smart-campus-enterprise-delivery`
8. `team-vl-actor-enterprise-delivery`
9. `team-vl-enterprise-delivery`

#### D. 可复用 smoke / verify utility workflow（2）

1. `editor-pause-smoke`
2. `factory-v21-smoke`

这一节的结论可以直接作为资源中心的判定规则：

- `workflow resource != Agent App`
- `top-level workflow != Agent App`
- `workflow-of-workflows != Agent App`
- `multi-actor visible delivery flow != Agent App`
- `只有 app manifest + entryWorkflow + instance lifecycle 才是 Agent App`

### 1.8 Agent App 生成工作流基线

当前 `agent-app-scaffold-main` 是 quick scaffold：一个 LLM 规划后交给 `AgentAppScaffold` 工具落盘。这个路径可以保留用于 smoke / demo，但不能作为高质量 Agent App 生成的唯一标准。

正式默认生成链路现在统一为：`agent-app-factory-main`（seed file: `public/seed-workflows/agent-app-factory-main.json`）。

这条单入口链路至少包含以下阶段：

| 阶段 | 产物 | 规则 |
|------|------|------|
| 1. Solution Elevation | `Process/Artifacts/AgentAppFactory/00_SolutionDecision.json` | 先判断需求应落成 `workflow_only`、`agent_app` 还是 `hybrid` |
| 2. Requirement Structuring | `ProductBrief / RequirementBundle / DependencyManifest / InteractionContract / SurfaceContract` | 把需求、依赖、交互、tools/toolScope、VL surface 规划成协议化产物 |
| 3. Delivery Blueprint | `WorkflowBlueprint / TargetManifestPlan` | 定义 actor、step family、ResultEnvelope、HumanGate、app runtime 边界 |
| 4. Generation | `Process/Artifacts/AgentAppFactory/90_GenerationResult.json` | 直接生成携带 `app` 块的入口 flow（manifest 由该块派生）、可选 VL surface 与 serviceCode |
| 5. Validation | `Process/Artifacts/AgentAppFactory/95_ValidationReport.json` | 校验 manifest schema、workflow required params、surface route、theme 暗底一致性、port/dir 规范、权限上限 |
| 6. Register & Open Runtime | `Process/Artifacts/AgentAppFactory/99_ScaffoldResult.json` | 把携带 `app` 块的入口 flow 放进 `.vl-code/workflows/`（discovery 自动派生 manifest），准备 runtime shell，而不是只给 artifact 页面 |

必须借鉴 VLC 生成链路的规则：

1. 先产出结构化 plan，再生成文件；不要把完整 app 交给单个 LLM 一次性自由发挥。
2. `defaults.params` 必须覆盖 `entryWorkflow` 的 required params；Run 按钮应能无额外 prompt 从头跑到尾。
3. 每个生成文件都要有明确 owner：manifest、workflow、VL surface、Theme、service runtime 分开。
4. 验证失败时进入 Chat 的问题卡和 Detail Log，不弹新页面，不吞错误。
5. 生成出的 Agent App 必须默认能在 Agent App runtime shell 中看到 DAG、AI Chat、Detail Log、VL Surface；9200-9299 的 artifact preview 只能作为辅助证据。
6. 如果需要大页面，写入 runtime page/tab 计划；如果只是小表格/图表/表单，写入 VL Floating Card 计划。
7. 生成出的 Agent App Home 必须采用 §1.4.3.0 的紧凑顶栏、§1.4.3.5 的 Node-IO-first Manifest Inspector、§1.4.3.9 的 shell-owned Run 输入卡与 checkpoint rerun 规则。
8. 对中大型生成器类 Agent App，workflow 必须暴露显式主输入参数（例如 `factoryBrief`），并把它接入需求/规划 LLM 节点；不允许只有 UI 输入框但 workflow messages 里查不到该输入。
9. 生成器必须提供低成本 smoke/bootstrap mode，用于验证 manifest、DAG、Run card、SSE、checkpoint、rerun 和基本 artifact 写入；full mode 再启动真实 LLM / compile / package 长链路。
10. 验收时必须留下真实 browser 证据：Run 输入卡、无 checkpoint 禁用状态、至少一次成功 run、checkpoint 后节点 rerun、子 workflow 页面切换、AI Chat/Detail Log 浮层。证据放在 `Process/PreviewEvidence/<appId-or-run>/`，默认不写入可复用 pack。

### 1.8.1 Agent App Factory 母工作流产物协议

`agent-app-factory-main` 把“用户意图 -> workflow + manifest”的前置规划和后续交付放在同一条主链里，先生成以下协议化产物：

1. `SolutionDecision`
   先判断需求应落成 `workflow_only`、`agent_app` 还是 `hybrid`
2. `RequirementBundle`
   结构化输入/输出、约束、非目标、完成定义、人工决策点
3. `DependencyManifest`
   规划 SysDoc、workspace 文件、上传资料、组件、skills、tools、toolScope、artifact roots
4. `InteractionContract`
   规划问答卡、上传卡、审批卡、补料卡、分支卡
5. `SurfaceContract`
   规划 AI Chat、Detail Log、VL Floating Card、Large App Page 的职责和恢复规则
6. `WorkflowBlueprint`
   先定义 actor、step family、branch、checkpoint、rerun、ResultEnvelope、HumanGate，再进入后续可执行 workflow JSON 生成阶段
7. `TargetManifestPlan`
   先定义 app 边界、runtime、permissions、surface、views，再进入后续最终 manifest 生成阶段

因此，正式默认路径统一为：

```text
User Intent
  -> agent-app-factory-main
  -> planning artifacts
  -> generation + validation + scaffold
  -> scaffold/register/runtime shell
```

固定规则：

1. 不是每个需求都应直接升级为 Agent App，母工作流必须先做 `SolutionDecision`
2. 需要补料时优先通过 `HumanTask` 卡片完成，而不是浏览器 `prompt()` 或新页面
3. 只有在 `solutionKind` 为 `agent_app` 或 `hybrid` 时，母工作流才继续进入交付阶段
4. 当结果只是 workflow backend 时，允许在蓝图和协议产物处停止，不强行包装成 App
5. `agent-app-3file-main` 可以作为内部兼容生成器保留，但不再作为对外并列的正式基线

---

## 2. 能力表面（Capability Surface）

Agent-OS 提供 **8 个能力维度**，Agent App 可以按需组合使用：

### 2.1 常驻内核（Resident Kernel）

| 项目 | 值 |
|------|---|
| 入口 | `bin/vlcode-kernel.js` |
| 端口 | 4300 |
| 职责 | 进程监督、实例注册、健康检查、自动重启、SSE 事件总线 |
| API | `GET /api/kernel/status`, `GET /api/kernel/instances`, `POST /api/kernel/instances` |
| 持久化 | `~/.vl-code/kernel/kernel-state.json` |

Agent App 作为 Kernel 管理的 instance 运行，Kernel 负责生命周期。

### 2.2 本地工作流（Local Workflow Engine 4.1）

| 项目 | 值 |
|------|---|
| 引擎 | `vl-workflow-engine` v4.16.0 |
| Spec | Workflow Spec 4.1 |
| 事件 | `vl.workflow.run-event.v4` |
| 能力 | checkpoint/resume/rerun、Actor/Review/GraphPatch/SpawnChildRun、step.tools/toolScope、Score/Grow/Channel/Topology/Iteration 步骤（4.12+）、`step_retrying`/`step_cached` 事件（4.12+）、Interact 步骤（`Pause.interact`，4.14+）、Breakpoints（`runParams.breakpoints` → `breakpoint_hit`，4.16+） |

**每个 Agent App 的 `entryWorkflow` 由此引擎执行。** 所有 AI 推理、工具调用、审批、并行都在 workflow 内编排。

### 2.3 本地前端（VL Local Runtime）

| 项目 | 值 |
|------|---|
| 编译 | `VLCompile` tool → ParseVL API |
| 本地渲染 | `GET /vl-app/:appKey` via vl-runner |
| CDN | `file.visuallogic.ai` (player.js + widgets.js) |

**流程：**
```
VL 源文件 (.vx/.sc/.cp/.vs/.vdb/.vth)
  → VLCompile (调用 ParseVL API)
  → 返回 previewUrl + appCaseId
  → vl-runner 生成本地 HTML
  → 浏览器访问 /vl-app/:appKey
  → VL App 在本地渲染运行
```

当 Agent App 需要展示 UI 时，**必须使用 VL 而非手写 HTML**。VL 是 Agent-OS 的原生展示层。

### 2.4 本地轻后端（Service Runtime）

| 项目 | 值 |
|------|---|
| 入口 | `AgentApp/runtime/server.mjs` |
| 端口 | auto，范围 4610-4699 |
| 协议 | HTTP (Express/原生 http) |

Service Runtime 是 **可选的辅助进程**，用于：
- 提供 Health endpoint（必须）
- 接收外部事件/webhook
- 定时轮询/调度
- 转发 chat 请求到 workflow

**重要：Service Runtime 不替代 entryWorkflow。** 即使有 service，workflow 仍然是执行主体。

### 2.5 本地运行时（Tool Registry + Permission + Control Plane）

| 项目 | 值 |
|------|---|
| 工具注册 | `ToolRegistry`（50+ builtin tools） |
| 权限管理 | `RuntimePermissionManager`（domain/tool/file scoping） |
| 审批代理 | `RuntimeApprovalBroker`（auto/required/never） |
| 审计日志 | `RuntimeAuditLog` |
| 控制平面 | `ControlPlaneDatabase` (SQLite) |

### 2.6 本地工具（50+ Builtin + OpenClaw Adapter）

**工具分类：**
- READ_ONLY: ReadFile, Grep, Glob, SysDoc, VLSyntaxRef, Memory, ...
- WRITE: WriteFile, EditFile, VLGenerate, VLAdjust, VLApplyDelta, ...
- NETWORK: SysDoc, Resource Center, ComponentFetch, VLCompile, WebsiteCapture, ...
- SHELL: Bash, CodeExec
- WORKFLOW: WorkflowRun, TeamWorkflowRuntime, VLGenerate, VLCompile, ...
- HUMAN_GATE: AskUserQuestion

**OpenClaw 适配：**
- `src/adapters/openclaw-skill-loader.js` — 加载 ClawHub SKILL.md 格式的 skills
- `src/adapters/openclaw-tool-adapter.js` — 包装 OpenClaw 插件的 tools 到我们的 ToolRegistry

### 2.7 LLM（多模型路由）

| 项目 | 值 |
|------|---|
| 提供商 | Anthropic (Claude), OpenAI (GPT-4o), Google (Gemini) |
| 路由 | per-node `step.model` + `step.meta.llmRoute` |
| 推理级别 | basic / standard / deep（可配置 thinking budget） |
| 并发 | sequential / parallel / swarm |

### 2.8 云端前后台（Cloud Frontend + Backend + Resources）

这是 Agent-OS 的**原生能力**，不需要额外基础设施：

**云端前端（Web App Hosting）：**
```
VL 源文件 → VLCompile → ParseVL API → preview URL
  → https://editor.visuallogic.ai/preview/{caseId}?nid=...&gid=...
  → 任何人可通过 URL 访问运行中的 Web App
```

**云端后端（Workspace API）：**
```
POST /ih5/editor/workspace/writeFiles   — 写文件到云端 workspace
POST /ih5/editor/workspace/readFiles    — 从云端读文件
POST /ih5/editor/workspace/deleteFiles  — 删除云端文件
POST /ih5/editor/workspace/listFile     — 列出云端文件
POST /ih5/editor/work/launchVersion     — 发布版本
```

**云端资源（Resource Hub 三通道）：**
```
workspace-local → cloud-private → cloud-submitted → platform-shared
```

**Workspace File Sync：**
- `CloudAPI.syncPush(gid, localFiles)` — 本地 → 云端
- `CloudAPI.readFiles(gid, paths)` — 云端 → 本地
- `ensureBoundCloudWorkspace()` — 自动绑定/创建云端 workspace

---

## 3. 架构层级

```
┌───────────────────────────────────────────────────────────┐
│ Layer 1: Operator Plane                                   │
│   Kernel Dashboard / 系统级 app 管理 / 实例控制 / 健康监控    │
├───────────────────────────────────────────────────────────┤
│ Layer 2: App Surface Plane                                │
│   App Runtime Console / AI Chat / VL Dynamic Views /      │
│   HumanGate Approval / Inbox                              │
├───────────────────────────────────────────────────────────┤
│ Layer 3: Host & Kernel Plane                              │
│   AppRegistry / AppInstanceManager / Workflow Executor /   │
│   Tool Registry / Permission Manager / Session Pool        │
├───────────────────────────────────────────────────────────┤
│ Layer 4: Control Plane                                    │
│   SQLite: runs / actors / tasks / artifacts / reviews /    │
│   resources / lineage / inbox / audit                     │
├───────────────────────────────────────────────────────────┤
│ Layer 5: Execution Resource Plane                         │
│   Workspace files / Process/Artifacts / Secrets / Models   │
│   VL files (.vx/.sc/.cp/.vs/.vdb/.vth) / Theme            │
├───────────────────────────────────────────────────────────┤
│ Layer 6: Cloud & Shared Plane                             │
│   ParseVL API / Workspace API / SysDoc / Resource Hub   │
│   CDN (player.js, widgets.js) / Preview URL Hosting        │
└───────────────────────────────────────────────────────────┘
```

---

## 4. Manifest 规范

### 4.1 文件位置

Manifest **不是独立文件**。它是入口 flow 顶层的 `app` 块，在加载时由 `manifestFromFlow` 派生：

```
.vl-code/workflows/<id>.json   ← 入口 flow（workflow JSON / .vflow），顶层带 `app` 块
                                  manifest = 该 `app` 块在加载时派生的投影
```

派生规则：

1. **`app` 块是唯一标记** — flow 顶层出现 `app: {...}` 才被识别为 Agent App；不会把其它键（如 workflow 自用的 `manifest`）误判为 app 块。
2. **humanInterface / interactionContract.cards 派生自 flow 步骤** — 卡片由 flow 的 `Pause`（带 `humanTask`）和 `Review`（带 decisionOptions / fields）步骤派生，卡片 `nodeId` 即步骤 id；flow 是这些卡片的单一事实来源，`app` 块内同 `nodeId` 的卡片只叠加展示字段。
3. **`entryWorkflow` 是 flow 自引用** — 入口工作流就是 flow 自身；默认解析为落盘文件名 / `app.entryWorkflow` / flow `name`。
4. **`app.metadata.source`** — `flow-app` 表示普通派生 app；`platform-builtin` 标识平台内置 app。
5. 落盘的 `.vl-code/registry/apps/<id>.app.json` 仅是该投影的**派生缓存（可选）**，由安装链路写出，不是手写来源，不应反向作为权威 manifest 编辑。

下面 §4.2 定义的字段语义不变，只是这些字段现在写在 flow 的 `app` 块里，而不是独立的 `.app.json` 文件里。

### 4.2 完整字段定义

下面展示的是**一个携带 `app` 块的 workflow（入口 flow）**：顶层是 workflow 本体（`version` / `name` / `steps`），manifest 字段全部写在 `app: {...}` 块里。

```jsonc
{
  // === workflow 本体（入口 flow 自身）===
  "version": "4.1",
  "name": "my-agent-app-main",     // flow 名；entryWorkflow 默认自引用到它
  "steps": [
    // ... 正常的 workflow 步骤；Pause / Review 步骤会派生出 humanInterface 卡片
  ],

  // === app 块：manifest 由它在加载时派生（manifestFromFlow）===
  "app": {
    // --- 元信息（必填）---
    "$schema": "VL-AgentOS/app-pack-manifest-v0.1",
    "kind": "app",
    "id": "my-agent-app",           // kebab-case，全局唯一
    "version": "0.1.0",             // semver
    "title": "My Agent App",        // 显示名称
    "description": "...",            // 简短描述

    // --- 入口工作流（自引用）---
    "entryWorkflow": "my-agent-app-main",  // 指向本 flow（.vl-code/workflows/<name>.json）

    // --- Actor 声明 ---
    "actors": ["AI-Core", "Human-Operator"],

    // --- 展示表面 ---
    "surface": {
      "mode": "hybrid",   // headless | console | visual | hybrid
      "chat": {
        "enabled": true,
        "dock": "right-panel",
        "contextScope": "instance"   // instance | run | global
      },
      "humanInteraction": {
        "enabled": true,
        "inbox": true,               // 收件箱（待审批项）
        "review": true               // 审批面板
      },
      "presentation": {
        "renderer": "vl-local-runtime",  // vl-local-runtime | custom
        "entryApp": "Apps/Main.vx",      // VL 入口文件
        "compileMode": "local-js",       // local-js | cloud-preview
        "cloudDeploy": {
          "enabled": true,               // 是否启用云端投放
          "autoSync": false              // 是否自动同步到云端 workspace
        },
        "preview": {
          "enabled": true,
          "mode": "local",               // local | hosted | hybrid
          "appId": "Main.vx",            // 默认 preview app
          "route": "/preview/local/Main.vx",
          "defaultViewport": { "width": 1440, "height": 900 },
          "evidence": {
            "enabled": true,
            "artifactRoot": "Process/Artifacts/Preview",
            "captureOn": ["create", "screenshot", "workflow-artifact"]
          }
        },
        "requiredPanels": ["overview", "workflow", "artifacts", "coreData", "inbox"],
        "dataSources": {
          "runs": "control-plane:runs",
          "artifacts": "control-plane:artifacts",
          "coreData": "domain:my-app"    // 业务数据视图
        }
      }
    },

    // --- 权限 ---
    "permissions": {
      "tools": ["WorkflowRun", "ReadFile", "WriteFile", "VLCompile"], // app 级 ceiling，不等于任何 chat 都能直接调用
      "network": ["localhost", "editor.visuallogic.ai"],
      "workspace": ["Process/**", "Apps/**", "Sections/**"],
      "secrets": [] // 空数组表示继承 Agent-OS 当前可用 provider；如需收窄，填 ["openai", "anthropic", "gemini"]
    },

    // --- 触发器 ---
    "triggers": [
      { "type": "manual" },
      { "type": "schedule", "id": "health-check", "cron": "*/15 * * * *" }
    ],

    // --- 运行时 ---
    "runtime": {
      "singleton": true,
      "startMode": "manual",         // manual | auto
      "controlPlaneNamespace": "app:my-agent-app",
      "appHome": ".",
      "masterAgent": {               // 可选：host-owned 主控 Agent，用于目标收敛型 app
        "enabled": true,
        "role": "PlannerEvaluatorSchedulerArbiter",
        "policy": "single-host-master",
        "goalTool": "GoalConvergence",
        "scoreThreshold": 0.86,
        "maxIterations": 12,
        "nodeAdapters": ["workflow-run", "agent-tool", "team-actor", "app-dispatch"],
        "versionRetention": "control-plane"
      },
      "service": {                   // 可选：长驻进程
        "command": "node",
        "args": ["AgentApp/runtime/server.mjs"],
        "cwd": ".",
        "port": "auto",
        "portRange": { "start": 4610, "end": 4699 },
        "healthUrl": "http://127.0.0.1:${PORT}/health",
        "env": {},                         // 只放非敏感覆盖项；API Key / 平台 cookie 由 host 注入
        "startTimeoutMs": 15000
      }
    },

    // --- VL 运行面 ---
    "vlRuntime": {
      "backend": {
        "mode": "vl-local",              // vl-local | platform | sidecar
        "baseUrl": "",
        "healthUrl": ""
      }
    },

    // --- 默认参数 ---
    "defaults": { "params": {} },

    // --- 元数据 ---
    "metadata": { "category": "operations", "tags": [] }
  }
}
```

### 4.2.1 Preview Surface Metadata

`surface.presentation.preview` 是 Agent App 对 host preview 能力的声明，不是运行态日志：

| 字段 | 含义 |
|------|------|
| `enabled` | 该 app 是否需要 preview surface |
| `mode` | `local` 使用 `/preview/local/:appId`，`hosted` 使用平台 preview URL，`hybrid` 两者都可用 |
| `appId` / `route` / `url` | 默认打开的 preview app、host route 或 hosted URL |
| `defaultViewport` | 默认截图/检查 viewport，必须包含正数 `width` / `height` |
| `evidence.artifactRoot` | preview screenshot / smoke report 默认产物目录，推荐 `Process/Artifacts/Preview` |
| `evidence.captureOn` | 可选：`create`、`screenshot`、`workflow-artifact`、`close` |
| `vlRuntime.backend` | VL runtime 后端声明：`vl-local` 使用本地 VL 前端运行面，`platform` 使用平台服务，`sidecar` 绑定 app 自带服务进程 |

Host 运行时会把 preview 工具返回的 `previewSessionRef` 记录为 `preview_session` resource，并把截图等文件作为 artifact 关联到同一个 run。

Console 型 Agent App 如果只是支持 AI Chat 生成临时 VL 页面/表格/图表，不应伪造静态 `preview.route`；它只需要声明 `preview.enabled=true` 和 `vlRuntime.backend.mode="vl-local"`，真正的 URL 由 `vl.surface.preview` 在创建 runtime surface 后产生。

### 4.3 Service Runtime 模板变量

| 变量 | 含义 |
|------|------|
| `${PORT}` | 分配的端口 |
| `${APP_HOME}` | App 根目录 |
| `${APP_ID}` | App ID |
| `${INSTANCE_ID}` | Instance ID |
| `${WORKSPACE_ROOT}` | Workspace 根 |
| `${ARTIFACT_DIR}` | 实例 artifact 目录 |

---

## 5. 目录结构规范

```
~/Documents/VLAgentApps/AgentApps/<AppName>/
│
├── .vl-code/
│   ├── workflows/                         ← Workflow 定义（必须）
│   │   ├── <app-id>-main.json            ← 入口 flow，顶层带 `app` 块 = manifest 来源
│   │   └── <app-id>-sub-*.json           ← 子 workflow
│   ├── registry/apps/<app-id>.app.json   ← 派生缓存（可选，安装链路写出；非手写来源）
│   ├── skills/                            ← App 特有 skills
│   ├── project.json                       ← VL 项目配置（有 VL UI 时）
│   └── control-plane.sqlite               ← 运行时自动创建
│
├── AgentApp/                              ← Agent 运行时资源
│   ├── runtime/server.mjs                 ← Service entry（可选）
│   ├── prompts/                           ← 提示词模板
│   │   ├── system.md
│   │   └── <role>.md
│   └── data/                              ← 运行时数据
│
├── Apps/                                  ← VL 应用入口（有 VL UI 时）
│   └── <AppName>App.vx
├── Sections/                              ← VL Section
│   └── <Name>.sc
├── ExtComponents/                         ← VL 组件
│   └── <Name>.cp
├── Services/                              ← VL 服务
│   └── <Name>.vs
├── Database/                              ← VL 数据库
│   └── <AppName>.vdb
├── Theme/
│   └── Theme.vth
│
├── Process/                               ← 执行输出（自动生成）
│   ├── Artifacts/                         ← Workflow 产出物
│   ├── AppInstances/<instanceId>/         ← 实例隔离目录
│   └── Reviews/                           ← 审批记录
│
└── VL.md
```

**命名规则：** 所有 VL 文件名 **必须英文 PascalCase**，不得使用中文或特殊字符。

---

## 6. Surface Mode 选型

### 6.1 四种模式

| 模式 | Chat | Workflow | VL UI | 人机交互 | 适用场景 |
|------|------|---------|-------|---------|---------|
| **headless** | 无 | 有 | 无 | 无 | 后台任务、纯自动化 |
| **console** | 有 | 有 | 无 | Inbox + Review | 任务队列、审批流 |
| **visual** | 可选 | 有 | 有 | 有 | 数据仪表盘、复杂 UI |
| **hybrid** | 有 | 有 | 有 | 有 | **推荐默认**：通用型 |

### 6.2 决策树

```
需要独立 UI 展示？
  ├── 否 → 需要人工审批或 Chat？
  │         ├── 否 → headless
  │         └── 是 → console
  └── 是 → 需要 AI Chat 交互？
            ├── 否 → visual
            └── 是 → hybrid（推荐）
```

---

## 7. Workflow 设计规范

### 7.1 入口 Workflow 必须包含

1. **至少一个 LLM 节点** — 这是 "Agent" 的核心，没有 AI 推理就不是 Agent App
2. **Artifact 输出** — 通过 `out` 字段写入 `Process/Artifacts/`
3. **ResultEnvelope** — 所有节点通过 engine 自动返回 envelope

### 7.2 AI Chat 集成

Chat 不是独立产品，也不等于 workflow 本身。

它在 Agent App 中更准确的角色是：

1. `app runtime console` 的自然语言入口
2. 当前 `appId / instanceId / runId / selected resource` 的解释层
3. 把自由文本路由成 `start / resume / rerun / inspect / explain` 等受控动作的控制器

因此，推荐方式不是“做一个脱离实例上下文的全局聊天框”，而是：

> `App-scoped Chat Session + Workflow / Control-Plane Dispatch`

**推荐方式：Service Runtime 或 Host Surface 绑定实例上下文后，再路由到 workflow / app lifecycle**
```javascript
// AgentApp/runtime/server.mjs
app.post('/api/chat', async (req, res) => {
  const { appId, instanceId, message, selectedResourceId } = req.body;

  const ctx = await loadAppRuntimeContext({
    appId,
    instanceId,
    selectedResourceId,
  });

  const decision = await routeMessageWithAppAI({
    message,
    context: {
      appId,
      instanceId,
      runId: ctx.runId,
      waitingNodeId: ctx.waitingNodeId,
      selectedResourceId,
    },
  });

  if (decision.action === 'start') {
    const started = await fetch(`${HOST_URL}/api/app-instances/start`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        appId,
        instanceId,
        input: {
          userMessage: message,
          selectedResourceId,
        },
      }),
    }).then((r) => r.json());

    return res.json({
      mode: 'run-started',
      instanceId: started.instance?.instanceId,
      runId: started.instance?.lastRunId,
    });
  }

  if (decision.action === 'resume' && instanceId) {
    const resumed = await fetch(`${HOST_URL}/api/app-instances/${instanceId}/resume`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        nodeId: ctx.waitingNodeId,
        payload: decision.payload ?? true,
      }),
    }).then((r) => r.json());

    return res.json({
      mode: 'resumed',
      resumed: resumed.resumed === true,
      instanceId,
      runId: ctx.runId,
    });
  }

  return res.json({
    mode: 'chat-reply',
    reply: decision.reply,
    context: {
      appId,
      instanceId,
      runId: ctx.runId,
      selectedResourceId,
    },
  });
});
```

固定规则：

1. app 级 chat session 应属于 `appId + instanceId`，而不是 workspace 级全局会话
2. chat 可以只做解释、查询、路由，不必每次都启动 workflow
3. 有 `humanInteraction` 的 app，chat 必须和 `Inbox / Review / HumanGate` 协同，而不是替代它们

### 7.2.1 Slash command 扩展协议

> 本节来自 `AgentAppRuntimeSpec` v0.3 patch P3（VflowTestRunner 参考实现反馈）。
> 与 §7.4.8.7 关系：§7.4.8.7 定义 `app-runtime` / `review-task` 等 **profile-level** 默认命令集；本节定义 **App-level** 扩展——一个具体 Agent App `.vflow` 如何声明自己的领域命令。

每个 Agent App MAY 通过 `surface.presentation.slashCommands` 字段声明其 App-level slash commands。Host 渲染 Composer 时，将 profile 默认集与 App 扩展集合并（去重），按 scope 过滤后展示。

Manifest 片段：

```jsonc
{
  "surface": {
    "presentation": {
      "slashCommands": [
        { "command": "/help",      "routesTo": "local",                         "description": "List available commands + tools" },
        { "command": "/run",       "routesTo": "tool:WorkflowRun",              "args": "[L1|L2|L3]" },
        { "command": "/test",      "routesTo": "tool:VflowSingleTest",          "args": "<bundle-name>" },
        { "command": "/test-all",  "routesTo": "tool:VflowBatchTest",           "args": "[filter]" },
        { "command": "/switch",    "routesTo": "tool:VflowSelect",              "args": "<bundle-name>" },
        { "command": "/inspect",   "routesTo": "tool:WorkflowInspect" },
        { "command": "/models",    "routesTo": "local",                         "description": "List detected LLM models" }
      ]
    }
  }
}
```

规则：

1. `routesTo: "local"` — Host 本地处理（如列命令、显示状态），不走 LLM
2. `routesTo: "tool:<ToolName>"` — 前置解析为 tool_use，跳过 LLM 路由直接调工具，省 token
3. `routesTo: "workflow:<workflowId>"` — 启动一个具体 workflow
4. App-level commands 永远受 §7.4.8 三层 Scope 约束；Host 在渲染前二次校验
5. 同名命令：App 扩展 > Profile 默认（允许 App 覆盖，便于本地化或收窄语义）

最小建议集（用于所有 `console` / `hybrid` surface 的 App）：`/help`、`/inspect`、`/status`、`/run`。其余按 App 领域需要扩展。

### 7.3 HumanGate 规范

当需要人类决策时，使用 Review 节点：

```json
{
  "id": "Review_Approval",
  "meta": { "title": "Human Approval", "stepType": "Review" },
  "review": {
    "type": "human",
    "decisionOptions": ["approve", "reject", "request_changes"],
    "humanTask": {
      "title": "Review Output",
      "description": "审查生成的产出物并决定。",
      "fields": [
        { "id": "notes", "type": "textarea", "label": "备注", "required": false }
      ]
    }
  }
}
```

HumanGate 会：
1. 暂停 workflow 执行
2. 将审批任务推入 Inbox
3. 等待用户通过 `POST /api/resource-tree/review/:reviewId/decision` 提交决策
4. 决策持久化到 `gate_reviews` 表
5. workflow 根据决策继续或终止

### 7.4 InteractiveCard 规范

从这一版开始，Agent App、Workflow Engine 运行态、Agent-OS IDE、VLC IDE 右侧 AI 面板中的一切结构化展示与人机交互，统一收敛到 `InteractiveCard`。

它不是“聊天里随手插一段 HTML”，而是：

> 由 runtime / workflow / app control-plane 生成，带有 scope、状态、动作、输入 schema、资源引用、审计信息的正式结构化对象。

固定边界：

1. `InteractiveCard` 是展示与交互协议，不是 workflow step 本身
2. `InteractiveCard` 可以承载 run/node/artifact/review/form/picker 等事实，但不替代 control-plane 持久化
3. AI 模型可以产出 `card intent` 或 `card payload`，但前端渲染必须走 host 提供的 schema renderer，禁止模型直接返回任意 HTML/JS
4. `HumanGate`、`Review`、参数补录、模板选择、资源选择、审批、上传附件，统一视为 `InteractiveCard` 的特例

#### 7.4.1 AI Console 固定分层

Agent App 右侧 AI Console 固定为 4 层：

1. `Assistant Header`
   显示当前 `workspace / app / instance / run / selected node`、模型、权限模式、资源计数
2. `Conversation Card Stream`
   在 `Chat` Tab 的消息滚动区内显示 `Run / LLM / Tool / Artifact / Blocking Human Input` 卡片；普通运行卡片随对话自动上滚，不在外部 rail 堆叠
3. `Tabs`
   固定为 `Chat`、`Runs`、`Context`、`Resources`、`Tasks`
4. `Composer`
   只负责输入消息、slash commands、附加文件，不承担主展示职责

各 Tab 的职责固定如下：

| Tab | 职责 |
|-----|------|
| `Chat` | 自然语言解释、总结、运行卡片、HumanGate 卡片、结果卡片、简短事件流 |
| `Runs` | 当前 run、历史 runs、subflow/actor run、已归档卡片 |
| `Context` | 当前 flow 初始化资料、docs、prompts、当前节点输入/输出、source bindings |
| `Resources` | AI 当前可用资源总览，含 docs/files/artifacts/tools/skills/reviews |
| `Tasks` | 所有待人处理项：HumanGate、审批、填表、选择、上传、确认 |

#### 7.4.2 卡片驻留规则

`InteractiveCard` 必须声明自己的驻留类型 `residence`。平台统一支持 5 类：

| residence | 用途 | 默认位置 |
|-----------|------|----------|
| `ambient` | 轻量状态摘要，不随聊天滚动 | Header |
| `live` | 运行中短卡，如 LLM / Tool / Run | Chat 对话流；完成后折叠并归档到 Runs |
| `blocking` | 需要人输入才可继续的卡 | Chat 对话流常驻当前位置 + Tasks 镜像 |
| `feed` | 可滚动结果卡，适合 transcript | Chat |
| `archive` | 已结束历史卡 | Runs / Tasks |

统一规则：

1. `live` 卡在运行完成后默认折叠并保留在 Chat transcript 中，同时归档副本到 `Runs`
2. `blocking` 卡在用户提交后进入 `submitted` 或 `validated`，只有当引擎确认恢复或任务关闭后才从 `Tasks` 移除；Chat 中保留已提交状态
3. 同一 run 存在多个并发 `live` 卡时，允许同时出现在 Chat 对话流中，但不得在 Chat 外部单独堆叠遮挡 DAG
4. `ambient` 卡只显示摘要，不展示完整输入输出

#### 7.4.3 标准卡片种类

第一阶段标准化以下卡片：

| kind | 说明 |
|------|------|
| `run-card` | 当前 workflow run 摘要、状态、耗时、错误、artifact 数 |
| `llm-live-card` | 当前 LLM 调用的运行信息、token、输入资源、输出变量 |
| `tool-live-card` | Tool/Compile/Service 调用的运行信息与目标文件 |
| `node-result-card` | 节点输入/输出、result envelope、写入文件、子 run、重跑入口 |
| `artifact-card` | artifact 列表、预览、打开、复制路径 |
| `review-card` | 审批、证据、diff/checklist、决策 |
| `form-card` | 结构化填表、参数补录、上传 |
| `picker-card` | 选 flow / node / component / template / artifact / release |
| `context-card` | 运行时上下文、docs、prompts、source bindings |
| `resource-card` | AI 当前可用的 docs/files/tools/skills/reviews 总览 |

补充约定：

1. 对 `chat-log` shell 的 Agent App，若 workflow 因 `Pause` / `HumanGate` / host resume 参数而阻塞，host 可以在 Chat 中额外投递一个轻量 `blocking` 卡片，用来解释当前等待原因、提示 resume payload，并把用户动作导回 `/api/app-instances/:id/resume`。
2. 这类卡片是 `InteractiveCard` 的 `blocking` 呈现变体，不是新的 workflow step type，也不能替代 `Tasks / Inbox / Review` 中的正式待办记录。
3. 如果 app 同时暴露领域态查询数据源，允许补充对应 slash commands，并在 Chat 中返回结构化卡片摘要；例如 `domain:evolution-state` 对应 `/evolution`，`domain:evolution-claims` 对应 `/claims`。

#### 7.4.4 InteractiveCard 正式 JSON Schema

以下 schema 为平台正式契约。实现可在此基础上扩展字段，但不得删除根字段语义：

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "vl://schemas/interactive-card.v1.json",
  "title": "InteractiveCard",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "cardId",
    "schemaVersion",
    "kind",
    "scope",
    "status",
    "residence",
    "title"
  ],
  "properties": {
    "cardId": {
      "type": "string",
      "minLength": 1
    },
    "schemaVersion": {
      "type": "string",
      "const": "1.0"
    },
    "kind": {
      "type": "string",
      "enum": [
        "run-card",
        "llm-live-card",
        "tool-live-card",
        "node-result-card",
        "artifact-card",
        "review-card",
        "form-card",
        "picker-card",
        "context-card",
        "resource-card"
      ]
    },
    "scope": {
      "type": "string",
      "enum": [
        "host",
        "workspace",
        "app",
        "instance",
        "run",
        "node",
        "review",
        "artifact"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "draft",
        "pending",
        "running",
        "waiting",
        "submitted",
        "validated",
        "resolved",
        "rejected",
        "error",
        "expired",
        "archived"
      ]
    },
    "residence": {
      "type": "string",
      "enum": [
        "ambient",
        "live",
        "blocking",
        "feed",
        "archive"
      ]
    },
    "priority": {
      "type": "string",
      "enum": ["low", "normal", "high", "blocking"],
      "default": "normal"
    },
    "sticky": {
      "type": "boolean",
      "default": false
    },
    "dismissMode": {
      "type": "string",
      "enum": ["never", "manual", "on_resolve", "on_run_end"],
      "default": "manual"
    },
    "title": {
      "type": "string",
      "minLength": 1
    },
    "summary": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "source": {
      "$ref": "#/$defs/source"
    },
    "context": {
      "$ref": "#/$defs/context"
    },
    "metrics": {
      "$ref": "#/$defs/metrics"
    },
    "body": {
      "$ref": "#/$defs/body"
    },
    "inputs": {
      "$ref": "#/$defs/inputs"
    },
    "actions": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/action"
      },
      "default": []
    },
    "resources": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/resourceRef"
      },
      "default": []
    },
    "openRef": {
      "$ref": "#/$defs/openRef"
    },
    "audit": {
      "$ref": "#/$defs/audit"
    }
  },
  "$defs": {
    "source": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "origin": {
          "type": "string",
          "enum": ["workflow", "control-plane", "app", "host", "tool", "actor", "human"]
        },
        "workflowId": { "type": "string" },
        "stepId": { "type": "string" },
        "actorId": { "type": "string" },
        "toolName": { "type": "string" },
        "provider": { "type": "string" },
        "model": { "type": "string" }
      }
    },
    "context": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "workspaceId": { "type": "string" },
        "appId": { "type": "string" },
        "instanceId": { "type": "string" },
        "runId": { "type": "string" },
        "nodeId": { "type": "string" },
        "reviewId": { "type": "string" },
        "artifactId": { "type": "string" },
        "selectedResourceId": { "type": "string" },
        "selectedTab": {
          "type": "string",
          "enum": ["Chat", "Runs", "Context", "Resources", "Tasks"]
        }
      }
    },
    "metrics": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "startedAt": { "type": "string", "format": "date-time" },
        "endedAt": { "type": "string", "format": "date-time" },
        "durationMs": { "type": "integer", "minimum": 0 },
        "inputTokens": { "type": "integer", "minimum": 0 },
        "outputTokens": { "type": "integer", "minimum": 0 },
        "contextFiles": { "type": "integer", "minimum": 0 },
        "artifactCount": { "type": "integer", "minimum": 0 },
        "writtenFiles": { "type": "integer", "minimum": 0 }
      }
    },
    "body": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "layout": {
          "type": "string",
          "enum": ["compact", "detail", "split", "wizard"],
          "default": "detail"
        },
        "sections": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/section"
          },
          "default": []
        }
      }
    },
    "section": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "title", "items"],
      "properties": {
        "id": { "type": "string" },
        "title": { "type": "string" },
        "items": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/bodyItem"
          }
        }
      }
    },
    "bodyItem": {
      "type": "object",
      "additionalProperties": false,
      "required": ["kind"],
      "properties": {
        "kind": {
          "type": "string",
          "enum": [
            "text",
            "kv",
            "code",
            "json",
            "markdown",
            "artifact-list",
            "resource-list",
            "diff-preview",
            "table"
          ]
        },
        "label": { "type": "string" },
        "value": {},
        "collapsed": { "type": "boolean", "default": false }
      }
    },
    "inputs": {
      "type": "object",
      "additionalProperties": false,
      "required": ["schema"],
      "properties": {
        "schema": {
          "$ref": "#/$defs/humanTaskSchema"
        },
        "value": {
          "type": "object"
        },
        "validationState": {
          "type": "string",
          "enum": ["idle", "validating", "valid", "invalid"],
          "default": "idle"
        }
      }
    },
    "humanTaskSchema": {
      "type": "object",
      "additionalProperties": false,
      "required": ["title", "fields"],
      "properties": {
        "title": { "type": "string" },
        "description": { "type": "string" },
        "submitLabel": { "type": "string" },
        "allowDraft": { "type": "boolean", "default": true },
        "fields": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/humanTaskField"
          }
        }
      }
    },
    "humanTaskField": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "type", "label"],
      "properties": {
        "id": { "type": "string" },
        "type": {
          "type": "string",
          "enum": [
            "text",
            "textarea",
            "number",
            "boolean",
            "select",
            "multiselect",
            "radio",
            "checklist",
            "json",
            "code",
            "file-upload",
            "artifact-picker",
            "flow-picker",
            "node-picker",
            "component-picker",
            "template-picker"
          ]
        },
        "label": { "type": "string" },
        "description": { "type": "string" },
        "placeholder": { "type": "string" },
        "required": { "type": "boolean", "default": false },
        "defaultValue": {},
        "options": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/option"
          },
          "default": []
        },
        "accept": {
          "type": "array",
          "items": { "type": "string" },
          "default": []
        },
        "maxFiles": {
          "type": "integer",
          "minimum": 1
        }
      }
    },
    "option": {
      "type": "object",
      "additionalProperties": false,
      "required": ["value", "label"],
      "properties": {
        "value": { "type": "string" },
        "label": { "type": "string" },
        "description": { "type": "string" }
      }
    },
    "action": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "label"],
      "properties": {
        "id": { "type": "string" },
        "label": { "type": "string" },
        "kind": {
          "type": "string",
          "enum": ["primary", "secondary", "danger", "link"],
          "default": "secondary"
        },
        "submit": { "type": "boolean", "default": false },
        "command": { "type": "string" },
        "endpoint": { "type": "string" },
        "method": {
          "type": "string",
          "enum": ["GET", "POST", "PUT", "PATCH", "DELETE"]
        },
        "payload": {
          "type": "object"
        },
        "requiresConfirm": { "type": "boolean", "default": false }
      }
    },
    "resourceRef": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "kind", "label"],
      "properties": {
        "id": { "type": "string" },
        "kind": {
          "type": "string",
          "enum": [
            "doc",
            "file",
            "artifact",
            "tool",
            "skill",
            "review",
            "run",
            "node",
            "component",
            "template"
          ]
        },
        "label": { "type": "string" },
        "path": { "type": "string" },
        "ref": { "type": "string" },
        "previewable": { "type": "boolean", "default": false }
      }
    },
    "openRef": {
      "type": "object",
      "additionalProperties": false,
      "required": ["kind", "id"],
      "properties": {
        "kind": {
          "type": "string",
          "enum": ["file", "run", "node", "artifact", "review", "url"]
        },
        "id": { "type": "string" },
        "path": { "type": "string" },
        "url": { "type": "string" }
      }
    },
    "audit": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "createdAt": { "type": "string", "format": "date-time" },
        "updatedAt": { "type": "string", "format": "date-time" },
        "archivedAt": { "type": "string", "format": "date-time" },
        "createdBy": { "type": "string" },
        "lastUpdatedBy": { "type": "string" }
      }
    }
  }
}
```

#### 7.4.4.1 AskUserQuestion Promise 合约

> 本节来自 `AgentAppRuntimeSpec` v0.3 patch P2（VflowTestRunner 参考实现反馈）。

`AskUserQuestion` 是 workflow / tool 内部向用户请求结构化输入的标准入口。Kernel 的行为合约：

1. **调用侧**：workflow 节点或 App 工具调用 `AskUserQuestion({ title, prompt, fields })`，拿到一个 `Promise<{ ok, values, submittedAt, cancelled? }>`。
2. **Kernel**：生成 `cardId`，基于 `fields` 构造 `form-card`（`residence: blocking`, `scope: run`），挂入 pending 表并通过 SSE 广播 `ask_user` 事件。
3. **用户路径**：用户在 Composer / Sticky Live Rail 看到 form-card，手动填表 → 点 Submit → Host POST `/api/app-instances/:id/resume`（或 `/api/cards/:cardId/submit`）→ Kernel resolve Promise。
4. **AI 路径**（新）：AI 通过 §7.4.5.1 的 `FillFormCard` 工具往表单写 values（不触发 resolve）；用户一键确认 Submit 后 resolve。
5. **取消**：用户 Dismiss card → Kernel resolve with `{ ok: false, cancelled: true }`。
6. **超时**：`fields[].timeout_sec` 可选；超时后 resolve with `{ ok: false, cancelled: true, timedOut: true }`。

最小字段 schema：

```jsonc
{
  "name":       "userRequest",                // required, 英文 identifier
  "label":      "User Request",               // 可选，UI 显示用
  "type":       "string | number | boolean | select | textarea",
  "required":   false,
  "default":    "",                           // 初始值
  "placeholder":"",                           // 可选
  "options":    ["A","B","C"]                 // 仅 select 用
}
```

参考实现：VflowTestRunner v0.2 legacy 运行时（`AgentApp/runtime/legacy-kernel/runtime.js` 中的 `pendingForms` Map + `resolveForm()`）。该实现在 dual-provider（Anthropic + OpenAI）tool_use 循环下通过了端到端验证。

与 `HumanGate`（Blueprint §8.2）的关系：`AskUserQuestion` 是 `HumanGate` 的 **结构化输入变体**；`HumanGate` 侧重 approve/reject/revise 决策，`AskUserQuestion` 侧重参数补录。两者共享 Promise resolution 机制。

#### 7.4.5 生成方式与限制

`InteractiveCard` 只允许通过以下三类来源生成：

1. `声明式生成`
   由 workflow step、app manifest、tool schema、review schema 直接声明
2. `Schema 派生`
   已有输入 schema 的 tool / app command / review，自动编译为 `form-card` 或 `picker-card`
3. `AI 规划 + Host 编译`
   AI 只产出结构化 intent，由 host 校验并编译成正式卡片，不允许模型直接下发 HTML/JS

禁止事项：

1. 不允许模型自由生成前端 DOM 或脚本
2. 不允许把长篇 docs、完整 artifact 内容直接塞进 transcript 代替卡片
3. 不允许用聊天消息模拟审批、填表、上传、资源选择这类有状态交互

#### 7.4.5.1 Card 操作工具（Card operation tools）

> 本节来自 `AgentAppRuntimeSpec` v0.3 patch P1（VflowTestRunner 参考实现反馈）。
> §7.4.5 定义了 AI 如何**生成**卡片；本节补充 AI 如何**操作已存在的卡片**（例如 "你帮我自动填一下"）。

除了"生成"外，AI 还 MAY 通过以下四个受治理的工具操作已显示给用户的 card：

| Tool | 作用域 | 对卡片的影响 | 用户确认默认 |
|---|---|---|---|
| `FillFormCard` | `form-card` | 写入 `inputs.values`，`draft → pending`（**不**触发 submit） | 无 — AI 可自由填写 |
| `SubmitFormCard` | `form-card` | `pending → submitted`，resolve 关联 Promise | **必需** — 用户需手动点 Submit |
| `PickOption` | `picker-card` | 写入 `selection`，`pending → submitted` | **必需** — 一键确认 |
| `DismissCard` | `feed` 驻留的卡片 | 状态转为 `archived` | 无 — 用户已表示完成 |

**治理原则**（对齐 §7.4.5 "AI 规划 + Host 编译"）：

> AI 可以产出 card intent 与 card value，但凡涉及副作用的**提交动作**（form submission、picker confirmation、review decision）必须由用户点击触发。

实现要求：

1. Kernel 的 ToolRegistry 对这四个工具默认分配 `scope: ["card"]` 的权限层
2. Host 在接受 `SubmitFormCard` / `PickOption` 调用时 MUST 校验该 call 是否来自用户动作（UI 事件），不是 LLM tool_use 直接提交
3. 被 AI 填写过的 form-card 在 UI 上 SHOULD 显示"由 AI 预填"的视觉提示（例如 subtle badge），便于用户审阅
4. 审计 trail：`FillFormCard` 的调用记录（actor, timestamp, values）持久化到 Control Plane `gate_reviews` 或新表 `card_operations`

#### 7.4.6 Resources Tab 分类

`Resources` Tab 必须让用户一眼看到当前 AI 能访问什么。第一版统一分 5 类：

| 分类 | 内容 |
|------|------|
| `Execution Context` | workspace、app、instance、run、selected node、params |
| `Knowledge` | docs、prompts、workflow 绑定说明、specs |
| `Files` | workspace files、生成文件、artifacts、preview links |
| `Capabilities` | tools、skills、permissions、app commands、widgets |
| `Human State` | inbox、reviews、pending forms、uploaded evidence |

每个资源项至少支持 3 个动作：

1. `Open`
2. `Copy Ref`
3. `Inject to Chat`

#### 7.4.7 与 HumanGate / Review 的关系

`HumanGate` 与 `Review` 继续作为 workflow/control-plane 原语存在，但在 UI 层一律以 `InteractiveCard` 呈现：

1. `Review` 节点默认映射为 `review-card`
2. 带 `humanTask.fields` 的 review，同步生成 `inputs.schema`
3. 上传附件、下载证据、填写备注、approve/reject/request_changes，均通过卡片动作完成
4. 提交后卡片状态流转为 `submitted -> validated -> resolved/rejected`

规范结论：

> `HumanGate` 解决“流程暂停与决策恢复”，`InteractiveCard` 解决“如何稳定展示与采集这次决策”。

#### 7.4.8 AI Chat 的 Tool / Skill Scope

这一层必须单独定死，否则不同产品的 chat 很容易出现两类错误：

1. 把 `skill` 当成可执行权限，导致“看起来会做”被误判成“允许执行”
2. 把某个 app / run / review 的能力泄漏到全局 host chat

先固定两条基础定义：

1. `Tool` 是可执行能力，走 `ToolRegistry + PermissionManager + approval`，可能产生读写、网络、运行、审批、副作用
2. `Skill` 是行为契约、提示模板、检查单、工作法、角色包，它可以影响思考和路由，但**不能单独赋予执行权限**

规范结论：

> `Skill` 只能塑造“怎么做”，不能扩大“能做什么”；真正的执行上限只由 tool scope / permission scope 决定。

#### 7.4.8.1 三层 Scope

每个 AI Chat 必须同时带 3 层 scope，不能只存一个 `contextScope`：

| Scope | 作用 | 例子 |
|-------|------|------|
| `sessionScope` | 这是谁的会话 | `host` / `workspace` / `instance` / `run` / `review` |
| `resourceScope` | 这个 chat 能看到哪些 docs/files/artifacts/reviews | 当前 workspace、当前 instance、当前 run |
| `capabilityScope` | 这个 chat 能调用哪些 tools，能挂载哪些 skills | `workspace-dev`、`app-runtime`、`review-task` |

固定规则：

1. `sessionScope` 决定身份边界
2. `resourceScope` 决定可见事实范围
3. `capabilityScope` 决定可执行动作
4. 三者必须同时计算，不能互相偷换

#### 7.4.8.2 Effective Tool Scope 计算规则

任意 chat 的 `effectiveToolScope` 必须按“逐层收窄”的交集计算，而不是简单并集。

建议公式：

```text
effectiveToolScope
  = HostSessionView
  ∩ SurfaceProfile
  ∩ AppManifest.permissions.tools
  ∩ InstanceRuntimePolicy
  ∩ ActorDomain.tools.allow
  ∩ Step.tools/toolScope
  - all explicit deny lists
```

说明：

1. `HostSessionView`
   来自宿主为当前 session 创建的 scoped tool view
2. `SurfaceProfile`
   来自当前 chat 所属表面，如 `host-admin`、`workspace-dev`、`app-runtime`
3. `AppManifest.permissions.tools`
   是 app 级 ceiling，只能继续收窄，不能突破宿主上限
4. `InstanceRuntimePolicy`
   是实例运行时补丁，可临时禁用某些工具
5. `ActorDomain.tools.allow`
   是 actor / session domain 的局部允许集
6. `Step.tools/toolScope`
   是 run / node 级的最终收口

如果某层没有声明 allow 集，则按“继承上层”处理；如果声明 deny，则 deny 永远优先。

#### 7.4.8.3 Effective Skill Scope 计算规则

`Skill` 的挂载使用“分层合并 + 高层覆盖低层”的模型，但它只影响提示与流程，不影响权限。

建议来源层级：

```text
effectiveSkillScope
  = platform-shared
  + workspace-local
  + app-local
  + actor-role
  + run-ephemeral
```

同名 skill 的覆盖优先级：

```text
run-ephemeral
> actor-role
> app-local
> workspace-local
> platform-shared
> legacy-home
> builtin-legacy
```

固定规则：

1. `skill` 可以收窄推荐动作、补充 prompt、提供 checklist
2. `skill` 不可直接暴露隐藏 tool
3. `skill` 不可越过 `effectiveToolScope`
4. `role skill` 只对对应 actor / chat session 生效，不能自动外溢到其他 chat

#### 7.4.8.4 不同产品 / Chat 的默认 Scope Profile

第一版统一 5 个 profile：

| profile | sessionScope | 默认资源 | 允许的能力重点 | 明确禁止 |
|---------|--------------|----------|----------------|----------|
| `host-admin` | `host` / `workspace` | workspace、registry、instances、docs | workspace 管理、pack/app 管理、instance 生命周期、SysDoc、诊断 | 直接继承某个 app 的私有 secret / review context |
| `workspace-dev` | `workspace` | 项目文件、workspace docs、compile 结果、project skills | `ReadFile`、`WriteFile`、`Search`、`WorkflowRun`、`VLCompile`、`VLLint`、`VLAutoFix` 等开发工具 | 跨 app 实例控制、其他实例 review/inbox |
| `app-runtime` | `instance` | 当前 app instance 的 runs、artifacts、reviews、core data | `/status`、`/runs`、`/artifacts`、`/core-data`、`/inbox`、`/reviews`、`/start`、`/pause`、`/resume`、`/stop`、`/rerun-step` | workspace 切换、registry 安装卸载、全局 host 管理 |
| `run-debug` | `run` | 当前 run、当前 node lineage、当前 run artifacts | explain-node、compare-runs、open-artifact、rerun-step、node-result 查看 | app/host 级安装、无关 workspace 写操作 |
| `review-task` | `review` / `node` | 当前 review、证据、下载项、上传项 | approve/reject/request_changes、upload、download、delegate、补表单 | 广域文件修改、全局 workflow 调度 |

#### 7.4.8.5 各类 Chat 的推荐挂载

| Chat 类型 | Tool Profile | Skill Mount |
|----------|--------------|-------------|
| `Agent-OS IDE 全局 Chat` | `host-admin` | `platform-shared + workspace-local` |
| `VLC IDE 项目 Chat` | `workspace-dev` | `platform-shared + workspace-local + vl-domain` |
| `Agent App Instance Chat` | `app-runtime` | `platform-shared + app-local + actor-role` |
| `Run / Node 调试 Chat` | `run-debug` | `app-local + actor-role + run-ephemeral` |
| `HumanGate / Review Task Chat` | `review-task` | `app-local + actor-role + review-template` |

推荐理解：

1. `Agent-OS IDE 全局 Chat` 负责“宿主运维和总控”，不是某个 app 的私有执行器
2. `VLC IDE 项目 Chat` 负责“项目开发和编译修复”，不是实例审批中心
3. `Agent App Chat` 负责“某个实例的运行时控制台”，不是全局 workspace 管理器
4. `Review Task Chat` 负责“当前任务的人机交互”，不应拥有宽泛写权限

#### 7.4.8.6 稳定实现基线

前端和后端都不应各自硬编码一套 scope 规则。稳定实现应共享同一份 `ChatScopeProfile` 配置，最少包含：

1. `visibleTabs`
2. `commandSet`
3. `toolFamilies`
4. `skillMount`
5. `cardKinds`

推荐最小配置形态：

```json
{
  "id": "app-runtime",
  "visibleTabs": ["Chat", "Runs", "Context", "Resources", "Tasks"],
  "commandSet": ["/status", "/runs", "/artifacts"],
  "toolFamilies": ["app-runtime-ops", "run-inspect", "artifact-inspect", "review-ops"],
  "skillMount": ["platform-shared", "app-local", "actor-role"]
}
```

第一版按下表落地即可：

| profile | visibleTabs | commandSet | tool / command families |
|---------|-------------|------------|--------------------------|
| `host-admin` | `Chat` `Resources` `Runs` | 默认不暴露 app-runtime slash commands | `doc-admin` `workspace-read` `instance-admin` `diagnostics` |
| `workspace-dev` | `Chat` `Context` `Resources` `Runs` | 默认不暴露 app-runtime slash commands | `workspace-read` `workspace-write` `workflow-dev` `vl-verify` |
| `app-runtime` | `Chat` `Runs` `Context` `Resources` `Tasks` | `/status` `/runs` `/artifacts` `/core-data` `/inbox` `/reviews` `/open-artifact` `/explain-node` `/compare-runs` `/rerun-step` `/start` `/pause` `/resume` `/stop` | `app-runtime-ops` `run-inspect` `artifact-inspect` `review-ops` |
| `run-debug` | `Chat` `Runs` `Context` `Resources` | `/status` `/runs` `/open-artifact` `/explain-node` `/compare-runs` `/rerun-step` | `run-inspect` `artifact-inspect` `rerun-ops` |
| `review-task` | `Chat` `Context` `Resources` `Tasks` | `/reviews` `/open-artifact` | `review-ops` `evidence-io` |

工具族只定义到“稳定家族”即可，不在 profile 表里重复展开：

| family | 稳定展开 |
|--------|----------|
| `doc-admin` | `SysDoc`、`VLSettings` |
| `workspace-read` | `ReadFile`、`Glob`、`Grep`、`VLMetadata`、`VLSymbols`、`VLImpact` |
| `workspace-write` | `WriteFile`、`EditFile`、`VLApplyDelta`、`VLEditSection` |
| `workflow-dev` | `WorkflowRun`、`TeamWorkflowRuntime`、`VLAdjust`、`VLGenerate` |
| `vl-verify` | `VLCompile`、`VLLint`、`VLValidate`、`VLAutoFix`、`AutoTestPipeline` |
| `instance-admin` | 实例启动、暂停、恢复、停止、运行时策略更新 |
| `diagnostics` | runtime/status、run ledger、node result、health/debug 查询 |
| `app-runtime-ops` | `/status`、`/start`、`/pause`、`/resume`、`/stop` |
| `run-inspect` | `/runs`、`/explain-node`、`/compare-runs` |
| `artifact-inspect` | `/artifacts`、`/open-artifact`、`/core-data` |
| `review-ops` | `/inbox`、`/reviews`、approve/reject/request_changes/delegate |
| `rerun-ops` | `/rerun-step` |
| `evidence-io` | upload、download、evidence preview、artifact attach |

固定实现规则：

1. `visibleTabs` 决定 UI 是否渲染该 tab，不允许“显示了但一定报权限错”
2. `commandSet` 决定 slash command 帮助、按钮和命令面板的可见性
3. `toolFamilies` 决定后端为该 session 生成的默认 capability set
4. `review-task` 以卡片动作为主，slash commands 只保留最小辅助集
5. `host-admin` 和 `workspace-dev` 不应复用 `app-runtime` 命令集合

#### 7.4.8.7 Slash Commands 与 UI 可见性

slash commands 必须遵循当前 chat 的 `effectiveToolScope` 与 `resourceScope`。

规则：

1. UI 只展示当前 scope 允许的 commands
2. 即使用户手工输入命令，后端也必须再次校验 scope
3. `app-runtime` 默认开放：
   - `/status`
   - `/runs`
   - `/artifacts`
   - `/core-data`
   - `/inbox`
   - `/reviews`
   - `/open-artifact`
   - `/explain-node`
   - `/compare-runs`
   - `/rerun-step`
   - `/start`
   - `/pause`
   - `/resume`
   - `/stop`
4. `review-task` 默认不开放 `WorkspaceManager`、registry 管理、跨实例调度

#### 7.4.8.8 与 Manifest / Runtime 的关系

Manifest 只负责声明 app 自身 ceiling，不负责跳过宿主治理。

因此：

1. `surface.chat.contextScope` 继续定义 app chat 的身份边界
2. `permissions.tools` 定义 app 自身允许申请的工具 ceiling
3. `runtime policy` 可以在实例级继续收窄
4. `workflow step.tools + toolScope` 可以在 run / node 级继续收窄
5. 前端 `Tabs / Cards / Commands` 的显示必须根据最终 scope 过滤，而不是根据 manifest 生硬展开

规范结论：

> 对任何一个 AI Chat，都必须先问 3 个问题：它是谁、它能看到什么、它到底能执行什么。三者缺一不可。

### 7.5 VL 展示节点

当 workflow 需要生成 UI 展示时：

```json
[
  {
    "id": "Tool_VLGenerate",
    "meta": { "title": "Generate Dashboard UI", "stepType": "Tool" },
    "tool": "VLGenerate",
    "in": { "userRequest": "基于 =$artifactData 生成数据看板", "mode": "3-file" },
    "out": { "/Apps/Dashboard.vx": "=_result" },
    "next": "Tool_VLCompile"
  },
  {
    "id": "Tool_VLCompile",
    "meta": { "title": "Compile VL to JS", "stepType": "Tool" },
    "tool": "VLCompile",
    "in": { "action": "parsePjt" },
    "out": { "$previewUrls": "=_result.previewUrls" }
  }
]
```

编译后，用户通过 `GET /vl-app/:appKey` 在本地浏览器渲染 VL App。

### 7.6 舰队 / 分片 fan-out 范式（Fleet / Sharded fan-out）

当一个 Agent App 要做**大规模并行生产**（批量造组件、批量生成页面、批量跑用例等），用"父编排器 + 每分片子工作流"的舰队范式，而不是把所有工作塞进一个巨型 loop。参考实现：`agent-component-expansion-lab`（Mass-dev Component Factory）。

#### 7.6.1 静态 N 路并行 Fork

引擎靠 step 上是否存在 `children: []` 数组识别并行 fan-out——**没有 `type: "Fork"` 这种 step 类型**。fork step 自身不带 `type` / `tool` / `target`，只有 `children`（要并行的子 step id 列表）和 `next`（join 目标）：

```json
{
  "id": "Fork_100_Fleet",
  "title": "Fleet · launch N shard workers concurrently",
  "children": ["Run_f_form", "Run_f_display", "Run_f_table", "..."],
  "next": "Tool_200_Aggregate"
}
```

每条 lane 是一个子 step，通常是 `WorkflowRun` 调一个子工作流，并且必须：

- `"next": "RETURN"` —— fork 子 step 完成后回到 fork，而不是顺序流走；
- `"allowError": true` —— **一条 lane 失败不能拖垮整个舰队**，失败通过它自己的 honest 工件浮现；
- `"mode": "sync"` + `"emit_events": true` —— 同步等待、转发子运行事件给宿主监视器；
- 省略 `work_dir` —— 子运行继承父运行的 workDir，避免并行分支抢同一个共享变量。

```json
{
  "id": "Run_f_form",
  "tool": "WorkflowRun",
  "input": {
    "mode": "sync", "emit_events": true,
    "workflow_path": "component-factory-shard-worker.json",
    "params": { "category": "f_form", "batchId": "=$batchId", "dryRun": "=..." }
  },
  "out": { "$f_formRun": "=_result" },
  "next": "RETURN",
  "allowError": true
}
```

> 分片数应在分片阶段就**静态确定并固定写死**（例如组件工厂的 8 大族），让 fork 的 children 列表可静态校验、监视器可立即显示全部 lane。不要用动态生成的 children——那会让引用完整性和监视都失去确定性。

#### 7.6.2 父编排器的标准段落

1. **解析 / 分片**：一个确定性脚本（Bash step）把输入去重后按分片键切成 N 个分片清单，**总是写全 N 个文件（即使为空）**，并为每个分片播种一个初始状态文件，让监视器一开始就显示全部 lane。
2. **Fork fan-out**：§7.6.1 的静态 N 路并行。
3. **Join + 汇总**：fork 的 `next` 指向一个聚合脚本，把 N 个分片的真实状态文件滚成一个 `fleet-summary.json`。
4. **重建真相视图**：从真实目录 + 磁盘重建快照 / 索引（**不要用 LLM 猜测产物清单**）。
5. **运行报告**：把各阶段真实 stdout 拼成人读 Markdown，落到 `Process/Run/`。

#### 7.6.3 每分片子工作流

子工作流自包含：读自己的分片清单 → 标记 lane running → 空分片直接 Stop → 内部 `parallel` loop 生成 → **真实确定性 QA + 提升** → **dry-run 闸门控制的诚实发布** → 用真实报告写最终 lane 状态。它通过 `Process/ComponentCatalog/fleet/<shard>.json` 这类**状态文件**与父级通信，父级聚合脚本只读这些真实文件。

#### 7.6.4 舰队监视面（Fleet Monitor surface）

舰队进度通过 manifest 的数据源 + view 投影，而不是塞进 statusBar：

- `dataSources`: `fleet`（`file:.../fleet-summary.json`）+ `fleetLanes`（`glob:.../fleet/*.json`）；
- `views`: 一个 `large-app-page` view 渲染 totals + 每条 lane 的 status/qa/promoted/published，外加一个 `vl-floating-card` miniCard；
- `pages` / `floatingCards` 引用该 view。

#### 7.6.5 诚实纪律（强制）

舰队范式最容易滑向"看起来完成"。固定四条硬规则：

1. **QA 必须真实**：用确定性结构检查或真实测试，不允许伪造 pass。失败件落 `Rejected/` + 错误报告。
2. **发布默认 dry-run**：`dryRun` 默认 `true`；真实上线需 `dryRun=false` **且**磁盘有平台 cookie。LIVE 发布在 UI 上必须是 confirm-gated 的显式动作。
3. **快照/索引来自磁盘真相**：从真实 catalog + 文件系统重建，不用 LLM 猜。
4. **可视化审计不造假**：抽样审计只给"在画廊里搜 moduleName"这类**诚实提示**；没有可靠截图管线或 deep-link 就不要编造。manifest 只声明工作流真正调用的 tool 权限（用了什么声明什么，没用的真实工具也不声明）。

---

## 8. VL 展示层规范

### 8.1 两条渲染路径

**路径 A：本地渲染（开发/测试）**
```
VL 源 → VLCompile → ParseVL API → previewUrl + caseId
  → vl-runner 生成本地 HTML (注入 player.js + widgets.js from CDN)
  → GET /vl-app/:appKey → 浏览器渲染
```

**路径 B：云端渲染（生产/分享）**
```
VL 源 → VLCompile → ParseVL API → previewUrl
  → https://editor.visuallogic.ai/preview/{caseId}?nid=...&gid=...
  → 任何用户可通过 URL 直接访问
```

### 8.2 Artifact 视图 vs Core Data 视图

| 视图 | 数据源 | 用途 |
|------|--------|------|
| **Artifact 视图** | `control-plane:artifacts` | 展示 workflow 产出物（报告、代码、文件） |
| **Core Data 视图** | `domain:<app-id>` | 展示业务数据（任务列表、监控指标、审批单） |

两种视图都通过 VL 组件渲染，从 Component Factory 引用组件。

### 8.3 可用的 Component Factory 组件

| 组件 | 用途 |
|------|------|
| `V21ChatPanel` | AI 对话面板 |
| `V21TaskBoard` | 任务看板 |
| `V21AlertCard` | 告警卡片 |
| `V21CodeBlock` | 代码展示 |
| `V21ReviewPanel` | HumanGate 审批面板 |
| `V21AgentStatus` | Agent 状态指示器 |
| `V21MetricGrid` | 指标网格 |
| `V21StatusTimeline` | 状态时间线 |
| `V21SignalFeed` | 信号/告警 Feed |

---

## 9. 云端投放规范

### 9.1 自动绑定云端 Workspace

首次编译时自动执行：
```javascript
ensureBoundCloudWorkspace(config)
  → 调用 /ih5/editor/workspace/createWorkspace 创建云端 workspace
  → 返回 gid（全局唯一 ID）
  → 保存到 .vl-code/project.json
```

### 9.2 投放流程

```
1. 开发者在本地编写 VL 源文件
2. 运行 VLCompile → 调用 ParseVL API（自动上传 + 编译）
3. ParseVL 返回 preview URL（立即可访问）
4. 分享 preview URL 给用户
5. 可选：运行 launchVersion 发布正式版本
```

### 9.3 Workspace File Sync API

| 操作 | API | 说明 |
|------|-----|------|
| 批量写入 | `POST /ih5/editor/workspace/writeFiles` | 最多 20 个文件/次 |
| 批量读取 | `POST /ih5/editor/workspace/readFiles` | 支持版本号 |
| 删除 | `POST /ih5/editor/workspace/deleteFiles` | 批量删除 |
| 列表 | `POST /ih5/editor/workspace/listFile` | 列出云端文件 |
| 发布版本 | `POST /ih5/editor/work/launchVersion` | 发布正式版本 |

### 9.4 Resource Hub 三通道

```
workspace-local        → 本地开发
  ↓ publishToCloud(channel: 'private')
cloud-private          → 个人备份（仅自己可见）
  ↓ submitForReview()
cloud-submitted        → 待审核（开发者 + 管理员可见）
  ↓ approveAndPromote()
platform-shared        → 平台共享（所有用户可见）
```

---

## 10. 控制平面与审计

### 10.1 存储

文件：`.vl-code/control-plane.sqlite`

### 10.2 核心表

| 表 | 职责 |
|----|------|
| `runs` | Workflow 执行记录 |
| `actor_sessions` | Actor 会话 |
| `actor_tasks` | 任务 envelope |
| `artifacts` | 产出物（path, status, producer） |
| `artifact_edges` | 血缘关系（from → to） |
| `gate_reviews` | 审批记录（decision, reviewer, notes） |
| `gate_review_checks` | 验证检查（compile/lint/test） |
| `resources` | 资源元数据（kind, version, owner） |
| `resource_versions` | 资源版本 |
| `task_queue` | 异步任务队列（dispatchTask/awaitTask） |

### 10.3 Resource ID 约定

```
workflow:<name>         → 工作流定义
artifact:<relativePath> → 产出物
code:<relativePath>     → 代码文件
data:<name>             → 数据资源
review:<envelopeId>     → 审批记录
```

版本编码：`<resourceId>@<runId>`

### 10.4 查询 API

| API | 用途 |
|-----|------|
| `GET /api/workflow/runtime-manifest` | 运行时能力清单 |
| `GET /api/workflow/run-ledger?runId=` | 执行记录详情 |
| `GET /api/workflow/run-state?runId=` | 当前运行状态 |
| `GET /api/workflow/node-result?nodeId=` | 节点输出 |
| `GET /api/resource-tree` | 资源树 |
| `GET /api/app-instances/:id/runs` | 实例执行历史 |
| `GET /api/app-instances/:id/resources` | 实例产出的资源 |

---

## 11. Pack → Release → Instance 生命周期

### 11.1 安装

```
POST /api/apps/install { flow }          // flow = 携带 `app` 块的入口 workflow
  → manifestFromFlow(flow)               // 从 `app` 块 + Pause/Review 步骤派生 manifest
  → validateAppManifest(derivedManifest)
  → 写入 .vl-code/workflows/<id>.json     // flow 是单一产物（事实来源）
  → (可选) 写出派生缓存 .vl-code/registry/apps/<appId>.app.json
  → INSERT app_packs
  → INSERT app_releases (初始版本)
```

安装 = 把携带 `app` 块的 flow 放进 `.vl-code/workflows/`，discovery（`discoverAgentApps`）会自动从 flow 派生 manifest；落盘的 `.app.json` 仅是派生缓存。

### 11.2 启动

```
POST /api/app-instances/start { appId, instanceId? }
  → ensureInstance() → INSERT app_instances (status: stopped)
  → startInstance()
    ├── Workflow 模式: WorkflowExecutor.execute(entryWorkflow)
    └── Service 模式: spawn(command, args, env)
  → status: running
```

### 11.3 暂停/恢复

```
POST /api/app-instances/:id/pause   → executor.requestPause() → status: paused
POST /api/app-instances/:id/resume  → executor.resume() → status: running
```

### 11.4 升级/回滚

```
POST /api/apps/:appId/upgrade   { instanceId, releaseId }
POST /api/apps/:appId/rollback  { instanceId, releaseId }
```

### 11.4.1 Agent-OS 资源继承

Agent App 默认复用当前 Agent-OS workspace 的共享资源，不要求每个 app 单独登录或手工复制 key。

固定规则：

1. Workflow runtime 通过 host config 读取当前 Settings、SecretRoot、平台 cookie、Resource Center、SysDoc、ToolRegistry。
2. `runtime.service` sidecar 启动时由 host 注入共享环境变量：`VL_PLATFORM_COOKIE` / `IH5BEARER_COOKIE`、常见 provider key（如 `OPENAI_API_KEY`、`ANTHROPIC_API_KEY`、`GEMINI_API_KEY` / `GOOGLE_API_KEY`）、`OPENAI_BASE_URL`、`VL_SECRET_SOURCE_PATH`、`VL_AGENT_APP_SECRET_PROVIDER_IDS`。
3. `permissions.secrets: []` 表示继承当前 Agent-OS 可用 provider；声明 `["openai"]`、`["anthropic"]`、`["gemini"]` 等 provider id 时，只注入对应 provider。
4. `runtime.service.env` 只能放非敏感默认值或显式覆盖项；不要把真实 API key、平台 cookie、JWT、个人 token 写入 manifest、workflow JSON、README 或可提交代码。
5. 前端 VL surface / browser 页面不直接读取 secret 环境变量；需要平台认证或 provider 调用时，应走 host tool、workflow、或 service sidecar。

### 11.5 隔离模型

| 维度 | 说明 |
|------|------|
| Identity | 独立 appId + instanceId |
| File | 独立 workDir + artifactDir |
| Tool | scoped ToolRegistry view |
| Secret | 独立 secretScope；默认继承 Agent-OS provider/cookie，可用 permissions.secrets 收窄 |
| Data | 独立 controlPlaneNamespace |
| Quota | 独立 quotaProfile |
| Network | permission.network allowlist |
| Review | 独立 review chain |

---

## 12. Step-by-Step 开发指南

### 步骤 1：创建项目目录

```bash
mkdir -p ~/Documents/VLAgentApps/AgentApps/MyApp/{.vl-code/{workflows,skills},AgentApp/{runtime,prompts,data},Apps,Sections,ExtComponents,Services,Database,Theme,Process/Artifacts}
```

### 步骤 2：编写入口 flow（顶层带 `app` 块）

创建 `.vl-code/workflows/my-app-main.json`。它是**单一产物**：顶层是 workflow 本体（`version` / `name` / `steps`），manifest 写在 `app` 块里（字段参考 §4.2 的完整字段定义）。manifest 在加载时由 `manifestFromFlow` 从该 `app` 块 + flow 的 `Pause` / `Review` 步骤派生，**无需另写 `.app.json`**：

```jsonc
{
  "version": "4.1",
  "name": "my-app-main",
  "steps": [
    { "id": "LLM_Init", "in": { "messages": [...] }, "out": { "$result": "=_result" }, "next": "..." },
    ...
  ],
  "app": {
    "$schema": "VL-AgentOS/app-pack-manifest-v0.1",
    "kind": "app",
    "id": "my-app",
    "version": "0.1.0",
    "title": "My App",
    "entryWorkflow": "my-app-main",
    "permissions": { "tools": ["WorkflowRun"], "network": [], "workspace": ["Process/**"], "secrets": [] }
    // ... 其余字段见 §4.2
  }
}
```

### 步骤 3：编写 Service Runtime（可选）

创建 `AgentApp/runtime/server.mjs`，提供 `/health` endpoint。

### 步骤 4：编写 VL UI（可选）

创建 `Apps/MyApp.vx`、`Sections/*.sc`、`ExtComponents/*.cp`。

### 步骤 5：安装并运行

```bash
# 通过 API 安装：提交携带 `app` 块的入口 flow（discovery 自动派生 manifest）
curl -X POST http://127.0.0.1:9000/api/apps/install \
  -H 'Content-Type: application/json' \
  -d @.vl-code/workflows/my-app-main.json

# 启动实例
curl -X POST http://127.0.0.1:9000/api/app-instances/start \
  -H 'Content-Type: application/json' \
  -d '{"appId":"my-app"}'
```

### 步骤 6：编译 VL UI 并预览（可选）

```bash
# 编译
curl -X POST http://127.0.0.1:9000/api/compile \
  -H 'Content-Type: application/json' \
  -d '{"action":"parsePjt"}'

# 本地预览
open http://127.0.0.1:9000/vl-app/MyApp
```

---

## 13. 常见反模式（Don'ts）

1. **不要把 Service Runtime 当作全部** — Service 只是辅助，entryWorkflow 才是执行主体
2. **不要手写 HTML 代替 VL** — VL 是原生展示层，手写 HTML 无法享受编译/预览/云端投放能力
3. **不要把 AI Chat 当作独立系统或全局聊天框** — Chat 是 app runtime console 的交互入口，必须绑定实例上下文
4. **不要跳过 Control Plane** — 所有 run/artifact/review 必须持久化，不能只存在 AI context 中
5. **不要把 Artifact 当作共享资源** — Artifact 是执行证据，要共享需先提升为 doc/tool/component/pack
6. **不要在 workflow JSON 里硬编码** — 使用 params 和 docs 绑定，保持 workflow 可复用
7. **不要忽略 ResultEnvelope** — 每个节点的输出都应该通过 envelope 契约标准化
8. **不要手动管理进程** — 使用 Kernel 的 Instance Manager 管理 Agent App 生命周期
9. **不要混淆 Pack 和 Plugin Runtime** — Pack 是分发层，Plugin Runtime 是执行治理层
10. **不要用旧文档覆盖运行时真相** — 当文档和 `runtime-manifest` 冲突时，以 runtime 为准
11. **不要把 Workflow Definition / Workflow Run / App Instance 混成一层** — workflow 是执行定义，run 是执行事实，instance 是运行实体
12. **不要把完整 Agent App 当普通 Subflow 复用** — `3-file/6-file` 这类默认是 workflow；只有需要独立实例生命周期与隔离面时才升级为 Agent App，并通过 app dispatch 启动

## 12. 并行检查点与取消契约（v2.6.1）

Engine 4.21.9 的开放 fan-out 检查点保存各分支游标、局部变量和待汇合位置。Host 必须在每次 onCheckpoint 时保存当前 Run 的检查点，包括另一个分支已经等待人工时才完成的分支；普通启动和节点重新运行使用同一保存逻辑。保存时保留其它分支的等待节点、审批和状态，并拒绝旧执行器、其它 Run 和倒序事件的写回。

Resume 保留原 Run；从节点重新运行创建新 Run，移除原恢复帧、reviewState 和 pauseState，不把旧审批伪装成新 Run 的等待。并行循环中的各迭代拥有独立的子分支完成记录，不能因其它迭代完成过同名节点而跳过执行。

损坏的 recovery 不得退回普通 currentStepID 路径后执行；应在产生新检查点或副作用前拒绝。开放并行恢复遇到结果未知的工具调用或无可信恢复协议的自定义 handler 时保持受阻。旧历史中缺失的分支信息不得按猜测补写。

取消必须保留 cancelled，而不是 completed/failed 的替代展示。原生 Pause/Review 取消后退出等待，不生成虚构的人工答案，迟到 Continue 被拒绝；独立发生的失败仍记失败。图上的已完成节点保留 done/cached 来源，当前被取消节点显示 cancelled。

Flow31 对 MatrixInteract / RequestHumanInput 的纯人工等待已有本地真实进程 SIGKILL 验证，包括审批答案已持久保存而 Engine 尚未接收时，以原 requestId、token 和答案恢复同一 Run。已完成分支和 join 不重复执行；未知自定义副作用与旧历史缺失恢复帧仍拒绝。进程所有权复用既有 SQLite 锁表，普通 TTL 不能证明原进程退出；原生执行真正结束后才释放。

这些局部结果不代表 Matrix L05 通过。一次性 issuer 冷恢复仍未实现；额度中断和真实 Hand/Authority 恢复须保留独立验收证据。正式发布以完整候选安装组合与原业务用例为准。
