Task in. Accountable change in production out.
sembl-stack runs the whole pipeline around your coding agent: a spec becomes declared bounds, an agent writes inside a disposable sandbox, the sembl gate judges the real diff against those bounds, a PASS merges and deploys, and a post-deploy gate confirms it's healthy - or rolls it back. Every stage is a swappable adapter behind one typed contract. The stack doesn't promise the model writes better code; it guarantees the process around the model is correct, recorded, and can't be talked out of its verdict.
A scripted replay of a real loop - including the part vendors don't show you: the first attempt gets BLOCKED and retried. Run it yourself: quickstart →
Nine stages. One wire between them.
Each stage consumes typed artifacts and produces typed artifacts - that's the whole interface. A stage doesn't know or care what implements its neighbors.
Stages talk in artifacts, not in prose.
Every hand-off in the pipeline is a typed, serialized artifact in the run store. That's what makes stages swappable - and what makes a run auditable after the fact: .sembl/runs/<id>/ holds the complete paper trail of how a change reached production.
Taskwhat was asked - the input to everythingBoundsthe contract: editable paths, forbidden areas, churn budgetChangethe real unified diff the executor producedVerdictPASS / WARN / BLOCK, with reasons, bound to the exact diff it judgedMergeRecordwhat merged, under which verdict, with the binding check's outcomeDeliverywhat deployed where - the input to the post-deploy gateTraceevery stage transition, timed
.sembl/runs/2ca41f/
├─ task.json # what was asked
├─ bounds.json # the declared contract
├─ change.json # the actual diff
├─ verdict.json # the gate's judgement + subject binding
├─ merge-record.json # what shipped, and under whose PASS
└─ trace.json # the timelineChange a layer with one line. Not one refactor.
The stack takes no side in the agent wars. If a better executor ships next month, you swap it in sembl.stack.yaml and the rest of the pipeline doesn't notice. The same goes for the sandbox, the repo-intel layer, and the deploy target.
execute: claude # → aider | opencode | yours
sandbox: clone # disposable worktree
intel: symgraph
gate: sembl # the one layer that never lies
deploy: vercelWe own exactly three things
The artifact contract + stage Protocol, the gate (L5 and the post-deploy L8), and the glue that lets layers be replaced. Everything else is deliberately someone else's best-in-class tool behind an interface.
Executors are interchangeable
Three ship today - Claude Code, Aider, OpenCode - and adding one is an adapter, not a fork. The gate treats them all identically: it only ever sees the diff.
Presets to start from
just-gate gates any diff with nothing but sembl installed. gate+sandbox runs the whole loop with a mock executor and no API keys. full-loop is the real thing.
A verdict is bound to the change it judged.
Most agent pipelines stop at "the check passed." sembl-stack's spine goes further: a verdict can only ship the exact change it was issued for.
Verdicts carry their subject
Every verdict is stamped with the SHA-256 and file set of the diff it judged. apply recomputes the hash and refuses a verdict that wasn't issued for that patch; merge refuses if the merge would ship files the verdict never saw.
BLOCK means blocked
A BLOCK verdict is never applied and never merged - the loop retries the executor instead. Overrides exist (--skip-binding-check), but they're recorded in the MergeRecord forever. There is no quiet way past the gate.
Production is gated too
After deploy, the L8 gate checks the live delivery - health and payload, deterministically - and triggers a rollback when it fails. Proven live against a real deployment, not a diagram.
The gate at the center is Sembl - and it stands alone.
If you don't want the whole factory, take just the gate: pip install sembl gives you the deterministic PASS / WARN / BLOCK verdict in CI, pre-commit, or over MCP. The stack is what you graduate to when you want the gate wired through merge, deploy, and production.
From zero to a gated loop in four commands.
Or in one: bare sembl-stack in your repo starts a guided run - agent & keys with live status, the task in plain English, the loop streaming in your terminal. The commands below are the same machinery, scriptable. Full detail in the documentation.
pip install sembl-stack sembl
# scaffold sembl.stack.yaml + task.yaml from a preset
sembl-stack init
sembl-stack doctor # config-aware preflight
# plan → execute → gate → retry-on-BLOCK
sembl-stack loop task.yaml
sembl-stack runs # inspect the run store
sembl-stack apply <run-id> # apply the accepted patch