winson-requirement-to-delivery-loop
从需求到交付成功的项目级闭环技能
一、核心哲学(必读)
1.1 唯一铁律
> 围绕核心目标锚定优先级,把每一分算力都投在"能否让用户验收通过"这一件事上。
不是"代码写完",不是"功能跑通",不是"页面好看"——这些都只是交付的必要条件。真正的交付是:用户能完整使用、关键路径全打通、失败不丢数据。
1.2 三个底层认知
| 认知 | 说明 |
|---|---|
| 核心目标是北极星 | 没有锚定的开发会陷入"修了 A 发现 B 也没接"的无底洞。第一步必须明确"这个项目/这次迭代要让用户能用哪些核心路径" |
| 逆向工程是反熵增的利器 | 需求方给的描述永远不完整。用"系统化扫描+逆推功能意图"补全缺失,比追问更高效 |
| 沉淀比交付更值钱 | 每完成一次交付,把踩坑、可复用模式、决策逻辑写入 MEMORY/CHANGELOG。下次遇到类似问题,3 步内定位 |
1.3 六阶段闭环公式
理解需求(明确核心目标 + 关键路径)
→ 拆解任务(按交互元素类别分类,而非按页面)
→ 开发实施(同一类型问题并行处理)
→ 验证质量(语法 + 引用 + 端到端)
→ 交付上线(用户视角验收清单)
→ 复盘沉淀(踩坑入坑库,模式入复用库)
→ 循环:下一个需求进来时,从 MEMORY 优先读取
1.4 四道闸门(防止"交付了但不可用")
| 闸门 | 检验内容 | 失败信号 |
|---|---|---|
| 目标闸门 | 这次开发是不是冲着核心目标去的? | 开始做一些"看起来有用但与核心目标无关"的功能 |
| 风险闸门 | 关键路径上的失败点有没有被预演过? | 用户在使用过程中会遇到"点击没反应""数据没保存""页面 404" |
| 质量闸门 | 语法/引用/边界条件有没有检查? | 出现 ReferenceError、undefined function、null pointer |
| 验收闸门 | 用户视角能完整跑通关键路径吗? | 交付后用户问"这个按钮怎么用" |
二、完整执行流程
Phase 1:理解需求(Requirement Understanding)
Step 1.1:明确核心目标
做什么:用一句话回答"这次要让用户能完成什么"。
为什么重要:所有后续决策都要回溯到这一句话。任何偏离核心目标的工作都是浪费算力。
检验标准:
- [ ] 能用一句话(不超过 30 字)说清核心目标
- [ ] 能列出 3-5 条关键路径(用户从进入到完成核心目标会经过哪些步骤)
- [ ] 关键路径上有明确的"完成标志"(数据已保存 / 页面已跳转 / 状态已变更)
反例:
- ❌ "做一个功能医学管理系统"(太抽象)
- ✅ "让医生能录入客户档案、查看客户详情、给客户建健康计划,并能在管理后台看到所有数据"
Step 1.2:识别隐含需求
做什么:用 5W1H 主动补充需求方没说的内容。
| 维度 | 要回答 |
|---|---|
| Who | 谁会使用?角色是什么?(医生/患者/管理员) |
| What | 关键功能是否完整?是否有"必然存在但没说"的功能?(搜索/筛选/排序/分页/导入/导出) |
| When | 是否有时间约束?是否需要倒计时/截止日期/历史记录? |
| Where | 数据存在哪?localStorage / 接口 / 文件? |
| Why | 用户为什么用这个?解决什么痛点? |
| How | 失败时如何处理?空数据如何展示? |
检验标准:能列出至少 5 条需求方没明说但必须实现的功能。
Step 1.3:定义"完成"的边界
做什么:和需求方对齐"什么是做完",避免无限循环。
模板:
本次迭代完成 =
✅ 关键路径 1: [用户路径 + 完成标志]
✅ 关键路径 2: [...]
✅ 关键路径 3: [...]
✅ 数据持久化: [数据存哪、怎么读出来]
✅ 异常处理: [失败时用户看到什么]
⏸️ 不在本次范围: [明确说"不做"的事项]
Phase 2:拆解任务(Task Decomposition)
Step 2.1:按"交互元素类别"分类,不按页面分类
反例(按页面拆):
P1: 仪表盘页面
P2: 客户列表页面
P3: 客户详情页面
P4: 计划页面
...
问题:按页面拆会让你陷入"做完仪表盘去做客户"的串行模式。但其实"按钮没接事件"这种问题在每个页面都存在,应该一次性扫完。
正例(按交互类别拆):
P1: 全局导航(侧边栏 + 顶部栏 + Logo + 头像 + 主题切换 + 锁屏)
P2: 数据列表(客户/计划/模板/知识库 × 搜索 + 筛选 + 分页 + 行点击)
P3: 详情页(标签页 + 内嵌统计 + 关联跳转 + 编辑/删除按钮)
P4: 模态弹窗(新增/编辑/确认/详情查看)
P5: 装饰性交互(标签点击筛选、性别条筛选、趋势图、徽章)
P6: 数据持久化 + 异常处理
P7: 验收清单(用户视角的端到端测试)
优势:同类问题一次性扫完,并行处理,效率高 3-5 倍。
Step 2.2:建立任务依赖图
做什么:识别"必须先做"和"可以并行做"的任务。
模板:
[必须先做]
- 数据模型定义(影响所有页面)
- 路由/页面切换(影响所有跳转)
[可以并行做]
- 各页面的渲染函数
- 各模态的打开/保存函数
- 各种工具函数(脱敏、格式化、ID生成)
Step 2.3:每条任务写"完成标志"
模板:
任务:[描述]
完成标志:
- 函数/文件存在
- 在 X 场景下点击会触发 Y
- Y 完成时会更新 Z 状态
- Z 状态会持久化到 W 存储
反例:
- ❌ "做一下客户编辑"
- ✅ "做一下客户编辑:openClientModal(id) 打开模态、saveClient() 校验后更新 STATE.clients、Store.save() 持久化、renderClients() 重新渲染列表、添加 auditLog('update', 'client', id, name)"
Phase 3:开发实施(Implementation)
Step 3.1:先搭骨架,再填细节
顺序:
1. 数据模型 + Store(先有数据容器)
2. 路由/页面切换(先有页面跳转)
3. 列表渲染(先有数据展示)
4. 详情页 + 模态(先有数据编辑)
5. 关联/跳转(先有导航)
6. 装饰性交互(最后打磨)
为什么:骨架不通,所有细节都是空中楼阁。先跑通"只读"路径,再加"写"。
Step 3.2:每写完一个函数,立即自我验证
验证清单:
- [ ] 语法正确(node --check 或 IDE 红色波浪线)
- [ ] 引用的函数/变量都存在
- [ ] 边界条件处理(空数据/null/undefined/数组越界)
- [ ] 异常路径(用户输入错误时不会崩)
反模式:
- ❌ 写完 10 个函数一起测(一次崩在第 7 个,前 6 个白写)
- ✅ 写完 1 个就测 1 个
Step 3.3:发现 bug 立即修,不要攒
为什么:bug 会传染。一个未修的 bug 会让后续代码基于错误假设,导致更多 bug。
模板:
发现 bug
→ 立即定位(不要"先标记,稍后看")
→ 立即修复(不要"等修大功能时一起改")
→ 立即验证(修完就跑一遍相关路径)
→ 立即记录(写入 MEMORY 的踩坑区)
Step 3.4:双保险原则
适用场景:关键交互元素(导航、提交、删除、锁屏)
做法:同时用 addEventListener + onclick 直接绑定
<button id="themeToggle" onclick="toggleTheme()">切换主题</button>
// bindFilters 内部
const btn = $('#themeToggle');
if(btn) btn.addEventListener('click', toggleTheme);
为什么:DOMContentLoaded 之前的事件不会触发,addEventListener 失败的话 onclick 兜底。
Phase 4:验证质量(Quality Verification)
Step 4.1:语法检查(第一道关卡)
HTML 单文件项目:
# 提取 script 标签内容并检查语法
node -e "const fs=require('fs');const html=fs.readFileSync('index.html','utf8');const m=html.match(/<script>([\s\S]*?)<\/script>/);if(m){try{new Function(m[1]);console.log('OK');}catch(e){console.log('ERROR:',e.message);}}"
多文件项目:
# 后端
node --check server.js
# 前端构建
npm run build
# 类型检查
tsc --noEmit
Step 4.2:引用完整性检查(第二道关卡)
做什么:扫描所有 onclick / addEventListener / 模板字符串中引用的函数,确保它们都存在。
方法 1:人工扫描(小项目)
# 提取所有 onclick 中的函数名
grep -oE 'onclick="[a-zA-Z_]+\(' file.html
# 提取所有函数定义
grep -oE 'function [a-zA-Z_]+' file.html
# 对比是否一致
方法 2:静态分析(大项目)
- 用 ESLint 的 no-undef 规则
- 用 TypeScript 编译器
- 用 IDE 的"查找引用"功能
反模式:
- ❌ openClientModal(btn.dataset.id) 用了 btn 但实际变量名是 act(ReferenceError)
Step 4.3:端到端检查(第三道关卡,最重要)
用户视角验收清单(按关键路径):
| 路径 | 操作序列 | 预期结果 |
|---|---|---|
| 录入客户 | 点"新增客户" → 填表 → 保存 | 列表多一条、刷新不丢、可编辑可删除 |
| 查看详情 | 点客户行 → 看详情 | 显示该客户的所有数据 |
| 建计划 | 进详情 → 点"+ 计划" → 选客户 → 填表 → 保存 | 计划列表多一条、关联到客户 |
| 切换主题 | 点主题按钮 | 全站颜色变化、刷新保持 |
| 数据导出 | 点"导出" | 下载 JSON 文件、文件可读 |
反模式:
- ❌ "代码写完"就认为"功能完成"
- ✅ "用户能跑通关键路径"才是完成
Step 4.4:边界条件检查
必查清单:
- [ ] 空数据(首次进入、删完所有数据)
- [ ] 极端输入(超长字符串、特殊字符、单引号、emoji)
- [ ] 重复操作(连续点 5 次保存)
- [ ] 刷新页面(数据是否还在)
- [ ] 切换页面后回来(状态是否丢失)
- [ ] 并发操作(编辑未保存就关闭)
Phase 5:交付上线(Delivery)
Step 5.1:交付前自查清单
- [ ] 所有需求方明确要求的功能都已实现
- [ ] 关键路径用户能跑通
- [ ] 数据持久化(刷新/重启不丢)
- [ ] 异常路径有友好提示(不是红色报错)
- [ ] 没有遗留的 console.error
- [ ] 没有 TODO/FIXME 注释
- [ ] 文档已更新(README、MEMORY)
Step 5.2:交付物清单
给用户:
- 可运行的代码(包/可执行文件/在线链接)
- 用户使用手册(如有需要)
- 已知问题清单(避免后期扯皮)
给自己:
- MEMORY.md(踩坑 + 模式 + 决策)
- CHANGELOG.md(按时间记录变更)
- 测试用例(如有)
Step 5.3:交付话术模板
✅ 已完成 [核心目标]:
1. [关键功能 1] - 测试方式:XXX
2. [关键功能 2] - 测试方式:XXX
3. [关键功能 3] - 测试方式:XXX
📋 数据已持久化到 [位置],刷新不丢。
⚠️ 已知限制:[如"目前不支持导入历史数据"]
🔄 下次可继续:[如"可加用户权限管理"]
Phase 6:复盘沉淀(Retrospective)
Step 6.1:必做的 3 件事
1. 踩坑入坑库
## 踩坑记录
- **编辑按钮 ReferenceError** → 事件委托中用 `btn` 变量但实际是 `act` → 改用解构后的 `id/idx`
- **性别筛选无效** → 传 'male' 但 select value 是 '男' → 加值映射
2. 模式入复用库
## 可复用模式
### 双保险事件绑定
- 关键交互元素同时用 addEventListener + onclick
- 适用:导航、提交、删除、锁屏
### 编辑模式 XXX_EDIT_IDX
- -1 = 新增, >=0 = 编辑
- 适用:同一模态支持增改
3. 决策入决策库
## 决策记录
- **为什么用 localStorage 不用后端** → 单文件项目、无需多端同步
- **为什么用 onclick + addEventListener 双保险** → addEventListener 在某些边界场景不触发
Step 6.2:识别"这次值得升级到 SKILL 的部分"
什么值得沉淀为技能:
- 跨 3 个项目都用得上的方法论
- 踩过 2 次以上的坑
- 有清晰输入输出的操作流程
- 别人也能照着做的步骤
什么不值得:
- 一次性的项目特定配置
- 偶然出现的特殊 bug
- 个人习惯
Step 6.3:循环触发
下次接到类似需求时:
1. 优先读 MEMORY:看有没有相关踩坑和模式
2. 套用六阶段:理解→拆解→开发→验证→交付→复盘
3. 新踩坑再入库:滚动累积 MEMORY
三、常见陷阱与避坑指南
| 陷阱 | 表现 | 后果 | 修正 |
|---|---|---|---|
| 目标漂移陷阱 | 做着做着去优化一些"看起来有用"的功能 | 算力分散,核心目标没完成 | 每 30 分钟回溯核心目标,偏离就停下 |
| 页面陷阱 | 按页面顺序开发,做完 A 再做 B | 同一类问题在不同页面反复出现 | 按交互类别扫,一次性处理同类 |
| 语法自信陷阱 | 写完不检查语法,运行时才发现 | 整个应用崩在第一行 | 写完每个函数就 node --check |
| 引用自信陷阱 | 复制粘贴时不改变量名 | ReferenceError | 引用完整性扫描(Phase 4 Step 2) |
| 完成错觉陷阱 | "代码写完"="功能完成" | 用户用不起来 | 端到端验收(Phase 4 Step 3) |
| 知识流失陷阱 | 做完不写 MEMORY | 下次踩同样的坑 | 强制把沉淀作为交付的一部分 |
| 无限循环陷阱 | "再做一点就更好" | 永远交付不了 | Phase 1 Step 3 定义"完成"边界 |
| 确认瘫痪陷阱 | 每步都问用户 | 用户没耐心 | 零确认执行,最后统一验收 |
四、场景适配指南
| 场景 | 重点强调的 Phase | 关键调整 |
|---|---|---|
| 从 0 到 1 的新项目 | Phase 1 + Phase 2 | 多花时间在核心目标定义和任务分类 |
| 已有项目补全功能 | Phase 2 + Phase 3 | 先扫"哪些交互元素没接",按类别批量修 |
| 紧急 bug 修复 | Phase 3 Step 3 + Phase 4 | 立即定位→立即修→立即验→立即记 |
| 多人协作项目 | Phase 2 + Phase 5 | 任务依赖图清晰,交付物有明确边界 |
| 个人/副业项目 | 全部六阶段,简化 | 一个人 = 同时是产品/开发/QA,靠 SKILL 自我约束 |
| AI 协作项目(当前主流) | 全部六阶段 | MEMORY 是 AI 的工作记忆,必须持续更新 |
五、质量检验清单
完成一次交付前,逐项检查:
- [ ] 核心目标能用一句话说清?
- [ ] 关键路径有 3-5 条且都有完成标志?
- [ ] 任务按"交互类别"而非"页面"分类?
- [ ] 每条任务有明确的完成标志?
- [ ] 骨架先跑通(只读路径)再填细节?
- [ ] 写完每个函数就自测?
- [ ] 关键交互有双保险绑定?
- [ ]
node --check语法通过? - [ ] onclick 引用完整性扫描通过?
- [ ] 端到端关键路径用户能跑通?
- [ ] 边界条件(空/极端/刷新)已测?
- [ ] MEMORY 踩坑 + 模式 + 决策都更新了?
- [ ] 交付话术清楚说明"测试方式"?
六、执行原则
- 目标锚定 > 完美主义:每 30 分钟回溯核心目标,偏离就停。
- 分类 > 顺序:按交互类别扫,比按页面顺序快 3-5 倍。
- 自测 > 联调:每个函数写完就测,bug 越早发现成本越低。
- 端到端 > 单元完美:用户能跑通 = 完,单元测试 100% 但用户卡在登录 = 没完。
- 沉淀 > 交付:MEMORY 是下次省力的本金,不写就等于白踩坑。
- 零确认 > 反复确认:AI 时代,独立判断是核心竞争力,每步问用户会拖垮效率。
- 完成边界 > 完美边界:明确说"这次不做"比"无限延展"更专业。
七、与 self-evolving-loop 的关系
| 维度 | winson-requirement-to-delivery-loop | self-evolving-loop |
|---|---|---|
| 视角 | 项目级(单次交付) | AI 级(持续协作) |
| 时间盒 | 有明确起点和终点 | 无限循环 |
| 输出 | 可交付的产品 | 持续改进的产品 + 不断丰富的 MEMORY |
| 适用 | 接到需求→做出能用的东西 | 长期陪伴一个项目的所有迭代 |
| 关系 | self-evolving-loop 的"单次循环" | winson-requirement-to-delivery-loop 的"持续化" |
何时用哪个:
- 接新需求 / 启动新项目 → 用 winson-requirement-to-delivery-loop
- 项目长期迭代 / AI 持续协作 → 用 self-evolving-loop
- 实际场景:两者嵌套使用,每次需求用本 SKILL,每次迭代用 self-evolving-loop