{"slug": "bondsmith-hard-bonds-for-soft-claims", "title": "Bondsmith: Hard Bonds for Soft Claims", "summary": "A developer has released Bondsmith, a Rust-based workflow engine for agentic software development built on the rule that no LLM claim counts without a deterministic proof bonded to it. Bondsmith runs each step as a disposable LLM Worker session, verifies results through deterministic Gates such as lint, type-check and test runs, and uses a Driver state machine as the only component that writes state, with a thin CLI and a read-only UI on top. The design targets six requirements, led by deterministic proof and freedom from any single LLM provider or coding harness like Claude Code or Codex.", "body_md": "\"All tests pass.\" I have read that sentence at the end of an agent session more times than\nI can count, and more than once it was false. The tests weren't run, or they were run before\nthe last edit, or they were never written.\n\nBondsmith is the workflow engine I built around one rule: no claim counts without a proof\nbonded to it. I still want the model to do what it is good at, which is generating code.\nBut whatever it tells me about that code afterwards, I check with something which is not an\nLLM.\n\nWhere the name comes from\n\nBrandon Sanderson's The Way of Kings, the first book of the Stormlight Archive. The\nBondsmiths are one of the ten orders of the Knights Radiant, and the rarest: there are never\nmore than three of them. The other orders fight, heal or travel. A Bondsmith's power is\nconnection, binding things and people together. Highly recommend this one.\n\nWork is admitted only when its entry conditions hold, and it counts as done only when its\nexit conditions are shown to hold against real evidence. The LLM is free inside one step.\nWhatever it says about that step afterwards is a soft claim, and a soft claim needs a hard\nbond. Let me show you.\n\nSix requirements decide whether a system for agentic development works for me.\n\n1. Deterministic proof. I don't want to take the LLM's word that an action happened. For\nevery action I care about, a tool runs a check and writes the result by deterministic\naction.\n\n2. No single harness. I don't want to be chained to one LLM provider, or to one agentic\ncoding harness like Claude Code or Codex. I want to be able to use different ones. Models\nchange every few months and the pricing and limits change with them, so I don't want to\nrebuild my whole workflow every time I switch.\n\n3. Generic workflows. There is no one generic approach, one SDD definition or one flow\nwe can use for every implementation, every feature delivery and every piece of tech debt. A\nnew feature needs a spec and a breakdown into tasks. A bug fix needs neither. I should be\nable to define my own workflows and change them without touching the engine that runs them.\n\n4. A CLI. I want to run the commands for the different actions from the terminal. I can\nrepeat a command, I can put it in a script, and it was the simplest thing to build first.\nEverything else can be built on top of it.\n\n5. Observability. I want to see anything and everything. I want to see agent logs. I\nwant to see the effects of the deterministic gates. I want to see the definition of each\ntask. Everything under my control. When a run goes wrong I need to know what the agent\nread, what it changed and which check stopped it, without asking the agent.\n\n6. One place to look. I want a UI which presents the different features in one place,\nso I can easily check where I am with a given implementation. When I have a few features\nrunning in a few repos at the same time, I lose track pretty quickly, and I don't want to\nopen five terminals to find out where I was.\n\nNot all six are equally important to me. The first one is the reason I built Bondsmith at\nall, and the other five are there to make it hold no matter what kind of work I do or which\nmodel I use.\n\nBondsmith is a Rust workspace: one core library, a thin CLI, and a\nread-only UI. The crate layout is on the Bondsmith project page.\nHere I care about who does what during a run.\n\nA Worker is a disposable LLM session spawned for exactly one step of work, which then\nexits. A Gate is a deterministic check, a test or a lint run, whose verdict comes from\nthe tool. The Driver is the state machine in the middle: it spawns Workers, runs Gates,\nand is the only thing that writes state.\n\nEach repo configures its own set of Gates, such as lint, type-check and the test suite. That\nset is the repo's gate pool, and a Flow can ask for the whole pool to run at once.\n\nThere is no arrow from the Worker to state in the figure. The Worker edits files and makes\ncommits, that's all it can do, and nobody asks it whether it passed or failed.\n\nEvery step in Bondsmith declares Postconditions: assertions over the state of the world\nafter the step has run. The Driver gathers the facts itself, from disk, from git and from\nGate results, and evaluates each Postcondition in plain Rust code. The vocabulary is closed.\nA few of the verbs:\n\nexit_zero. The Gate's command exited with code 0.\n\nsha_is_ancestor. One commit is in the history of another.\n\nnon_empty: spec.md. The file exists and has content.\n\ngate_pool_pass. Every Gate in the gate pool passed.\n\nA missing fact fails closed: if the Driver can't find the evidence a verb needs, the\nPostcondition fails.\n\nA Postcondition either passes or hard-blocks the run, there is nothing in between.\n\nThis way \"the tests were run\" is exit_zero: role:test, checked against the exit code of a\ntest command which the Driver ran itself.\n\nNothing in a workflow definition knows which harness runs it, or which model. The contracts\nand the prompts carry no harness-specific text, and Workers are launched through one port in\nthe core. Claude Code or Codex, or anything else with a headless mode, can sit behind that\nport.\n\nToday one launcher sits there: Claude Code. Pi is the next target on the\nRoadmap.\n\nA workflow in Bondsmith is called a Flow: a named, ordered chain of Phases, each\nwith its own Steps and Postconditions. A Flow is plain data, JSON contracts and Markdown\nprompts in a directory, read from disk at run time. Nothing is compiled into the binary, and\nno Flow is built in. I can copy a Flow, drop a Phase, add a Gate, and the next run uses it.\n\nEvery run leaves three things on disk. A state file, which is the single source of truth.\nAn append-only event log, one JSON line per event: step started, Gate finished,\nPostconditions checked, step advanced or held. And for every headless Worker, a Session log\nwith its raw output.\n\nFor a headless Worker the raw log is a stream of JSON, so Bondsmith also derives a Session\ntranscript from it: every file the Worker read, every edit, every command, in order, with\nthe model, the tokens and the duration.\n\nThe trail on disk is complete. The Bondsmith UI is a local, read-only page over the same\nfiles. Its first tab lists every feature across my projects with its current status.\n\nOpen a feature and you see where the implementation is: the Phase it is in, the Task graph,\nand the progress of every step for every Task. Open a step and you are in that Worker's\nSession transcript.\n\nI use two Flows. feature is the main one, of course: it takes a feature from an\ninterview to a set of merged pull requests. address-issue takes one GitHub issue to one\npull request. A third, file-fix, is address-issue with a diagnosis Phase in front.\n\nThe Phases are different because the work is different. A feature needs an exploration, a\nspec and a graph of Tasks. An issue already says what is wrong, so a plan is enough and we\ncan go straight to code. I described the Phases of the feature flow in\nBounded Chaos, back when it was a pile of bash and slash commands.\nThe Phases are mostly the same as back then. The difference is that now each of them is a\ntyped contract, enforced by the engine.\n\nBoth Flows keep one Phase: a test-first implement. In the feature Flow it runs nine Steps\nfor every Task.\n\nHere is a real run where one Postcondition of the second test Gate didn't hold:\n\nGoing through the checks from the bottom up:\n\ngate_failed_at: red_test_sha,role:test found true. The Driver checked out the commit\nwhere the Worker claimed to have written a failing test, ran the tests there, and they\nfailed.\n\nsha_is_ancestor: red_test_sha,HEAD found true. That commit is in the history of the\ncurrent code. It wasn't written afterwards and slipped in.\n\ngt: test_count,baseline found 1711,1708. The suite had 1708 tests before the Task and\nhas 1711 now. Tests were added, and I know how many.\n\nsha_recorded found true. The red commit exists at all.\n\nexit_zero: role:test required 0 found 1. And still one test fails right now.\n\nSo four checks out of five hold, and it is still not enough. The step is held until the\nfailing test passes.\n\nThe review Steps produce Findings: one issue each, with a type, a severity, a file and a\nproposed fix. Each reviewing agent writes its Findings into a report, one per Task. Ruling\non them by hand, I kept making the same ruling again and again. So in the feature Flow the\nsystem learns from its mistakes, and from my decisions.\n\nThe first mechanism is Triage rules. Each repo carries its own, ordered,\nfirst match wins. This is a real one:\n\nAn accepted Finding gets fixed, without asking me first. A Worker groups related Findings\ninto Review units and applies the rules. The Driver doesn't trust the Worker's triage\neither: it re-derives every claimed decision from the rules, in code, and a mismatch\nhard-blocks. There is also a floor no rule can cross. A rule may never\ndecide a security Finding, or anything above medium severity. Those always come to me.\n\nThe second mechanism is the learn-from-reports Phase. The reports are the ones the review\nSteps wrote during implement. The Phase mines their Findings and my decisions on them for\npatterns, and puts each candidate in front of me to accept, reject or\nedit. A decision I keep repeating is proposed as a new Triage rule, in a pull request\nagainst that repo. A lesson general enough to reuse is written as a rule into the\nKnowledge base.\n\nThe mechanism for feeding these rules back is fully there. What I'm working on now is how\nto use it in the different implementation and review Phases, so the next Task starts with\nthe rule already in place.\n\nThere is a lot, lot, lot still to cover. The system learns from the codebase, but the\nsystem also needs to evolve, and the observability I built for myself is the best source for\nthat. Every Worker run already leaves a Session log and its cost behind. Analyzing them\ntells me why a single step went wrong, and where model routing can make the whole Flow\ncost-effective. Reading them all should tell me what to change in Bondsmith.\n\nIf you take one thing from this post, you don't need Bondsmith for it: pick one action your\nagent reports on, and replace the report with a check a program runs.\n\n\"All tests pass\" becomes the exit code of the test command, run by a script after the\nsession ends. \"I committed the fix\" becomes a git log on the branch. \"The report is written\"\nbecomes a file that exists and is not empty.\n\nStart with the claim which burned you the most. For me it was the tests. One check is enough\nto feel the difference, because the agent can say whatever it wants and you don't have to\nbelieve it anymore.\n\nBondsmith is the same habit, just applied to every step. Start with one check and see for\nyourself.\n\nBondsmith is going open source\n\nI'm opening the Bondsmith repository in the upcoming weeks. Subscribe to not miss the\nday!\n\nDeep DiveAIWorkflow\n\nThanks for reading\n\nMore like it are on the way - subscribe to catch them.", "url": "https://wpnews.pro/news/bondsmith-hard-bonds-for-soft-claims", "canonical_source": "https://coldtake.dev/blog/bondsmith-hard-bonds-for-soft-claims", "published_at": "2026-10-12 00:00:00+00:00", "updated_at": "2026-11-09 11:51:42.339507+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "artificial-intelligence"], "entities": ["Bondsmith", "Rust", "Claude Code", "Codex", "Brandon Sanderson", "The Way of Kings", "Stormlight Archive"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/bondsmith-hard-bonds-for-soft-claims", "markdown": "https://wpnews.pro/news/bondsmith-hard-bonds-for-soft-claims.md", "text": "https://wpnews.pro/news/bondsmith-hard-bonds-for-soft-claims.txt", "jsonld": "https://wpnews.pro/news/bondsmith-hard-bonds-for-soft-claims.jsonld"}}