Skip to content
Back to all field notes knowledge · 9 min

Reading a repo into product artifacts: stories, criteria, decisions

Everyone teaches the forward path: spec first, then build. For software that already exists you need the reverse, and almost nobody explains it.

field note 9 min

You open a repo you did not write, or one you vibe-coded five months ago and no longer remember. There is no PRD. No user stories. No decision log. The code is the only document in the room, and it does not explain itself.

Every guide teaches the same direction. Write the spec, let the agent build. That is a good workflow for a blank folder. It is useless for the software that already exists, which is almost all software. The repo in front of you was not built from a spec, and you cannot un-build it to get one.

So you need the other direction. Read the repo into product artifacts: the stories it already delivers, the criteria it already enforces, the decisions it already froze into structure. This is the path almost nobody documents, and it is the one you reach for most.

The forward path assumes a repo that does not exist yet

Spec-driven development, at least the way it gets sold, starts before the code. You describe behaviour, an agent generates an implementation, the spec stays as the contract. Clean, when the timeline runs that way.

Existing code ran the timeline backwards. Someone made hundreds of small choices under deadline, half of them in a chat window, none of them written down. The behaviour is real and shipping. The record of why it behaves that way evaporated the moment the session closed. Ask the original author six months later and you get a shrug, because code is the only documentation that is guaranteed to be current, and it is also the least legible.

So the useful question is not “what spec would produce this code.” It is narrower and answerable. What contract is this code already enforcing, right now, whether anyone wrote it down or not?

Three artifacts hide in a repo, at three different depths

Reading a repo into artifacts is not one extraction. It is three, and they get progressively lossier.

Stories are the shallowest. The behaviour the software delivers is right there in the routes, the handlers, the UI states. A signup flow, a password reset, an export button that emails a CSV. You can read these off the surface with decent confidence, because the code runs them every day. An agent is genuinely good at this pass. Point it at the codebase, ask what a user can do, and the list it returns is mostly true.

Acceptance criteria sit one layer down, and the tests are where they live. A test is a criterion someone already agreed to, written in a language that executes. “Reset tokens expire after one hour” is not a comment, it is an assertion that fails if you break it. The test suite is the richest vein of acceptance criteria in the whole repo, because unlike documentation it cannot quietly go stale without turning red. Where there are no tests, the criteria are still there, buried in validation code and error branches, just harder to trust.

Decisions are the deepest, and the extraction gets lossy fast. Why is auth its own service? Why does this module reimplement something the framework already provides? Some of that is recoverable from git history, commit messages, the shape of the dependency graph. Much of it is gone, and an accurate artifact says so. This is where reverse extraction earns its danger.

The line between reading and inventing

The failure mode is not laziness. It is confidence. An agent asked to “document this repo” will produce a beautiful set of user stories, acceptance criteria and rationale, and a chunk of the rationale will be fabricated. Not maliciously. It fills the gap where a decision should be with a plausible-sounding reason, and the reason reads exactly like the ones that are real.

That is worse than an empty doc, because a confident wrong “why” gets treated as ground truth by the next person and the next agent. A folder named legacy becomes “the team decided to deprecate this,” when actually someone just moved a file once and never came back.

The discipline is provenance. Every extracted artifact carries a tag. Behaviour observed from a passing test is proven. Behaviour read off a route is observed. A decision guessed from structure is inferred. You keep the three apart and you never let inferred quietly promote itself to proven.

This is the same rule that keeps a reverse-read product knowledge graph true instead of turning into a confident hallucination over messy code.

How I actually run the pass

Not “summarize the repo.” That gives you prose. You want artifacts you can build against.

Start with the tests, because they are the highest-signal source and the least likely to lie. Every assertion is a candidate acceptance criterion with evidence attached. Read them into criteria first, before you touch a line of implementation.

Then read the surface: routes, handlers, entry points, UI states. These become stories. Keep them at the level of user-visible behaviour, not implementation. “A user can export their data,” not “the export controller calls the serializer.”

Then, and only then, go for decisions, and treat git history as the primary witness. Commit messages, the order things were built, what got reverted. Anything you cannot source, you either mark inferred or you leave out. The gap is data too. A story with no test underneath it is telling you exactly where the software is unproven.

The output is not a document you read once. It is a set of artifacts an agent can build against tomorrow without re-deriving the whole contract from scratch, which is the same problem a product brain that maintains itself is trying to solve upstream.

The gaps are half the value

The artifacts you can extract are useful. The ones you cannot are more useful, because a gap is a signal with a location.

A route with no test underneath it is behaviour running in production that nobody agreed to verify. Extraction finds it and puts a flag on it. A cluster of code no story reaches is either dead weight or a feature so undocumented that removing it is a gamble. A decision you could not source, only infer, marks a place where the next change is being made blind.

When I ran this pass on an old prototype of mine, the most valuable output was not the tidy list of stories. It was the short list of endpoints the intake could describe but could not connect to any reason for existing. Two were leftovers from an idea I abandoned and forgot to delete. One was load-bearing and I had genuinely forgotten it was there. A forward spec would never have surfaced that, because a forward spec only knows what you remembered to write.

Where PaellaDoc fits

This reverse pass is what PaellaDoc calls intake. It reads an existing repo and its history into stories, acceptance criteria and decisions, each one tagged with where it came from, and holds them as a living contract on your machine instead of a one-off summary in a chat you will lose. The point is not a prettier export. It is that the next agent, and the next you, starts from what the code actually enforces instead of guessing again.

It runs local-first and free, no cloud and no account, against the repo you already have.

↓ Download PaellaDoc · macOS

Which of your repos has real behaviour and zero written record of why? Tell me on the forum.

Frequently asked questions

What product artifacts can you extract from an existing repo?

The behaviour the code enforces (user stories), the conditions it checks (acceptance criteria, richest when there are tests), and some of the decisions frozen into structure. What you cannot fully recover is intent: why a choice was made, what was rejected, and what the code does by accident rather than on purpose.

Why read a repo into artifacts instead of writing specs forward?

Because most software already exists. The forward path (spec, then build) fits greenfield. Inherited code, vibe-coded prototypes and legacy systems have no spec at all, and the fastest way to get a contract you can build against is to read the one the code is already enforcing.

Can you trust artifacts reverse-extracted from code?

Only if each one carries its provenance. Behaviour read from a passing test is evidence. A decision inferred from a folder name is a guess. Extraction is dangerous when it launders guesses into confident documentation, so the artifacts must mark what is proven, what is observed and what is inferred, and keep them apart.