关于 why
面向 Agent 的代码调查技能,追溯设计背后的动机与约束,并补充说明代码实现方式的 `how` 技能。它强调谨慎搜集证据、并行调查,以及区分发现与推断。
主要功能
- 01调查设计动机
- 02追踪代码与提交历史
- 03协调并行调查
- 04区分证据与推断
适用场景
- 01了解代码模式的由来
- 02探究设计决策的权衡
- 03追溯功能演变历史
MCP 相关
该技能指导 Agent 将可用的 MCP 用作证据来源,并按问题跟踪、团队聊天和可观测性等类别进行归类。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ michael-denyer/ pstack-claude --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详细介绍
原因
在 Codex 上,遵循此技能前,请阅读平台映射,包括其中针对各项技能的说明。
在 GitHub Copilot 上,遵循此技能前,请阅读平台映射,包括其中针对各项技能的说明。
在 Muse 上,遵循此技能前,请阅读平台映射,包括其中针对各项技能的说明。
调查代码背后的动机和意图。配套的 how 技能回答代码做什么以及如何运作。why 则回答促使代码形成当前样貌的各种因素。
下面每次启动都指定了 pstack-models.md 中的一条角色配置,以及 Models 中的一个默认值。将 model 设为该配置行的值;如果配置表或该行缺失,则使用默认值。如果值为 auto 或 inherit-parent,则不设置 model。如果 Agent 工具拒绝某个标识符,则使用默认值并说明这一点。如果它拒绝默认值,则使用错误消息中同一系列里最接近的有效标识符。请根据 poteto-mode 技能的 Subagents 部分,为每个子 Agent 选择适合任务的推理级别。
每次启动都使用 general-purpose,并设置 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:并行启动调查人员
**默认进行完整的并行调查。**目标是建立完整的覆盖图,而不是尽量精简。记录无结果的情况,不要跳过搜索。
发现
在启动调查员之前,先列出 Claude Code 环境中可用的 MCP。使用系统提示顶部的工具列表(每个 MCP 都会显示为前缀为 mcp__<server>__<name> 的工具)。否则,读取插件/项目中的 .mcp.json,或运行 claude mcp list。
将每个可用的 MCP 映射到一个证据类别:
- 源代码控制历史
- 问题 / 工单跟踪
- 长篇文档
- 实时团队聊天
- 基础设施可观测性
- 错误 / 异常跟踪
- 产品分析数据仓库
始终可以通过 git 和 gh 使用源代码控制。对于其他六类,根据 MCP 名称、服务说明、工具名称和资源描述进行分类。如果某个 MCP 可能属于多个类别,选择与其主要证据最匹配的类别。在覆盖范围映射中记录存在歧义的情况。
每个有匹配 MCP 的类别都启动一名调查员;在同一条消息中启动所有调查员,以便并行运行,每名调查员恰好负责一个工具或 MCP。model:使用“why investigators”行指定的模型,默认为 Models。
每名调查员的提示词由填入内容的 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)。最擅长揭示塑造代码的产品和数据实际情况。对受功能标志控制的代码、实验驱动的发布、数据迁移以及“这个数字是从哪里来的?”这类问题尤其有力。
何时跳过调查者
只有在最终的 Sources Consulted 中给出明确的书面理由时,才能跳过。以下是两种有效理由:
- 此环境中没有适用于该类别的 MCP。应将其标记为缺口,而非选择:“跳过实时团队聊天。没有匹配的 MCP,因此无法搜索对话记录。”
- 已证实该来源无关,而非仅仅“可能无关”。门槛很高:“跳过错误/异常跟踪。目标是一个构建时脚本,没有运行时代码路径。”
如果范围评估表明目标只是一个单次提交的简单目标,且 PR 描述已包含完整答案,那么只有在确认所有七类可用搜索都多余之后,才可以直接回答。必须明确说明这一点。这种情况应当很少见。
第 4 步:综合
启动一名综合者。model:使用 why synthesizer 行指定的模型,默认为 Models 中的设置。向其提供:
- 调查者的发现,包括任何无结果的调查,以及有理由跳过的类别
- 代码锚点
- 用户的原始问题
references/epistemics.md中的认识论框架references/synthesizer-prompt.md中的综合者提示词模板
第 5 步:呈现
向用户呈现综合者的输出。可以稍作润色以提高清晰度,或补充对话中的背景信息,但不得改写置信度表述。
输出格式
结构应遵循 references/synthesizer-prompt.md:问题、相关代码、我们的发现、我们可以合理推断的内容、相互竞争的假设、我们不知道的内容、Sources Consulted、置信度摘要。可按需调整,但须保留置信度区分,并将 Sources Consulted 按每位调查者一行列出,包括没有发现结果或被跳过的调查者,并注明理由。
如果用户的 why 问题是修改这段代码的前置步骤,则在 Sources Consulted 之后,将沿革发现转化为用于规划修改的 Preserve / Change / Avoid / Risk 约束集。
常见失败模式
- 近因偏差。假定最近的提交最具权威性。当前的代码形态往往是多次演进累积而成的。应追溯更早的决策。
模型
角色默认值取自 plugins/pstack/models.json(在该文件中编辑,然后重新运行 tools/generate.mjs)。运行时,覆盖表 pstack-models.md 中匹配的角色行会覆盖每个默认值;/setup-pstack 会写入该表,并列出其在各运行时中的路径。
- why investigators:
opus - why synthesizer:
opus
推理力度
覆盖表中的角色值可以在模型名称后指定推理力度,例如 opus @xhigh。Claude Code 支持的级别:low、medium、high、xhigh、max。具体适用级别取决于模型。不带 @ 的值使用表中的 default effort 行所指定的级别或 session;如果表中没有该行,则使用 session。在 Claude Code 中,session 不设置推理力度。对于其他运行时,按照平台对 session 的映射处理。读取模型时,应去掉后缀:inherit-parent 或 auto 仍会在所有级别省略 model,而模型名称则会作为 model 传递。将级别作为调度调用的推理力度字段传递,并保留原本要使用的 subagent_type。在 Claude Code 的 Agent 调用中,该字段是 effort;在 Codex 的 spawn_agent 中是 reasoning_effort。在 Muse 中,它是工作流子项上的 effort;subagent_spawn 调度则沿用会话的推理力度。