mcpField
U
ultrathink-protocol

ultrathink-protocol

github.com/bmad-labs开发1994 次安装6 天前更新
代码仓库

关于 ultrathink-protocol

用于先诊断、再修复复杂技术问题的协议 Skill。它通过基于证据的调查步骤,定位实际行为偏离预期的位置。

主要功能

  1. 01分离诊断与实施
  2. 02假设—行动—观察循环
  3. 03分层诊断步骤
  4. 04修复前验证证据
  5. 05处理调查陷入停滞

适用场景

  1. 01追踪跨系统层的问题
  2. 02检查运行时配置和进程状态
  3. 03以定向调查取代反复尝试修复

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bmad-labs/skills --skill ultrathink-protocol

安装后在 Claude Code 中输入/ultrathink-protocol确认已加载。

详细介绍

Ultrathink Protocol

此协议的用途

复杂技术问题常以一种特定模式告终:匹配一个看似合理的修复方案,应用它,发现并未奏效,再换一种方案重复尝试。每次迭代都让人觉得有所进展,却没有一次真正带来理解。这个循环可能持续数小时。

此协议通过将两种绝不能混为一谈的模式分开,打破这个循环:

  • 诊断模式 — 构建经过验证的模型,弄清实际发生了什么
  • 实施模式 — 确定原因后再应用修复方案

在诊断模式得出一个经过验证的原因之前,不能进入实施模式——这意味着你掌握了能够解释症状的直接证据(日志行、端口号、源代码函数、网络跟踪记录,或从运行中的进程读取的配置值)。“可能是 X”是一个假设,不是经过验证的证据。“运行中的进程从路径 Y 读取配置,而不是路径 Z,因为启动脚本在执行程序前覆盖了环境变量”才是经过验证的证据。


执行周期

复杂调查中的每一步都遵循以下三部分结构。 明确写出,不要压缩成一个段落。

THOUGHT:      What hypothesis am I testing? What do I expect to find?
              What would this result mean for my current model of the problem?

ACTION:       The single most informative thing I can do right now —
              a command, a source read, a log grep, a process inspection.
              One action per cycle. Pick the action that would most change
              your model if the result is unexpected.

OBSERVATION:  What actually happened. Quote the relevant output directly.
              Does this confirm or refute the hypothesis?
              How does it change the model?

理解是在 OBSERVATION 步骤中建立的。如果观察结果只说“这证实了我的理论”,却没有解释为什么,那就是一个危险信号——这意味着你可能是在让证据符合预先形成的结论,而不是据此更新自己的模型。


诊断阶梯

从上往下逐级排查。在找到经过验证的证据时停止。排查得过多会浪费时间;过早停止则会得出错误诊断。

Level 1 — 精确描述症状

采取任何行动之前,先用尽可能具体、可观察的方式重述症状:

  • 较弱:“不工作”
  • 较强:“根据进程 A 自身的日志,它以 1 Hz 写入输出,但 30 秒后消费者 B 仍未收到任何内容,尽管双方都声称连接到了同一个通道”

观察结果与预期结果之间的差距,决定了问题的轮廓。每项诊断操作都应针对性地解释这一差距,而不是探索相邻的可能性。

Level 2 — 排除显而易见的问题

检查那些无需成本就能检查、且一旦出错就能解释所有问题的事项:

  • 进程是否实际在运行?
  • 运行中的进程是否确实能看到你认为它应该看到的配置/环境变量? (**关键:**检查进程自身的环境,而不是 shell 或配置文件——它们经常并不相同)
  • 部署的代码/二进制文件是否为正确版本?
  • 进程是否连接到了正确的端点、接口或地址?

**进程环境陷阱。**这是所有技术栈中非常常见的故障模式:你在启动器、compose 文件或包装脚本中配置了变量,但进程会在启动时、变量生效前覆盖它。务必验证运行中的进程实际看到的内容,而不是你让启动器传入的内容。在 Linux 上:/proc/<pid>/environ。在其他平台上:使用等效的进程检查工具。

Level 3 — 跟踪实际数据路径

确定预期的数据流,然后验证它在实际运行的系统中的每个步骤:

  • 实际行为从哪一步开始偏离预期行为?
  • 链条中最后一个行为正常的组件是什么?
  • 第一个行为异常的组件是什么?

根本原因几乎总是恰好出现在一个偏离点——可能是层边界、被静默覆盖的配置值,或代码绑定到的接口与预期不同。“最后一个正常”与“第一个异常”之间的差距,就是需要排查的地方。

具体而言:不要推测可能出现什么问题,而要检查运行状态——打开的文件描述符、绑定的地址、活动连接、正在处理的实际值——并将它们与你的预期进行比较。

第 4 级 — 阅读源代码

当组件的行为与文档或配置不符时,阅读处理配置或负责相关路径的代码。听起来很慢,但与猜测各种配置变体相比,这种方法始终更快。

源代码访问优先级:

  1. 搜索已安装的头文件或打包脚本——它们通常随已安装的软件包提供,并能揭示函数签名、常量值、环境变量名称
  2. 在二进制文件中搜索字符串字面量——找到代码在运行时实际读取的环境变量名称、配置键、特殊值
  3. 阅读上游源代码(GitHub、软件包注册表)——这是最权威的依据;只需查看一个函数的实现,就能省去数小时的配置尝试
  4. 在文档和问题跟踪器中搜索你遇到的确切行为

源代码阅读之所以如此有价值,关键就在于:如果某个函数读取的是 CONFIG_VAR_B,而不是你一直在设置的 CONFIG_VAR_A,调查就能立即结束。无论你尝试多少种变体,对 CONFIG_VAR_A 进行任何配置更改都不会奏效。

第 5 级 — 受控实验

当无法获取源代码,或代码路径过于复杂、无法静态追踪时,运行受控实验,准确隔离一个变量:

  • 将系统缩减到仍能复现故障的最小情况
  • 只更改一项,然后观察效果
  • 设计实验来证伪你当前的假设,而不是证实它

好的实验应当有可能证明你错了。如果它只能证实你已有的想法,那就不具备诊断价值——这只是多绕了几步的确认偏误。


卡住时的门槛

出现以下任一情况,就说明你卡住了:

  1. 在没有新的、经过验证的证据表明根本原因已经改变的情况下,你对同一类修复方法尝试了两次以上(不同的配置值、同一补丁的不同版本、不同的重启顺序)
  2. 最近三个观察步骤都没有改变你对问题的判断
  3. 你正在考虑采用某种已失败方案的更复杂版本
  4. 你的推理中出现了“也许”,却没有测试计划

卡住时:停下来。不要再尝试其他修复变体。

改为:

  1. 明确说明情况:

    “我卡住了。我目前对问题的判断是 [X]。我掌握的证据是 [Y]。我无法解释的部分是 [Z]。”

  2. 沿诊断阶梯继续深入——说明你还没有查得足够深入。卡住最常见的原因是:没有直接检查某一层的实际行为;某个假设取代了观察。

  3. 如果所有可用的诊断工具都已用尽,就升级到外部研究(见下文)。

用户说“停止在不了解根本原因的情况下反复试错”,这是一个必须立即停止的信号。它意味着违反了流程——无论当前的修复尝试看起来离成功有多近,都要立即返回诊断模式。


升级:何时以及如何开展研究

在以下情况下,应升级到网络搜索、查阅文档或研究源代码:

  • 根本原因需要理解你无法直接检查的系统(闭源二进制文件、第三方中间件、未记录的协议行为)
  • 你已经得出了清晰、具体且可以回答的问题
  • 如果不获取更多信息就继续诊断,只会沦为猜测

可供研究的问题应足够具体,能够通过搜索直接回答:

“[库 X] 的 [函数 Y] 在运行时实际读取哪个环境变量?”

无法供研究的问题,是你卡住时写下、希望靠研究来解围的问题:

“[技术 A] 如何与 [技术 B] 配合使用?”

如果你无法写出一个具体问题,就说明诊断还不够深入。此时正确的做法是继续诊断,而不是继续研究。


调查期间的沟通

要说什么
  • 每次执行 ACTION 前,用一句话说明正在验证的假设
  • 每次 OBSERVATION 后,说明你的模型发生了什么变化——即使答案是“没有变化,而这本身也缩小了可能性范围”
  • 确认根因后,提出任何修复方案之前,先完整、准确地说明根因:

    “根因已确认:[组件 A] 使用 [值 X],因为 [机制 Y] 在启动时覆盖了已配置的 [值 Z]。证据:[日志/源代码/进程状态中的直接引文]。”

不要说什么
  • 不要把工具调用描述成进展(“我来查看日志……”不是发现——报告发现,而不是意图)
  • 不要在确认原因之前宣布修复方案
  • 不要说“我觉得问题可能是 X”,然后立刻针对 X 应用修复——“可能是”代表假设;先验证
  • 不要把 THOUGHT/ACTION/OBSERVATION 压缩成一个段落——明确的结构正是为了避免跳过验证步骤

多层分解

当系统包含多个层(任何技术栈:硬件 → 驱动程序 → 操作系统 → 运行时 → 中间件 → 应用程序 → 配置)时,故障几乎总是发生在某一层边界上。定位方法如下:

  1. 找出最后一个正常工作的层。 链路中的哪一处行为符合预期?从输入端开始,沿链路向前检查。

  2. 找出第一个发生故障的层。 行为最先从哪一处开始偏离预期?

  3. 根因就在该边界上。 现在你有了一个精确的单层问题,而不是一个整个系统的问题。只调查该边界。

这种分解能将“整个流程都无法正常工作”转化为一个单层问题,只需一两个诊断操作即可解答。

避免调查尚未检查的层。 表层尚未彻底检查时,很容易对更深层提出假设。实际的偏离点几乎总比预想的更浅。


本协议可避免的反模式

反模式信号正确做法
配置反复尝试对同一项配置更改尝试第三种变体停下。查看正在运行的进程实际加载了什么配置。
重启循环重新构建 → 重启 → 检查,但没有获得新的诊断信息停下。代码没有变化。再次重启前先检查状态。
假设漂移尚未验证原因 X,就针对 X 编写修复方案将 X 视为假设。编写修复方案前先找到直接证据。
复杂度升级每次修复尝试失败后,都增加更多层或间接步骤运用奥卡姆剃刀。更简单的解释往往更正确。在正确位置修改 3 行,胜过在错误位置添加 50 行变通方案。
确认式阅读阅读诊断输出是为了印证已有观点,而不是检验观点思考:如果我的假设是错的,我会看到什么?有针对性地寻找这些迹象。
Shell ≠ 进程环境假设进程看到的就是启动器被告知要传入的内容在运行时检查进程自身的环境,而不是启动配置。
跳过层级未检查表层,就推测更深层的问题从输入到输出逐层检查。第一次出现偏离的位置就是根因。

通用诊断工具包

# What environment does the running process actually see?
# Linux:
cat /proc/<pid>/environ | tr '\0' '\n'
# Or filter for a specific variable:
cat /proc/<pid>/environ | tr '\0' '\n' | grep VAR_NAME

# Which network sockets does a process own? (Linux)
# Map process file descriptors to UDP/TCP ports:
python3 -c "
import os, re
pid = <pid>
inodes = {}
for fd in os.listdir(f'/proc/{pid}/fd'):
    try:
        m = re.match(r'socket:\[(\d+)\]', os.readlink(f'/proc/{pid}/fd/{fd}'))
        if m: inodes[int(m.group(1))] = fd
    except: pass
for proto in ['udp', 'tcp']:
    try:
        with open(f'/proc/net/{proto}') as f:
            for line in f:
                p = line.split()
                if len(p) >= 10:
                    try:
                        i = int(p[9])
                        if i in inodes:
                            port = int(p[1].split(':')[1], 16)
                            print(f'{proto.upper()} fd{inodes[i]} port={port}')
                    except: pass
    except: pass
"

# What string literals (env var names, config keys) does a binary contain?
grep -oa '[A-Z_][A-Z0-9_]\{3,\}' /path/to/binary | sort -u | head -50

# Read source from a public GitHub repo without cloning:
gh api repos/<org>/<repo>/contents/<path/to/file> --jq '.content' | base64 -d

# Which file is a process actually reading? (Linux, requires strace)
strace -p <pid> -e trace=openat 2>&1 | grep -v ENOENT

# What is the process's working directory and open files?
ls -la /proc/<pid>/fd
readlink /proc/<pid>/cwd

完成检查清单

只有在检查完每一项后,才能宣布修复完成:

  • 用一句话说明根本原因,并附上直接证据引用
  • 修复针对根本原因,而非下游症状
  • 没有为绕过原因不明的行为而增加复杂性
  • 修复是解决已验证原因的最简单改动
  • 应用修复前,已作出具体预测:“修复后,我预计会观察到 [X]”
  • 应用修复后,已通过观察验证该预测
  • 在故障发生的层级测试系统,而不只是进行端到端测试

评论

支持 Markdown