doctor · git:20261020.a6b5608 · 2026-10-20 · sha256 132259a121cf2e2b

doctor git:20261020.a6b5608A

Immutable. This exact content never changes and is served at /api/v1/blob/132259a121cf2e2b.

---
name: doctor
description: >
  本机环境体检:一条命令问清这台机器上哪些流程能跑、哪些会降级(缺 Python 包、git、node、gh,
  traces/ 能否解析,知识库索引在不在),并给出每项缺失的修法。任务开始前环境可疑、换机器、
  内网新部署、或流程中途以一句 import 报错退出时用。可反复执行:同一台机器两次跑结论一致。
---

# Doctor(本机环境体检)

依赖缺了不在开单时报,而是在任务中途以一句 traceback 冒出来。实测:缺 PyYAML 的机器上点「导出交接包」,面板只回一句「导出脚本没有给出 JSON 结果」,真因(`ModuleNotFoundError: No module named 'yaml'`)在 traceback 的最后一行,读者要自己认。全仓有一部分脚本在 import 阶段就依赖它,缺一个包会同时断掉几条流程。

本 skill 的动作只有一件:**跑体检器,然后按它给的顺序修一项、重跑一次**。

## 何时触发

- 用户问「这台机器能不能用」「装了什么」「为什么报缺依赖」;
- 流程中途出现 `ModuleNotFoundError`、`command not found`、面板报「没有给出 JSON 结果」这类只有结果没有病因的错;
- 换机器、换解释器、内网新部署第一次用;
- 修完一项要复验。

## 只跑一条命令

```bash
python3 scripts/doctor.py          # 人读三段:结论 / 证据 / 下一步
python3 scripts/doctor.py --json   # 面板或脚本消费
```

退出码:`0` 无阻断、`2` 有阻断项、`3` 不在 ascend-sleuth 检出里。

**不要自己另写探测命令**(手敲 `python3 -c "import yaml"` 只能验一个包,且会漏掉解释器不一致这一层)。体检器扫的是 `scripts/` 下全部脚本的 import,新增第三方包会被它自动发现。

## 怎么读输出

三段对应三个问题:

| 段 | 回答 | 用法 |
|---|---|---|
| 结论 | 哪些流程能跑 / 降级 / 不能跑 | 第一屏直接转述这三行,不要让用户自己读全表 |
| 证据 | 每一项缺什么、影响几个脚本、修法原值 | 修的时候照抄「修:」后面那条命令,不自己拼 |
| 下一步 | 按影响面排序的修复动作 | 一次只做第一条 |

报告末尾那行「体检用的解释器」必须带上:面板与终端可能不是同一个解释器(Windows 上按 `python3` → `python` → `py -3` 的顺序探活),把包装到另一个解释器上,体检结论不会变。

## 修复循环

1. 读结论段,记下第一条**阻断**项。
2. 只修那一项,命令照抄证据段给的「修:」原值。
3. 重跑同一条命令。
4. 阻断项清零后再处理降级项。
5. 结论与上一次不一致时先停:同一台机器两次跑出不同结果,说明环境在变(PATH、解释器、代理),先查这个再继续修。

## 硬规则

- 没跑就不许说「环境没问题」。结论只从脚本输出里取。
- 不许为了让检查变绿去改体检器或绕开它。它是判据,不是待办清单。
- 阻断与降级的判据不同:缺 Python 包是**阻断**(相关脚本在 import 阶段退出);缺 `node`、`gh`、`git` 是**降级**(对应流程退化,其余照跑)。修阻断项优先。
- 修不了的项照实说。内网装不了包就给出带 wheel 的离线装法,不要再给一条本机执行不了的联网命令。
- 降级项不挡流程时不要顺手修:一次只动一项,修完重跑,否则下一轮分不清是谁改好了。

## 它不负责什么

- **内容门禁**:索引新鲜度、结构校验、面板契约由各自的检查脚本判,体检器不碰内容。
- **一次跑完所有 CI 命令**:那是 `python3 scripts/rehearse_evolve_loop.py`(逐条复跑 CI 的 `run:`)。体检器只在「下一步」里指出该跑哪一条,不抄那份清单。
- **装包与改配置**:它只读。装包是人的决定,装法由它给出、人执行。