Skip to content
Development
Skill

/pdlc-relate

管理 feature 关系链(set/query/impact/orphans/rebuild/validate)

From plugin
pdlc
1838 skills2 hooks

Claude Code

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

SKILL.md

pdlc-relate.SKILL.md
name: pdlc-relate
description: 管理 feature 关系链(set/query/impact/orphans/rebuild/validate)
argument-hint: "<set|query|impact|orphans|rebuild|validate> [args]"
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
layer: 3
stage: ops
produces:
  - docs/.pdlc-state/_relations.json
  - docs/.pdlc-state/_graph.md
requires: []
next_step: null
terminal_state: null

Feature 关系链管理

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

本命令不是主链路上的阶段:**不追加 `history`,不改 `current_stage` / `next_step` / `last_phase_result`**,也不为此分配功能ID。以下规则不可协商:

1. **文件必须落盘**:正文要求创建的文件必须作为实际文件写入磁盘,不可仅在对话中输出(只要求在对话里输出的,照正文办)。 2. **自检必须执行**:产出后按本命令的自检项逐项核对,不得以"已经很好了"为由跳过。 3. **防循环**:修复只做一次,不递归。修不了的问题记进报告,继续往下走。

**违反任一条 = 立即中止当前命令,输出违规详情,等待人工介入。** <!-- @include-end templates/prompts/iron-law-tool.md -->

管理 PDLC feature 之间的关系链。维护反向索引 `docs/.pdlc-state/_relations.json` 和全局图 `docs/.pdlc-state/_graph.md`。

<!-- @include templates/prompts/relations.md(已内联于下方,无需另读) -->

Feature 关系链(6 种类型)

PDLC 用扁平 feature ID 空间。关系链在 5 个位置冗余表达,本文件是类型与语法的**单一真相源**。

6 种关系类型

| 类型 | 语义 | 方向性 | 示例 | |---|---|---|---| | `extends` | A 是 B 的增量增强 | 有向(A→B) | `user-auth-otp` extends `user-auth-phone` | | `depends_on` | A 需要 B 存在 | 有向(A→B) | `user-profile` depends_on `user-base` | | `supersedes` | A 替代 B(B 进入废弃/待机) | 有向(A→B) | `auth-v2` supersedes `auth-v1` | | `resolves` | A 修复缺陷 B | 有向(A→B) | `F20260603-090000` resolves `B20260520-110000` | | `conflicts_with` | A 与 B 互斥 | 对称 | `payment-stripe` conflicts_with `payment-paypal` | | `relates_to` | 弱耦合,应一起考虑 | 对称 | `password-policy` relates_to `otp-policy` |

**有向 vs 对称**:

  • 有向类型(extends / depends_on / supersedes / resolves)只在源 feature 的关系块里存一条出边。
  • 对称类型(conflicts_with / relates_to)写入时**两端都要镜像**(A.conflicts_with 含 B 时,B.conflicts_with 也必须含 A)。

表达位置 1:文档追溯头(pdlc-trace)

在 PDLC-TRACE 头加一行(无关系时整行省略):

<!-- 关系: extends=F20260510-100000; depends_on=F20260501-090000,F20260415-110000; resolves=B20260520-110000 -->

语法:`type=id` 对,多 id 用 `,` 分隔,多对用 `; ` 分隔。

表达位置 2:状态机关系块(state JSON)

即状态机文件里的 `relations` 块(六键对象,每键一个 ID 数组)。存**出边**;入边由 `/pdlc-relate rebuild` 派生到 `_relations.json`。**只写本功能自己的状态文件**——不要为了「双向」去改对方功能的 `relations`,那是别的功能的状态,改了会让它看起来又被动过。

表达位置 3:反向索引 `_relations.json`(自动生成)

`/pdlc-relate rebuild` 扫描所有 `<id>.json` 关系块 + 文档头,生成正向 edges + 预计算 inbound/outbound index。

表达位置 4:全局图 `_graph.md`(自动生成)

mermaid 可视化。边样式按类型区分:`supersedes` 虚线、`conflicts_with` 粗线、其余实线。

表达位置 5:PRD §6.1 关系表

见 PRD 文档的 §6.1「关系」一节。

校验规则(`/pdlc-relate validate`)

  • 悬空引用:关系指向的 ID 不存在
  • 自引用:feature 关系到自己
  • 循环:`extends` / `depends_on` 链不允许成环
  • 矛盾对:同一目标同时 `supersedes` + `depends_on`
  • 对称一致性:`conflicts_with` / `relates_to` 两端必须互含

<!-- @include-end templates/prompts/relations.md -->

<!-- @include templates/prompts/state-read.md(已内联于下方,无需另读) -->

读状态机之前:先做契约体检

`docs/.pdlc-state/*.json` 不一定都是 `/pdlc-*` 命令写出来的——手写的、旧版本写的、照着格式仿写的 都可能混在里面。字段对不上契约时,**不许边猜边算、再把猜出来的东西当结论**。先体检,再计算; 体检发现的每一处偏差,都必须出现在输出的**最前面**。

1. 跑体检

体检脚本随本 skill 一起分发,就在本 skill 目录下:`scripts/pdlc-state-lint.sh`(运行时会告知本 skill 的 所在目录)。它与正在运行的 skill 同一版本,体检规则——合法阶段名、偏差代码——与下方 §2 一致。

在项目根执行 `bash <本 skill 目录>/scripts/pdlc-state-lint.sh .`。stdout 每行一条偏差:`文件<TAB>代码<TAB>说明`。退出码三态:

  • `0` 已体检、全部合契约 → 照常出结论,不输出体检块
  • `1` 已体检、有偏差 → 照常计算,但输出最前面必须先放「输入契约体检」块(见 §3)
  • `2` 无法体检(缺 jq / 无状态目录)→ 体检块写「无法体检:<原因>」,**不得当成合契约**

体检脚本不可用时(找不到,或当前平台没有随 skill 分发它),按 §2 的规则逐条人工核对, 体检块首行注明「体检脚本不可用,以下为人工核对」。

2. 体检规则(偏差代码)

读侧跳过 `_` 前缀的索引文件(如 `_relations.json`)与 `statusline.json`,它们不是功能状态机。

<!-- finding-codes:start --> | 代码 | 判定 | 读侧怎么处理 | |---|---|---| | `json-invalid` | 文件不是合法 JSON | 跳过该文件,列入体检块 | | `missing-field` | 缺 `feature_id` / `current_stage` / `history` / `next_step` / `created_at` 之一 | 用到该字段的指标,对这份文件记「不可判」 | | `field-type-invalid` | 字段在、类型不对(如 `current_stage` 不是字符串、`history` 不是数组、`last_phase_result` 不是对象、history 条目不是对象) | **按缺失处理**:用到它的指标对这份文件记「不可判」。类型不对的时间戳不再另报 `timestamp-no-time` | | `missing-last_phase_result` | 缺 `last_phase_result`(多为旧文件) | 不推断本阶段结果与 checks | | `terminal_state-in-instance` | 实例里出现 `terminal_state` | **忽略该字段**,判终态只看 §4 | | `non-contract-field` | 其它表外顶层字段(如 `title`) | 忽略 | | `stage-alias` | `stage` 用了已知别名 | 可按说明里的 `别名→短名` 归一化计数,**但必须在体检块写明归一化了哪些** | | `stage-unknown` | `stage` 既不是短名也不是已知别名 | 单独成行,不并入任何阶段 | | `current_stage-unknown` | `current_stage` 既不是短名,也不以 `_done` 结尾 | 该功能归入「❓ 异常」 | | `next_step-not-command` | `next_step` 不是纯命令名(如带散文后缀) | 按原文展示,不据此推断下一步 | | `timestamp-no-time` | 时间戳只有日期、没有时刻 | 依赖它的**耗时类指标记「不可测」**,不得算成 0 | | `relations-not-object` | `relations` 不是六键对象(如数组) | 这份文件的关系**不入图**,列入体检块 | | `relations-unknown-type` | 关系键不在六类之内 | 该键下的关系不入图 | | `relations-target-not-id` | 关系目标不是 feature ID(散文、模块路径等) | 该条不入图 | | `relations-dangling` | 目标 ID 没有对应的状态文件 | 标「悬空」,不参与影响半径计算 | | `id-prefix-mismatch` | 走的是修复流程(有 `fix` 阶段),ID 却不以 `B` 开头 | 缺陷计数按 ID 前缀的契约口径算,同时在体检块点名这份 | | `checks-key-unknown` | `last_phase_result.checks` 里有状态机不认的键(如照抄 yml 的 `unit` / `lint`) | 该键当作不存在:对应维度记「无法判定」,**不**按键名猜它对应哪个 check | | `checks-value-invalid` | check 的值不是布尔也不是 `null`(如 `"4 passed, 1 failed"`) | 该项记「无法判定」,不从字符串里解析结论 | | `ok-checks-mismatch` | `ok=true`,但有 check 为 `false` | **以 checks 为准**:本阶段按未通过展示,在体检块点名这份 | | `done-legacy` | `current_stage` 以 `_done` 结尾,但不是 `ship_done` / `deploy_done`(旧版写法) | 按「已走完」展示但标「是否已发布未知」;`/pdlc-ship` 会列出来请人确认 | | `second-state-dir` | 仓库根另有一个 `.pdlc-state/` | 本命令只读 `docs/.pdlc-state/`,提示两处并存 | <!-- finding-codes:end -->

**「不入图」不是丢弃**:关系目标是散文时,把它硬解读成某个 feature,等于把猜测升格成结构—— 影响半径会因此多出一条本不存在的强依赖。宁可在体检块里原样列出,交给人判断。

阶段短名全集

`history[].stage` 与 `last_phase_result.stage` 只能取下表的短名——每个短名由对应命令写入, 等于该命令 frontmatter 的 `stage:`。别名只为**读**旧数据时容忍,归一化必须披露;**写**的时候一律用短名。

<!-- stage-names:start --> | 短名 | 由哪个命令写入 | 已知别名(读侧可归一化,须披露) | |---|---|---| | `requirements` | `pdlc-prd` | `prd` | | `design` | `pdlc-design` | | | `tdd` | `pdlc-tdd` | | | `impl` | `pdlc-implement` | `implement, implementation` | | `review` | `pdlc-review` | | | `e2e` | `pdlc-e2e` | | | `ship` | `pdlc-ship` |

Read more
@kanfu-panda
Ships withpdlc

Author: kanfu-panda Repo: github.com/kanfu-panda/pdlc-skills License: MIT pdlc-skills is built on one rule: an AI saying "done" doesn't count — exit codes do.

Stars on GitHub

Momentum

stars in total
18
Star history of kanfu-panda/pdlc-skills on GitHub, a chart by star-history.com

Other skills on pdlc.

pdlc-add-app

pdlc-add-app

在已有项目里加一个前端应用(先探测布局,跟随现有目录与技术栈);新项目一次性初始化用 /pdlc-bootstrap

@kanfu-panda@kanfu-pandaInstall Skill
pdlc-add-service

pdlc-add-service

在已有项目里加一个后端服务(先探测布局,跟随现有目录与技术栈);新项目一次性初始化用 /pdlc-bootstrap

@kanfu-panda@kanfu-pandaInstall Skill
pdlc-adopt

pdlc-adopt

已有代码、还没有 PDLC 文档的老项目接入——只读扫描后逆向生成基线文档并做健康检查,不改代码;空目录新项目用 /pdlc-bootstrap

@kanfu-panda@kanfu-pandaInstall Skill
pdlc-arch

pdlc-arch

架构分析(生成/更新 docs/ARCHITECTURE.md 系统架构总览 · surface 型)

@kanfu-panda@kanfu-pandaInstall Skill
pdlc-bootstrap

pdlc-bootstrap

空目录从一句话描述初始化新项目(服务 / 应用拆分、技术栈、目录骨架与 PDLC 文档目录);已有代码的项目用 /pdlc-adopt

@kanfu-panda@kanfu-pandaInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc11d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about pdlc-relate.

Which coding agents can use pdlc-relate?
pdlc-relate installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.