Scriptonia/blog
DocsGet Scriptonia
← All posts
FORMAT2026-07-03 · 5 min read

PLAN.md: a spec format coding agents can actually execute

PLAN.md is a one-page markdown spec with YAML frontmatter and seven fixed sections — Goal, Evidence, Constraints, Non-goals, Acceptance criteria, Implementation steps, Test plan. It works because agents execute fenced, cited, self-contained instructions far more faithfully than prose briefs.

Agents don't fail specs randomly. They fail them in three predictable ways: they over-build past the ask, they guess at unstated defaults, and they silently override decisions they were never told about. PLAN.md is a format designed against those three failure modes — one page, seven sections, nothing optional.

The format

PLAN.md
---
plan: filter-audit-log-by-actor
version: 2
issue: "filter the audit log by actor"
sources: [d4c0c394, f1d0347b, 256c4967]
decisions_checked: [2026-04-roadmap]
---
 
## Goal
## Why now — customer evidence ← every bullet cites a signal id
## Constraints & prior decisions ← ⚠ UNRESOLVED until a human approves
## Non-goals — do NOT build ← the fence
## Acceptance criteria ← testable, numbered
## Implementation steps ← real file paths from a repo scan
## Test plan

Why Non-goals is the most important section

An agent with room to impress you will use it. “Add actor filtering” becomes a filter system — dates, actions, resources, saved views. Each extra is individually defensible and collectively wrong: more review surface, more risk, less of what the customer asked for. A plan that says “Do not build date-range, action-type, or resource filters” converts scope from a vibe into an instruction. In our testing this single section eliminates most re-review cycles.

Why citations belong in a spec

[d4c0c394] after a requirement means any reviewer — or the agent itself — can resolve the claim to the exact sales-call sentence it came from (scriptonia link d4c0c394). Specs stop being trust-me documents. Disagreements become “read the source,” not “I remember it differently.”

Why UNRESOLVED gates beat silent overrides

When an issue conflicts with a recorded decision, the plan doesn't pick a winner. It prints the conflict, marks it ⚠ UNRESOLVED, and instructs the agent to stop. A human clears it with one comment; the plan regenerates as v2 with the gate marked RESOLVED (human-approved override) and the approval recorded. That's the difference between an agent that respects your roadmap and one that rewrites it.

Frequently asked questions

Why markdown instead of an issue tracker ticket?

A file in the repo is in the agent's working directory, versionable, diffable, and readable by every agent without an integration. Tickets describe work; PLAN.md is executed as work.

What's in the frontmatter?

plan slug, version, the originating issue, project, source signal ids, and which decisions were checked — machine-readable provenance for the PR and for audits.

Can I write PLAN.md by hand?

Yes — the format is just markdown. The value of generating it is retrieval (signal you forgot existed) and the contradiction check (decisions you forgot you made).

Try the loop on your own repo

One command, free tier, sample data included. Issue in, PLAN.md out.

npx scriptonia login