user-vibeloop · 使用教程

用户在网页报 bug,AI 分诊、改代码、跑测试、合进主线

user-vibeloop 是一个放进任何 git 项目的框架。用户提交的 bug,AI 从分诊一路做到合并, 最后由报告问题的用户点一下「修好了」,才算关闭。你只做两件事:在 vibeloop.yaml 里写清目标、约束和验证命令; AI 撞上没有标准答案的取舍时,替它拍板一次。你不看代码——合不合并,取决于 verify 命令的退出码, 和 judge 对照你写的目标给出的评估。

下面按顺序走:3 分钟看 demo 跑一遍 → 15 分钟接入你的项目 → 一个工单从提交到关闭要经过什么 → 你会被打断的两种情况 → 我实测发现的 7 个问题(只报告,没修)。

AI 自动完成 你看不到,也不用管 需要你操作 流程停在这里等你

01它到底做什么

用户在网页提交 bug → AI 初筛(判断是不是有效问题、跟已有工单比对是否重复、信息不全就追问用户) → AI 在一个独立的 git worktree 里改代码 → 框架跑你指定的 verify 命令 → judge agent 拿 diff 对照你写的 goalconstraints 打分 → 低风险且通过,就 squash 合并进主线,并在主线上再跑一遍 verify → 通知报告问题的用户,他点一下「修好了」,工单才关闭。

这七步,传统上每一步都是你:你看、你判断、你写、你测、你合、你回复。这里六步 AI 执行,留给你的只有两个动作:

一次性 · 之后很少动

写 vibeloop.yaml

三个必填字段:goal(一句话产品目标,judge 打分的最高准绳)、 constraints(红线,judge 认定违反任何一条,就把这次修复直接打回)、 verify(一条命令,比如 npm test)。写完就放着。

按需 · 每周几次

点决策卡片

AI 撞上真正没有标准答案的取舍(例:只加一个深色模式开关,还是做一整套主题系统?), 它不硬猜——把工单挂起(awaiting_decision),弹一张卡片给你。 你点一次,这个决定会被记下来,写进之后每一次 AI 的提示词里,同类问题不再问你。

设计如此 · 不是漏了

你不做代码审查

合不合并只看两样:verify 跑没跑过,judge 对照你的目标怎么评。 不看你觉得对不对。直接后果:verify 有多严,自动化就有多可信—— verify 只跑一个 lint,AI 就能把假修复合进主线。

两条硬护栏,配置绕不过去: ① riskTiers.high 的 glob 命中的文件(保护路径)一律人审, gates.high 就算写成 auto 也会被强制改回 human; ② testPaths 覆盖的测试文件里,删掉的行比新增的多,强制人审—— 防的是 AI 靠删测试让 verify 变绿。

02第一天:先花 3 分钟看它跑一遍

别急着接自己的项目。先让它在一个临时仓库里把四个剧本跑给你看——不调用任何 AI,零成本,不碰你的代码。

终端
git clone <this-repo> && cd user-vibeloop
npm install          # 只装一个依赖:yaml
node src/cli.js demo   # 临时 git 仓库 + mock agents,30 秒跑完四个剧本

下面是它真实的输出结尾(我刚跑的,不是编的)。四个工单,四种结局:

demo 输出(节选)
▸ 主线 git log(squash 合并 + Source-branch trailer):
4e5a917 other(t-20260712-d3154b): 更新 package 依赖元数据
6f76cc8 feature(t-20260712-2d378a): 希望能换主题配色
4373912 bug(t-20260712-107aab): 折扣价格算错:100 元打 9 折显示 10 元
7a5e97b demo-app 初始版本(含种子 bug)

工单终态: {
  't-20260712-107aab': 'closed',                 // 剧本1:自动修好 → 用户确认 → 关单
  't-20260712-46b9ce': 'duplicate',              // 剧本2:跟剧本1重复,自动并过去,没调 AI
  't-20260712-2d378a': 'awaiting_confirmation',  // 剧本3:AI 问你要个决策 → 你点了 → 它照做 → 合了
  't-20260712-d3154b': 'awaiting_confirmation'   // 剧本4:碰了 package.json → 强制你审批 → 你批了 → 合了
}

▸ 演示全部剧本达到预期终态 ✅

看懂这四行,你就看懂了整个系统。剧本 1 你完全没出现——用户报了个折扣算错的 bug, AI 改了 lib.js、顺手在 test.js 里加了条回归断言、测试全绿、squash 进 main、 给用户发确认链接、用户说"好了"、关单。你在睡觉。

剧本 3 和 4 你出现了,各一次,各花 10 秒。一次是点选项,一次是点批准。

03第二天:15 分钟接入你自己的项目

终端
node src/cli.js init /path/to/your-repo   # 生成 vibeloop.yaml 模板
$EDITOR /path/to/your-repo/vibeloop.yaml   # ← 全部功夫都在这一步

# 起服务:反馈网页 + 决策队列 + 观察面板 + 引擎守护,同一个进程
export ADMIN_TOKEN=$(openssl rand -hex 16)
export BASE_URL=https://vibeloop.yourdomain.com
node src/cli.js serve /path/to/your-repo --port 8123

框架对你的项目零侵入:只放一个 vibeloop.yaml,运行数据全在 <repo>/.vibeloop/, 并且自动写进 .git/info/exclude,不会弄脏你的工作树。

三个字段决定一切

模板里字段不少,但真正决定成败的只有三个。写的时候记住一件事:说清你要什么结果、哪些线不能碰,不要去规定 AI 该怎么做。

字段写法写砸了会怎样
goal 一句话,写结果不写路径。
✅"一个响应快、零崩溃的 macOS 语音输入法"
❌"用 Swift 重写音频模块"
judge 拿它当最高准绳评估每一个 diff。写成路径,judge 就没法判断"这修得对不对",只能判断"这照做了没有"。
constraints 只写违反即拒绝的硬边界。
✅"不引入新的运行时依赖"
❌"代码风格要简洁"
judge 认定违反任何一条,这次修复就直接打回重做。把风格偏好写进来,会让大量正常的修复被打回。风格偏好不该写在这里——遇到了你裁决一次,AI 会记住,以后照办。
verify 唯一的自动化信任来源。要快、要确定性、要覆盖核心行为。
npm test
这是最危险的一格。verify 太弱 → judge 只能看 diff 猜 → 你在赌 AI 的自觉。verify 越硬,你越敢把门槛开成 auto。

然后是那个真正的开关:谁能自动合并

riskTiers 用 glob 把改动文件分成 low / medium / high,gates 决定每档要不要人审。 这是你调节"胆子多大"的旋钮:

vibeloop.yaml
riskTiers:
  low:  ["docs/**", "**/*.md", "**/*.css"]
  high: ["auth/**", "payment/**", ".github/**", "vibeloop.yaml", "package.json"]
  # 没匹配上的 = medium

gates:
  low:    auto     # judge 通过就合,你不会知道
  medium: auto     # ← 刚上线时建议先改成 human,跑一周看 AI 靠不靠谱再放开
  high:   human    # 恒为 human。你写 auto 也会被框架强制覆盖(安全不变量)

我的建议:第一周把 medium: human 你会看到 AI 每一次修复的 diff 和 judge 的评语,一周后你就知道该不该放手了。 这个框架允许你从"全人工"平滑滑到"全自动",没必要第一天就赌。

04跟着一个工单走一遍:用户说折扣算错了

具体点。用户 A 在你的 App 里发现结算页 100 块打 9 折显示 10 块。下面是接下来 20 分钟真实发生的事—— 左边圆点是机器琥珀色是你

数一下你出现了几次:零次。这个 bug 从用户抱怨到关闭,前后 20 分钟,你不知道它发生过。 你只会在观察面板 GET / 上事后看到它——如果你想看的话。

05你被打断的两种时刻

两种,只有两种,都汇聚到同一个页面:GET /decisions。这是你每天唯一需要打开的东西。

时刻一:AI 撞上了没有标准答案的取舍

用户 B 说"希望能换个主题配色"。fixer 停下来了——它可以做一个深色模式开关(一天交付,覆盖 80% 诉求), 也可以做一整套主题系统(可扩展,但引入配置面)。这不是技术问题,是产品问题。它不硬猜,它问你。

/decisions —— 待裁决卡片
┌─ 主题功能的形态:深色模式开关还是全套主题系统?
│
│  用户想要"换个配色"。两个方向都合理:
│  · 深色模式开关:一天内可交付,覆盖 80% 诉求
│  · 主题系统:可扩展但引入配置面
│
│  ( • ) 仅深色模式开关   最小交付,符合 KISS      ← AI 推荐
│  (   ) 完整主题系统     可扩展,但超出当前诉求
│
│  批注(选填,进入决策台账,后续同类问题 AI 直接遵循)
│  ┌──────────────────────────────────────────┐
│  │ 先做减法。用户要的是"晚上不刺眼",不是"我要 │
│  │ 一个调色板"。                              │
│  └──────────────────────────────────────────┘
│  管理口令 [ •••••••••• ]      [ 提交裁决 ]
└─

你点一下,写两句话,10 秒。工单带着你的决定回到队列,fixer 照着做,judge 评,合并。 你写的话会被记进一个决策记录文件ledger.jsonl)—— 之后每一次 fixer 和 judge 干活之前,框架都会把这些记录的摘要塞进它们的提示词里。

这是"AI 乱打补丁"的机制化解法。不是你盯着每一步,而是把偏好一次性沉淀下来: 下次再有人提"想要主题",AI 会看到"这个项目的老板说过:先做减法",它自己就不问了。 你的裁决次数应该随时间递减——如果没有递减,说明你的 goal 写得不够清楚。

时刻二:改动碰了保护路径

有个工单要改 package.json。judge 说没问题、测试全绿、风险低——没用,照样停下。 保护路径恒需人审,你把 gates.high 写成 auto 都会被框架强制覆盖成 human。 这是硬编码的安全不变量,配置绕不过去。

你在决策页看到 judge 的完整评语和 diff 链接,三个选项:批准合并 / 驳回 / 退回重修(带批注)。

riskTiers.high 这一栏值得你认真想一遍。 认真想一遍:这个项目里哪些文件被改坏了会让你半夜爬起来?支付、鉴权、CI 配置、数据库迁移、发版脚本—— 全塞进 high。剩下的交给 verify 命令去把关。

06推演:内测第一周会是什么样

下面这张表是推演,不是实测——基于代码里的实际路由逻辑和 demo 行为,假设 30 个内测用户、一周报了 20 个问题。 我标出了哪些数字是结构性的(代码决定),哪些是我的估计。

发生了什么工单数你花的时间依据
closed 自动修好,用户确认关单 8 0 分钟 估计。取决于你的 verify 有多硬
duplicate 自动判定重复,没花一分钱调 AI 4 0 分钟 估计。内测早期重复率很高,这是 Cathier 踩过的坑
needs_info AI 追问,等用户补充 3 0 分钟* 估计。* 补充信息链路曾断裂(P2),2026-07-13 已修复
awaiting_human 碰保护路径,等你批 2 ~1 分钟 结构性:high 档恒人审
awaiting_decision AI 要你做产品决策 2 ~5 分钟 结构性:无标准答案时 fixer 主动升级
fix_failed 修两次都没修好,给你一张处置卡 1 ~5 分钟 结构性:fixer 重试上限 = 1(共 2 次尝试)

推演结论:一周 20 个工单,你大约花 15 分钟,全部花在 /decisions 页面上, 而且随着决策记录越攒越多,这个数字应该逐周下降。这就是这个系统承诺的东西。

成本的结构(不是金额)

我不给你美元数字(没实测计费),但给你结构,你可以自己算:

所以真正的成本控制点是:verify 越硬,fixer 重试越少,花的钱越少。省钱和质量在这里是同一件事。

07实测发现的 7 个问题(已全部修复)

首次审查(2026-07-12)按"只报不修"交付了这 7 条;次日全部修复并配回归测试(136/136 全绿,demo 四剧本复跑通过)。 每张卡保留原始发现(当时都会让用户反馈静默消失——这是这个系统最不能有的性质), 卡片末尾的绿色部分是修复方式。

P1 · High 已修复

已修复关闭的 bug 回归后再被报告,会被静默吞掉

用户 A 报了折扣 bug → AI 修好 → A 确认 → 工单 closed(关闭)。 三个月后某次改动让这个 bug 回归了,用户 B 重新报告同一个问题。 查重逻辑把 B 的工单判成 duplicate(重复),并到 A 那个工单上—— 而 A 那个工单已经是 closed,这是最终状态——系统里没有任何一条路能把它重新打开

结果:B 的工单躺在 duplicate 里,A 的工单躺在 closed 里,决策队列 0 张卡片,观察面板一切正常, 引擎再跑多少轮都不会有人碰它。这个回归 bug 永远不会被修,而且没有任何人会知道。

代码里只对 fix_failed(修复失败)的工单做了"再有人报 = 重试信号"的复活处理 (src/pipeline/triage.js 里那段 if (primary.status === FIX_FAILED)), closed 没有对应处理。讽刺的是,README 明确写着"同一个 bug 再被报告,应该并到原工单上"—— 并过去是对的,但并到一个已经关闭、再也不会被处理的工单上,就等于扔进黑洞。

实测复现:写探针让 demo 的 mock fixer 真修好 bug、工单走到 closed,再报同一个 bug。 结果:新工单 duplicate,原工单 closed,待处理决策卡 0 张,流程里活跃工单 0 个。

✔ 修复:查重撞上已关闭的工单时,按"疑似回归"处理——新工单不再并过去,标记 regressionOf 独立走一遍完整流程(改由新的报告者来确认修好没有),原工单留一条 regressionReported 审计记录、关闭状态的含义不变; fixer 的提示词里会带上上次修复的 commit sha,方便追溯。fix_failed 工单的复活逻辑保持原样。

P2 · High 已修复

AI 追问用户,用户看得见问题,却没有回答的入口

工单被判成 needs_info(信息不足),AI 列出了"什么操作后崩溃?崩溃前有报错吗?" 报告者手里只有两个链接(提交时给的):

  • /confirm/:id?token=… —— 打开显示"当前状态 needs_info,暂不需要你的确认"。死路。
  • /tickets/:id不带 token)—— 能看到 AI 的追问,但没有输入框。死路。

补充信息的表单只在 /tickets/:id?token=… 上出现, 而框架从来没有把这个 URL 给过用户。用户必须自己意识到"我要把 confirm 链接里的 token 拷到 tickets 链接后面"—— 没有任何真实用户会这么干。

后果不只是这一个工单卡住。needs_info 是初筛的主要去向之一(内测早期,信息不全的反馈占比很高), 这条路断了意味着:所有"需要追问"的反馈全部石沉大海,而用户以为自己已经报告过了。

实测复现:起真实服务,提交一条会被判成 needs_info 的反馈。 /tickets/:id 无 token → 页面含追问、不含 name="message" 输入框; 手动拼上 token → 输入框出现。当时的修复建议(ticketUrl 带上 token)即最终修法。

✔ 修复:提交回执(JSON 与成功页)现在给出带报告者 token 的 ticketUrl,补充表单开箱即达; confirm 页在 needs_info / duplicate 状态不再是死路,就地引导到工单页操作。真实 HTTP 回归测试覆盖全链路。

P3 · Medium 已修复

你收集了用户的邮箱,但框架从来不用它通知任何人

反馈表单有"联系方式"一栏,工单里也存了 contact。但是: 默认 notify.mode: log 下,修好后的确认链接只写进服务端日志文件; 就算你配了 webhook,POST 出去的 payload 里 (ticketId / title / status / fixSummary / confirmUrl压根没有 contact 字段—— 接收方不知道该通知谁。

所以"报告者是第一验证环境"这个核心设计,目前完全依赖用户自己收藏了那个确认链接。 关掉页面 = 永久失联,工单停在 awaiting_confirmation(等待确认)直到天荒地老。

代码路径确认src/pipeline/notify.js 的 payload 构造。 这不是 bug 而是缺口——但它让整个闭环的最后一环变成了概率事件。

✔ 修复:webhook payload 与服务端日志现在携带 contact(接收方知道通知谁); 事件流和公开接口里依然不含联系方式(个人信息边界不变)。log 模式下日志行同时给出联系方式与确认链接,便于手动转发。

P4 · Medium 已修复

verify 是唯一的信任来源,而 fixer 有权改 verify 的内容

fixer 拿着 Read, Edit, Write, Grep, Glob, Bash 全套权限在 worktree 里干活—— 它当然能改测试文件——"每修一个 bug 就补一条断言"本来就要求它能改。 但反过来:它同样能删掉或弱化一条挡路的断言,让 verify 变绿。

而默认模板的 riskTiers.highauth/** payment/** .github/** vibeloop.yaml package.json—— 不含任何测试路径。也就是说 AI 改测试文件 = medium 档 = 默认 auto = 自动合并。 唯一的防线是 judge 看 diff 时能不能识破,这是一个 AI 在看另一个 AI 的自觉。

我不觉得这是 bug(这是个开放的设计张力:既要 AI 加测试,又不想它删测试), 但默认配置应该站在保守一侧,至少在文档里显式警告一句。

代码路径确认src/agents/runner.jsCLAUDE_TOOLS.fixer + templates/vibeloop.yaml 的默认 riskTiers。

✔ 修复:新增测试删除守卫(testPaths)——diff 里测试文件"删掉的行数 > 新增的行数"时, 哪怕 judge 通过也一定强制人审(只加断言的情况不受影响);judge 的提示词里增加了一条显式检查项:有没有在弱化测试, 覆盖替换型弱化。端到端回归测试验证"fixer 删断言 → 停在 awaiting_human"。 要绝对保证仍可把测试路径放进 riskTiers.high(README 已注明取舍)。

P5 · Medium 已修复

改了 vibeloop.yaml 不会生效,必须重启 serve

vibeloop.yaml 只在 serve 启动时读一次进内存,之后引擎每一轮都在用这份旧的。 你半夜把 gates.mediumauto 收紧成 human、 或者往 constraints 里加了一条硬边界——磁盘上改了,跑着的引擎不知道, 它继续按老规矩自动合并。

危险在于这个失败是无声的:你以为你收紧了,实际没有。README 没有提这一点。

实测确认:探针里改了磁盘上的 goal,再跑 runOncectx.manifest.goal 纹丝不动。(createContext 只 load 一次。)

✔ 修复:配置改了会自动生效——引擎每一轮(默认 30 秒)重读一次 vibeloop.yaml,改门槛/约束/超时即改即生效; 配置写错了就沿用旧的并在日志里报错,引擎绝不带着坏配置自动合并。

P6 · Medium 已修复

观察面板、工单详情、代码 diff——全部公开,无任何鉴权

GET /GET /tickets/:id含完整代码 diff)、 GET /api/tickets 全部无需认证。ADMIN_TOKEN 只保护"写"(审批/裁决),不保护"读"。

对开源项目这没问题。但如果你的目标项目是闭源产品——比如那个语音输入法—— 把这个服务挂到公网 = 把你的源码 diff 和产品缺陷列表实时公开。 README 的部署章节给了 pm2 和 systemd 的例子,但没有一句话提醒这件事。

(做对了的地方:报告者的 contact 和 confirmToken 在公开 API 里都被正确剥离了,这块是干净的。)

实测确认:无任何 header 直接 GET,200 + 返回全部工单。 当时的缓解建议是反向代理加访问控制。

✔ 修复:新增可选 VIEWER_TOKEN:设置后面板 / 决策页 / 工单列表 / 工单详情(含 diff) 需要口令(页面 ?token=,API x-viewer-token 头;ADMIN_TOKEN 同样可用); 报告者持 per-ticket token 永远能看自己的工单;/report 与提交入口永远开放。 不设置保持公开(开源默认),启动时打印提醒。

P7 · Low 已修复

三个小坑

  • 被误判成重复,没地方申诉duplicate 是最终状态,出不去。相似度阈值 0.55 用的是 overlap 系数 (交集÷较小集),对短标题特别敏感——两个不同的 bug 只要标题措辞接近就可能被并到一起, 而报告者没有任何"这不是重复"的按钮。
  • triage 借用了 judge 的超时timeouts 里没有 triageMs, 代码里 triage 复用 judgeMs。不影响正确性,但 README 的字段表没写,调超时的时候会困惑。
  • examples/demo-app 不能直接 serve:它的 agents 配的是 mock, 而 buildRunners 对生产路径的 mock 会直接抛错(这是对的设计), 但如果有人照着 README 的 serve 命令指向 examples 目录,会撞一脸报错。

代码路径确认dedup.js / triage.js / runner.js

✔ 修复:①可以申诉了:duplicate 不再是死路,报告者在工单页一键"这不是重复" (POST /api/tickets/:id/not-duplicate),排除原工单,重走一遍初筛; ②timeouts.triageMs 独立可配(默认 300000); ③examples 的配置文件顶部注明:mock 只供 demo/测试,正式跑 serve 要改成 claude 或 codex。

一句总结这 7 条:这个框架里 AI 那一侧(修代码、跑测试、判风险、合并)做得非常扎实—— 126 个测试全绿,五条安全不变量都落了测试,去重、幂等恢复、跨进程锁、凭证剥离这些硬骨头都啃了。 问题全部集中在"人的那一侧":用户报完之后怎么被联系、AI 追问了他怎么回话、 他的问题被误判成重复怎么申诉、bug 回归了谁来发现。 这很符合直觉——你是照着"让人不用管"的目标建的,于是留给人的那几个入口是最后才想的。 2026-07-13 复审后补:7 条已全部修复,人的那一侧闭合了——报告者能回话、能申诉、能被通知, 回归的 bug 会重新进流程,面板可以加口令锁上,配置改完自动生效。新增回归测试 10 项,全量 136/136 通过。

08接第一个真实项目前的检查清单