Skip to content

Install and state machine #68

Merged
Doorman11991 merged 4 commits into
Doorman11991:masterfrom
scardoso-lu:master
May 30, 2026
Merged

Install and state machine #68
Doorman11991 merged 4 commits into
Doorman11991:masterfrom
scardoso-lu:master

Conversation

@scardoso-lu

Copy link
Copy Markdown
Contributor

No description provided.

claude and others added 4 commits May 29, 2026 23:26
Closes the five structural gaps identified in the TDD analysis:

1. run_tests compound tool (src/tools/run_tests.js)
   - Runs auto-detected test suite and returns structured output:
     { passed, failed, errors, skipped, failures[{name, message}], raw }
   - Per-framework parsers for pytest, jest, vitest, go test, cargo test,
     mocha, node:test — no more small-model output parsing
   - test_filter arg maps to each framework's native pattern flag
     (pytest -k, jest --testNamePattern, go -run, cargo positional, etc.)

2. TDD state machine (src/session/tdd_state.js)
   - Tracks phase: idle → red → green → refactor → idle
   - beginCycle(testName) / confirmRed / advanceToGreen / enterRefactor /
     completeCycle — each with guard checks before transitioning
   - checkToolCall(name, args) blocks impl writes before red is confirmed,
     blocks test edits during green phase
   - phasePrompt() injects current phase context into the system prompt
   - Persists to .smallcode/tdd_state.json across session restarts

3. TDD governor (src/governor/tdd_governor.js)
   - processTestResult(result) drives automatic phase transitions after
     every run_tests call — confirmRed, advanceToGreen, completeCycle
   - checkToolCall delegates to state machine for phase gates
   - Singleton, reset between test runs

4. Tool wiring (bin/tools.js, bin/executor.js, src/api/index.js)
   - run_tests, tdd_begin_cycle, tdd_status, tdd_advance, tdd_reset
     added to COMPOUND_TOOLS and executor switch
   - TDD gate checked before each tool execution in the agent loop
   - Phase prompt injected into system prompt on every turn

5. Updated skills/tdd.md — references new tools and state machine;
   documents phase gates and when each tool should be called

79 new tests across run_tests.test.js, tdd_state.test.js, tdd_governor.test.js

https://claude.ai/code/session_01S8ieQDoUu2nhnLNZYcLaR1
The TDD system now drives a full loop across a list of requirements,
not just a single cycle. The loop only exits when every requirement
has a passing test AND a clean full-suite regression run confirms no
regressions.

Changes:

TDDStateMachine (tdd_state.js):
- New loop mode: initRequirements(list) registers requirements as
  pending, arms the loop, and resets any in-flight cycle
- Requirements tracked as {id, text, status: pending|active|done}
- After skipRefactor/completeCycle in loop mode, _finishCycle()
  auto-advances: marks requirement done, activates the next one,
  returns {loopAdvanced, nextRequirement} for the governor to relay
- allRequirementsDone() / loopComplete() / markRegressionClean()
  for the two-condition completion gate
- phasePrompt() now renders a requirements checklist with ✓/→/○
  markers showing loop progress
- Both modes (single-cycle and loop) persist to tdd_state.json

TDDGovernor (tdd_governor.js):
- processTestResult() handles the IDLE+loop case: after all
  requirements are green, a clean full-suite run triggers
  markRegressionClean() and emits "LOOP COMPLETE"
- Prompts for next requirement when idle between cycles

New tool:
- tdd_loop(requirements[]) — entry point; calls initRequirements,
  resets governor singleton, returns requirements checklist + first action

Updated tools:
- tdd_status — shows full requirements checklist in loop mode
- tdd_advance — skip_refactor auto-advances loop to next requirement

97 tests pass (56 state, 13 governor, 28 run_tests)

https://claude.ai/code/session_01S8ieQDoUu2nhnLNZYcLaR1
The TDD loop now runs without the model knowing TDD protocol.
The model only needs to write tests and implementation — the harness
handles phase transitions automatically.

Harness post-write hook (_tddPostWrite / executeToolWithTDD):
- Wraps executeTool in bin/executor.js and _executeTool in src/api/index.js
- Fires after every successful write_file / patch / append_file / read_and_patch
  when a TDD loop is active
- Runs run_tests automatically (filtered to target test in RED/GREEN,
  full suite in REFACTOR or when all requirements are done)
- Auto-begins cycle: if idle + test file written + failures detected,
  infers the test name from the first failure and calls beginCycle()
- Calls governor.processTestResult() to drive phase transitions
- Appends "[harness] run_tests: <summary>" to the tool response so
  the model sees the result without having called run_tests itself

Tool surface visible to the model reduced from 5 TDD tools to 2:
- tdd_loop(requirements[]) — entry point
- tdd_status — read current progress

tdd_begin_cycle, tdd_advance, tdd_reset remain executable via the
harness internally but are no longer in the model-facing schema.

skills/tdd.md reduced from 66 lines to 14:
  "call tdd_loop, write tests and implementation, harness handles the rest"

115 tests pass

https://claude.ai/code/session_01S8ieQDoUu2nhnLNZYcLaR1
Add agentic TDD loop: run_tests tool, TDD state machine, and phase gates
@Doorman11991

Copy link
Copy Markdown
Owner

Reviewed and merging — this is a strong contribution. A TDD harness (Red→Green→Refactor state machine + run_tests/tdd_loop/tdd_status/tdd_advance tools) fits SmallCode's "small models need guardrails" philosophy well.

What I verified locally (the repo's Build/test workflow only runs on non-fork PRs, so CI here only shows Socket Security):

  • Branches cleanly off current master (9b68e71, post-1.4.0) — no staleness or provider-import conflicts.
  • npm run build passes.
  • 267/267 tests pass (162 existing + ~105 new across tdd_state, tdd_governor, tdd_harness, run_tests test files).
  • Integration is fully opt-in and defensive: phase enforcement / write-gating are no-ops until tdd_loop/tdd_begin_cycle is called, and all hooks are wrapped in try/catch. Existing flows are untouched.
  • All new files are under the repo's 600-line guideline.

Two non-blocking follow-ups for a later PR (no need to hold this one):

  1. A PR description / short doc pointer would help future readers.
  2. There's a small conceptual overlap between the new run_tests tool and the existing src/tools/test_runner.js detector. They serve different roles (detector = discovery of the test command; run_tests = execution + structured output for TDD transitions), so it's fine as-is — but worth a note in skills/tdd.md so they don't get confused.

Shipping in the next minor release (1.5.0). Thanks @scardoso-lu!

@Doorman11991
Doorman11991 merged commit bdaab72 into Doorman11991:master May 30, 2026
2 checks passed
Doorman11991 added a commit that referenced this pull request May 30, 2026
chore(release): v1.5.0 — TDD harness (#68)
@Doorman11991

Copy link
Copy Markdown
Owner

Thank you for your contribution!

scardoso-lu pushed a commit to scardoso-lu/smallcode that referenced this pull request May 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants