Files
msd-core/capabilities/opencode/capability.json
Tom Boucher a3853472de fix(#2598): declare OpenCode subagent dispatch synchronous, not background (#2682)
* fix(#2598): declare OpenCode subagent dispatch synchronous, not background

capabilities/opencode/capability.json advertised dispatch.background: true and
dispatch.backgroundDispatch: true. negotiateHostCapabilities and every
degradationFor / shouldFlattenDispatch consumer trusts these per-field values, so
declaring a capability the host lacks OVERSTATES it — the opposite of the
fail-closed posture the negotiation is built for.

The issue's own citations needed checking before acting: the host-integration
matrix (ADR-1239's designated deployment source-of-truth) documented `true` with
NEWER evidence than the issue cited, and explicitly marked the issue's
sst/opencode#5887 reference as a stale snapshot superseded by #2087. git log
confirms #2087 deliberately flipped these from false to true, citing OpenCode
v1.15.0/v1.17 as "background subagents enabled by default in all modes". Applying
the issue as filed would, on that evidence, have REGRESSED a deliberate update.

So the claim was verified against current upstream rather than either document.
`packages/opencode/src/effect/runtime-flags.ts` on `dev` today reads:

    experimentalBackgroundSubagents: enabledByExperimental("OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS")

`enabledByExperimental` falls back to the `experimental` flag and `bool()`
defaults to false — the parameter is hidden from the model unless an operator
opts in by env var. Upstream #29638 is still OPEN and confirms the session loop
`tasks.pop()`s one subtask at a time. #2087's "default-on in all modes" reading
does not hold against current dev.

The issue's CONCLUSION is therefore right even though part of its evidence was
superseded: concurrent dispatch cannot be relied on, so both fields are false.

The matrix rows are corrected with the verified citation rather than reverted to
the old #5887 quote, so the record shows why the value is false TODAY rather than
re-asserting evidence that was legitimately superseded. Neighbouring sub-fields
are untouched and pinned by test: namedDispatch, subagentToolkit, and
isolation:'orchestrator-worktree' (which works via `opencode run --dir` at the OS
process level and is unaffected — #2584 does not depend on this value either way).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015TCwhbMuY37DzRMCfzTABJ

* fix(#2598): re-pin the dispatch contract tests to synchronous OpenCode dispatch

gsd-test on the descriptor change came back FAILED (5 unique, both node
versions). The failures were not incidental — they were deliberate contract-pin
tests encoding #2087's decision, one named literally "background UPGRADE":

  tests/host-integration-descriptors.test.cjs
    - EXPECTED_FLATTEN[opencode] === false (background-eligible)
    - the derived background-eligible set pin
  tests/opencode-imperative-reference.test.cjs
    - "descriptor declares background dispatch true/true (v1.15/v1.17 upgrade)"
    - "background UPGRADE changes shouldFlattenDispatch: false now"

So this is a recorded decision being reversed, not drift being corrected, and it
is reversed on evidence: current upstream `dev` gates the capability behind
OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS (default false) and upstream #29638
(OPEN) confirms the session loop still handles one subtask at a time. The issue
is filed by the maintainer and explicitly directs "update golden-parity /
validator fixtures as needed", which sanctions re-pinning.

Behavioral consequence, verified: shouldFlattenDispatch(opencode) now returns
TRUE, so GSD serializes opencode dispatch instead of trusting concurrency it
cannot get. That is the correct fail-closed direction and is safe today — no
shipped GSD flow drives OpenCode background waves (per the issue), and
isolation:'orchestrator-worktree' is unaffected because it works at the OS
process level via `opencode run --dir`, not via the native subagent.

Each re-pinned test now asserts the retracted contract in the opposite
direction — feeding the #2087 axes back in must still yield "would not flatten" —
so a silent re-flip of either field is caught rather than merely un-asserted.

lint:ci exit 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015TCwhbMuY37DzRMCfzTABJ

* chore(#2598): backfill changeset pr number (#2682)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 21:47:54 -04:00

115 lines
3.0 KiB
JSON

{
"id": "opencode",
"role": "runtime",
"version": "1.8.0",
"title": "OpenCode",
"description": "OpenCode — XDG-based config dir; flat commands/ + skills artifact layout; settings-json config format; no lifecycle hook registration; tier-2 support.",
"tier": "core",
"requires": [],
"engines": {
"gsd": ">=1.6.0"
},
"runtime": {
"configHome": {
"kind": "xdg",
"name": "opencode",
"env": [
"OPENCODE_CONFIG_DIR",
"OPENCODE_CONFIG",
"XDG_CONFIG_HOME"
]
},
"localConfigDir": ".opencode",
"configFormat": "settings-json",
"artifactLayout": {
"global": [
{
"kind": "commands",
"destSubpath": "commands",
"prefix": "gsd-",
"nesting": "flat",
"recursive": false,
"converter": null
},
{
"kind": "skills",
"destSubpath": "skills",
"prefix": "gsd-",
"nesting": "flat",
"recursive": true,
"converter": "convertClaudeCommandToOpencodeSkill"
}
],
"local": [
{
"kind": "commands",
"destSubpath": "commands",
"prefix": "gsd-",
"nesting": "flat",
"recursive": false,
"converter": null
},
{
"kind": "skills",
"destSubpath": "skills",
"prefix": "gsd-",
"nesting": "flat",
"recursive": true,
"converter": "convertClaudeCommandToOpencodeSkill"
}
]
},
"commandStyle": "slash-hyphen",
"hooksSurface": "none",
"extensionEvents": "opencode",
"sandboxTier": "none",
"supportTier": 2,
"installSurface": "settings-json",
"writesSharedSettings": true,
"permissionWriter": "opencode",
"extendedHookEvents": [],
"hostIntegration": {
"embeddingMode": "imperative",
"commandSurface": "slash-file",
"dispatch": {
"namedDispatch": true,
"nested": "undocumented",
"maxDepth": "undocumented",
"background": false,
"subagentToolkit": "full",
"backgroundDispatch": false,
"isolation": "orchestrator-worktree"
},
"modelMode": "active",
"hookBus": "host",
"stateIO": "filesystem",
"transport": "mcp",
"runtime": "bun",
"effortSurface": "argv"
},
"orchestratorExec": {
"command": "opencode",
"args": ["run"],
"cwdFlag": "--dir",
"promptFlag": null
},
"hostBehaviors": {
"reapplyCommand": "/gsd-update --reapply",
"attributionConfigResolver": "opencode",
"flatCommandDir": "commands",
"combinedFamilyInstall": true,
"frontmatterDialect": "opencode",
"nativePlugin": {
"dir": "plugins",
"file": "gsd-core.js",
"source": ".opencode/plugins/gsd-core.js"
},
"skipHomePrefixSubstitution": true,
"skipSettingsUi": true,
"skipUpdateBannerCommand": true,
"skipCodexSkillsManifest": true,
"reviewerCli": true
}
}
}