关于 product-thinking
Product Thinking 是一份运行手册,用于在实现前评估开发者或 CI 使用的 React Doctor 产品界面变更。它指导范围、复用、指标、兼容性、文档和检查,并要求将简报纳入 PR。
主要功能
- 01明确用户任务与最小改动
- 02查找可复用的现有界面
- 03设定成功指标与阈值
- 04规划默认值和兼容性材料
- 05更新文档并运行检查
- 06记录移除未使用界面的指标
适用场景
- 01评估 CLI 标志或配置选项提案
- 02规划报告或 API 变更的兼容性
- 03判断用户可见变更是否值得实现
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ millionco/ react-doctor --skill product-thinking安装后在 Claude Code 中输入/product-thinking确认已加载。
详细介绍
产品思维
一份用于变更用户交互内容的操作手册。Agent 默认会完全按照要求实现;这一轮会补上它跳过的产品检查——这项变更是否值得永久保留在界面上,以及如何判断它是否奏效。编码前先完成这些步骤,边做边填写简报,并将简报纳入 PR。如果变更缺乏依据,就用它提出异议,而不只是照单全收。
何时执行
只要差异涉及用户所依赖的界面,就执行这轮检查;用户可以是运行 React Doctor 的开发者,也可以是他们的 CI。每个界面都是一份契约:一旦发布,人们就会基于它构建,你不能悄无声息地撤回。先找到界面所在的位置,这样你才能修改正确的位置,并在添加内容前搜索是否有可复用的内容。
| 界面 | 所在位置 | 为何至关重要 |
|---|---|---|
| CLI 命令 / 标志 | cli/index.ts、cli/commands/*.ts、cli/utils/inspect-flags.ts | 每个标志都将长期存在——必须解析、记录、测试,并确保在各个版本中持续可用。 |
| 0–100 分数 | core/src/calculate-score.ts、core/src/constants.ts | 这是人们截图并用于 CI 门禁的数字;悄悄更改计算方式会改变每位用户的分数。 |
| 配置选项 | core/src/types/config.ts、core/src/services/config.ts | 这是一份长期契约,会与现有的优先级规则交互;新增的配置项日后很少能移除。 |
| JSON 报告字段 | core/src/schemas.ts、core/src/build-json-report.ts | 这是其他工具会解析的线上格式;除非妥善处理 schemaVersion,否则结构变更会破坏集成。 |
| 包 API / 退出码 | react-doctor/src/inspect.ts、api/src/diagnose.ts | 程序化使用者会固定依赖这些内容,因此变更会破坏语义化版本兼容性,需要提供 changeset。 |
| GitHub Action 输入 / 输出 | action.yml | 版本独立管理(vN);输入或输出变更会导致其他仓库中的工作流出错。 |
| 终端输出 / 用户体验 | cli/utils/ 渲染器 | 这是用户的第一印象和日常体验;这里的噪声或困惑会让人不再运行它。 |
不适用: lint 规则走 rule-research → rule-writing → rule-validate 流程,规则配置则走 doctor-explain——这轮检查针对的是规则_周边_的界面,而不是规则本身。仅限内部的变更(引擎、私有 core 类型、测试、工具)完全跳过这轮检查;用一句话说明该变更属于内部内容,然后继续。
步骤
- [ ] 1. Write the job + the change (2 lines)
- [ ] 2. Search for a reuse candidate; extend it or justify new surface
- [ ] 3. Wire exactly one metric
- [ ] 4. Pick the default + add the compatibility artifacts
- [ ] 5. Update docs
- [ ] 6. Record the kill metric
- [ ] 7. Run checks
1. 写明任务和改动
首先写下两行,为后续每一步奠定基础:
- 任务 — 谁在运行 React Doctor,他们实际想完成什么,以及他们今天用什么方式替代(现有标志或配置选项、其他工具,或什么都不用)。任务应以你观察到的行为为依据,而不是以某人声称自己假设会想要什么为依据。
- 改动 — 完成该任务所需的最小改动范围。如果改动超出了任务范围,你就是在进行推测性开发。
如果你说不出当前功能范围尚无法满足的任务,就停下来——没有什么需要构建,正确的做法是告诉用户如何用现有方式完成。
在决定构建之前,先通过以下两个筛选条件:
- 持久性 — 随着模型越来越擅长 React(或目标框架),这项功能还会有价值吗?模型会逐渐掌握的能力,或很容易被商品化的能力,不值得永久占据功能范围。把功能范围留给持久、确定的价值。
- 信任 — 用户不信任的功能比没有功能更糟,因为它会让用户学会忽略这个工具。如果改动可能产生误报,或无法用证据支持其建议,就先解决信任问题;发布一个“基本正确”的功能会损害整个产品。
2. 添加前先搜索
复用永远优于添加——最精简的功能范围,就是你从未创建的那部分。在添加标志、选项或报告字段之前,先搜索是否已有可扩展的内容:
bunx @rayhanadev/truffler "<name or behavior>" packages --kind function,interface,type,constant --limit 20
rg -n "<flag-or-option-name>" packages/react-doctor/src/cli packages/core/src/types
开始编写前,先阅读最相关的搜索结果。如果现有功能几乎能完成相同的任务,就扩展它——为现有标志添加一个新值,为现有配置对象添加一个新字段,或为已有输出添加一列。只有当任务确实不同,且现有条目无法承载而不致造成混淆时,才新增功能。如果确实新增了,请在简报中记录你搜索了什么,以及为什么没有合适的选项,这样后续接手的人就能继承你的判断,而不必重新争论一遍。
3. 恰好接入一个指标
看不到的功能就无法管理,因此只有在改动发出信号后,才算完成。构建前先确定这个信号——如果你无法描述哪个数字会发生变化,就说明你还不知道成功意味着什么。CLI 遥测使用匿名化的 Sentry,且对于 @react-doctor/api 库、测试和 --no-score 已经是空操作,因此你只需接入发送逻辑:
- 采用次数 — 有人在用吗?在
cli/utils/constants.ts的METRIC映射中添加一个名称,并通过cli/utils/record-metric.ts发送。用于衡量“有多少人启用了这个标志”。 - 单次扫描结果 — 本次运行发生了什么?在
cli/utils/build-run-event.ts的宽事件中添加一个属性(运行级维度则添加到cli/utils/build-sentry-scope.ts)。优先使用一个信息丰富的宽事件属性,而不是堆叠许多狭窄的计数器——这样无需新增代码,事后仍可查询。
匿名化是不可妥协的:属性中绝不能包含用户名、路径、机密信息或仓库身份——所有数据都必须经过 scrubSentryEvent / scrubSentryMetric。然后将指标名称和代表“已奏效”的阈值写入简报。
衡量成效的北极星:唯一持久的指标是 CI 队列留存率——团队几周后还会继续在 CI 中运行 React Doctor 吗?其他大多数数字都只是虚荣指标。要判断用户是“喜爱”这项功能,而不只是“使用”它,可以参考 PMF 调查中的代理指标:如果功能消失,评分为“非常失望”的用户占比是否达到 ≥40%。
4. 选择默认值并添加兼容性产物
默认值是产品决策,而非实现细节——大多数用户从不更改它,因此对几乎所有人来说,默认值_就是_实际行为。选择一个能保留当前行为的默认值,并将有风险的选项设为可选。然后发布兼容性产物,避免现有用户受到影响:
- 已发布软件包的行为发生变化 → 添加 changeset(
nr changeset),以便为此变更生成版本并写入变更日志。 - JSON 报告的结构发生变化 → 编辑
core/src/schemas.ts,保留现有结构或递增schemaVersion,然后运行nr smoke:json-report。CI 流水线会解析此输出,因此未经通知的结构变更会导致它们悄然出错。 - 分数权重或算法发生变化 → 每位用户的分数都会同时变化,按阈值设置的 CI 门禁也可能改变结果。将其视为破坏性变更:添加 changeset,并明确说明这一变化。
action.yml发生变化 → 创建vX.Y.Z标签并移动浮动标签vN,因为其他仓库固定使用主版本标签,否则无法收到此变更。
5. 更新文档
没人能发现的功能就等于浪费,过时的文档则会损害信任。文档属于“完成”的一部分,而不是后续工作:
- 在新标志或命令旁补充
--help/ 用法文本,以便用户能直接从 CLI 中发现它。 - 更新网站页面和
react.doctor/prompts/...下的规范提示词,Agent 会在运行时获取此提示词。 - 如果变更会影响面向用户的工作流,则更新分发的技能(
skills/react-doctor、skills/doctor-explain)。
6. 记录淘汰指标
功能面会不断累积:每个无人使用的标志和无用的配置键都会成为永久的维护负担,也会多一个让用户误解的地方。提前决定如何判断这项功能是否值得保留。在简要说明中写一行——包含第 3 步中的指标、阈值和观察期限,例如:“如果 <metric> 在 2 次发布后仍低于 N,就移除”。安排检查时间,而不是指望自己记得;删除无人使用的功能面应视为成果,而非承认失败。
7. 运行检查
nr typecheck && nr test && nr lint
nr smoke:json-report # only if you touched the JSON report
简要说明
在执行这些步骤时填写此内容;将其纳入 PR 的“原因”部分。
## Product brief: <change>
Job: <who / goal / what they do today>
Change: <smallest surface that does it>
Reuse: <what you searched; what you extended, or why new surface was needed>
Metric: <METRIC name or wide-event attribute + the number that means success>
Compat: <default state; changeset / schemaVersion / action tag>
Kill: <metric threshold + horizon that triggers removal>
以下情况请暂停并询问
遇到以下情况时,应先提出决策,而不是继续推进——每一种都表明此变更需要人工判断:
- 你无法说出当前功能面无法完成的任务 → 提议复用现有功能或移除此功能,而不是增加新的功能面。
- 你无法为此定义指标 → 添加相应的检测机制,或重新考虑此变更是否确有必要。
- 此变更会破坏已发布的契约(软件包行为、JSON
schemaVersion、分数或 action I/O)→ 合并前确认 changeset、版本递增和迁移路径。 - 此变更会将范围扩大到请求内容之外 → 扩大范围前取得明确同意。
检查通过后,使用 ship(deslop、changeset、PR、babysit)来提交此变更。
产品原则(React Doctor)
当某个步骤存在歧义时,用以下原则作出取舍——如果两个选项看起来都不错,就优先选择符合这些原则的选项:
- 少报问题 > 多报问题。 开发者会实际处理的十个问题,胜过他们一眼扫过的一百个;应限制数量并排序,而不是一股脑全部列出。
- 根本原因 > 单条警告。 将同一根本问题引发的各种症状合并为一个发现,而不是把每个回响都单独报告。
- 证据 > 断言。 展示依据——代码、测量结果、原因——而不是让用户相信工具的一面之词。
- 可执行性 > 正确性。 有明确后续步骤、可以修复的问题,胜过技术上完美却让人无从下手的发现。
- 工作流 > 仪表板。 融入开发者已有的工作方式——CLI、PR、编辑器——而不是让他们转到另一个界面。
- 教育 > 诊断。 解释某件事_为什么_是个问题,让用户有所收获,而不只是告诉他们_它_是个问题。
- 信任 > 检测覆盖率。 最好的发现是用户相信并会采取行动的发现;一次误报损失的信任,远比漏掉一个问题造成的覆盖率损失更大。