* 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>