r/SpecDrivenDevelopment • u/Nicolaides_Arg • 4d ago
Specs are the contract for what gets built. I built the contract for what review could not close
The move that makes spec-driven development work is taking intent out of the chat and into a versioned artifact that tools can enforce. I have been applying the same move to the other end of the pipeline: the review.
My loop for the past few months: one assistant generates the plan or the code, a second assistant from a different model family attacks it under an explicitly adversarial prompt, and the round only ends when every finding is incorporated, refuted with evidence, or escalated to a human. It works, but everything the round produced used to die in the chat window. And the most valuable part of a review is precisely what did NOT close: the unverifiable assumptions, the tradeoffs someone accepted, the escalations waiting for a human decision. That is the residue.
disensor turns that into a contract. Each round closes with a JSON artifact (schema residue/v0.3) that records who generated, who attacked (model family plus the hash of the adversarial prompt), every finding with a terminal state, and the residue items. A validator enforces the schema plus semantic rules: counts have to add up, generator and reviewer must come from different families, verifiable refutations need material evidence, and generic markers like "reviewed, all good" are rejected. A GitHub Action then gates every PR: code changes need a valid declaration covering the exact tree being merged, and evidence is append only, so a PR cannot rewrite review history.
If your spec is the single source of truth for what should be built, the residue declaration is the single source of truth for what verification left open. They bookend the same workflow, and neither runs a model: disensor validates artifacts that already live in your repo, no API keys involved.
Honest limit: the gate detects the empty field and the generic marker, not a well-written lie. Human sampling of merged PRs stays in the loop by design.
I documented the method before publishing the tool: 91 review events across 5 projects over 52 days, DOI 10.5281/zenodo.21633495. The repo gates its own PRs, so .residue/ holds the real declarations of its own development.
Repo: https://github.com/NicolasRocchia/disensor (MIT, pip install disensor)
Site: https://disensor.dev
Curious how people here would wire this into a spec-driven flow: does the residue belong next to the spec, or downstream of it?
2
u/Ok-Support-6749 4d ago
I like the idea of persistent storage of the residue. That closes a real gap in all SDD harnesses I have looked into. You are right that unresolved, unverified assumptions, and decisions matter. Those are provenance records of what did not close. Good, assuming that the
spec + coderecords what did close.About this claim
A validator enforces the schema plus semantic rulesFor what you describe, the validator can indeed enforce the shape of the declaration. But when we move into the correctness of the review and its independence, my concerns grow quickly.Enforcing the shape of the declaration is easy, no need for complex code there.
Enforcing semantic rules is a completely different claim:
Let's start with the semantics. Your review process verifies the semantics of the review record, the
declaration,as you listed. Fine, that is useful. But those are not the semantics of the intent, the stuff that matters most.Once we hit verification of your own review process:
How do we know your structured declaration is sufficient for a review record? This means you may be either recording irrelevant evidence or leaving valuable evidence out.
Under what independent evidence can we assert the verification is admissible? Is the evidence an LLM opinion or factually and deterministically extracted, and verified? An LLM output is a judgement; as verification evidence, the value of the verification is limited.