Back to insights

DevSpark v4: The Spec Was Never the Record

August 30, 202615 min read

The last DevSpark article left assimilation unsolved: how does a completed spec's knowledge merge back into a project without the destination becoming the same kind of pile the spec used to be? Working through v4, the fix turned out to be a reframe, not a new mechanism — the spec was never a record to begin with, and the prompts that check it were already asking the wrong question.

DevSpark Series — 30 articles
  1. Taking DevSpark to the Next Level
  2. From Oracle CASE to Spec-Driven AI Development
  3. Fork Management: Automating Upstream Integration
  4. Why I Built DevSpark
  5. Getting Started with DevSpark: Requirements Quality Matters
  6. DevSpark: Constitution-Based Pull Request Reviews
  7. DevSpark: The Evolution of AI-Assisted Software Development
  8. DevSpark: Months Later, Lessons Learned
  9. DevSpark in Practice: A NuGet Package Case Study
  10. DevSpark: From Fork to Framework — What the Commits Reveal
  11. DevSpark v0.1.0: Agent-Agnostic, Multi-User, and Built for Teams
  12. DevSpark Monorepo Support: Governing Multiple Apps in One Repository
  13. Bring Your Own AI: DevSpark Unlocks Multi-Agent Collaboration
  14. Dogfooding DevSpark: Building the Plane While Flying It
  15. DevSpark: Constitution-Driven AI for Software Development
  16. The DevSpark Tiered Prompt Model: Resolving Context at Scale
  17. Workflows as First-Class Artifacts: Defining Operations for AI
  18. Closing the Loop: Automating Feedback with Suggest-Improvement
  19. Observability in AI Workflows: Exposing the Black Box
  20. Autonomy Guardrails: Bounding Agent Action Safely
  21. Designing the DevSpark CLI UX: Commands vs Prompts
  22. A Governed Contribution Model for DevSpark Prompts
  23. The Alias Layer: Masking Complexity in Agent Invocations
  24. Prompt Metadata: Enforcing the DevSpark Constitution
  25. DevSpark Blogging Workflow: How I Built Better Articles
  26. DevSpark and Agent Skills: Beyond Portable AI Capabilities
  27. The Methodology Tax: Why Grassroots Innovation Gets Rejected
  28. DevSpark's Next Evolution: Rethinking Where Knowledge Lives
  29. DevSpark v4: The Spec Was Never the Record
  30. DevSpark: Change Must Start With a Real Need

Topic cluster

DevSpark and Spec-Driven Delivery

Spec-driven development, AI-assisted delivery workflows, governance, and the DevSpark toolkit.

The Question I Had Backwards

I ended the last article with a test I didn't have a design for yet: knowledge that serves build time and runtime differently, costs less context, stays portable, and stays something a human can audit. I had the requirements document. I didn't have assimilation — the mechanism that was supposed to merge a completed spec's knowledge back into the project without letting the destination become the same kind of pile the spec itself used to be.

Working through v4, I found I'd had the mechanism backwards. I kept asking "how does assimilation extract the knowledge worth keeping," as if the spec were a source you mine and then set aside — the same posture harvest already had. The question that actually unlocked it was simpler and less comfortable: what if nothing in the spec was ever supposed to survive its own implementation? Not a decision worth preserving. Not a rationale. Nothing.

The Spec Was Never a Record

A specification isn't a document that happens to become obsolete after implementation. It's a definition of a delta — a change to the code and a change to the knowledge — and once that delta has landed in both places, the spec has done the only job it ever had. It was never a record of what happened. It was an instruction for getting from one state to the next, consumed in the getting.

That's a stronger claim than the delta framing from the last article, which still left room for the spec to linger as a reference, the way an archived spec technically still exists as evidence of intent. The v4 version has no such residue. The spec package — plan, tasks, checklists, gates — is deleted once the delta is verified in code and knowledge. Nothing references it afterward, because nothing is left to reference.

That's a bigger ask at the moment of completion than harvest ever made. Harvest could run as a sweep, decoupled from any individual spec, whenever someone remembered to run it. If the spec disappears entirely, the extraction has to happen before deletion, every time, because there's no second chance to check whether anything important got missed. Verification comes before deletion, not after. That ordering is the whole model's integrity check.

What Survives, Restated More Precisely

The last article said two things persist: the code, and something like a living knowledge model. Working through v4 forced me to split the second thing into three, because "knowledge" alone was hiding a category error.

.knowledge answers what is true now, and an agent needs it to act correctly on today's task. The Constitution answers a different question — what are the rules of the game — the part that almost never changes and governs how decisions get made rather than what any one decision was. And there's a third category I'd been folding into "documentation" without noticing it deserved its own treatment: decisions, in the ADR sense — what did we choose, and why not the alternative — which a human needs when revisiting a choice, and which an agent needs when a .knowledge constraint looks arbitrary and has to be checked against whether it's still load-bearing.

Three different questions, three different documents, one identical rule across all of them: none is an archive. All three describe current state. I'd been treating that discipline as something only .knowledge needed. It turned out to be the missing piece for governance too. An ADR isn't "here's everything we tried" — it's a present-tense claim: here's what we do, here's why we don't do the alternatives. When the reasoning changes, the ADR gets edited in place. It doesn't get superseded, and it doesn't accumulate into a chain someone has to read chronologically to find the current answer.

That also killed sequential ADR numbering. If an ADR never gets superseded and just gets corrected, a number assigned at creation stops meaning anything except trivia about when the topic first came up — exactly the kind of history the whole model is trying to keep out of the repo. Decisions get keyed by domain instead: auth-strategy.md, not ADR-0042.md.

Where Decisions Actually Live

My knowledge ontology is domain-driven — entity folders, each carrying a developer guide and a business overview, with an ontology layer that points an agent to the right entity. My instinct was to put each entity's decisions inside its own folder, next to its other current-truth documents.

I talked myself out of that fast, for a reason I recognized as soon as I said it out loud: most decisions that matter are cross-cutting. "We use REST instead of GraphQL" doesn't belong to any one entity — it constrains all of them. Filing decisions per-entity means either duplicating a cross-cutting decision everywhere it applies, or losing it inside whichever entity happened to be open when the decision got made. Neither is better than the chronological ADR chain I was trying to escape.

This is domain-driven design's oldest unresolved argument, and I don't think DevSpark escapes it so much as it gets to attack it differently than a human team can. A bounded context gives you a place for entity-local logic, but it was never going to tell you where the seams go — concerns that are true across contexts always end up either duplicated or hoisted into a shared kernel, and human teams lose track of shared-kernel dependencies because no one person reads the whole system before every change. An agent doesn't get to make that excuse. If a decision declares which entities it constrains, and an entity carries a pointer back, checking "does anything here constrain what I'm about to touch" can be a mechanical gate every time, not a discipline that degrades under load the way it does for people.

So decisions live centrally, under governance, keyed by topic. Entities stay complete and autonomous in the sense that matters — an agent working on one never needs to separately go read governance to know a constraint exists — without the entity owning or duplicating the why, which stays singular in one place.

The Evidence Problem I Didn't Know I Had

Somewhere in working this out, I added a requirement almost as an afterthought: every knowledge object and every decision has to cite evidence — something that lets a claim be checked instead of trusted. It turned out to be doing more work than I expected, because not all evidence is equally strong.

A knowledge claim backed by a test is mechanically checkable: the claim holds if and only if the test passes, no interpretation required. A claim backed only by a code reference needs a human or an agent to read the code and judge whether it still matches — slower, and the harder case I'm not willing to hand to an agent unsupervised. So I built a preference for test evidence over code evidence, and then immediately ran into my own stated aversion to dogmatic rules. I didn't want to require a test for every claim, because sometimes a test genuinely isn't practical, and a hard rule there would produce exactly the kind of noncompliance-by-workaround I've been trying to design out of this whole system.

The resolution: encourage, don't block, but make the encouragement leave a trace. A code-only evidence entry has to say whether a test was attempted and, if not, why. That doesn't stop anyone from shipping code-only evidence — it stops the reasoning from disappearing. Missing that explanation becomes a warning, surfaced independently by both the continuous audit pass and PR review at merge time, and neither one blocks anything.

It's the one place in the whole model where visibility, not enforcement, is the mechanism. Whether a claim is cheap or expensive to verify is a question of degree, not existence — and degree questions get warnings in this system. Only existence questions get gates.

The Minimum Non-Negotiable Rules

Once I had the full picture, I went looking for the smallest possible set of hard rules, on the theory that dogmatism kills compliance and I'd rather have five rules everyone actually follows than fifteen everyone routes around. A rule earned a hard gate only if breaking it falsifies the core guarantee — that the permanent record is current-truth-only, checkable, and carries no trace of the ephemeral scaffolding that produced it. Everything else is a quality question and gets a warning, not a wall.

Five survived that filter:

RuleWhat it protects
The permanent record (code, knowledge) never references a spec, task, or plan identifier, in either directionKeeps the destination free of ephemeral scaffolding
A spec can't be deleted until its delta is verified as landed in both code and knowledgeVerification happens before the only chance to check is gone
Every knowledge object and decision needs at least one piece of evidence, regardless of typeClaims stay checkable, not just asserted
Exactly one current file per decision topic, never a chainNo chronological archaeology to find the current answer
No code comment references a spec, task, or plan identifierThe sharpest instance of the first rule

The reverse direction of the first rule is actually encouraged — an ephemeral artifact pointing at the permanent record is safe by construction, since the pointer disappears when the ephemeral thing does. And the last rule is the one that started the whole exercise: I'd always been leaving those comments in, always planning to clean them up later, and finally admitted the fix was never creating them in the first place.

What Actually Triggers Assimilation

This is the piece I didn't have when I wrote the last article, and it turned out not to need a new mechanism at all — just a different question asked of prompts I already had.

DevSpark's commands group into three phases: plan-and-build (specify, plan, tasks, analyze, critic), implementation (implement), and validation (PR review, audit, harvest). I'd been thinking of validation's prompts as things that check whether a spec got implemented. The reframe was to stop asking that question entirely, because once a spec is gone, there's nothing left to check it against — asking "did this match the spec" about a document that no longer exists isn't a coherent question. The prompts that used to check spec-completion pivot instead to checking knowledge-and-code consistency, full stop, with no reference to any particular spec at all.

PR review became the obvious trigger, because nothing merges without one — it isn't a sweep someone has to remember to run, the way harvest's old sweep was. The PR diff itself, not the spec, is what proves a delta's code and knowledge changes landed together, which meant the spec didn't need to survive long enough to be checked against; the diff outlives it. Harvest's job shrank once I saw this. Its old purpose — verifying durable knowledge still matches the code — is now something pr-review and a repo-wide audit do continuously, so what's left for harvest is narrower: sweeping up abandoned in-flight work that never finished, not primary verification.

That reframe also dissolved a problem I'd been carrying without noticing it was malformed. I'd been calling it "cross-spec drift" — the idea that two unrelated specs might quietly interact and produce an inconsistency neither one would show on its own. But that concept assumes specs have enough persistent identity to have interacted, which contradicts everything else I'd just established. Once nothing tracks spec identity, there's no "spec A" and "spec B" left to have collided. What's actually checkable, stripped of that framing, is much plainer: does the knowledge currently contradict itself, and does it currently match the code — a synchronic question, not a historical one, askable at any moment regardless of how the current state was reached.

Retrieval, Which I Didn't Expect to Close This Cleanly

The original requirements document flagged retrieval as the hardest open problem: which of a hundred small knowledge objects an agent actually needs for a given task, without a similarity-search system that trades transparency for convenience and adds a second thing that can drift.

The answer came from taking my own "complexity should be worked out before we code" instinct more literally than I'd been applying it. If specify and plan already have to think hard about what a change touches, that's exactly where the expensive part of retrieval belongs — not at implement time, when speed matters more and the thinking should already be done. So the plan phase now does a real multi-hop walk of the ontology graph and writes down exactly what it found as an explicit list in the spec package. Analyze checks that everything in that list actually still resolves — a mechanical, hard-stop check, the same kind the ontology's own build tooling already runs on its internal references. Critic checks something harder and softer: whether that list looks sufficient for the change being planned, which is a judgment call, not a lookup.

Implement, then, never traverses the graph itself. It just reads what design time already resolved. If it ever needs to go further than that, the escalation is explicit and logged rather than silent — and the pattern of those escalations turns into a diagnostic I didn't have before. Frequent escalation on one specific pair of entities means the ontology's relations are too sparse and a direct edge should exist. Escalation despite a resolved list that passed analyze means critic isn't catching sufficiency gaps and needs sharpening. I like this better than a single retrieval rule for everything, because it turns "is retrieval good enough" from a vague worry into something with an actual failure signature.

Where the Pilot Already Is

None of this stayed abstract for long, because I already had a working pilot ontology to check it against — a coverage matrix generated from doc frontmatter and entity nodes, reporting which of an entity's required knowledge layers exist. Running the v4 philosophy against that pilot surfaced the gaps precisely: no slot yet for a decision as an entity type, evidence expressed as a flat list of code paths with no test/code distinction, and — the one that mattered most — a generator invoked as ordinary engineering tooling, entirely outside the DevSpark prompt lifecycle rather than wired into it.

Closing that meant deciding where decisions physically live (under governance, as markdown with frontmatter rather than the YAML node format entities use, because a decision's content is prose for a human to read), how a generated fact like "which decisions constrain this entity" gets tracked without becoming something a human has to hand-maintain and therefore lets go stale (derived into its own small sibling file, never mixed into the hand-authored entity node, with a drift check that flags — rather than silently corrects — any sign the generated file was hand-edited between runs), and which existing prompt should actually be running all of this.

That last question turned up something I hadn't expected: a command already in my prompt inventory, devspark.verify, has a stated purpose — producing empirical proof-of-change evidence, not document review — that is almost exactly the evidence-execution engine this whole design depends on. It's also the one command in the inventory missing both its shims. That's not a coincidence I'm inclined to ignore.

Where This Leaves Me

I still don't have full confidence in the one piece I think never fully mechanizes: judging whether two current knowledge claims are genuinely contradictory or just sit at different levels of nuance. I looked hard at whether a structured, comparable claims format could turn some of that into a mechanical check, and decided against adding the schema surface for it — one discipline (audit surfaces, a human disposes) beats maintaining two different contradiction-detection paths for a narrow win. That one stays a permanent warning, on purpose, not as an admission of defeat.

Everything else that felt open when I wrote the last article has an actual design now, traceable to a specific decision rather than a placeholder: what triggers assimilation, what the five things are that can never be compromised, how evidence gets weighted without being dogmatic about it, and how retrieval gets bounded without a similarity search.

What's left isn't "what should this look like" anymore. It's whether the pilot actually holds up once devspark.verify exists and the generator is wired into pr-review instead of run by hand — a much better problem to have than the one I started with.

Explore More

Working through a similar architecture decision?

If this article maps to a problem in your system, send a short note with the constraint, the risk, and what decision is blocked.