* test(#3242): failing-first suite for the codex posture health-check Specifies ADR-2313 D6 before the implementation exists, so the tests bind to the contract rather than to whatever the code happens to do. RED is established by construction, not by a remote run: checkCodexModelPosture and POSTURE_REASON are absent from the compiled lib today, so every row fails on the missing export. A remote checkpoint here would prove only that the function is missing, which is already known — so the run is deliberately deferred to the combined green checkpoint rather than spent proving a tautology. That makes the NEGATIVE PROOFS the rows that carry real signal. Every positive row passes even for a naive implementation that greps /model\s*=/ over the whole file. Six rows fail it: light-tier service_tier/model_verbosity decoupling (#774), hand-added keys, a commented pin, the model_verbosity key-prefix collision, the runtime no-op ordering, and the headline case — a literal `model = "sonnet"` inside the developer_instructions ''' block, which the emitter fills with agent prompts that discuss models constantly. Row 14's fixture was verified to discriminate before being written: a whole-file scan matches it and a header-slice scan does not. Without that check the test would pass trivially and prove nothing, which is the vacuous-test failure this epic has already hit repeatedly. Adversarial TOML fixtures are hand-authored against the real Codex shape rather than generated by generateCodexAgentToml, per #2371 — a fixture from the writer can only confirm what the writer already believed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(#3242): validate codex .toml model posture, not just presence Implements ADR-2313 D6. checkCodexModelPosture is a new sibling export, not a branch inside checkAgentsInstalled — that function carries 33 upstream dependents, cyclomatic 25, and sits in two traced process flows, so it is deliberately left untouched. It imports isAnthropicFlavoredModel from model-catalog, a genuine leaf. That is what Phase 1's constant move bought: agent-install-check is documented as pure read/verify and imports only leaves, so reaching the rule through model-resolver would have dragged config-loader into it. Reads liberally, judges strictly, and never guesses. Tolerates comments, key order, whitespace, CRLF, and a BOM; anchors on full key names so model_verbosity does not satisfy a `model` probe; treats extra hand-added keys as none of its business, since the check is a predicate on the two fields the posture owns rather than a whitelist over the document. An unreadable file becomes a named violation and the loop keeps going. The scan covers only the header slice — the lines before the developer_instructions ''' marker. The emitter writes agent prompts into that block and GSD's prompts discuss models constantly, so a whole-file scan reports violations for prose. This is the highest-risk defect in the phase and the reason its fixture was verified to discriminate before being written. The non-codex short-circuit runs before any filesystem call, so a stray .toml under another runtime is never inspected. Wired through cmdValidateAgents as an additive codex_posture key, so a violating install is visible from a command a user actually runs rather than only from a library nothing calls. Also fixes a test defect found while implementing: .gitattributes forces `* text=auto eol=lf` repo-wide, so the committed CRLF fixture was normalized to LF in the index — `git ls-files --eol` reported `i/lf w/crlf`, the working copy being stale pre-normalization bytes. The CRLF row was asserting against a file that could not survive a fresh clone. CRLF is now derived at runtime, which puts it under the test's control rather than git's, instead of adding a .gitattributes exception that fights a deliberate repo-wide policy and that anyone could re-normalize. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(#3242): document the codex posture check where a user will look Three quadrants, filed by where the reader actually arrives. How-to (recover-and-troubleshoot.md, under Install and update problems) is titled by the SYMPTOM — "If Codex agents fail to spawn with a 400 about an unsupported model" — and opens with the verbatim error string. Someone hitting this does not know the words "posture" or "ADR-2313"; they have a 400 in their terminal and will search for that. Reference (COMMANDS.md) had no `validate agents` entry at all, though sibling gsd-tools subcommands are documented. Adding user-visible output to an undocumented command and then linking to it from the new how-to would have left a dangling reference. The entry carries the violation-reason table, since the frozen POSTURE_REASON enum is the machine-readable contract a reader needs rather than the prose. Both surfaces state that presence and posture are separate verdicts — a missing agent lands in `missing`, never as a posture violation. That is a deliberate design decision and would otherwise be invisible to someone watching one command emit both. Explanation stays in ADR-2313, which already covers D6 and the liberal-parse/strict-judge boundary. Pointing at it beats duplicating it into COMMANDS.md and creating two copies to drift. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(#3242): close two false negatives in the posture scan Both found by an isolated reviewer and reproduced before fixing. Both made the check report clean when it was not — the worst direction for this function, since the how-to tells users an empty violations list means the install is posture-clean. A quoted TOML key was never matched. `"model" = "sonnet"` is legal TOML, but the key pattern required a bare identifier, so the pin was silently invisible. Bare, "double" and 'single' quoted forms now normalize to the same key name. The block marker was found by unanchored whole-content search and used to truncate the header. A `description` value merely containing the literal text `developer_instructions = '''` truncated the scan before a real pin, and a user who hand-reordered `model` to sit after the block — still legal TOML — was never scanned at all. Fixed by changing the strategy rather than the regex: find the block's range, anchored at line start, and scan every line OUTSIDE it. That covers both failures and is strictly more correct than truncation, while still never reading prompt prose. An unterminated block excludes the rest of the file, which fails toward a false positive — the safe direction, since misreading prose as a pin wastes a user's time while the alternative hides a real one. Also corrects two overclaims of mine. The how-to named "v1.11", a version that does not exist — package.json is 1.10.0 and unreleased — so it now describes the boundary by behavior and links the ADR. And the test matrix asserted that a naive whole-file scan "fails exactly rows 12,13,14,15,16,25"; the reviewer computed that rows 12, 13, 15 and 16 produce the correct result against that baseline too. They guard real but *different* mistakes, and the matrix now says which one each catches instead of attributing them all to the header-slice defect. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(#3242): skip symlinked agent files instead of following them Security review finding. The scan listed entries with readdirSync and read them with readFileSync, which follows symlinks — so a symlink in the agents directory pointing anywhere would have its contents read, and any line matching the model pattern echoed into cmdValidateAgents' output through the `value` field. A read-and-echo primitive on an arbitrary path. It needs write access to the agents directory, so it crosses no new trust boundary today. Fixed anyway, for two reasons. This repo already does it correctly next door: cmdEffortSync filters with lstatSync().isFile() and the comment "Skip symlinks — only write regular files to avoid clobbering symlink targets." Being inconsistent with a sibling in the same subsystem IS the defect. And Phase 3 (#3243) extends that same cmdEffortSync to WRITE these files. Establishing symlink-following as the house pattern for Codex .toml handling here would hand Phase 3 a worse starting point while it writes rather than reads. Skipped silently rather than reported, matching the sibling: a symlinked agent file is a structural install choice, which checkAgentsInstalled owns, not a model-content posture defect. An lstat that itself throws excludes the file rather than crashing the scan. That does narrow the guarantee slightly, so the how-to now says an empty list means every REGULAR .toml is clean, and tells anyone symlinking their configs to check the targets by hand. Claiming a clean bill of health over files the check declined to open would be the same kind of false confidence the two false negatives above produced. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore(#3242): backfill changeset pr number (#3290) --------- Co-authored-by: sim <sim@local> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
GSD Core
Git. Ship. Done.
English · Português · 简体中文 · 日本語 · 한국어
A light-weight meta-prompting, context engineering, and spec-driven development system for Claude Code, OpenCode, Antigravity CLI, Kimi CLI, Kilo, Codex, Copilot, Cursor, Windsurf, and more.
What is GSD Core
GSD Core is a context-engineering and spec-driven development framework that drives AI coding agents (Claude Code, Codex, Antigravity CLI, Kimi CLI, Copilot, Cursor, and more) through a disciplined phase loop. It solves context rot — the quality degradation that accumulates as an AI fills its context window — by running all heavy research, planning, and execution work in fresh-context subagents while keeping your main session lean.
How it works
Each milestone repeats the same five-step loop, one phase at a time:
- Discuss — capture implementation decisions before anything is planned
- Plan — research, decompose, and verify the plan fits a fresh context window
- Execute — run plans in parallel waves; each executor starts with a clean 200k-token context
- Verify — walk through what was built; diagnose and fix before declaring done
- Ship — create the PR, archive the phase, repeat for the next one
Quickstart
npx @opengsd/gsd-core@latest
The installer prompts for your runtime (Claude Code, OpenCode, Antigravity CLI, Kimi CLI, Kilo, Codex, Copilot, Cursor, Windsurf, and more) and whether to install globally or locally. The installer is required for cross-runtime compatibility — do not copy files from agents/ or commands/ directly.
On another runtime or without Node.js? See Install on your runtime.
Once installed, start a new project or onboard an existing repo:
/gsd-new-project # greenfield project
/gsd-onboard # existing codebase
New here? Follow Your first project for a guided walkthrough from install to first shipped phase, or Onboarding an existing codebase for brownfield setup.
Documentation
What's new in 1.7.0 → docs/whats-new-1.7.0.md
Tutorials — learning by doing:
How-to guides — task-focused recipes:
Reference — authoritative facts:
Explanation — concepts and design decisions:
Full index: docs/README.md. Other languages: 日本語 · 한국어 · Português · 简体中文.
Why it works
Most AI-coding setups fail at scale because context bloat silently degrades output quality, there is no shared memory between sessions, and nothing verifies that code actually works. GSD Core solves all three: heavy work runs in fresh subagents, structured artifacts like STATE.md and CONTEXT.md survive session boundaries, and the verify step walks through what was built and generates fix plans before a phase is declared done. See docs/explanation/context-engineering.md for the full reasoning.
Troubleshooting? See docs/how-to/recover-and-troubleshoot.md.
Community
| Project | Platform |
|---|---|
| gsd-opencode | Original OpenCode port |
| Discord | Community support |
Star History
License
MIT License. See LICENSE for details.
Claude Code is powerful. GSD Core makes it reliable.