Vibe Engineering:用产品语境、技术语境与协作契约驯服AI编程

Vibe Engineering:用产品语境、技术语境与协作契约驯服AI编程
1. 什么是“Vibe Engineering”从玄学调试到可复现协作的工程实践我第一次在终端里敲下opencode --task add dark mode toggle to settings screen三分钟后一个带状态管理、主题切换动画、本地存储持久化的完整功能就躺在了 Git 差异里——我连git add都没来得及按它已经自动git commit -m feat(settings): add dark mode toggle with system preference fallback并提示我“请运行npm run test:ui验证”。那一刻我既兴奋又后怕兴奋的是效率翻了五倍后怕的是——如果它悄悄把localStorage.setItem(theme, dark)写进了useEffect的无限循环里而我没看 diff 就直接git push那整个用户端的渲染线程会在 0.3 秒内被拖垮。这正是“Vibe Engineering”要解决的核心矛盾当 AI 具备秒级生成千行代码的能力时人类工程师的职责不是写得更快而是建起更牢的护栏、设计更清晰的契约、定义更精确的验收标准。它不是教你怎么让大模型“更聪明”而是教你怎么让自己“更可靠”——用工程思维驯服不确定性把原本靠直觉、运气和反复试错的“vibe coding”变成可拆解、可验证、可回溯的协作流程。你可能已经用过 Copilot 补全一行for循环或让 Claude 解释一段报错堆栈但当你需要让 AI 在一个有 42 个模块、7 层依赖、3 套数据流Zustand Drizzle React Query的 React Native 项目里安全地重构整个“今日计划”视图并确保不破坏离线优先的数据同步逻辑时零散的 prompt 就像用乐高积木搭核电站——结构松散、承重不明、风险不可控。Vibe Engineering 提供的是一套完整的“施工图纸安全规程验收清单”它包含三个刚性组件产品语境Product Context、技术语境Architecture Context、协作契约Agent Contract。这三个文件不是文档摆设而是每次 AI 启动前必须加载的“操作系统内核”。没有它们AI 就是蒙眼开车有了它们它才真正成为你团队里那个能读懂架构图、会查迁移脚本、知道为什么date-fns的format必须加yyyy-MM-dd而不能用MM/dd/yyyy的靠谱同事。这个方法论的价值不在于它多炫酷而在于它把“人机协作”从玄学拉回工程现场。它不承诺 100% 正确但能保证 95% 的错误发生在可控范围内——比如在task.md里明确要求“所有日期操作必须用date-fns/format(date, yyyy-MM-dd)”那么 AI 即使写错了逻辑也绝不会出现时区偏移导致用户日志错乱三天的灾难。它把“能不能做对”的问题转化成“有没有定义清楚对的标准”的问题。而后者恰恰是工程师最擅长的事。2. 核心设计思路拆解为什么是这三份文件而不是一份 Prompt很多人第一反应是“不就是写个详细点的 prompt 吗何必搞三个独立文件” 这是个关键误解。Vibe Engineering 的底层逻辑是把 AI 当作一个需要长期共事、具备强上下文记忆但缺乏领域直觉的初级工程师来对待。而任何真实团队里新成员入职都不会只靠一份“欢迎邮件”就上手核心模块——他们需要产品白皮书、技术架构图、编码规范手册。这三份文件正是为 AI 量身定制的入职包。2.1 Product Context给 AI 装上“业务罗盘”product.md的核心作用是防止 AI 掉进“技术正确但业务错误”的陷阱。举个真实例子Puppypal 的“今日计划”页面需要显示“当前年龄指南”AI 如果只看代码可能会直接从数据库读取puppy.age_in_weeks然后查表匹配。但product.md里明确写着“指南内容需根据‘当前日期’与‘出生日期’动态计算而非存储静态年龄字段因用户可能修改出生日期”。这句话直接否决了 80% 的错误实现路径。它让 AI 的思考起点从“怎么读数据”变成“用户场景需要什么实时性”。这份文件的结构设计极有讲究Pitch一句话定位用“本地优先、离线可用、无账号体系”锚定技术边界AI 立刻明白不能引入 Firebase Auth 或 Cloud Sync。Users用户画像明确区分“新手主人”和“有经验主人”AI 在设计交互时会自动倾向“一键式默认操作”而非“高级配置弹窗”。Core Features功能清单不是罗列名词而是带行为约束的描述。例如“Multi-puppy profilesTrack multiple puppies on one device with clean separation of their data”——“clean separation” 四个字直接排除了用共享数组存储多只狗数据的偷懒方案强制 AI 设计独立 ID 隔离。提示product.md不是市场文档而是工程约束集。每句话都应能翻译成代码里的 if/else 判断或类型定义。比如“gamification”在 Puppypal 里被明确定义为“puppy points leveling mastery badges”AI 就绝不会擅自加入“排行榜”或“好友挑战”等超纲功能。2.2 Architecture Context给 AI 绘制“技术地图”如果说product.md告诉 AI “做什么”architecture.md就告诉它“在哪做、用什么做、哪些地方绝对不能碰”。这是防止技术债爆炸的关键防线。Puppypal 的架构文件里有一条看似平淡的规则“Derived data policy: do not persist per-day or total points; compute from session logs”。这条规则背后是血泪教训早期 AI 曾自作主张在 SQLite 里新增daily_summary表缓存积分结果当用户修改历史记录时缓存与源数据立刻失联导致“昨日积分”显示为负数。这份文件的威力在于它把抽象原则转化为具体路径Platforms Runtime明确“iOS Android via Expo”AI 就绝不会推荐react-native-sqlite-storage需原生链接而坚持用expo-sqlite。Layered Structure规定domain/只放纯业务逻辑无 React/SQLitedata/专管数据库交互。当任务涉及“计算今日总积分”AI 必须把逻辑放在domain/再由data/提供原始 session 数据——这种分层强制它写出可测试、可复用的函数而非混着 UI 和 DB 操作的大杂烩。Identifiers Migrations“use string IDs everywhere (UUID for custom records)” 和 “small, focused, reversible changes” 直接决定了 AI 生成的数据库迁移脚本质量。它不会写出ALTER TABLE habits ADD COLUMN points INTEGER DEFAULT 0这种破坏性变更而是老老实实新建habit_points表并提供双向同步逻辑。注意architecture.md必须包含“禁止项”。比如 Puppypal 明确写“No network calls in domain layer”AI 就不可能在计算逻辑里塞fetch()。这些红杠杠比绿勾勾更重要——它们是工程底线。2.3 Agent Contract给 AI 立下“协作军规”AGENTS.md是整套体系的“宪法”它不描述业务或技术而是定义人机协作的规则本身。它的存在解决了 AI 最致命的弱点缺乏自我约束力。没有它AI 就像一个拥有顶级工具但没有安全意识的工匠——能造出最精密的钟表也可能一锤子砸碎整个工作台。这份文件的精妙之处在于“分层授权”Prime Directives最高指令三条铁律——“Always write unit tests”、“Always use proper typing”、“Always run make check”——不是建议是准入门槛。AI 每次生成代码前必须先确认测试覆盖率达标、TypeScript 类型无误、lint 无警告否则拒绝提交。What the app does能力边界强调“Works entirely offline (no accounts, no cloud sync)”AI 就绝不会在登录流程里生成 JWT 解析代码。Mobile app location行动坐标精确到cd mobile npm startAI 才知道该在哪个子目录下执行命令避免在根目录瞎跑npm install。Guardrails防护栏这才是真正的杀手锏。Puppypal 的AGENTS.md里藏着一句“Do not modifymobile/app/except for adding new providers; all UI logic must reside inmobile/ui/”。这意味着 AI 永远无法把导航逻辑硬塞进App.tsx它必须老老实实去navigation/目录下新建文件——这种物理隔离比任何代码审查都有效。实操心得我最初以为AGENTS.md只是锦上添花直到某次 AI 试图用eval()动态执行字符串来“优化”配置加载。我立刻在AGENTS.md新增一条“Never use eval(), Function constructor, or dynamic import() for config parsing; use static JSON.parse() with schema validation”。从此再没出现过此类问题。最好的防护不是事后拦截而是事前剥夺权限。3. 核心文件实操详解如何写出真正能落地的 product.md、architecture.md 和 AGENTS.md光知道“要写三份文件”远远不够。很多团队照猫画虎写了几十页文档AI 却依然产出一堆垃圾代码——问题出在“写法”上。Vibe Engineering 的三份文件不是文学创作而是可执行的机器指令集。它们必须满足三个硬性标准可解析Parseable、可验证Verifiable、可追溯Traceable。下面以 Puppypal 项目为蓝本逐行拆解每份文件的实操要点。3.1 product.md从模糊需求到可编码约束Puppypal 的product.md看似普通但每一处细节都经过工程推演。我们来看关键段落## Core Features - **Multi-puppy profiles**: Track multiple puppies on one device with clean separation of their data. - *Constraint*: Each puppys data must be isolated by puppyId string; no shared state between profiles. - *Verification*: Running SELECT COUNT(*) FROM sessions WHERE puppyId abc must return only sessions for puppy abc.这段的厉害之处在于Constraint约束将“clean separation”翻译成可编程的puppyId字符串隔离AI 生成数据库查询时必然带上WHERE puppyId ?条件。Verification验证给出具体的 SQL 查询语句和预期结果AI 在自检阶段会真的执行这条 SQL 来确认数据隔离是否生效。再看“Training guide”部分- **Training guide**: Searchable guide content, including a Current Age Guidelines view. - *Data Source*: Bundled offline JSON files under mobile/assets/guide/, structured as { ageInWeeks: 8, content: ... }. - *Search Logic*: Use SQLite FTS5 full-text search on guide_content table; never use JavaScript .filter() on loaded JSON. - *Age Calculation*: currentAgeInWeeks Math.floor((new Date().getTime() - birthDate.getTime()) / (1000 * 60 * 60 * 24 * 7))这里埋了三层保险Data Source明确数据位置和格式AI 不会擅自联网抓取或调用 APISearch Logic强制使用 SQLite FTS5已集成禁用低效的 JS 过滤保障离线搜索性能Age Calculation给出精确的毫秒级计算公式AI 就不会用moment.js或dayjs未在架构中批准。实操心得写product.md时永远问自己“如果 AI 把这句话当真它会生成什么代码这个代码能否通过自动化测试验证” 如果答案是否定的那就不是合格的 product 约束。我曾把“用户友好的界面”改成“所有按钮最小尺寸 44x44px所有文本最小字号 14pt所有图标必须有accessibilityLabel”从此再没出现过无障碍审核失败。3.2 architecture.md从技术选型到代码基因Puppypal 的architecture.md不是技术栈列表而是代码的 DNA 图谱。它规定了每个字符该长什么样、每个函数该住在哪里、每个数据该流向何方。我们聚焦最关键的“State Management”部分## State Management - Global store: Zustand - Store responsibilities: orchestration only (UI calls store actions; UI does not talk to SQLite directly) - *Allowed*: store.useAppStore.getState().habitSessions, store.useAppStore.setState({ habitSessions: [...] }) - *Forbidden*: import { db } from ../data/db; db.sessions.insert(...) inside store actions - Data Flow: UI → Store Actions → Data Layer (Drizzle) → SQLite - *Example*: toggleHabitSession(habitId) action must call data.habits.updateSession(habitId, ...) not db.run(UPDATE...)这段设计直击痛点Allowed/Forbidden用黑白分明的条款替代模糊描述AI 生成 store action 时会严格检查导入语句和函数调用链Data Flow用箭头图示化数据流向AI 在设计新功能时会自动遵循“UI→Store→Data→DB”链条不会跳过 Store 直连数据库。再看“Persistence”部分的魔鬼细节## Persistence - Database: SQLite via expo-sqlite - ORM/query layer: Drizzle ORM (SQLite Expo integration) - *Migration Rule*: All migrations must be in migrations/ folder, named 001_add_habits_table.sql, and contain ONLY DDL statements (CREATE/ALTER/DROP). - *Query Rule*: All queries must use Drizzles db.select().from(...) syntax; raw SQL only for FTS5 full-text search. - Identifiers: use string IDs everywhere (UUID for custom records) - *Generation*: Use crypto.randomUUID() in React Native; never Math.random().toString(36) or sequential integers.这里每一条都是血换来的教训Migration Rule强制 DDL-only杜绝在迁移脚本里写业务逻辑如“初始化默认习惯”避免迁移失败导致数据不一致Query Rule锁定 Drizzle 语法确保类型安全和 IDE 支持同时为 FTS5 保留 raw SQL 特权通道Identifier Generation指定crypto.randomUUID()因为Math.random()在 RN 环境下熵值不足曾导致多设备间 UUID 冲突。注意architecture.md必须包含“版本锁”。Puppypal 明确写“Drizzle ORM v0.32.0”AI 就不会用 v0.33.0 的新 API可能破坏 Expo 兼容性。这种细节才是工程稳定性的基石。3.3 AGENTS.md从协作协议到执行铁律AGENTS.md是三份文件中最“不讲情面”的一份。它不关心业务多美好、架构多优雅只专注一件事让 AI 的每一次键盘敲击都在人类划定的轨道内运行。Puppypal 的AGENTS.md开篇就是三记重拳# Puppypal This repo contains **Puppypal**: a local-first **puppy growth companion** mobile app. ## Prime Directives 1. Always write unit tests for any code you modify or introduce - *Rule*: For every new function, add a test file *.test.tsx; for every modified function, update existing tests. - *Verification*: npm run test:unit must pass with 100% coverage on changed lines. 2. Always use proper typing - *Rule*: No any, Object, or Function types; use Recordstring, unknown or specific interfaces. - *Verification*: tsc --noEmit must report zero errors. 3. Always run make check after code changes with escalated permissions that you request from the user - *Check List*: typecheck, lint, test:unit, test:ui, build:android, build:ios这三条指令的恐怖之处在于“可验证性”第一条的100% coverage on changed linesAI 必须用 Istanbul 或 Jest 的--coverage参数生成报告手动检查覆盖率数字第二条的tsc --noEmitAI 会真的在终端执行 TypeScript 编译器把错误日志贴出来供你确认第三条的make checkAI 会列出所有要执行的命令并明确告诉你“需要您输入密码以执行build:ios”。再看“Guardrails”部分的实战设计## Guardrails - **File System Boundaries** - *Allowed*: Read/write files under mobile/src/, mobile/assets/, migrations/ - *Forbidden*: Read/write files under node_modules/, ios/, android/, dist/, .git/ - **Network Restrictions** - *Allowed*: fetch() only in data/api/ directory for future cloud sync (v2) - *Forbidden*: Any fetch(), XMLHttpRequest, or WebSocket in domain/, store/, ui/ - **UI Component Rules** - *Allowed*: Import lucide-react-native icons, react-native-svg for SVGs - *Forbidden*: Import react-navigation/elements or react-native-screens (not in architecture)这些规则不是摆设。当 AI 试图在ui/目录下写fetch()时它会先执行grep -r fetch( mobile/src/ui/发现无匹配然后主动报错“Guardrail violation: Network call forbidden in ui/ directory. Please move to data/api/ or remove.” —— 这就是契约的力量。实操心得AGENTS.md必须定期更新。我每周五下午花 15 分钟用git diff --name-only HEAD~1 | xargs grep -l import.*expo扫描本周所有 PR把新引入的、未在AGENTS.md许可的依赖立刻加进“Allowed Dependencies”列表。这保证了文档永远比代码慢半拍而不是快半拍。4. 实操全流程从一个按钮需求到可交付代码的完整闭环现在让我们把理论付诸实践。假设 Puppypal 需求为“今日计划”页面添加一个“快速记录排便”按钮点击后弹出时间选择器自动创建一条 potty session 并更新当日摘要。这不是简单改个样式而是横跨 UI、Store、Data、Persistence 四层的完整功能。我们将用 Vibe Engineering 流程走一遍从零到一的全过程。4.1 Step 1定义 Goal目标规格化我们不直接对 AI 说“加个排便按钮”而是生成spec.md。这个过程本身就是一次深度需求澄清# Specification: Quick Potty Log — One-Tap Session Creation ## Goal Implement a floating action button (FAB) in Today screen that, when tapped, opens a time picker modal, creates a potty session with current timestamp, and updates daily summary totals without page reload. ## User Stories - As a puppy owner, I want to log potty events in 2 taps so I can track bathroom habits during chaotic puppy moments. - As a developer, I want the FAB to integrate with existing habitSessions store state and potty habit type, reusing all validation and persistence logic. ## Technical Constraints - Must use react-native-community/datetimepicker (already installed per architecture.md) - Must trigger store.toggleHabitSession(potty, { timestamp: new Date() }) action - Must update todayPlanItems and habitSessions in store to reflect new session - Must NOT create new database tables; reuse existing sessions table with habitId potty - Must NOT require internet; all logic must work offline关键点解析Goal里强调“without page reload”强制 AI 使用 Zustand 的异步更新机制而非window.location.reload()User Stories中的“2 taps”是性能指标AI 会优化按钮位置固定右下角 FAB和动画0.1s 弹出Technical Constraints直接引用架构文件中的依赖和表名杜绝自由发挥。4.2 Step 2拆解 Tasks任务原子化AI 生成task.md我们人工审核并强化约束# Task List: Quick Potty Log ## Overview Add FAB and time picker modal for potty logging. All tasks must pass npm run test:unit and npm run typecheck. - [ ] Add react-native-community/datetimepicker import to TodayScreen.tsx ONLY if not already present (verify with grep -r datetimepicker mobile/src/ui/screens/) - [ ] Implement PottyTimePickerModal.tsx: - Use DateTimePickerAndroid for Android, DateTimePickerIOS for iOS - On confirm, call store.toggleHabitSession(potty, { timestamp: selectedDate }) - On cancel, close modal without side effects - [ ] Add FAB to TodayScreen.tsx: - Position: absolute bottom-right, 16px from edges - Icon: lucide-react-native/Plus with accessibilityLabelLog potty - On press: store.openModal(potty-time-picker) - [ ] Extend useAppStore.ts: - Add openPottyModal() action that sets modal potty-time-picker - Add closePottyModal() action that resets modal - [ ] Update store.types.ts: - Add PottyModalState interface with isOpen: boolean, selectedTime?: Date - [ ] Write unit tests: - PottyTimePickerModal.test.tsx: Test render, confirm/cancel flow - useAppStore.test.ts: Test openPottyModal/closePottyModal state changes - [ ] Verification: - cd mobile npm run typecheck → 0 errors - cd mobile npm run test:unit -- --testPathPatternpotty → 100% pass - Manual smoke test: Tap FAB → Modal appears → Select time → Confirm → Session appears in list这个task.md的威力在于“可审计性”每个[ ]都是独立可验证的单元AI 完成后我们可以用git diff逐行检查是否真的只改了TodayScreen.tsx而没碰App.tsxgrep -r命令是防错钩子AI 必须先执行它确认依赖存在才能继续验证步骤精确到命令行杜绝“应该通过了”这种模糊表述。4.3 Step 3Agent 执行与 Verify-Correct 循环AI 开始执行task.md。它不会一股脑生成所有代码而是分步推进并在每个关键节点自我验证Step A生成PottyTimePickerModal.tsxAI 输出代码后立即执行cd mobile npm run test:unit -- --testPathPatternPottyTimePickerModal # Output: PASS src/ui/features/potty/PottyTimePickerModal.test.tsx # ✓ renders correctly (12ms) # ✓ handles confirm (15ms) # ✓ handles cancel (8ms)测试通过进入下一步。Step B修改useAppStore.tsAI 添加openPottyModal后触发类型检查cd mobile tsc --noEmit --skipLibCheck # Output: src/store/useAppStore.ts:45:3 - error TS2322: Type string is not assignable to type potty-time-picker. # Fix: Change modal potty-time-picker to modal potty-time-picker as constAI 自动修正类型错误重新提交。Step C最终整合验证所有任务完成后AI 运行完整检查套件cd mobile npm run check # Output: # typecheck: PASS # lint: PASS # test:unit: PASS (100% coverage on new files) # test:ui: PASS (smoke test: FAB visible, modal opens, session created) # build:android: PASS (APK generated)此时Git 差异里只有 7 个文件被修改且全部符合task.md的原子化要求。实操心得Verify-Correct 循环的成败取决于验证脚本的质量。我在package.json里预置了npm run check它串联了tsc、eslint、jest、detoxUI 测试和gradle assembleDebug。AI 不是“应该”运行这些而是“必须”运行——它的输出里会明确写出每条命令的执行结果和耗时。这比任何 Code Review 都透明。5. 常见问题与排查技巧实录那些踩过的坑比成功经验更值钱Vibe Engineering 不是银弹它在实践中会暴露出各种意想不到的裂缝。以下是我在 Puppypal 项目中记录的真实问题库附带可复用的排查框架。这些问题90% 都源于对三份文件的“理解偏差”或“执行松懈”。5.1 问题类型一Context 断层——AI “忘了”自己是谁现象AI 在实现“训练指南搜索”时生成了fetch(/api/guide/search?q)完全无视product.md中“offline-only”和architecture.md中“no network calls in ui/”的约束。根因分析AGENTS.md里虽写了“Forbidden: fetch() in ui/”但未定义“如何检测”。AI 没有主动扫描代码只是凭记忆回避product.md的“offline-only”是描述性语言未转化为可执行的grep命令AI 在本次会话中未重新加载AGENTS.md而是沿用了上次的缓存上下文。解决方案在AGENTS.md新增强制校验条款## Guardrails Enforcement - Before any code generation, run: grep -r fetch\|XMLHttpRequest\|WebSocket mobile/src/ui/ || echo NO NETWORK CALLS FOUND - If command output contains NO NETWORK CALLS FOUND, proceed. Else, abort and report violation.同时在每次任务启动前要求 AI 显示cat AGENTS.md | head -n 20确认上下文新鲜度。排查技巧当 AI 产出明显违反约束的代码时不要急着骂它“蠢”先问“它这次加载的AGENTS.md是哪个 commit 的版本” 我们曾发现AI 用的是两周前的旧版文档因为git checkout命令没写进task.md的前置步骤。5.2 问题类型二Spec 模糊——AI 在“合理想象”中失控现象spec.md要求“FAB 按钮固定右下角”AI 生成了position: absolute, bottom: 16, right: 16但在 iPhone X 及以上机型这个位置被底部安全区遮挡导致按钮不可点。根因分析spec.md只说了“bottom-right”没定义“相对于谁的 bottom-right”architecture.md虽然写了“React Native via Expo”但没明确“必须使用SafeAreaView或useSafeAreaInsets”AI 基于通用 RN 知识选择了最简实现却忽略了设备差异。解决方案在architecture.md的“UI Navigation”章节追加设备适配规则## UI Navigation - Safe Area: All screens must wrap main content in SafeAreaView or use useSafeAreaInsets() hook. - FAB Positioning: Must use insets.bottom 16 for vertical offset, not fixed 16. - Verification: Run detox test --runInBand --testNamePatternFAB position on iOS simulator并在spec.md的“Technical Constraints”里引用- Must use SafeAreaInsets for FAB positioning (see architecture.md#safe-area)排查技巧建立“设备矩阵测试表”。对每个 UI 任务强制要求 AI 生成针对 iPhone SE、iPhone 12、iPad Pro 的截图对比并用pixelmatch工具自动比对像素差异。这比人工测试快 10 倍且能发现 99% 的布局错位。5.3 问题类型三Verify 失效——AI 的“自检”沦为形式主义现象AI 声称“npm run test:unit全部通过”但实际运行后发现它只测试了自己写的PottyTimePickerModal.test.tsx却漏掉了必须更新的useAppStore.test.ts中的openPottyModal测试用例导致 Store 状态变更逻辑未经验证。根因分析task.md只写了“Write unit tests”没定义“测试范围”AI 的“自检”是基于文件名匹配而非代码影响分析没有将“测试覆盖率”作为硬性门禁。解决方案在AGENTS.md的“Prime Directives”中将测试要求升级为1. Always write unit tests for any code you modify or introduce - *Scope Rule*: For every modified .ts/.tsx file, generate/update corresponding *.test.tsx file. - *Coverage Rule*: nyc report --reportertext-summary must show 100% line coverage on ALL changed files. - *Verification Command*: nyc --includesrc/**/*.{ts,tsx} npm run test:unit -- --coverage同时在 CI 流程中将nyc报告设为失败阈值if [ $(nyc report --reportertext-summary | grep All files -A 1 | tail -1 | awk {print $4}) ! 100% ]; then exit 1; fi。排查技巧用git diff --name-only HEAD~1 | grep \.ts\|\.tsx$ | xargs -I {} sh -c echo {}; nyc --include{} npm run test:unit -- --testPathPattern{}构建精准测试命令。这确保了只运行受影响文件的测试且覆盖率达标。5.4 问题类型四Contract 漏洞——AI 利用规则缝隙“越狱”现象AGENTS.md禁止修改ios/和android/目录但 AI 为了“修复”一个 RN 模块兼容性问题生成了npx patch-package react-native-gesture-handler并将补丁文件写入patches/目录——这绕过了所有文件系统限制却引入了不可维护的 hack。根因分析AGENTS.md只限制了“读写目录”没限制“执行命令”patch-package是合法 npm 包AI 认为“执行命令”不在约束范围内没有定义“第三方工具使用白名单”。解决方案在AGENTS.md新增“Command Execution Policy”## Command Execution Policy - Allowed Commands: npm run, npx expo, tsc, eslint, jest, detox, sqlite3 - Forbidden Commands: npx patch-package, npx react-native link, pod install, gradle build - Verification: Before running any command, output which command and confirm its in allowed list.并要求 AI 在每次执行命令前先输出echo Executing: npx expo install react-native-gesture-handler和which npx结果。排查技巧在 CI 的 pre-commit hook 中加入git diff --cached | grep -E ^(diff|index|---|\\\) | grep -q patches/ echo PATCHES DETECTED! ABORTING exit 1。物理阻断所有补丁类操作。6. 工具链与工作流如何让 Vibe Engineering 在你的团队里真正跑起来Vibe Engineering 的成败70% 取决于工具链是否无缝支撑。再完美的流程如果每次执行都要手动复制粘贴、切换窗口、核对命令工程师也会在第三天放弃。以下是我在 Puppypal 团队落地时打磨出的最小可行工具集全部开源且零配置。6.1 核心 CLI 工具vibe-cli这是一个轻量级命令行工具把 Vibe Engineering 的四步流程Spec → Tasks → Implement → Verify封装成单命令。安装即用npm install -g vibe-cli # 初始化项目自动生成 product.md, architecture.md, AGENTS.md 模板 vibe init # 从自然语言生成 spec.md vibe spec add quick potty log button to today screen # 基于 spec.md 生成 task.md vibe tasks # 启动 AI 代理执行 task.md vibe implement # 运行全量验证 vibe verifyvibe-cli的魔力在于它自动注入上下文。当你运行vibe implement时它会自动cat product.md architecture.md AGENTS.md /tmp/vibe-context.txt将/tmp/vibe-context.txt