# VLCode AI Assistant 控制手册

> **版本**: VLCode v1.172+ | **状态**: 生产验证  
> **核心目标**: 掌握 AI Assistant 对工作流 DAG 的完整操控能力

---

## 目录

1. [快速入门](#1-快速入门)
2. [基础对话能力](#2-基础对话能力)
3. [工作流 DAG 控制——核心](#3-工作流-dag-控制核心)
   - [3.1 启动工作流](#31-启动工作流)
   - [3.2 实时监控](#32-实时监控)
   - [3.3 中断与暂停](#33-中断与暂停)
   - [3.4 恢复与继续](#34-恢复与继续)
   - [3.5 Watch 规则——条件自动触发](#35-watch-规则条件自动触发)
   - [3.6 变量注入与步骤跳转（时间旅行）](#36-变量注入与步骤跳转时间旅行)
   - [3.7 查看变量与产出物](#37-查看变量与产出物)
4. [高级 DAG 操控——实操案例集](#4-高级-dag-操控实操案例集)
   - [案例 A: 节点断点 + 变量注入](#案例-a-节点断点--变量注入)
   - [案例 B: 步骤时间旅行（跳过 39 步）](#案例-b-步骤时间旅行跳过-39-步)
   - [案例 C: 阶段拦截（抢在执行前 abort）](#案例-c-阶段拦截抢在执行前-abort)
   - [案例 D: 运行中文件注入](#案例-d-运行中文件注入)
   - [案例 E: 多重暂停链（单次运行两次自动暂停）](#案例-e-多重暂停链单次运行两次自动暂停)
   - [案例 F: 分支强制路径（注入变量控制分支走向）](#案例-f-分支强制路径注入变量控制分支走向)
   - [案例 G: 运行中热挂载 Watch（动态注册）](#案例-g-运行中热挂载-watch动态注册)
5. [项目工具能力](#5-项目工具能力)
6. [代码生成与 VL 开发](#6-代码生成与-vl-开发)
7. [常见问题与诊断](#7-常见问题与诊断)
8. [速查卡](#8-速查卡)

---

## 1. 快速入门

VLCode 的 AI Assistant 是一个**内嵌于 IDE 的智能代理**，拥有直接操控工作流引擎、读写工程文件、调用编译器等的完整能力。它不是普通的问答机器人——它可以启动一个 51 步的代码生成工作流、在第 12 步暂停、修改变量、然后从第 30 步重新续跑。

### 打开方式

- **Web IDE**: `http://localhost:4000` → 左侧 AI Chat 面板
- **Electron 桌面**: 直接打开 VLCode 应用

### 理解输出面板

| 面板 | 显示内容 |
|------|---------|
| **AI Chat（主对话区）** | 摘要、结论、需要你决策的问题 |
| **Detail Log（右侧日志）** | 每个步骤的启动/完成/错误、文件写入、变量变化、LLM 流式输出 |
| **Flow Tab（DAG 视图）** | 工作流节点高亮动画，直观看当前跑到哪一步 |
| **Status Bar（底部）** | 当前步骤名，实时刷新 |

---

## 2. 基础对话能力

### 文件操作

```
"读取 Apps/MainApp.vx 的内容"
"把 Sections/Dashboard.sc 的第 42 行改成 ..."
"列出 ExtComponents/ 目录下所有 .cp 文件"
"写一个新文件 Process/Plan.md，内容如下 ..."
```

### 编译与 Lint

```
"编译一下当前项目"
"lint 这个文件并显示错误"
"自动修复最近的编译报告"
```

### 符号查询

```
"#EventList 这个 VL 组件在哪里定义？"
"哪些 section 引用了 UserService？"
```

### 系统文档查询

```
"查一下 VL 4.3 的 #FormField 语法"
"WorkflowSpec 里 Loop 步骤的 source 字段怎么用？"
```

---

## 3. 工作流 DAG 控制——核心

这是 AI Assistant 最强大的能力。工作流是一个**有向无环图（DAG）**，由数十个步骤（LLM 调用、Tool 调用、Fork/Loop/Branch 等）组成。AI 可以在任意时刻介入这个执行过程。

### 架构概览

```
用户指令 ──→ AI Assistant
                │
                ├── WorkflowControl tool  (启动/暂停/恢复/watch)
                ├── WorkflowRerunStep tool (步骤跳转/变量注入)
                ├── WorkflowRun tool       (执行/验证)
                └── WorkflowEdit tool      (在线编辑 DAG)
                
                    ↕ HTTP SSE
                    
            VLCode Server :4000
                │
                └── Workflow Executor (DAG 引擎)
                        ├── 节点状态追踪
                        ├── 检查点持久化
                        ├── Watch 规则引擎
                        └── 变量管道 (pipeline variables)
```

### 3.1 启动工作流

**自然语言指令：**
```
"用 meta-direct-codegen 工作流，目标：开发一个待办事项 app"
"启动 3-file-codegen，输入 PRD 如下..."
"跑一下 metadata-check，看看项目健康状况"
```

**底层 API：**
```
POST /api/workflow/execute
{
  "workflowName": "meta-direct-codegen",
  "params": { "goal": "开发一个待办事项记事本" },
  "clientRunToken": "my_run_001"
}
```
返回一个 **SSE 流**，实时推送所有节点事件。

**查看可用工作流：**
```
"列出所有工作流"
"有哪些代码生成工作流？"
```

目前有 **72 个工作流**，涵盖：
- `meta-direct-codegen` — 51步，小型项目完整代码生成
- `enterprise-meta-cascade-codegen` — 122步，企业级瀑布生成
- `design-reference-codegen` — 10步，设计图驱动生成
- `debug-multi-file` / `compile-fix` — 调试修复
- `theme-customize` — 主题定制
- `metadata-check` — 只读健康检查

---

### 3.2 实时监控

工作流运行时，AI 可以随时查询进度：

```
"现在跑到哪一步了？"
"status"
"当前完成了几步？"
```

**返回信息示例：**
```json
{
  "active": true,
  "workflowName": "meta-direct-codegen",
  "runID": "wf_1780981829097",
  "completedSteps": ["ClearFiles_005", "LLM_010_GenMeta", "NormalizeMeta_012"],
  "runningSteps": ["LLM_040_GenService", "LLM_060_GenSection"],
  "totalSteps": 51
}
```

**在 Flow Tab 中**，你会看到每个节点的实时颜色变化（与 `public/workflow-editor.html` 的节点状态样式一致）：
- 灰色 = 等待（未执行）
- 青色脉冲 = 即将执行（排队中）
- 橙色脉冲 = 运行中
- 绿色 = 完成
- 紫色脉冲 = 暂停
- 红色 = 错误

---

### 3.3 中断与暂停

#### abort — 立即终止

```
"停止"  "终止"  "abort"  "不跑了"
```

立即 kill 所有 LLM 调用和工具执行，无法恢复。适用于：
- 发现方向错了，整个重来
- 工作流卡死
- 紧急叫停

#### pause — 在下一个检查点暂停

```
"暂停"  "pause"  "先暂停一下"
```

在**当前正在执行的最小步骤完成后**暂停，保留完整检查点（所有已完成步骤、变量、文件）。适用于：
- 想先看看中间结果再决定继续不继续
- 需要手动修改某个生成文件再恢复
- 想检查变量状态

> **重要**: `pause` 不是立即停，而是在下一个步骤边界停。如果当前有 LLM 正在生成（可能 30-60 秒），需要等它完成。如果想立即停，用 `abort`。

---

### 3.4 恢复与继续

#### resume — 从暂停点原地继续

```
"继续"  "resume"  "恢复"
```

在原 SSE 流上从检查点直接继续，不重新创建 run。

#### continue — 从最近中断点重跑

```
"continue"  "从断点继续"  "继续上次"
```

找到最近的可恢复检查点，创建一个新 run 从该检查点接续跑。适用于：
- 工作流因网络错误/LLM 超时中断
- abort 之后想从断点重来
- 错误修复后重试

#### rerun-from-step — 从指定步骤重跑

```
"从 NormalizeMeta_012 步骤重跑"
"重跑 LLM_070_GenApp"
"从第 5 步开始，把 goal 改为 ..."
```

这是最强大的功能之一。AI 会：
1. 找到最近的检查点
2. 保留检查点里所有已完成步骤的结果
3. 从你指定的步骤开始重新执行
4. 可以同时注入新的变量覆盖旧值

---

### 3.5 Watch 规则——条件自动触发

Watch 规则是工作流的**自动驾驶系统**，可以让你在不手动盯屏幕的情况下，在指定条件满足时自动执行动作。

#### 注册 Watch 规则

```
"如果 LLM_070_GenApp 出错就停止"
"当 ValidateOutputs_075 开始前自动暂停"
"NormalizeMeta_012 完成后暂停，让我看看变量"
"如果任意节点报错就 abort"
```

**三个维度配置：**

| 参数 | 可选值 | 含义 |
|------|--------|------|
| `event` | `node_start` | 节点**即将**执行时触发 |
| | `node_done` | 节点**执行完成**时触发 |
| | `node_error` | 节点**报错**时触发 |
| `action` | `pause` | 暂停（可恢复） |
| | `abort` | 终止（不可恢复） |
| `nodeId` | 任意步骤 ID | 监控特定节点（省略 = 监控所有节点） |

**实操示例：**
```
"注册一个规则：LLM_010_GenMeta 完成后暂停"
→ set_watch(nodeId:"LLM_010_GenMeta", event:"node_done", action:"pause")
→ 返回 ruleId: watch_007

"查看所有 watch 规则"
→ list_watches

"删除 watch_007"
→ clear_watch(ruleId:"watch_007")

"清空所有规则"
→ clear_watch  (不传 ruleId)
```

#### ⚠️ 关键知识点：Fork 节点的 node_done 语义

Fork 节点（如 `Fork_AllCode`）的 `node_done` **在子节点执行前**就会触发！

原因：引擎设计是先 emit `StepDone` 事件，再 dispatch 子节点：
```
Fork_AllCode StepDone → [node_done 触发]
    ↓
执行子节点: Loop_Services, Loop_Components, Loop_Sections, Loop_Apps
    ↓
_moveToNext → ValidateOutputs_075 [node_start 触发]
```

**正确做法：** 想在 Fork 的所有子节点完成后暂停 → 监控 Fork 的**后继节点**的 `node_start`：
```
"Fork_AllCode 的所有并行子节点跑完后暂停"
→ set_watch(nodeId:"ValidateOutputs_075_ProjectFiles", event:"node_start", action:"pause")
```

---

### 3.6 变量注入与步骤跳转（时间旅行）

这是最高级的 DAG 操控能力，可以**修改流水线变量**并**跳转到任意步骤**。

#### 场景：LLM 生成了不理想的 meta → 修改后从下一步继续

```
用户: "LLM_010 生成的 projectMeta 里 services 太多了，帮我简化"

AI 操作:
1. 查看当前 $projectMeta 变量
2. 构造简化版 meta（只保留 2 个 service）
3. rerun from NormalizeMeta_012_ProjectMeta with overrides: {projectMeta: simplified}
4. 工作流从 NormalizeMeta 开始，用新 meta 继续跑
```

#### 场景：跳过所有代码生成，直接到 Stop_Done

```
"我不想跑代码生成了，直接跳到 Stop_Done"
→ rerun from step: Stop_Done (checkpoint 保留之前所有变量)
→ 16.7 秒完成（正常要 5 分钟）
```

#### 技术细节

`/api/workflow/rerun` 接受：
- `workflowName` — 工作流名
- `checkpoint` — 来自 `/api/workflow/{runID}/checkpoint`（包含所有变量状态）
- `stepID` — 从哪个步骤开始执行
- `overrides` — 覆盖 checkpoint 里的变量（键名对应变量名）

```javascript
// 变量注入示例
overrides: {
  projectMeta: { ...simplifiedMeta },  // 覆盖 $projectMeta
  "$codeValidation": { errCount: 0 }   // 覆盖 $codeValidation，让 branch 走 clean 路径
}
```

---

### 3.7 查看变量与产出物

#### 查看流水线变量

```
"当前有哪些变量？"
"$projectMeta 里有几个 app？"
"查看 $codeValidation"
```

常见变量：

| 变量名 | 含义 |
|--------|------|
| `$projectMeta` | 项目结构描述（apps/sections/services/components） |
| `$projectMetaStr` | 同上的 JSON 字符串 |
| `$vdbContent` | 数据库 schema 内容 |
| `$vthContent` | 主题文件内容 |
| `$parallelPromptSlices` | 每个文件的独立 prompt 上下文 |
| `$codeValidation` | 代码 lint 结果（errCount, warningCount, errList） |
| `$compileResult` | VL 编译结果 |
| `$metaAlignment` | 代码与 meta 的对齐报告 |
| `$outputValidation` | 文件存在性验证结果 |

> ⚠️ 变量 API 对超过 500 字符的值会**截断显示**（显示 preview 前 200 字符）。大型变量需要通过 read-file 读取磁盘上的对应 JSON 文件。

#### 查看生成文件

```
"这次生成了哪些文件？"
"artifacts"
```

返回本次 run 写入的所有文件路径。

```
"检查 Apps/MainApp.vx 是否生成了"
"读取 Process/ProjectMeta.json"
```

---

## 4. 高级 DAG 操控——实操案例集

以下 4 个案例均已在本机实测通过（VLCode v1.172.0）。

---

### 案例 A: 节点断点 + 变量注入

**目标**: 在 LLM 生成 ProjectMeta 之后自动暂停，检查内容，然后注入简化版继续执行。

**适用场景**: LLM 生成的 meta 过于复杂（太多 service/component），想精简后再生成代码。

**完整对话流程**:
```
用户: "启动 meta-direct-codegen，目标：开发一个简单待办事项 app。
      在 LLM_010_GenMeta 完成后自动暂停，让我看看生成的 meta。"

AI:
  1. set_watch(nodeId:"LLM_010_GenMeta", event:"node_done", action:"pause")
     → ruleId: watch_001
  
  2. 启动工作流
     → POST /api/workflow/execute  {workflowName: "meta-direct-codegen", params: {goal: "..."}}
  
  3. 等待 pause 触发（约 20-30 秒）
     → checkpoint: {status: "paused", currentStepID: "LLM_010_GenMeta"}
  
  4. 查询变量
     → GET /api/workflow/variables
     → 显示 $projectMeta: {apps: [MainApp], sections: [HomePage], services: [DataService]}
  
AI 向用户报告:
  "已暂停。LLM 生成了 1 个 app、1 个 section、2 个 service。
   是否要简化？或者直接继续？"

用户: "service 太多了，只保留 1 个，然后继续"

AI:
  5. 构造简化 meta（去掉一个 service）
  
  6. rerun from NormalizeMeta_012_ProjectMeta with overrides: {projectMeta: simplified}
     → 工作流从 NormalizeMeta 开始用新 meta 继续
  
  7. 等待完成
     → "代码生成完成，共 41 步，写入 7 个文件"
```

**关键 API 调用**:
```javascript
// Step 1: 注册断点
await fetch('/api/workflow/watch', {
  method: 'POST',
  body: JSON.stringify({
    nodeId: 'LLM_010_GenMeta',
    action: 'pause',
    event: 'node_done'
  })
})

// Step 6: 注入变量从指定步骤续跑
const checkpoint = await fetch('/api/workflow/{runID}/checkpoint').then(r => r.json())
await fetch('/api/workflow/rerun', {
  method: 'POST',
  body: JSON.stringify({
    workflowName: 'meta-direct-codegen',
    checkpoint,
    stepID: 'NormalizeMeta_012_ProjectMeta',
    overrides: { projectMeta: simplifiedMeta }
  })
})
```

---

### 案例 B: 步骤时间旅行（跳过 39 步）

**目标**: 在完成第 3 步（NormalizeMeta）后，直接跳到第 49 步（Stop_Done），绕过所有代码生成。

**适用场景**: 
- 测试 meta 生成质量，不需要完整代码生成
- 重新跑后段步骤而不重跑耗时的 LLM 步骤
- 调试工作流的收尾步骤

**完整对话流程**:
```
用户: "启动代码生成，但我只想测试 meta 生成，不需要跑代码生成步骤。
      NormalizeMeta 完成后暂停，然后直接跳到 Stop_Done。"

AI:
  1. set_watch(nodeId:"NormalizeMeta_012_ProjectMeta", event:"node_done", action:"pause")
  
  2. 启动工作流
  
  3. 等待暂停（约 30 秒，只运行了 3 步）
     → completedSteps: [ClearFiles_005, LLM_010_GenMeta, NormalizeMeta_012_ProjectMeta]
  
AI 向用户确认:
  "已暂停，完成了 3/51 步。$projectMeta 生成正常：
   1 个 app、1 个 section、2 个 service。
   现在直接跳到 Stop_Done（跳过 39 步代码生成）？"

用户: "是的，跳过"

AI:
  4. rerun from stepID: "Stop_Done"
     → 新 run 从 Stop_Done 开始
     → 16.7 秒完成
     → "时间旅行成功！39 of 49 步被绕过"
```

**实测数据**（meta-direct-codegen 51步）:
- 正常完整跑: ~5-8 分钟
- 时间旅行到 Stop_Done: **16.7 秒**
- 节省: 39 步 / 49 步可跳步骤 = **79.6% 步骤被跳过**

---

### 案例 C: 阶段拦截（抢在执行前 abort）

**目标**: 如果工作流即将进入 Lint 修复阶段，自动 abort——保留代码生成结果但阻止任何修复。

**适用场景**:
- 只需要生成代码，不需要 AI 自动修复（想手动修复）
- 修复阶段有 bug，需要绕过
- 节省时间（修复可能跑 2-3 轮，每轮 1-2 分钟）

**完整对话流程**:
```
用户: "启动代码生成，但如果开始跑 lint 修复就立刻停止"

AI:
  1. set_watch(nodeId:"Tool_089r1_LintRepairPlan", event:"node_start", action:"abort")
     → ruleId: watch_002
     → "Watch 已激活：一旦 lint 修复开始，立即 abort"
  
  2. 启动工作流
  
  3. 代码生成阶段（约 3-5 分钟）正常跑完
  
  4. Lint 修复节点触发前 → Watch 触发 → 立即 abort
     → stopReason: "watch:watch_002 triggered — Tool_089r1_LintRepairPlan start"
     → completedSteps: 30  (代码生成全部完成)

AI 报告:
  "代码生成完成（30 步），在修复阶段启动前已自动停止。
   生成文件: MainApp.vx, HomePage.sc, DataService.vs, Theme.vth
   Watch 规则仍激活，下次运行同样会阻止修复阶段。"
```

**Watch 的 node_start 语义**:  
`node_start` 在节点**即将执行**时触发，所以 abort 是抢先的——节点实际上没有执行任何一行代码。

---

### 案例 D: 运行中文件注入

**目标**: 等所有代码文件生成完毕，在 ValidateOutputs 开始前暂停，向 MainApp.vx 注入自定义注释，然后让工作流用修改后的文件继续验证。

**适用场景**:
- 在不中断工作流的情况下，给生成文件打上时间戳/水印
- 测试工作流后段（验证、lint 修复）的行为
- 在自动化管道中注入外部数据（如 Feature Flag、AB 测试标记）

**完整对话流程**:
```
用户: "生成代码后，在开始验证之前暂停，我要在 .vx 文件里加一行注释"

AI:
  0. 清理工作区旧文件（避免残留污染）
  
  1. set_watch(
       nodeId: "ValidateOutputs_075_ProjectFiles",
       event: "node_start",    ← 注意：不是 Fork_AllCode 的 node_done！
       action: "pause"
     )
  
  2. 启动工作流
  
  3. 等待暂停（约 2-3 分钟，29/51 步已完成）
     → 所有 Loop_Apps/Sections/Services/Components 已跑完
     → Apps/MainApp.vx、Sections/*.sc、Services/*.vs 等均已写入磁盘
  
  4. 查看生成文件
     → artifacts: [ProjectMeta.json, GeneratedVlApp.vdb, Theme.vth, DataService.vs,
                   ProductTable.cp, StatCard.cp, Dashboard.sc, MainApp.vx, ...]
  
  5. 读取 Apps/MainApp.vx，在首行插入:
     "# [注入] 生成时间: 2026-06-09T05:16:03Z"
  
  6. resume（原地恢复，不重新创建 run）
     → ValidateOutputs 开始，验证修改后的文件
     → Lint 修复（如有需要）
     → Stop_Done 完成

AI 报告:
  "✓ 文件注入成功！工作流运行到 Stop_Done，共 41 步完成。
   MainApp.vx 的修改被验证系统接受，工作流正常完成。"
```

**为什么不用 `Fork_AllCode node_done`？**

```
错误做法:  set_watch(nodeId:"Fork_AllCode", event:"node_done", ...)
结果: 在 Fork_AllCode 标记 done 时触发，但此时子节点（Loop_Apps 等）还没有跑！
      代码文件根本不存在！

正确做法: set_watch(nodeId:"ValidateOutputs_075_ProjectFiles", event:"node_start", ...)
结果: 在 Fork 的所有子节点都跑完、下一步即将开始时触发。
      此时所有代码文件已经写入磁盘。
```

这是 Fork 节点的引擎机制（`StepDone` 在 `_executeChildren()` 前触发），必须特别注意。

---

### 案例 E: 多重暂停链（单次运行两次自动暂停）

**目标**: 注册两个 Watch 规则，工作流在单次执行过程中**自动暂停两次**，分别在 meta 生成后和代码生成后。

**适用场景**: 
- 需要在流程的多个关键节点检查状态
- 分阶段审批：先审核 meta 结构，通过后再等代码生成完再审核文件
- 调试复杂流程中跨步骤的数据变化

**核心机制**: Watch 规则是持久化的。注册后，每次命中的节点触发时都会激活。两个 Watch 同时存在，分别在各自的节点触发，形成链式暂停。

**完整对话流程**:
```
用户: "帮我同时监控两个节点：LLM_010_GenMeta 完成后暂停查看 meta，
      然后继续，ValidateOutputs 开始前再暂停查看生成文件。"

AI:
  1. set_watch(nodeId:"LLM_010_GenMeta", event:"node_done", action:"pause")
     → ruleId: watch_001
  
  2. set_watch(nodeId:"ValidateOutputs_075_ProjectFiles", event:"node_start", action:"pause")
     → ruleId: watch_002
  
  3. 确认两条规则同时激活:
     → GET /api/workflow/watches → [{watch_001}, {watch_002}]
  
  4. 启动工作流
  
  ── 第一次自动暂停 ──────────────────────────────
  5. LLM_010_GenMeta 完成 → watch_001 触发 → 自动暂停
     → 已完成: [ClearFiles_005, LLM_010_GenMeta]
  
  AI 报告:
    "已到达第一个断点（LLM_010 完成）。$projectMeta 已生成：
     1 个 app, 2 个 section。是否继续到第二个断点？"
  
  用户: "继续"
  
  6. POST /api/workflow/resume → 从暂停点继续（watch_002 仍然活跃）
  
  ── 第二次自动暂停 ──────────────────────────────
  7. 经过 Fork_AllCode + 所有 Loop 子节点 → ValidateOutputs_075 即将开始
     → watch_002 触发 → 再次自动暂停
     → 已完成: 29/51 步，所有代码文件已写入磁盘
  
  AI 报告:
    "已到达第二个断点（ValidateOutputs 开始前）。
     磁盘文件: MainApp.vx (2.3KB), Dashboard.sc (1.8KB), DataService.vs (0.9KB)
     是否继续运行验证？"
  
  用户: "继续"
  
  8. POST /api/workflow/resume → 继续到 Stop_Done
```

**关键 API 调用**:
```javascript
// 注册两个 Watch（顺序执行，两者同时生效）
const w1 = await fetch('/api/workflow/watch', {
  method: 'POST',
  body: JSON.stringify({ nodeId: 'LLM_010_GenMeta', action: 'pause', event: 'node_done' })
}).then(r => r.json())

const w2 = await fetch('/api/workflow/watch', {
  method: 'POST',
  body: JSON.stringify({ nodeId: 'ValidateOutputs_075_ProjectFiles', action: 'pause', event: 'node_start' })
}).then(r => r.json())

// 启动后第一次暂停发生 → 检查 → 继续
await fetch('/api/workflow/resume', {
  method: 'POST',
  body: JSON.stringify({ runID: resumable.runID })
})

// 第二次暂停发生 → 检查 → 继续
await fetch('/api/workflow/resume', {
  method: 'POST',
  body: JSON.stringify({ runID: resumable.runID })
})
```

**注意**: `resume` 不改变 stepID 或变量，仅从当前暂停点继续。如需修改变量则用 `rerun`。

---

### 案例 F: 分支强制路径（注入变量控制分支走向）

**目标**: 在 Branch_081_LintRepairGate 暂停，通过注入 `$codeValidation.errCount=0`，强制分支走 Stop_Done 路径（跳过所有修复轮次）。

**适用场景**: 
- 绕过已知的误报 lint 错误（LLM 生成的代码偶尔触发假阳性）
- 测试工作流后段步骤（验证 Stop_Done 后的清理逻辑）
- 强制特定测试路径（测试"无错误时的快乐路径"）
- 调试分支条件（确认 branch 读取哪个变量）

**Branch_081 的条件逻辑**:
```javascript
// Branch_081_LintRepairGate 的判断条件（实际源码）:
const count = Number(r.errCount || r.blockingErrCount || r.pendingErrCount || 0);
return count > 0 || (Array.isArray(r.errors) && r.errors.length > 0);
// true  → Tool_089r1_LintRepairPlan（修复路径）
// false → Stop_Done（默认路径）
```

**完整对话流程**:
```
用户: "代码生成完成后，帮我强制跳过 lint 修复阶段，
      不管有没有 lint 错误，直接走到 Stop_Done。"

AI:
  1. set_watch(nodeId:"Branch_081_LintRepairGate", event:"node_start", action:"pause")
     → 在分支条件求值之前暂停
  
  2. 启动工作流（完整代码生成，约 3-5 分钟）
  
  3. 等待暂停（29/51 步完成，所有代码已生成，lint 已跑）
     → 暂停在 Branch_081_LintRepairGate
  
  4. 读取实际 $codeValidation:
     → GET /api/workflow/variables → {errCount: 3, warningCount: 7, errList: [...]}
     (或者 errCount: 0 表示无错误)
  
  AI 向用户报告:
    "已暂停在 Branch_081。实际 lint 结果: errCount=3（有3个错误）。
     正常会走修复路径，现在强制注入 errCount=0 跳过修复。"

  5. rerun from Branch_081_LintRepairGate with override:
     {$codeValidation: {errCount: 0, errList: [], ok: true}}
     → 分支重新求值：errCount=0 → 走 Stop_Done 路径
  
  6. 约 2 秒后 Stop_Done 完成（完全跳过 3 轮修复）

AI 报告:
  "✓ 分支强制成功！Branch_081 直接走了 Stop_Done。
   跳过了 Tool_089r1_LintRepairPlan 和后续所有修复步骤。"
```

**关键 API 调用**:
```javascript
// 在 Branch_081 处暂停
const watch = await fetch('/api/workflow/watch', {
  method: 'POST',
  body: JSON.stringify({
    nodeId: 'Branch_081_LintRepairGate',
    event: 'node_start',
    action: 'pause'
  })
}).then(r => r.json())

// 获取检查点
const resumable = await fetch('/api/workflow/resumable').then(r => r.json())
const checkpoint = await fetch(`/api/workflow/${resumable.runID}/checkpoint`).then(r => r.json())

// 强制注入：重跑 Branch_081，但使用 clean 的 $codeValidation
await fetch('/api/workflow/rerun', {
  method: 'POST',
  body: JSON.stringify({
    workflowName: 'meta-direct-codegen',
    checkpoint,
    stepID: 'Branch_081_LintRepairGate',
    overrides: {
      '$codeValidation': {
        errCount: 0,
        errList: [],
        warningCount: 0,
        ok: true
      }
    }
  })
})
```

**反向操作**（强制走修复路径）:
```javascript
overrides: { '$codeValidation': { errCount: 99, errors: ['forced error 1', 'forced error 2'] } }
// 即使代码完全干净，也会强制进入修复路径
```

---

### 案例 G: 运行中热挂载 Watch（动态注册）

**目标**: 在工作流**已经启动并运行中**时，动态注册一条 Watch 规则——证明 Watch 是实时检查的，不需要在启动前注册。

**适用场景**: 
- 临时决定要在某个节点检查（启动时没有预料到）
- 生产监控：对已在运行的工作流补充监控规则
- 条件性干预：基于某个节点的结果决定是否挂载下一个断点

**核心机制**: 工作流引擎在每个事件触发时查询当前活跃的 Watch 规则列表。这个查询是**实时的**——注册后，新规则立即对后续节点生效。

**完整对话流程**:
```
用户: "先启动代码生成，运行起来之后，我临时决定想在
      ValidateOutputs 之前暂停看看文件。"

AI:
  1. 不注册任何 Watch，直接启动工作流:
     → POST /api/workflow/execute
     → 工作流开始运行...
  
  2. 等待工作流变为 active 状态:
     → 轮询 /api/workflow/current-state 直到 active: true
     → 约 2-5 秒后确认 active
  
  AI 提示:
    "工作流已启动（运行中）。正在处理 ClearFiles → LLM_010 阶段。"

  3. 热挂载 Watch（工作流正在运行时注册）:
     → POST /api/workflow/watch
       {nodeId:"ValidateOutputs_075_ProjectFiles", event:"node_start", action:"pause"}
     → ruleId: watch_hot_001
  
  AI 报告:
    "✓ Watch 已热挂载到运行中的工作流！
     ruleId: watch_hot_001
     当工作流到达 ValidateOutputs_075 时，将自动暂停。"
  
  4. 继续等待...（约 3-5 分钟后）
     → ValidateOutputs_075_ProjectFiles 即将执行
     → 引擎查询 Watch 列表 → 命中 watch_hot_001 → 暂停！
  
  5. 暂停成功:
     → checkpoint: {status: "paused", currentStepID: "ValidateOutputs_075..."}
  
  AI 报告:
    "热挂载的 Watch 触发了！文件已生成：
     Apps/MainApp.vx, Sections/Dashboard.sc, ...
     是否继续？"
  
  用户: "继续"
  
  6. POST /api/workflow/resume → 继续到 Stop_Done
```

**关键 API 调用**:
```javascript
// Step 1: 无 Watch 直接启动
const sseStream = await fetch('/api/workflow/execute', {
  method: 'POST',
  body: JSON.stringify({ workflowName: 'meta-direct-codegen', params: { goal: '...' } })
})
// 保持 SSE 连接活跃（否则 server 会 abort）
keepReadingSSE(sseStream.body.getReader())

// Step 2: 等待工作流 active
let state;
do {
  await sleep(1000);
  state = await fetch('/api/workflow/current-state').then(r => r.json());
} while (!state.active);

// Step 3: 热挂载 Watch（workflow 已在运行）
const hotWatch = await fetch('/api/workflow/watch', {
  method: 'POST',
  body: JSON.stringify({
    nodeId: 'ValidateOutputs_075_ProjectFiles',
    event: 'node_start',
    action: 'pause'
  })
}).then(r => r.json())
console.log('Hot-patched! ruleId:', hotWatch.ruleId)

// Step 4: 等待 Watch 触发
while (true) {
  await sleep(3000);
  const s = await fetch('/api/workflow/current-state').then(r => r.json());
  if (s.checkpoint?.status === 'paused') break;
  if (!s.active) break;
}

// Step 5: Resume
const { runID } = await fetch('/api/workflow/resumable').then(r => r.json())
await fetch('/api/workflow/resume', { method: 'POST', body: JSON.stringify({ runID }) })
```

**时序限制**: 如果工作流在热挂载前就已经通过了目标节点，Watch 不会触发（无法回溯已执行的节点）。应当在目标节点**执行之前**完成注册。

对于 `meta-direct-codegen`，`ValidateOutputs_075` 在全量代码生成之后（约第 29 步），距离启动约 3-5 分钟。只要在 LLM_010_GenMeta 完成之前完成热挂载（约前 30 秒），Watch 一定能触发。

---

## 5. 项目工具能力

### 文件读写

| 指令示例 | 工具 |
|---------|------|
| "读取 Apps/MainApp.vx" | ReadFile |
| "修改第 15 行为..." | EditFile |
| "创建新文件 Sections/NewSection.sc" | WriteFile |
| "grep 所有用到 #Button 的文件" | Grep |
| "列出 Services/ 下的文件" | Glob |

### Git 操作

```
"提交当前改动，消息：fix: 修复登录逻辑"
"查看 git diff"
"当前分支是什么？"
"回退到上一个 commit"
```

### 系统文档

```
"查询 VL 的 #DataTable 组件文档"
"WorkflowSpec 里 Branch 步骤怎么配置？"
"ComponentFactory 里有没有日期选择器？"
```

### 控制面板 (Control Plane)

```
"查看当前项目配置"
"列出所有 workspace"
"切换工作区到 ~/Documents/VLProjects/TeamPM"
```

---

## 6. 代码生成与 VL 开发

### 工作流选择指南

| 项目规模 | 推荐工作流 | 步数 | 用时 |
|---------|-----------|------|------|
| 极小（1-2 页） | `meta-direct-codegen` | 51 | 3-5 min |
| 小型（3-5 页） | `parallel-codegen` | 24 | 2-4 min |
| 中型（5-15 页） | `meta-sharded-codegen` | 55 | 8-15 min |
| 大型（15-50 页） | `meta-thin-fast-codegen` | 82 | 15-30 min |
| 企业级（50+ 页） | `enterprise-meta-cascade-codegen` | 122 | 30-60 min |
| 设计稿还原 | `design-reference-codegen` | 10 | 2-4 min |

### 生成后的标准工具链

```
1. 代码生成工作流完成
2. "编译一下" → vl-compile
3. "lint 修复" → debug-multi-file 或 compile-fix 工作流
4. "跑 autotest" → autotest-pipeline 工作流
5. "生成质量评分" → vl-generation-quality-control 工作流
```

### 增量修改

```
"修改 Dashboard 的布局，把统计卡片移到顶部"
→ vl-adjust（单文件 AI 修改）

"给项目添加一个新的报表页"  
→ meta-apply-delta（meta 级增量，自动生成新页面代码）

"修复编译错误"
→ compile-fix 工作流
```

---

## 7. 常见问题与诊断

### Q: 工作流启动后没有反应

```
排查步骤:
1. "status" — 看 active 是否为 true
2. 检查 server 日志：tail -f /tmp/vlcode-4000.log
3. 检查是否有 WORKFLOW_ALREADY_ACTIVE 错误
   → "force-clear"（向 POST /api/workflow/force-clear 发请求）
   → 然后重试
```

### Q: pause 了但无法 resume

```
可能原因: force-clear 把 paused executor 清掉了

诊断:
"resumable？" → GET /api/workflow/resumable
→ 如果 resumable: false，需要重新跑（检查点数据可能已丢失）
→ 如果 resumable: true，直接 continue 或 rerun from step
```

### Q: ValidateOutputs 报告文件缺失

```
常见原因:
1. $projectMeta 的 apps/sections 与实际生成文件不匹配（LLM 随机性）
2. Loop_Apps/Sections 迭代了 0 次（meta 里 apps: [] 空数组）
3. 工作区残留旧文件干扰

解决:
- 清理工作区旧 .vx/.sc 文件
- 查看 $projectMeta.apps 是否非空（variables API）
- 如果 meta 为空，在 LLM_010 后设断点注入 meta
```

### Q: Watch 规则注册了但没有触发

```
检查:
1. list_watches 确认规则存在
2. 确认 nodeId 拼写正确（大小写敏感）
3. 确认 event 类型匹配（node_done vs node_start）
4. Fork 节点用 node_done 不会在子节点完成后触发（见 3.5 节）
```

### Q: 工作流 SSE 连接断开，workflow 被 abort 了

```
原因: server 的 SSE close handler 在客户端断连时会调用 executor.abort()

解决: 
- 使用后台引流模式：fetch SSE 后在后台持续 read（不要让 reader 关闭）
- 或使用 async mode（rerun/execute 的 mode:"async" 参数）
```

---

## 8. 速查卡

### 工作流控制一览

| 你说什么 | AI 做什么 | API |
|---------|---------|-----|
| "启动 X 工作流" | 执行工作流 | POST /api/workflow/execute |
| "暂停" | 在下个检查点暂停 | requestPause() |
| "停止" / "abort" | 立即终止 | POST /api/workflow/{id}/abort |
| "继续" / "resume" | 从暂停点继续 | POST /api/workflow/resume |
| "从断点重来" | 从最近检查点重跑 | POST /api/workflow/rerun |
| "从第 N 步重跑" | 步骤跳转 | POST /api/workflow/rerun {stepID} |
| "查进度" | 当前状态 | GET /api/workflow/current-state |
| "查变量" | 流水线变量 | GET /api/workflow/variables |
| "查文件" | 产出物列表 | GET /api/workflow/artifacts |
| "监控 X 节点" | 注册 watch | POST /api/workflow/watch |
| "看规则" | Watch 列表 | GET /api/workflow/watches |
| "删规则" | 删除 watch | DELETE /api/workflow/watch/{id} |

### Watch 事件时序

```
节点执行时序:
  node_start 触发  →  节点实际执行  →  node_done 触发
  ↑                                      ↑
  "抢在执行前"                          "执行完成后"

Fork 节点特殊时序:
  Fork.node_done 触发  →  子节点开始执行  →  后继节点.node_start 触发
  ↑ 子节点还没跑!                              ↑ 子节点全部完成!
```

### 常用工作流变量

```
$projectMeta        项目结构（apps/sections/services/components）
$vdbContent         数据库内容
$vthContent         主题内容  
$codeValidation     {errCount, errList, warningCount}
$compileResult      VL 编译结果
$outputValidation   文件存在性验证
$parallelPromptSlices 代码生成 prompt 上下文（每个文件独立）
```

### 节点 ID 命名规律（meta-direct-codegen）

```
ClearFiles_005_*    清理旧文件
LLM_010_GenMeta     生成 ProjectMeta（核心）
NormalizeMeta_012_* 规范化 meta
Fork_DBTheme        并行: 数据库 + 主题
LLM_020_GenDB       生成数据库
SeedTheme_030_*     生成默认主题
SliceContext_035_*  构建 prompt 上下文
Fork_AllCode        并行: 服务/组件/页面/App 代码
Loop_Services/*/Components/Sections/Apps  循环生成各类文件
LLM_040_GenService  生成 .vs 服务文件
LLM_050_GenComponent 生成 .cp 组件文件
LLM_060_GenSection  生成 .sc 页面文件
LLM_070_GenApp      生成 .vx App 文件
ValidateOutputs_075_* 验证文件是否存在
NormalizeCode_081_* 规范化生成代码
BuildMeta_082_*     重建 workspace meta
Tool_080_LintGeneratedCode  代码 lint
Branch_081_LintRepairGate   分支: 有错误 → 修复轮次
Tool_089r1/r2/r3_*  三轮 lint 修复
Stop_Done           完成
```

---

> **提示**: 所有工作流控制均可通过自然语言指令完成，无需记住具体 API。AI Assistant 会自动将"暂停"→ requestPause、"从 NormalizeMeta 重跑" → POST /rerun with stepID 等转换。只需关注**你想达到的效果**，让 AI 处理底层细节。

---

*文档版本: 2026-06-09 | VLCode v1.172.0 | 全部案例实机验证*
