阅读,与值得关注的内容Readance

告别“散装 AI ”:用 SKILL 编排对存量代码做“微创手术”

作者:vivo IT 技术团队- Liu Heng


目录

01. 典型场景:一个看似简单的存量代码变更

02. 解决方案:从"散装AI"到"编排流水线"

03. 架构设计

04. 实战推演:以"图片压缩"需求跑通流程B

05. 编排设计原则与决策

06. 结语

面对涉及存量代码变更的需求,挑战不在于编码,而在于如何安全、精准地修改。本文通过构建一个由1个编排器和多个单职责Skill组成的AI协作流水线,将影响分析、规则沉淀、埋点和回归检查等隐性工作流程化,确保在实现功能的同时,对存量代码实现最小侵入式改造。



1分钟看图掌握核心要点👇




01

典型场景:

一个看似简单的存量代码变更


某业务上报模块需要新增“图片上传前压缩”功能。需求本身简单,但作为存量修改,真正的复杂性在于:

  • 影响范围不确定:报量中涉及上传图片的场景不止一处,具体要改哪一处?同一个上传组件被多个父组件共用,改了这一处,其他调用方会不会受影响?

  • 逻辑分支复杂:单文件上传和批量上传两条路径,压缩逻辑要插入哪个分支、插到哪一层,会不会有副作用?

  • 降级策略未定义:压缩失败时是折回调用方、静默降级上传原文件,还是提示用户?会不会导致上传功能不可用导致稳定性风险?边界值等于 3MB 或 10MB 时算哪边?

  • 效果难以量化:压缩功能上线后,没有埋点就无法证明它在起作用。压缩阶段耗时和上传阶段省下来的时间对比,是否实现正向收益?需要数据支撑以验证优化效果。


核心矛盾:改存量代码,最怕的不是“不会改”,而是改完不知道哪里会炸。传统的“打开文件直接改”模式,极易遗漏代码之外的隐性工作:影响面没分析、处理规则没定义、埋点没集成、回归用例没覆盖——任何一个环节的遗漏都可能导致线上事故。



02

解决方案:

从"散装AI"到"编排流水线"


为解决上述问题,我们不再依赖零散的AI问答,而是构建了一条可复用的AI辅助开发流水线。其核心思想是:将开发过程中那些"每次都要做、但容易忘"的环节,沉淀为独立的、单职责的AI Skill,并通过一个智能编排器按需串联执行。


这就像为存量代码修改制定了一份标准的"外科手术SOP",让AI作为助手,严格遵循流程,确保每一步都精准、可控。



03

架构设计


整个系统由 1个中央编排器 (dev-workflow) 和 多个独立Skill 构成。编排器负责根据需求类型,智能调度并串联Skill;每个Skill则像流水线上的专用工具,只完成一项特定任务。


3.1 流程编排:两条路径,按需组装


dev-workflow(编排器)│├── 判断需求类型(增量 / 存量)│├── 增量需求 → 流程 A│   ││   ├── Phase 1 — 搭建骨架│   │   ├── scaffold-generator   → 生成模块目录结构│   │   ├── api-definition       → 生成 API 请求函数│   │   └── i18n-integration     → 生成国际化文案│   ││   ├── Phase 2 — 编写业务代码│   │   ├── [编写或生成业务逻辑]│   │   └── monitor-integration  → 埋点集成(如需要)│   ││   └── Phase 3 — 验证提交│       ├── regression-cases     → 回归用例生成│       └── cr-self-check        → CR 自查│└── 存量修改 → 流程 B    │    ├── Phase 1 — 分析评估    │   ├── impact-analysis        → 影响面分析    │   ├── processing-principles  → 处理原则提取    │   └── minimal-invasion       → 最小侵入分析    │    ├── Phase 2 — 编写代码    │   ├── [实施代码修改]    │   ├── monitor-integration    → 埋点集成    │   └── i18n-integration       → 国际化文案    │    └── Phase 3 — 验证提交        ├── regression-cases       → 回归用例生成        └── cr-self-check          → CR 自查


编排器并非机械地运行所有Skill,而是根据需求类型(增量、存量),选择不同的Skill组合与执行顺序,形成两条优化流程:

流程类型

典型场景

Phase 1 核心任务

Phase 2 核心任务

关键区别

流程A

增量变更

新增页面

搭建骨架:

- 生成目录

- API

- 国际化文案


- 编写业务逻辑

- 埋点

跳过分析类Skill

流程B

存量变更

修改通用组件

风险分析:

- 影响面

- 处理原则

- 最小侵入点


- 按方案实施修改

- 埋点与国际化

最大风险是引入Bug

Phase1全力用于风控


以流程B为例,下面的状态机图展示了完整的动态执行流转——包括 Phase 内部的 Skill 串行顺序、两个并行分支,以及每个 Phase 结束后的关门确认点:


3.2 技能矩阵:每个Skill的职责与产出


每个 Skill 好比流水线上的每台"机器"。多个 Skill,每个只做一件事。 它们之间通过"产出物"传递数据——上游 Skill 的输出,就是下游 Skill 的输入。


设计思路:每个 Skill 都是独立的 Markdown 文件,既能被编排器调度,也能单独使用——例如:只想分析影响面?直接调 impact-analysis;紧急 hotfix 可以跳过 Phase 1,直接进 Phase 2。


3.3 编排机制:三个机制让流水线不僵化


编排器通过三个核心机制确保流水线灵活可控:

  • 智能跳过:不是每个 Skill 都要跑。编排器根据需求特征自动判断,跳过不适用的 Skill。本次实战中 9 个 Skill 执行了 7 个,跳过了 2 个(scaffold-generator、api-definition)。

  • Phase 关门:每个 Phase 完成后暂停确认,输出摘要并询问是否继续,让人类保留纠偏的权力。

  • 独立可拆卸:每个 Skill 可独立使用,编排器只是"推荐的串联方式",不是"唯一的使用方式"。


三个机制的设计动机、实现细节和实战效果,详见第四、五章。


3.4 数据流转:Skill 间的接力赛模式


整个流程中最值得关注的,是 Skill 之间怎么传递数据。


这不是通过 API 或数据库,而是通过自然语言形式的产出物在对话上下文中流转:

impact-analysis    │ 输出:"影响面极小,修改封闭在 uploadComponent.vue 内部"    ▼processing-principles    │ 输入:上游结论 → 跳过"跨组件兼容性"检查项    │ 输出:6 条编码规则(含阈值、降级策略、埋点要求)    ▼minimal-invasion    │ 输入:6 条规则 → 确定需要"条件守卫 + 前置处理"两种模式    │ 输出:具体的代码插入方案    ▼[代码实施]    │ 输入:插入方案 → 机械化编写代码    ├──▶ monitor-integration(规则第 5 条触发)    ├──▶ i18n-integration(Toast 文案触发)    ▼regression-cases    │ 输入:变更的文件和函数 → 生成回归清单    ▼cr-self-check    │ 输入:所有修改的文件 → 逐项检查    │ 输出:CR 自查报告


上游 Skill 的结论会直接影响下游 Skill 的行为。 比如:

  • impact-analysis 判定"影响面小"→ processing-principles 跳过了"跨组件兼容"和"回滚策略"检查项

  • processing-principles 明确了"需要埋点"→ 编排器在 Phase 2 自动激活了 monitor-integration

  • processing-principles 没提到"新建模块"→ 编排器跳过了 scaffold-generator



04

实战推演:

以"图片压缩"需求跑通流程B


以下以"某业务上报图片压缩"这一典型存量需求,演示流程B如何运行。


开发者输入需求描述后,编排器 dev-workflow 自动分析需求特征。本次"图片上传前压缩"涉及对现有 uploadComponent.vue 组件的修改,编排器判定为存量变更,自动路由至流程B,并规划出 Phase 1(分析评估)→ Phase 2(编写代码)→ Phase 3(验证提交)的执行路径。


Agent执行过程


以下按 Phase 逐步拆解,看每个 Skill 具体干了什么、产出了什么。


4.1 Phase 1:分析评估(三个 Skill 严格串行)


Phase 1 的三个 Skill 是有依赖关系的——后者需要前者的输出。所以必须串行执行。


Skill 1: impact-analysis — 影响面分析

输入:需求描述 + 目标文件路径(uploadComponent.vue)


AI 自动扫描了调用链——向上追溯(谁在调用我)、向下追溯(我依赖了谁)、横向扫描(谁和我用同一个 API),最终输出:

关联文件

关联方式

影响评估

parentForm.vue

父组件调用

props/emit 不变,无影响

readonlyPreview.vue

父组件(只读模式)

不触发上传,无影响

business.uploadFile API

上传接口

入参仍为 FormData,无影响

结论:影响面极小,修改完全封闭在 uploadComponent.vue 内部。 这一步给了我们动手的信心。


这个结论被传递给下一个 Skill——processing-principles 因此知道不需要考虑"跨组件兼容"的问题。


Agent执行过程


Skill 2: processing-principles — 处理原则提取

输入:需求描述 + impact-analysis 的结论(影响面小,无跨组件变更)


它拿着结构化 Checklist(边界阈值、失败处理、兼容性、并发与顺序、可观测性、回滚策略六大维度)逐项引导确认。中间抛出了两个关键问题:

  • "等于 3MB 时算哪边?" → 用户选择:不压缩

  • "压缩失败要不要提示用户?" → 用户选择:不提示


最终沉淀出 6 条编码级规则:

#

原则

规则

1

触发阈值

>3MB 触发压缩,≤ 3MB 直接上传

2

大小上限

>10MB 拒绝上传,Toast 提示

3

失败降级

压缩异常 → 静默上传原文件

4

用户感知

压缩失败不提示,对用户完全透明

5

埋点监控

成功/失败状态 + 压缩耗时

6

接口兼容

不改变 props/emit/API 接口

亮点:等于 3MB 时不压缩,等于 10MB 时允许上传——这种边界值的决策,如果没提前想清楚,写到一半才发现又得改。


这 6 条规则被传递给下一个 Skill——minimal-invasion 据此决定代码怎么插入。


Agent执行过程


Skill 3: minimal-invasion — 最小侵入分析

输入:目标函数源码 + processing-principles 的 6 条规则


它读取 uploadFileToServer 方法,画出分支结构:

uploadFileToServer(file)├── if (Array) ──── 批量上传│   └── forEach → FormData.append → 调用接口└── else ─────────── 单文件上传    └── FormData.append → 调用接口


然后从 5 种集成策略中选择了两种的组合:

  • 条件守卫(规则 2):入口处 10MB 拦截,快速失败

  • 前置处理(规则 1/3):FormData.append 之前插入压缩,失败降级返回原文件


输出了具体的代码变更方案:

// 原来formData.append("file", item.file);
// 改为const processedFile = await this.processFileWithCompress(item.file);formData.append("file", processedFile);


只改一个变量名,原有的上传、回调、状态管理全部不动。 这就是"最小侵入"的精髓。


Agent执行过程


Phase 1 小结:三个 Skill 像接力赛一样——impact-analysis 递出"影响面",processing-principles 接棒递出"规则",minimal-invasion 再接棒递出"插入方案"。上游的结论直接影响下游的行为:

  • impact-analysis 判定"影响面小"

  • processing-principles 就跳过了"跨组件兼容"检查项

  • processing-principles 明确了"需要埋点"


编排器就在 Phase 2 自动激活 monitor-integration;没提到"新建模块",编排器就跳过了 scaffold-generator。此时编排器暂停,输出摘要并询问是否继续——这是关门机制的第一道确认门。


4.2 Phase 2:编写代码(实施 + 两个辅助 Skill)


拿到 Phase 1 的三份产出,写代码就变得非常机械化。


代码实施:三个文件,一套设计


文件 1:压缩工具函数 fileCompress.js


核心设计是 Promise + 回调双通道:

export function compressImage(file, callbacks = {}){  return new Promise((resolve) => {    // ...    new Compressor(file, {      quality: 0.8,      success(result) {        callbacks.onSuccess?.({ duration, originalSize, compressedSize, savedRatio });        resolve(compressedFile);  // Promise 通道:返回压缩结果      },      error(err) {        callbacks.onFail?.({ duration, error: err.message });        resolve(file);  // 关键:失败也 resolve,不 reject!      }    });  });}


设计亮点:永远 resolve,永不 reject。 压缩失败时返回原文件,调用方完全不需要 try/catch。这保证了:

  • 压缩成功 → 上传压缩后的文件

  • 压缩失败 → 上传原文件

  • 调用方代码完全一致,零分支


文件 2:集成到 uploadComponent.vue


核心文件 uploadComponent.vue 只改了三处:

改动位置

改动内容

改动量

文件头部

新增 2 行 import

+2 行

uploadFileToServer 入口

新增 10MB 守卫

+8 行

FormData 构建前

原 item.file → processedFile

改 2 处

methods 中

新增 processFileWithCompress

+35 行


原有的 loading 管理、save 触发、错误处理——一行没动。


Agent执行过程


Skill 4: monitor-integration — 埋点集成

因为处理原则第 5 条要求"埋点监控",编排器自动触发了 monitor-integration Skill。它扫描了 monitorReporter.js 现有的 20+ 个埋点函数,识别出命名模式(report_ 前缀)和公共上报字段(运行环境、用户标识、页面地址),然后在文件末尾追加了 report_imageCompress 函数——风格和已有函数完全一致。


上报字段包括:

status(success/fail)| duration(耗时ms)| originalSize | compressedSize | savedRatio | fileName


埋点与压缩逻辑的解耦:压缩工具函数不依赖任何埋点库,通过 callbacks.onSuccess / onFail 暴露钩子:

compressImage(file, {  onSuccess: (data) => report_imageCompress({ status: 'success', ...data }),  onFail: (data) => report_imageCompress({ status: 'fail', ...data })});


fileCompress.js 是纯工具函数,可在任何模块复用;埋点逻辑留在业务层,由调用方决定是否监控、怎么监控。


Agent执行过程


Skill 5: i18n-integration — 国际化文案

因为代码中有一处 Toast 提示("文件大小不能超过10MB"),编排器触发了 i18n-integration Skill。它在 zhLang.js中加了一条词条,在 common/index.js 中注册了 key。


Agent执行过程


Phase 2 小结:代码实施阶段的核心特征是机械化——Phase 1 已经定好了"在哪改、怎么改、改多少",这一阶段只是按图施工。三个关键设计决策值得注意:

  • fileCompress.js 采用"永远 resolve"模式,压缩失败自动降级,调用方零分支

  • uploadComponent.vue 仅改 3 处,原有 loading/save/错误处理一行未动

  • 埋点通过 callback 钩子与压缩逻辑解耦,工具函数保持纯粹可复用


编排器根据 Phase 1 的结论自动激活了 monitor-integration(处理原则第 5 条要求)和 i18n-integration(检测到硬编码 Toast),跳过了 scaffold-generator 和 api-definition。此时编排器再次暂停——这是关门机制的第二道确认门。


4.3 Phase 3:验证提交(两个 Skill 可并行)


Skill 6: regression-cases — 回归用例生成


它分析了本次变更涉及的文件和新增逻辑,生成了 13 条回归用例:

优先级

示例场景

预期

P0

上传11MB 图片

Toast 提示"文件大小不能超过10MB"

P0

上传 5MB 图片

自动压缩后上传,埋点记录 success

P0

上传 1MB 图片

不压缩,直接上传

P1

批量上传混合大小

各自按规则处理

P1

只读模式预览

正常预览(行为不变)

P2

上传正好 3MB

不压缩

P2

上传正好 10MB

允许上传


Agent执行过程


Skill 7: cr-self-check — CR自查

它逐项检查了本次修改的所有文件,区分存量修改的专项检查(分支覆盖、接口兼容、loading 状态、新逻辑失败不阻断原流程)和基础检查,输出:

  • 通过项:无 ESLint 错误、无 console.log 残留、所有文案已国际化、所有分支已覆盖、原有接口未变化、新逻辑失败不阻断原流程

  • 需关注:监控规则 ID 为占位符(待监控平台申请后替换)


Agent执行过程


Phase 3 小结:两个验证 Skill 无依赖关系,可以并行执行。regression-cases 从变更文件和新增逻辑中自动推导出 13 条分级用例(P0/P1/P2),覆盖了核心路径、交叉场景和边界条件;cr-self-check 则从代码规范、存量兼容性、埋点完整性三个维度逐项扫描,输出结构化的自查报告。


两个 Skill 的产出互补:回归用例告诉你"该测什么",CR 自查告诉你"代码本身有没有问题"——一个面向测试,一个面向审查,共同构成提交前的最后一道防线。


4.4 执行数据总览


代码变更统计

文件

操作

变更行数

src/utils/fileCompress.js

新增

+119 行

src/utils/monitorReporter.js

修改

+21 行

src/views/business/components/uploadComponent.vue

修改

+60 行

src/lang/libraryFile/zhLang.js

修改

+1 行

src/lang/common/index.js

修改

+1 行

合计

5 个文件

+202 行


3 个 Phase、7 个 Skill 执行(跳过 2 个)、6 条处理原则、13 条回归用例、CR 自查全部通过。


流水线产出清单


Phase

Skill

产出

1

impact-analysis

影响面清单(3 个关联文件,均无影响)

1

processing-principles

6 条编码级处理原则

1

minimal-invasion

插入方案(条件守卫 + 前置处理)

2

monitor-integration

埋点函数 report_imageCompress

2

i18n-integration

中文词条 + 公共模块注册

3

regression-cases

13 条分级回归用例

3

cr-self-check

CR 自查报告(通过)



05

编排设计原则与决策


从架构设计和实战验证中,我们提炼出六条可复用的编排原则。每条原则不仅说明“做什么”,更解释“为什么”——没有它会怎样,以及实战中如何体现。


5.1 六条原则


1. 单一职责——做螺丝刀,不做瑞士军刀

  • 问题:如果把多个能力塞进一个“万能 Skill”,任何小改动都需要重新调试整个 Skill;不同场景无法按需组合。

  • 设计:每个 Skill 只解决一个问题,独立成 Markdown 文件。编排器负责组合,Skill 只负责执行。

  • 实证:本次实战中,monitor-integration 和 i18n-integration 各自独立触发——如果合并为“辅助集成 Skill”,就无法单独跳过某项能力。


2. 接力模式——上游的输出是下游的输入

  • 问题:如果每个 Skill 独立获取信息(如各自重新分析代码),不仅浪费 token,还可能产出矛盾的结论。

  • 设计:Skill 之间通过自然语言“产出物”传递数据,而非 API 或数据库。LLM 天然产出自然语言,无需额外的序列化/反序列化成本。

  • 实证:impact-analysis 输出“影响面极小” → processing-principles 据此跳过“跨组件兼容”检查项 → minimal-invasion 据此选择“前置处理”而非“逻辑替换”。


3. 串行 vs 并行——有依赖的串行,无依赖的并行

  • 问题:如果一律串行,浪费时间;如果一律并行,下游 Skill 拿不到上游结论。

  • 设计:编排器判断 Skill 间是否存在数据依赖。Phase 1 三个分析类 Skill 有严格依赖,必须串行;Phase 3 两个验证类 Skill 无依赖,可以并行。

  • 实证:如果 processing-principles 和 impact-analysis 并行执行,processing-principles 就无法根据影响面结论跳过不适用的检查项,产出会包含大量无关的“跨组件兼容”分析。


4. 智能跳过——不是每个 Skill 都要跑

  • 问题:如果 7 个 Skill 每次都跑,增量需求也要走完“影响分析 → 处理原则 → 最小侵入”这条存量路径,“走流程”就变成了“走形式”。

  • 设计:编排器维护一张跳过规则表,根据需求特征和上游产出自动判断:

SKill

跳过条件

scaffold-generator

不新建模块时跳过

api-definition

不新增接口时跳过

impact-analysis

纯增量需求时跳过

processing-principles

逻辑简单无歧义时跳过

minimal-invasion

纯增量需求时跳过

i18n-integration

无用户可见文案变更时跳过

monitor-integration

用户明确不需要埋点时跳过

regression-cases

不涉及代码修改时跳过

cr-self-check

不涉及代码修改时跳过


  • 实证:本次实战中 9 个 Skill 执行了 7 个,跳过了 scaffold-generator 和 api-definition——编排器检测到没有“新建模块”和“新增接口”的需求特征。


5. 关门机制——每个阶段都有“确认门”

  • 问题:AI 一口气写完代码,你发现方向就不对,全部要返工。越晚纠偏,成本越高。

  • 设计:编排器在每个 Phase 完成后暂停,输出摘要并询问是否继续:

✅ Phase 1 完成。摘要:- 影响面:修改封闭在 uploadComponent.vue 内部- 处理原则:6 条编码规则- 插入方案:条件守卫 + 前置处理
是否进入 Phase 2?或者需要调整什么?


  • 实证:本次实战中,Phase 1 完成后编排器暂停,确认了影响面和插入方案后才进入 Phase 2。如果 Phase 1 的结论有误(如影响面判断遗漏),可以在此时纠正,而不是等 200 行代码写完再推翻。


6. 可拆可组——流水线是“建议”,不是“强制”

  • 问题:如果编排器是唯一入口,那只想加个埋点就必须走完整个流程,使用门槛过高。

  • 设计:每个 Skill 可独立调用。编排器是“推荐的串联方式”,不是“唯一的使用方式”。

  • 实证:紧急 hotfix 可以跳过 Phase 1 直接进入 Phase 2;其他项目可以复用单个 Skill(如只用 impact-analysis),不需要搬走整个编排器。


5.2 设计决策对比


编排设计的每个选择背后,都有替代方案。以下对比解释了“为什么选这条路”:

设计决策

本文选择

替代方案

不选替代方案的原因

Skill 粒度

7 个单职责 Skill

1 个大提示词

大提示词不可复用、难调试、无法单独跳过某项能力

数据传递

自然语言产出物

结构化 API / JSON

LLM 天然产出自然语言,API 对接需额外序列化成本;且自然语言更灵活,能传递“影响面极小”这类模糊结论

流程控制

编排器推荐 + 关门确认

全自动执行

存量修改风险高,人必须保留纠偏权;全自动执行无法在 Phase 1 发现方向错误时及时纠偏

Phase 划分

3 阶段(分析→实施→验证)

不分阶段

不分阶段则无法做阶段性质量把控,也失去了关门机制的锚点



06

结语


存量代码如同有人居住的老宅,改造之道在于"微创"。本次实践表明,AI的价值不仅在于生成代码,更在于将散落的能力编排成一条严谨、可复用的"开发流水线"。它通过流程的确定性,对抗存量修改中的不确定性风险,让"做得对"从一种运气,转变为一种习惯和必然。


这条流水线并未增加工作的复杂度,而是将那些原本依赖个人经验、容易遗漏的隐性工作显性化、自动化。最终,我们以最小的切口(改动202行代码),安全地嵌入了一个新功能,同时获得了完整的影响分析、清晰的规则定义、可量化的监控以及全面的测试保障——这正是工程化AI协作带来的深层价值。


AI 写代码的能力已经不稀奇了。真正有价值的,是把 AI 的能力编排成一个可复用的流程——让"做得对"变成一种习惯,而不是一种运气。



END


猜你喜欢

从混乱到秩序:我如何搭建一套「规范驱动」的 AI 协作开发体系

Agent 工程思考:从 ReAct 到 Agent Harness

协同文档下的 Agent 协作闭环:可回滚、可对比的透明化编辑实现



前往微信阅读全文

内容来自公众号,可前往微信查看原文。

查看作者的更多文章 →