- 人工智能
- AI 技能
- AI 插件
- 开发工具
【免费下载链接】pstack-claude
Claude Code, Codex, Copilot, Pi, OpenCode, Gemini, and Prime Agent versions of Poteto's pstack. Rigorous agent workflows with Cursor primitives translated for other harnesses.
导读:本文剖析 pstack-claude 仓库中why技能的证据源框架——一套把"为什么这段代码长这样"的追问拆解为七类可检索证据源(源码控制历史、工单追踪、长文文档、团队聊天、基础设施可观测性、错误追踪、产品分析数仓)的实操手册。你将掌握每类证据源的检索命令与 MCP 工具调用序列、判断"什么才算好证据"的标准、常见陷阱清单,以及如何把示例 playbook 适配到同类的其他工具(Jira、Confluence、Discord、New Relic、Rollbar、Snowflake 等)。
为什么需要一份"证据源手册"
在 pstack 的技能体系中,why与how是一对互补技能:how技能 回答"代码做了什么、怎么工作的",而why技能 回答"是什么力量塑造了它现在的样子"——设计理由、权衡取舍、边界用例、外部约束、死代码成因、历史脉络。
why技能的核心执行模型是:按可用证据类别各派出一个 investigator 子代理并行调查,再由一个 synthesizer 汇总成带引用的结论。而**证据源手册(source-playbook)**正是每个 investigator 的"作战地图":它不回答具体问题,而是告诉调查者在某个信息源里该找什么、怎么找、什么算好证据、容易踩哪些坑、最后该返回什么。
这个索引文件的存在解决了两个实际问题:
- 调查者不知道从哪下手:面对"为什么这里有重试逻辑"这类问题,新手只会盯着代码本身,而手册明确指出"代码不是它自身动机的证据",动机藏在 commit、PR、工单、文档和对话里。
- 不同信息源的检索范式差异巨大:git 的历史检索靠 pickaxe 和 blame,Databricks 数仓查询必须先探测 schema,Slack 检索要先检查认证状态。手册把这些范式差异固化成可复用的模板。
证据分类框架总览:七大类别加一个横切视角
source-playbook.md将证据按信息源划分为七个类别,每类对应一份自包含的示例 playbook 和一个代表性 MCP:
| 类别 | 手册文件 | 示例 MCP(可同类别适配) |
|---|---|---|
| 源码控制历史(Source control history) | code-archaeology.md | git、gh |
| 工单 / 缺陷追踪(Issue / ticket tracker) | linear.md | Linear(可适配 Jira、GitHub Issues、Plane、Shortcut) |
| 长文文档(Long-form documents) | notion.md | Notion(可适配 Confluence、Google Docs、Coda) |
| 实时团队聊天(Real-time team chat) | slack.md | Slack(可适配 Discord、Microsoft Teams、Mattermost) |
| 基础设施可观测性(Infrastructure observability) | datadog.md | Datadog(可适配 New Relic、Honeycomb、Grafana、Splunk) |
| 错误 / 异常追踪(Error / exception tracking) | sentry.md | Sentry(可适配 Rollbar、Bugsnag、Airbrake) |
| 产品分析数仓(Product analytics warehouse) | databricks.md | Databricks SQL(可适配 Snowflake、BigQuery、ClickHouse、dbt) |
此外还有一个横切视角:incident-postmortem.md(事故与事后复盘)。它不是一个独立的信息源,而是一个角度——当目标代码看起来具有防御性(空值检查、重试、超时处理、限流、特性开关、出口防护、OOM 处理器)时,必须叠加使用,因为在生产事故之后添加防御性代码是极其常见的动机。
七类信息源 + 横切视角共同构成了why技能 Step 3 中"每类证据一个 investigator、并行启动"的完整覆盖图(coverage map)。
逐类拆解:每个证据源怎么找、怎么用
以下按仓库中七份 playbook 的实际内容逐类展开。每个类别遵循统一结构:源里有什么 → 怎么检索 → 什么算好证据 → 常见陷阱 → 返回什么。
1. 源码控制历史(git + gh):最可信、最完整、唯一保证可用的源
code-archaeology.md强调:源码控制是与代码直接绑定、最可信、最完整的证据源——凡是进过仓库的东西都应该在这里。它包含 commit 历史(消息、日期、作者、diff)、PR 描述与评审讨论(经gh)、行内注释与 TODO/FIXME、ADR、测试(测试命名常编码触发变更的边界用例)、同 commit 修改的相关文件(共变信号)、CHANGELOG 与发布说明、commit 消息与 PR 正文中引用的工单 ID。
检索命令(在why技能 Step 2 建立代码锚点时即已用到一部分,此处为深度展开版):
# 经重命名追踪文件的完整历史 git log --follow --oneline -- <file> # Pickaxe:添加或删除了这段精确文本的 commit git log -S '<exact_string_from_code>' -- <file> # 或针对正则模式 git log -G '<regex>' -- <file> # 每行是谁、何时写的 git blame -L <start>,<end> <file> # 某个 commit 的完整 diff git show <hash> # 两个时间点之间影响此文件的 commit git log <old>..<new> -p -- <file>对每个实质性 commit,拉取 PR 上下文:
# 从 merge commit 或分支找到 PR 号 git log -1 --format=%B <hash> # 完整 PR 上下文:正文、评审、关联 issue gh pr view <number> --json title,body,author,createdAt,mergedAt,labels,closingIssuesReferences,comments,reviews,files # 真正的信号藏在 --json 的 reviews 和 comments 字段里再寻找"带外"文档:
# ADR 常位于 docs/adr/ 等目录 rg -l -i 'architecture.decision' --glob '*.md' # 目标附近的 TODO / FIXME rg -n -C2 '(TODO|FIXME|HACK|XXX|NOTE)' <target_file> # 相关测试,测试名常编码"为什么" rg -l '<symbol>' --glob '*test*'好证据的样子:PR 描述解释的是被解决的问题而非改动本身;评审线程里争论过备选方案;目标行附近解释非显然约束的行内注释;名为test_handles_edge_case_when_X的测试;引用工单或事故 ID 的 commit 消息;概括用户可见理由的 CHANGELOG 条目。
常见陷阱(这份手册特别值得反复读的部分):
- Squash-merge 平原:仓库若 squash PR,分支里的单个 commit 就丢了,要退回 PR 正文与评论。
- 误导性 commit 消息:"Small refactor" 有时藏着一个有意的行为变更——看 diff,别只看消息。
- 照搬的模式:作者可能复制了模式却不懂其缘由。去查该模式在代码库中更早的出处,调查那个commit。
- 机器 commit 与自动合并:Dependabot、Renovate、自动 backport 通常不携带动机,找意图时应跳过。
- 把代码当作意图证据:代码本身不是它为什么存在的证据,证据来自 commit 消息、PR、注释、测试、文档。禁止用"函数叫 X"来证明意图。
返回内容:每个与问题相关的 commit/PR/评论,附精确原文(引用)、hash/PR 号/file:line、作者与日期、以及它是直接证据(显式回应问题)还是旁证。
2. 工单 / 缺陷追踪(Linear 及同类):产品与业务驱动力所在
linear.md指出:产品/业务上下文通常活在这里——"做这个是因为客户 X 要求"或"这是为了 Q3 合规专项"这一层。源里包含描述功能/缺陷及其动机的 issue、挂在 issue 上的项目文档(常为 PRD 或 spec)、父子 issue 关系(大计划 → 具体工单)、issue 评论(澄清、范围变更、"为什么做这个"的理由)、标签(如compliance、customer-request、perf)、解释范围变更的状态更新、附件与关联的 GitHub PR。
检索方法(使用 Linear MCP):
- 从关联工单开始:seed commit/PR 引用了工单 ID(如
ENG-1234、[BUG-567]),先用get_issue抓取,读完整 issue 含评论。 - 按关键词列相关工单:用
list_issues按功能名、关键符号、业务术语做文本搜索,尝试多种措辞。 - 走 issue 树:落在子 issue 上就抓父 issue——子 issue 是战术性的,父 issue 常带着"为什么"。
- 读项目文档:issue 属于某个项目时用
get_project检查挂载文档,项目级文档是 spec 和理由最常被记录的地方。 - 查标签和里程碑:标签暗示动机类别(customer-request、incident-followup、compliance),里程碑把工作绑定到截止日期,常能揭示动机。
好证据:陈述业务问题的 issue 描述("客户 Acme 因 SOC2 审计需要 X");记录决策的评论("我们选了方案 B,因为方案 A 要动计费服务");标题像专项的父 issue("Q3 企业就绪"或"降低支付失败率");挂载的 PRD/spec;customer:acme、incident-followup、compliance、perf-regression这类标签。
陷阱:范围漂移(工单被关过又开且范围变了,要读完整历史);机械模板(有些团队强制填"Why"栏但都是套话,"improve user experience"这种泛泛文本不是真答案);过期工单(旧工单反映的计划可能已变,对照代码上线日期);closed-as-duplicate 链(沿 duplicate-of 关系追回权威工单);私有工作区内容(访问不了就记为 gap,不要猜)。
返回内容:每个相关工单的 ID 与标题、从描述/评论引用的问题与动机(必须引用原文,不许转述——synthesizer 需要精确文本才能引用)、标签/父 issue/项目、作者与创建/关闭日期、工单链接。
3. 长文文档(Notion 及同类):决策在变成代码之前被写下的地方
notion.md强调:Notion 是"why"在变成代码之前以长文形态存在的地方,一个显著功能通常有一份文档。源里包含 PRD、技术 spec 与 RFC、ADR、设计评审的会议纪要、带领域上下文的团队页面、事故 postmortem、可能解释防御性代码的 runbook、设定优先级的战略文档。
检索方法(使用 Notion MCP):
- 用
notion-search做关键词搜索,尝试:功能名、目标代码的关键符号/类名、作者 handle(设计文档常在代码落地前写好)、错误字符串或用户可见术语、知道上线时间时做时间有界查询。 - 用
notion-fetch抓候选页面,读全文而非预览——理由常埋在文档中段。 - 追踪反向链接与子页面:设计文档常有备选方案、附录、实现说明等子页。
- 查相关数据库:
notion-query-data-sources和notion-query-meeting-notes能捞出讨论过该决策的会议纪要。 - 搜作者专属空间:PR 作者若有个人笔记本(某些公司常见),可能存有先于代码的探索性思考。
好证据:带"Problem statement"或"Motivation"章节且与目标代码目的吻合的 PRD;"Alternatives considered"或"Rejected approaches"章节;把目标代码命名为某次事故修复方案的 postmortem;记录"我们决定 X 因为 Y"且作者/日期范围与 PR 吻合的会议纪要;非平凡填写的 ADR 模板(status、context、decision、consequences)。
陷阱:过期文档(spec 写在实现之前且不更新,与真实 PR 交叉核对);文档与现实的漂移(spec 说做 X,代码实际做 Y,要标记分歧,让 synthesizer 暴露矛盾);模板套话(组织要求"Why"栏却填废话,寻找具体性);未链接文档(最相关的文档可能没被任何地方链接,宽关键词搜索有用);多份草稿(同主题多份文档时,找最终版或最近更新的,查日期);访问受限页面(记为 gap)。
返回内容:每个相关文档的标题与 URL、作者与最后更新日期、动机文本(原文引用)及其页面/章节位置、相关链接页面(供 synthesizer 引用)、文档是定稿还是草稿。
4. 实时团队聊天(Slack 及同类):从未进入文档的真实决策现场
slack.md的观点最犀利:Slack 常常是真正决策发生的地方,尤其对不值得写文档的小改动;但它也是最易消逝的信息源——线程被删、频道被归档、搜索质量随时间退化。源里包含问题的实时讨论、事故频道的救火决策、争论权衡的设计讨论线程、资深工程师回答过却没进文档的问题、合并后解释为何返工的回帖、DM(通常不可搜索,按此限定范围)。
检索方法(先检查可用的 Slack MCP 工具 schema,可能需要mcp_auth;认证失败就停下来报告 gap,不要硬编):
- 作者有界搜索:PR 作者在 PR 合并日期附近的消息。大幅缩小范围且常常一击命中。
- 功能名与关键符号关键词搜索:包含拼写错误与口语化写法。
- PR URL 搜索:Slack 常在评审/讨论时贴 PR 链接,搜 PR URL(或只搜
/pull/<number>)。 - 错误字符串搜索:代码处理特定错误时搜错误字符串,事故线程常浮出水面。
- 频道有界搜索:缩到可能相关的频道——
#eng-*(工程讨论)、#proj-*(项目频道)、#incident-*/#sev-*(事故频道)、所属团队的团队频道、设计评审频道。 - 线程遍历:找到相关消息就抓整个线程——决策常在回复里。
好证据:明确争论过权衡的线程("我本来要用 A,但 B 更好因为……");描述目标代码所防之 bug 的事故频道消息;评审者的提问与作者/负责人的权威回答;提及做出决策的会议的消息;产品经理或面向客户工程师解释客户诉求的消息。
陷阱:频道考古限制(旧消息可能因保留策略消失,某日期之前找不到就记下 retention 悬崖);未搜索的 DM(许多决策发生在不可搜索的 DM 里,这是已知局限);把玩笑当决策("Lol just do the thing"不是决策,找深思熟虑的讨论);单条消息的语境坍缩(没有线程,单条消息的读法常与上下文不同,务必抓线程);认证失败(MCP 未认证就停下来,不编造发现,报告 Slack 不可搜索)。
返回内容:每个相关线程的频道名、permalink 或线程 ID、参与者、讨论日期范围、带归属的关键原文引用、上下文(属于什么线程/事故/讨论)。
5. 基础设施可观测性(Datadog 及同类):生产环境的运行时现实
datadog.md开宗明义:Datadog 持有运行时记录——生产实际发生了什么,而不是计划或讨论了什么。源里包含:计数器/仪表/直方图等指标(指标的存在本身就是证据——有人觉得这个数字值得盯);监视器与告警(团队认为值得半夜叫醒人的条件;rate_limit_hit > 10/min触发的监视器直接证明团队担心这个阈值);仪表盘(精选视图,图表告诉团队某个子系统什么重要);APM trace 与 span(请求级运行时数据,回答"为什么慢""为什么这里有超时");日志(常含驱动防御性代码的错误条件);正式事故记录(含时间线与关联 postmortem);Notebook(探索性调查,常含假设与分析)。
检索方法(Datadog MCP,先宽后窄):
- 确定归属服务:
search_datadog_services(按名字或团队过滤)、search_datadog_service_dependencies(看上下游)。 - 先看仪表盘和监视器——它们告诉你团队在意什么:
search_datadog_dashboards、search_datadog_monitors(query 用功能名/服务名/符号)。当仪表盘或监视器覆盖目标时,记下其 query 与被盯的阈值——阈值常常就是"为什么这里钳制在 N"的答案。 - 目标周围的指标:
search_datadog_metrics(按名字模式)、get_datadog_metric_context(元数据:描述、单位、标签)、get_datadog_metric(时间序列;"PR 日期附近有尖峰吗?")。把指标轨迹与目标新增/变更日期关联是强支撑证据:"payment_timeout指标 2023-11-03 尖峰,重试逻辑 2023-11-06 合入。" - 日志:收窄,不要倾倒:
search_datadog_logs(目标附近的原始日志模式,设use_log_patterns=true)、analyze_datadog_logs(SQL 式聚合,只在需要计数时)。强烈优先时间有界查询(变更前后约 30 天),日志量巨大,无约束搜索浪费时间还可能超时。 - APM span 与 trace:
aggregate_spans(统计"这个端点多久失败一次")、search_datadog_spans(检视单个 span)、get_datadog_trace(具体 trace ID)。适用于超时、重试、慢路径与跨服务行为。 - 事故:
search_datadog_incidents(按标题/团队/日期范围)、get_datadog_incident(具体事故详情)。目标看起来防御性时,查其添加时间附近的事故——时间线含"为 X 添加防御性检查"的事故近乎直接证据。
好证据:query 与阈值匹配代码所执行约束的监视器(代码钳制在 100,监视器在请求超 100/min 时告警);目标作者创建、组件与代码所测量/防御内容对应的仪表盘;代码合入前立即出现、合入后稳定的生产指标尖峰;引用目标代码、相同符号或相同错误字符串的事故记录;时间戳落在变更前窗口、防御代码将阻止的特定错误模式的日志。
陷阱:相关不是因果(PR 前尖峰 + PR 后稳定只是提示性证据,检查邻近 PR);过度拟合找到的图表(可视化是人做的,反映制作者的框架;"重试成功率"图表证明团队在意重试成功率,不证明某行代码存在的原因);消失的遥测(指标可能被改名/删除/保留期短,找不到相关窗口的数据是 gap 而非 null);规模噪音(常见字符串搜出数千条匹配,按服务/标签/时间激进收窄,用analyze_datadog_logs聚合而非倾倒原始日志);埋点 ≠ 起因(指标存在只说明有人在意到去测量,不说明代码因为它而存在,与 commit/PR 日期交叉核对)。
返回内容:每个相关项的类型(dashboard/monitor/metric/log pattern/trace/incident/notebook)、标题或名称、链接或标识符(ID)、属主/作者与创建/修改日期、与该问题相关的具体条件/query/引用(尽量原文)、相关性判断(对目标代码意味着什么、联系有多强)。
6. 错误 / 异常追踪(Sentry 及同类):出错历史的档案馆
sentry.md描述 Sentry 是"出错之事的档案"——对防御性、纠正性、错误处理代码,它常常握着直接动机:促使某人加检查、catch、重试或兜底的具体异常、堆栈与频率。源里包含:issue(按指纹分组的错误,含计数、首次/末次出现时间戳、受影响版本、评论)、event(issue 内的单个错误实例:堆栈、标签、用户上下文)、release(部署记录与关联 issue,"哪个版本修了这个?")、replay(面向用户的错误会话录制,若启用)、profile(性能剖析,对"why"帮助小、对"多慢"帮助大)、issue 评论与指派(有时含工程师的根因笔记)。
Sentry 提供的最有价值之物是时间相关性:"issue X 2024-01-02 创建、峰值 500 events/day、在 2024-01-15 发布 v2.14.0(搭载防御性检查的版本)后不再出现。"
检索方法(Sentry MCP):
- 定位:不知道 project slug 和组织时,用
find_organizations、find_projects。 - 搜索相关 issue:
search_issues(自然语言,如"PaymentService timeout 错误"、"uploadFile 未处理异常")。好的 query 组件:目标处理的异常类名、目标的函数/类名、目标检查的错误消息字符串、目标的文件路径。 - 按版本与时间窗收窄:
search_issue_events(按 release、时间、环境、trace ID、标签过滤)、get_issue_tag_values(issue 在版本/用户/环境间的分布)。对疑似 issue 检查:首次出现(错误何时开始出现)、末次出现(何时停止,是否与目标上线日期对齐)、受影响版本(哪些版本见过它,哪个是修复版)、频率轨迹(是否尖峰后解决)。 - 拉完整 event 取上下文:
get_sentry_resource(传 Sentry URL 或类型+ID)。堆栈是否穿过目标代码?标签与 breadcrumb 是否匹配目标防御的条件? - 查目标附近的版本:
find_releases(在目标 commit 日期附近),把 release 版本与 PR 合并日期交叉对照。 - 节制使用 Seer:
analyze_issue_with_seer产出 AI 根因分析,可作假设生成器,但当作推断而非权威——真正的 event 和堆栈才是主证据,Seer 的叙述是次要的。
好证据:首次出现紧邻目标 PR 之前、末次出现紧邻之后(暗示目标处理了该错误);穿过或落在目标函数上的堆栈(展示被防御的确切失败模式);PR 作者在 issue 上描述修复的评论;目标 PR 描述或 commit 消息引用 Sentry issue URL/ID;事件计数高、在含目标的版本后停止的 issue。
陷阱:分组漂移(Sentry 按指纹分组,重构/改名会把"同一个"错误归入新 issue ID,issue 突然结束时错误可能只是被重新分组,立即查其后新 issue);版本相关噪音(一个 release 含许多 commit,错误止于 v2.14.0 不证明目标修了它,与目标的确切 commit 交叉核对);静默修复(错误停止可能是上游变了,相关性只提示修复,不证明作者身份);resolved ≠ fixed(issue 可被手动标为"resolved"而没有任何代码变更,把 resolved 当人类标记而非代码修复的证据);Seer 幻觉(可能给出听起来自信却错误的解释,下结论时回到真实 event/堆栈/时间戳);采样(项目可能激进采样,低计数只意味着高采样而非错误罕见,不确定就记 gap)。
返回内容:每个相关 issue 的 ID 与标题、项目与组织、首次/末次出现时间戳、事件计数(与已知采样率)、受影响版本、能证明与目标相关性的代表性堆栈片段(原文摘录,不是概括)、首/末次出现与目标上线日期的相关性、issue 链接、作者评论或解决备注。
7. 产品分析数仓(Databricks 及同类):产品与数据现实
databricks.md界定其与 Datadog 的分工:Datadog 是基础设施/运行时视角,Databricks 是产品/数据视角(用户做了什么、哪些实验跑了、功能使用如何演进、某个阈值常量从哪来)。源里包含:产品分析事件(原始表your_warehouse.events.analytics_track_event与类型化、去重的 dbt 模型<your_analytics_db>.<schema>.<table>:功能调用、点击、接受/拒绝、提交、客户端上报错误);用量与计费事件;实验/特性开关数据(暴露与结果表,schema 公司特定,先SHOW TABLES探测再假设表名);系统表(system.query.history、system.compute.warehouses、system.billing.*、system.access.audit:回答"这个查询贵吗""多久有人跑一次""仓库负载何时尖峰");dbt lineage(模型揭示哪些管道依赖某表/字段,上游变更常驱动消费者代码变更);Databricks notebook(SQL MCP 查不到,怀疑理由在 notebook 里就记为 gap)。
检索方法(Databricks SQL MCP,主工具execute_sql_read_only;返回statement_id就用poll_sql_result轮询而不要重跑):
查询前先定向——schema 公司特定,先探测再信任表名:
SHOW TABLES IN <your_analytics_db>.<schema> LIKE '*<keyword>*'; DESCRIBE TABLE <your_analytics_db>.<schema>.stg_<event>;每个查询都做时间有界:这些表巨大,无约束扫描会超时。在_timestamp(事件)或start_time(system.query.history)上过滤,窗口包裹上线日期——通常前后约 30 天,只有强理由才放宽。
优先用类型化 dbt 模型而非原始表:<your_analytics_db>.<schema>.<table>去重、类型化、liquid-clustered;your_warehouse.events.analytics_track_event有重复且properties_json无类型。模型名模式:stg_<source>_<event_name_with_underscores>,<source>为app/backend/website/cli。模式解析不出确切名字时用SHOW TABLES确认。只有尚无可用的 dbt 模型、或需要 dbt 刷新延迟窗口内的事件时,才落到原始表。
类型化 dbt 模型上的列约定(记住可省一次DESCRIBE往返):_timestamp、_id、_auth_id、_request_id、event_name每张模型都有;properties_<name>类型化下划线命名的事件属性(properties_entrypoint、properties_size_bytes…);context_team_id、context_client_version、context_country、context_client_os预提取的客户端上下文。
五个通常划算的调查模式:
- 事件用量轨迹:在 PR 合入前后 ±30 天窗口内对相关
stg_*模型做每日计数。合入后一两天内从零到稳定量的阶跃函数是强旁证(该 PR 启动了功能);衰减到零提示弃用或删除。 - 护栏/防御检查的由来:PR 之前 14 天相关
properties_<name>列的分布(median/p99/max)。p99 与目标阈值常量吻合,提示该数字是从数据里选出来的。 - 实验/特性开关查询:
SHOW TABLES ... LIKE '*experiment*'找暴露表,然后按 PR 日期附近的相关 flag key 拉各变体的暴露计数。 - 迁移/回填/性能重写的查询历史证据:
system.query.history按statement_text ILIKE '%<table_or_symbol>%'过滤并收紧start_time窗口,找出很可能驱动变更的昂贵查询(按total_duration_ms排序,或聚合SUM(read_bytes)、COUNT(*))。 - dbt lineage:目标读取/写入
<your_analytics_db>.<schema>模型时,模型自身的 git 历史(在本仓库内)常携带理由——把这条线索交回给 git investigator,别自己追。
好证据:错误分类事件计数在防御代码 PR 后几天内降至接近零(提示该 PR 解决了该错误类);暴露表行点名目标的特性开关 key,且 PR 上线日期附近有 "shipped"/"concluded" 决定。
陷阱:埋点 ≠ 起因(事件存在只说明有人在意到记录它,声称因果前先配 git investigator 的 PR/commit 引用);静默埋点变更(事件量阶跃可能只是开始记录新事件而非用户行为变了,先查同窗口的埋点 PR 再读阶跃);schema 漂移(事件属性会演进,今天类型化模型上的列在目标编写时可能不存在,旧数据可能只在原始properties_json里);dbt 刷新延迟(<your_analytics_db>.<schema>.*按计划重建,常为小时/日级;最近几小时的事件回退到your_warehouse.events.*并按_id去重);公司特定表(实验/特性开关/计费/用量表各不相同,从未确认存在就报告结果是经典失败模式,先SHOW TABLES/DESCRIBE TABLE);保留期悬崖(相关窗口早于表保留期或 dbt 模型创建日期是gap而非 null 结果,显式命名以免 synthesizer 把"无结果"读成"无活动");notebook 不可查询(SQL MCP 看不到 Databricks notebook,怀疑理由在 notebook 里就返回 gap)。
返回内容:每个相关发现的类型(产品事件/实验暴露/用量或计费事件/系统表行/dbt 模型)、全限定表名与实际运行的查询、查询的时间窗、紧凑的数值摘要(计数、分位数、首/末次出现时间戳,不要倾倒原始行)、与目标上线日期的时间相关性(如"首行 2024-08-15,PR #49074 2024-08-14 合入")、相关性与强度(direct/circumstantial/weak)。
横切视角:事故与事后复盘(incident-postmortem)
incident-postmortem.md反复强调它不是独立信息源,而是横切角度:事故常催生防御性代码("X 事故之后我们加了这条检查")。因此当目标代码看起来防御(空值检查、重试、超时处理、限流、特性开关、出口防护、OOM 处理器)时,要在每个可用信息源里专门猎取事故历史:
- Notion:搜提到目标文件、功能或错误字符串的 postmortem;
- Linear:找标了
incident、sev-*、postmortem-action-item、reliability的工单; - Slack:搜目标代码添加日期前后的
#sev-*和#incident-*频道; - Git:消息像"fix for incident""add defensive check""revert"后接"re-apply with..."的 commit 是强信号;
- Datadog:
search_datadog_incidents找带时间线的正式事故记录,以及作为 postmortem 行动项创建的仪表盘和监视器; - Sentry:首/末次出现窗口与目标 PR 上线日期对齐的 issue、穿过目标的堆栈;
- Databricks:把错误条件分类的产品分析事件(客户端上报失败、用户可见的重试事件等)常在事故窗口尖峰;目标 PR 上线后该事件计数下降,是目标代码解决了用户可见症状的旁证——即使 Datadog/Sentry 信号嘈杂也有价值。
找到事故链接就抓完整 postmortem——postmortem 通常有直接对应代码变更的 "Action Items" 章节。当多个信息源互相印证时证据尤其强:一个 Datadog 事故 ID 出现在 Linear 工单里,该工单出现在 Notion postmortem 里,该 postmortem 出现在链接了目标 PR 的 Slack 线程里,且修复后 Databricks 错误事件计数下降。反之,对不具防御性的代码可以跳过此视角。
在 why 技能工作流中,playbook 如何被使用
why技能把这些 playbook 编排进五步工作流(SKILL.md):
- Step 1 理解目标与问题:目标通常是代码块、模式、功能或命名决策;问题是设计理由、权衡、边界用例、外部约束、死代码或历史脉络。
- Step 2 建立代码锚点:先内联构建文件路径与行范围、关键符号、最近几笔 commit、merge commit 中的 PR 号(
git blame -L、git log --follow -p、gh pr view的种子命令见上文),再把锚点传给 investigators。 - Step 3 并行派出 investigators(默认姿态):先做discovery(工具列表里所有
mcp__<server>__<name>前缀的工具,否则读.mcp.json或claude mcp list),把每个可用 MCP 映射到七个证据类别之一;源码控制永远可用(git +gh),其余六类按 MCP 名、服务说明、工具名与资源描述分类。目标完整覆盖图而非最小覆盖——"记下 null,不要跳过搜索"。所有匹配的 investigator 在单条消息里同时启动;每个 investigator 拿到的材料是:investigator-prompt.md基础提示词 + 对应类别的 playbook(源自source-playbook.md索引、按可用 MCP 适配)+ 目标防御性时追加的 incident-postmortem + 代码锚点 + 用户原问题。 - Step 4 合成:一个 synthesizer 子代理拿到所有 investigator 的发现(含 null 结果与带理由的跳过)、代码锚点、原问题、
epistemics.md置信度框架与synthesizer-prompt.md模板。 - Step 5 呈现:可轻编辑,但不得改写置信度措辞。
两份配套文档的要点值得单独强调:
Investigator 提示词模板(investigator-prompt.md)规定了证据收集纪律:先宽后深("Go wide before going deep")、引用而非转述、记录搜索了什么(不仅找到什么)、抵制顺滑叙事(矛盾之处是最有趣的发现)、考虑反事实、永不编造、不把机制与动机混淆、不从代码风格推断意图、不静默替换(问功能 X 却只找到功能 Y 的证据,不要假装它回答了 X)。输出结构固定为:Source / What I Searched / Direct Evidence Found / Indirect-Circumstantial Evidence / Contradictions / Gaps / Additional Leads。
Synthesizer 提示词模板(synthesizer-prompt.md)要求最终输出严格按八段结构:The Question → The Code in Question → What We Found([Direct]/[Supported]带引用)→ What We Can Reasonably Infer([Inferred]带推理链)→ Competing Hypotheses(证据支持多种叙事时并列呈现)→ What We Don't Know(显式列出 gap)→ Sources Consulted(每个 investigator 一行,含空结果与跳过及其理由)→ Confidence Summary。若why之问是改动代码的前奏,还要把 lineage 发现转成 Preserve / Change / Avoid / Risk 约束集。
置信度分层(epistemics.md)是贯穿全流程的校准框架:Direct(作者写过、显式回答问题的文本)、Supported(多份间接证据收敛)、Inferred(合理解读但无显式支撑,必须用 "appears to"/"likely"/"suggests" 等对冲措辞)、Speculative(可能性但证据单薄,进 Competing Hypotheses)、Unknown(查了没找到,如实记录搜索了什么)。措辞上,"because""the reason is""was designed to""fixes" 只配 Direct/Supported;"obviously""clearly""just" 是禁用词;特别要警惕奉承陷阱——用户常把假设嵌在问题里("为什么这么做,我猜是为了性能?"),要把它当候选而非结论独立核查。代码永远不能当作自身意图的证据。
实战:如何把示例 playbook 适配到同类其他 MCP
why技能的设计意图是"每个类别一份自包含示例 playbook,把同类别的不同 MCP 适配进去"。适配不是重写,而是保持结构、替换工具名:
- 确认同类性:先对照
source-playbook.md的类别表确认归属。Linear 与 Jira 同属"工单/缺陷追踪";Confluence 与 Notion 同属"长文文档";New Relic/Honeycomb/Grafana/Splunk 与 Datadog 同属"基础设施可观测性";Rollbar/Bugsnag/Airbrake 与 Sentry 同属"错误追踪";Snowflake/BigQuery/ClickHouse/dbt 与 Databricks 同属"产品分析数仓"。跨类别的 MCP(如能搜索工单又能查数据的)按其主要证据归属,歧义记入覆盖图。 - 替换工具名与参数:Linear 的
get_issue/list_issues/get_project换成 Jira 或 GitHub Issues 的对应 API;Notion 的notion-search/notion-fetch换成 Confluence 或 Google Docs 的检索工具;Datadog 的search_datadog_monitors换成 New Relic 或 Grafana 的告警查询。先检查可用 MCP 的工具 schema(mcp__<server>__<name>前缀)再动手。 - 保留检索策略骨架:工单类别"从关联工单开始 → 关键词展开 → 走父 issue → 读项目文档 → 查标签里程碑"的顺序、可观测性类别"先仪表盘监视器 → 再指标 → 日志收窄 → APM → 事故"的先后、数仓类别"先 SHOW TABLES 探测 → 时间有界 → 优先类型化模型"的纪律,全部与具体工具无关,直接继承。
- 保留陷阱清单:squash 平原、机械模板、相关不是因果、分组漂移、采样、保留期悬崖——这些陷阱是跨工具的普遍规律,适配时逐条对照。
常见失败模式与规避
why技能在 SKILL.md 的 "Common Failure Modes" 中点名了一个全局失败模式:
- 近因偏差(Recency bias):假定最近的 commit 是权威的。但当前形态常常是许多更早决策的累积——要往回追溯,而不是停在最近一次提交上。
各 playbook 还揭示了更多值得警惕的失败模式:把代码本身当意图证据、把相关性当因果、把"没找到"当"不存在"、把用户嵌在问题里的假设当结论直接采信、用顺滑的叙事掩盖矛盾证据。规避之道是严格执行调查者纪律:引用原文、记录搜索、暴露矛盾、显式命名 gap。
总结
why技能的证据源手册是一套把"历史性、碎片化、有时互相矛盾"的动机证据系统化的分类框架:七大证据源各司其职(git 管实现期理由、工单管业务驱动力、长文管设计理由、聊天管未入文档的决策、可观测性管基础设施现实、错误追踪管防御动机、数仓管产品数据现实),横切的事故视角在防御性代码上叠加一层追因维度。调查者凭各自的 playbook 在并行中收集原始证据,synthesizer 依置信度框架(Direct/Supported/Inferred/Speculative/Unknown)输出带引用的结论,并诚实呈现未知。这套方法论的价值不在权威感,而在诚实性——让拿到答案的读者知道什么是确证的、什么是推断的、什么缺失,从而能向原作者或负责人提出正确的追问。
- 人工智能
- AI 技能
- AI 插件
- 开发工具
【免费下载链接】pstack-claude
Claude Code, Codex, Copilot, Pi, OpenCode, Gemini, and Prime Agent versions of Poteto's pstack. Rigorous agent workflows with Cursor primitives translated for other harnesses.
相关推荐
pstack 项目 why 技能 Investigator 提示词模板深度解析:如何让子代理并行取证代码背后的动机
pstack 项目 why 技能 Investigator 提示词模板深度解析:如何让子代理并行取证代码背后的动机 导读 investigator prompt
人工智能AI 技能AI 插件开发工具pstack 的 `why` 技能置信度框架:如何在碎片化历史证据上诚实回答「代码为什么这样写」
pstack 的 why 技能置信度框架:如何在碎片化历史证据上诚实回答「代码为什么这样写」 导读 :本篇文章深入解析 pstack 开源仓库中 why 技能的
人工智能AI 技能AI 插件开发工具pstack teach 技能解析:让 AI 用 how 与 why 把代码讲明白的完整方法论
pstack teach 技能解析:让 AI 用 how 与 why 把代码讲明白的完整方法论 导读 本文深入解析 pstack 插件库中的 teach 技能。
AI 技能AI 插件插件系统AI Agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考