be-code
TDD-implement a CQRS/WebFlux feature: RED-GREEN cycle through command executors, query processors, and router/handler code. Consumes a be-crud scaffold, plan.json, or an existing work document with test scenarios; drafts scenarios manually if none exist. Use be-crud first when no scaffold exists yet.
- License 许可
- MIT
- 最近更新
- 2026-11-11
- Stars
- ★ 2
- Forks
- 0
01 前言 Front Matter
- name
- be-code
- description
- TDD-implement a CQRS/WebFlux feature: RED-GREEN cycle through command executors, query processors, and router/handler code. Consumes a be-crud scaffold, plan.json, or an existing work document with test scenarios; drafts scenarios manually if none exist. Use be-crud first when no scaffold exists yet.
- allowed-tools
- Read, Write, Edit, Glob, Grep, Bash, Agent
- argument-hint
- <feature-name or work-doc-path> [--yes]
- user-invocable
- true
02 资源文件 2
- 参考文档references/error-handling.md2.1 KB
- 参考文档references/example.md2.8 KB
03 SKILL.md 正文
Implement Feature with TDD
Implement a feature using strict Test-Driven Development. This skill orchestrates the full TDD workflow: context gathering, scenario writing, and RED-GREEN cycle execution.
This skill holds an exclusive cross-skill lock ({workDocDir}/.progress/.lock) for the duration of the run and can demote a feature's pipeline status, discarding verification/review progress (see Step 3.5). Ground every claim in the Step 6 report in evidence — build output, git status/git diff — never narrate completion from memory, and never leave the lock file behind on failure or cancellation (see Error Handling) — and whenever the lock is released, on any path, remove the directory its snapshotDir names if the implement agent recorded one (its revert snapshot, outside the repository).
Files under references/ write the plugin root as {pluginRoot}, which is ${CLAUDE_PLUGIN_ROOT}.
Instructions
Step 0: Validate Configuration
- Read
.claude/backend-webflux-plugin.json - If missing, tell the user to run
/backend-webflux-plugin:be-initfirst and stop
Step 1: Parse Argument
Strip a trailing --yes flag first (it is not part of the path or feature name). The argument can be:
- File path: If argument looks like a path (contains
/or.md), treat it as a work document path. Extractfeature-namefrom the filename by removing the.mdextension and directory prefix (e.g.,work/features/employee.md→employee). Thisfeature-nameis used for lock files and progress file lookups. - Feature name: Otherwise, treat it as a feature description
Validate feature-name (however derived above): reject and stop with an error if it contains /, \, .., or any character outside [a-z0-9-]. It is used directly to build progress-file and lock-file paths under {workDocDir}/.progress/ in later steps — an unvalidated value could escape that directory.
Step 1.5: Check Plan
If the argument is a feature name (not a file path):
- Check if
docs/specs/{feature}/.implementation/backend/plan.jsonexists- If exists:
planAvailable = true, read plan.json - If not exists:
planAvailable = false
- If exists:
- If
planAvailable:- List all entities from
plan.json.entities[] - Validate each entity's
name: reject and skip that entity if it contains/,\,.., or any character outside[A-Za-z0-9].plan.jsoncomes from another agent reading a spec file this skill does not control the provenance of, so it gets no more trust than direct user input — and the derived kebab-case form is used to build work-document and progress-file paths below. - For each remaining entity, check if
{workDocDir}/{kebab-case-entity}.mdexists - Build two lists:
entitiesWithWorkDocandentitiesWithoutWorkDoc
- List all entities from
- If
planAvailableand multiple entities exist:"Plan contains {count} entities: {entity names}" "Options:" "1. Process all entities sequentially (dependency order)" "2. Select a specific entity to implement"
- If user chooses 2: ask which entity, set
targetEntity = {chosen entity} - If user chooses 1:
targetEntity = null(process all inentityDependencyOrder)
- If user chooses 2: ask which entity, set
Step 2: Gather Context
- Read
${CLAUDE_PLUGIN_ROOT}/templates/core-conventions.mdfor architecture and conventions (a trimmed, execution-facing subset of ${CLAUDE_PLUGIN_ROOT}/CLAUDE.md — see that file's own header for what it omits) - If the argument is a work document path:
- Read the document
- Extract
- [ ]scenarios - Skip to Step 3.5 (single work document mode)
- If the argument is a feature name and
planAvailable:- Determine entity list to process:
- If
targetEntityis set: process only that entity - If
targetEntityis null: process all entities inplan.json.entityDependencyOrder
- If
- For each entity to process:
- Check if
{workDocDir}/{kebab-case-entity}.mdexists - If exists: extract
- [ ]scenarios - If not exists: mark for auto-generation in Step 3
- Check if
- Multi-entity iteration: Steps 3 through 3.7 execute once (scenarios, lock, the per-entity demotion check in Step 3.6a, pipeline init for the confirmed entities). Steps 4 through 6 (the TDD cycle, build, and report) then execute once for the whole batch, not per entity — see Step 4's "Multi-entity batching" note. Step 7 (pipeline-state bookkeeping) still executes per entity in dependency order.
- Determine entity list to process:
- If the argument is a feature name and not
planAvailable:- First, check if
{workDocDir}/{feature-name}.mdexists- If found: treat it as the work document — read it, extract
- [ ]scenarios, and skip to Step 3.5 (same as file path mode)
- If found: treat it as the work document — read it, extract
- If no matching work document:
- Explore existing code: scan
{sourceDir}/{basePackage}/for related entities, controllers, commands, queries - Read existing work documents in
{workDocDir}/for patterns - Check for any related PRD/TSD documents
- Explore existing code: scan
- First, check if
Step 3: Write Test Scenarios
When planAvailable and work document does not exist
Auto-generate an enriched work document from plan.json for each entity that lacks one:
- Read
${CLAUDE_PLUGIN_ROOT}/templates/work-document-template.mdfor the document format — including theData profile:line at the top: resolve it asbe-crudStep 1 does (config.dataProfile, orr2dbcwhen that isbothand nothing says otherwise) and record it; the implement agent reads it to choose the entity-conventions file - For each entity in plan.json that has no existing work document, generate
{workDocDir}/{kebab-case-entity}.mdwith:- Entity section: fields table from
plan.json.entities[].fields[]with types, constraints, and source references - Commands section: from
plan.json.commands[]for this entity, including validation steps from BR-nnn - Queries section: from
plan.json.queries[]with filter/sort/pagination details - API Endpoints section: from
plan.json.endpoints[]with HTTP methods, paths, status codes - Validation Rules section: from
plan.json.validationRules[]with regex patterns and source references - Exceptions section: from
plan.json.exceptions[]with E-nnn codes, HTTP status, and conditions - Test Scenarios section: from
plan.json.testScenarios[]as- [ ]items with source references in comments### POST /{domain}/{entities} - [ ] valid request returns 201 Created <!-- TS-001, AC-001 --> - [ ] invalid email format returns 400 Bad Request <!-- TS-002, BR-001 --> - [ ] duplicate email returns 409 Conflict <!-- TS-003, BR-002 --> - Test Data section: auto-generate generator class stubs based on entity fields
- Entity section: fields table from
- Present the generated work document to the user for confirmation:
"Work document generated from plan.json for {EntityName}:" "{scenario count} test scenarios from spec (TS-nnn references preserved)" "Review and confirm to proceed with TDD implementation."
- Wait for user approval before proceeding
- If user requests changes, apply them to the work document
When not planAvailable and no work document
Follow the original manual flow:
- Read
${CLAUDE_PLUGIN_ROOT}/templates/test-scenario-template.mdfor the scenario format - Draft test scenarios following ${CLAUDE_PLUGIN_ROOT}/CLAUDE.md scenario writing rules:
- Single sentence, English, present tense
- Start with lowercase (usable as snake_case method name)
- Use
- [ ]checkbox format - Most important scenario first
- Mark uncertain scenarios with
?:- [ ] valid request returns 201 Created - [ ] duplicate email returns 409 Conflict - [ ] ? empty display name returns 400 Bad Request - Present the scenario list to the user for approval:
"Here are the test scenarios for {feature}:" {scenario list} "Please review. I'll remove scenarios marked with
?unless you confirm them." - Wait for user approval before proceeding
- Save approved scenarios to
{workDocDir}/{feature-name}.md, with the template'sData profile:line resolved exactly as the plan path above does — the implement agent reads it to choose the entity-conventions file, and a document without it leaves the profile to a guess
Step 3.5: Demotion Check
--yes answers this step's and Step 3.6a's confirmation with yes — for an unattended caller (be-jira-auto) that has already decided the re-entry; without it the prompts below are asked.
Work-document mode (file path, or a feature name with a work document and no plan): If {workDocDir}/.progress/{feature-name}.json exists:
- Read
pipeline.status - If status is anything past
"implementing"—"implemented","verified","verify-failed","reviewed","review-failed","fixing","resolved","escalated","done"— (${CLAUDE_PLUGIN_ROOT}/CLAUDE.md § Demotion Warning: any earlier-stage skill resetting a later status asks first):"This feature is currently '{status}'. Re-running TDD implementation will reset the pipeline status to 'implementing', discarding verification/review progress." "Continue?" If the user declines, stop here.
fixingandescalatedare covered by item 2 — one confirmation, not two.resolvedcounts only when thepreviousStatusrecorded beside it (pipeline.debugorpipeline.build— whichever has the newertimestamp, the one that produced thisresolved) is itself pastimplementing— be-debug resolving a mid-implementation failure leaves nothing to discard, and the prompt would be false.
Plan-driven mode (one entity or many): Skip this step here. Step 3.7 writes {kebab-case-entity}.json, not {feature-name}.json, so a check on the feature name would never see the entity's status — the demotion check is performed per entity in Step 3.6a, after the lock and before Step 3.7 writes any progress file.
Step 3.6: Acquire Lock
mkdir -p {workDocDir}/.progress— on the "start TDD withoutbe-crud" path nothing has created it yet, and a lock cannot be written into a directory that does not exist- Check if
{workDocDir}/.progress/.lockexists - If it exists and
lockedAtis less than 30 minutes ago: warn the user that another operation ({operation}) is in progress and stop - If it exists and
lockedAtis older than 30 minutes: remove the stale lock (first the directory itssnapshotDirnames, if any) - Write lock file:
{ "lockedAt": "{ISO 8601}", "operation": "be-code", "feature": "{feature-name}", "runId": "{a fresh random id, kept in memory for the release}" }
Multi-entity mode: The lock is acquired once here and held for the entire multi-entity operation. It is released once in Step 7 after all entities are processed.
Step 3.6a: Per-entity Demotion Check
Plan-driven mode only (work-document runs did this in Step 3.5). Before Step 3.7 writes any
progress file, loop over every entity being processed (targetEntity alone, or all of
entityDependencyOrder) and check {workDocDir}/.progress/{kebab-case-entity}.json:
- If it exists, read
pipeline.status - If status is anything past
"implementing"(the Step 3.5 list): warn the user (same messages as Step 3.5) and ask for confirmation for this entity - If the user declines for a specific entity: leave it out of the batch and proceed to the next entity's check
Build confirmedEntities from every entity that was not declined, in dependency
order. If confirmedEntities ends up empty, do not launch the implement agent and
do not run Step 5's build (there is nothing new to build) — go directly to Step 6
and produce its combined report with an empty "Entities implemented" list and the
full "Entities skipped" list (Step 6's own format already covers this; do not skip
Step 6 itself, since it is the only step that renders that report). Step 7 then
runs with an empty confirmedEntities loop — it has nothing to update, so it just
releases the lock.
Step 3.7: Initialize Pipeline State
For each entity in confirmedEntities (plan-driven mode — a declined entity is not touched) or the one work-document feature, create or update {workDocDir}/.progress/{kebab-case-entity}.json ({feature-name}.json in work-document mode — the name Step 3.5 checked):
- Create
{workDocDir}/.progress/directory if it does not exist - If progress file does not exist, create it:
{ "feature": "{kebab-case-entity}", "workDocument": "{workDocDir}/{kebab-case-entity}.md", "createdAt": "{ISO 8601}", "updatedAt": "{ISO 8601}", "pipeline": { "status": "implementing", "scenarios": { "total": {count}, "completed": 0 } } } - If progress file exists: read-modify-write — update only
pipeline.statusto"implementing"and refresh scenario counts. Preserve all existing fields includingspecSource,pipeline.verification,pipeline.review, etc.
Multi-entity mode: initialize only the entities Step 3.6a confirmed. This step writes
"implementing"; a check that ran after it would read the status it just wrote, never warn, and
demote a done/verified entity without the consent ${CLAUDE_PLUGIN_ROOT}/CLAUDE.md § Demotion Warning requires. An
entity the user declined keeps its progress file untouched.
Step 4: TDD Cycle
Multi-entity batching: When processing multiple entities (plan-driven mode),
Steps 4-6 run once for the whole batch, not once per entity — launching a
separate implement agent per entity repeats that agent's own Phase 0 context load
(conventions, templates) for no benefit, since it never changes across entities in
the same run. Step 7 (pipeline-state bookkeeping) still runs per entity, since each
entity has its own progress file.
Subagent Isolation: Pass only the specified parameters below. Do not include conversation history or user feedback from prior steps.
Baseline for evidence: Before launching the agent, run git status --porcelain
once for the whole batch. Record this output as the baseline — Step 6 diffs against
it to ground the Files created/modified lists in evidence instead of memory.
Launch the implement agent (subagent_type: "backend-webflux-plugin:implement" — qualified: backend-springboot-plugin ships an agent of the same name, and a bare name may resolve to it when both are installed) once with:
- Single-entity mode (file path argument, or plan-driven with exactly one
entity):
workDocument: path to the work document. - Multi-entity mode:
workDocuments: ordered array of work document paths, one per entity inconfirmedEntities(dependency order), e.g.["{workDocDir}/leave-type.md", "{workDocDir}/leave-request.md"]. config: the parsed plugin configprojectRoot: current project root
The implement agent loads its Phase 0 context once, then processes each document's scenarios in order (all of document 1's scenarios, then document 2's, ...):
- Select the next
- [ ]scenario in the current document - Write test (RED)
- Implement minimum code (GREEN)
- Mark as
- [x] - Repeat until the current document is complete, then move to the next document
Step 5: Final Build
Skip this step when confirmedEntities was empty (nothing was implemented — see
Step 4) and report Build: not run — no entities to build in Step 6 instead.
Otherwise, after the implement agent returns (single document, or the whole batch, complete — or stopped early per its own 3-consecutive-failure rule), run a full build:
{config.buildCommand}
Set Bash tool timeout to 600000ms.
Step 6: Report
Derive the "Files created" and "Files modified" lists from git status --porcelain (compared against the Step 4 baseline) and git diff --stat — never from memory or the implement agent's self-report. A ?? entry is a created file; an M entry is a modified file. If git is unavailable or the working tree is outside version control, state "not verified: file lists" instead of guessing.
Display implementation summary in the working language.
Single-entity mode:
Feature Implementation Complete: {feature-name}
=======================================
Scenarios: {completed}/{total}
{list each scenario with status}
Files created:
{list of new files}
Files modified:
{list of modified files}
Build: {PASS / FAIL}
Multi-entity mode — one combined report covering every entity in
confirmedEntities, plus any skipped in the demotion check:
Feature Implementation Complete: {feature} ({entityCount} entities)
=======================================
Entities implemented (in dependency order):
1. {Entity1} — {completed}/{total} scenarios
2. {Entity2} — {completed}/{total} scenarios
Entities skipped (demotion declined):
{Entity} — existing status was '{status}', or "(none)"
Files created:
{list of new files, across all entities}
Files modified:
{list of modified files, across all entities}
Build: {PASS / FAIL}
If the build failed, suggest running /backend-webflux-plugin:be-build for auto-diagnosis.
Step 7: Update Pipeline State
For each entity in confirmedEntities (or the single entity in single-entity mode),
update {workDocDir}/.progress/{kebab-case-entity}.json:
- Read progress file
- Update
pipeline.scenarios.completedwith final count of- [x]items in that entity's own work document - Update
pipeline.status:- All scenarios complete + build passes →
"implemented" - All scenarios complete + build fails →
"implementing"— code that does not build is not implemented, and"implemented"is the statebe-reviewaccepts; report the build failure and point atbe-build - Some scenarios remain →
"implementing"
- All scenarios complete + build passes →
- Update
updatedAttimestamp - Write back (read-modify-write — preserve all existing fields including
specSource)
After every entity's (or the single entity's) progress file is updated, release the
lock: delete {workDocDir}/.progress/.lock — release per ${CLAUDE_PLUGIN_ROOT}/CLAUDE.md § State File Safety.
Suggest next step:
- All entities implemented + build passes:
/backend-webflux-plugin:be-verify {entity}for each entity - all scenarios done but the build fails (status stays
implementing):/backend-webflux-plugin:be-build - implementing: resume with
/backend-webflux-plugin:be-code {workDoc}
Error Handling
When a step fails or the user cancels, read ${CLAUDE_PLUGIN_ROOT}/skills/be-code/references/error-handling.md and follow it.
Example: Single-Entity, Non-Plan-Driven Run
A worked single-entity run: ${CLAUDE_PLUGIN_ROOT}/skills/be-code/references/example.md.
04 同仓库更多 Skills
hp-shared
Shared conventions for every homepage-plugin agent and skill — stack, code conventions, state-file writes, check commands and how to report them. Preloaded into agents through their `skills:` frontmatter; not meant to be invoked by hand.
fe-shared
Shared conventions for every frontend-react-plugin agent and skill — code conventions, state files and locks, accepted deviations, design principles, build working directory, router-mode command matrix, TypeScript check. Preloaded into agents through their `skills:` frontmatter; not meant to be invoked by hand.
be-spring-shared
Shared conventions for every backend-springboot-plugin agent and skill — tech stack, CQRS architecture, naming, coding standards, TDD, commit and build rules, state files. Preloaded into agents through their `skills:` frontmatter; not meant to be invoked by hand.
pp-translate
Use after directly editing the working language spec to sync changes to other supported languages.
pp-sync-stitch
Use when wireframes were manually edited on the Stitch website and need to be re-fetched to the local project.
pp-sync-notion
Use when a specification needs to be published or re-synced to Notion after finalization or manual edits.