The short answer: spec-driven development (SDD) means you write down what the system should do, including the acceptance criteria, before the coding agent writes a single line. The agent then implements against that document, and you check the result against the document rather than against your memory of what you meant.
The honest answer: it works, and it fails, in ways you can predict in advance. On one ten day build of an enterprise admin console it produced 25,546 net lines through 2,754 tool calls with a reported 36% speed gain. On the same project, a single CI only build failure ate 4 hours, 7 sessions, 15+ attempted fixes and 59 instructions, because the failure lived in the CI environment and the agent could not see it.
The method is not the variable. Whether the machine you run it on is reproducible is the variable.
Four documents, in this order. Everything else is tooling detail.
Two habits separate teams that get value from this and teams that generate paperwork. First, keep the three documents out of the chat window. A new session is a new context, so anything agreed in chat is gone; anything in a file survives. Second, commit immediately and often. The rollback ladder is short and worth memorising:
git restore . # changes not staged yet
git restore --staged . # staged but not committed, then run the line above
git reset --hard HEAD^ # already committed, back up one commit
One team that ran this for ten days recorded 738 file reads, 550 code edits, 662 terminal commands and 208 progress markers across that period, and kept 205 files consistent in naming purely because the convention lived in a rules file instead of in someone's head.
Roughly two thirds of the time lost to spec-driven tooling is lost here, before any spec is written. These are the failures people hit, in the order they hit them.
npm writes a .ps1 shim next to the executable. PowerShell refuses to run it under the
default policy, and the error looks like the install failed:
openspec-cn : 无法加载文件 C:\Users\evan\AppData\Roaming\npm\openspec-cn.ps1,因为在此系统上禁止运行脚本。
有关详细信息,请参阅 https://go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
所在位置 行:1 字符:1
+ openspec-cn init
+ ~~~~~~~~~~~
+ CategoryInfo : SecurityError: (:) [], PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
The fix is scoped to your user, needs no admin rights, and is one line:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force
openspec-cn --version
If that prints 1.4.1, the shim problem is gone. If Get-ExecutionPolicy -List
shows MachinePolicy Restricted, group policy outranks you: call the
.cmd shim from cmd.exe, run from Git Bash, or invoke the entry point through
npx or node.
The first error is a Windows problem. The second one is not, and mixing them up is what makes people think the fix above did not work:
错误:未检测到工具且未提供 --tools 参数。有效工具:
amazon-q
antigravity
auggie
bob
claude
cline
codex
...
请使用 --tools all、--tools none 或 --tools claude,cursor,...
The tool will not guess which coding agent to generate slash commands for. Name it:
openspec-cn init --tools codex
正在创建 OpenSpec 结构...
OpenSpec 结构已创建
OpenSpec 设置完成
已创建:Codex
5 个技能和 5 个命令在 .codex/ 中
配置:已跳过 (非交互模式)
开始使用:
开始您的第一个变更:/opsx:propose "您的想法"
重启您的 IDE 以使斜杠命令生效。
That last line is the one people miss. The commands were written to disk correctly and your editor has not reloaded them, so the slash commands appear to be missing until you restart it.
This one presents as a pnpm problem and is not one. The tell is that an unrelated system command has also stopped working:
ERR_PNPM_NO_GLOBAL_BIN_DIR
Unable to find the global bin directory
Command failed with exit code 1: chcp
chcp lives in C:\Windows\system32. If pnpm cannot find it, that directory has
fallen out of the system Path, which is why ping is dead too. Repair in this order:
C:\Windows\system32, C:\Windows and
C:\Windows\System32\Wbem back to the system Path.PNPM_HOME with the value
C:\Users\<your name>\AppData\Local\pnpm, then add %PNPM_HOME% to the
user Path.chcp. If it returns
活动代码页: 936, the environment is back.Then reinstall. If the download itself dies with ERR_BAD_REQUEST, that is your proxy, not
the package.
This is the failure that spec-driven development does not protect you from, and it is worth understanding why. Each verification round required pushing code and waiting about ten minutes for CI, and the agent was analysing log screenshots rather than the live environment. Every single analysis was correct. Each one was correct about a different layer, because fixing one layer exposed the next.
Three causes were stacked:
omit=optional in .npmrc. It was added earlier to stop
@next/swc-darwin-arm64 from downloading on Linux. It also skipped
@tailwindcss/oxide-linux-x64-gnu, the Tailwind v4 native binding, so postinstall waited
for something that would never arrive.node_modules/@prisma/fetch-engine/dist/index.js line 2319.The fix that finally held, after 15+ attempts:
pin tailwindcss@4.1.11
PRISMA_ENGINES_MIRROR=https://registry.npmmirror.com/-/binary/prisma
standardise on pnpm, update the CI commands to match
delete omit=optional from .npmrc
Nothing about that fix is a specification problem. It is a reproducibility problem, and no amount of spec quality will compensate for it.
Everything above, plus the cases that did not fit in prose, in one table. Symptom, the exact text, the environment, the cause, the fix, and when it was first written up.
The file itself lives at
https://openspec-mvp.pages.dev/sdd-failure-matrix.csv
(4.2 KB, 10 rows plus a header, served as text/csv). It opens in Excel, Numbers or any text
editor. The print button strips the navigation and prints the tables and code blocks cleanly.
| Symptom | Environment | Cause | Fix | Written up |
|---|---|---|---|---|
| Installed, but every run dies at startup | Windows 11, PowerShell, npm global | .ps1 shim blocked by execution policy |
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force |
2026-06-27 |
| Init stops and lists agent names | openspec-cn 1.4.1 | target agent not specified | openspec-cn init --tools codex |
2026-06-27 |
| Slash commands missing after init | any editor, non-interactive init | editor has not reloaded the new config | restart the IDE | 2026-06-27 |
Global install fails, ping also dead |
Windows, pnpm | system32 missing from system Path |
restore three Path entries, set PNPM_HOME, verify with chcp |
2026-03-16 |
| Download dies midway | behind a proxy | proxy rejects the registry request | fix the proxy configuration | 2026-03-16 |
| Green locally, red on CI, no error at all | cloud CI runner | omit=optional plus Prisma v6 engine fetch plus cross platform lockfile |
pin tailwindcss@4.1.11, set PRISMA_ENGINES_MIRROR, one package manager,
drop omit=optional |
2026-03-12 |
| Code runs but ignores house style | TypeScript admin console | rules say what not to do, no reference implementation | add a worked-example layer beside the rules layer | 2026-03-12 |
| Agent picks a deprecated API | antd v5 | model defaults to the most common API in training data | list the deprecations in the rules file | 2026-03-12 |
| Terminal shows mojibake | Windows PowerShell | console code page mismatch, file is fine | Get-Content .\log.md -Raw -Encoding UTF8 |
2026-06-27 |
| Execution policy will not change | domain joined Windows | group policy outranks the user scope | use the .cmd shim, another shell, or npx |
2026-06-27 |
Every figure below is claimed by a specific write-up on a specific date. None of them is a benchmark, and none of them transfers automatically to your project. Read them as one team's logbook.
| Date | Source | What they claimed |
|---|---|---|
| 2026-03-12 | Post-mortem of a ten day, from scratch build of an enterprise admin console, run with an agent under a three layer rules setup | 25,546 net lines added; 2,754 tool calls; 738 reads, 550 edits, 662 terminal commands, 208 progress markers; reported 36% gain. Phase split: 2 days and 20 instructions to scaffold, 4 days and 89 instructions once the spec workflow was introduced, 4 days and 108 instructions for hardening and deploy. Naming held across 205 files. |
| 2026-03-12 | Same post-mortem, troubleshooting section | One CI only build failure: 4 hours, 7 sessions, 15+ attempted fixes, 59 instructions, about ten
minutes per verification round. Root causes: omit=optional, Prisma v6 silent engine
download, macOS arm64 lockfile on a Linux x64 runner. Fix: pin tailwindcss@4.1.11, set
PRISMA_ENGINES_MIRROR, standardise on pnpm, remove omit=optional. |
| 2026-03-12 | Same post-mortem, refactor case | 9 groups and 34 subtasks ran to completion with under 5 human instructions. A hook exporting 20+ methods was split into three single purpose hooks, and a component taking 17 props came down to 6 to 8. |
| 2026-03-16 | Windows setup write-up for the same tooling | Two blockers on Windows: the PowerShell script policy, and
ERR_PNPM_NO_GLOBAL_BIN_DIR caused by system32 leaving the Path. Verify with
chcp returning 活动代码页: 936. |
| 2026-05-16 | Walkthrough running the workflow on Windows against a non default model | Floor is Node.js 20.19.0. Model configured through ANTHROPIC_BASE_URL with
API_TIMEOUT_MS set to 300000. Recommends stepping through
/opsx:new then /opsx:continue instead of generating all artifacts in one
shot, so each one can be reviewed. |
| 2026-06-27 | Windows 11 troubleshooting post for the Chinese language build | openspec-cn --version reported 1.4.1. Two errors in sequence:
PSSecurityException then "no tool detected, pass --tools". Successful init
wrote 5 skills and 5 commands into .codex/. |
This is the part most write-ups leave out. Spec-driven development has a real setup cost, and below a certain change size that cost is larger than the thing you are changing.
Specs rot faster than code, because code fails loudly and a stale spec fails silently. The failure mode to
watch is this: the spec says errors return {"code": "USER_NOT_FOUND", "message": "..."}, two
weeks later the spec adds trace_id, and the module written in week one is never updated. Nothing
breaks. The next agent reads the new spec and writes code that disagrees with the old module.
The cheap defence is mechanical rather than disciplined: keep a list of dependent modules in each spec file, and add one CI step that runs the tests of any module whose spec file changed. If you cannot do that, at least make the spec the thing the agent reads at the start of every session, which is what makes it worth maintaining at all.
If you want the short version of the whole method: write the four documents, keep them in git next to the code, pin your dependencies, and treat any build that passes locally and fails on the server as an environment bug until proven otherwise.