Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD
across contents and paths, upstream package/repo coordinates -> @golem15/msd-core
and golem15com/msd-core. Deep links into upstream history, sibling upstream
packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is.
Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line,
package/plugin identity, regenerated lockfile, install-tree fixtures, derived
registries and benchmark baseline; migration checksum baseline re-locked
(MSD keeps its own install state, so no install had applied the old sums);
sort-order and regex-escaped expectations in tests adjusted.
* docs(registries): add gsd-qoder EoS entry
Adds one `type: "eos"` entry for a Qoder host integration and regenerates
docs/registries/eos-registry.md.
Qoder is Alibaba's AI coding product family (Qoder CLI and Qoder Desktop).
The integration depends on @opengsd/gsd-core, negotiates the ADR-1239
host-integration handshake, and projects GSD's agents, skills, and hook
scripts into the Qoder config directory (~/.qoder, or ~/.qoder-cn for the
China edition), merging GSD's lifecycle hooks into settings.json.
Every axis is sourced from Qoder's own docs per the never-infer rule.
`dispatch.isolation` is `none`: Qoder documents `isolation: worktree` as a
frontmatter-declared, per-agent-definition property, and GSD's two
isolation negotiation models both assume a per-dispatch injection point
Qoder does not expose.
Re-homes the Qoder runtime work from #860 / PR #2005, which was closed in
favor of the EoS path.
Closes#4123
* docs(#4123): backfill changeset pr field
Adds one `type: "eos"` entry for a Reasonix host integration and regenerates
docs/registries/eos-registry.md.
Reasonix is a Go, single-static-binary, DeepSeek-native terminal coding agent.
The integration renders the GSD workflow set as native Reasonix slash-command
launchers; GSD workflows are not reimplemented.
Every axis is sourced from Reasonix's own docs per the never-infer rule.
`effortSurface` is omitted: Reasonix resolves effort from config and the
/effort command with no argv route, so neither allowed value fits and the
field is optional.
Supersedes #3346, which proposed an in-tree capabilities/reasonix entry and
was closed as filed against the wrong surface.
Co-authored-by: onionviolet <apexofficial21@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
* docs(#2904): how-to for listing a reviewer lane in the registry
#2912 shipped the Reviewer Lane Registry, which lands in 1.9.1. Two docs
consequences.
New: docs/how-to/list-your-reviewer-lane.md. A Diataxis how-to for the
publish task -- which of the three catalogs applies (and why a runtime
carrying a reviewer body lists under its primary install shape instead),
opening the required discussion thread BEFORE the PR, the three fields
that reject entries most often (slug grammar differs from id, flags stay
kebab when the slug is snake, install/uninstall must be copy-pasteable),
regenerate-don't-hand-edit, and register-once-then-Releases. Links the
registry README for the field table rather than duplicating it -- the
spec is reference, this is the task flow.
Corrected: ship-a-reviewer-lane.md said "Listing your lane is not wired
yet" and pointed at #2904 as future work. #2906 merged at 11:25Z and
#2912 at 12:11Z, so that section shipped false the moment the registry
landed. Replaced with the publish pointer.
Indexed the new guide and the generated catalog in docs/README.md, and
added the guide to develop-a-capability.md's ecosystem list.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs(#2904): caveat credential-bearing configKeys in both the guide and the spec
Isolated security review found the worked entry's `configKeys:
["acme.api_key"]` modelled storing a live credential with no note on
where that value ends up.
Verified: config values are written in plaintext to
.planning/config.json (docs/CONFIGURATION.md:227 -- masking is
display-only, "that file is the security boundary"), and
planning.commit_docs defaults to true (:466). So a credential declared
that way lands in the installing user's git repository unless they have
gitignored .planning/. None of the twelve first-party lanes does this --
they own only review.models.*, host, and prompt-budget keys.
The pattern originates in docs/registries/README.md:221, shipped by
#2912, so the caveat goes on BOTH surfaces rather than only on the copy
that inherited it -- the spec's example is what future authors will read
first.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* chore(#2915): backfill changeset PR number
pr: 0 -> 2917.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: sim <sim@local>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* feat(#2904): add a `reviewer` entry type so third-party reviewer lanes are discoverable
ADR-2782 made a reviewer lane installable by a third party, but neither
discoverability catalog could hold one. The Community Capability Registry
requires a non-empty `loopExtensionPoints` and forbids a lane from declaring
any hook kind, so a `role: "reviewer"` entry is unsatisfiable by construction;
the EoS Registry is for ADR-1239 host integrations, which a lane is not.
Adds a third catalog — `docs/registries/reviewers.json` →
`docs/registries/reviewer-registry.md` — whose `interactions` describes the
lane: slug, flags, transport, evidenceClass, reviewsSection, requiresBinaries,
configKeys, runtimeCompat.
The lane vocabulary is a hand-written mirror of `capability-validator.cjs`
(the same pattern as `AXES` mirroring `HOST_INTEGRATION_AXES`), with parity
enforced by tests/registry-reviewer-parity.test.cjs. `slug` deliberately uses
the runtime `LANE_SLUG_RE` grammar rather than the registry's kebab-only `id`
rule, so real lanes (`lm_studio`, `4o-mini`) are not rejected.
Two binary type branches became three-way Map dispatch. Both now fail loudly
on an unrecognized type instead of silently treating it as a capability —
`renderMarkdown` in particular writes a committed catalog file, so a silent
wrong-title render was the worst failure mode available.
Also fixed while here: `gen-registry.cjs` parsed source JSON with no error
handling, so a malformed or non-array `capabilities.json` surfaced as a raw
SyntaxError/TypeError instead of an actionable CLI error.
Closes#2904
* fix(#2904): bound and sanitize untrusted registry `interactions` strings
Review findings from the pre-PR passes.
Security (isolated pass): `interactions` string fields reached the generated,
committed Markdown catalog with no control-character check and no length
bound. A `reviewsSection` carrying ESC and a `requiresBinaries` element
carrying NUL plus 5000 characters validated clean and landed verbatim in the
rendered page — `mdInline` escapes Markdown metacharacters and collapses CRLF,
but nothing else. The identical gap already existed on the capability type's
`configKeys`/`requires`/`runtimeCompat`/`produces`/`consumes`, so it is fixed
there too rather than inherited into a third type.
`hasDisallowedControlChar` is lifted to module scope so exactly one
implementation exists, and a shared `validateStringArrayField` enforces
control-character rejection, a 200-character element cap and a 50-element
array cap for both types.
Correctness (standards pass): `renderMarkdown`'s per-entry summary builder was
still an if/else-if chain whose final `else` was the capability branch — the
one per-type dispatch point this change had not converted, and the same silent
fallthrough it removes elsewhere. It now lives in `RENDER_META` alongside the
title, so a fourth type cannot silently inherit capability's rendering. All
three types' rendered output is byte-identical to before the refactor.
Also corrects a test comment that still claimed the reviewer suites were
failing-first against an unmodified module.
* chore(#2904): backfill changeset PR number (#2912)
* fix(#2810): accept the documented effortSurface axis on EoS registry entries
The EoS registry schema required an exact eight-key `interactions.axes`
object, while `docs/registries/README.md` and `CONTEXT.md` both documented
nine keys including `effortSurface`. An entry that faithfully mirrored its
upstream descriptor's `effortSurface` key was rejected outright.
`effortSurface` reached the runtime-descriptor vocabulary through ADR-1239
amendment #2481 (`HOST_INTEGRATION_AXES`), but the registry's hand-maintained
copy of that vocabulary never picked it up. The runtime-descriptor surface is
guarded by tests/host-integration-validator-parity.test.cjs; the registry copy
had no equivalent guard, which is what let the two drift.
Accept `effortSurface` as an OPTIONAL ninth axis validated against the
canonical ['argv','none'] rather than a required one: registry entries mirror
their upstream registry/eos-entry.json byte-for-byte, so requiring it would
retroactively invalidate every entry published before the amendment.
Adds tests/registry-axes-parity.test.cjs, which asserts that every key shared
between the registry vocabulary and HOST_INTEGRATION_AXES has an identical
enum array, plus limit-1/limit/limit+1 boundary coverage on the axes key set.
Closes#2810
* test(#2810): fail when a canonical axis is added but never mirrored
The enum-equality assertion compares only keys the registry and
HOST_INTEGRATION_AXES already share, so it is blind to the exact drift that
produced #2810: a new canonical axis appears and the registry copy is never
told. Verified by simulation — mutating an enum is caught, adding a new
canonical key is not.
Assert instead that every HOST_INTEGRATION_AXES key is either modeled by the
registry or named in an explicit NOT_MODELLED allowlist (subagentToolkit and
isolation, both dispatch sub-fields the registry collapses into its free-form
dispatch summary). Adding a canonical axis now fails until someone decides
which bucket it belongs in. The allowlist is itself guarded against going
stale.
Refs #2810
* fix(#2810): harden the axis value lookup with the CodeQL barrier pattern
Both orthogonal reviews flagged the same line: `AXES[key] !== undefined`
is not an own-property test, and the bracket reads are shaped like a
prototype-pollution sink even though the unknown-key gate above provably
makes them unreachable.
Switch the presence test to `Object.hasOwn` and add the repo's inline
literal guards (`capability-state.cts:146-155`, "Prototype-pollution guard
(inline literal, CodeQL barrier)"), which CodeQL can follow where it cannot
follow the `.includes()` filter that actually does the work.
Behavior is unchanged — re-verified all five axes key-count shapes plus a
genuine own `__proto__` property built through JSON.parse (the shape a
third-party registry PR would submit): it is rejected as an unknown key and
Object.prototype is untouched.
Refs #2810
* chore(#2810): backfill changeset PR number
* docs: add gsd-cursor to the EoS registry
Appends the gsd-cursor EoS entry to docs/registries/eos.json and regenerates
docs/registries/eos-registry.md. Discussion: open-gsd/gsd-core#2578.
* docs(#2533): regenerate eos-registry.md (id-sorted) + add changeset
Addresses review on #2581: the generator sorts entries by id, so gsd-cursor
(< gsd-omp) must appear first in both the table and the detail sections.
Also adds the required .changeset Added fragment (mirrors precedent #2448).
* docs(#2533): regenerate eos-registry.md via gen-registry.cjs (markdown escaping)
The hand-written markdown left ( ) and _ unescaped; scripts/gen-registry.cjs
escapes them (\(...\), model\_profile\_overrides), so gen-registry.cjs --check
(part of lint:ci / the lint-tests job) failed. This is the generator's exact
output; node scripts/gen-registry.cjs --check now passes.
* docs(#2533): regenerate eos-registry.md for corrected compat floor
Regenerated via scripts/gen-registry.cjs after the enginesGsd fix.
node scripts/gen-registry.cjs --check passes (exit 0).
* docs(#2533): correct gsd-cursor enginesGsd floor to >=1.8.0 (real release)
The >=1.39.0 floor referenced a legacy-lineage version number that no
current @opengsd/gsd-core release has ever reached (latest is 1.8.0).
Per trek-e's review, corrected to >=1.8.0 — the current release, which
ships the model_profile_overrides.<runtime> config key gsd-cursor uses.
* docs(#2533): regenerate eos-registry.md (enginesGsd >=1.0.0, install v1.0.1)
* docs(#2533): mirror gsd-cursor enginesGsd >=1.0.0 + repoint install to v1.0.1
Per review: enginesGsd must mirror what the package declares. Corrected
engines.gsd upstream in gsd-cursor to >=1.0.0 and cut v1.0.1; this mirrors
that range and pins install at the new tag.
* fix(#2615): document the effortSurface axis in the host-integration matrix
#2481 added `effortSurface` as the ninth negotiated `hostIntegration` axis and
wrote documentation-sourced values into 18 descriptors, but never touched
`docs/reference/host-integration-capability-matrix.md`. The matrix that ADR-1239
designates the cited source of truth had zero occurrences of the axis: no entry in
the axes legend, and no row in any of the per-runtime tables. `src/host-integration.cts`
states "every value is documented or explicitly 'undocumented'" — for this axis
that was false for every runtime.
Adds the legend entry (the `argv` / `none` / `undocumented` vocabulary, plus why
there is deliberately no config-file member) and an `effortSurface` row to all 19
per-runtime tables. Every citation is carried over from #2481's own commit message,
where the values were sourced:
- claude argv -- `claude --help` documents `--effort <level>`
- opencode argv -- `opencode run --help` documents `--variant`
- codex argv -- `model_reasoning_effort` is a config.toml key, not a dedicated
flag, so the generic `-c key=value` override is the only argv
route (still argv)
- 15 hosts undocumented -- their docs state no reasoning setting
kimi-code is the nineteenth section (added by #2603 after #2481) and is the one
runtime with no declared value. Its row and a Documentation-gaps entry record why
rather than inventing one: Kimi Code documents `/effort` (alias `/thinking`), but
only as an INTERACTIVE slash command — `-m, --model` is the only model-adjacent
argv. Neither vocabulary member is accurate (`none` would deny a mechanism the host
has, `argv` would claim one it does not expose), so closing that gap needs a
vocabulary decision, which is a negotiation change and not a documentation one. The
absent value already degrades closed exactly as the sentinel does.
The regression test derives its runtime list from the registry rather than
hardcoding it, so a runtime added later fails until its matrix row exists — the
ratchet whose absence let #2481 add an axis with nothing catching the missing docs.
Closes#2615
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QT3ibz5qJuDuGqpTGRYVGf
* docs(#2615): honest citations for the undocumented rows; fix the four stale 8-axis lists
Two findings from the orthogonal review of the first commit.
1. The 15 `undocumented` rows shared byte-identical text — "searched the runtime's
official docs (see Sources consulted above)" — which is weaker than this file's
own convention ("no authoritative doc — searched: <url>") and, worse, implies a
per-host targeted search that did not happen: each section's Sources-consulted
list was gathered for OTHER axes and contains no CLI-reference or
reasoning-effort source. The rows now say plainly what the finding is — an
ABSENCE established by #2481's cross-host survey — and cite that survey rather
than implying a URL was checked per host.
2. Four normative docs still described "the eight negotiated axes" and omitted
effortSurface entirely. The worst of them is
docs/how-to/add-or-update-a-host-integration.md — the maintainer's own guide for
onboarding a host, whose Step 2 axis table would have a maintainer reproduce
exactly the gap #2615 exists to close. Also fixed:
docs/reference/host-integration-interface.md (which calls itself the normative
reference and had no effortSurface row at all),
docs/how-to/author-a-host-plugin.md, docs/registries/README.md ("**exactly** the
eight … axes keys"), and CONTEXT.md's matching EoS-registry sentence.
Deliberately NOT changed, because they are historical records rather than current
contract: docs/whats-new-1.7.0.md and docs/FEATURES.md's 1.7.0 entry (effortSurface
shipped in 1.8.0 via #2481 — rewriting them would falsify the release history),
ADR-1239's pre-amendment body (already superseded by its own
"Amendment (2026-07-21): effortSurface axis (#2481)"), and ADR-1016's "original
eight axes", which refers to a different axis set entirely.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QT3ibz5qJuDuGqpTGRYVGf
* chore(#2615): backfill changeset PR number (#2698)
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
The submission process told an admin to create a `Registry` Discussions
category and never stated its format. Both were wrong in a way a correct
reading of the docs could not catch.
Name: the category is `EoS Registry`, and it carries threads for both
registries — `discussion` is a required field on Capability entries as well as
EoS entries. A reader following the old text would create a second, duplicate
category.
Format: `discussion` being required means the thread must exist before the
entry's PR, opened by the entry's author — an outside contributor holding
neither `maintain` nor `admin`. GitHub's Announcement format restricts starting
discussions to those two levels, so an admin could pick it, block every external
submission at the first step, and see nothing wrong. Records open-ended as the
required format, and why Announcement and Question/Answer do not work.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Instantiates the second discoverability catalog from issue #2182 on top of the
shared registry foundation shipped in PR #2188: an empty eos.json source and the
generated eos-registry.md (EoS entries declare the six Host-Integration interface
points, eight negotiated axes, and protocol version per ADR-1239). The validation,
generation, and rendering machinery + README schema + glossary term already landed
and are tested in PR #2188; this PR adds the EoS registry data + catalog page.
Closes#2182
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements the three pure functions in registry-schema.cjs (isValidGsdRange,
validateEntries, renderMarkdown) that were stubbed in the previous commit, turning
the red suite green: strict per-type schema validation (capability + eos), a
self-contained engines.gsd range validator (no semver dep), and deterministic
Markdown generation with shields.io release badges + per-entry Discussion links.
Regenerates docs/registries/capability-registry.md and adds the Added changeset.
Also hardens the isValidGsdRange fast-check property (letters-only major) so it
cannot intermittently generate a valid prerelease range and flake.
Closes#2182
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the discoverability-registry surface for issue #2182: JSON-sourced
capability/eos catalogs, a pure schema/vocab module (registry-schema.cjs)
with the ADR-857 loop points + ADR-1239 axes, thin validate/gen CLIs,
the registry-entry PR template, README spec, and CONTEXT.md glossary terms.
The three pure functions (isValidGsdRange/validateEntries/renderMarkdown)
are stubbed here so the comprehensive test suite fails first (red), per the
feature-implementation red-first directive; the next commit implements them.
Refs #2182
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>