Back to blog
Doors

The intent door: from a one-line idea to shipped, linked code

Browse the spec funnel, author or fast-path a requirement, implement it in an isolated worktree, review it against a rubric, triage a bug to the spec it belongs to, or capture a domain fact — all behind one door. Intent becomes a first-class artifact, and the spec is the contract.

funnelnew · fastimplement reviewtriagebehaviour · domain

Most tools treat what you want as ephemeral — a sentence in a chat that scrolls away the moment the code lands. The requirement lived in your head, briefly in the prompt, and then only in the diff, where the “why” is already lost. SpecShip treats intent as a durable, addressable artifact: a spec, with edges to the exact code that satisfies it. The intent door is where that artifact is born, grows, gets built, and stays honest.

/specship:spec is one door over the whole lifecycle. It routes on the first word of what you type, so a single command covers browsing, authoring, implementing, reviewing, triaging, testing, and capturing domain knowledge.

The funnel behind the door

Open it with no argument and you get the spec lifecycle funnel: brainstormed ideas → written specs → implemented-and-linked requirements, with a rollup per document. It's the one screen that answers “where does intent stand in this repo?” — what's been captured, what's been built, what's still just an idea. Under the hood that's specship_spec called with no ID; it reads the spec layer of the graph directly.

Hand it a specific ID (/specship:spec REQ-AUTH-005) and it opens that spec: the requirement body, its parent document and sibling requirements, and — the part a plain file can't give you — the code it links to, with each link's state: verified, drifted, orphaned. You read the intent and its real implementation side by side, before touching a file.

Authoring, at two speeds

A requirement enters the graph one of two ways, and the door offers both because the right one depends on how settled the design is.

new
the gated authoring loop — scope, ground in the actual code, diverge on 2–3 approaches, gap-fill the questions the graph can’t answer, then write. For when the design isn’t settled.
fast
the fast-path — ground briefly, pick sensible defaults, and write a clean, well-formed spec without the interview. For a solo dev who wants to record intent and move.

Both produce the same thing: a spec that indexes cleanly, carries RFC-2119 keywords and independently-checkable acceptance criteria, and is ready to implement. fast trades the interview for speed, not correctness.

Implement — plan, gate, build, link

/specship:spec implement REQ-X runs the bundled spec-implement workflow in an isolated git worktree: it fetches the spec, writes a concrete plan, pauses at an approval gate, implements, verifies, and links the resulting code back to the spec. The isolation means a failed run never touches your working tree; the gate means a non-coding spec author can review the plan before any code is written.

The link is the contract closing. After editing code for a spec, the door calls specship_link_assert — declaring “this symbol implements REQ-X.” That edge is what later lets drift detection notice when the code moves out from under the requirement. A spec’s implementations: block is the backstop: it re-asserts the link on every index even if the agent forgets.

Review, triage, behaviour, domain

The same door carries the rest of the loop, each as a first-word sub-action:

  • review — a read-only rubric pass over a spec: are the embedded IDs and frontmatter valid, are the acceptance criteria testable, is there exactly one concern per requirement, does any implementations: path actually exist? It reports findings and changes nothing.
  • triage — you paste a bug, an error log, or a one-line enhancement, and it finds the existing spec it belongs to (an error's file:line resolves through the graph to the owning requirement). Then it previews the exact diff — a new acceptance criterion for a regression, a new requirement for a new concern — and only writes on your confirmation.
  • behaviour — turns a requirement's acceptance criteria into real end-to-end tests (Playwright when there's a UI, a backend test otherwise), links them at the .A<n> criterion, runs them, and reports each result through specship_link_verify so a passing test moves the link to verified.
  • domain — captures a human-confirmed domain fact (a term, a rule, a decision, a constraint) and links it to the specs and code it governs, so the “why” lives next to the “what.”

A chat message says what you want once. A spec says it durably, points at the code that satisfies it, and files a review the day that code quietly changes.

Why one door for all of it

Because it's all the same object at different stages of its life. A funnel view, a spec you're reading, a draft you're authoring, a requirement you're building, a bug you're routing back to its source — every one of those is a spec node and its edges to code. Splitting them into seven commands would make you remember which verb lives where; folding them into the intent door means you name the stage and step through.

The payoff is traceability that survives the session. Long after the diff merges and the chat is gone, the requirement is still in the graph, still pointing at its code — and the moment someone renames that code, the link goes to drifted and lands in a queue. That queue is the next door.

#doors#specs#workflows#requirements
SE
Selva E.
Building SpecShip · graph, specs & harness
Works on the parsing, storage, and spec layers of SpecShip. Spends an unreasonable amount of time thinking about edges.