Skip to content
Back to skills

Pdlc Quality

ASecurity

质量闸门——跑真实 check、对照质量目标、出可核对报告,由人签字放行

  • 16 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 6, 2026
ai-agentsgobashgit

Works with

  • terminal

Security analysis

A100/100

Scanned September 25, 2026

npx -y skills add kanfu-panda/pdlc-skills --skill pdlc-quality --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Pdlc Quality?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Pdlc Quality
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/kanfu-panda-pdlc-quality/badge)](https://www.skillsdirectory.com/skills/kanfu-panda-pdlc-quality)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: pdlc-quality
description: 质量闸门——跑真实 check、对照质量目标、出可核对报告,由人签字放行
argument-hint: [--init] [--autonomous]
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
layer: 3
stage: quality
artifact_type: ledger
produces:
  # 主产物(ledger 型,一次一份可看趋势);.md 是真源,.html 是同数据的可视化视图
  - docs/07_reviews/quality/<YYYY-MM-DD>.md
  - docs/07_reviews/quality/<YYYY-MM-DD>.html
  # 仅 --init 时创建(surface 型,就地编辑不累积)
  - docs/00_standards/quality-targets.yml
  - docs/00_standards/e2e-flow-map.yml
requires:
  - docs/00_standards/test-commands.yml
next_step: null
terminal_state: null
recommended_model: sonnet
recommended_effort: medium
---

# 质量闸门与报告

跑真实 check → 对照质量目标 → 出可核对的报告 → **人签字放行**。

<!-- @include templates/prompts/iron-law.md(已内联于下方,无需另读) -->
⛔ **IRON LAW · 不可违反的硬门禁**

以下规则为**不可协商**的执行约束:

1. **文件必须落盘**:所有带编号(功能ID / 缺陷ID)的文档,必须作为实际文件写入磁盘,不可仅在对话中输出。
2. **阶段必须落章**:每个阶段完成后必须在状态机 `docs/.pdlc-state/<feature-id>.json` 追加 history,不可跳过。
3. **测试必须存在**:进入 `/pdlc-implement` 前,对应测试必须存在且处于红灯状态。违反则中止。
4. **自检必须执行**:段二自检为强制步骤,不得以"已经很好了"为由跳过。
5. **防循环**:段三修复为单次,不递归。无法自动修复的问题记录到报告,继续往下走。
6. **状态必推进**:成功执行某 phase 后 `current_stage` 必须变更。收尾时若发现 `current_stage` 未推进,视为失败并报错,**不得静默返回**(防止外层循环拿滞后的状态空转烧额度)。唯一例外:命中人工点主动 block 时,`current_stage` 保持不变但必须写 `last_phase_result.ok=false` + `blocked_reason`。

**违反任一条 = 立即中止当前命令,输出违规详情,等待人工介入。**
<!-- @include-end templates/prompts/iron-law.md -->
<!-- @include templates/prompts/noninteractive.md(已内联于下方,无需另读) -->
## 非交互模式(`--autonomous`)

若本命令的参数含 `--autonomous`,本命令进入**无人值守**模式,按以下规则处理原本需要人应答的交互点。**参数是唯一真源**:不带 `--autonomous` 即为交互模式,一切照旧正常询问用户;绝不回读状态机 `run_mode` 兜底(「掉出 autonomous」是安全的失败方向)。

1. **流程性确认**(如「测试已绿是否继续」「是否覆盖已有文件」)→ **不询问**,按预设默认前进,并把决策追加到状态机 `history[].auto_decisions[]`:
   ```json
   { "point": "<确认点描述>", "chose": "<所选默认>", "at": "<ISO 8601>" }
   ```
2. **真需人判断**(PRD 关键取舍、评审「需人工确认」项、真实循环依赖等无法安全默认的点)→ **不猜**:
   - `current_stage` 保持不变(不推进)
   - 写 `last_phase_result.ok = false` 且 `blocked_reason = "<原因>"`
   - 末行输出哨兵:`<<<PDLC blocked reason="<原因>">>>`
   - 立即结束命令,交还人类
3. **破坏性操作**(发布 / 部署 / 打 tag / 触发 CI / DROP / force-push 等不可逆·外发操作)→ `--autonomous` **无效**,仍必须人工显式确认。
4. **顺手的 sidecar 产物**(如缺失时创建 `CHANGELOG.md`、补全文档 PDLC-TRACE 的创建时间等本阶段职责内、可安全默认的辅助改动)→ 视为流程性默认,**直接做并记入 `auto_decisions[]`**;这类改动不新增外部副作用,不属破坏性操作。

> 进入 autonomous 模式时,在状态机顶层写 `run_mode: "autonomous"` 仅供留痕(复盘区分人工 vs 循环产出)。
<!-- @include-end templates/prompts/noninteractive.md -->

## 这个命令的立身之本

**一切判定来自客观数据**:覆盖率数字来自覆盖率工具、E2E 覆盖来自 flow→test 映射 + 真跑结果、lint 来自退出码。
**AI 只负责把这些数据整理成报告,不参与"达标与否"的判定**,放行由人。

> ⛔ 绝不允许出现的行为:用"我看了一下代码,测试挺全的"这类判断替代真实数据;
> 用上一次的结果冒充本次;命令没跑通却按通过处理;覆盖率没测量却写一个数字。
> **量不到就如实写"未测量"**——这与状态机里「无命令可跑 → `checks: {}`」是同一条纪律。

## 前置:两份真源

| 文件 | 作用 | 缺失时 |
|---|---|---|
| `docs/00_standards/test-commands.yml` | 怎么量(命令) | **中止**,提示先跑 `/pdlc-test-setup` |
| `docs/00_standards/quality-targets.yml` | 量到多少算达标 | 走 `--init` 交互创建(见下) |
| `docs/00_standards/e2e-flow-map.yml` | 核心流 → E2E 测试 的映射 | 若 targets 里声明了 `core_flows` 则**必须有**,否则 E2E 判定无法机械化 |

### `--init`:首次建立目标声明

1. 读 本 skill 目录下的 `assets/quality-targets-template.yml` 作骨架。
2. **从 PRD 自动抽 `core_flows` 草稿**:扫 `docs/01_requirements/prd/`,提取标记为 **P0 / P1** 的功能流程,
   生成候选清单(含来源 PRD 路径)**供人确认**——降低首次声明的摩擦,但**最终清单必须人确认**,不自动落盘。
3. 覆盖率达标线:默认与 `test-commands.yml` 的 coverage 命令参数对齐;两者不一致要提示人对齐
   (**以命令参数为准**——那才是真正的强制点)。
4. 同时生成 `e2e-flow-map.yml` 骨架(每条 flow 一个空 `tests` 列表待填)。

## 段一:跑真实 check

按 `test-commands.yml` 逐条真跑 `coverage` / `e2e` / `lint`,记录**命令原文 + 退出码 + 关键输出**。
退出码的三态语义、以及「命令跑不了 = yml 过期信号」按下面的规则处理:

<!-- @include templates/prompts/check-commands.md(已内联于下方,无需另读) -->
## 跑 check 命令:退出码的三态语义

命令取自 `docs/00_standards/test-commands.yml`(唯一真源)。逐条真跑,**按退出码分三态**——
不是两态。这是 IRON LAW「checks 只认客观事实」在执行层的落法:

| 观察到的 | 含义 | 写进 `checks` |
|---|---|---|
| 退出码 `0` | 通过 | 对应键 = `true` |
| 退出码非 0(命令**跑起来了**,只是没过) | 未通过 | 对应键 = `false` |
| 退出码 `127` / `command not found` / 脚本文件不存在 / 该项为空字符串 | **无法判定** | **省略该键,或写 `null`**——**绝不能是 `false`** |

> ⛔ **唯一的红线是不许写 `false`**:那是**会误导人的虚报**——它说的是"检查失败了",
> 于是有人去查代码,但真正的问题是**配置过期**,代码可能完全没毛病。
>
> **省略键与 `null` 等价,两种都可以**:对消费方而言无法区分(`jq '.checks.lint_clean'`
> 在两种情况下都返回 `null`)。`null` 甚至更明确——省略是歧义的("没看"还是"看了判不出"),
> `null` 明说"看了,判不出"。**别在这上面纠结,力气花在不写 `false` 上。**
>
> 这与「没有检查命令可跑的阶段 → `checks: {}`」同源。

## 「跑不了」= `test-commands.yml` 过期信号(顺带检测,零额外成本)

命令跑不起来,几乎总意味着**这份 yml 已经跟不上项目了**——脚本改名、runner 换了、
工具从依赖里移除、子项目路径调整。真实项目里这类漂移是常态(例如某前端框架升级后
移除了内置 lint 子命令,而 yml 里那条命令还在)。

由于**各阶段本来就在跑这些命令**,这个信号是白捡的。检测到时:

1. 在本阶段的报告里单列一条:**「`test-commands.yml` 疑似过期」**,写明是哪一项、
   观察到什么(退出码 / 报错原文)、以及为什么判定为"跑不了"而非"没通过"。
2. 提示补救:`/pdlc-test-setup --refresh`(重新探测并给出 diff)。
3. **不要自作主张改 yml**——本阶段的职责是干活,不是改配置;只报告,不动手。

## 变更方向决定自动化程度(`--refresh` 时适用)

更新这份 yml 等于**改变"通过"的定义**,所以按**方向**区别对待:

| 方向 | 例子 | 处理 |
|---|---|---|
| **让闸门变严** | 空着的 `e2e` 现在能跑了、覆盖率阈值上调 | **可自动应用**,报告留痕 |
| **平移替换** | 命令改名但语义相同,且新命令**已验证能跑** | **可自动应用**,报告留痕 |
| **让闸门变松** | 删掉某条 check、把命令改成空、下调阈值 | **必须人确认**,绝不自动 |

> ⚠️ 这条方向规则是防「自动修复把闸门修没了」:lint 命令坏掉时,**把它留空**是最省事的
> "修法",结果闸门悄悄松了、报告还是绿的——比不更新更危险。
> **变严可以自动,变松必须由人签字。**
<!-- @include-end templates/prompts/check-commands.md -->

补充两条本命令特有的:

- 命令为空字符串(项目未配置该项)→ 如实记为「留空,未测量」,**不得因此判为通过**
- 覆盖率数字从工具输出中**摘取原文**,不重新计算、不四舍五入到好看的数

## 段二:三项机械核对

### 2.1 覆盖率

拿实测数字对 `quality-targets.yml` 的达标线。真正的强制点是命令参数里的阈值(如 `--cov-fail-under=85`)——
**退出码就是判定**;yml 里的数字用于报告展示与趋势。两处不一致 → 报告里提示对齐。

### 2.2 E2E 覆盖矩阵(B2 的第一个地基)

对每条 `core_flow`,按 `e2e-flow-map.yml` 找到映射的测试标识,再到**本次真跑的 E2E 结果**里核对:

| 情况 | 判定 |
|---|---|
| 映射存在 且 对应测试本次通过 | ✅ |
| 映射存在 但 测试本次失败 | ❌ |
| 映射存在 但 该测试在本次结果里**找不到** | ❌ **映射腐烂**(指向了不存在的测试) |
| `core_flow` 在映射文件里**没有条目** | ❌ 缺映射 |
| 映射里有 `core_flows` 中不存在的 id | ⚠️ 黄:孤儿映射,建议清理 |

**缺一条 = 红。** 绝不用"我觉得这条流程被别的测试覆盖了"来补空缺——那正是要消灭的主观判断。

### 2.3 配置健康度(顺带检测,零额外成本)

段一已经把每条命令真跑了一遍,**过期信号是白捡的**。汇总成报告的一节:

| 状态 | 判据 | 报告里怎么写 |
|---|---|---|
| ✅ 健康 | 命令跑起来了(退出码 0 或非 0 皆可) | 正常 |
| ⚠️ **已失效** | 127 / `command not found` / 脚本不存在 | 「`<项>` 的命令已跑不通——yml 过期」+ 报错原文 |
| 💡 **可收紧** | 该项当前留空,但本次探测到**已可用**的命令 | 「`<项>` 现在可以填了:`<候选命令>`(已验证退出码 `<N>`)」 |
| — 留空 | 该项留空且确无可用命令 | 「留空,未测量」(不得判为通过) |

**本节只报告、不改 yml**——改配置等于改"通过"的定义,要走 `/pdlc-test-setup --refresh`(严向自动、松向人确认)。

### 2.4 PRD ↔ core_flows 对账(B2 的第二个地基,防 false-green)⭐

清单靠"有人记得改"维护必然腐烂;**腐烂的清单产出 false-green**——新增的核心流没进清单,矩阵照样全绿,
把"我们不知道"伪装成"我们覆盖了",比没有闸门更坏。所以每次运行都强制对账:

1. 扫 `docs/01_requirements/prd/` 所有 PRD,提取 **P0 / P1** 流程。
2. 与 `quality-targets.yml` 的 `core_flows` 做 diff。
3. **漂移即红灯**,不是温柔提示:
   - PRD 有、`core_flows` 无 → ❌「PRD 流程 X 未进 core_flows」
   - `core_flows` 有、映射无 → ❌「core_flow Y 尚无映射的 E2E」
   - 映射有、`core_flows` 无 → ⚠️ 孤儿映射

> ⛔ **"不可判"绝不能被当成"没问题"**(对账自身的 false-green,真项目上实测踩到过):
> 若某份 PRD **不含任何 P0/P1 标记**,它提取出的就是空集,于是**不产生任何漂移条目**——
> 报告若就此显示"对账通过",等于宣称"这份 PRD 里的流程都覆盖了",而事实是**它整份都没进闸门视野**。
> 已上线的主链路最容易栽在这里(老 PRD 常只写"已上线/待开发",不标优先级)。
>
> **规则**:统计"因无优先级标记而未参与对账"的 PRD,**在报告里单列告警**,并且
> **对账项不得判为 ✅**——写成 `⚠️ 无漂移,但另有 N 份 PRD 不可判`。
> 处理建议:给这些 PRD 补优先级标记,或在 `quality-targets.yml` 里显式声明豁免(写明理由)。

> 这样清单维护就从"靠自觉"变成**被产物纪律接管**——PRD 本就被 pdlc 逼着落盘并保持最新,
> 让它当 `core_flows` 的唯一上游真源,与「状态外化到磁盘」是同一个哲学。

## 段三:出报告(真源 `.md` + 视图 `.html`)

**① 先出 `.md`(真源)**:按 本 skill 目录下的 `assets/quality-report-template.md` 生成
`docs/07_reviews/quality/<YYYY-MM-DD>.md`(**ledger 型**:一次一份,可 git diff、可看趋势;
同日重跑则覆盖当日文件)。必须包含:

1. 结论红绿表 2. 实测证据(命令 + 退出码 + 关键输出) 3. E2E 覆盖矩阵
4. **配置健康度**(§2.3) 5. PRD 对账结果 6. 趋势(首次则写「无趋势基线」) 7. **人工确认签字栏**

**② 再出 `.html`(视图)**:按 本 skill 目录下的 `assets/quality-report-template.html` 生成同目录同名
`<YYYY-MM-DD>.html`——给人看的那一份,可直接双击打开、可打印签字、可发给同事。

> **`.md` 是唯一真源**:`/pdlc-ship` 的发布闸门读它、`git diff` 看它、趋势对比取它。
> `.html` 只是同一份数据的另一种呈现,**没有任何独立信息**。
>
> ⛔ **铁律:HTML 里的每个数字都从 `.md` 抄,不得重新计算、不得另行判断。**
> 双写最容易出的错就是「两份报告各说各话」——那比没有 HTML 更糟:读者不知道该信哪份,
> 而错的那份通常更好看。两处不一致时一律以 `.md` 为准并改正 `.html`。
>
> 填写要求:只替换 `{{...}}` 占位符与各表格的 `<tbody>` 内容;**不要改 `<style>`**
> (排版由模板负责,改了就失去一致性);删掉模板顶部的「填写说明」注释块;
> 保持自包含——**不得引入任何外部 URL**(css / js / 字体 / 图片一律不许外链:
> 报告含项目内部数据,一张远程图片就够把打开时间、IP、referer 送给第三方,
> 而且离线打不开)。确需图片内联成 `data:` URI。
>
> 三态 class 必须对号入座:`st-pass` 达标 / `st-fail` 未达标 / `st-warn` **无法判定** /
> `st-na` 留空未测量。**`st-warn` 绝不能写成 `st-pass`**——这是 §6.5 那条反模式
> (「把我判断不了当成没问题」)在报告上的最后一道落地面。页头的
> `{{VERDICT_SHORT}}` 只填裸词 `pass` / `fail` / `warn`,一处占位符同时驱动顶条
> 与徽章,顶条不会和总判定说两套话。

## 段四:自检(强制)

<!-- @include templates/prompts/self-audit.md(已内联于下方,无需另读) -->
## 段二:自检(强制)

重新阅读本次产出物,按质量关卡清单逐项检查。勾选已通过,标注未通过原因。

> **注意**:自检清单的具体内容由各命令自行定义,本片段只规定结构。

## 段三:修复(单次,不递归)

针对自检段标注为未通过的项:

- **可自动修复**:直接修复(如补缺字段、修正格式、补齐缺失段落)
- **修复后回验**:再次运行自检,确认被修复项现在通过
- **无法自动修复**:记录到自审报告,不再尝试,流程继续

⚠️ 单次修复原则:若一轮修复后仍有项未通过,**不再递归修复**,防止死循环。
<!-- @include-end templates/prompts/self-audit.md -->

- [ ] 报告里每一条判定,都能追到本次真跑的退出码 / 工具输出 / 映射核对结果
- [ ] 没有任何一项是靠"读代码觉得"得出的
- [ ] 留空 / 无法执行的项,如实标注且**未按通过处理**
- [ ] 覆盖率数字是从工具输出摘的原文
- [ ] E2E 矩阵里每条 `core_flow` 都有明确判定(含"映射腐烂"这种红)
- [ ] PRD 对账已执行,漂移项按红灯列出
- [ ] 配置健康度已汇报:失效项 / 可收紧项都列了出来,且**没有擅自改动 yml**
- [ ] 报告落盘到 `docs/07_reviews/quality/`,含生成时间与 commit SHA
- [ ] 未在报告里替人做 go/no-go 决定
- [ ] `.html` 已同步产出,且与 `.md` **逐项核对过关键数字**(覆盖率、核心流 M/N、各 check 退出码、不可判份数、总判定)——不一致以 `.md` 为准并已改正
- [ ] `.html` 里无残留 `{{` 占位符、无任何外部 URL(含图片)、`<style>` 未被改动
- [ ] 「无法判定」的项在 HTML 里用的是 `st-warn` 而非 `st-pass`;总判定未达标时页头顶条颜色已同步

## 段五:修复(单次,不递归)

<!-- @include templates/prompts/loop-prevention.md(已内联于下方,无需另读) -->
## 防循环规则

本命令所有的自检-修复循环均受以下约束:

1. **单次检查**:同一个自检清单在本次命令执行中只跑一次(起始 + 修复后验证共两次读)
2. **单次修复**:发现的问题只尝试修复一轮
3. **不递归**:修复后不再重新触发自检的全量重跑
4. **失败降级**:无法自动修复的问题 → 记录到自审报告 → 流程继续 → 最终报告标注待人工处理

这是为了防止 agent 在"修完再查、查完再修"的往返中陷入死循环。
<!-- @include-end templates/prompts/loop-prevention.md -->

可自动修复的(如 lint 可自动修的告警)→ 修完**重跑该 check** 并以重跑结果为准,报告里注明"已自动修复后重测"。
不可自动修复 → 如实留红,写进报告。

## 怎么"自动化运行"(不依赖 CI)

- **pre-push 钩子**:push 前本地跑一遍质量闸,不达标就拦或告警——日常自动且**零 CI 成本**
- **按需**:随时 `/pdlc-quality` 出全量报告
- **发布挂钩**:`/pdlc-ship` 会读最近一份质量报告,未达标不让发(除非人显式 override 并写明理由)
- **要"每天一份"**:用本机 launchd / cron 跑,报告进 git;**绝不**用 GitHub Actions `schedule`

## 段六:交接

<!-- @include templates/prompts/handoff.md(已内联于下方,无需另读) -->
## 段四:交接(Handoff)

命令完成后必须输出以下格式的最终消息:

```
✅ <阶段名> 完成:<主要产出物路径>
📊 自检:<通过数>/<总数> 通过(若有未通过,附要点)
📦 状态快照:docs/.pdlc-state/<feature-id>.json
👉 下一步:/pdlc-<next_step>
   (如果有分叉)或 /pdlc-<alt>(条件:<选择依据>)
```

**规则:**
- 主流程命令(写状态机的命令;下一跳见正文里「本命令的状态机取值」)必须显式输出"下一步",不可省略
- 工具型命令(Layer 3)可以没有 `next_step`,此时输出 `👉 下一步:(本次流程结束,无后续)`
- 分叉场景必须说明**选择条件**,例如"若需补充测试用例 → `/pdlc-tdd`;若测试已齐 → `/pdlc-review`"
<!-- @include-end templates/prompts/handoff.md -->

**本命令的 handoff 输出:**

```
📊 质量报告:docs/07_reviews/quality/<YYYY-MM-DD>.md
  覆盖率      : <实测> / 目标 <目标>   ✅|❌
  E2E 核心流  : <M>/<N> 条已覆盖        ✅|❌
  Lint        : 退出码 <N>             ✅|❌
  PRD 对账    : <无漂移 | N 项漂移 | 另有 N 份不可判>  ✅|⚠️|❌
  配置健康度  : <全部健康 | N 项已失效 | N 项可收紧>
🧾 总判定:<达标 | 未达标>
✍️ 待人工签字:报告最后一节(go/no-go 由你拍,本命令不代劳)
👉 未达标项处理:<每条给出具体下一步>
```

## 诚实边界

- **达标不等于质量好**:覆盖率线挡的是"几乎没测",不保证用例有效;矩阵证明"每条核心流有测试跑过",
  不证明"测得对"。报告要如实呈现这层含义,不要把"全绿"说成"质量有保障"。
- **保障强度取决于 `core_flows` 维护得多勤**——这正是 §2.4 强制对账存在的原因,但对账只能发现
  "PRD 里有而清单里没有",**PRD 本身漏掉的核心流谁也发现不了**。这条限制要让用户知道。

---

**参数**: $ARGUMENTS

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.