ADR-301: Add tdd-tester/tdd-implementer agents and the implement-tdd red/green loop - #52
Conversation
build-and-test: Python test resultsStatus: ✅ Passed Test log |
jodavis-claude
left a comment
There was a problem hiding this comment.
Solid, careful piece of work overall — the turn-message templates match the spec verbatim, the tool grants and file-scope constraints are exactly as required, both required dry runs are documented with real (not fabricated) build/test output, and the practice-rule references are by-name only as required. I found two protocol-completeness gaps in implement-tdd/SKILL.md that should be addressed before merge (see inline comments) — both are cases where a sub-agent reply that the design allows for isn't actually routed anywhere in the skill's step-by-step instructions, which would leave a future live run of this loop stuck with no next action.
jodavis-claude
left a comment
There was a problem hiding this comment.
Sign-off review
Both prior review threads are resolved by commit d6087fd:
- Step 4 missing an
escalatebranch for structural turns — fixed.implement-tdd/SKILL.mdstep 4 now routestdd-implementer'sescalatereply to step 7, with a note that the escalation originated from the structural turn (noAssertexists yet). Step 7'sclarifyhandling correctly distinguishes retrying step 6 vs. re-sending step 4's structural stub-resolution message.tdd-implementer.md's "Structural turns" section now also notes escalation is possible there. - Step 5 missing a
structural-redbranch — fixed.implement-tdd/SKILL.mdstep 5 now routes an unexpectedstructural-redreply back to step 4's structural-red handling, correctly framing step 3's skip-structural decision as a heuristic guess rather than a guarantee.
Re-read both modified files in full (plugins/dev-team/skills/implement-tdd/SKILL.md, plugins/dev-team/agents/tdd-implementer.md) against the loop's own internal consistency (all reply branches now route somewhere, no dangling states) and against the spec's turn-message contract — no regressions or new Priority 1-5 issues found. CI (build-and-test) is green.
Approving. Thank you for the quick, well-scoped fix.
jodavis-claude
left a comment
There was a problem hiding this comment.
Sign-off review (round 2)
Re-checked this PR after the pipeline looped back from validation. No new commits or review comments have landed since the prior sign-off review (submitted 2026-07-05T02:49:47Z, which approved commit d6087fd) — status is unchanged from that pass:
- Both prior review threads remain resolved (confirmed via the PR's review-threads API): the step 4 missing-
escalate-branch gap and the step 5 missing-structural-red-branch gap, both fixed by commitd6087fd. - No files have changed since that commit — re-scanning
plugins/dev-team/skills/implement-tdd/SKILL.mdandplugins/dev-team/agents/tdd-implementer.mdfound no new Priority 1-4 issues; all reply branches route somewhere, no dangling states. - CI (
build-and-test) is green.
Flagging one open item that is outside this review's scope to resolve via further code changes to this PR: the subsequent researcher-validate pass reported exit criterion 1 as partial because tdd-tester.md/tdd-implementer.md reference test-driven-development's Practice-rule headings ("AAA structure", "Red must fail for the right reason", "Arrange and Act are frozen after first green", "Naming convention") by name, but those headings don't yet exist in this branch's test-driven-development/SKILL.md — they're added by ADR-300 (GitHub PR #51), which is still open/unmerged. This was flagged and accepted as a known, deliberate risk as far back as the original task brief (Known ambiguity 1), and confirmed again in fix round 2 that the referenced heading names are an exact match against PR #51's current diff, so no rewrite will be needed here once #51 merges. This is a merge-order/sequencing question (should ADR-301 wait for PR #51 to merge first), not a defect in this PR's diff, and merging another PR is outside what a code review on PR #52 can or should resolve. Re-approving PR #52's own code changes on their merits; the merge-order question needs a decision from the user/orchestrator, independent of this review.
Approving.
…estration skill Adds the sub-agent pair that drives one Testable component through the structural-then-behavioral red/green TDD ping-pong loop, plus the implement-tdd skill Developer uses to orchestrate them turn by turn through to done + commit. Post-done tdd-refactorer wiring is explicitly out of scope (ADR-302). Proceeds referencing test-driven-development's anticipated Practice-rule headings (AAA structure, Red must fail for the right reason, Arrange/Act frozen after first green, Naming convention) by name, per ADR-300 (PR #51, still open) landing those headings unchanged.
… in implement-tdd's structural and behavioral turns - Step 4 (structural turn): tdd-implementer's reply to the stub-resolution message can now branch to escalate (go to step 7), not just structural-green, matching tdd-implementer.md's own Escalation section and dry run 2's transcript. - Step 5 (behavioral turn): tdd-tester's reply can now branch to structural-red (route back to step 4) in addition to red/done, since step 3's skip-structural decision is only a heuristic guess, not a guarantee, and tdd-tester's Arrange/Act check is unconditional. - Step 7's clarify handling now distinguishes retrying the behavioral turn (step 6) from retrying the structural stub-resolution message (step 4) depending on where the escalation originated. - tdd-implementer.md's Structural turns section now states explicitly that escalation is a possible outcome there too, not just structural-green.
d6087fd to
4c3a4f6
Compare
jodavis-claude
left a comment
There was a problem hiding this comment.
Sign-off review — ADR-301 (PR #52)
Prior review threads: Both Priority-1 protocol-completeness threads from round 1 are confirmed resolved and correctly fixed in the current file content (commit 4c3a4f6, rebased equivalent of d6087fd):
implement-tdd/SKILL.mdstep 4 now has an explicitescalate: ... — go to step 7branch for the structural turn, and step 7'sclarifyhandling correctly distinguishes retrying step 4 vs. step 6 depending on escalation origin.- Step 5 now has the
structural-red: ... — route back to step 4branch for the behavioral turn. tdd-implementer.md's "Structural turns" section now states escalation is a possible outcome there too.
Blocking dependency resolved since last validation: ADR-300 (PR #51) has merged (0a142e4, mergedAt: 2026-07-05T02:57:44Z) and is now an ancestor of both this PR's head and its base branch (feature/ADR-288-tdd-milestone-1). Confirmed test-driven-development/SKILL.md now contains the four Practice-rule headings ("AAA structure", "Red must fail for the right reason", "Arrange and Act are frozen after first green", "Naming convention") verbatim, and tdd-tester.md/tdd-implementer.md's by-name references match exactly — no rewording needed. This resolves the "partial" finding on exit criterion 1 from the prior validation; all four exit criteria are now satisfied.
New issues in modified files: none found. Tool grants remain exactly [Read, Glob, Grep, Edit, Write, Bash] with no Agent/SendMessage/Task in either agent file; file-scope discipline, the escalation tiers, and the behavior-selection rubric are all correctly wired.
Minor, non-blocking note: the PR description's "Design decisions" and "Known ambiguities" sections still say ADR-300/PR #51 "is still unmerged" — this is now stale given the merge above. Worth a quick edit to the PR body before merge, but not a code issue and not blocking sign-off.
Signing off — approved.
jodavis
left a comment
There was a problem hiding this comment.
At a high level, the two new agents should each be broken into an agent and a skill. The agent should focus on constraints ("You only modify test code, never product code", and vice versa) and general guidelines ("You always make the simplest, dumbest change possible to make tests pass"). The skill should describe the mechanics of a turn. That skill will give the Developer agent a simple prompt to send as well ("invoke tdd-add-red-test or tdd-make-test-green as examples) so maybe that will help the 'Developer' not need to predict whether a structural or behavioral prompt is needed.
…ownership Addresses PR #52 review comments: - Split each agent into constraints/guidelines (agent) and turn mechanics (new tdd-red-turn / tdd-green-turn skills), so Developer no longer predicts structural vs. behavioral turns — tdd-tester and tdd-implementer decide that themselves via their own skill each turn. - Escalation retries are now fully generic: Developer resends the same per-turn message with the clarification folded in, without tracking whether the escalation originated from a structural or behavioral turn. - Replaced the shared per-component log file with staging between turns: each verified turn is `git add`-ed (never committed) so file-scope checks stay exact and no commit ever captures a red/broken intermediate state; a single real commit happens once the component reaches `done`. - Added the requested async/dependency-failure coverage guidance to tdd-red-turn's behavior-selection rubric, and concrete C# "dumbest thing possible" examples to tdd-implementer's smallest-possible-change section. - Reworded tdd-implementer's escalation note to stop forward-referencing a "behavioral turns" section that no longer exists in the trimmed agent doc. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CCMPzipW7hxA1GMjmfkiJ4
|
Addressed the CHANGES_REQUESTED review and all outstanding inline threads in commit 29349c8. Agent/skill split (the core ask):
This directly fixes the turn-ownership inconsistency flagged in the inline threads: Developer no longer predicts or names whether the next turn is structural or behavioral (the old step 3 in Other threads, all replied to inline:
Ready for another look whenever you have a chance. |
…plement-direct
implement-task/SKILL.md now branches on the task brief's Components in scope section:
absent or explicitly empty falls back to the pre-existing single-agent
test-driven-development flow (one commit for the whole task); one or more components
dispatches each, in dependency order, to implement-direct (Wrapper/Orchestrator) or
implement-tdd (Testable), each of which commits its own component. The pipeline's
single-spawn_agent interface with Developer is unchanged. implement-direct/SKILL.md
(new) implements one Wrapper (no test) or Orchestrator (one narrow integration test
against real, non-mocked direct dependencies) directly, then commits — or stages
instead of committing when invoked with the optional skip-commit argument from
implement-tdd's Tier 2 resolve_directly escalation, which still owns that component's
single commit.
Verified implement-tdd's existing "follow the implement-direct skill... Stage the
change" resolve_directly text already resolves correctly against implement-direct's
new stage-vs-commit contract with no change needed there.
Dry runs (scratch fixtures under scratchpad/adr303_dryrun_{zero,three}, transcripts
under ~/.dev-team/jodavis/agent-plugins/logs/ADR-303-dryrun-*.log):
- Zero-component task brief: implemented directly via test-driven-development, single
commit, no dispatcher iteration.
- Three-component task brief (SystemClock Wrapper, TTLCache Testable, CachingService
Orchestrator depending on both): produced exactly one commit per component in
dependency order, each routed to the correct skill. The Testable component went
through a real structural/behavioral red-green loop with an interleaved refactor
turn (consolidating two tests into a parametrized one) using real pytest runs.
Known limitation, consistent with ADR-301 PR #52 and ADR-302 PR #53: this session's
Agent tool does not expose tdd-tester/tdd-implementer/tdd-refactorer as spawnable
agent types, so Developer manually played each role's turn rather than using literal
Agent/SendMessage sub-agent spawning. The protocol choreography and every build/test
run were genuine, real pytest executions — only sub-agent process isolation was
simulated.
…plement-direct (#54) * ADR-303: Rewrite implement-task as a per-component dispatcher, add implement-direct implement-task/SKILL.md now branches on the task brief's Components in scope section: absent or explicitly empty falls back to the pre-existing single-agent test-driven-development flow (one commit for the whole task); one or more components dispatches each, in dependency order, to implement-direct (Wrapper/Orchestrator) or implement-tdd (Testable), each of which commits its own component. The pipeline's single-spawn_agent interface with Developer is unchanged. implement-direct/SKILL.md (new) implements one Wrapper (no test) or Orchestrator (one narrow integration test against real, non-mocked direct dependencies) directly, then commits — or stages instead of committing when invoked with the optional skip-commit argument from implement-tdd's Tier 2 resolve_directly escalation, which still owns that component's single commit. Verified implement-tdd's existing "follow the implement-direct skill... Stage the change" resolve_directly text already resolves correctly against implement-direct's new stage-vs-commit contract with no change needed there. Dry runs (scratch fixtures under scratchpad/adr303_dryrun_{zero,three}, transcripts under ~/.dev-team/jodavis/agent-plugins/logs/ADR-303-dryrun-*.log): - Zero-component task brief: implemented directly via test-driven-development, single commit, no dispatcher iteration. - Three-component task brief (SystemClock Wrapper, TTLCache Testable, CachingService Orchestrator depending on both): produced exactly one commit per component in dependency order, each routed to the correct skill. The Testable component went through a real structural/behavioral red-green loop with an interleaved refactor turn (consolidating two tests into a parametrized one) using real pytest runs. Known limitation, consistent with ADR-301 PR #52 and ADR-302 PR #53: this session's Agent tool does not expose tdd-tester/tdd-implementer/tdd-refactorer as spawnable agent types, so Developer manually played each role's turn rather than using literal Agent/SendMessage sub-agent spawning. The protocol choreography and every build/test run were genuine, real pytest executions — only sub-agent process isolation was simulated. * ADR-303: Rework implement-task dispatcher and implement-direct per PR #54 review implement-task/SKILL.md's steps 5-11 now: write E2E scenarios first (behavior-driven-development), dispatch each declared Components-in-scope row to implement-direct (Wrapper/Orchestrator) or implement-tdd (Testable), triage any leftover exit-criteria work -- including the whole task when there's no Components in scope section at all -- into component-shaped-but-uncaptured (classified on the spot via component-taxonomy, routed through implement-direct/implement-tdd) or non-component-shaped (implemented directly, staged for later), re-confirm E2E scenarios, self-review the cumulative diff, fix anything it surfaces, then make one final commit covering leftover work plus review fixups (skipped when nothing remains). There is no longer any code path that reaches test-driven-development's old write-all-tests-then-implement procedure. implement-direct/SKILL.md now states explicitly to fix any build/test failures before committing or staging (step 3), removes the stale "no Components in scope -> fall back to test-driven-development" bullet (that case is now implement-task's triage bucket instead), and cites tdd-practices in place of test-driven-development for the Orchestrator integration test's AAA/naming conventions. Dry runs (scratch fixtures under scratchpad/adr303_dryrun_{adhoc,leftover}, transcripts under ~/.dev-team/jodavis/agent-plugins/logs/ADR-303-dryrun-*.log): - Zero-Components-in-scope task brief with real logic (a percent_change utility): Developer classified the whole task ad hoc as Testable via component-taxonomy and drove it through implement-tdd's real red/green loop (manually playing tdd-tester/tdd-implementer/tdd-refactorer's turns -- these agent types are not in this session's available agent list, the same disclosed constraint as PR #54). Result: exactly 1 commit, made by implement-tdd itself, not a whole-task commit from a test-driven-development-style flow. - One declared Testable component (RetryPolicy) plus a leftover demo script and doc note: RetryPolicy went through its own real red/green loop and commit via implement-tdd; the script and doc were implemented directly and staged; a deliberately-introduced self-review finding (a doc file missing CONTRIBUTING.md's required Summary: line) was caught and fixed before the final commit. Result: 2 commits -- RetryPolicy's own commit, then one final commit covering the leftover work and the self-review fix, confirmed by a clean `git status` afterward. - Exit criterion 5's one-Wrapper/one-Orchestrator/one-Testable dry run reuses PR #54's already-executed evidence (ADR-303-dryrun-three-*.log) rather than re-running it: the declared-component dispatch mechanics (this rework's step 6) and both E2E wrapper calls are unchanged in substance, only renamed to cite behavior-driven-development -- re-deriving an identical result was out of scope. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RUxmZpJaDFeN8edPacgkZQ --------- Co-authored-by: Joe Davis <ElwoodMoves@hotmail.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Work item
ADR-301: Add the
tdd-testerandtdd-implementersub-agent definitions and theimplement-tddskill that drives one Testable component through the structural-then-behavioral red/green ping-pong loop — the behavior-selection rubric plus all three escalation tiers — up through the component reachingdoneand being committed. (The post-donetdd-refactorerpass is out of scope; that's ADR-302.)Changes
plugins/dev-team/agents/tdd-tester.md(new) — Tester half of the TDD pair. Tools:Read,Glob,Grep,Edit,Write,Bashonly (noTask/Agent/SendMessage). Scoped to test-files-only. Covers structural-vs-behavioral red decision logic, the three-point behavior-selection rubric (skip Wrapper-tier, cheapest structural fit, happy-path-first), and the one-line reply contract (structural-red/red/done). Referencestest-driven-development's Practice rules (AAA structure, Red must fail for the right reason, Arrange/Act frozen after first green, Naming convention) by name only.plugins/dev-team/agents/tdd-implementer.md(new) — Implementer half, same tool grant, scoped to production-files-only. Covers the smallest-possible-change rule, structural-turn stub resolution, the Tier 1 pair-internal retry, and the Tier 2/3escalatereply (clarify/resolve_directly/split_scope).plugins/dev-team/skills/implement-tdd/SKILL.md(new) — orchestration skill invoked by Developer (not the sub-agents). Drives: per-component log file setup, spawning the pair, the "needs a structural turn?" judgment, structural and behavioral turn routing using the spec's exact verbatim turn-message templates, the Tier 1 mechanical relay, Tier 2 escalation handling (including aresolve_directlypath that calls out toimplement-direct), Tier 3 best-effort fallback, protocol-violation handling viagit diff --name-onlyafter every turn, and the post-donecommit-changescall. Ends cleanly at "done → commit" — no post-donerefactor step.Design decisions
Agent/SendMessagesub-agent spawning available in this session. Both required dry runs were driven by manually simulating the orchestrator/tester/implementer roles against a syntheticTTLCachecomponent, running realpytestbuilds/tests at each turn so red/green transitions are genuine. The protocol logic and build/test execution were real; the sub-agent invocation mechanism was simulated. Re-validating with a live multi-agent run oncedeveloper.mdgainsSendMessage(ADR-304) would be worthwhile.resolve_directlystood in forimplement-direct(ADR-303, not yet built). In dry run 2, Developer implemented the disputed piece (FIFO eviction) directly itself, then ran the disputed test plus the full suite to confirm the regression check passes.tdd-implementer.mdowns the Tier 1 judgment;implement-tdd/SKILL.mdonly describes Developer's role as a mechanical, no-judgment relay of therevise-requestnote andtdd-tester's reply, since neither sub-agent hasAgent/SendMessageto message each other directly.Dry run results
Dry run 1 (TTL cache, empty test file to full coverage) — sequence of one-line replies produced (full transcript:
~/.dev-team/jodavis/agent-plugins/logs/ADR-301-tdd-TTLCache-dryrun.log):Ends with every branch of
TTLCachecovered. Confirms the structural/behavioral split, cheapest-structural-fit rubric, and Wrapper-tier skip all fire as designed.Dry run 2 (forcing a Tier 2
resolve_directlyescalation) — full transcript:~/.dev-team/jodavis/agent-plugins/logs/ADR-301-tdd-TTLCache-resolve-directly-dryrun.log:Developer resolved directly: implemented FIFO eviction, then ran the disputed test plus the full 7-test suite. Result: all 7 tests pass, including the disputed test — retained unmodified in the test file (not discarded or rewritten) and counted toward coverage, exactly as the exit criterion requires.
Tests
No unit/E2E tests apply — the deliverable is markdown-only agent/skill definition files with no executable production code (per
missing-test-harness, this repo has no test harness for prose/instruction files). The two dry runs above are this repo's documented stand-in for automated verification of this kind of deliverable.Known ambiguities for reviewer attention
Agent/SendMessagespawning, since this session's persona lacksSendMessageand the new agent types aren't yet registered as spawnable.resolve_directlypath stood in forimplement-direct(ADR-303, not yet built) by having Developer implement the disputed piece directly inline.