* 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
4.5 KiB
4.5 KiB
Registry Entry PR
Using the wrong template? — Bug fix: use fix.md — New feature (not a registry listing): use feature.md — Enhancement to existing behavior: use enhancement.md
Full schema and process: docs/registries/README.md.
Registry type
- Capability Registry entry — adds/updates one object in
docs/registries/capabilities.json - EoS Registry entry — adds/updates one object in
docs/registries/eos.json
The entry
{
"id": "",
"name": "",
"type": "",
"repo": "",
"description": "",
"author": "",
"license": "",
"enginesGsd": "",
"install": "",
"uninstall": "",
"interactions": {},
"discussion": ""
}
Required-field checklist
id,name,type,repo,description,author,license,enginesGsd,install,uninstall,interactions,discussionare all present and non-empty- (Capability entries only)
interactions.loopExtensionPointsis a non-empty subset of the 12 Loop Extension Points,interactions.hookKinds⊆{step, contribution, gate}, andinteractions.configKeys/requires/runtimeCompat/produces/consumesare present (empty arrays are fine where nothing applies) - (EoS entries only)
protocolVersionis an integer ≥ 1,interactions.interfacePointsis a non-empty subset of the six interface points,interactions.profileis one ofprogrammatic-cli/declarative-cli/ide, andinteractions.axeshas exactly the eight required axis keys plus, optionally,effortSurface(argv/none)
Ownership & non-endorsement
repolinks to a repository I own or am the primary maintainer of — not a fork, mirror, or someone else's project- I understand that inclusion in this registry means only that a maintainer merged this PR — it is not an endorsement, and GSD has not reviewed, tested, audited, or verified my solution or its claimed GSD interactions
- I understand this entry is removed only for illegal content, malware, spam, or a dead/non-functional link — never for quality — and a maintainer may remove it on that narrow basis without further notice
One entry, one PR
- This PR adds or updates exactly one entry, in exactly one of
capabilities.json/eos.json - I have not bundled any other registry entry, code change, or unrelated docs change into this PR
Generated file in sync
- I ran
npm run gen:registryafter editing the JSON source, and this PR includes the regenerateddocs/registries/capability-registry.mdordocs/registries/eos-registry.md - I did not hand-edit the generated
.mdfile directly — all edits were made to the JSON source
Documentation
CI enforces
lint:docsfor any changeset fragment typedAdded/Changed/Deprecated/Removed— it must also touch a file underdocs/. The JSON source and its regenerated markdown, both underdocs/registries/, satisfy this.
- This PR includes both the JSON source file and the regenerated markdown file under
docs/registries/
Checklist
npm run validate:registrypasses locally against my entrydiscussionlinks to a GitHub Discussion in theRegistrycategory (or notes that one will be created on merge, per docs/registries/README.md).changeset/fragment added with anAddedtype describing the new listing
Example filled entry
{
"id": "linear-issue-sync",
"name": "Linear Issue Sync",
"type": "capability",
"repo": "some-org/gsd-cap-linear-sync",
"description": "Mirrors ROADMAP.md items to Linear issues as a ship:post contribution.",
"author": "Some Org <hello@some-org.example>",
"license": "MIT",
"enginesGsd": ">=1.6.0",
"install": "gsd capability install https://github.com/some-org/gsd-cap-linear-sync.git#v1.0.0",
"uninstall": "gsd capability remove linear-issue-sync",
"interactions": {
"loopExtensionPoints": ["ship:post"],
"hookKinds": ["contribution"],
"configKeys": ["linear-issue-sync.enabled"],
"requires": [],
"runtimeCompat": ["all"],
"produces": ["linear-issue-links"],
"consumes": ["ROADMAP.md"]
},
"discussion": "https://github.com/open-gsd/gsd-core/discussions/1234"
}