关于 why
why 是面向开发者的代码调查技能,用于理解实现选择背后的动因。它指导从代码历史和可用的 MCP 来源收集证据,并区分事实、推断与未知之处。
主要功能
- 01调查设计动因
- 02结合代码与提交历史定位
- 03并行搜索可用证据来源
- 04区分调查结果与推断
- 05报告置信度和研究缺口
适用场景
- 01了解防御性检查或重试的缘由
- 02追溯某项设计决策的背景
- 03修改代码前审查历史依据
MCP 相关
该技能要求在可用时使用已连接的 MCP 服务,并将其分配到问题跟踪、团队聊天或可观测性等证据类别。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ backnotprop/ pstack --skill why安装后在 Claude Code 中输入/why确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/epistemics.mdinvestigator-prompt.mdsource-playbook.mdsynthesizer-prompt.mdreferences/sources/code-archaeology.mddatabricks.mddatadog.mdincident-postmortem.mdlinear.mdnotion.mdsentry.mdslack.md详细介绍
Why
探究代码背后的动机和意图。配套的 how 技能会说明代码的功能和工作方式;why 则会回答是什么因素促成了代码现在的形态。
下面每次启动都指定了 pstack 设置文件中的一个角色行(Cursor 中为 ~/.cursor/rules/pstack-models.mdc,Claude Code 中为 ~/.claude/rules/pstack-models.md,其他 harness 中为 ~/.agents/pstack-models.md)以及一个默认值。将 model 设为该行的值;如果文件或该行不存在,则使用默认值。如果值为 auto 或 inherit-parent,则不设置 model。如果你的子 Agent 工具不接受某个 slug,则使用默认值并说明。如果它不接受默认值,则从错误消息或你的 harness 的模型列表中,选择同一系列中最接近的有效 slug。根据 poteto-mode 技能的 Subagents 部分,为每项工作选择子 Agent 的推理级别以及快速或标准速度。
每次启动都使用 generalPurpose,并设为 readonly: false(Agent 模式)。不要使用 readonly/Ask 模式。 该模式会移除 MCP 访问权限,从而禁用基于 MCP 的调查器以及综合器的引用抽查。调查器仍不应写入任何内容。
工作姿态
以谨慎、审慎且严谨的调查者姿态开展工作。诚实区分已知事实与推断内容。完整的置信度框架和措辞指南请参阅 references/epistemics.md。综合器必须遵循该指南。
步骤 1:了解目标和问题
目标通常是一段代码、一种模式、一个功能或一项明确命名的设计决策。问题通常涉及设计理由、权衡、促成因素、外部约束、死代码或广泛的历史调查。
如果目标含糊不清(例如“我们为什么这样做?”但没有明确指向),请根据对话上下文尽力判断(打开的文件、最近的编辑、光标位置、刚刚讨论的内容)。简要说明你的理解,以便用户发现偏差时能及时纠正,然后继续。
步骤 2:确定代码锚点
启动调查器之前,先在当前上下文中整理种子信息:文件路径和行范围、关键符号(函数、类、常量)、涉及目标的最近几次提交、合并提交中的 PR 编号(主题行中符合 (#1234) 模式),以及任何关联的工单 ID。针对最后修改的提交运行 git blame -L <start>,<end> <file>;通过 git log --follow -p -- <file> 查看完整历史和补丁(包括重命名);通过 git log --oneline -20 -- <file> 查看近期提交(确保 PR 编号可见);通过 git log -1 --format=%B <commit> 提取 PR 编号。然后拉取所有实质性提交对应 PR 的正文和讨论:gh pr view <number> --json title,body,author,createdAt,mergedAt,labels,closingIssuesReferences,comments,reviews。将这些锚点信息提供给每位调查器和综合器。
步骤 3:并行启动调查器
默认执行完整的并行调查。 目标是全面覆盖,而不是尽量精简。请记录未发现结果的情况,不要跳过搜索。
发现
启动调查员之前,先列出连接到你的执行环境的 MCP 服务。若有可用工具映射,请使用该映射。在 Cursor 中,你也可以检查它公开的 mcps/ 目录,查看已启用的 MCP 服务。在其他执行环境中,MCP 工具通常会显示在工具列表中,工具名称会包含服务名称(例如 Claude Code 中的 mcp__<server>__<tool>)。
将每个可用的 MCP 映射到一个证据类别:
- 源代码管理历史
- 问题/工单跟踪器
- 长篇文档
- 实时团队聊天
- 基础设施可观测性
- 错误/异常跟踪
- 产品分析数据仓库
源代码管理始终可通过 git 和 gh 使用。对于其他六类,请根据 MCP 名称、服务说明、工具名称和资源描述进行分类。如果某个 MCP 可能属于多个类别,请选择与其主要证据相符的类别。将有歧义的情况记录在覆盖范围映射中。
对于每个有匹配 MCP 的类别,各启动一名调查员;在一条消息中启动所有调查员,使其并发运行,并让每名调查员恰好负责一个工具或 MCP。model:使用 why investigators 行中的模型,默认为 grok-4.7-xhigh-fast。
每名调查员的提示词为填入内容后的 references/investigator-prompt.md,并附上:
- 所选 MCP 对应的类别手册
references/sources/<source>.md,根据references/source-playbook.md中的示例进行调整 - 如果目标代码看起来具有防御性(空值检查、重试逻辑、超时处理、速率限制、功能标志、出口防护、OOM 处理),则附上
references/sources/incident-postmortem.md - 代码锚点和用户的原始问题
其他执行环境。 本技能中的启动操作使用 Cursor 的 Task 工具。在其他执行环境中,请使用其子 Agent 工具:Claude Code 中的 Agent(subagent_type: general-purpose)、OpenCode 中的 task(subagent_type: general)、Codex 中的 spawn_agent。保留提示词和模型。省略工具不支持的参数。如果你的执行环境没有子 Agent 工具(例如未安装扩展的 Pi),则自行依次运行每名调查员。
调查员名单:每个可用证据类别各一名
以下每个类别都有独特优势,能够揭示一种“为什么”,具体见“最擅长”。根据这些信息判断预期结果;如果某个类别没有返回结果,可据此指出信息缺口;只有在极少数、确实能证明某类别无关的情况下,才可据此说明跳过理由。
- 源代码管理(git 历史、用于 PR 的
gh、代码注释、测试)。始终启动,这是唯一有保障的信息来源。最擅长发现评审过程中记录的实现时理由。 - 问题/工单跟踪器(例如 Linear、Jira、GitHub Issues、Plane、Shortcut MCP)。最擅长发现产品或业务方面的驱动因素。当“为什么”源于工程之外时,尤其有用。
- 长篇文档(例如 Notion、Confluence、Google Docs、Coda MCP)。最擅长发现在实现为代码之前写下的长篇设计理由。
- 实时团队聊天(例如 Slack、Discord、Microsoft Teams、Mattermost MCP)。最擅长发现未曾写入文档的实时讨论。尤其在源代码管理、工单和文档记录稀少时重要。
- 基础设施可观测性(例如 Datadog、New Relic、Honeycomb、Grafana、Splunk MCP)。最擅长发现促使代码改动的基础设施和运行时实际情况。当目标代码会响应基础设施信号(超时、重试、速率限制、断路器)时尤其有用。
- 错误/异常跟踪(例如 Sentry、Rollbar、Bugsnag、Airbrake MCP)。最擅长发现促使编写防御性或修正性代码的具体异常及错误轨迹。对于 catch 代码块、空值保护、类型检查、重试及其他防御措施尤其有用。
- 产品分析数据仓库(例如 Databricks、Snowflake、BigQuery、ClickHouse、dbt、Redshift MCP)。最擅长发现影响代码的产品和数据实际情况。对于由功能标志控制的代码、基于实验的发布、数据迁移,以及“这个数字从何而来”之类的问题尤其有用。
何时跳过调查者
只有在最终的 Sources Consulted 中提供明确的书面理由时才能跳过。以下是两个有效理由:
- 此环境中没有适用于该类别的 MCP。应将其标记为缺口,而非选择:“跳过实时团队聊天。没有匹配的 MCP 可用,因此无法搜索对话记录。”
- 已证实该来源无关,而非“可能无关”。标准很高:“跳过错误/异常跟踪。目标是一个构建时脚本,不存在运行时代码路径。”
如果范围评估表明目标只是一个单提交的简单目标,且 PR 描述已包含完整答案,那么只有在确认所有七类可用搜索都属于冗余之后,才可以直接回答。请明确说明这一点。这种情况应当很少见。
第 4 步:综合
启动一位综合者。model:why synthesizer 行中的值,默认为 claude-opus-5-5-xhigh。向其提供:
- 调查者的发现,包括任何空结果,以及有理由跳过的类别
- 代码锚点
- 用户的原始问题
references/epistemics.md中的认识论框架references/synthesizer-prompt.md中的综合者提示词模板
第 5 步:呈现
向用户呈现综合者的输出。可以为清晰起见稍作编辑,或补充对话中的背景信息,但不要改写置信度措辞。
输出格式
结构应遵循 references/synthesizer-prompt.md:问题、相关代码、我们的发现、我们可以合理推断的内容、相互竞争的假设、我们不知道的内容、Sources Consulted、置信度摘要。可酌情调整,但必须保持置信度层次清晰;Sources Consulted 中每位调查者占一行,包括没有返回结果或被跳过的调查者,并注明原因。
如果用户的 why 问题是修改此代码的前置步骤,则在 Sources Consulted 之后,将代码沿革发现转化为用于规划修改的 Preserve / Change / Avoid / Risk 约束集。
常见失败模式
- 近因偏差。假定最近的提交最具权威性。当前代码形态往往是许多早期决策逐渐累积的结果。应追溯其沿革。