Generic builder guardrails for Hermes agents running local or OpenAI-compatible models.
Current release: 0.8.10. See CHANGELOG.md for upgrade notes.
Local coding models can be useful builders, but they tend to fail in predictable ways: too many files before the first test, repeated full-suite loops, weak resume state after compaction, and language-specific setup mistakes. Builder Doctor gives Hermes agents a small toolset and skill card that makes large software builds incremental, resumable, and verifiable.
This repository is model-agnostic. It does not include model weights, private Hermes configuration, API keys, session logs, or machine-specific paths.
builder_map: compact project facts before editing.builder_plan: phased build plan with small batches and verification gates.builder_doctor: static project risk scan for common setup mistakes.builder_budget: phase/file budget check so models stop widening scope.builder_verify: bounded build/test runner with compact diagnostics.builder_failure_plan: focused language repair plan after a failed verifier.builder_resume: project-local checkpoint state in.hermes-builder/state.json.builder_acceptance: measurable artifact-and-verifier contract that prevents a thin passing test from being mistaken for completion of the requested scope.builder_receipt: final handoff summary with files, checks, and warnings.- Hermes hooks that enforce staging inside Builder Doctor-marked projects:
three write/patch calls trigger a verification gate before more edits can run,
passing verification
requires budget/receipt before more edits, failed verification allows two
repair patches before another check, edits are anchored to the mapped project
root, terminal commands cannot
cdinto or execute scripts from another project, and raw terminal verifier loops are redirected back tobuilder_verify.
Supported lanes:
- Node, JavaScript, TypeScript, package scripts, ESM, Vitest.
- SwiftPM, Swift, XCTest.
- Python,
uv,pytest,pyproject.toml. - Rust, Cargo.
- Go modules, including mixed-package directory detection.
For a substantial build, the intended sequence is:
builder_mapandbuilder_planestablish project facts and the objective.builder_doctoridentifies setup risks.builder_resumesaves the objective and current phase.builder_acceptancerecords concrete artifact paths and exact verifier commands.- The model writes a small source/test batch, then calls
builder_budget. builder_verifyruns the bounded proof command; failures go throughbuilder_failure_planbefore repair.- After a pass,
builder_budget(after_verify=true)andbuilder_receiptclose the stage.
If unchanged work is verified or receipted again, 0.8.0+ returns
already_verified / already_complete instead of rerunning the proof. The
model should follow next_required and answer the user rather than cycling.
In 0.8.1, replacing or updating acceptance opens a fresh evidence stage. Swift gets a six-edit coherent checkpoint batch, and placeholder-only Swift tests no longer satisfy handoff readiness.
In 0.8.2, a failed builder_verify persists a compact latest-failure record.
After context compaction, builder_failure_plan can recover it from only the
project path, and blocked repair edits return that exact recovery call.
In 0.8.3, verifier timeouts terminate the verifier's whole process group before returning. This prevents test runners such as XCTest from surviving as orphaned processes, while safely preserving partial timeout output for diagnosis.
In 0.8.4, timeout cleanup also snapshots and terminates detached descendants. This covers XCTest runners that create their own process group before hanging.
In 0.8.5, a verified build artifact may be copied from the project's build output into a macOS Applications folder. Terminal-based source edits and unverified exports remain blocked.
In 0.8.6, project-root anchoring also inspects terminal working-directory changes and directly executed script paths. A mapped build cannot silently switch into another repository and run that repository's installer.
In 0.8.7, only builder_verify can establish verification proof. Manual
checkpoint summaries remain visible history but cannot unlock a receipt or
shadow a trusted passing verifier record.
In 0.8.10, planning tools return an action deadline until the project contains
a real implementation slice. After planning, the agent must create a manifest,
one core module, and one focused test in at most three writes before checking
its budget and calling builder_verify. This prevents reasoning-heavy local
models from spending an entire build turn planning without producing runnable
work.
plugin/builder-doctor/ Hermes plugin tool implementation
skills/builder-doctor/ Skill instructions for agent behavior
examples/ Optional generic config and soul snippets
docs/ Installation and operating notes
tests/ Standard-library smoke tests
CHANGELOG.md Release and upgrade notes
If you are driving this through a Hermes agent, you can point the agent at this repo and ask it to do the install:
Install Hermes Builder Doctor from
https://github.com/embwl0x/hermes-builder-doctor.
Clone or update the repo into a normal workspace you control, run
./scripts/install.sh --verify for this Hermes home, restart or reload the Hermes
gateway/app so the plugin is visible, then run ./scripts/verify-install.sh.
Do not change model aliases, personas, production configs, or API keys unless I
explicitly ask.
Clone the repository:
git clone https://github.com/embwl0x/hermes-builder-doctor.git
cd hermes-builder-doctorThen install:
./scripts/install.sh --verifyThen restart Hermes or its gateway so the plugin and skill are reloaded.
Confirm the install:
./scripts/verify-install.shOptional: copy the ideas from examples/ into your own Hermes config or agent
soul files. Do not paste examples blindly over an existing production config.
Start here if you are installing for the first time:
docs/QUICKSTART.md— short end-to-end install and first test.docs/HERMES_AGENT_SETUP.md— custom Hermes homes, force installs with backups, and smaller local model prompt guidance.docs/LOCAL_MODEL_PLAYBOOK.md— operating pattern for weaker local models.
uv run --no-project python -m unittest discover -s tests
uv run --no-project python -m py_compile plugin/builder-doctor/tools.py plugin/builder-doctor/__init__.py
uv run --no-project --with pytest pytest -q tests/test_stress_harness.py
./scripts/install.sh --force --dry-runThe core suite uses the standard library. The stress-harness tests use an
ephemeral pytest environment through uv; they do not add project dependencies.
After installing into a Hermes agent, you can run disposable build stress tests against that agent:
export HERMES_BASE_URL="http://127.0.0.1:8644" # replace with your Hermes api_server URL
export HERMES_MODEL="your-local-model-alias" # replace with a model listed by that gateway
export HERMES_PROVIDER="your-provider-slug" # optional; needed for aliases that are not model routes
export API_SERVER_KEY="..." # only if your gateway requires it
./scripts/stress_hermes_builds.py \
--base-url "$HERMES_BASE_URL" \
--model "$HERMES_MODEL" \
--provider "$HERMES_PROVIDER" \
--tasks node,python,go127.0.0.1:8644 is only the common local default. Use the host and port from
the target agent's platforms.api_server.extra.host / port configuration, or
any remote/Tailscale URL that reaches that Hermes gateway.
your-local-model-alias must be the model name exposed by that gateway; the
harness no longer assumes a project-specific default model.
Pass --provider (or set HERMES_PROVIDER) when the local model alias needs an
explicit Hermes provider slug. Omit it for normal model routes.
Use --prompt-mode giant to test whether an intentionally over-scoped product
prompt is converted into staged verified layers instead of a one-shot build.
Use --prompt-mode probe first when testing a new or smaller model: the prompts
are compact and rely on the configured Hermes build workflow instead of naming
every Builder Doctor tool explicitly.
Use --prompt-mode natural --tasks node to measure whether an agent discovers
and follows Builder Doctor from an ordinary build request that names no tools.
The JSON report includes staging signals such as budget use, writes before the
first verifier, receipt use, raw terminal verifier leaks, and completion churn
(verifier/acceptance/receipt calls made after the first receipt).
Start with --prompt-mode probe. A healthy run independently passes its language
verifier, has no raw terminal verifier leak, uses acceptance and receipt, and
keeps completion_churn.excess_completion_calls close to zero.
The stress harness starts Hermes /v1/runs, streams tool events, independently
verifies the generated projects, asks for one repair pass by default, writes a
JSON report, and deletes generated projects unless --keep-projects is passed.
On timeout, SIGINT, or SIGTERM it sends Hermes a stop request for active runs
and only deletes generated projects after Hermes reports a terminal run status.
builder_verifyblocks install/mutation commands such asnpm install,pip install,cargo add, andgo get.builder_verifytreats zero-test output from test commands as a failed checkpoint, even when the command exits with status 0.builder_failure_planturns verifier failures into one-file repair guidance before the next patch; after a failed verifier, write/patch calls are blocked until a failure plan is recorded.builder_acceptancerejects empty/vacuous criteria, duplicate IDs, evidence outside the project root, and evidence from Builder Doctor's own state. A recorded contract blocksbuilder_receiptuntil every artifact exists and every exact verifier command has a successful post-contractbuilder_verifyrecord. The latest trustedbuilder_verifyresult wins, and evidence changes invalidate old proof; checkpoint summaries cannot replace verifier evidence.- Successful unchanged verifier and receipt calls are cached as compact no-ops, with an explicit instruction to stop tool cycling and answer the user.
- For Rust projects, compile-only verification such as
cargo checkis paired withcargo testso a completed stage cannot receipt without the test gate. - Targeted Rust repair commands such as
cargo test test_nameare treated as diagnostics; Builder Doctor requires fullcargo testbefore final receipt. - After
builder_mapmarks a project, Builder Doctor's hooks enforce staged build flow only inside that project's.hermes-builder/state.jsonboundary and block identifiable write/patch/terminal work outside the mapped root. - Terminal heredoc,
tee, redirection,rm,cp,mv, andtouchsource mutations are blocked inside mapped projects; usewrite_fileorpatchso guardrails can count edits. - The tools do not run dev servers, watchers, or long-lived app processes.
- Verification output is compacted and tailed to reduce context growth.
- The skill encourages staged vertical slices instead of one-shot large systems.
See docs/SAFETY.md for packaging and secret-hygiene notes.