Skip to main content

Autonomous architect→plan→code→test→review→security-review loop exposed as a local MCP server

Project description

SDD Harness v2

An autonomous coding loop exposed as an MCP server for Claude Code and Codex. The harness drives a full engineering workflow — from architecture discussion to security review — and requires no Anthropic API key when running through host sampling.

map → architect ──[discuss]──► plan → code → test ──pass──► review → security_review → awaiting_confirmation ──confirm──► done
                                               ↑──fail (retry < MAX_RETRIES)──┘                               └─changes──► code

Every phase is driven by the active host agent (Claude or Codex). The harness manages state, prompts, artifacts, and tests. You stay in the loop at architecture and security milestones.


Install

Option A — zero install with uvx (recommended)

No setup needed. uvx downloads and runs the package on demand.

Add to your Claude Code MCP settings (~/.claude/settings.json or the project's .mcp.json):

{
  "mcpServers": {
    "sdd-harness": {
      "command": "uvx",
      "args": ["sdd-harness"],
      "timeout": 300000
    }
  }
}

Verify Claude sees it:

claude mcp list
# sdd-harness  stdio  uvx sdd-harness

Option B — pip install

pip install sdd-harness

Then use sdd-harness as the command:

{
  "mcpServers": {
    "sdd-harness": {
      "command": "sdd-harness",
      "timeout": 300000
    }
  }
}

Option C — Codex

Clone this repo. Codex picks up .codex-plugin/plugin.json from the checkout automatically — no further configuration needed.


Quickstart

1. Map the target project (once per project)

map_codebase(project_dir="/path/to/your-service")

This parses every source file, builds a SQLite symbol index, and writes an AI architecture narrative to .sdd/codebase/map.md. Run it once per project, then again after large structural changes.

You can also say: "Map the codebase for this project." — the host agent calls the tool automatically.

2. Add project skills (optional but recommended)

Skills teach the harness your project's conventions and are injected into every prompt. Create a skills directory in your target project and add skill files:

/path/to/your-service/.sdd/skills/
    api-conventions.md
    testing-patterns.md
    security-checklist.md

Starter skills are in docs/skills-examples/ — copy and customise the ones you want. See Project Skills for the format.

3. Run a ticket

harness_architect(
  task="add JWT auth middleware",
  service="api-gateway",
  project_dir="/path/to/your-service"
)

Then follow the harness prompts through each step.


The Workflow

Each ticket moves through six phases. The host agent does the thinking; the harness manages state and runs tests.

Phase 1 — Architect

harness_architect(task, service, thread_id?, project_dir?)

Returns an architecture prompt. The host agent produces:

  • Problem framing — what we're solving and the hard constraints
  • Candidate approaches — 2–3 options with genuine tradeoffs
  • Recommended approach — direct and opinionated
  • API / interface design — concrete method signatures, endpoint shapes
  • Implementation concerns — risks, edge cases, known unknowns

Discuss with the human. Once the approach is agreed, move on.

Set REQUIRE_ARCH_APPROVAL=true in your environment to make the harness pause and wait for explicit human sign-off before proceeding.

Phase 2 — Plan

harness_code(thread_id, plan, arch_feedback?, project_dir?)

Pass the implementation plan you produced. Use arch_feedback to record any architectural decisions made during the discussion (e.g. "chose token-bucket over leaky-bucket for burst tolerance"). The harness saves it alongside the plan artifact.

Returns a coding prompt.

Phase 3 — Code

Write the implementation using the coding prompt. Pass it to:

harness_test(thread_id, code, project_dir?)

Phase 4 — Test

The harness runs:

  1. Validator scripts*.sh scripts in VALIDATORS_DIR
  2. Unit tests — command from .sdd/config.json (if configured)
  3. Integration tests — command from .sdd/config.json (if configured)

Returns either:

  • A review prompt if all tests pass
  • A fix prompt if tests failed (up to MAX_RETRIES attempts)
  • A failure summary if retries are exhausted

Phase 5 — Review

Write a code review covering correctness, quality, test coverage, and concerns. Pass it to:

harness_review(thread_id, review, project_dir?)

The symbol DB auto-refreshes here (fast mtime scan). Returns a security review prompt.

Phase 6 — Security Review

Write the security review covering threats, OWASP scan, auth gaps, secrets handling, and risk rating. Pass it to:

harness_security(thread_id, security_report, project_dir?)

The harness stops at awaiting_confirmation.

Confirmation

harness_confirm(thread_id, confirmed, feedback?, project_dir?)

  • confirmed=true → task is done
  • confirmed=false, feedback="..." → reopens coding; retries reset; feedback is included in the next prompt

Project Skills

Skills are reusable engineering patterns stored in the target project at:

<project_dir>/.sdd/skills/*.md

Each skill file has a YAML frontmatter block followed by the skill content:

---
name: rest-endpoint-pattern
description: How to add a new REST endpoint in this project
phases: [architect, plan, code]
priority: high
---
## REST Endpoint Pattern

When adding an endpoint always:
1. Add route in routes/
2. Add service method in services/
3. Add repository method
4. Write an integration test

Frontmatter fields

Field Values Default
name string filename stem
description string
phases [architect, plan, code, review, security_review] or [all] all phases
priority high, medium, low medium

Skills are filtered by phase, sorted by priority, and injected as a ## Project Skills block in the prompt. The history log records which skills were loaded at each step.

Starter skills are in docs/skills-examples/. Copy and customise:

File Phases Based on
api-rest-conventions.md architect, plan, code, review Zalando REST guidelines
testing-patterns.md plan, code, review goldbergyoni/javascript-testing-best-practices
security-checklist.md architect, code, security_review OWASP CheatSheetSeries
clean-code.md code, review zedr/clean-code-python
architecture-patterns.md architect kamranahmedse/design-patterns-for-humans
_TEMPLATE.md blank template

Test Configuration

Structured unit and integration tests are configured per-project in .sdd/config.json:

{
  "tests": {
    "unit": {
      "enabled": true,
      "command": "pytest tests/unit -v --cov=src --cov-fail-under=80",
      "timeout": 120
    },
    "integration": {
      "enabled": false,
      "command": "pytest tests/integration -v",
      "timeout": 300,
      "base_url": "http://localhost:8000"
    }
  }
}

Commands run in project_dir. The harness injects:

  • HARNESS_WORKFILE — path to the written code blob
  • HARNESS_SERVICE — service name from the task
  • TEST_BASE_URL — integration only, from base_url in config

Unit tests run first, then integration tests. Either can be disabled independently. Validator scripts run regardless of this config.


Artifacts

Everything is written inside the target project, not the harness:

your-service/
└── .sdd/
    ├── codebase/
    │   ├── map.md                ← AI architecture narrative        (commit this)
    │   └── symbols.db            ← SQLite symbol index              (commit or gitignore)
    ├── skills/
    │   └── *.md                  ← your project skill files         (commit these)
    └── tasks/
        └── 29062026140509-add-jwt-auth/
            ├── task.md           ← original task + service
            ├── architect.md      ← architecture proposal
            ├── arch_feedback.md  ← architectural decisions (if any)
            ├── plan.md           ← implementation plan
            ├── code.md           ← generated code (last attempt)
            ├── test_report.md    ← PASS / FAIL + test output
            ├── review.md         ← code review
            ├── security_review.md← security review
            └── confirmation.md   ← human confirmation / feedback

What to commit: codebase/map.md, skills/, and tasks/ give the whole team context on what was built, how the architecture was decided, and what concerns were raised. symbols.db can be committed (saves re-indexing on clone) or gitignored (rebuilt with map_codebase).

Scratch files excluded by the auto-created .sdd/.gitignore:

state.sqlite      ← session state DB
validators.log    ← raw validator output
_work.code        ← scratch file passed to validators

Resuming After a Crash

Pass the same thread_id — the harness picks up from the last saved checkpoint:

harness_architect(
  task="add JWT auth middleware",
  service="api-gateway",
  thread_id="29062026140509-add-jwt-auth-middleware",   ← same ID
  project_dir="/path/to/your-service"
)

If the latest session is not done, harness_architect refuses to open a new task and tells the host agent to resume the unfinished one instead.

Check the state of any run:

harness_status(thread_id="...", project_dir="/path/to/your-service")

Validators and Hooks

Validators

Shell scripts that gate the test → review transition. Set VALIDATORS_DIR in your environment:

# validators/lint.sh
#!/usr/bin/env bash
# $1 = path to generated code   $2 = service name
pylint "$1" --fail-under=8

Non-zero exit triggers a retry. After MAX_RETRIES failures the run ends in failed.

Hooks

Shell scripts that fire before/after each phase. Set HOOKS_DIR in your environment. Full state JSON arrives on stdin:

# hooks/post_review.sh
#!/usr/bin/env bash
state=$(cat)
echo "$state" | jq -r '.history[]'

Suffix the filename -blocking to halt the graph on non-zero exit; otherwise failures are warnings only.

Available events: pre_architect · post_architect · pre_plan · post_plan · pre_code · post_code · pre_test · post_test · pre_review · post_review · pre_security_review · post_security_review


Keeping the Map Fresh

The symbol DB auto-refreshes after every completed ticket (fast mtime scan, no model call). For manual refresh — after pulling a big diff or restructuring directories:

refresh_map(project_dir="/path/to/your-service")
Situation Action
First time on a project map_codebase
After each ticket automatic
After pulling upstream changes refresh_map
After renaming / moving many files map_codebase (full rebuild)
Narrative feels stale map_codebase

MCP Tools Reference

Tool Purpose
map_codebase(project_dir) Full index + AI narrative. Run once per project.
refresh_map(project_dir) Incremental update + regenerated narrative.
write_map_narrative(project_dir, narrative) Save a narrative written by the host (used when sampling unavailable).
harness_architect(task, service, thread_id?, project_dir?) Start or resume a ticket. Returns architecture prompt.
harness_code(thread_id, plan, arch_feedback?, project_dir?) Save plan + arch decisions. Returns coding prompt.
harness_test(thread_id, code, project_dir?) Run all tests. Returns review prompt or fix prompt.
harness_review(thread_id, review, project_dir?) Save code review. Returns security review prompt.
harness_security(thread_id, security_report, project_dir?) Save security review. Stops at awaiting_confirmation.
harness_confirm(thread_id, confirmed, feedback?, project_dir?) Mark done or reopen with human feedback.
harness_status(thread_id, project_dir?) Inspect the last saved checkpoint for a run.

Environment Variables

Set these in your shell, a .env file in the working directory, or your system environment.

Variable Default Purpose
ANTHROPIC_API_KEY "" CLI fallback only. Not needed for Claude Code or Codex MCP usage.
SDD_MODEL claude-sonnet-4-6 Model used for CLI fallback path.
SDD_CHECKPOINTS_DIR ~/.sdd-harness/checkpoints Override the default fallback checkpoints location.
MAX_RETRIES 3 Max code→test retry cycles.
REQUIRE_ARCH_APPROVAL false When true, harness pauses at architecture phase for explicit human sign-off.
VALIDATORS_DIR "" Directory of *.sh validator scripts.
HOOKS_DIR "" Directory of lifecycle hook scripts.

CLI Usage

For scripted, fully autonomous runs without an MCP host. Requires ANTHROPIC_API_KEY:

python -m sdd_harness.main "add health endpoint" "my-service" "29062026140509-add-health" \
  /path/to/project /path/to/project/.sdd

The CLI runs the full graph: map → architect → plan → code → test → review → security_review, then stops at awaiting_confirmation.


Publishing to PyPI

To make the harness available to anyone via pip install sdd-harness or uvx sdd-harness:

pip install build twine
python -m build
twine upload dist/*

After publishing, users need zero local setup — uvx sdd-harness downloads and runs the latest version automatically.


Development

git clone https://github.com/Jackson1996vn/sdd-harness-v2
cd sdd-harness-v2

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

# Run all tests — no API key needed
pytest tests/ -v

# Run a single test file
pytest tests/test_routing.py -v

How It Works

Architecture

map → architect → plan → code → test ──pass──► review → security_review ──► awaiting_confirmation
                                  ↑──fail (retry)──┘

The graph is a LangGraph state machine compiled with a SQLite checkpointer. The same thread_id resumes from the last checkpoint after any crash or interruption.

Each node: runs pre_<phase> hooks → does its work → updates state → runs post_<phase> hooks.

Symbol DB (SQLite)

The codebase map is backed by SQLite:

  • Indexed lookups — symbol queries are O(log n) regardless of codebase size
  • Targeted contextmap_node fetches only symbols relevant to the current task
  • Incremental refresh — re-parses only files whose mtime changed (typically <50ms after a ticket)

Languages with AST-level parsing: Python, TypeScript, JavaScript, Go, Rust. Regex fallback for everything else.

No API Key — How Model Calls Work

Claude Code / Codex (your session)
  └── spawns sdd-harness via stdio
        └── harness tool called
              └── ctx.sample("architect this task...")
                    └── routed back to the MCP host session
                          host agent executes the prompt
                          result returned to harness

Every model call is delegated back to the active host session via sampling. The harness never contacts the Anthropic API directly when running through Claude Code or Codex.


Legacy

legacy/watcher.sh — the original bash implementation, kept for reference.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sdd_harness-0.2.1.tar.gz (45.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sdd_harness-0.2.1-py3-none-any.whl (43.9 kB view details)

Uploaded Python 3

File details

Details for the file sdd_harness-0.2.1.tar.gz.

File metadata

  • Download URL: sdd_harness-0.2.1.tar.gz
  • Upload date:
  • Size: 45.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.5

File hashes

Hashes for sdd_harness-0.2.1.tar.gz
Algorithm Hash digest
SHA256 004ec1b5a6ac7fb2b4d3cd42cfe20cdb14f8b4eb31dc309a36baf493fd1111f3
MD5 7223ba498678b067be2efb9c9d75dcf5
BLAKE2b-256 6990f47160610099add4bace34cf281f5700c97ad58453c75e202258e335e15c

See more details on using hashes here.

File details

Details for the file sdd_harness-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: sdd_harness-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 43.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.5

File hashes

Hashes for sdd_harness-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3ee4d3b41a375dc4d8f493bab162bd6b96b850fe6856ae964e49354a6cda50d4
MD5 32c36e3527db910f71e7743a53b23c21
BLAKE2b-256 863917e4f1b387ebc7fe90481cfeed3eda0761e4521f6825db1978294cc463e6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page