How OpenSpec’s Three‑Stage Workflow Cuts Code Rework to Below One‑Third
The article explains OpenSpec’s three‑stage workflow—Propose, Apply, Archive—driven by AI agents, showing how its strict state machine, 50 KB context limit, and structured specs (proposal.md, specs/, design.md, tasks.md) reduce code rework to under one‑third compared with traditional documentation and tools like SpecKit.
OpenSpec (Specification‑Driven Development) differs from traditional documentation by targeting AI agents rather than humans; its structure lets models reference and verify against the spec throughout a session.
Why choose OpenSpec
The author evaluated two open‑source options: GitHub’s SpecKit and Fission‑AI’s OpenSpec. SpecKit offers a constitution model that embeds cross‑domain rules (TDD requirements, coding standards, compliance constraints) into each feature workflow, which is useful for regulated environments. OpenSpec, by contrast, works out‑of‑the‑box with over 25 AI tools, requires no pre‑written constitution, and imposes a hard 50 KB context limit on each spec—a design choice explained later.
The author uses Claude Code and occasionally Cursor, making OpenSpec a better fit; however, for strict regulatory needs (e.g., “every API endpoint must have an OpenAPI document”), SpecKit’s constitution may be preferable. The choice is a trade‑off, not a right‑or‑wrong decision.
Three‑stage workflow
OpenSpec enforces a strict state machine with three non‑optional stages: Propose, Apply, and Archive.
Stage 1: Propose
The starting point is an intent, not code. The agent reads the existing openspec/specs/ directory (the current system source) and creates a new folder openspec/changes/add-rate-limiting/ containing four files:
proposal.md – a structured document describing the problem, the changes (marked ADDED, MODIFIED, REMOVED), invariants, key risks and dependencies.
specs/ – behavior scenarios written in GIVEN/WHEN/THEN format, usable directly as test cases.
design.md – technical solution, libraries, patterns, architectural decisions.
tasks.md – a checklist of small, independently reviewable implementation items.
All of these must be reviewed and approved before any implementation begins; issues are caught early rather than after code is written.
The ADDED/MODIFIED/REMOVED markers force both the spec author and the AI to state explicitly what exists now and what will exist, exposing potential technical debt before it accumulates.
Stage 2: Apply
After the proposal is approved, the author runs /opsx:apply. The AI processes each task in tasks.md, reading the spec files for guidance instead of relying on memory or a prompt. Because each task is small, failures can be traced to a specific scenario, providing a tight feedback loop.
When Apply finishes, the author runs /opsx:verify. This step does not merely run tests; it checks the implementation against the GIVEN/WHEN/THEN scenarios, reporting exactly which scenario is unmet.
In the author’s experience, verification on about thirty features uncovered problems in roughly one‑third of them, typically missing error states or uncovered edge cases. Catching these before merge is the primary value of the framework.
Stage 3: Archive
Running /opsx:archive moves the change folder to openspec/changes/archive/ and merges the incremental spec into openspec/specs/, which becomes the single source of truth for the whole project.
Unlike SpecKit, which maintains separate spec files indefinitely, OpenSpec consolidates everything into a live document that always reflects the current system state. At any time, reading openspec/specs/ gives a complete understanding of the system without piecing together dozens of feature files, and the AI reads this document at the start of every new proposal.
50 KB context limit: a feature, not a flaw
Modern LLMs can handle windows of a million tokens, tempting users to dump all specs, code, and history into the context. However, a larger context does not equal a focused one; the model may prioritize irrelevant sections.
OpenSpec’s 50 KB limit forces authors to be disciplined about what to include, ensuring the agent receives only the information needed to implement the feature. This constraint also yields better‑written specs—concise, targeted, and brief enough to serve as a “briefing” rather than an information dump.
For teams running multiple agents in parallel, the limit prevents agents from competing for context budget, addressing a practical operations concern at scale.
Real‑world example: rate‑limiting feature
The author shows a trimmed proposal.md for adding a rate‑limiting middleware to all /api/v1/* routes, including added and modified items, a Redis‑backed counter, and a risk description about Redis failure.
## What is changing
ADDED: Rate limiting middleware on all /api/v1/* routes
MODIFIED: Express app configuration to mount rate limiter before routes
ADDED: Redis‑backed rate limit counter (per API key, per 15‑minute window)
## What is NOT changing
Authentication flow, response format, existing error codes.
## Risk
Redis dependency — if Redis is unavailable, the middleware must fail open
(allow requests) not fail closed (block all traffic).The corresponding specs/rate-limiting.md defines two scenarios in GIVEN/WHEN/THEN form, one for normal throttling and one for Redis failure (fail‑open behavior). The fail‑open scenario was added during spec review, not by the AI’s first draft, illustrating how the review step forces consideration of edge cases.
GIVEN a valid API key making requests
WHEN the key exceeds 100 requests per 15‑minute window
THEN the API returns 429 with a Retry‑After header
GIVEN Redis is unavailable
WHEN a request arrives at the rate limiter
THEN the request proceeds as normal (fail‑open behaviour)This example shows that a good spec pushes the developer (and the AI) to think about the whole system, resulting in graceful handling of Redis outages.
What makes a good spec
After writing dozens of specs, the author distilled several criteria:
Describe behavior, not implementation. “User must receive a notification within 30 seconds” is a good spec; “Use WebSocket to push the notification” belongs in design.md.
Explicitly state boundary cases. The value of a spec lies in handling failures, duplicate calls, empty inputs, etc.
Keep each scenario atomic: one GIVEN/WHEN/THEN per scenario, no nested conditions. Complex logic should be split into multiple scenarios.
Write in plain language understandable by non‑technical stakeholders. If a scenario needs three paragraphs of background, it is too complex.
Summary
The article demonstrates how OpenSpec can be applied within a single repository using one AI agent and three mandatory stages—proposal, verification, and archiving—to reduce code rework to below one‑third. The 50 KB context limit drives concise, focused specs, and the strict workflow ensures that intent is clarified before implementation, the AI follows the spec at every step, and verification cross‑checks the final code against the original scenarios.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
DeepHub IMBA
A must‑follow public account sharing practical AI insights. Follow now. internet + machine learning + big data + architecture = IMBA
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
