Tom Boucher c547e73a71 fix(#2927): merge installed overlay reviewer lanes into review-lane invocation (#3062)
* test(#2927): prove overlay reviewer lanes are invisible to review-lane

Failing-first regression for #2927. routeReviewLane builds its lane map from
the static REVIEWER_LANES array only, so an installed overlay reviewer lane
(role:"reviewer" capability) is roster-visible and disclosed at install but
never selectable, plannable, or invocable. The test exercises a pure
mergeReviewerLanes(firstParty, registry) helper that does not exist yet, so
every row fails at the require().

* fix(#2927): merge installed overlay reviewer lanes into review-lane invocation

routeReviewLane built its lane map exclusively from the frozen first-party
REVIEWER_LANES array, so an installed, consented third-party reviewer lane
(role:"reviewer" capability) was roster-visible and disclosed at install but
never selectable, plannable, or invocable — sections/flags/plan/invoke all
shared the one static map.

Add a pure, total mergeReviewerLanes(firstParty, registry) helper
(src/review-lane-descriptor.cts) implementing ADR-2782 D8: first-party ∪
installed overlay reviewer bodies, first-party winning on slug collision. The
overlay body is field-identical to ReviewerLane per ADR-2782 D1 ("no
translation layer"), so the helper MERGES rather than PROJECTS. Malformed
overlays (missing/non-object body, empty or grammar-invalid slug) are skipped,
never thrown — one bad third-party manifest cannot take the first-party lanes
down. routeReviewLane consults loadRegistry({includeInstalled:true}) and
degrades to the static set on any load failure.

* test(#2927): add CLI-seam coverage for the wiring defect + normalize slug

Two findings from the isolated adversarial review:

1. The test matrix's rows 9-10 (acceptance criteria #1-#3: overlay appears
   in sections/flags and plan resolves ok) were documented as covered but
   had no backing tests. The eight pure-helper tests would stay green if the
   one-line routeReviewLane wiring were reverted — the actual defect this PR
   closes had no regression guard. Add real end-to-end CLI tests that install
   a global-scope role:"reviewer" overlay and assert review-lane
   sections/flags/plan see it through loadRegistry -> mergeReviewerLanes.

2. mergeReviewerLanes trimmed the slug for the map key but stored the body
   with its untrimmed slug, diverging from deriveReviewerSlugs (which trims
   before adding to the roster). Normalize the stored lane's slug to the
   trimmed value so the two surfaces agree on the canonical key.

* test(#2927): correct CLI-seam fixtures for reviewer manifest shape

Two corrections from local CLI smoke-testing before the verification run:

1. role:"reviewer" manifests must omit feature-only fields (skills/agents/
   steps/contributions/gates/hooks/runtimeCompat) — the validator rejects them.
   Match the shipped capabilities/lm-studio shape.

2. The plan subcommand renders an ARRAY of {slug,ok,section,transport,...}
   (it strips the nested invocation plan object), so assert on the array
   element, not a top-level object. Also drop the malformed-flag-filter
   assertion: the capability validator enforces flag grammar at install time,
   so a lane with a malformed flag cannot be installed and never reaches the
   flags shape filter (which is defense-in-depth, not independently reachable).

* fix(#2927): drop unnecessary type assertion flagged by lint:ci

The `body as object` cast inside the spread is redundant — body is already
narrowed to object by the preceding typeof check. eslint no-unnecessary-type-
assertion flagged it; lint:ci is a merge gate.

* chore(#2927): add changeset fragment

pr:0 placeholder backfilled with the real PR number once the PR exists.

* fix(#2927): access runGsdTools result via .output in CLI-seam tests

runGsdTools returns {success, output, exitCode, error}, not a string. The CLI
tests (rows 9-10) passed the result object directly to JSON.parse/.split, which
string-coerced to "[object Object]" and threw under gsd-test (3 failures). My
local smoke test ran the CLI directly (string stdout), so it missed this — the
helper wraps execFileSync and returns a result object. Access .output and assert
.success explicitly, matching the established capability-cli.test.cjs convention.

* chore(#2927): backfill changeset PR number 3062

---------

Co-authored-by: sim <sim@local>
2026-08-04 18:59:19 -04:00

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.

npm version npm downloads Tests Discord GitHub stars License


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:

  1. Discuss — capture implementation decisions before anything is planned
  2. Plan — research, decompose, and verify the plan fits a fresh context window
  3. Execute — run plans in parallel waves; each executor starts with a clean 200k-token context
  4. Verify — walk through what was built; diagnose and fix before declaring done
  5. 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

Star History Chart

License

MIT License. See LICENSE for details.


Claude Code is powerful. GSD Core makes it reliable.

Description
No description provided
Readme MIT 77 MiB
Languages
JavaScript 82.3%
TypeScript 17.4%
Shell 0.3%