Add tdd-impl workflow: parallel TDD implementations with one-shot audit

Two agents (impl_a: airouter, impl_b: best-complexity model) implement
in parallel against pre-written tests using TDD composites. An audit
node compares both outputs and emits a JSON verdict (pass/more_work_needed,
winner: a/b/neither, gaps). Harnesses are param-overridable for
provider flexibility. F-WE-PDIV note in description for future
unique_providers enforcement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Paul O'Reilly
2026-04-28 15:37:22 +12:00
parent f392f72ca2
commit 21f1cb6f17

162
workflows/tdd-impl.yaml Normal file
View File

@@ -0,0 +1,162 @@
name: tdd-impl
version: 1
description: >
Parallel TDD implementation: two agents implement against a pre-written test suite,
then an audit node compares both outputs and emits a one-shot JSON verdict.
Tests must already exist in the repo before dispatching this workflow. Use the
sonnet-test-writer or opus-test-writer template to write tests first if needed.
Default model routing: impl_a → Airouter Qwen3.6 (cost-efficient), impl_b →
best Anthropic model by complexity score. Override impl_a_harness / impl_b_harness
to change providers. When F-WE-PDIV lands, add unique_providers: true to the
audit node requirements to guarantee cross-provider auditing automatically.
params:
required:
task_description:
type: string
description: "What to implement — the feature or subsystem covered by the tests"
project_id:
type: string
description: "Target project identifier for task grouping"
repo_url:
type: string
description: "Git repo URL containing the spec and pre-written tests"
agent_repo_url:
type: string
description: "Agent repo URL for branch-per-task output persistence"
optional:
spec_file:
type: string
default: ""
description: "Path to the spec file(s) the tests cover (e.g. spec/my-feature.md). Leave blank to let the agent discover specs."
impl_a_harness:
type: string
default: "code-airouter-tdd-repo/v1"
description: "Harness for implementation A (default: Airouter TDD). Override to change provider."
impl_b_harness:
type: string
default: "code-sonnet-tdd-repo/v1"
description: "Harness for implementation B (default: Sonnet TDD). Override to change provider."
test_file_glob:
type: string
default: "tests/"
description: "Pytest path/glob to run (default: full tests/ directory)"
scope_notes:
type: string
default: ""
description: "Any constraints, prior decisions, or scope boundaries for the agents"
nodes:
impl_a:
name: "Implementation A"
prompt: |
You are implementing source code to make a test suite pass.
## Task
{{ task_description }}
{% if spec_file %}
## Spec
Read the spec at `{{ spec_file }}` in the repo for the full requirements.
{% endif %}
{% if scope_notes %}
## Scope Notes
{{ scope_notes }}
{% endif %}
## Instructions
1. Run `python -m pytest {{ test_file_glob }} -v --tb=short` to see the current test state.
2. Implement source code in `lib/` and `controlplane/` (or as specified in the spec) until all tests pass.
3. Do NOT modify any test files — they are read-only and OS-locked.
4. Run the full test suite before finishing to confirm everything is green.
5. Write a brief summary of your implementation approach to `/workspace/project/output.md`.
Include: files created/modified, key design decisions, any known limitations.
Finish only when `pytest {{ test_file_glob }}` exits 0.
harness: "{{ impl_a_harness }}"
requirements:
labels: [airouter]
min_scores:
cost_efficiency: 8
impl_b:
name: "Implementation B"
prompt: |
You are implementing source code to make a test suite pass.
## Task
{{ task_description }}
{% if spec_file %}
## Spec
Read the spec at `{{ spec_file }}` in the repo for the full requirements.
{% endif %}
{% if scope_notes %}
## Scope Notes
{{ scope_notes }}
{% endif %}
## Instructions
1. Run `python -m pytest {{ test_file_glob }} -v --tb=short` to see the current test state.
2. Implement source code in `lib/` and `controlplane/` (or as specified in the spec) until all tests pass.
3. Do NOT modify any test files — they are read-only and OS-locked.
4. Run the full test suite before finishing to confirm everything is green.
5. Write a brief summary of your implementation approach to `/workspace/project/output.md`.
Include: files created/modified, key design decisions, any known limitations.
Finish only when `pytest {{ test_file_glob }}` exits 0.
harness: "{{ impl_b_harness }}"
requirements:
min_scores:
complexity: 7
spec_adherence: 8
audit:
name: "Audit — one-shot verdict"
depends_on: [impl_a, impl_b]
prompt: |
You are auditing two independent implementations of the same feature and picking the winner.
## Task that was implemented
{{ task_description }}
{% if spec_file %}
## Spec (requirements to check against)
Read `{{ spec_file }}` in the repo for the authoritative requirements.
{% endif %}
## Implementation A summary
<<ARTIFACT:impl_a:output>>
## Implementation B summary
<<ARTIFACT:impl_b:output>>
## Instructions
1. Read the spec (if provided) to understand the requirements.
2. Review each implementation summary against the requirements.
3. Identify any spec gaps, correctness concerns, or quality issues in each.
4. Pick the stronger implementation, or flag if neither is acceptable.
Write your verdict to `/workspace/project/output.md` as valid JSON followed by a brief rationale:
```json
{
"verdict": "pass" | "more_work_needed",
"winner": "a" | "b" | "neither",
"gaps": ["gap 1", "gap 2"],
"rationale": "one paragraph explaining the decision"
}
```
Use `"verdict": "pass"` only if at least one implementation fully satisfies the spec with no
significant gaps. Use `"more_work_needed"` if both have significant gaps or if `"winner"`
is `"neither"`. Set `"gaps"` to the list of outstanding spec items not addressed by the winner.
harness: planning/v1
requirements:
min_scores:
complexity: 8
spec_adherence: 9