CLAUDE.md · diff

git:20260910.ec1ba16 to git:20260910.1e5fbcf

1 added, 1 removed. Audit A to A.

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Overview
ascend-sleuth is an Agent Skills-based diagnostic system for Huawei Ascend NPU training/inference issues. It structures support knowledge into an evolvable, multi-tier system so problem diagnosis improves over time rather than rotting.
This is a **knowledge/skills repo** — there is no build, no lint, no test suite, no application code. Everything is YAML case files, Markdown skill definitions, and Markdown postmortems.
## Architecture
### 三个闭环(读这套系统之前先分清)
系统由三个闭环构成,**混起来读是理解这套机制最大的障碍**。判断一个动作属于哪个闭环,比记住任何机制名都重要:
| 闭环 | 何时发生 | 入口 skill | 产出 |
|------|---------|-----------|------|
| **诊断闭环** | 每次问题(分钟级) | `diagnose`(被打断则 `resume-diagnosis`) | 修复建议 + `traces/<session>.yaml` |
| **沉淀闭环** | 定位结束 / 定期批量 | `to-postmortem`、`to-reference`、`issue-ingest` | `postmortems/inbox/` 草稿 → groom 升格为 case / reference |
| **演进闭环** | 内容流程收尾 / 全库体检轮 | `evolve-check`(伴随)、`self-evolve`(深度轮) | EV 卡 → 执行 → 验证 → 攒批 PR(人审) |
- 三者共用一条链:前两个产生数据,演进读数据改机制,改完回落。**机制地图、权威归属(每件事由哪篇文档说了算)与周度 runbook 在 `docs/evolution.md`——那是演进机制的唯一入口**,其余 `docs/evolution-*.md` 是论证层(改机制本身时才读)。
+ 三者共用一条链:前两个产生数据,演进读数据改机制,改完回落。**机制地图、权威归属(每件事由哪篇文档说了算)与周度 runbook 在 `docs/evolution.md`——那是演进机制的唯一入口**,其余 `docs/mechanism/*.md` 是论证层(改机制本身时才读)。
### Three-tier knowledge loading (controls context cost)
| Tier | Content | When loaded |
|------|---------|-------------|
| Tier 1 | `triage-tree.yaml` — symptom → namespace routing (≤30 branches) | Always |
| Tier 2 | `knowledge/<ns>/*.yaml` — structured case rules | Two-phase: read **命中 namespace 的索引分片** `knowledge/_index/<ns>.yaml` first (瘦身行 F2: id/title/symptoms 首条摘要/category/score + file;完整 symptoms/quickly_check 在 case 本体), filter candidates ≤5 by title/symptom-summary/score, then load full body (with quickly_check) to verify. Rebuild index (master + shards) after any case change via `scripts/build_index.py` |
| Tier 3 | `postmortems/` — raw investigation records | Keyword grep fallback when Tier 2 misses |
### Two orthogonal problem dimensions
- **Where** (training vs inference × framework) — determines which namespace directory to search. Encoded in `triage-tree.yaml`'s `search_namespaces`.
- **What** (interrupt / precision / performance) — determines the diagnosis path and `quickly_check` shape. Interrupt uses error-signature grep, precision uses numeric threshold assertions, performance uses profiler metric comparisons. **Do not mix these.**
### Skills
Ten skills in `skills/<name>/SKILL.md`, following the [Agent Skills](https://agentskills.io/) spec. **名单与数量不在此硬编码**——由 `docs/_manifest.yaml` 生成到 README 的「skill 名单」节(`scripts/build_docs_index.py --check` 保证一致)。按"谁用得上"分三组:**你要用的**(`diagnose`、`resume-diagnosis`)、**沉淀知识**(`to-postmortem`、`to-reference`、`issue-ingest`)、**维护与演进**(`knowledge-groom`、`self-evolve`、`evolve-check`、`skill-review`、`preload-panel`)。
- **`diagnose`** — Core diagnostic loop: symptom collection → (data gap? take the tool entry's collection surface) → triage-tree routing → two-phase Tier 2 loading (phase 2.5 loads active references from the prior-knowledge layer) → verify diagnosis checks → output fix or fall back to deep investigation. Writes trace to `traces/<session_id>.yaml` on every step (incl. `reference_lookup` events, `purpose: collect|signature|fix|background`). On fix delivery writes `feedback_pending`; any diagnose/resume startup nags for the outcome (degrades to `feedback_stale` after 2 unanswered attempts — polite, not coercive) and updates case confidence. `disable-model-invocation: true` (user-triggered only).
- **`to-postmortem`** — Case-knowledge injection entry. Accepts inline paste, single file, multiple files, or directory. Extracts symptoms/root cause/fix, suggests namespace, runs semantic validation + redaction, outputs YAML draft + postmortem.md into `postmortems/inbox/` (review queue; human-contributed drafts batch weekly, automation-sourced drafts may be groomed directly). Decoupled from diagnose — any investigation source can feed it.
- **`to-reference`** — Prior-knowledge injection entry. Accepts inline paste, file, URL crawl (`--ingest`), or case-set generalization (`--ingest-cases`); `--update <ref-id>` revises existing entries. Extracts facts/methodologies, classifies by `references/_types.yaml` (error-code is table form — one family per file, append-don't-create), runs a **graded** grill phase (high-confidence single confirmation, low-confidence full rounds), outputs schema-complete YAML with `status: active` directly into the formal type dir (`references/<type-dir>/`); **PR review is the review gate — merge = activation** (deep-review gate for case-derived methodology, ≥3 case refs, enforced at production time by CI). Decoupled from diagnose, parallel to to-postmortem.
- **`issue-ingest`** — Upstream issue (GitHub etc.) → case batch ingestion. Orchestrates fetch (`fetch_issues.py`, slim metadata, no body) → hard filter + heuristic sort (`issue_filter.py`: label pool / comments / title / processed-exclusion) → per-candidate evaluation (subagent reads body, judges distillability) → distill via to-postmortem (drafts into `postmortems/inbox/`) → `--mark-imported` for idempotent state. Prerequisite: gh installed + `gh auth status` (guide `gh auth login` web flow otherwise). Framework differences (repo / label system) parameterized. Promotion splits by scenario: default drafts go through owner batch review; owner-preauthorized automation source (this pipeline) may groom directly without waiting for weekly batch.
- **`knowledge-groom`** — Maintenance: batch-process the case inbox queue (pre-triage new_pattern / variant_of / covered_by, human accepts), promote postmortems to Tier 2, validate references, detect value duplication, recalculate confidence scores with time decay, soft-retire stale cases, report namespace capacity, rebuild `knowledge/_index.yaml`; parallel reference-layer maintenance (draft review, degradation signals, observability writeback, index-trigger check). Human-contributed drafts batch weekly; automation-sourced drafts may be processed immediately. `disable-model-invocation: true`.
- **`resume-diagnosis`** — Reads `traces/*.yaml` to resume an interrupted diagnosis session. `disable-model-invocation: true`.
- **`self-evolve`** — Self-evolution deep round + batch aggregator. Explicit deep review of the whole knowledge base (capacity / attribution aggregation / metrics / S2 set) when the user says "run a self-evolve round" or "what could be improved"; also aggregates evolve-check cards into one review PR. `disable-model-invocation: true` (user-triggered only).
- **`evolve-check`** — Lightweight post-content-flow evolution check (default, no separate goal round). After a content task (issue-ingest / to-postmortem / to-reference / knowledge-groom) finishes, checks for improvement signals (≥3 same-root cases → generalize, coverage gaps, repeated manual steps, component failure clusters); produces EV cards only when a signal fires, one line otherwise. Reads the round's on-site record through `scripts/tail_exec_log.py` (never inline python; a missing/empty exec-log is a normal degradation path, exit 0) and **logs its own closing record — including the no-signal case** (`log_skill_exec.py --skill evolve-check`), so "ran and found nothing" is distinguishable from "never ran" (surfaced in the ev-panel 执行现场 section).
- **`skill-review`** — Quality/UX review of a skill (default `diagnose`): five lenses — static audit (rule density, output-segment count, judgment-vs-step ratio, resident token cost), perturbation probes (ordering / information saturation / false premise / hurry-up / wording drift), blind discrimination + persona walkthrough, bad-path experience (empty KB, all-miss, no data, second failure, flow-vs-evidence conflict), attention budget. Report → `proposals/reviews/` (local), improvements → EV card. **Never a CI gate**: experience is a judgmental norm, hardening it is fake hardening. `disable-model-invocation: true` (user-triggered only).
- **`preload-panel`** — Loads DSH visualization panels (diagnose / metrics tabs) via `cordis_define` + `cordis_run`. DSH only.
### Reference layer (prior knowledge)
`references/` holds prior knowledge (facts + methodologies independent of any specific incident), parallel to cases. **Layer position: reference is NOT a fourth retrieval tier** — it never participates in candidate routing/filtering; routing and ranking see cases only. What it does have is **two consumption points, both keyed to a gap in the flow**: the **data gap** (no measurement data yet → the tool entry's collection surface, consumed at step 1, before candidates load) and the **judgment gap** (a candidate is loaded but signature/background/fix evidence is missing → phase 2.5). Both load `status: active` only. The step-1 binding (category → question → branch → ref ids) lives in data, not prose: `skills/diagnose/references/collect-gates.yaml`, whose ids are CI-checked by `verify_references.py` (a hardcoded ref-id in prose once rotted silently):
- **Two organization forms** (organization unit = verification unit): dataset tables (error-code / fault-pattern / env-var-table — one family/domain/module per file, e.g. `errors/ge.yaml` holds the E1xxxx family) vs independent entries (fact: platform-fact / software-fact / tool / command-side-effect; flow: methodology).
- **Lifecycle**: to-reference produces `status: active` → PR review is the gate → merge = activation. Diagnose phase 2.5 loads **active only** — unmerged PR branches are not on main, so unreviewed content never enters diagnostic context (no draft intermediate state; legacy drafts from before this change are groomed out). Revision of active content is `kb/high-risk` (dual sign-off); degradation signals (low resolve-rate, stale `last_verified`, dead sources) come from observability + groom.
- **Clustering rules**: family division follows source; append-don't-create (new error code goes into the existing family table); relate-don't-merge (theme aggregation via `tags`/`related_references`, not file merging).
- **No graph store** — relations are light single-hop, lexically expressible; graph algorithms (if ever needed for v2 trace mining) stay in offline tooling memory.
### Case schema (YAML in `knowledge/<ns>/`)
Each case file has: `id`, `title`, `category` (interrupt|precision|performance), `tags`, `platforms`, `compat` (multi-dimensional: framework/CANN/HDK version ranges), `confidence` (hits/misdiagnoses/score managed by groom — **只承载 S1 现场 resolve 口径**), `symptoms`, `quickly_check` (primary + fallback regex), `diagnosis` steps with `command_template`/`expected`/`fix_on_mismatch`/`rollback`, `severity` (benign|service-affecting|data-loss-risk), `fix_type` (env-var|config-change|code-patch|pending-investigation), `root_cause`, `fix`.
Optional field — `validation_record`: {consistent, inconsistent, self_consistent, last_verified} — 内容被**外部验证**的累积记录(由 `scripts/settle_s2_feedback.py` 结算,非人设定)。与 confidence 分开:S2 issue-replay 对照的是外部 ground truth(issue resolution / 维护者 fix PR / committer 确认),其结果也是 feedback——反馈对象是"case 内容正确性"而非"fix 现场有效性"。`consistent`=外部验证一致(同等 score 下排序优先)、`self_consistent`=自证命中(replay issue 即 case 来源——如实标注不虚增)、`inconsistent`=命中但结论与 resolution 不符(复审信号)。无 S2 验证不填。
Optional field — `source_ref`: {repo, ref, file, line} — 根因定位到源码时的代码位置(如 `vllm_ascend/quantization/modelslim_config.py`)。诊断时 agent 按需取该版本源码片段作为证据链。**「源码不落库」= 源码不随仓库提交、也不写进知识库**——`.gitignore` 已忽略 `src-code/<org>/<repo>/`(作为本地分析缓存,按需 `git clone`/checkout 到对应版本、同版本**复用**以免重复 clone);知识库只记结论 + `source_ref` 代码指针(上游 repo 维护各自版本)。「不落库」≠ 分析不需要/不保留源码——深入排查**仍要 clone 源码**。ref 用触发版本对应的 commit/tag;`line` 可选。
Optional field — `ref_knowledge`: structured linkage to prior-knowledge entries in `references/`. Each entry is `ref: <reference-id>` + `role: signature-source | fix-methodology | root-cause-context`. `ref` must exist in `references/` and `role` must be legal — enforced by `scripts/verify_references.py` (dangling refs and illegal roles fail CI). The reverse view (which cases reference a given entry) is derived by that script, never stored on the reference side — one relation, stored once. Not required on existing cases; add as needed.
Version matching is **soft**: compat mismatch downgrades confidence but never hard-excludes a case. Undefined dimensions are skipped.
### Severity gate
诊断输出的安全语义——不是通知机制(通知链路已移除,见 roadmap):诊断系统只输出建议,不接管通知行为。
- `benign` → give fix directly
- `service-affecting` → give fix but flag `fix_side_effects` (e.g., requires-restart)
- `data-loss-risk` → **do not give fix**; output "halt training, preserve state, notify owner"
**为什么需要 data-loss-risk 档**:诊断输出是给工程师的执行建议。若根因是"checkpoint 可能被污染"(数据损坏风险),给 fix 让工程师继续跑 = 可能加速损坏——高危场景的正确动作是**停**不是**补丁**(诚实退化的延伸:不确定就承认、高危就停)。"通知 owner"是给工程师的一句话建议,不是系统对接 on-call/IM 的链路。
### Platform dispatch
Platform differences are **field-level** within cases, not separate cases. A single case can have multiple `diagnosis` blocks keyed by `platforms` (e.g. `A2-910B`, `A3-910C`, `A5-950`); a case with no `platforms` field is treated as cross-platform. Platform background docs were abolished (agent-generated, zero external sources) — platform facts live in the reference layer (`references/platform-facts/`, populated via to-reference with real sources). Diagnose phase 2.5 injects platform background summary (summary layer) for matched platforms; unmatched platforms get no platform prior (each case still carries its own platform evidence in its `platforms`-keyed diagnosis branches).
### Trace and misdiagnosis attribution
Every diagnose step writes to `traces/<session_id>.yaml` trace array (trajectory: `{role, ...}` events). On misdiagnosis, read the trace to determine: **case error** (fix the knowledge YAML) vs **execution error** (fix the skill body). Without trace, misdiagnosis attribution is impossible and you risk corrupting correct cases.
**Trace schema 关键字段**(诊断面板 + 跨 agent/session resume 的数据源):
- `summary`:agent 诊断收尾整合的问题背景段(什么问题/环境/关键报错/定位结果)——面板展开直接显示,人不必逐个打开证据
- user 事件 `content`(摘要)+ `evidence`(完整证据:`inline` 原文 / `files` 相对路径 / `sources` URL / `missing` 缺口)——**跨 agent/session 自包含的关键**(平台 memory 不可跨,新 agent 靠 trace 证据重建);大文件落 `traces/evidence/<session_id>/`
- agent 事件 `output`(给用户)+ `reason`(决策依据,关键决策必写)——回放/归因/沉淀的证据
- `created_at`/`updated_at`:诊断面板按 `updated_at` 排序(resume 续接刷新 → 置顶)
- `resume` action:续接事件(resume skill 必写 + 刷新 updated_at)
**诊断面板**(DSH 插件)展示:会话列表(状态/时间/计数徽章)→ 展开轨迹(summary/evidence/reason/reference 参与标注)→ 证据文件可点击打开。
### Eval
Golden-case regression suite in `eval/golden/`. Public repo contains only constructed examples (no real customer data). Real fixtures go in a private repo. Run before/after skill changes: feed fixed input via replay mode, verify namespace routing + case matching + fix content against `expected`. LLM non-determinism means asserting "top-3 hit" rather than "must be first."
**门禁分级(改哪里测哪里,不机械全量)**:检索/路由/候选选择面 → golden 子集 + 基线缓存;交互/追问/指引面 → ixn 对口样本(**不跑检索 golden**);输出契约/交互形态 → 盲辨对照(主观成败只有对照能证);纯文档 → 不跑 replay。分级表与判据强度在 `docs/eval.md`。
**封存对照集(holdout)——"无回归"是否有意义的前提**:`eval/golden/` 在改动者可写面内,且 groom 被要求跟着 case 改夹具,所以"golden 无回归"原本是**可控信号**。`eval/holdout.yaml` 把一部分夹具按内容哈希封存(`scripts/holdout.py --check`,CI `holdout-integrity` job):改封存夹具内容或删除即红;合法改需维护者 `--reseal` 且 PR 带 `holdout-change` 标签。`--list` 报出"有 case 却无夹具"的格子。**覆盖率仍有缺口**(training / common 段无夹具)——改 skill 对那些场景没有 golden 信号,别把"CI 绿"读成"全都测过"。
**评审把手**:EV 卡的 `predicted_effect.measure` 给出"一条命令 + 期望",`python3 scripts/ev_measure.py <卡号> --run` 打印实测并判 `符合 / 被证伪 / 无法判定` 三态。它证明**效果**,不证明价值("命令是否真在测那件事"是约定强度)。
## Multi-agent collaboration (worktree 约束)
多 agent/session 可能并发操作同一仓库——**共享检出目录是冲突根源**(未提交改动随 checkout 流动、共享状态文件互相覆盖)。本仓库约定(机制细节见 `docs/git-workflow.md`「多 agent / 多 session 并行」节):
- **必须在独立 worktree 中工作**:每个 agent/session 使用 `git worktree add <路径> <自己的 kb/* 分支>` 检出独立工作区,禁止直接在主检出目录修改/提交(`git worktree remove <路径>` 清理)。
- **git 强制的边界**:worktree 隔离工作区/index/未提交改动;同一分支同时只能被一个 worktree 检出(git 拒绝重复检出)。
- **worktree 不隔离的(合流时显式解决)**:refs 全局共享(分支名 `kb/<用途>` 全局唯一);共享状态文件(`ingest-state.json` 的 processed、`metrics/timeline.yaml`、`knowledge/_index.yaml`、`postmortems/inbox/`)在各 worktree 是各自分支副本——并发修改靠 PR merge 显式合并,不靠覆盖。
- **exec-log 是"同一克隆共享"的运行时件(跨 worktree 共写共读,跨克隆不聚合)**:`metrics/skill-exec-log.yaml` 虽在 `.gitignore` 里,但路径由 `scripts/exec_log_path.py` 解析到**主检出**(`git rev-parse --git-common-dir` 的父目录)——**所有 worktree 写的是同一份**,因此代理在 worktree 里收尾落的记录,主检出(= 用户会话 cwd / 面板读处)立刻可见,且 worktree 清理不会连带丢数据。它是 read-modify-write:**写侧持 flock**(并发实测:无锁 16 次写入只剩 3 条),别用其他方式直接改写它。读法一律走 `scripts/tail_exec_log.py`(自带路径与共享范围标注);跨克隆/跨机的口径走它的 `--summary` 聚合值进 `metrics/timeline.yaml`,流水本身不进 git。
- **串行操作**:`ingest-state.json` 的 fetch / `--mark-imported` / 游标更新是 read-modify-write 无锁,必须串行;groom 清空 inbox 前先确认无其他 session 未提交草稿。
- **开工/收工纪律**:开工 `git fetch origin` 确认最新 + 确认自己在自己的 worktree 与分支;收工前提交或 stash,不留未提交改动。
## Key constraints
- **Normative foundation:** all design/implementation/evolution changes must be traceable to `docs/design-principles.md` (the normative articles); the derivation chain lives in `docs/design-theory.md` (four axioms → formulas → principles). An untraceable rule is suspect; an unexplainable real-world choice indicts the theory.
- **Diagnose does not access customer environments.** All info (logs, versions, errors) comes from the engineer pasting it. The agent's role is to ask for what's missing when information is insufficient.
- **Agent never applies fixes to production.** Fixes are suggestions for the human to apply.
- **知识库结构性状态**:实时数字(各 namespace 条数/容量,含 soft_cap=30 容量治理信号)以 `python3 scripts/build_index.py` 生成的 `knowledge/_index.yaml` 头部注释为准,**不在 CLAUDE.md 硬编码**(具体条数/哪个格子接近上限随 KB 增长腐烂——如 verl 从空到非空、容量格子持续增长);按周 append 的指标时序数据在 `metrics/timeline.yaml`(结构由 `verify_metrics.py --check` 校验),机制定义见 `docs/metrics.md`。通用原则:
- namespace 是否有内容以 `knowledge/_index.yaml` 头注为准;空的 namespace 走 Tier 3 fallback,不假装有内容可检(与 `triage-tree.yaml` 头部注释同源)
- canonical sample 仍是 `examples/sample-case.yaml`
- **人读面的名单与数字同样不硬编码**:skill 名单、文档目录由 `docs/_manifest.yaml` 生成到 README(`scripts/build_docs_index.py`;`--check` 进 CI `docs-index` job,**生成物不一致或 `docs/` 下有未登记文档即红**)。改文档或 skill 后跑它。手写数字会腐烂且不报错(实测:入口文档曾写"123 条 case / 7 张 EV 卡",实际已 158 / 50)。
- **代号有生存范围**:`docs/glossary.yaml` 每条带 `scope`。记账号(roadmap 事项 A/E/M/O/P、治理缺口 G、触发信号 T、落地阶段 Phase)**只在各自的计划文档里裸用**;你写的 PR body / EV 卡 prose / 机制文档要引用就写中文含义(`scripts/render_review_summary.py --scan <文件或目录>` 会报越界)。同形冲突(`A1/A2/A3` = 公理 / roadmap 事项 / 平台前缀;`P0` = 优先级)已登记消歧,别新增同类。`docs/adr/` 与 `proposals/` 是只追加档案,豁免且不追溯。
- **Public/private separation:** `skills/`, `references/`, `examples/` are methodology (public). `knowledge/` and `postmortems/` with real content contain customer data and must stay private. `.gitignore` enforces this boundary for `traces/` files.
- **Index freshness:** `knowledge/_index.yaml` is generated by `scripts/build_index.py` and committed. After changing any case YAML, regenerate it; `--check` (run by groom and the kb-checks CI) fails on staleness. Retrieval is deliberately lexical/structural — no vector RAG (see `docs/adr/0002`).
- **Git gating:** KB changes land via PR — triage labels (`kb/new-pattern|variant|covered`), `kb/high-risk` dual sign-off, CODEOWNERS-based review (see `docs/git-workflow.md`; `CODEOWNERS.example` is a placeholder until owners are named). Deployable centralized or as a framework fork — knowledge dirs never merge from upstream.
- **Skill self-containment (CI-enforced):** skill files (`skills/**`) must not reference ADR numbers (`ADR-\d{4}`), dates (`20\d\d-\d\d`), or EV card numbers (`EV-\d{4}-\d{3}`) — ADRs get revised/absorbed; a number anchor makes skill behavior look externally defined; dates read as facts; card numbers rot when the card is superseded. Behavior rules must be inline; traceability belongs to git/PR/card history. This is a *hygiene* check (mechanical + recurrent), not a correctness check.
- **EV 卡的预测必须可复现 (CI-enforced):** `predicted_effect.measure` 要带一条命令 + 期望(`expect_exit` / `expect_stdout` 至少一项),或如实声明 `reason`(不可度量)。缺它则"评审 30 秒判定"无从执行——reviewer 只能开全文或直接批。产卡骨架的占位 `measure` 会被 CI 拦下(忘填 = 响亮失败,不带假绿过审);判 `validated` 前先跑一遍自己的 measure。存量卡(`MEASURE_CUTOVER` 之前)豁免,缺口由 `scripts/ev_measure.py --audit` 如实报出。
- **对照集不由改动者削弱:** `eval/holdout.yaml` 封存的夹具按内容哈希钉住(CI `holdout-integrity`)——改内容或删除即红,要合法改就得维护者 `--reseal` 并带 `holdout-change` 标签。**注意强度**:哈希是硬门,但"谁有权 reseal"在 CODEOWNERS 落实前是半硬(有写权限者仍可打标签),别把它读成"已有人把关"。
- **Check-admission criterion (what deserves CI):** only rules that are ①mechanically checkable, ②have deterministic consequences, ③proven recurrent (failed ≥2×) go into CI. Judgmental norms (grill grading, asking-what's-needed, redaction thoroughness) stay as SKILL.md execution instructions + review spot-checks — never fake-hardened (principle six). Adding a check without meeting all three = over-engineering.
- **提交前必跑的 CI(`kb-checks`,八条)**:`build_index.py --check`(索引新鲜度 + 顺带解析全部 case YAML)、`verify_references.py --check`、`build_ref_summary_index.py --check`、`build_procedure_index.py --check`、`verify_metrics.py --check`、`verify_proposals.py --check`(卡结构 + 生命周期 + 预测口径)、`holdout.py --check`(对照集未被削弱)、`build_docs_index.py --check`(名单与文档目录一致);另有 `pr-template`(PR body 模板结构)与 `skill-self-contained`(skills/ 的 ADR/日期/卡号锚三条 grep)。本地逐条复跑:`python3 scripts/rehearse_evolve_loop.py`(含 CI parity,120 条断言)。**`verify_exec_log.py` 不进 CI**(exec-log 是 .gitignore 运行时件)。
- **No more than 2 consecutive failed case attempts** — fall back to human on the third (serial protection against misdiagnosis cascades).
- **Log clipping is mandatory.** Only paste failed-rank logs + error stack tails into context. Full profiler data overwhelms the ~120K token reasoning sweet spot.