Skip to content

tdd-workflow: missing plan.md integration, human-readable test specification, and squash-merge guidance #2138

@sesame0224

Description

@sesame0224

Summary

While using tdd-workflow alongside the /plan skill, I identified three design gaps
that cause information loss and make it hard to answer "what was verified and how."


Gap 1: No integration with /plan output

tdd-workflow begins with "Step 1: Write User Journeys" — but when used after /plan,
the User Journeys and task breakdown already exist in *.plan.md.

The skill has no mechanism to accept a plan.md as input.
Inter-skill orchestration is left entirely to the user, and breaks completely across sessions.

Question: Is connecting /plantdd-workflow intentionally the user's responsibility?
If so, is there a recommended handoff pattern? I think we should add an argument hint to the skill.


Gap 2: Test specification is only readable as code

tdd-workflow records what was tested through checkpoint commits and test files.
This aligns with TDD's philosophy that test code is the specification.

However, I find myself wanting a human-readable test specification — a document
that answers "what behaviors are guaranteed?" without opening test files:

# What is guaranteed Test file Test type Result
1 Returns ValidationError when NodeAffinity is missing controller/numanetwork_controller_test.go:TestValidation_MissingNodeAffinity Unit PASS
2 CR status becomes Ready after valid apply controller/numanetwork_controller_test.go:TestReconcile_ValidCR Integration PASS

I'm not sure whether this desire is:

  • In scope: a missing output step that tdd-workflow should generate, or
  • Out of scope: fundamentally at odds with TDD's "test code is the spec" philosophy

Question: Does tdd-workflow intentionally leave this to the reader of the test code?
Or is generating a natural-language test specification a valid addition to the workflow?


Gap 3: Squash merge destroys checkpoint history

SKILL.md says:

Do not squash or rewrite these checkpoint commits until the workflow is complete.

But it doesn't define what happens at merge time.
Squash merging into a development branch eliminates all RED/GREEN checkpoints,
removing the only record of when and why tests were written.

Question: Is squash merge incompatible with tdd-workflow by design?
Should the skill recommend a merge strategy?


Proposed improvement

Add argument-hint

argument-hint: "path/to/*.plan.md"
### Add Step8
After GREEN is validated, write a summary to `.claude/tdd/<plan-name>-m<milestone>.tdd.md`
containing the four sections below.

**1. User Journeys**  
List user journeys from the plan or derived from the test file comments.

**2. Task Report**  
For every task in the plan, include the applicable subsections:

- **Execution Log** (always): what was done (one sentence), the validate command and
  its **actual output** (verbatim), and what is guaranteed as a result.
- **Testing Policy** (when the task has test functions): explain the rationale — what
  aspects needed to be verified for this task and why, and how that led to the specific
  tests that were created. This is the intent, not the mechanics.
- **Test Results** (when the task has test functions): a table with the test function
  link, a sentence describing what is verified, test type (unit / integration / E2E),
  and result (PASS / FAIL / SKIP with a brief reason for any SKIP).
  After the table, add a **保証** paragraph summarising what is collectively guaranteed
  by the passing tests in plain language.

Tasks verified solely by shell commands have only an Execution Log.
Tasks verified by test functions have Testing Policy + Test Results; their Execution Log
records artifact creation (e.g. `ls` of a generated file) if applicable.

**4. Coverage**  
Report coverage achieved (`go test -cover` or equivalent) and note any known gaps
(e.g. generated code inflating the denominator).

Example output:

## 2. Task Report

### Task 1: XXX

**Execution Log**
...

**Testing Policy**
...
  

**Test Results**

  | Test function | What is verified | Type | Result |
  |---|---|---|---|
  | [`TestWidgetModeConstants`](../../api/v1alpha1/widget_types_test.go#L20) | `WidgetModeFast` resolves to `"fast"` and
  `WidgetModeSlow` to `"slow"` | unit | PASS |
  

**Guarantee**
...

Generating this document serves two purposes simultaneously:

  1. Human readability — answers "what is guaranteed?" without reading test code, with direct links to the relevant test functions
  2. Evidence persistence — provides a durable record that survives squash merges and session restarts, independent of git history

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions