首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
AI 工具与工作流
发新帖
2
1
AI Agent 工程化原理与工作流插件套件实现
发表于: 2026-7-1 10:27
1515
AI Agent 工程化原理与工作流插件套件实现
air龙典
1
2026-7-1 10:27
1515
# AI Agent 工程化原理与工作流插件套件实现 --- # 第一部分:原理 --- ## 一、AI 编码的工程瓶颈转移 软件工程数十年来围绕一个核心约束运转——编码成本高昂。瀑布模型的需求规格化、敏捷迭代的 Sprint 规划、代码评审制度、架构决策流程,本质上都在管理"工程师时间"这一稀缺资源。 AI Agent 时代改变了这一前提。编码执行不再是成本瓶颈,瓶颈转移至**验证**(代码是否正确)、**治理**(是否符合架构约束)、**可续接性**(跨会话、跨模型、跨设备如何保持工程连续性)。 这一变化影响五个维度:规划方式(产出速率数量级提升)、代码所有权(生成者归属模糊化)、代码评审(规模与工具的根本变化)、团队构成(技能组合重新定义)、知识共享(文档不再是唯一知识载体)。 --- ## 二、上下文质量决定输出质量 ### 2.1 信噪比决定输出质量 LLM 的输出质量与输入上下文的信噪比强相关。无关信息占据 token 预算,会降低模型对关键信息的注意力。实践中应遵循: - **项目文件精简**:清除编译缓存、构建产物、无关文档;引用文件时使用绝对路径而非让 Agent 自行搜索。 - **输入去噪**:去除修饰词和语气词;将富文本转换为纯文本(Markdown/TXT),减少非语义标记干扰。 - **无倾向性输入**:提问时避免引导性表述,让模型独立判断而非拟合用户预期。 ### 2.2 上下文污染与上下文腐烂 在 Agent 工作流中,有两个核心上下文退化机制: **上下文污染(Context Pollution)**:不相关的信息进入模型的可见上下文,干扰当前任务的推理。典型场景——3 个并行任务共享同一个上下文窗口时,任务 A 的代码搜索结果会占据任务 B 的注意力。 **上下文腐烂(Context Decay)**:随着对话增长,模型对早期信息的回忆准确度下降。一个 200K token 的对话在第 150K token 时,对第 10K token 处的架构决策的引用可能出现幻觉。 这两个问题要求对上下文进行**主动的边界管理**——不是让上下文自由增长,而是在多个尺度上持续控制其质量和规模。 ### 2.3 三层上下文边界模型 有效的上下文管理需要在三个尺度上同时建立边界: | 层级 | 边界定义 | 解决的问题 | | ------- | -------------------------------- | ------------------------ | | **会话级** | 压缩旧对话,保留摘要 + 近期消息 | 上下文腐烂——长对话中早期信息被遗忘 | | **任务级** | 每个任务使用独立上下文,不继承调度器历史 | 上下文污染——并行任务之间互相干扰 | | **项目级** | 结构化文档(AGENTS.md、ADR、C4)作为跨会话认知载体 | 认知断裂——换会话/换模型/换设备后丢失项目理解 | 三层边界的协同效果:会话级保证单次对话的质量,任务级保证并行执行的质量,项目级保证跨时间跨空间的连续性。 ### 2.4 上下文压缩的信息保留策略 上下文压缩不应该是简单的截断,而是分层的信息保留策略: - **永久保留层**:最近 N 条消息逐字保留,不送入压缩模型——这是当前工作状态的"工作记忆" - **高优先级保留层**:文件路径、架构决策、未解决的 TODO、用户目标——这些是不可推导的项目事实 - **低优先级丢弃层**:探索性搜索结果、已覆盖的文件内容、重复搜索、"looks good" 式中间确认——这些是一次性消费品 这一分层策略的目标是:用远小于原始上下文的 token 数,保留恢复工作所需的全部关键信息。 V2 进一步引入**压缩质量校验**——压缩后自动验证关键模式(文件路径、ADR 引用、TODO/FIXME、不变量引用)的保留率是否 ≥ 70%。校验失败时触发三级降级:重试(换 prompt)→ 换模型 → 截断(保留原始上下文并通知用户),保证坏摘要不会静默损坏上下文。 ### 2.5 上下文隔离与并行效率的关系 上下文隔离通常被视为质量保障手段,但它同时也是**并行调度的效率前提**。 **共享上下文下的并行**:每个 worker 的工具调用结果都进入共享上下文 → 并发数越高,上下文膨胀越快 → 更快触发上下文窗口限制 → 更频繁的压缩 → 输出质量下降。 **隔离上下文下的并行**:每个 worker 的上下文独立增长 → 并发数不受上下文窗口约束 → 每个 worker 的上下文保持稳定规模 → 输出质量恒定。 这意味着:没有上下文隔离,并行度越高,质量衰减越快。隔离使并行加速比可以**线性扩展**而非在并发数增加时边际递减。 --- ## 三、并行调度原理 ### 3.1 依赖感知调度 朴素并行(所有任务同时启动)在有文件写集冲突时会导致并发任务互相覆盖,产出的代码需要大量人工修复,实际效率反而低于串行。有效的并行调度必须: 1. **分析依赖关系**:识别任务之间的前置依赖(任务 B 依赖任务 A 的产出) 2. **检测写集冲突**:识别哪些任务会修改相同文件 3. **波次分组**:将无依赖、无冲突的任务组织为可并行执行的波次 4. **序列化冲突点**:对有冲突的任务强制串行执行 ### 3.2 并行加速比模型 设 N 个任务,平均执行时间 T,依赖深度 D: | 调度策略 | 总时间 | 加速比 | 结果可靠性 | | ----------- | -------- | ----- | ----------------- | | 串行执行 | N × T | 1x | 可靠 | | 朴素并行(无冲突分析) | ~N/C × T | ~C x | **不可靠**——写集冲突导致覆盖 | | 依赖感知波次调度 | D × T | N/D x | 可靠——冲突已消除 | 关键洞察:加速比的上限取决于**依赖深度 D**(关键路径长度),而非并发数 C。依赖越浅、独立任务越多,加速比越高。 ### 3.3 调度器的可交互性 调度器在并行执行期间应始终保持可交互状态——用户可以随时查询进度、修改需求、取消任务。这要求: - 调度器与 worker 运行在不同的上下文/进程中 - 调度器的状态通过持久化文件(而非内存)暴露 - 轮询间隔是无人值守时的巡检节奏,用户主动查询时同步响应 V2 进一步引入 **ScheduleWakeup 机制**——调度器不自行循环轮询,而是通过系统的定时唤醒功能(每 5 分钟)被唤醒执行检查。这消除了"Agent 忘记轮询"的风险,将轮询从 Agent 的自觉行为升级为系统级保障。后台 Worker 完成时系统还会主动推送通知,调度器可以立即处理而不必等到下一个 5 分钟窗口。 --- ## 四、证据驱动原理 ### 4.1 AI Agent 的虚假验证问题 AI Agent 在验证自身产出时存在系统性偏差:倾向于以"命令返回 0"、"进程存在"、"日志无异常"等间接指标判定通过,而这些指标与实际功能正确性之间没有必然关系。尤其在 GUI 场景中,窗口拉起 ≠ 界面渲染正确,端口监听 ≠ 业务逻辑正确。 ### 4.2 证据先于修复 正确的调试流程必须强制要求**直接证据**先于任何修复行为: - GUI 问题需要截图/图像证据 - 网络问题需要抓包/pcap 证据 - 代码质量问题需要静态分析报告 修复后必须用**同类证据**再次验证。不能以"代码改了"代替"问题验证了"。 ### 4.3 闭环自动修复 执行 → 失败 → 收集证据 → 诊断 → 修复 → 重新执行,形成自动化循环。设置**干预预算**(如最多 2 次自动重试),耗尽后升级到人工决策。这避免了无限循环,也避免了过早打扰用户。 ### 4.4 任务类型感知的证据门控(V2 新增) V1 的证据门控是**无差别触发**——所有任务完成后都尝试触发 AirXDB 截图,导致非 GUI 任务(如纯后端逻辑修改)产生 11+ 次假阳性阻塞,每次都需要人工覆盖。 V2 引入 **EvidenceGatePolicy**——基于任务特征的差异化证据分类: | 证据类别 | 触发条件(关键词匹配) | 要求的证据类型 | | ------------------ | -------------------------------------------------------- | ------------- | | `GUI_REQUIRED` | gui, ui, render, layout, dialog, widget, canvas, 界面, 按钮… | 截图 + GUI 操作验证 | | `NETWORK_REQUIRED` | network, rtsp, http, tcp, socket, stream, 网络, 抓包… | 抓包 + 连通性验证 | | `STATIC_ANALYSIS` | cppcheck, clang-tidy, mypy, lint, static analysis… | 静态分析报告 | | `CODE_ONLY` | 不匹配以上任何关键词 | 代码审查 + 测试结果 | 关键词匹配而非 LLM 分类的设计决策: - **确定性**:相同输入总是产生相同输出,可测试 - **零成本**:不需要额外 API 调用 - **可解释**:用户可以理解为什么某个任务被分类为 GUI 任务 - **可覆盖**:用户可在 todo.md 中用 `[no-xdb]`/`[no-ndb]`/`[no-sdb]` 标记显式跳过 --- ## 五、多模型交叉审计原理 ### 5.1 单模型审计的系统性盲区 每个 LLM 有其固有的偏见和遗漏模式:某些模型倾向于关注文件完整性而忽视语义正确性,某些模型对安全问题的敏感度高于其他模型,某些模型在特定领域的推理深度更强。单模型审计无法识别这些盲区——你无法用同一个模型来验证它自己的遗漏。 ### 5.2 交叉确认与置信度分级 多个独立模型对同一制品进行审计后,通过**交叉确认矩阵**对发现进行置信度分级: | 独立确认的模型数 | 置信度 | 处置策略 | | -------- | --- | ---------- | | ≥ 3 | 高置信 | 必须立即修复,不复核 | | 2 | 中置信 | 应当修复,可快速复核 | | 1 | 低置信 | 需人工复核确认 | 核心逻辑:如果 3 个独立模型都发现了同一个问题,这个问题几乎一定是真实的。如果只有 1 个模型发现,可能是该模型的特有视角,也可能是误报。 ### 5.3 评级不一致也是一种信息 当不同模型对同一制品给出显著不同的评级时,分歧本身就是有价值的信息——它揭示了不同模型的评价维度差异。例如:一个模型以"文件创建完成度"为主轴给出高评价,而另一个模型以"与规范的语义一致性"为主轴给出低评价。这种分歧恰恰指向了"文件存在 ≠ 语义正确"这一深层问题。 ### 5.4 三种交叉审计模式 | 模式 | 结构 | 适用场景 | | --------- | ------------------ | --------------- | | **并行审计** | N 个模型同时独立审计,结果汇总 | 开发阶段审计、代码质量评估 | | **递进审计** | N 轮串行,每轮读取前轮发现并深挖 | 详细设计审查、根因分析 | | **多视角审计** | 扮演不同角色(架构师/开发者/用户) | 需求覆盖性检查、UX 缺口发现 | --- ## 六、架构状态持久化原理 ### 6.1 架构即项目认知骨架 软件项目的架构知识通常存在于架构师脑中。AI Agent 时代,执行者每次可能是不同的模型实例——架构认知必须外化为**结构化文档**,成为任何执行者都能加载的项目认知。 两类核心文档承担这一角色: - **C4 模块文档**:定义模块边界、职责、公共接口、依赖关系、数据所有权。模块边界直接影响调试时的范围判定和并行调度的写集冲突分析 - **ADR(架构决策记录)**:记录每条架构决策的上下文(为什么)、决策(选了什么)、后果(正反面影响)和被拒绝的替代方案 ### 6.2 C4 与 ADR 的联动:决策图谱 C4 定义了系统的静态边界——哪些模块存在、边界在哪、接口是什么。ADR 记录了边界的演化历史——为什么这样划分、拒绝了哪些替代方案、已知哪些代价。 两者构成**决策图谱**:C4 回答"现在是什么",ADR 回答"为什么是这样"。当新任务到来时,执行者加载决策图谱即可理解项目全貌,而不需要与前任执行者对话。 ### 6.3 ADR 后果分析作为影响面定位工具 每条 ADR 的 Consequences 段落列出正面和负面影响——这些影响本质上定义了该决策的**作用面**。当出现问题时: 1. 从问题症状出发,定位涉及的模块(C4) 2. 从模块关联的 ADR 后果中,快速收窄根因搜索范围 3. 如果修复与某条 ADR 的后果冲突,要么创建新 ADR 覆盖旧决策,要么放弃修复方向 这形成**不可绕过的决策审计链**——每次架构变更都有理由记录,每个理由都可追溯。 ### 6.4 架构状态不丢失的保证(原理) 架构文档与代码同步的核心原则:**不更新架构文档的任务无法标记为完成**。 这意味着每次任务合并时,系统必须强制验证 Worker 是否提交了所要求的架构文档更新——缺失则拒绝合并。架构文档因此成为**代码合并的门控条件**,而不是"事后补写"的附属物。 > 具体的标记块命名空间、6 阶段合并流水线、合并去重等实现细节,见第二十章 § 20.1。 ### 6.5 ADR 变更级联失效(原理,V2 新增) V1 暴露的深层问题:当架构方案变更(如 ffmpeg → gstreamer)时,基于旧 ADR 已完成的任务不会自动失效,旧代码残留与新方案冲突,下游任务基于过期产出继续执行。 **原理层面的要求**:架构决策一旦变更,所有引用该决策的已完成任务必须自动失效、进行中任务必须自动中止、下游依赖必须级联失效、基于旧决策的代码必须回滚、受影响的任务必须局部重规划。这五个动作构成一个**架构变更的闭环**——缺少任何一环,都会留下"幽灵代码"。 > 具体的 10 步级联闭环(ADRWatcher hash 对比 → TaskGraph.invalidate_by_adr → 调度冻结 → git revert → PartialReplanner 局部重规划 → 解冻)见第二十章 § 20.2。 ### 6.6 认知卸载:从"记在脑中"到"写在文件中" 传统工程依赖架构师的持续在场来维护架构一致性。AI 工程将架构认知卸载到文件: - **AGENTS.md**:项目级指令与工作流规则——任何 AI 加载即获项目上下文 - **ADR**:架构决策的永久记录——新模型或新设备上的新会话也能理解历史决策 - **C4**:模块边界的权威定义——约束任务写集和调试范围 - **debug-log.md**:问题生命周期的完整记录——从引入到解决的全链路可追溯 这些文件的集合构成项目的**认知基础设施**——不依赖任何特定人或特定 AI 会话。 --- ## 七、范围约束降本原理 ### 7.1 规划-执行分离与智能放大 传统开发中规划和执行混杂在同一上下文:开发者同时理解需求、设计架构、编写代码。范围约束将规划与执行分离: - **规划阶段**(高能力模型):定义范围、验收标准、验证命令、依赖关系、写集冲突分析 - **执行阶段**(任意模型):在预定义的窄化切片内执行,不需要理解全局 关键洞察:当执行者的上下文被精确约束到**6 个文件 + 1 个任务切片 + 预声明的写集**时,执行者不需要"理解整个项目"——只需要在预先确定的范围内执行。 ### 7.2 上下文约束使廉价模型可用 当任务上下文被约束在有限文件和结构化模板中时,执行者面对的是一个**高度简化的问题空间**: - 不需要仓库探索(写集已预声明) - 不需要架构决策(ADR/C4 已作为必读文件提供) - 不需要任务规划(只有一个任务切片) - 不需要结果格式化(结构化模板已预填充) 执行者只需要:**在预声明的文件中编写片段代码 → 按模板填入结果 → 运行预声明的验证**。这个能力门槛远低于"理解一个项目并规划开发"——廉价模型完全可以胜任。 ### 7.3 弱模型安全保障(V2 新增) 廉价模型的固有限制是**字面理解、无推断能力**。V2 在 AirArc 规划阶段引入 **INV-16 弱模型安全**约束,从四个维度保障任务描述的精确性: | 约束维度 | 具体要求 | 防止的问题 | | ----------- | ------------------------------------------------- | ------------- | | **禁止歧义词** | 不用"清理"、"重构"、"优化"等宽泛动词,指明具体改什么 | Worker 误解任务意图 | | **否定约束显式化** | 写明**不做什么**(如"不删除 src/ 下现有模块") | Worker 过度执行 | | **文件范围精确化** | `files_dirs` 精确到文件级,不写 `src/` 目录级 | Worker 越界修改 | | **完成标准可验证** | `done_when` 能用 `grep`/`diff`/`cmake --build` 客观验证 | Worker 无法判定完成 | AirArc 在生成 execution-plan.json 时自动扫描所有 TODO 任务,检测危险词("清理"、"删除所有"、"重构整个"等)和目录级文件范围,产出 `safetyWarnings` 列表。 ### 7.4 成本结构的反转 传统模式下,规划和执行都由同一高能力模型完成: ``` 传统: 每个任务都需要昂贵模型(因为需要完整项目上下文 + 探索 + 规划 + 执行) 成本 = N × 昂贵模型单价 范围约束: 规划一次(昂贵模型),执行 N 次(廉价模型) 成本 = 规划费用 + N × 廉价模型单价 ``` 当 N 较大且廉价模型单价为昂贵模型的 1/10 时,边际成本降低约一个数量级。 ### 7.5 约束边界与质量的关系 约束越严格,执行者的搜索空间越小,偏离预期的可能性越低: | 约束类型 | 约束内容 | 防止的问题 | | ---- | ----------------- | -------- | | 写集约束 | 只能修改预声明的文件 | 越界修改导致回归 | | 验收约束 | 必须满足 Done When 条件 | 不完整交付 | | 验证约束 | 必须运行预声明的验证命令 | 遗漏测试 | | 文档约束 | 必须更新预声明的架构文档 | 架构腐化 | 这些约束将执行者的行动空间从"修改仓库中的任何文件"收窄到"修改这 3 个文件并满足这 2 个条件"——搜索空间缩小约两个数量级。 --- ## 八、长期工程迭代管理原理 ### 8.1 状态持久化与会话连续性 AI Agent 时代,执行者每次可能是不同的模型实例。项目状态不能依赖会话内存——必须**外化到磁盘文件**: - 项目目录包含完整状态:规划文档、架构记录、执行状态、调试历史、修复记录 - 任何新会话从磁盘文件恢复,获得与上一会话完全一致的项目认知 - 会话中断不丢失任何进度——所有状态变更即时写入磁盘 ### 8.2 波次递进与增量交付 任务按依赖关系组织为波次(wave)。每个波次完成后自动触发下一波次。已完成任务的文档更新在合并时即时应用到项目文档——后续波次的执行者看到的是包含所有前序成果的**最新上下文**。 增量交付的保证:第 N 波次的所有产出在第 N+1 波次启动前已合并到项目文档和架构记录中。 ### 8.3 动态图调度替代静态表格(原理,V2 新增) V1 的调度基于静态 `todo.md` 表格——AirArc 产出表格,AirEng 基于表格调度。当需求变更时 Arc 重新生成表格,Eng 无法增量吸收差异,需多轮 AI 迭代才能恢复调度。 **原理层面的要求**:调度结构必须是一个**活的有向无环图(DAG)**,而非静态表格。它需要具备四项核心能力: - **增量吸收**:重规划只更新变化的部分,已调度任务不受影响 - **全量替换时保留完成态**:避免已完成任务被重新调度 - **图差异计算**:新旧 DAG 对比产出精确的变更集(PlanDelta) - **就绪计算**:返回入度为 0 且未开始的节点,调度冻结时返回空 这四项能力共同支撑**"需求变更是非破坏性的"**这一工程承诺——用户在执行中途修改任务表,系统能够增量吸收而非推倒重来。 > TaskGraph 的具体数据结构(TaskNode 含 adr_refs/test_required/write_set)、PlanDelta 的 added/removed/modified 结构、apply_delta 的实现细节见第二十章 § 20.3。 ### 8.4 范围变更的非破坏性 用户可以在执行中途修改任务表(添加、修改、取消任务)。V2 的 TaskGraph 使这一过程变为增量操作: 1. 用户修改 `todo.md` 2. AirEng 检测到 todo.md mtime > task-graph.json mtime 3. 自动触发 `incremental_replan`:全量重建新 DAG → diff 旧 DAG → 产出 PlanDelta 4. `apply_delta()` 增量更新,保留已调度任务的 DISPATCHED/DONE 状态 5. 新任务自动进入后续波次调度 ### 8.5 回归防护机制 - **状态过滤**:已完成任务不参与重新调度(`ready_tasks()` 只返回 `status == "TODO"`) - **分组追踪**:已完成的波次不会被重复派发 - **合并验证**:结果必须包含实质产出才能标记为完成 - **文档强制**:涉及全局文档的任务必须提交架构文档更新 - **证据强制**:GUI 任务必须有截图证据才能关闭 - **TaskGraph 状态同步**(V2):merge 后 Phase 6.5 自动同步 `task-graph.json` 节点 status,防止重复派发已完成任务 ### 8.6 跨模型、跨设备、跨时间的连续性 所有状态都是纯文件(JSON、Markdown),可通过版本控制或文件同步在多个维度实现连续性: - **跨模型**:不同模型实例读取同一套制品,获得一致的项目认知 - **跨设备**:不同物理设备通过远程访问同一状态目录 - **跨时间**:任意时间点中断,从文件恢复完整执行历史 --- ## 九、工具扩展与自动化原理 ### 9.1 从语言模型到工程平台 LLM 本身不具备工具能力,但通过 CLI 工具注册、MCP 协议桥接、Skill 封装等机制,可以将其扩展为具备完整工程能力的平台。关键设计原则: - **工具注册与路径声明**:显式注册工具路径,避免 Agent 在执行时重复发现或误用 - **持久记忆**:通过结构化文档(AGENTS.md、ADR、plan.md)为 Agent 提供跨会话记忆 ### 9.2 重复的事情应该被自动化 > 如果一件事要重复五次,那么它应该被自动化 在以前,自动化涉及开发,是一件成本很高的事情,但 AI 发展后的现在,自动化的难度已经被极大的降低了,如果一件事你至少要重复五次,那为什么不拿出 2-3 次的时间把它自动化,然后省下几次的时间去做其他更重要的事? AI 工程迭代路径恰好与以前工业时代的一句话对应: > 复杂的事情简单化 > 简单的事情标准化 > 标准的事情自动化 > 自动的事情智能化 --- ## 十、L1 代码级保障原理(V2 新增) ### 10.1 从"建议性"到"强制性"的范式跃迁 V1 的许多关键约束(证据先于修复、AirDbg 路由、AirArc 只读)仅通过 SKILL.md 的自然语言指令传达——本质上是**建议性约束**,依赖 LLM 的"自觉"遵守。V1 真实项目数据证明了这一范式的失效: | 约束 | V1 表达方式 | 实际违规率 | 根因 | | --------------- | ----------- | -------------- | ------------- | | AirDo 调用 AirDbg | SKILL.md 建议 | 频繁跳过 | Worker 倾向直接返回 | | AirArc 不写代码 | SKILL.md 声明 | 被 plan mode 劫持 | Agent 框架覆盖 | | AirEng 自主推进 | SKILL.md 期望 | 反复询问用户 | 无强制决策指令 | | AirDbg 先取证 | 7 步工作流 | 不取证就改代码 | 步骤可跳过 | V2 的核心设计原则:**凡是造成过实际损失的约束,必须从自然语言建议升级为 L1 代码级保障**——即通过 Python 代码的门控逻辑、工具白名单、数据结构约束来硬性执行。 ### 10.2 五种 L1 保障机制(原理层枚举) L1 代码级保障体系在**五个层面**叠加防御,每一层针对不同类型的违规模式: | 层面 | 针对的违规模式 | 硬化方式 | | ------------- | ------------------------- | ------------------- | | ① 工具白名单 | Agent 越权操作(如 AirArc 写代码) | 命令文件 frontmatter 声明 | | ② Python 门控函数 | 跳步执行(如未取证就改代码) | 运行时返回值强制 | | ③ 数据结构约束 | 数据不合法(如 task_id 路径注入) | 契约层校验 | | ④ 强制路由链 | 跳过协作环节(如 AirDo 不调 AirDbg) | finish_worker 强制派发 | | ⑤ 原子操作 + 并发控制 | 状态损坏(如并发写竞态) | 基础设施层保证 | 五层叠加后,任何一层失守都不会直接造成事故——其余层仍能阻断违规。这是**纵深防御**在 AI 工程中的体现。 > 每一层的具体代码实现(allowed-tools frontmatter、ArcPhaseGate/EvidenceFirstGate、WorkerResult.validate_for_finalize、finish_worker 6 级路由链、atomic_json_write + FileLock)见第二十章 § 20.4。 ### 10.3 指令操作化:消除 Agent 推理歧义(原理) V1 的命令文件使用**意图描述**(如"读取派发清单,为每个任务 spawn 隔离的 Worker 子代理"),Agent 需要多轮推理才能翻译成具体操作:用什么工具?参数格式?task-text 从哪取?猜错就多一轮,猜不出来就回退自己执行。 **原理层面的要求**:关键操作路径必须从**意图描述**升级为**可执行伪代码**——给出确切的工具名、参数结构、执行顺序、并发约束。Agent 不再需要推理,只需要**按步骤执行**。 这背后的原则是:**人类读意图,机器读指令**。SKILL.md 同时服务于人类理解("为什么要派发子代理")和 Agent 执行("用什么工具、什么参数派发子代理"),但这两个目标对表达精度的要求完全不同。V2 的做法是在人类可读的意图描述之后,紧跟一份**机器可执行的操作步骤**——两套表达服务于两类读者,互不替代。 > 具体操作化示例(如 AirEng 派发 Worker 的 Agent 工具调用步骤、AirDo 路由链的 finish_worker 伪代码)见第二十章 § 20.5。 ### 10.4 前置条件注入:在派发点强制补齐缺失制品(原理) 很多工作流约束失败,不是因为下游 Agent 不够聪明,而是因为**上游在错误的前提条件下启动了它**。例如:Scheduler 的运行前提本应是 `plan.md` 和 `task-graph.json` 已存在;如果这个前提只靠 Main Agent "记得先做架构设计",那么一旦它漏掉一步,整个后续调度都会在错误世界里开始。 **原理层面的要求**:关键前置条件不能只写在文档里,而要在**派发点**由系统主动检查和补齐。 - 当上游试图直接派发 Scheduler 时,运行时先检查 `.air/shared/plan/plan.md` 和 `task-graph.json` 是否存在 - 如果缺失,不是让 Scheduler 自己"发现后再说",而是系统在派发前直接改写/注入指令,强制先派发 Architect 生成规划 - 下游 Agent 看到的永远是"前置条件已满足"的世界,而不是带缺口的半成品上下文 这条原则很重要,因为它把"先做架构设计"从**流程约定**升级成了**入口门控**。约束不再依赖 Agent 的记忆,而是依赖系统在工作流接缝处的主动校验。 ### 10.5 自由文本也必须进入协议:把 Agent 输出转化为可审计信号(原理) 结构化字段(如 `status=completed`)只能表达"Agent 自称完成",却不能表达它**是如何完成的**。真实工程里,很多违规恰恰藏在自由文本里:例如 Worker 一边写着 `completed`,一边说"for now 先这样";Reviewer 一边给 PASS,一边整份报告都只在说"build 通过、测试通过、函数存在"。 **原理层面的要求**:凡是会参与关闭任务、放行结果的自由文本,都必须被视作**协议的一部分**,进入机器可检查的门控链路。 - Worker 输出不仅要有状态字段,还必须包含编译 / 测试 / `cppcheck` 证据,且不得出现降级关键词 - Reviewer 报告不仅要给 verdict,还必须包含 Code-to-Design 逐行对照表,不能只凭"表面证据"判定 PASS - 调度器读取的不只是结构化结果,还要读取 `output_text` 片段,把文本中的软违规纳入状态机判断 这背后的设计思想是:**自然语言不是日志附属物,而是可被滥用的接口面**。一旦把它纳入协议,系统就能拦住那些"字段合法、语义违规"的软逃逸行为。 --- # 第二部分:实践——Air 插件套件 V2 与 AirCoding Alpha --- ## 十一、V2 架构总览 ### 11.1 V1→V2 核心命题 V1 证明了**制品驱动 + 上下文隔离 + 波次并行**的架构方向成立。V2 要解决三个系统性问题: 1. **可靠性**:状态写入不丢失,并发操作不竞态,崩溃后可自愈 2. **可观测性**:所有引擎操作可追溯,指标可导出,异常主动通知 3. **智能化**:证据门控感知任务类型,轮询频率自适应,修复模式可学习 ### 补充:AirCoding V1.0.0 Alpha 的当前完成态(2026-07) AirCoding 已经不再只是"下一步想做什么"的路线图。到 `V1.0.0 Alpha / 0.1.0 release` 这个时间点,它已经完成了**首个公开可用闭环并开源**。但它的落地路径并不是"完整自研运行时已经成熟",而是更克制也更现实的一条路线:**基于 OpenCode fork 的最小改造,把多 Agent 调度层、权限矩阵和关键门控内嵌进宿主运行时**。 当前 alpha 已实装的关键能力: - **5 类 Agent 已代码注册**:Main / Scheduler / Worker / Architect / Reviewer 都已在运行时注册,不再只是文档里的角色想象 - **权限矩阵已代码化**:Scheduler 无写权限、Architect 仅可写 `.air/shared/plan/**`、Worker 无 `task` 权限,这些边界由代码控制而非 Prompt 自觉 - **确定性调度器已落地**:`coordinator_tick` 已承担 `task-graph.json` 的 DAG 就绪计算、状态迁移、重试预算、里程碑审查预算、`scheduler-state.json` 实时落盘 - **关键门控已进入 hook / tool 层**:派发 Scheduler 前强制检查 `plan.md + task-graph.json`;Worker 缺少 `cppcheck` 或输出降级关键词会被打回;Reviewer 缺少 Code-to-Design 对照表或只凭表面证据判 PASS 会被强制重审 - **最小工程闭环已成立**:架构产物、任务图、调度状态、调试记录都已有明确目录约定,系统已具备可恢复、可审计、可追踪的最小工程能力 当前 alpha 仍未完全到位的部分: - **仍受宿主框架约束**:当前主实现仍主要复用 OpenCode 的 Agent、Session、BackgroundJob、Plugin Hook 和 Tool Registry,而不是完整自研 EventBus + NDJSON IPC 运行时 - **理想形态仍在后续路线**:语言无关运行时、经验学习/记忆层、独立事件存储、动态权限切换等更完整的设计,仍属于后续演进目标 因此,对 AirCoding Alpha 最准确的表述不是"只有 shell 雏形",也不是"完整独立运行时已完成",而是:**它已经完成了一版可公开使用、可公开审视的工程化 Alpha,用宿主内嵌的方式验证了关键约束能否从插件层继续推进到 Agent 框架层。** ### 11.2 统一插件架构 V1 由 8 个独立插件组成,各自有独立的安装、注册和运行时。V2 将 8 个插件统一为 **1 个插件(airplan-v2)12 种模式**: | 模式 | 对应 V1 插件 | V2 核心改进 | | -------- | ---------- | ------------------------------------------------------------- | | **/arc** | AirArc | 三阶段门控、plan mode 阻断、工具白名单只读、弱模型安全审计、DAG 产出、边界测试注入 | | **/eng** | AirEng | 中文锁定、自主决策、ScheduleWakeup 轮询、调度职责边界、事务化合并、ADR 级联失效、worktree 并行 | | **/do** | AirDo | 全专家插件强制路由、UI 任务 frontend-design Skill、task_id 注入防护 | | **/dbg** | AirDbg | EvidenceFirstGate 先读后写门控、步骤追踪不可跳过、修复前 git snapshot、选择性快照 | | **/xdb** | AirXDB | DRM/KMS 原生截图、Xvfb headless CI、多后端自动降级 | | **/ndb** | AirNDB | TLS 解密、pcapng 支持 | | **/sdb** | AirSDB | 六语言后端(cppcheck/clang-tidy/clippy/go-vet/tsc/mypy)、diff 模式 | | **/ctx** | AirContext | 压缩质量校验、自适应 Token 估算、陈旧锁检测、三级降级压缩 | | **/dep** | 新增 | SSH 远程构建 + scp + MD5 校验 + systemd 生命周期 + 冒烟验证 | | **/tst** | 新增 | 统一测试执行(pytest/googletest/jest/go test/cargo test)+ 结构化报告 | | **/sec** | 新增 | 制品敏感数据扫描 + 白名单 + advisory/blocking 模式 | | **/rvr** | 新增 | 需求一致性审查 + Code-to-Design 对照 + 高风险审计 + verdict 控制合并 | ### 11.3 流水线拓扑 ``` ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ /arc │────►│ /eng │────►│ /do │────►│ /dbg │ │ (规划) │ │ (调度) │ │ (执行) │ │ (调试) │ └──────────┘ └──────────┘ └──────────┘ └────┬─────┘ │ │ │ │ │ task-graph │ Agent 子代理 │ finish 路由链 │ │ + plan-delta │ run_in_bg │ │ │ │ ├──────────────────┤ │ │ ▼ ▼ │ │ ┌──────────┐ ┌──────────┐ │ │ │ /xdb │ │ /ndb │ │ │ │(GUI证据) │ │(网络证据)│ │ │ └──────────┘ └──────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌──────────┐ ┌──────────┐ │ │ │ /sdb │ │ /rvr │ │ │ │(静态分析)│ │(需求审查)│ │ │ └──────────┘ └──────────┘ │ │ │ │ │ ┌──────────────┐ │ │ │ │ /dep │ │ │ │ │ (部署) │ │ │ │ └──────────────┘ │ │ │ ┌──────────────┐ │ │ │ │ /tst │ │ │ │ │ (测试) │ │ │ │ └──────────────┘ │ │ │ ┌──────────────┐ │ │ │ │ /sec │ │ │ │ │ (安全扫描) │ │ │ │ └──────────────┘ │ │ │ │ │ └───────────────────────────────────┘ │ │ │ ┌──────────┐ └───────────────────►│ /ctx │ │(上下文) │ └──────────┘ ``` 关键变化:V1 的 AirDo 只路由到 AirDbg/AirXDB。V2 的 /do 在 finish 时执行**全专家插件强制路由链**——根据任务类型和状态,依次路由到 /dbg、/xdb、/ndb、/sdb、/rvr,无强制路由时才允许 merge。 ### 11.4 基于制品的通信协议(V2 扩展) ``` AirPlan/ ├── AGENTS.md # 项目级 AI 上下文(多模式标记块共管) ├── plan.md # 总体执行计划 ├── todo.md # 结构化任务表(人可读,DAG 的辅助视图) ├── docs/ │ ├── architecture/ │ │ ├── adr/ADR-NNNN-*.md # 架构决策记录 │ │ └── c4/module.md # C4 模块边界文档 │ ├── debug/ │ │ ├── debug-log.md / gui-debug-log.md │ │ └── airxdb-artifacts/ │ ├── network/ │ │ ├── airndb-log.md │ │ └── airndb-captures/ │ ├── reviews/ │ │ └── {task_id}-review.md # V2: AirRvr 审查报告 │ └── staticanalysis.md └── state/ ├── airarc/reviews/ │ ├── execution-plan.json │ ├── parallel-review.json │ ├── task-graph.json # V2: 动态 DAG(调度权威来源) │ └── plan-delta.json # V2: 增量重规划差异 ├── aireng/ │ ├── state.json / plans/ │ ├── dispatch/{wave-id}.json │ ├── archive/{task-id}-{ts}.json # V2: 已合并结果归档 │ └── repairs/{task-id}/{repair-id}/ ├── airdo/tasks/{task-id}/ │ ├── brief.md / subagent-handoff.md │ ├── result.json / worker-state.json ├── airdbg/{state,sessions,snapshots}/ # V2: 新增 snapshots 目录 ├── airxdb/{state,requests,sessions}/ ├── airndb/ ├── airsdb/reports/ ├── airdep/sessions/ # V2: 部署会话 ├── airtst/reports/ # V2: 测试报告 ├── airrvr/reviews/ # V2: 审查报告 ├── airsec/ # V2: 安全扫描 ├── aircontext/ # V2: 上下文管理 └── events.jsonl # V2: 事件日志(完整时间线) ``` V2 新增 `events.jsonl`——结构化事件日志(JSONL 格式),与 `state.json` 互补:`state.json` 是当前快照,事件日志是完整时间线。事件类型覆盖全生命周期: | 事件类型 | 触发时机 | 负载信息 | | ----------------------------------- | ------------- | ----------------------------------------------- | | `task.dispatched` | Eng 派发任务 | taskId, waveId | | `task.entered` | Worker 进入 | taskId, uiRouting | | `task.finished` | Worker 完成 | taskId, status, routingTargets | | `task.completed` | 合并成功 | taskId, archivePath | | `task.blocked` | 任务阻塞 | taskId, status | | `merge.started` / `merge.completed` | 合并开始/完成 | taskId, appliedDocCount | | `intervention.stall` | 停滞检测 | taskId | | `worker.timeout` | Worker 超时 | taskId, ageSeconds | | `eng.replan.triggered` | 增量重规划 | added, removed, modified | | `adr.change.detected` | ADR 变更检测 | adrId, kind | | `adr.invalidation` | ADR 级联失效 | adrId, invalidatedCompleted, cascadedDownstream | | `worktree.merge.conflict` | Worktree 合并冲突 | taskId, action | | `context.compacted` | 上下文压缩 | compressionLevel, tokens | --- ## 十二、核心实现详解 ### 12.1 调度算法:从静态表格到动态 DAG #### V1 的静态表格调度 V1 的 AirArc 产出 `todo.md` 表格,AirEng 基于表格解析任务、构建依赖边、波次分组。当需求变更时 Arc 全量重新生成表格,Eng 无法增量吸收,需多轮 AI 迭代恢复。 #### V2 的 DAG 调度 V2 的 AirArc 同时产出 `task-graph.json`(动态 DAG)和 `todo.md`(人可读辅助视图)。调度逻辑从 DAG 计算而非表格解析: ``` 输入: todo.md + task-graph.json 1. 构建 DAG → TaskGraph (TaskNode + Edge) 2. 注入边界测试任务 → _inject_boundary_tests() - 按 files_dirs 推断模块(取第一级目录作为模块名) - 每个模块创建接口测试 + 单元测试任务 - 实现任务 → 测试任务建立依赖边 3. 依赖边构建 → review.py build_parallel_review() 4. 波次调度 (拓扑排序): ready_tasks() → 入度 = 0 且 status = TODO 的任务 调度冻结时返回空列表 5. 区域冲突检测 → RegionConflictDetector NONE: 直接并行 SOFT: worktree 隔离并行 HARD: 强制串行 6. 产出 execution-plan.json + task-graph.json ``` 增量重规划(需求变更时): ``` 1. todo.md mtime > task-graph.json mtime → 触发 maybe_replan() 2. 全量重建新 DAG → new_graph.diff(old_graph) → PlanDelta 3. old_graph.apply_delta(delta) → 保留已调度任务的 DISPATCHED/DONE 状态 4. 写回 task-graph.json + plan-delta.json 5. emit ARC_REPLANNED 事件 ``` ### 12.2 全链路上下文隔离 AirEng 派发 /do Worker 时使用 Agent 工具(`run_in_background: true`),**每个子 Agent 拥有独立上下文**,天然满足 `fork_context=false`。 V2 的 spawn_workers() 标准化了派发流程: ```python def spawn_workers(project_root, task_ids) -> list[dict]: """为每个 ready 任务准备 Agent 派发指令。 返回 Agent 调用参数列表,Eng Agent 遍历列表逐个调用。""" for tid in task_ids: node = graph.nodes.get(tid) instructions.append({ "description": f"Do Worker: {tid}", "subagent_type": "general-purpose", "run_in_background": True, # 关键:后台运行,Eng 不阻塞 "prompt": f"你是 AirDo Worker,任务 ID: {tid}...\n" f"## 任务\n{task_text}\n" f"## 文件范围\n{files}\n" f"## 完成标准\n{done_when}\n" f"## 工作流程\n1. 初始化 Worker 状态\n" f"2. 读取项目文件\n3. 实现任务需求\n" f"4. 运行 finish 命令\n", }) ``` **传递的信息**(5K-20K token):任务描述 + 文件范围 + 完成标准 + 6 个必读文件路径 + 10 条执行契约。 **不传递的信息**:调度器 200K 对话历史、其他 Worker 状态、引擎内部 state。 信噪比提升约一个数量级。 ### 12.3 全专家插件强制路由链 V1 的 AirDo finish 时只有两条路由(GUI 关键词 → AirXDB,blocked → AirDbg),且为建议性而非强制。V2 将路由升级为 **6 级强制链**: ``` finish_worker() 路由决策(按优先级): ┌─ 1. blocked / failed → 强制 AirDbg ────────────── (最高优先级) │ "AirDbg mandatory before return" │ ├─ 2. done 但无 validations + 无 filesChanged → 强制 AirDbg │ "done without evidence — mandatory debug review" │ ├─ 3. GUI 任务(关键词命中)且无 xdbSessions → 强制 AirXDB │ "GUI task requires screenshot evidence" │ ├─ 4. 网络任务(关键词命中)且无 ndbSessions → 强制 AirNDB │ "network task requires packet capture evidence" │ ├─ 5. C/C++ 文件变更(.cpp/.h/.hpp)且无 sdbReports → 强制 AirSDB │ "C/C++ task requires static analysis" │ ├─ 6. 所有 done 任务且无 rvrReviews → 强制 AirRvr │ "completed task requires requirements review" │ └─ 无强制路由触发 → merge ──────────────────────── (最低优先级) ``` 返回 `routingDecisions` 列表(可能有多个路由目标),Worker 依次处理后重新 finish。路由决策由 Python 代码生成,不依赖 LLM 判断——**即使 LLM 尝试跳过,代码层仍然强制执行**。 ### 12.4 事务化合并流水线 V1 的 `merge_worker_result()` 执行 8+ 次文件写入,中间崩溃导致不一致。V2 引入事务语义的 **6 阶段合并流水线**: ``` merge_worker_result(project_root, result_path): state_lock = FileLock(state.json) todo_lock = FileLock(todo.md) with state_lock: ┌─ Phase 1: 验证 ──────────────────────────────────────┐ │ enforce_doc_sync_requirements(result) │ │ - deployRequired → 必须有 deploy 验证 │ │ - documentUpdates 路径必须在 AirPlan/ 内 │ │ 失败 → 抛 ValueError,不触碰文件系统 │ ├─ Phase 1.5: Rvr 审查(可选)─────────────────────────┤ │ reviewPolicy.requireBeforeMerge 或 result.requireReview │ │ verdict=fail → 阻止合并 │ │ verdict=conditional-pass → 记录遗留项但允许合并 │ ├─ Phase 2: 归档 ──────────────────────────────────────┤ │ archive/{task_id}-{timestamp}.json │ │ 原子写入,可重试 │ ├─ Phase 3: 应用文档更新 ──────────────────────────────┤ │ apply_document_updates(result.documentUpdates) │ │ write / append 两种动作 │ ├─ Phase 4: 同步引擎管理文档 ──────────────────────────┤ │ sync_engine_managed_docs(plan.md, debug-log.md, ...) │ │ 去重:检查 taskId 标记行是否已存在 │ ├─ Phase 5: 更新 todo(嵌套 FileLock)────────────────┤ │ update_todo_after_merge() │ │ 动态定位 Status 列(不硬编码列索引) │ │ 附加 <!-- merged:path --> 引用便于追溯 │ ├─ Phase 6: 更新引擎状态 ──────────────────────────────┤ │ state.json 原子写入 │ │ mergedResults 截断至 100 条(防止无界增长) │ │ 移除 activeWorkers 中已完成的任务 │ ├─ Phase 6.5: TaskGraph 状态同步 ─────────────────────┤ │ task-graph.json 节点 status → DONE │ │ 防止下次 dispatch 重复派发已完成任务 │ └──────────────────────────────────────────────────────┘ emit MERGE_COMPLETED + TASK_COMPLETED / TASK_BLOCKED ``` ### 12.5 AirArc 三阶段门控 V1 中 AirArc 频繁被 Agent 内置 plan mode 劫持,且在用户仅说一两句时就立即生成执行计划。V2 从工具层和代码层双重阻断: **工具层(命令文件 frontmatter)**: ```yaml allowed-tools: "[Read, Glob, Grep]" # 只有只读工具 deny-plan-mode: true # 硬性阻断 plan mode ``` **代码层(ArcPhaseGate)**: ``` 三阶段流程(不可跳过): Phase 1: discussing(默认) - 与用户反复讨论需求细节、边界条件、隐含约束 - 主动提问澄清模糊点 - 分析现有代码库结构 - 提出多种架构方案及优劣对比 - execution-plan.json 写入被禁止 Phase 2: proposing - 向用户呈现推荐架构方案 - 明确等待确认:"请确认此架构方案是否符合预期" - 用户有异议 → 回到 Phase 1 - execution-plan.json 写入被禁止 Phase 3: confirmed - 仅在用户说"确认"/"可以"/"同意"后自动推进 - 允许生成 execution-plan.json 和 task-graph.json - 规划产出严格对应用户确认的架构方案 ``` `parallel_review_mode()` 在写入前检查 `gate.can_write_plan()`,phase 不是 `confirmed` 则返回 `{"blocked": true, "reason": "arc phase is 'discussing'..."}`。 ### 12.6 AirDbg 先读后写门控 V1 的 AirDbg 7 步工作流为建议性——模型经常跳过取证直接修改代码,引入新问题且污染代码库。V2 通过 `EvidenceFirstGate` 硬性执行: ```python class EvidenceFirstGate: EVIDENCE_TYPES = [ "screenshot", # AirXDB 截图 "packet_capture", # AirNDB 抓包 "static_analysis", # AirSDB 静态分析 "log_analysis", # 日志分析 "code_trace", # 代码追踪(读取相关文件、调用链分析) "reproduction", # 复现步骤执行 ] def can_modify_code(self) -> bool: return len(self._collected_evidence) > 0 def gate_check(self) -> None: if not self.can_modify_code(): raise WorkflowViolation( "未执行任何取证行为,禁止修改代码。") ``` 步骤追踪机制: | 步骤 | 名称 | 推进条件 | 特殊规则 | | --- | ----------------- | ---------------------------------- | ----------------------------- | | 1 | confirm_symptoms | 提供 symptom/expected/actual | 取证步骤,计入 collectedEvidence | | 2 | load_context | 无强制证据 | 取证步骤,计入 collectedEvidence | | 3 | reproduce | 提供 reproduction_steps | 可跳过(标记为 non-reproducible) | | 4 | locate_root_cause | 提供 root_cause_analysis | 取证步骤,计入 collectedEvidence | | 5 | fix | 提供 fix_description + files_changed | **硬性门控**:collectedEvidence 非空 | | 6 | verify | 提供 validation_result | 同类证据验证 | | 7 | close_out | 提供 residual_risk + adr_updates | 更新项目文档 | 修复前快照:`pre_fix_snapshot()` 在步骤 5 执行前自动创建 git tag 回滚点。V2 改进为**选择性快照**——只提交 Worker result 中声明的 `filesChanged` 范围内的文件,避免全量 commit 混入无关变更。 ### 12.7 Worktree 隔离并行(同文件不同区域) V1 的冲突检测粒度为文件级。实际场景中,同一文件的不同区域可能互不影响(如 Qt 组件样式 vs 状态机逻辑),被迫串行降低了并行效率。 V2 引入**三级冲突检测 + git worktree 隔离**: ``` RegionConflictDetector.detect(): file_overlap = set(task_a.write_set) & set(task_b.write_set) if not file_overlap → NONE(直接并行) if 无区域信息 → SOFT(worktree 隔离并行) for fpath in file_overlap: ra = regions_a[fpath] # [(start_line, end_line), ...] rb = regions_b[fpath] if 行号区间重叠 → HARD(必须串行) else → SOFT(worktree 隔离并行) ``` WorktreeIsolation 生命周期: ``` 1. create_worktree(task_id, base_ref="HEAD") → git worktree add -b air-{task_id} {wt_path} HEAD → Worker 在独立 worktree 目录中执行 2. merge_back(task_id, wt_path) → git merge --no-ff air-{task_id} → 成功: cleanup(task_id) → git worktree remove + branch -D → 失败: _abort_merge() → 返回 Conflict 列表 3. 合并失败时的三级降级: → 升级到 AirDbg(调试冲突) → AirDbg 也失败 → 降级为串行重执行 → emit WORKTREE_MERGE_CONFLICT 事件 ``` Eng 的 `monitor_engine()` 在每轮轮询中自动检查 `.git/worktrees/air-*` 目录,处理已完成但未 merge 的 worktree。 ### 12.8 AirEng 调度引擎 V2 #### 角色边界硬性约束 V2 从 SKILL.md 和代码层双重约束 AirEng 的职责边界: ``` 核心职责:调度,不是编码 默认禁止:编写源代码、修改项目文件 极端接管(唯一例外,全部条件满足才允许): 1. 子代理陷入循环阻塞,修复预算已耗尽 2. 问题已通过 AirDbg 定位到明确的根因 3. 修复范围极小(≤5 行改动) 4. 继续等待 Worker 重派发已无意义 → 进入前必须记录 EXTREME_TAKEOVER 日志 → 即使接管也必须调用相关专家插件(Dbg/XDB/NDB/SDB/Rvr) ``` #### 监控循环 V2 ``` monitor_engine(): 1. 遍历 activeWorkers: a. Worker 存活时间 > 2 小时 → wall-time-exceeded → terminate b. state 文件 mtime > 5 分钟 → stalled → re-dispatch-or-block c. status = done → ready_to_merge 2. 资源压力检测: loadavg > 2× CPU 数 → 暂停派发 3. ADR 变更检测: ADRWatcher.detect_changes() → superseded/modified → handle_adr_invalidation() 4. Worktree 合并检查: → 已完成但未 merge 的 worktree → check_worktree_merge_status() → merge 失败 → 升级到 AirDbg → 再失败 → 降级串行 5. emit ENGINE_CYCLE 事件(stalledCount, readyToMerge, interventionCount) ``` #### 派发决策链 ``` dispatch_worker_group(): 1. maybe_replan() — 检查 todo.md mtime vs task-graph.json mtime → todo 更新 → 触发增量重规划 2. 检查调度冻结(dispatch_frozen = true → 返回 blocked) 3. 检查 block-release verdict(AirRvr 终审 → 阻止所有派发) 4. _select_ready_tasks() — 从 DAG 计算入度为 0 的 TODO 任务 → DAG 中 ready 为空时不 fallback 到 todo.md(空列表也是正确答案) 5. 区域冲突检测(多任务时) → HARD 冲突 → 强制串行,只派第一个 → SOFT 冲突 → 标记 worktree 隔离 6. 写 dispatch payload → emit TASK_DISPATCHED ``` ### 12.9 AirRvr 需求审查器(V2 新增) V1 中任务"完成"的判定仅依赖 Worker 自报 + AirEng 结构验证。没有任何组件将交付物与原始需求进行独立比对。AirRvr 填补了这一空白。 **多维度审查**: | 审查维度 | 检查内容 | 产出 | | -------------- | -------------------------------- | ------------------------------------------------------ | | 需求覆盖度 | 原始需求中的每个要求点是否被交付物覆盖 | coverage: [{requirement, status, evidence}] | | 意图一致性 | 交付物是否解决了需求想解决的真正问题 | intentAlignment: aligned / divergent | | 回归风险 | 变更是否破坏了需求的已有功能 | regressionRisk: none / low / medium / high | | 代码质量 | 复杂度、可读性、重复率、异常处理 | codeQuality: {complexity, readability, ...} | | 生命周期健壮性 | 资源释放、连接管理、超时/重试/降级 | lifecycleHealth: {resourceLeak, ...} | | 运行时稳定性 | 内存泄漏、竞态条件、崩溃路径 | runtimeStability: {crashRisk, ...} | | Code-to-Design | 代码实现与设计文档逐行对照 | codeToDesignTable: [{designRef, codeLocation, status}] | | 日志标准 | spdlog 集成、非标准日志、debug/release 开关 | loggingChecks: {spdlogIntegrated, ...} | | **高风险审计** | 生命周期/空指针/悬垂指针/异常安全/并发 | highRiskAudit: {lifecycle, nullPointer, ...} | **高风险审计五项检查**(里程碑审查时强制执行): ``` 生命周期风险: - 资源申请与释放是否配对(new/delete, malloc/free, open/close) - RAII 是否覆盖所有资源持有 - 异步操作的回调/完成是否保证执行 空指针/悬垂指针: - 指针使用前是否判空 - 智能指针生命周期是否覆盖使用范围 - 回调闭包中捕获的指针是否仍然有效 - 容器元素删除后迭代器是否失效 异常安全: - 异常路径中资源是否正确释放 - 是否存在异常吞没(catch 后无处理) - 跨模块边界是否有异常传播保护 并发风险: - 共享状态是否有锁保护 - 锁顺序是否一致(防死锁) - 条件变量是否有虚假唤醒保护 ``` **verdict 控制合并**: | verdict | 行为 | 集成点 | | --------------------------------- | ------------------- | ----------------------- | | `pass` | 正常合并 | merge Phase 1.5 | | `conditional-pass` | 合并但记录 residualItems | state.json | | `fail` | 阻止合并,要求修订 | merge 抛 ValueError | | `deliveryVerdict = block-release` | **阻止所有后续派发** | dispatch_worker_group() | 三种审查模式: | 模式 | 触发时机 | 审查范围 | | ------------- | ------------------------ | ---------------------- | | per-task | 单个任务完成后(/do finish 自动路由) | 单任务 | | per-wave | 一个波次所有任务完成后 | 整波次 | | per-milestone | 项目阶段结束时 | 全量(比对 requirements.md) | ### 12.10 AirDep 部署器(V2 新增) V1 无部署插件,导致"完成但未部署"事故(T-028b 发现 4 个 "done" 任务未实际部署,延迟发布一整天)。AirDep 提供标准化的部署流水线: ``` deploy() 完整流程: Step 1: 远程构建(可选) SSH → cd {build_dir} && {build_cmd} 超时 600s Step 2: 二进制传输 + MD5 校验 scp local_binary → remote:/tmp/ local_md5 = md5_file(local) remote_md5 = SSH md5sum remote 不匹配 → 返回失败 "md5 mismatch after transfer" Step 3: 部署二进制 SSH mv /tmp/{binary} → {deploy_dir}/ Step 4: systemd 生命周期 SSH systemctl daemon-reload SSH systemctl restart {service_name} SSH systemctl is-active {service_name} 返回 service_status Step 5: 冒烟验证(可选) SSH {smoke_test_cmd} 记录 smoke_test_passed Step 6: 持久化 DeploymentRecord → state/airdep/sessions/ emit DEPLOY_COMPLETED 事件 ``` 与合并流水线集成:`deployRequired=true` 时,`enforce_doc_sync_requirements()` 验证 result 中必须包含 `remote-deploy-verify` 或 `remote-binary-md5` 类型的 validation。 ### 12.11 AirTst 测试运行器(V2 新增) 统一测试执行接口,支持 5 种框架: | 框架 | 命令 | 解析方式 | | ---------------- | ----------------------------------- | ---------------- | | pytest | `python -m pytest --json-report -q` | JSON summary | | GoogleTest/CTest | `ctest --output-on-failure` | 文本 + JSON 双解析 | | jest/vitest | `npx jest --json` | JSON testResults | | go test | `go test -json ./...` | JSONL 事件流 | | cargo test | `cargo test -- --format=json` | JSONL 事件流 | 产出结构化 `TestRunResult`:`{framework, total, passed, failed, disabled, duration, failures}`。 与 AirArc 集成:规划阶段自动注入边界测试任务(`T-TEST-001` 等),标记 `test_required=true`,Done When 强制包含"测试通过"。 ### 12.12 AirSec 安全扫描器(V2 新增) 扫描制品中的敏感数据,防止 API 密钥、令牌、密码泄露到项目文档: ``` SECRET_PATTERNS (6 种): - api_key: api_key = "..." - aws_key: AKIA... - private_key: -----BEGIN RSA PRIVATE KEY----- - token: token = "..." - jwt: eyJ... - url_credential: https://user:password@... 三层过滤: 1. 内容模式匹配 → 原始发现 2. 允许列表过滤(EXAMPLE, YOUR_API_KEY, placeholder 等) 3. 文件名白名单过滤(.example., test_, mock_, _test.py, .fixture.) 两种运行模式: - advisory: 只报告,不阻止合并 - blocking: 发现敏感数据时阻止合并(merge Phase 1 检查 clean=false) ``` ### 12.13 AirContext V2 改进 #### 压缩质量校验 ```python MUST_PRESERVE_PATTERNS = [ r"[A-Za-z0-9_\-/]+\.(py|ts|js|cpp|h|md|json|yaml)", # 文件路径 r"ADR-\d{4}", # ADR 引用 r"TODO|FIXME|HACK", # 未完成项 r"INV-\d+", # 不变量引用 ] ``` 校验逻辑:对比原始文本和摘要中各模式的匹配集合,丢失 > 30% 则标记为失败。失败触发三级降级: | 降级级别 | 策略 | 适用场景 | | ---------------- | ----------------------------- | ---- | | `RETRY` | 重新压缩(换 prompt) | 首次失败 | | `FALLBACK_MODEL` | 换模型 + 简化 prompt + 放宽 token 限制 | 重试失败 | | `TRUNCATE` | 激进截断(保留最近 50 行 + 所有 ADR 引用行) | 最终兜底 | #### 陈旧锁检测 ```python def acquire_compactor_lock(lock_path): try: fd = os.open(lock_path, O_CREAT | O_EXCL | O_WRONLY) os.write(fd, str(os.getpid())) return True except FileExistsError: pid = int(lock_path.read_text()) os.kill(pid, 0) # 不发信号,只检查进程存在 → 进程存活 → 返回 False(锁有效) → 进程不存在 → 删除陈旧锁 → 重试 ``` ### 12.14 AirSDB V2 多语言静态分析 V1 仅支持 Cppcheck + C/C++。V2 扩展为 6 种后端: | 后端 | 语言 | 工具 | | ----------- | ---------- | ----------------------------------- | | Cppcheck | C/C++ | `cppcheck --check-level=exhaustive` | | Clang-Tidy | C/C++ | `clang-tidy` | | Clippy | Rust | `cargo clippy` | | go vet | Go | `go vet + staticcheck` | | tsc | TypeScript | `tsc --noEmit` | | mypy + ruff | Python | `mypy + ruff` | 新增 **diff 模式**:比较两次扫描结果,高亮新增/消除的 finding。通过 `(file, line, rule_id)` 三元组匹配,产出 `DiffReport(new_findings, resolved_findings, unchanged_count)`。 ### 12.15 AirXDB V2 扩展截图能力 V1 仅支持通用桌面截图。V2 扩展为多后端自动降级: | 后端 | 适用场景 | 技术实现 | | -------- | -------------- | ------------------------------------- | | KMS grab | 嵌入式 DRM/KMS 显示 | `ffmpeg -f kmsgrab -i /dev/dri/card0` | | Xvfb | CI headless 环境 | `Xvfb :99 + xwd -root` | | fallback | 通用桌面环境 | Midscene.js / Playwright | `--prefer auto` 时按 kms → xvfb → fallback 顺序自动检测。 --- ## 十三、基础设施层 ### 13.1 原子 I/O(消除 V1 数据损坏) V1 使用 `path.write_text()` 直接覆盖 JSON 文件——进程崩溃时 `state.json` 截断,下次加载 `JSONDecodeError`。V2 的 `atomic_json_write()`: ``` 写入流程: 1. 旧文件 → os.replace(path, path.bak) # 单级轮转备份 2. tempfile.mkstemp(dir=path.parent) # 同目录临时文件 3. os.write(fd, json_data) # 写入临时文件 4. os.close(fd) 5. os.replace(tmp, path) # POSIX 原子替换 安全加载: 1. json.loads(path.read_text()) # 正常加载 2. JSONDecodeError → 尝试 .bak 恢复 # 自动从备份恢复 3. .bak 不存在 → 返回 None + 日志告警 # 不静默吞异常 ``` ### 13.2 文件锁(消除 V1 并发竞态) V1 无任何锁、互斥量或原子操作。两个 Worker 同时完成时 `todo.md` 读-改-写竞态。V2 的 `FileLock`: ```python class FileLock: """基于 fcntl.flock 的进程级文件锁""" def __enter__(self): self._fd = os.open(path, O_CREAT | O_RDWR) while True: fcntl.flock(self._fd, LOCK_EX | LOCK_NB) # 非阻塞获取 → 成功 → return self → 超时 → raise TimeoutError → 等待 0.1s 重试 def __exit__(self): fcntl.flock(self._fd, LOCK_UN) os.close(self._fd) ``` 所有 `state.json` 和 `todo.md` 的读-改-写操作必须持有对应锁。合并流水线中嵌套两层锁(state_lock + todo_lock),保证跨文件一致性。 ### 13.3 公共工具层(消除 V1 代码重复) V1 中 `_json_dump` 5 份、`_ordered_unique` 4 份、`policy normalization` 3 份、`marker block upsert` 2 份、`_session_stamp` 格式不一致。V2 统一为 `air_runtime/utils.py`: | 函数 | 消除的重复 | 功能 | | -------------------- | --------- | ------------------------ | | `ordered_unique()` | 4 份 | 保序去重,支持字符串和字典列表 | | `session_stamp()` | 格式不一致 | 统一文件系统安全时间戳 | | `now_iso()` | 多处 | ISO 格式 UTC 时间戳 | | `normalize_policy()` | 3 份 | 通用策略合并,类型自动转换 | | `sanitize_task_id()` | 路径注入风险 | 正则校验 `[A-Za-z0-9_\-\.]+` | | `sanitize_marker()` | HTML 注入风险 | 拒绝 `-->` 和 `<!--` | | `truncate_history()` | 无界增长 | 截断至 max_items(默认 100) | ### 13.4 `air_runtime` 模块结构 ``` air_runtime/ __init__.py contracts.py # 数据契约(WorkerResult, TaskRecord, DeploymentRecord) io.py # 原子 I/O(替代 5 份 _json_dump) lock.py # 文件锁(fcntl.flock) utils.py # 公共工具(消除重复代码) events.py # 事件日志(JSONL + 轮转截断) task_graph.py # 动态任务依赖图(DAG + PlanDelta + ADR 级联失效) adr_watcher.py # ADR 文件变更监控(SHA256 hash 对比) worktree.py # git worktree 隔离并行(区域冲突检测) partial_replanner.py # 局部重规划(仅受影响任务子集) evidence_gate.py # 任务类型感知证据门控 paths.py # 路径约定 todo_parser.py # TODO 解析(动态列索引) review.py # 并行审查(依赖环检测、写集冲突) project_bootstrap.py # 项目引导(幂等创建 17 个制品) installer.py # 安装器(动态路径解析 + 安装后验证) deploy_runtime.py # AirDep 运行时 test_runtime.py # AirTst 运行时(5 框架解析器) sec_runtime.py # AirSec 运行时(6 模式 + 3 层过滤) review_runtime.py # AirRvr 运行时(审查报告 + 高风险审计) sdb_backends.py # AirSDB 多后端 xdb_capture.py # AirXDB 多后端截图 modes/ arc_mode.py # AirArc 模式(三阶段门控 + DAG 构建 + 弱模型安全) eng_mode.py # AirEng 模式(调度引擎 + 事务化合并 + ADR 级联) eng_orchestrator.py # AirEng 编排器 do_mode.py # AirDo 模式(全专家路由链 + UI 检测) dbg_mode.py # AirDbg 模式(7 步追踪 + 先读后写 + 快照) merge_pipeline.py # 合并管线(6 阶段纯函数集合) xdb_mode.py # AirXDB 模式 sdb_mode.py # AirSDB 模式 ndb_mode.py # AirNDB 模式 ctx_mode.py # AirContext 模式(三级降级 + 质量校验) dep_mode.py # AirDep 模式 tst_mode.py # AirTst 模式 sec_mode.py # AirSec 模式 rvr_mode.py # AirRvr 模式 ``` --- ## 十四、架构状态持久化机制 ### 14.1 标记块命名空间:多模式共管同一文件 `AirPlan/AGENTS.md` 和 `AirPlan/docs/architecture/c4/module.md` 被所有模式共同维护,通过**两层标记块命名空间**避免互相覆盖: **模式层**(各模式独立维护): | 标记块 | 所有者 | 内容 | | --------------------------- | ---- | ----------- | | `<!-- AIRARC:BEGIN/END -->` | /arc | 架构规划工作流指令 | | `<!-- AIRENG:BEGIN/END -->` | /eng | 调度引擎工作流指令 | | `<!-- AIRDO:BEGIN/END -->` | /do | 任务执行器工作流指令 | | `<!-- AIRDBG:BEGIN/END -->` | /dbg | 调试工作流指令 | | `<!-- AIRXDB:BEGIN/END -->` | /xdb | GUI 证据采集工作流 | | `<!-- AIRNDB:BEGIN/END -->` | /ndb | 网络证据采集工作流 | | `<!-- AIRSDB:BEGIN/END -->` | /sdb | 静态分析工作流 | **引擎层**(merge_pipeline.py 在每次合并时自动更新): | 标记块 | 所在文件 | 自动写入内容 | | -------------------------------------------- | -------------- | ------------- | | `<!-- AIR-ENGINE:AGENTS-SYNC:BEGIN/END -->` | `AGENTS.md` | 最新合并任务的完整审计记录 | | `<!-- AIR-ENGINE:C4-SYNC:BEGIN/END -->` | `c4/module.md` | 最新合并对模块边界的影响 | | `<!-- AIR-ENGINE:TODO-RUN-LOG:BEGIN/END -->` | `todo.md` | 累积合并日志 | ### 14.2 合并去重(V2 修复 P3-1) V1 中 AGENTS.md 持续膨胀——同一任务记录重复 2-3 次。V2 的 `sync_engine_managed_docs()` 在追加标记行前检查是否已存在: ```python # 去重:若该 taskId 的标记行已存在,则不再追加 if any(line.lstrip().startswith(marker_prefix) for line in existing.splitlines()): continue ``` 同样,`update_todo_after_merge()` 在更新行内 `<!-- merged:... -->` 引用前先剥离已有引用: ```python cleaned = _strip_merged_refs(line) # 去除行内所有已存在的 merged 引用 ``` --- ## 十五、复杂项目长期迭代管理 ### 15.1 任务生命周期与状态管理 V2 的任务生命周期扩展了 INVALIDATED 状态(ADR 级联失效): ``` TaskGraph 节点状态: TODO ──(调度)──→ DISPATCHED ──(合并成功)──→ DONE │ │ └──(合并失败)──→ BLOCKED │ │ │ DONE/DISPATCHED ──(ADR变更)──→ INVALIDATED ◄───┘ Worker 状态: entered → implementing → finished → archived 引擎状态: idle → planning → dispatching → monitoring → merging → completed | blocked 修复状态: queued → active → resolved | queued(预算内重试) ADR 失效流程: ADR superseded → dispatch_frozen → INVALIDATED → git revert → Arc replan → unfreeze ``` ### 15.2 修复预算与自动重试 当任务返回 `blocked` 或验证失败时,系统自动创建修复尝试: ``` 执行 → blocked/failed → ensure_repair_attempts_for_result() → 创建 RepairAttempt → 写入 attempt.json(完整失败上下文) → 写入 repair-brief.md(修复指引) → 重新派发 Worker → done: 修复成功 → resolved → blocked: 预算未耗尽 → 再试 → 预算耗尽 → 升级到用户 ``` V2 配置:`repairPolicy.maxAttempts = 3`。 ### 15.3 停滞检测与干预 V2 的停滞检测增加了 Worker 超时和资源压力维度: | 检测类型 | 条件 | 动作 | | ----------- | --------------------- | ----------------------------------------- | | 文件停滞 | state 文件 mtime > 300s | re-dispatch-or-block | | 存活超时 | Worker 存活 > 7200s | terminate-and-block | | 资源压力 | loadavg > 2× CPU 数 | 暂停派发 | | Worktree 冲突 | merge_back 失败 | upgraded-to-airdbg → downgraded-to-serial | | ADR 变更 | SHA256 hash 变化 | invalidate-by-adr | ### 15.4 文档级联:前序任务如何影响后续任务 ``` Wave 1 (T-001, T-002) 完成并合并 → todo.md: T-001 DONE, T-002 DONE → task-graph.json: 节点 status 同步为 DONE(Phase 6.5) → ADR/C4/plan.md: 文档更新已应用 → AGENTS.md: AGENTS-SYNC 块已刷新(去重后) → events.jsonl: MERGE_COMPLETED + TASK_COMPLETED 事件已记录 Wave 2 (T-003, T-004) 派发 → Worker 读取 Required Reads (6 个文件) → 看到的是已包含 Wave 1 产出的最新文档 → Worker 无需与 Wave 1 的 Worker 通信 → 自动获得前序工作的全部上下文 → AirRvr 审查时可引用 Wave 1 的审查报告 ``` --- ## 十六、多模型交叉审计实践 ### 16.1 AirCoding V1.0.0 Alpha 交叉审计 4 个模型对 146 个源文件独立审计,产出 18+ 份报告: | 模型 | 评级 | 发现数 | 阻断级 | 审计角度 | | ----------- | --- | ---- | --- | ------------- | | DeepSeek | B+ | 97 | 10 | 任务完成度 | | Opus 4.8 | C+ | 140+ | 18 | 逐字段对照规范 | | MiniMax-M3 | C+ | 38+ | 18 | 可执行性 + 治理 | | Qwen3.7-Max | D+ | 84 | 31 | 需求覆盖 + 规范一致性% | **评级分歧根因**:DeepSeek 以"123/123 文件创建"为主轴 → B+;其余三模型以"与冻结规范的语义一致性"为主轴 → C+/D+。Meta 裁决:**文件存在 ≠ 语义正确**,综合评级 C。 ### 16.2 4 轮递进审查(系统详细设计) | 轮次 | 模型 | 重点 | 评分 | | --- | ------------ | ------------- | --------------- | | 1 | DeepSeek | 基线覆盖性全量核对 | 9.6/10 | | 2 | MIMO 2.5 Pro | 内在一致性 + 架构合理性 | 9.4/10 | | 3 | GPT-5.5 Pro | 基线间冲突检测 | Requires repair | | 4 | Opus 4.8 | 前轮验证 + 根因分析 | 9.1/10 | ### 16.3 三视角审查(概要设计) | 视角 | 模型 | 独有发现 | | --- | --------------- | ------------------------------ | | 架构师 | MIMO 2.5 Pro | 模块边界、依赖方向 | | 开发者 | DeepSeek V4 Pro | 接口完整性、测试覆盖 | | 用户 | Opus 4.7 | 原始 UX 需求未进入 plan/todo(其他视角不可见) | --- ## 十七、配套工程实践 | 实践 | 方案 | 解决的问题 | | ------------------- | --------------------- | ------------------ | | **air_runtime 共享库** | 36 模块 ~6,000 行 | 12 模式核心逻辑去重 | | **统一插件安装器** | 动态路径解析 + 安装后自动验证 | 安装后插件不可用 | | **sub2api 多账号整合** | 代理层整合多个 Codex Plus 账号 | 5x PLUS 无中断长任务执行 | | **New API 多模型路由** | one-api 分支的统一 API 代理 | 多模型交叉审计的异构 API 聚合 | | **CC-Switch 本地代理** | 本地供应商管理与故障转移 | 供应商可用性保障 | | **ScheduleWakeup** | 系统级定时唤醒替代 Agent 自觉轮询 | Agent 遗忘轮询导致无限等待 | | **Hook 自动化** | Agent Hook 机制 | 项目打开前自动 git pull 等 | --- ## 十八、V1→V2 演进:从真实损失到系统性修复 ### 18.1 P0 缺陷修复清单(已造成实际损失) | V1 缺陷 | 实际影响 | V2 修复方案 | 保障层级 | | --------------------- | ------------------------------ | ----------------------------------------- | -------- | | AirXDB 假阳性阻塞 | 11+ 任务触发虚假修复循环 | EvidenceGatePolicy 任务类型感知 | L1 代码 | | 部署验证缺口 | 4 个 "done" 任务未实际部署 | deployRequired + deploy 验证强制 | L1 契约 | | 非原子写入 | state.json 截断致 JSONDecodeError | atomic_json_write (tempfile + os.replace) | L1 基础设施 | | 零并发控制 | todo.md 读-改-写竞态 | FileLock (fcntl.flock) | L1 基础设施 | | AirArc 被 plan mode 劫持 | 架构器偏离规划职责 | allowed-tools 只读 + deny-plan-mode | L1 工具 | | AirEng 停下来问不自主决策 | 调度流程反复中断 | SKILL.md 中文锁定 + 自主决策指令 | L1 指令 | | AirEng 无状态轮询 | 子线程卡死后无限等待 | ScheduleWakeup + 硬编码监控循环 | L1 指令+代码 | | AirDo 不调用 AirDbg | 直接报 blocked 或 false-done | finish_worker 强制路由链 | L1 代码 | | 安装器路径错误 | 安装后插件无法识别 | 动态路径解析 + post_install_verify | L1 代码 | | AirEng 偏离调度写代码 | 破坏隔离架构 | 极端接管条件 + 工具权限分层 | L1 指令+代码 | ### 18.2 P1 缺陷修复清单(限制可靠性) | V1 缺陷 | V2 修复方案 | | ----------------------- | ------------------------------------------ | | 硬编码开发者路径 | 路径约定模块 paths.py | | `_json_dump` 5 份重复 | `air_runtime/io.py` 统一 | | `_ordered_unique` 4 份重复 | `air_runtime/utils.py` 统一 | | todo.md 列索引硬编码 | 动态列定位(已知状态词搜索) | | 并发度上限硬编码为 3 | `state.concurrency` 可配置 | | 子进程无超时 | 所有 subprocess.run 加 timeout | | task_id 路径注入 | `sanitize_task_id()` 正则校验 | | 标记注入风险 | `sanitize_marker()` 拒绝注释分隔符 | | 静默吞异常 | 日志告警 + safe_json_load .bak 恢复 | | Arc 重规划后 Eng 无法衔接 | TaskGraph + PlanDelta 增量吸收 | | 同文件无冲突任务被迫串行 | RegionConflictDetector + WorktreeIsolation | | AirArc 跳过需求探讨 | ArcPhaseGate 三阶段门控 | | AirDbg 未取证就改代码 | EvidenceFirstGate 先读后写门控 | | 项目缺乏标准化日志 | AirArc 强制 spdlog + AirRvr 检查 | | 边界无测试 + 终审缺高风险检查 | _inject_boundary_tests + HighRiskAudit | | UI 任务无专业 Skill | frontend-design Skill 自动安装 + 强制路由 | | ADR 变更无级联失效 | ADRWatcher + invalidate_by_adr + 10 步闭环 | | Dispatch → Worker 断链 | spawn_workers + 指令操作化伪代码 | | Dispatch 指令歧义 | 可执行步骤替代意图描述 | | Merge 后 TaskGraph 不同步 | Phase 6.5 自动同步节点 status | ### 18.3 V2 度量目标 | 指标 | V1 基线 | V2 目标 | | -------------------- | ---------------- | -------------------------- | | AirXDB 假阳性率 | ~60%(11/18 任务) | < 5% | | 状态文件损坏率 | 已知发生 | 0%(原子写入 + .bak 恢复) | | 部署一致性事故 | 1 次关键事故 | 0 次(deployRequired 强制) | | 空壳修复循环 | 11+ 次 | 0 次(证据门控 + 强制路由) | | 代码重复度 | `_json_dump` 5 份 | 每函数 1 份 | | AirArc plan 模式劫持 | 频繁发生 | 0 次(工具白名单硬阻断) | | AirEng 轮询遗忘 | 频繁发生 | 0 次(ScheduleWakeup) | | AirDo 跳过 AirDbg | 频繁发生 | 0 次(强制路由链) | | AirDbg 未取证就改代码 | 频繁发生 | 0 次(EvidenceFirstGate) | | 需求变更后调度恢复 | 多轮 AI 迭代 | < 1 次(增量 delta 吸收) | | 同文件无冲突任务串行率 | 100% 串行 | < 20%(worktree 并行) | | ADR 变更后旧代码残留 | 无自动清理 | 0 次(级联失效 + git revert) | | Dispatch → Worker 断链 | Agent 回退自己写代码 | 0 次(spawn_workers + 操作化指令) | | Merge 后重复派发 | 已完成任务再次 dispatch | 0 次(Phase 6.5 同步) | --- ## 十九、演变史:从 Prompt 插件到代码级 Agent Air 插件套件的架构不是一次设计出来的——它经历了 9 个阶段、多次生产事故驱动的迭代,才从 3 个纯 Markdown 指令插件演化为具备代码级保障的统一调度平台。这条演变路径本身就是 AI Agent 工程化的一个缩影:**每一次架构跃迁都源于一次真实的失败**。 ### 19.1 时间线总览 ``` 2026 Q1 初 01 三个 Codex CLI 工作流插件(AirArc + AirDo + AirDbg) │ 纯 Markdown 指令,无代码执行,人工串联 ▼ 2026 Q1 中 02 AirDbg 不好用 → 增加 AirXDB(GUI 截图)+ AirNDB(网络抓包) │ "证据"概念萌芽,但仍靠 SKILL.md 建议 ▼ 2026 Q1 末 03 增加 AirSDB(静态分析)→ 6 插件 + 统一安装器 = 第一代插件包 │ 证据三件套(截图/抓包/静态分析)齐全 ▼ 2026 Q1-Q2 04 优化插件包 → 第一代手动插件包的生产版本 │ 打磨 SKILL.md 指令、修复安装器、完善模板 ▼ 2026 Q2 初 05 上下文爆炸 → AirContext(Hook + 外部 LLM 压缩 + JSONL DAG) │ 上下文管理从"不管"变成"必须管" ▼ 2026 Q2 中 06 插件多了、文件多了、太慢 → AirPlan-Para(air_runtime 共享库 + 表格调度) │ 架构跃迁:从"独立插件集合"到"有共享引擎的调度系统" ▼ 2026 Q2 末 07 多个版本迭代 → AirPlan-ParaV2(稳定并发版本) │ 修复并发 bug、稳定 air_runtime ~4,500 行 ▼ 2026 Q3 初 08 中途需求变更 + LLM 不按预期执行 → AirPlan V2(统一插件 + 12 模式) │ 三个周末重写:8 插件合 1、DAG 动态调度、L1 代码级保障 ▼ 2026 Q3 中 09 碰撞到 Plugin 边界 → AirCoding(独立 Agent,Fork OpenCode)【Alpha 已完成并开源】 从"插件"到"宿主内嵌调度层":在 OpenCode 内注册 Agent、coordinator 工具与 plugin hook,把工具白名单、状态机与审查门控落到代码;独立运行时仍是下一阶段目标 ``` ### 19.2 阶段 01:三个工作流插件(起源) **组件**:AirArc(架构规划)、AirDo(任务执行)、AirDbg(调试) **架构**:三个独立的 Codex CLI 插件,每个由 SKILL.md(自然语言指令)+ 命令文件(.md 入口)+ Python 引导脚本 + plugin.json 清单组成。 **核心设计决策**(贯穿至今): - **AirPlan/ 目录约定**:plan.md、todo.md、docs/、state/ 的目录结构在此阶段就已确立 - **AGENTS.md + ADR + C4 三件套**:项目认知通过结构化文档外化,不依赖特定会话 - **7 步调试工作流**:confirm → load → reproduce → locate → fix → verify → close 的流程在第一天就存在 **控制方式**:100% Markdown 指令。SKILL.md 告诉 AI "你应该这样做",AI 是否遵守完全取决于模型的自觉性。 **驱动下一阶段的问题**: - AirDbg 的调试质量差——没有证据支撑就猜测修复,引入更多 bug - 没有跨插件协调——AirArc 规划完需要人工切换到 AirDo,AirDo 完成后需要人工切换到 AirDbg - GUI 问题无法验证——嵌入式设备上跑的应用,"进程存在"不等于"界面渲染正确" - 上下文全在一起运行十分钟直接1M爆满 ### 19.3 阶段 02:增加图形和网络取证 **新增**:AirXDB(GUI 截图取证)、AirNDB(网络抓包取证) **关键概念萌芽**:**证据**——不同类型的问题需要不同类型的直接证据。 AirXDB 基于 Midscene.js,支持 Playwright(Web 应用)、Chrome Bridge(Chrome 扩展)、Desktop(桌面应用)、MCP(协议桥接)四种模式。支持远程设备截图(SSH → 远程执行 → base64 传输 → 本地解码)。 AirNDB 基于 tcpdump/WinDump,支持 BPF 过滤器、定时捕获、远程 SSH 抓包。 **学到的教训**: > "证据"这个概念看似简单,但它是整个 Air 体系的基石。没有证据约束的 AI 调试器,和一个随机修改代码的脚本没有区别。AirDbg 在没有截图的情况下"修复"了 GUI 问题,结果引入 3 个新 bug——因为它修复的是自己猜测的原因,而不是实际的问题。 **驱动下一阶段的问题**: - C/C++ 代码质量问题——仅靠调试和截图无法覆盖内存泄漏、空指针等静态缺陷 ### 19.4 阶段 03:静态分析 + 第一代插件包 **新增**:AirSDB(Cppcheck 静态分析)+ 统一安装器 + manifest.json AirSDB 的亮点是**跨平台自动安装**——自动检测系统包管理器(winget/choco/scoop/apt/dnf/yum/apk/pacman/brew),下载安装 cppcheck,支持本地和远程 SSH 扫描,产出 XML 报告解析为 JSON。 **统一安装器**(`install_air_suite.py`)将 6 个插件打包部署: - 复制插件到用户目录 - 同步 skills 到 `.agents/skills/` - 更新 marketplace.json - 支持 `--verify-only`、`--dry-run`、`--plugins` 过滤 **证据三件套成型**: | 证据类型 | 插件 | 适用场景 | | ------ | ------ | ------------------ | | GUI 截图 | AirXDB | 界面渲染、布局、交互验证 | | 网络抓包 | AirNDB | RTSP/HTTP/TCP 协议调试 | | 静态分析 | AirSDB | C/C++ 内存安全、代码质量 | **驱动下一阶段的问题**: - 6 个插件的 SKILL.md 指令打磨不均匀,有些插件的执行质量明显低于其他 - 安装器在不同系统上路径解析不一致 - 人工串联插件的效率瓶颈——一个完整的开发流程需要在 AirArc → AirDo → AirDbg → AirXDB 之间反复切换 ### 19.5 阶段 04:第一代手动插件包(生产版本) 这是阶段 03 的打磨版——相同的 6 插件架构,但每个插件的 SKILL.md 指令经过多轮优化,安装器路径问题修复,文档模板标准化。 **关键改进**: - AirArc 增加了工作分类(分析/设计/重构/执行),产出 requirements.md → solution-architecture.md → C4 → ADR → plan.md → todo.md 的完整链路 - AirDo 增加了 plan.md 和 todo.md 的读取,按顺序执行任务 - AirDbg 增加了与 AirXDB/AirNDB/AirSDB 的协作指令 **学到的教训**: > Markdown 指令优化存在天花板。无论 SKILL.md 写得多详细、多精确,AI 仍然会偶尔偏离——跳过步骤、忘记调用协作插件、在不该修改代码时修改代码。这不是模型质量问题,而是**控制方式的根本局限**:自然语言指令是建议性的,不是强制性的。 **驱动下一阶段的问题**: - 长会话中上下文窗口爆炸——对话到后期,AI 对早期架构决策的记忆出现幻觉 ### 19.6 阶段 05:上下文爆炸 → AirContext **问题**:AI Agent 执行复杂开发任务时,对话历史快速膨胀。一轮完整的开发流程(读代码 → 搜索 → 修改 → 测试 → 调试)就可以产生 50K-100K token 的上下文。当接近模型的上下文窗口上限时,AI 框架的内置自动压缩(auto-compact)会粗暴截断,丢失关键的架构决策和未完成工作项。 **解决方案**:AirContextServer——一个独立的上下文管理插件,替代框架的内置压缩。 **架构**: ``` ┌────────────────────────────────────────────────┐ │ Wrapper (bin/aircontext) │ │ 包装 claude CLI,劫持启动和恢复流程 │ ├────────────────────────────────────────────────┤ │ 4 个 Hook: │ │ SessionStart → 验证配置 │ │ UserPromptSubmit → 配置无效时阻止 prompt │ │ PostToolUse → 估算 token,超阈值触发压缩 │ │ PreCompact → 阻止框架内置自动压缩 │ ├────────────────────────────────────────────────┤ │ Compactor 后台进程: │ │ 1. 获取 compactor.lock(O_CREAT | O_EXCL) │ │ 2. 从 JSONL 文件加载消息链(DAG 遍历) │ │ 3. 切分:head(送入压缩)| tail(逐字保留 10 条) │ │ 4. 序列化 head → 纯文本(丢弃 thinking blocks) │ │ 5. 调用外部 LLM + rules.md 规则 → 压缩摘要 │ │ 6. 写入 JSONL:summary (parentUuid=null) + │ │ continuation prompt → 形成新链根 │ │ 7. SIGTERM → claude --resume → 加载压缩上下文 │ └────────────────────────────────────────────────┘ ``` **关键设计创新**: - **`parentUuid=null` 技巧**:摘要消息的 parentUuid 设为 null,在 JSONL DAG 中创建一个新的"孤岛"根节点。后续消息从摘要开始形成新链,旧消息变为不可达的死链。`claude --resume` 加载时只遍历到新链,获得一个"干净"的起点 - **外部 LLM 压缩**:不使用会话自身的模型做压缩——避免"自己压缩自己"的认知偏差。压缩模型只看序列化的文本,不了解对话历史,产出更客观的摘要 - **三级信息保留策略**:永久保留(最后 10 条)→ 高优先级(文件路径、ADR、TODO)→ 低优先级(搜索结果、完成确认) **学到的教训**: > 上下文管理不是"锦上添花"——它是 AI Agent 长时间运行的**生存前提**。没有上下文压缩,一个 200K token 窗口的模型在 3-4 小时的开发任务中就会耗尽空间。而框架内置的压缩策略太粗暴,无法区分"架构决策"和"一次性搜索结果"的价值差异。 **驱动下一阶段的问题**: - 6 个插件串行执行太慢——一个包含 20 个任务的项目,每个任务 15 分钟,串行需要 5 小时 - 插件之间的协调全靠人工——AirArc 规划完后需要人工启动 Airdo,Airdo后需要人工启动 Airdbg ### 19.7 阶段 06:AirPlan-Para(架构跃迁——共享引擎) **这是整个演变史中最关键的架构跃迁**——从"独立插件集合"到"有共享引擎的调度系统"。 **新增核心组件**:`lib/air_runtime/`(~3,700 行共享 Python 运行时库) ``` air_runtime/ contracts.py (~618 行) 结构化数据契约 engine.py (~500 行) 调度引擎 worker.py (~373 行) Worker 生命周期 review.py (~239 行) DAG 并行审查 todo_parser.py (~161 行) Markdown 表格解析 doc_sync.py (~351 行) 文档同步 debug_runtime.py (~414 行) 自动调试 airxdb_runtime.py (~818 行) 自动 XDB repair_runtime.py (~374 行) 自动修复 paths.py 路径约定 ``` **三个划时代的设计决策**: **① 结构化数据契约替代 Markdown 通信** V1 之前,插件之间通过 Markdown 文件传递信息——AirArc 产出 todo.md,AirDo 读取 todo.md。但 todo.md 是给人看的,不是给机器解析的。`contracts.py` 引入了 `TaskSpec`、`WorkerResult`、`ValidationRecord`、`DocumentUpdate` 等类型化数据结构: ```python class WorkerResult: task_id: str status: str # done | blocked | failed files_changed: list[str] validations: list[ValidationRecord] document_updates: list[DocumentUpdate] ``` 这意味着:引擎可以**程序化地验证** Worker 的产出,而不是靠 AI 阅读 Markdown 来判断。 **② DAG 依赖感知的并行调度** `review.py` 的 `build_parallel_review()` 实现了第一版并行调度算法: ``` 1. 解析 todo.md → TaskRecord 列表 2. 构建依赖边([deps: T-xxx] 标注) 3. 拓扑排序 → 波次分组 4. 贪心并行分组:每个任务放入第一个无写集冲突的组 5. 冲突检测:写集重叠的任务强制串行 ``` **③ 隔离 Worker 子代理** `engine.py` 的 `dispatch_worker_group()` 为每个任务创建独立的 AirDo 子代理,传递 `fork_context=false`——子代理不继承调度器的对话历史,只获得 brief.md 和 handoff.md。这是**上下文隔离**原则的第一次代码实现。 **学到的教训**: > 并行执行的正确性取决于**冲突检测的完备性**。第一版上线后,两个任务同时修改同一个 CMakeLists.txt,后完成的覆盖了先完成的——产出需要人工修复 3 个文件,效率反而低于串行。这证明了"朴素并行"在有写集冲突时是反效率的。 **驱动下一阶段的问题**: - 并发不稳定——偶尔出现状态文件损坏(非原子写入) - AirXDB 假阳性率 ~60%——非 GUI 任务也被要求提供截图 - 引擎的 5 分钟轮询依赖 AI "自觉执行",经常遗忘 ### 19.8 阶段 07:AirPlan-ParaV2(稳定并发版本) 经过多个版本的迭代修复,air_runtime 稳定在 ~4,500 行。这一阶段主要修复了: - **并发竞态**:引入基础的锁机制,防止两个 Worker 同时完成时的 todo.md 读-改-写冲突 - **AirXDB 误触发**:增加了基础的关键词过滤(但仍不够精确,假阳性率仍高) - **修复预算**:`maxAttemptsPerTask = 2`,防止无限修复循环 - **引擎状态持久化**:state.json 包含完整的运行时状态,崩溃后可恢复 **学到的教训**: > 并发系统的可靠性不是一步到位的——它需要在真实负载下反复暴露问题、反复修复。AirPlan-Para 经历了 3 个小版本才达到"稳定可用"状态。每次版本迭代都伴随着一次 state.json 损坏或 todo.md 竞态的事故报告。 **驱动下一阶段的问题**(V2 设计文档中的 P0/P1 缺陷清单): - 非原子写入导致 state.json 截断 → JSONDecodeError - AirArc 被 Agent 框架的 plan mode 劫持 - AirEng 停下来问用户而不是自主决策 - AirDo 跳过 AirDbg 直接返回 blocked - AirDbg 不取证就改代码 - 中途需求变更后调度需多轮 AI 迭代恢复 - 同文件无冲突任务被迫串行 ### 19.9 阶段 08:AirPlan V2 这是**从"建议性约束"到"代码级保障"的范式跃迁**。花费三个周末,将 8 个分散插件重构整合为 1 个统一插件 12 种模式,重写了整个调度引擎。 **核心动机**:V1(阶段 06-07)证明了**制品驱动 + 上下文隔离 + 波次并行**的架构方向成立,但所有关键约束都停留在 SKILL.md 的自然语言层面——AI 可以选择遵守,也可以选择忽略。真实项目数据(DecodePlayer 系列、AirCoding V1.0.0 Alpha)证明这种"建议性约束"不够。 **V2 的哲学转变**: ``` V1: "你应该在修改代码前进行取证" → AI 可以跳过 V2: can_modify_code() == False → 代码层面不允许 V1: "AirArc 不应该写代码" → AI 可以被 plan mode 劫持 V2: allowed-tools: [Read, Glob, Grep] → Agent 框架层面没有写工具 V1: "AirDo 应该调用 AirDbg" → AI 可以直接返回 blocked V2: finish_worker() 返回 routing → 代码层面必须经过 AirDbg V1: "调度器应该每 5 分钟轮询" → AI 可以忘记 V2: ScheduleWakeup(delaySeconds: 300) → 系统级定时唤醒 ``` **8 合 1 的工程价值**: | V1(8 个独立插件) | V2(1 个统一插件 12 模式) | | -------------------- | ------------------------- | | 每个插件独立安装、注册、版本 | 一次安装,12 个模式全部可用 | | 插件间通信靠文件 + 人工切换 | 统一的 air_runtime 库 + 自动路由链 | | 每个插件维护自己的 _json_dump | 统一的 atomic_json_write | | SKILL.md 约束不跨插件 | L1 代码级保障覆盖全链路 | | 静态 todo.md 表格调度 | 动态 TaskGraph DAG 调度 | **新增的 4 个模式**: | 模式 | 填补的空白 | | ------------ | ---------------------- | | /dep(AirDep) | V1 无部署 → "完成但未部署"事故 | | /tst(AirTst) | V1 无统一测试 → 边界无测试覆盖 | | /sec(AirSec) | V1 无安全扫描 → 制品敏感数据泄露风险 | | /rvr(AirRvr) | V1 无需求审查 → 交付物偏离需求无人检出 | ### 19.10 阶段 09:AirCoding——碰撞到 Plugin 边界并完成 Alpha **核心发现**:当 Air 插件套件在 Claude Code CLI 上运行时,无论 V2 的 L1 代码级保障做得多好,有一个层面始终无法控制——**Agent 框架本身的行为**。 具体表现: - Agent 框架的 plan mode 可以覆盖 SKILL.md 的角色指令(AirArc 被劫持) - Agent 框架的 auto-compact hook成 AirContext 并不稳定 - Agent 框架的 allowed-tools 是 per-command 而非 per-context 的,无法在一个 Agent 内动态切换工具权限 - Agent 框架不保证"自觉执行"的循环(轮询遗忘) **结论**:**插件范式有天花板**。你可以在插件层做代码级保障,但你无法控制宿主 Agent 框架的行为。当宿主框架的行为与你的工程约束冲突时,你只能二选一:要么忍受宿主框架的限制,要么拥有自己的运行时。 **当前状态**:AirCoding 现在已经不是"只剩路线图"的原型了。Alpha 版本已经完成首个公开可用闭环并开源,但它的实现形态也需要准确描述:它并不是"完整自研运行时已成型",而是**基于 OpenCode v1.17.4 fork 的最小改造**,通过 Agent 注册、Tool Registry、coordinator 工具、Plugin Hook 和权限矩阵,把 V2 里验证过的关键约束直接植入宿主运行时。 **Alpha 已经落地的能力**: - Main / Scheduler / Worker / Architect / Reviewer 五类 Agent 已进入运行时注册表,不再只是文档角色 - 子 Agent 的工具边界已由代码级权限矩阵硬控,例如 Scheduler 无 Write/Edit/Bash,Architect 只能写 `.air/shared/plan/**` - `coordinator_tick` 已承担最小确定性调度闭环:读取 `task-graph.json`、做 DAG ready 计算、处理状态迁移、执行 retry / milestone budget,并把状态实时写入 `scheduler-state.json` - Worker 的 `cppcheck` 强制、降级关键词扫描,Reviewer 的 Code-to-Design 对照表检查、表面证据 PASS 拦截,已经进入 hook / tool 层,而非只靠 Prompt 自觉 - `.air/shared/plan/*` 与 `.air/local/*` 的目录分层已成型,架构认知、执行状态和调试记录开始有了稳定的文件落点 **当前仍未完成的部分**: - 目前主要复用 OpenCode 的 Session / BackgroundJob / Plugin Hook / Tool Registry,而不是完整自研的 EventBus + NDJSON IPC runtime - 更理想的语言无关运行时、持久事件总线、学习记忆层、动态权限切换等能力,仍处于后续演进目标 - 宿主框架的约束仍然存在,因此这版 Alpha 更准确的定义是:**把关键工程约束嵌进宿主框架的一次成功验证**,而不是独立运行时的终点 **这个阶段的意义已经从"勾勒边界"前进到"验证路线"**:它不再只是告诉我们插件范式的边界在哪里,而是进一步证明了一个更重要的判断——**要想让关键约束可靠生效,必须把它们推进到宿主运行时层,而不能永远停留在插件层的自然语言约定里。** ### 19.11 演变史的核心规律 回顾 9 个阶段,可以提炼出三条贯穿始终的演变规律: **规律一:控制方式的硬化** ``` 阶段 01-05: 自然语言指令(SKILL.md) → "请遵守这个规则" 阶段 06-07: 运行时检查(Python 函数返回值) → "不遵守就报错" 阶段 08: 代码级门控(工具白名单 + 数据契约) → "不遵守就阻断" 阶段 09: 架构级不可能(运行时所有权) → "不可能违反"(方向已定,仍在原型阶段) ``` 每次硬化都由一次真实失败驱动:AirDbg 不取证就改代码 → EvidenceFirstGate;AirArc 被 plan mode 劫持 → deny-plan-mode;AirEng 忘记轮询 → ScheduleWakeup;Agent 框架覆盖插件行为 → Fork 拥有自己的运行时。 **规律二:问题驱动而非设计驱动** 没有任何一个架构决策是"提前设计好的"——它们都是**问题暴露后的被迫应对**: | 暴露的问题 | 驱动的架构决策 | | ----------------- | ---------------------------------- | | AirDbg 盲改代码引入 bug | 证据先于修复原则(阶段 02) | | 长会话上下文爆炸 | AirContext 透明压缩(阶段 05) | | 串行执行太慢 | DAG 并行调度(阶段 06) | | 朴素并行写集覆盖 | 写集冲突检测 + 波次分组(阶段 06) | | 非原子写入导致状态损坏 | atomic_json_write + .bak 恢复(阶段 08) | | 两个 Worker 同时完成竞态 | FileLock (fcntl.flock)(阶段 08) | | 需求变更后调度无法恢复 | TaskGraph DAG + PlanDelta(阶段 08) | | ADR 变更后旧代码残留 | ADR 级联失效 + git revert(阶段 08) | | Agent 框架覆盖插件行为 | Fork OpenCode + 宿主内嵌调度层(阶段 09,Alpha 已完成并开源) | **规律三:可检查性的坚持** 从阶段 01 到阶段 09,无论架构如何变化,有一条线始终未断:**所有中间状态都是人类可读文件**。 - 阶段 01-07:AirPlan/ 目录树(Markdown + JSON) - 阶段 08:events.jsonl 补充了完整时间线 - 阶段 09:继续坚持纯文件状态(`plan.md` / `task-graph.json` / `scheduler-state.json`),同时把调度逻辑和门控逻辑推进到宿主运行时;独立 EventBus / 持久事件流仍是后续目标 这意味着:即使在最复杂的并行调度场景中,开发者随时可以 `cat task-graph.json`、`cat scheduler-state.json`,或在需要时 `tail events.jsonl` 了解系统的精确状态。没有二进制数据库、没有私有格式、没有需要特殊工具才能解读的状态。 **可检查性是信任的前提**——如果你无法观察一个系统的内部状态,你就无法信任它的决策。对于 AI Agent 这样的非确定性系统,这一原则的价值比任何算法优化都大。 --- ## 二十、原理篇实现细节补充 本章集中承载第一部分(原理篇)各章交叉引用过来的实现细节。每一条都可追溯到原理篇的具体小节,避免原理与实践混杂。 ### 20.1 架构状态同步的合并流水线(对应 6.4) 每次任务合并时,`merge_pipeline.py` 按 6 个阶段顺序执行——任一阶段失败则整个合并回滚: 1. **Phase 1 — enforce_doc_sync_requirements**:验证 Worker 是否提交了所要求的架构文档更新;deploy_required 的任务必须有远程部署验证;路径必须落在项目根目录内 2. **Phase 2 — apply_document_updates**:将 Worker 提交的 `DocumentUpdate` 应用到 ADR、C4、AGENTS.md 等项目文档 3. **Phase 3 — sync_engine_managed_docs**:引擎自动写入同步标记块(AIR-ENGINE:AGENTS-SYNC / C4-SYNC / TODO-RUN-LOG),追加前检查去重 4. **Phase 4 — update_todo_after_merge**:更新任务表中的状态和验证摘要,支持动态列定位(按已知状态词搜索列头) 5. **Phase 5 — atomic persist**:使用 `atomic_json_write()`(tempfile + os.replace())原子写入 state.json,失败时自动从 .bak 恢复 6. **Phase 6 — FileLock release**:释放 `FileLock`(fcntl.flock) **Phase 6.5 — TaskGraph sync**:若启用了动态 DAG,合并后还需把 Worker 的 filesChanged、验证摘要、documentUpdates 反映回 TaskGraph,更新对应 TaskNode 的状态。 **标记块命名空间**(两层隔离避免模式间互相覆盖): - **模式层**(各模式独立维护):`<!-- AIRARC:BEGIN/END -->`、`<!-- AIRENG:BEGIN/END -->`、`<!-- AIRDO:BEGIN/END -->`、`<!-- AIRDBG:BEGIN/END -->`、`<!-- AIRXDB:BEGIN/END -->`、`<!-- AIRNDB:BEGIN/END -->`、`<!-- AIRSDB:BEGIN/END -->` - **引擎层**(merge_pipeline.py 自动写入):`<!-- AIR-ENGINE:AGENTS-SYNC:BEGIN/END -->`、`<!-- AIR-ENGINE:C4-SYNC:BEGIN/END -->`、`<!-- AIR-ENGINE:TODO-RUN-LOG:BEGIN/END -->` ### 20.2 ADR 变更级联失效的 10 步闭环(对应 6.5) V2 的 `handle_adr_invalidation()` 实现完整的 10 步闭环: ``` 1. ADRWatcher 每轮轮询时 SHA256 对比所有 ADR 文件 hash 2. 检测到 superseded / modified 变更 → 触发级联失效 3. TaskGraph.invalidate_by_adr() 冻结调度(dispatch_frozen = true) 4. 标记所有引用该 ADR 的已完成任务为 INVALIDATED 5. 标记进行中任务为 INVALIDATED,中止对应 Worker 6. BFS 遍历下游依赖 → 级联失效所有受影响的后继任务 7. 创建 git tag 回滚快照 8. git revert 已合并的旧代码(按 task_id 查找对应 commit) 9. PartialReplanner 生成局部重规划请求(仅重新规划受影响部分) 10. AirArc 基于新 ADR 重新生成任务 → apply_delta() → 解冻调度 ``` **关键数据结构**: - **TaskNode.adr_refs**:每个任务节点记录它引用的 ADR ID 列表,建立**架构决策 → 具体任务**的溯源链 - **PartialReplanner**:提取未受影响 DONE 任务的公共接口约束,确保重规划不破坏稳定依赖 - **dispatch_frozen**:级联失效期间 `ready_tasks()` 返回空列表,阻止任何新任务派发 - **git tag 回滚点**:精确定位需要回退的 commit,避免全量回滚 ### 20.3 TaskGraph 数据结构与 PlanDelta(对应 8.3) ```python class TaskGraph: nodes: dict[str, TaskNode] # 每个任务是一个节点 edges: list[Edge] # 依赖/冲突/同步边 dispatch_frozen: bool # ADR 级联失效时冻结 class TaskNode: id: str status: str # TODO | DISPATCHED | DONE | BLOCKED | INVALIDATED task: str # 任务描述 write_set: list # 声明的写集(用于 RegionConflictDetector 冲突检测) adr_refs: list # 引用的 ADR(溯源链,供 invalidate_by_adr 使用) test_required: bool # 边界测试标记(AirArc 在 _inject_boundary_tests 时设置) ``` **PlanDelta 结构**: ```python class PlanDelta: added: list[TaskNode] # 新增任务 removed: list[str] # 移除的任务 ID modified: list[TaskNode] # 修改的任务 edge_changes: list[Edge] # 新增/移除的依赖边 ``` **四项核心能力的实现**: - **apply_delta()**:增量更新图结构,已调度(DISPATCHED/DONE)任务不受影响 - **apply_full_replace()**:保留已完成任务的 DONE 状态,避免重新调度 - **diff()**:对比新旧两个 DAG,自动产出精确的 PlanDelta - **ready_tasks()**:返回入度为 0 且状态为 TODO 的节点;调度冻结时返回空列表 ### 20.4 五种 L1 机制的具体代码实现(对应 10.2) **① 工具白名单**:命令文件 frontmatter 声明 `allowed-tools: [Read, Glob, Grep]`,AirArc 配合 `deny-plan-mode: true` 在 Agent 框架层面阻断写操作和 plan mode。 **② Python 门控函数**: - `ArcPhaseGate`:AirArc 写入前必须处于 `confirmed` 阶段(discussing → proposing → confirmed),否则拒绝 - `EvidenceFirstGate`:AirDbg 未取证前 `can_modify_code()` 返回 False - `EvidenceGatePolicy`:根据任务类型(GUI / NETWORK / STATIC_ANALYSIS / CODE_ONLY)分类,替代 V1 的无差别触发 **③ 数据结构约束**: - `WorkerResult.validate_for_finalize()`:deployRequired 必须有 deploy 验证;done 必须有 validations 或 filesChanged - `sanitize_task_id()`:正则校验防止路径注入 - `sanitize_marker()`:拒绝 HTML 注释分隔符,防止标记注入 **④ 强制路由链**:`finish_worker()` 按 6 级优先级路由——blocked/failed → AirDbg、无取证 → AirDbg、GUI 任务 → AirXDB、网络任务 → AirNDB、C/C++ 任务 → AirSDB、所有 done → AirRvr。路由是代码级强制,不可跳过。 **⑤ 原子操作 + 并发控制**: - `atomic_json_write()`:写入前创建 .bak 备份,使用 tempfile + os.replace() 原子替换 - `safe_json_load()`:JSONDecodeError 时自动从 .bak 恢复 - `FileLock`:`fcntl.flock(LOCK_EX | LOCK_NB)` 带 timeout 重试 ### 20.5 指令操作化的具体示例(对应 10.3) **AirEng 派发 Worker 的操作化步骤**(从"读取派发清单 spawn 子代理"这一意图描述升级而来): ```markdown dispatch 返回 {waveId, taskIds, dispatchPath}。然后按以下步骤操作,不可跳过: 1. 从 dispatch 返回值中取 taskIds 列表 2. 对 taskIds 中的每个 tid,在同一条消息中并发调用 Agent 工具: Agent( description: "Do Worker: {tid}", subagent_type: "general-purpose", run_in_background: true, prompt: "你是 AirDo Worker..." ) 3. 所有 Worker spawn 完成后,进入 monitor 状态 ``` **AirDo 路由链的操作化**(对应 20.4 ④ 强制路由链): ```python def finish_worker(task_id, result): if result.status in ("blocked", "failed"): return route_to("airdbg", task_id) if not result.evidence and needs_evidence(result): return route_to("airdbg", task_id) if is_gui_task(result): return route_to("airxdb", task_id) if is_network_task(result): return route_to("airndb", task_id) if is_cpp_task(result): return route_to("airsdb", task_id) return route_to("airrvr", task_id) ``` 每一步都是确定的操作,消除了 Agent 的推理负担——不再需要猜测工具名、参数格式或数据来源。 --- ## 二十一、总结 Air 插件套件 V2 的十五个工程原则: 1. **制品驱动通信** — 插件间通过结构化文件通信,实现可检查、可恢复、可审计的松耦合 2. **三层上下文边界** — 会话级压缩 + 任务级隔离 + 项目级制品,三个尺度管理上下文质量 3. **隔离驱动的并行效率** — 上下文隔离是并行调度的前提;没有隔离,并行度越高,腐烂越快 4. **证据先于修复** — 截图、抓包、静态分析作为修复前置条件,消除虚假验证 5. **闭环自动修复** — 执行→失败→调试→修复→重执行的自动循环,预算耗尽才升级人工 6. **透明上下文压缩** — 三级降级 + 质量校验,~10 倍压缩比,保留关键决策 7. **多模型交叉审计** — 并行/递进/多视角审查 + 交叉确认矩阵,将单模型盲区转化为可量化置信度 8. **架构状态持久化** — C4 + ADR + 标记块 + 6 阶段合并流水线,架构文档不可能落后于代码 9. **范围约束降本** — 规划-执行分离 + 6 文件必读 + 预填充模板 + 弱模型安全,廉价模型在约束上下文中达到昂贵模型效果 10. **长期迭代管理** — 文件状态 + 波次递进 + 修复预算 + 文档级联 + 回归防护,跨会话/跨模型/跨设备的工程连续性 11. **L1 代码级保障**(V2) — 关键约束从自然语言建议升级为 Python 门控 + 工具白名单 + 数据契约的硬性执行 12. **动态图调度**(V2) — TaskGraph DAG 替代静态表格,增量重规划 + ADR 级联失效 + worktree 隔离并行 13. **全专家插件路由**(V2) — finish 时 6 级强制路由链(Dbg→XDB→NDB→SDB→Rvr),路由不是建议而是代码级强制 14. **指令操作化**(V2) — 关键操作路径从意图描述升级为可执行伪代码,消除 Agent 推理歧义 15. **需求一致性审查**(V2) — AirRvr 独立审查交付物与需求的一致性,含高风险审计 + Code-to-Design 逐行对照 **将 AI Agent 从不可控的对话式工具,转变为可审计、可续接、可验证、可交叉检验的工程化执行平台。V2 在 V1 的基础上,将"建议性约束"系统性升级为"代码级保障",针对真实项目中暴露的 P0/P1 缺陷逐项给出工程化对策。而阶段 09 的 AirCoding,则把这条路线继续推进到了宿主运行时内部:它已经完成首个公开 Alpha 并开源,用 OpenCode fork + Agent 注册 + coordinator 工具 + plugin hook 验证了"关键约束必须宿主内嵌"这一路线;但完全独立的运行时、事件总线和语言无关内核,仍是下一阶段。**
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。
收藏
・
2
点赞
・
1
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
程序原
感谢你分享这么好的资源!
2026-7-8 21:16
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
2
)
学计算机睡觉
雪 币:
779
活跃值:
(1242)
能力值:
( LV3,RANK:30 )
在线值:
发帖
3
回帖
94
粉丝
5
关注
私信
学计算机睡觉
2
楼
看见群友发帖,支持一下!
2026-7-1 10:38
0
air龙典
雪 币:
1086
活跃值:
(505)
能力值:
( LV4,RANK:50 )
在线值:
发帖
8
回帖
12
粉丝
12
关注
私信
air龙典
1
3
楼
学计算机睡觉
看见群友发帖,支持一下![em_079]
哇,谢谢,喵喵喵喵喵
2026-7-1 11:12
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
air龙典
1
8
发帖
12
回帖
50
RANK
关注
私信
他的文章
AI Agent 工程化原理与工作流插件套件实现
1515
[原创]Zed Editor 基于 CMAKE 和 (可选:Ninja 构建系统) 的 C 开发环境搭建
4506
[原创]神(精病)的一站式嵌入式入门教程(未完成,施工中)
19816
更改开机引导LOGO(无需下载BIOS文件)
11008
两小时C语言入门
9238
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部