Files
msd-core/docs/reference/host-integration-interface.md
Tom Boucher 1008aabd31 fix(#2615): document the effortSurface axis in the host-integration matrix (#2698)
* 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>
2026-07-27 09:02:20 -04:00

81 lines
4.3 KiB
Markdown

# Reference: the Host-Integration Interface
This is the normative reference for the GSD Host-Integration Interface (ADR-1239)
— the versioned, negotiated contract over which any host embeds GSD's
orchestration loop. The published surface is the SDK entry
(`src/host-integration-sdk.cts`); this document specifies every symbol on it.
The governing principle: **every axis value a host declares must come from that
host's authoritative documentation.** Where docs are silent, the host declares
the `undocumented` sentinel and the engine degrades fail-closed — it never
assumes a capability.
---
## Protocol version
`PROTOCOL_VERSION` (a positive integer) is the interface version. It governs the
negotiated capability set; see the [versioning policy](../explanation/interface-versioning-policy.md)
for what a bump means.
## The nine negotiated axes
`HOST_INTEGRATION_AXES` is the closed vocabulary. Each axis takes a documented
value (or the `undocumented` sentinel):
| Axis | Values |
|---|---|
| `embeddingMode` | `imperative` \| `declarative` |
| `commandSurface` | `slash-file` \| `slash-programmatic` \| `slash-toml` \| `palette` \| `prose-only` |
| `dispatch` | struct: `{ namedDispatch, nested, maxDepth, background, subagentToolkit, backgroundDispatch }` |
| `modelMode` | `active` \| `passive` |
| `hookBus` | `host` \| `engine` \| `none` |
| `stateIO` | `filesystem` \| `sandboxed-storage` \| `session-log-append` |
| `transport` | `mcp` \| `native-extension` |
| `runtime` | `node` \| `bun` \| `sandboxed-web` \| `python` \| `go` \| `rust` \| `electron` \| `other` |
| `effortSurface` | `argv` \| `none` |
## Classification + negotiation
- `profileOf(axes)` → `'programmatic-cli'` \| `'declarative-cli'` \| `'ide'` \| `null`.
- `negotiateHostCapabilities(host, engine)` → `{ protocolVersion, effective, points, warnings }` — the in-process negotiation. Pure; never throws.
- `handleHandshakeRequest(request)` / `buildHandshakeRequest(descriptor)` — the **serialized** (out-of-process) form of the same negotiation, JSON-safe across a wire boundary. The two are consistent: a serialized request yields the same `effective` axes as the in-process call.
- `degradationFor(point, axes)` → `{ level, fallback, unknown? }` for one of the six interface points (`command` \| `dispatch` \| `model` \| `hooks` \| `state` \| `artifact`).
- `hookEventSurfaceFor(hookEvents)` → the host-fireable hook events for a dialect (`'claude'` \| `'gemini'` \| `'opencode-subset'`), or `null` if unknown.
- `shouldFlattenDispatch(dispatch)` → `true` when the orchestrator must run inline (fail-closed).
## The engine adapters
All five satisfy a common `{ kind, runtime, install, uninstall }` shape and are
constructed fail-closed (they throw if a required host primitive is absent):
| Adapter | Factory | Selected by |
|---|---|---|
| Embedding (declarative) | `createDeclarativeAdapter({runtime})` | `embeddingMode: 'declarative'` |
| Embedding (imperative) | `createImperativeAdapter({runtime})` | `embeddingMode: 'imperative'` (also exposes the composed `registry`) |
| Model | `createModelAdapter({modelMode}, {sendRequest?})` | `modelMode` (`'active'` needs a host `sendRequest`) |
| Hook bus | `createHookBus({bus}, {hostEmit?})` | `hookBus` (`'host'` needs a host `hostEmit`) |
| State IO | `createStateIO({io}, {backend?})` | `stateIO` (`'sandboxed-storage'`/`'session-log-append'` need a host `backend`) |
The declarative + imperative adapters delegate install/uninstall in-process to
the **same** `installRuntimeArtifacts` engine function `bin/install.js` uses, so
adapter output is byte-identical to a first-party install (gated by
`tests/golden-install-parity.test.cjs`).
## Profiles
`PROFILE_BASELINES` fixes the three reference profiles:
| Profile | Baseline |
|---|---|
| `programmatic-cli` | imperative, slash-file, host bus, filesystem, mcp, node |
| `declarative-cli` | declarative, slash-file, host bus, filesystem, mcp, node |
| `ide` | imperative, palette, **active** model, **engine** bus, **sandboxed-storage**, sandboxed-web |
## See also
- [How-to: author a host-plugin](../how-to/author-a-host-plugin.md)
- [Tutorial: embed GSD in a new host](../tutorials/embed-gsd-in-a-new-host.md)
- [Interface versioning policy](../explanation/interface-versioning-policy.md)
- ADR-1239 (the design) · `docs/reference/host-integration-capability-matrix.md` (per-host values + citations)