CLAUDE.md · diff
git:20260905.bea8e96 to git:20260910.e0ac1aa
10 added, 6 removed. Audit A to A.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository purpose
pdlc-skills is a **Claude Code plugin**. It exposes 38 standardized "Product Development Life Cycle" stages as slash commands (`/pdlc-feature`, `/pdlc-prd`, `/pdlc-tdd`, ..., `/pdlc-onboard`) covering PRD → Design → TDD → Implement → Review → Ship → Deploy → Retro and 24 specialized tools.
The repo is **both a plugin and a single-plugin marketplace** (so `claude plugin marketplace add github:kanfu-panda/pdlc-skills` registers it directly).
This plugin is **Claude Code only** — it relies on Claude Code's plugin / skill mechanism. There's no port to Cursor, Copilot, Cline, etc.
## Repository layout
```
pdlc-skills/
├── .claude-plugin/
│ ├── plugin.json ← plugin manifest (name, version, author, ...)
│ └── marketplace.json ← marketplace manifest (so the repo is also a marketplace)
├── skills/ ← 38 sub-skills (each = one slash command)
│ ├── pdlc-feature/SKILL.md → /pdlc-feature
│ ├── pdlc-prd/SKILL.md → /pdlc-prd
│ ├── pdlc-tdd/SKILL.md → /pdlc-tdd
│ └── ... (38 dirs total)
├── bin/
│ └── pdlc-statusline.sh ← optional statusline segment (scanned by /pdlc-settings)
├── references/
│ └── templates/
│ ├── *-template.md ← user-facing document templates
│ └── prompts/*.md ← shared prompt fragments (iron-law / handoff / ...)
├── install.sh ← curl-based one-line installer wrapping `claude plugin install`
├── docs/
│ └── usage-guide.md ← single user manual (architecture + reference + scenarios)
- ├── tests/ ← 6 scripts, all of them part of the local gate
+ ├── tests/ ← 7 scripts, all of them part of the local gate
│ ├── frontmatter-check.sh ← validates skills/<name>/SKILL.md frontmatter
│ ├── install-smoke.sh ← end-to-end install layout test
│ ├── statusline-check.sh ← pdlc-statusline.sh scenario regression
│ ├── adapter-codex-check.sh ← adapters/build_codex.py projection output
│ ├── adapter-codex-loop-run-check.sh ← Codex loop-run mapping + guardrails
- │ └── evals-runner-check.sh ← evals/run.sh driver (stubbed, no model spend)
+ │ ├── evals-runner-check.sh ← evals/run.sh driver (stubbed, no model spend)
+ │ └── evals-scenario-check.sh ← assert_scenario verdicts (stubbed, no model spend)
└── VERSION ← canonical version (mirrored in plugin.json)
```
## Sub-skill naming
Every sub-skill at `skills/pdlc-<name>/SKILL.md` becomes the slash command `/pdlc-<name>` in Claude Code. The `pdlc-` prefix is **part of the skill name**, not a namespace separator. We chose this over the colon namespace `/pdlc:<name>` for two reasons:
1. Visual distinctiveness — typing `/pdlc-` filters cleanly to all 38 PDLC commands; suffix-only names (`/feature`, `/fix`) collide with built-in commands and other plugins.
2. Backwards compatibility — matches the v1 mental model of `/pdlc-feature`.
The full plugin namespace is `pdlc:pdlc-<name>` formally, but Claude Code's autocomplete simplifies to `/pdlc-<name>` since the suffix is unique. Both invocations route to the same skill.
## Common commands
Install / upgrade / uninstall (uses Claude Code's `claude plugin` CLI under the hood):
```bash
# One-line curl install
curl -fsSL https://raw.githubusercontent.com/kanfu-panda/pdlc-skills/main/install.sh \
| bash -s -- --global
# Or, equivalent native commands
claude plugin marketplace add kanfu-panda/pdlc-skills
claude plugin install pdlc@pdlc-skills
```
For local development from a clone:
```bash
claude plugin marketplace add /Users/me/projects/pdlc-skills
claude plugin install pdlc@pdlc-skills
```
Tests — **run these locally**; CI only fires on release tags and manual dispatch (see "CI scope" below):
```bash
bash tests/frontmatter-check.sh # skills/*/SKILL.md frontmatter + VERSION consistency
bash tests/install-smoke.sh # end-to-end install layout assertions
bash tests/statusline-check.sh # bin/pdlc-statusline.sh render scenarios
bash tests/adapter-codex-check.sh # adapters/build_codex.py projection output
bash tests/adapter-codex-loop-run-check.sh # Codex loop-run mapping + guardrails
bash tests/evals-runner-check.sh # evals/run.sh driver (stubbed, no model spend)
+ bash tests/evals-scenario-check.sh # assert_scenario verdicts (stubbed, no model spend)
# or the lot, stopping at the first red script
for f in tests/*.sh; do echo "== $f"; bash "$f" || break; done
- shellcheck install.sh tests/*.sh bin/*.sh evals/run.sh .githooks/pre-commit
+ shellcheck install.sh tests/*.sh bin/*.sh adapters/*.sh evals/run.sh \
+ evals/fixtures/*/scenario.sh .githooks/pre-commit
```
- **All six count** — 304 assertions as of v1.6.2. The list above used to name only two, which quietly
- documented a 221/304 gate; if you add a script under `tests/`, add it here too.
+ **All seven count** — 337 assertions at the time of writing; run them for the current number rather
+ than trusting this one. The list above once named only two, which quietly documented a 221/304 gate;
+ if you add a script under `tests/`, add it here too.
`statusline-check.sh` additionally needs a run under macOS's stock `/bin/bash` (3.2.57) — the
statusline script is deliberately bash-3.2 compatible (no `mapfile`, no bash-4 syntax), and a
Homebrew bash 5 on `PATH` will happily pass code that breaks on a stock Mac.
Enable the pre-commit secret scan once per clone (`.githooks/pre-commit`, uses `gitleaks` when present and falls back to a pattern scan with a loud warning when it isn't — "can't scan" must never read as "clean"):
```bash
git config core.hooksPath .githooks
```
**CI scope**: every workflow is `workflow_dispatch` or release-tag triggered — nothing runs on push-to-main or on PRs. Day-to-day checks belong on your machine; CI is reserved for the moment something gets published (`secret-scan` re-scans the full history with `fetch-depth: 0` before a release goes out). Adding a workflow, or widening an existing trigger, needs the maintainer's explicit go-ahead.
Behavioural evals (`evals/`, added v1.5.3) — verify contracts that only hold when a skill *really runs*:
```bash
./evals/run.sh --check # fixture structure only, no model, free (this is what CI runs)
./evals/run.sh --list # list scenarios
./evals/run.sh --only honest-checks # real run — costs one model turn
./evals/run.sh --platform codex --repeat 3 # pre-release: both platforms, 3 rounds each
```
The tier criterion is **who executes the contract**: deterministic code (bash driver, jq mapping) → stub-testable, keep it in `tests/`; the *model following SKILL.md prose* → stubbing the model stubs the object under test, so it needs a real run (`A-live`). Evals are **advisory, never a hard release gate** (a rate-limit shouldn't block a release) and **never run in CI**. Details and cost ledger: `evals/EVALS.md`, ADR `docs/decisions/0005-testing-and-quality-capability.md`.
## How sub-skills compose
Each `skills/pdlc-<name>/SKILL.md` has:
- YAML frontmatter (`name`, `description`, `argument-hint`, `allowed-tools`, plus PDLC-internal fields `layer`, `stage`, `produces`, `requires`, `next_step`, `terminal_state`)
- Markdown body — the workflow Claude follows when the slash command fires
- `<!-- @include templates/prompts/<x>.md -->` directives — shared prompt fragments (IRON LAW, handoff, self-audit, etc.) that Claude inlines from `references/templates/prompts/<x>.md` at runtime
The `@include` mechanism is **not** preprocessed by Claude Code — it relies on Claude reading the comment and following it on demand. This works in practice but is not a documented Claude Code feature.
## Layer structure
Sub-skills are grouped by `layer:` in frontmatter (the 38 names below all carry the `pdlc-` prefix):
- **Layer 1 (3)**: `pdlc-feature`, `pdlc-fix`, `pdlc-status` — one-sentence-driven entry points
- **Layer 2 (11)**: `pdlc-prd`, `pdlc-design`, `pdlc-tdd`, `pdlc-implement`, `pdlc-review`, `pdlc-e2e`, `pdlc-refactor`, `pdlc-ship`, `pdlc-deploy`, `pdlc-retro`, `pdlc-task` — single-stage fine control
- **Layer 3 (24)**: specialized tools (`pdlc-ui-design`, `pdlc-db-design`, `pdlc-arch`, `pdlc-lint`, `pdlc-perf`, `pdlc-security`, `pdlc-test-setup`, `pdlc-quality`, `pdlc-code-gen`, `pdlc-add-service`, `pdlc-add-app`, `pdlc-api-mock`, `pdlc-db-migrate`, `pdlc-i18n`, `pdlc-changelog`, `pdlc-standard`, `pdlc-relate`, `pdlc-bootstrap`, `pdlc-adopt`, `pdlc-onboard`, `pdlc-ui-design-pro`, `pdlc-loop-next`, `pdlc-loop-run`, `pdlc-settings`)
`pdlc-loop-next` / `pdlc-loop-run` are loop tooling (Loop 工程 / autonomous drive): `loop-next` prints the next mechanical-convergence command for an outer loop; `loop-run` is the convergence engine that auto-advances `tdd → implement → review` to `review_done` or blocked (release always stays human). See `docs/decisions/0001-loop-engineering-integration.md`.
`pdlc-settings` is the interactive config command (Layer 3); currently it wires up the optional PDLC statusline (`bin/pdlc-statusline.sh`) — enable/disable/display-items. Editing global `~/.claude/settings.json` is backup+diff+confirm-gated and degrades gracefully when the security layer blocks the write. See `docs/decisions/0002-statusline-pdlc-status.md`.
## Invariants enforced by the skills themselves
Every Layer 1/2 sub-skill **that produces artifacts** (i.e. `produces: []` is empty for read-only stages like `pdlc-status`) `@include`s `templates/prompts/iron-law.md`, which states the IRON LAW:
1. Artifacts must be persisted to disk (not just chat output)
2. The state machine `docs/.pdlc-state/<feature-id>.json` must be updated on every stage transition
3. Tests must exist (and be red) before implementation
4. A self-check runs before handoff
5. Auto-repair runs at most once
6. State must advance — a successful stage must change `current_stage`; a stalled stage fails loudly instead of returning silently (so autonomous loops can't spin on stale state), except for a deliberate human-block which records `blocked_reason` (added in v1.2)
Skill bodies follow a four-phase skeleton (execute → self-check → one-shot repair → handoff), with `next_step:` in frontmatter declaring the next stage so multi-stage flows are command-driven, not memorized.
## Target-project contract
When the user invokes a `/pdlc-*` slash command in their project, the skill reads/writes these paths in that project:
- `docs/00_standards/coding/` — coding standards (read by `pdlc-prd` / `pdlc-implement` / `pdlc-tdd` / `pdlc-code-gen` / `pdlc-onboard`; optional)
- `docs/00_standards/test-commands.yml` — single source of the project's objective `check` commands (`unit` / `coverage` / `lint` / `e2e`), read by `pdlc-tdd` / `pdlc-implement` / `pdlc-review` and the loop drivers so `last_phase_result.checks` come from real exit codes, not model self-audit; template at `references/templates/test-commands-template.yml`; optional
- `docs/01_requirements/prd/`
- `docs/02_design/{api,database,architecture,ui-ux}/`
- `docs/03_development/` — developer manuals (`pdlc-onboard` writes here)
- `docs/04_testing/{unit-tests,e2e-tests,defects,security,perf}/`
- `docs/05_deployment/`
- `docs/06_tasks/`
- `docs/00_standards/quality-targets.yml` — declared quality targets (coverage line, `core_flows`, lint policy) read by `pdlc-quality`; template at `references/templates/quality-targets-template.yml`; optional
- `docs/00_standards/e2e-flow-map.yml` — explicit `core_flow → E2E test` map so "all core flows covered" is a mechanical check rather than a model opinion; required once `core_flows` is declared; template at `references/templates/e2e-flow-map-template.yml`
- `docs/07_reviews/{doc,code,design,retro,quality}/` — the `quality/` subdir holds dated `pdlc-quality` reports as a `.md` / `.html` pair. The **`.md` is the source of truth** (`git diff`-able, read by `pdlc-ship` as a release gate); the `.html` is a self-contained view of the same data (template: `references/templates/quality-report-template.html`, zero external assets so it opens offline and prints for sign-off). Numbers in the HTML are copied from the `.md`, never recomputed.
- `docs/.pdlc-state/<feature-id>.json` — per-feature state machine, ID format `F<YYYYMMDD>-<HHMMSS>` (creation-time, collision-safe under parallel work; legacy `-<NN>` still parses)
Changing this contract requires updating both the relevant `skills/pdlc-*/SKILL.md` bodies AND the `Target-project contract` sections in README and `docs/usage-guide.md`.
## When editing this plugin
- Edit sources under `skills/pdlc-<name>/SKILL.md` (sub-skill bodies), `references/templates/prompts/*.md` (shared fragments), or `references/templates/*-template.md` (user document templates). Don't edit installed copies in `~/.claude/plugins/cache/`.
- New required frontmatter fields → also update `required_fields` in `tests/frontmatter-check.sh`.
- - Run all six test scripts and shellcheck before committing (see "Common commands").
+ - Run all seven test scripts and shellcheck before committing (see "Common commands").
- New shared prompt fragments → put under `references/templates/prompts/` and reference via `<!-- @include templates/prompts/<name>.md -->` (path is relative to `references/`).
- New sub-skill: create `skills/pdlc-<name>/SKILL.md` with the standard frontmatter (`name: pdlc-<name>`, layer/stage, produces/requires, etc.). The `pdlc-` prefix in directory and `name:` is mandatory.
## Bumping versions
`VERSION` and `.claude-plugin/plugin.json`'s `version` field must match. `tests/frontmatter-check.sh` asserts this.
## Notes
- Public-facing entry: `README.md` (English) and `README.zh-CN.md` (Chinese). They mirror each other.
- User manual: `docs/usage-guide.md` — single source containing install, command catalog, contract, scenarios, FAQ.
- This file (`CLAUDE.md`) is contributor-facing only. **It is still shipped to users**, though — see below.
- **Everything in this repo is installed, including dev-only files.** `claude plugin install` copies the whole source directory (minus `.git`) into `~/.claude/plugins/cache/`, so `evals/`, `tests/`, `docs/`, `adapters/`, `.github/` and this file all land on the user's machine (~950K total, of which ~520K is dev-only).
The plugin manifest schema has **no** `exclude` / `files` / `ignore` field, and there is no `.claudeignore` — verified against the [plugins reference](https://code.claude.com/docs/en/plugins-reference). The only way to ship less is to move the user-facing parts (`skills/`, `references/`, `bin/`, `.claude-plugin/plugin.json`) into a subdirectory and point the marketplace entry's `source` at it.
We deliberately have **not** done that: the token cost is zero either way (`claude plugin details` reports ~1,345 always-on tokens, all of it skill descriptions — dev files never enter the context window), so the only gain is ~520K of disk, against a restructure that touches 26 + 15 + 11 path references and risks silent breakage in the statusline symlink and adapter template paths. Revisit if the plugin grows substantially or if Claude Code adds an exclusion mechanism.