关于 why
why 是用于调查代码背后动机与约束的技能,与说明代码行为和实现方式的 how 技能互补。它引导研究者查看代码历史和可用证据来源,并区分发现、推断与未知事项。
主要功能
- 01以代码和提交历史为调查依据
- 02并行检索相关证据来源
- 03使用按来源类别划分的调查提示
- 04区分证据、推断和不确定性
- 05综合发现并列出查阅的来源
适用场景
- 01理解某种代码模式背后的原因
- 02追溯设计决策的历史
- 03调查防御性代码的成因
- 04找出可用证据中的缺口
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mariusflorescu/ pstack-t3 --skill why安装后在 Claude Code 中输入/why确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlreferences/epistemics.mdinvestigator-prompt.mdsource-playbook.mdsynthesizer-prompt.mdreferences/sources/code-archaeology.mddatabricks.mddatadog.mdincident-postmortem.mdlinear.mdnotion.mdsentry.mdslack.md详细介绍
原因
以粗体或反引号标出的技能名称,或以 /<name> 形式运行的技能,是此技能目录旁边的 ../<name>/SKILL.md 文件;不带前缀的原则名称对应 ../principle-<name>/SKILL.md。请阅读该文件并遵循其中的要求。大多数 pstack 技能仅供用户使用,因此你的技能工具无法加载它们。每次 delegate_task 调用都遵循 ../poteto-mode/SKILL.md 的 Subagents 部分中的默认设置。
调查代码背后的动机和意图。配套的 how 技能会说明代码的作用及其工作方式。why 则回答促使代码形成当前形态的各种因素。
下面每次派生都会创建一个 mode: "async" 的 delegate_task 子任务,并使用 ~/.config/pstack/pstack-models.md 中的一行角色配置。条目 <providerInstanceId>/<model> (<effort>) 会转换为 target: {"providerInstanceId": ..., "model": ..., "options": {"<effort option id>": "<effort>"}},其中 effort option id 是该模型的 orchestrator_capabilities 列表中的值。如果值为 auto 或 inherit-parent,或文件不存在、对应行缺失,则省略 target,让子任务使用父线程的模型。如果文件不存在,请说明并建议运行 /setup-pstack。如果 delegate_task 拒绝某个条目,则使用 orchestrator_capabilities 列出的同一提供商中最接近的模型,并说明这一点。根据 poteto-mode 技能的 Subagents 部分,为每个子 Agent 选择合适的推理级别以及快速或标准速度。子任务只能获得其简报中的内容,因此请将它需要的每个参考文件粘贴到简报中,或提供其绝对路径。派生任务后立即结束本轮,等待完成通知唤醒你。
每次派生都会继承运行时模式。**不要传入较弱的模式。**较弱模式会移除 MCP 访问权限,导致依赖 MCP 的调查工具不可用,也会禁用综合者的引用抽查。任何派生任务都不得写入内容,因此每份简报都必须注明只读:仅检查,不写入,不运行会改变状态的 git 命令。
工作准则
以谨慎、审慎且精确的调查者身份开展工作。坦诚区分已知事实与推断。阅读 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。按服务分组列出 MCP 工具,包括架构尚未加载、仅显示名称的工具。
将每个可用的 MCP 映射到以下一个证据类别:
- 源代码管理历史
- 问题/工单跟踪
- 长篇文档
- 实时团队聊天
- 基础设施可观测性
- 错误/异常跟踪
- 产品分析数据仓库
源代码管理始终可通过 git 和 gh 使用。对于其他六类,请根据 MCP 名称、服务说明、工具名称和资源描述进行分类。如果某个 MCP 可能属于多个类别,请选择与其主要证据最匹配的类别。请在覆盖图中记录有歧义的情况。
每个有匹配 MCP 的类别都启动一名调查员,并在同一轮中启动,让他们并发运行;每名调查员只负责一个工具或 MCP。不要让一名调查员负责多个 MCP。标题格式为 why investigator: <category>,其中 target 取自 why investigators 行。
每名调查员的提示词由填充完成的 references/investigator-prompt.md 以及以下内容组成:
- 所选 MCP 对应的类别手册
references/sources/<source>.md,根据references/source-playbook.md中的示例进行调整 - 如果目标代码看起来具有防御性(空值检查、重试逻辑、超时处理、速率限制、功能标志、出口防护、OOM 处理),则加入
references/sources/incident-postmortem.md - 代码锚点和用户的原始问题
调查员名册:每个可用证据类别各一名
以下每个类别都能独特地揭示一种“原因”,其特点见“最擅长”。请据此预判调查结果、在类别未返回结果时指出缺口,并且仅在极少数可明确证明与目标无关的情况下说明为何跳过。
- 源代码管理(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)。最擅长发现塑造代码的产品和数据实况。对于受功能标志控制的代码、由实验推动的发布、数据迁移,以及“这个数字从何而来”之类的问题,证据最有力。
何时跳过调查员
只有在有明确的书面理由,并将其写入最终的「查阅的来源」时,才能跳过。以下是两个有效理由:
- 在此环境中,该类别没有可用的 MCP。将其标记为缺口,而非选择:"跳过实时团队聊天。没有匹配的 MCP 可用,因此无法搜索对话记录。"
- 已证实该来源无关,而不只是「可能无关」。门槛要高:"跳过错误/异常跟踪。目标是一个构建时脚本,没有运行时代码路径。"
如果范围评估表明目标只是一个单次提交的简单改动,且 PR 描述已包含完整答案,你可以直接作答,但前提是先确认所有七类可用来源的搜索都属于多余操作。必须明确说明这一点。这种情况应该很少见。
第 4 步:综合
启动一个名为 why synthesizer 的综合器,其 target 取自 why synthesizer 行。向其提供:
- 调查员的发现,包括任何空结果,以及任何附有理由的跳过类别
- 代码锚点
- 用户的原始问题
references/epistemics.md中的认识论框架references/synthesizer-prompt.md中的综合器提示词模板
第 5 步:呈现
向用户呈现综合器的输出。你可以稍作编辑以提升清晰度,也可以补充对话中的背景信息,但不得改写置信度表述。
输出格式
结构以 references/synthesizer-prompt.md 中的要求为准:问题、相关代码、我们的发现、我们可以合理推断的内容、相互竞争的假设、我们不知道的内容、查阅的来源、置信度总结。可酌情调整,但必须保持置信度分级,并且「查阅的来源」中每位调查员占一行,包括没有返回结果或被跳过的调查员,并说明理由。
在「查阅的来源」之后,如果用户的 why 问题是修改此代码的前置问题,请将代码沿革的发现转化为一组用于规划修改的约束:保留/修改/避免/风险。
常见错误,务必避免
- 新近性偏差。不要认为最近的提交就最具权威性。当前形态往往是多次早期决策不断累积的结果。追溯源头。