refactor: hard-fork GSD -> MSD (Make Software Done)
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.
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
# Capability Manifest Reference (`capability.json`)
|
||||
|
||||
> **Canonical ADRs:** [ADR-1244](../adr/1244-capability-ecosystem.md) · [ADR-894](../adr/894-capability-declaration-format.md) · [ADR-1016](../adr/1016-runtime-capability-descriptor.md)
|
||||
> **See also:** [How to develop a capability](../how-to/develop-a-capability.md) · [Capability Command Reference](gsd-capability-command.md)
|
||||
> **See also:** [How to develop a capability](../how-to/develop-a-capability.md) · [Capability Command Reference](msd-capability-command.md)
|
||||
|
||||
Each capability is a folder `capabilities/<id>/` (or an overlay root `~/.gsd/capabilities/<id>/` / `.gsd/capabilities/<id>/`) containing one `capability.json` declaration.
|
||||
Each capability is a folder `capabilities/<id>/` (or an overlay root `~/.msd/capabilities/<id>/` / `.msd/capabilities/<id>/`) containing one `capability.json` declaration.
|
||||
The file is schema-validated JSON with a common **envelope** plus a **role-typed body** (`role: "feature"`, `role: "runtime"`, or `role: "reviewer"`).
|
||||
|
||||
---
|
||||
@@ -14,16 +14,16 @@ These fields are present for `role: "feature"`, `role: "runtime"`, and `role: "r
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `id` | string (kebab-case) | Yes | Unique identifier; **must equal the folder name**. The prefix `gsd-`, `gsd-core-`, and `anthropic-` are reserved for first-party use. |
|
||||
| `id` | string (kebab-case) | Yes | Unique identifier; **must equal the folder name**. The prefix `msd-`, `msd-core-`, and `anthropic-` are reserved for first-party use. |
|
||||
| `role` | `"feature"` \| `"runtime"` \| `"reviewer"` | Yes | Discriminator that selects the body schema. `"reviewer"` is for lane-only capabilities that ship a `reviewer` body and nothing else — see [Reviewer body](#reviewer-body-role-reviewer-or-on-any-role) below. |
|
||||
| `version` | semver string | Yes (1.6.0+) | Semantic version of this capability. The registry rejects a manifest without one. |
|
||||
| `title` | string | Yes | Short human-readable label. Must be a non-empty string. |
|
||||
| `description` | string | Yes | Longer summary sentence. Must be a non-empty string. |
|
||||
| `tier` | `"core"` \| `"standard"` \| `"full"` | Yes | **Source of truth** for install-profile membership and surface cluster assignment. `tier` propagates via the `requires`-closure; install profiles are generated from it. |
|
||||
| `requires` | string[] | Yes | Capability `id` values this capability depends on. Must be present as an array (use `[]` when there are no dependencies). Each entry must exist in the registry, be acyclic, and be tier-monotone (a `core` capability may not require a `standard` or `full` capability; a `standard` capability may not require a `full` capability). |
|
||||
| `engines` | object | No | Host-compatibility constraint. Sub-field: `gsd` — semver range string (e.g. `">=1.6.0 <3.0.0"`). Acts as a hard gate at install **and** at load; a mismatch blocks installation and causes the overlay to be skipped with a warning at load time. |
|
||||
| `engines` | object | No | Host-compatibility constraint. Sub-field: `msd` — semver range string (e.g. `">=1.6.0 <3.0.0"`). Acts as a hard gate at install **and** at load; a mismatch blocks installation and causes the overlay to be skipped with a warning at load time. |
|
||||
| `runtimeCompat` | object | Yes (`role: "feature"`) | Declares which host runtimes this capability can surface through. Validated for every `role: "feature"` capability (a feature manifest without it fails validation). Sub-fields: `supported` — a **non-empty** array of kebab-case runtime ids, or the single wildcard `["*"]` for a runtime-agnostic capability; `unsupported` — an array of kebab-case runtime ids (the wildcard is **not** permitted here); `notes` — optional object mapping a runtime id (or `"*"`) to a non-empty explanatory string. The wildcard `"*"` may not be mixed with concrete ids in the same array, and the reserved names `__proto__`/`constructor`/`prototype` are rejected. |
|
||||
| `compatVersions` | object | No | Graceful-downgrade table mapping `"<capVersion>"` to `"<min gsd version>"`. Only meaningful for sources that enumerate versions (git tags, registry, npm); a bare tarball URL carries one version and simply blocks on incompatibility. |
|
||||
| `compatVersions` | object | No | Graceful-downgrade table mapping `"<capVersion>"` to `"<min msd version>"`. Only meaningful for sources that enumerate versions (git tags, registry, npm); a bare tarball URL carries one version and simply blocks on incompatibility. |
|
||||
| `integrity` | string | No | `sha512-<base64>` hash of the capability bundle. Verified before extraction when present; mismatch aborts install. |
|
||||
| `provenance` | object | No | `{ sourceRepo: string, commit: string }`. Emitted in CI for first-party and curated capabilities. |
|
||||
| `author` | object | No | `{ name: string, email?: string, url?: string }`. |
|
||||
@@ -114,7 +114,7 @@ Gates check a condition at a loop extension point and optionally block progressi
|
||||
|
||||
| Form | Shape | Blocking permitted | Notes |
|
||||
|---|---|---|---|
|
||||
| Query | `{ "query": "<gsd_run query>" }` | Yes | Deterministic first-party code. |
|
||||
| Query | `{ "query": "<msd_run query>" }` | Yes | Deterministic first-party code. |
|
||||
| Predicate | `{ "predicate": { "kind": "artifact-exists" \| "config-equals" \| …, … } }` | Yes | Declarative; no code path. |
|
||||
| Agent verdict | `{ "agentVerdict": { "ref": …, "prompt": … } }` | No (forced advisory) | LLM evaluation; non-deterministic checks may not halt the loop. |
|
||||
|
||||
@@ -126,16 +126,16 @@ Declares that this capability resolves per-task content (`<action>`/`<verify>`/
|
||||
one of `steps` / `contributions` / `gates`, and it does not use a `point` value from the closed
|
||||
12-point vocabulary above — it is dispatched directly, once per task, by `execute-plan.md` before
|
||||
that task's `read_first` gate, documented separately in
|
||||
[`loop-hook-dispatch.md`](../../gsd-core/references/loop-hook-dispatch.md#the-executetask-point-a-different-shape).
|
||||
[`loop-hook-dispatch.md`](../../msd-core/references/loop-hook-dispatch.md#the-executetask-point-a-different-shape).
|
||||
See [ADR-3646](../adr/3646-per-task-content-resolution-seam.md) for the full design and
|
||||
[Develop a task-content resolver capability](../how-to/develop-a-task-content-resolver-capability.md)
|
||||
for the authoring walkthrough.
|
||||
|
||||
| Sub-field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `trackerPrefix` | string (kebab-case) | Yes | Matches the prefix of a task's `<task tracker-id="beads:GSD-42">` attribute — everything before the **first** `:`. Text after the first colon, including further colons, is passed through verbatim as the id. Must be unique across the merged first-party ∪ overlay capability set. |
|
||||
| `trackerPrefix` | string (kebab-case) | Yes | Matches the prefix of a task's `<task tracker-id="beads:MSD-42">` attribute — everything before the **first** `:`. Text after the first colon, including further colons, is passed through verbatim as the id. Must be unique across the merged first-party ∪ overlay capability set. |
|
||||
| `invoke.binary` | string | Yes | Executable name or path for the resolver subprocess. |
|
||||
| `invoke.args` | string[] | Yes | Argv passed to `invoke.binary`. Must contain the `{{id}}` placeholder at least once — GSD substitutes it with the task's tracker id (everything after the first `:`); an `args` array that never carries the placeholder fails validation, since the id could never reach the resolver. |
|
||||
| `invoke.args` | string[] | Yes | Argv passed to `invoke.binary`. Must contain the `{{id}}` placeholder at least once — MSD substitutes it with the task's tracker id (everything after the first `:`); an `args` array that never carries the placeholder fails validation, since the id could never reach the resolver. |
|
||||
| `invoke.timeoutMs` | number | Yes | Bound on the subprocess invocation. Required — an unbounded resolver subprocess is this repo's named Unbounded Subprocesses defect class. A resolver exceeding this bound is killed and `task resolve-content` exits non-zero. |
|
||||
|
||||
`taskContentResolver` is feature-role only (`role: "feature"`); it is not admissible on `role: "runtime"` or `role: "reviewer"` bodies.
|
||||
@@ -169,12 +169,12 @@ A valid point is necessary but not sufficient: each host workflow decides, per p
|
||||
|
||||
## Runtime body (`role: "runtime"`)
|
||||
|
||||
Runtime capabilities describe how GSD projects its artefacts onto one host CLI. The body is a closed 8-axis (plus 4 install-surface) vocabulary; no feature-only fields (`skills`, `agents`, `steps`, `contributions`, `gates`, `hooks`) are permitted. Full semantic specifications, the closed enum values for each axis, and the 16-runtime worked examples are in [ADR-1016](../adr/1016-runtime-capability-descriptor.md).
|
||||
Runtime capabilities describe how MSD projects its artefacts onto one host CLI. The body is a closed 8-axis (plus 4 install-surface) vocabulary; no feature-only fields (`skills`, `agents`, `steps`, `contributions`, `gates`, `hooks`) are permitted. Full semantic specifications, the closed enum values for each axis, and the 16-runtime worked examples are in [ADR-1016](../adr/1016-runtime-capability-descriptor.md).
|
||||
|
||||
| Axis | Field | Type summary |
|
||||
|---|---|---|
|
||||
| Config home | `runtime.configHome` | Structured object with `kind` (`dot-home` \| `dot-home-nested` \| `xdg` \| `generic-agents-root`), `name`, optional `parent`, `env[]`, `probe[]`, `probeExists`, `skillsHome`. `probeExists` is an optional sub-path applied to probe candidates: for `generic-agents-root` it is a hard filter (a candidate qualifies only if `<candidate>/<probeExists>` exists); for `dot-home-nested` it is a preference that makes probing pick the candidate GSD owns (e.g. `gsd-core/VERSION`) over a bare-existing sibling before falling back — see ADR-1016 and #213/#217. |
|
||||
| Local config dir | `runtime.localConfigDir` | Required dot-prefixed string. The runtime's **local** content-rewrite directory — the `./` target GSD stamps into rewritten artefact bodies (e.g. `./.claude/` → `./<localConfigDir>/`) and the local install dir basename. Backs `getDirName()` (registry-derived, #1679). Usually `.<runtime>` (the runtime's home dot-dir), but **three runtimes diverge** because they read GSD's content from a non-home directory: `copilot` → `.github` (GitHub Copilot reads custom instructions from `.github/copilot-instructions.md` / `.github/instructions/`; see `convertClaudeToCopilotContent` rewrites in `src/runtime-artifact-conversion.cts`), `antigravity` → `.agents` (local agent/workflow dir; see the antigravity rewrites in `src/runtime-artifact-conversion.cts`), `kimi` → `.kimi-code`. Distinct from `configHome.name` (the **global** install home, which for these three is `.copilot` / `antigravity` / `agents`). Byte-parity-proven against the prior hand-maintained mapping by the golden-install-parity harness. |
|
||||
| Config home | `runtime.configHome` | Structured object with `kind` (`dot-home` \| `dot-home-nested` \| `xdg` \| `generic-agents-root`), `name`, optional `parent`, `env[]`, `probe[]`, `probeExists`, `skillsHome`. `probeExists` is an optional sub-path applied to probe candidates: for `generic-agents-root` it is a hard filter (a candidate qualifies only if `<candidate>/<probeExists>` exists); for `dot-home-nested` it is a preference that makes probing pick the candidate MSD owns (e.g. `msd-core/VERSION`) over a bare-existing sibling before falling back — see ADR-1016 and #213/#217. |
|
||||
| Local config dir | `runtime.localConfigDir` | Required dot-prefixed string. The runtime's **local** content-rewrite directory — the `./` target MSD stamps into rewritten artefact bodies (e.g. `./.claude/` → `./<localConfigDir>/`) and the local install dir basename. Backs `getDirName()` (registry-derived, #1679). Usually `.<runtime>` (the runtime's home dot-dir), but **three runtimes diverge** because they read MSD's content from a non-home directory: `copilot` → `.github` (GitHub Copilot reads custom instructions from `.github/copilot-instructions.md` / `.github/instructions/`; see `convertClaudeToCopilotContent` rewrites in `src/runtime-artifact-conversion.cts`), `antigravity` → `.agents` (local agent/workflow dir; see the antigravity rewrites in `src/runtime-artifact-conversion.cts`), `kimi` → `.kimi-code`. Distinct from `configHome.name` (the **global** install home, which for these three is `.copilot` / `antigravity` / `agents`). Byte-parity-proven against the prior hand-maintained mapping by the golden-install-parity harness. |
|
||||
| Config format | `runtime.configFormat` | Closed enum: `settings-json` \| `toml` \| `markdown` \| `markdown-dir` \| `none`. |
|
||||
| Artefact layout | `runtime.artifactLayout` | Object with `global` and `local` arrays of `ArtifactKind` (`kind`, `destSubpath`, `prefix`, `nesting`, `recursive`, `stage`). |
|
||||
| Command style | `runtime.commandStyle` | Closed enum: `slash-hyphen` \| `shell-var`. |
|
||||
@@ -188,7 +188,7 @@ Runtime capabilities describe how GSD projects its artefacts onto one host CLI.
|
||||
|
||||
### `hostBehaviors`
|
||||
|
||||
`runtime.hostBehaviors` is a **closed vocabulary** of per-host behavior switches consumed directly by installer and runtime-adaptation code. A key outside the vocabulary is **ignored, with a non-fatal warning** naming the capability and the key; it is never a validation error, so a manifest authored against a newer GSD degrades visibly instead of failing the build of a repo that merely reads it.
|
||||
`runtime.hostBehaviors` is a **closed vocabulary** of per-host behavior switches consumed directly by installer and runtime-adaptation code. A key outside the vocabulary is **ignored, with a non-fatal warning** naming the capability and the key; it is never a validation error, so a manifest authored against a newer MSD degrades visibly instead of failing the build of a repo that merely reads it.
|
||||
|
||||
Adding a key is a reviewed first-party change, which is [ADR-1016](../adr/1016-runtime-capability-descriptor.md)'s intended friction rather than an obstacle: the runtime descriptor expresses every per-host difference as a value over a closed vocabulary, and a host needing a new shape gets a named primitive rather than an open escape hatch.
|
||||
|
||||
@@ -202,8 +202,8 @@ The vocabulary holds 59 keys; 39 of them are set by exactly one capability. This
|
||||
| `skipSharedHooksInstall` | 8 |
|
||||
| `frontmatterDialect` | 5 |
|
||||
| `hyphenNameAgentBody` | 3 |
|
||||
| `legacyCommandsGsdInstallMigration` | 3 |
|
||||
| `legacyCommandsGsdUninstall` | 3 |
|
||||
| `legacyCommandsMsdInstallMigration` | 3 |
|
||||
| `legacyCommandsMsdUninstall` | 3 |
|
||||
| `nativePlugin` | 3 |
|
||||
| `skipUpdateBannerCommand` | 3 |
|
||||
| `verificationStyle` | 3 |
|
||||
@@ -220,16 +220,16 @@ For a minimal `role: "runtime"` example, see [ADR-1016 §Decision 8](../adr/1016
|
||||
|
||||
## Reviewer body (`role: "reviewer"`, or on any role)
|
||||
|
||||
[ADR-2782](../adr/2782-reviewer-lane-capability-surface.md) introduces the *reviewer lane*: one external CLI or model endpoint that `/gsd-review` hands a plan to for independent review.
|
||||
[ADR-2782](../adr/2782-reviewer-lane-capability-surface.md) introduces the *reviewer lane*: one external CLI or model endpoint that `/msd-review` hands a plan to for independent review.
|
||||
|
||||
To declare one, follow [Ship a reviewer lane in your capability](../how-to/ship-a-reviewer-lane.md). This section is the field reference behind that guide.
|
||||
|
||||
The `reviewer` body is **optional and absent-safe at every layer**. A capability with no `reviewer` body is simply not a lane — that is never a validation error. This is a normative forward/backward-compatibility invariant, not a nicety: a plugin, a runtime, or a future GSD version may omit `reviewer` entirely with no consequence.
|
||||
The `reviewer` body is **optional and absent-safe at every layer**. A capability with no `reviewer` body is simply not a lane — that is never a validation error. This is a normative forward/backward-compatibility invariant, not a nicety: a plugin, a runtime, or a future MSD version may omit `reviewer` entirely with no consequence.
|
||||
|
||||
The shape is **hybrid**:
|
||||
|
||||
- A `reviewer` body is admissible on `role: "runtime"`, so an existing runtime capability — `codex`, `antigravity` — keeps **one** manifest that is both an installable runtime and a reviewer lane.
|
||||
- A third role, `role: "reviewer"`, exists for lane-only CLIs that GSD never installs into. There are currently 5: `coderabbit`, `gemini`, `llama-cpp`, `lm-studio`, `ollama`.
|
||||
- A third role, `role: "reviewer"`, exists for lane-only CLIs that MSD never installs into. There are currently 5: `coderabbit`, `gemini`, `llama-cpp`, `lm-studio`, `ollama`.
|
||||
|
||||
Current role counts across `capabilities/`: `feature` 20, `runtime` 19, `reviewer` 5.
|
||||
|
||||
@@ -256,7 +256,7 @@ All 12 shipped lane declarations carry all 14 fields below.
|
||||
|
||||
Uniqueness is enforced across the merged first-party ∪ overlay set: duplicate `slug`, duplicate `flags` entry, and duplicate `reviewsSection` are each build-time violations. Two lanes sharing a `reviewsSection` heading would silently merge their output in `REVIEWS.md`, producing apparent consensus that does not exist.
|
||||
|
||||
An unknown field inside a `reviewer` body is a **non-fatal warning on stderr, never a build failure** ([ADR-2782](../adr/2782-reviewer-lane-capability-surface.md) D4), so a manifest built against a newer GSD degrades visibly rather than crashing.
|
||||
An unknown field inside a `reviewer` body is a **non-fatal warning on stderr, never a build failure** ([ADR-2782](../adr/2782-reviewer-lane-capability-surface.md) D4), so a manifest built against a newer MSD degrades visibly rather than crashing.
|
||||
|
||||
### Example — lane-only `role: "reviewer"` capability
|
||||
|
||||
@@ -266,10 +266,10 @@ An unknown field inside a `reviewer` body is a **non-fatal warning on stderr, ne
|
||||
"role": "reviewer",
|
||||
"version": "1.8.0",
|
||||
"title": "CodeRabbit",
|
||||
"description": "CodeRabbit CLI — cross-AI /gsd-review reviewer lane only; not a GSD install target (no runtime body, no artifacts).",
|
||||
"description": "CodeRabbit CLI — cross-AI /msd-review reviewer lane only; not a MSD install target (no runtime body, no artifacts).",
|
||||
"tier": "full",
|
||||
"requires": [],
|
||||
"engines": { "gsd": ">=1.8.0" },
|
||||
"engines": { "msd": ">=1.8.0" },
|
||||
"reviewer": {
|
||||
"slug": "coderabbit",
|
||||
"flags": ["--coderabbit"],
|
||||
@@ -311,9 +311,9 @@ The following invariants are enforced at **build time** by `scripts/gen-capabili
|
||||
- **`contribution.into` is a published agent role.** The `into` value must be an agent role declared by the host contract for that loop extension point. The published roles are **family-partitioned** (ADR-894 §3, Amendment 2026-09-14): every role belongs to exactly one of orchestration (`orchestrator`), planning (`researcher`, `planner`, `checker`) or execution (`executor`, `verifier`), and each loop step publishes exactly one family. So `execute:*` publishes `executor`/`verifier` and never `orchestrator`, and `discuss:*`/`verify:*`/`ship:*` publish `orchestrator` and never `executor`/`verifier`. The partition is enforced when the host contract is generated, so the role set a point publishes is stable rather than incidental.
|
||||
- **Config key exclusivity.** A federated config key must be owned by exactly one capability and absent from the central `config-schema`. Presence in both is a collision; a half-migrated key fails the build gate.
|
||||
- **Artefact production uniqueness per point.** No two capability steps may `produces` the same artefact name at the same loop extension point.
|
||||
- **`engines.gsd` is a hard gate.** A capability whose `engines.gsd` range does not satisfy the installed GSD version is blocked at install and skipped (with a warning) at load time.
|
||||
- **`engines.msd` is a hard gate.** A capability whose `engines.msd` range does not satisfy the installed MSD version is blocked at install and skipped (with a warning) at load time.
|
||||
- **Path confinement.** Declared module paths may not use parent-directory traversal (`../`); modules are `require()`'d only from the capability's own install root.
|
||||
- **Reserved namespace.** Capability `id` values beginning with `gsd-`, `gsd-core-`, or `anthropic-` are reserved; third-party capabilities using these prefixes are rejected.
|
||||
- **Reserved namespace.** Capability `id` values beginning with `msd-`, `msd-core-`, or `anthropic-` are reserved; third-party capabilities using these prefixes are rejected.
|
||||
- **`taskContentResolver.trackerPrefix` uniqueness, feature-only.** `trackerPrefix` must be unique across the merged first-party ∪ overlay capability set (mirrors `reviewsSection` uniqueness on the reviewer body above); a collision is a build-time violation. `taskContentResolver` is admissible only on `role: "feature"` bodies.
|
||||
|
||||
---
|
||||
@@ -331,10 +331,10 @@ The following is the canonical UI design-contract capability from ADR-894. It il
|
||||
"description": "UI-SPEC design contract and retrospective UI audit for frontend phases.",
|
||||
"tier": "standard",
|
||||
"requires": [],
|
||||
"engines": { "gsd": ">=1.6.0" },
|
||||
"engines": { "msd": ">=1.6.0" },
|
||||
"runtimeCompat": { "supported": ["*"], "unsupported": [] },
|
||||
"skills": ["ui-phase", "ui-review"],
|
||||
"agents": ["gsd-ui-checker", "gsd-ui-auditor"],
|
||||
"agents": ["msd-ui-checker", "msd-ui-auditor"],
|
||||
"hooks": [],
|
||||
"config": {
|
||||
"workflow.ui_phase": {
|
||||
|
||||
@@ -18,28 +18,28 @@ See also: [ADR-1244](../adr/1244-capability-ecosystem.md) —
|
||||
|
||||
| Column | Description |
|
||||
|---|---|
|
||||
| **id** | Canonical capability identifier; unique across first- and third-party capabilities. Reserved prefixes: `gsd-`, `gsd-core-`, `anthropic-`. |
|
||||
| **role** | `feature` — extends what the loop does; `runtime` — adapts GSD to a specific AI runtime/IDE; `reviewer` — declares a cross-AI reviewer lane (ADR-2782). A capability may be both a runtime and a reviewer. |
|
||||
| **id** | Canonical capability identifier; unique across first- and third-party capabilities. Reserved prefixes: `msd-`, `msd-core-`, `anthropic-`. |
|
||||
| **role** | `feature` — extends what the loop does; `runtime` — adapts MSD to a specific AI runtime/IDE; `reviewer` — declares a cross-AI reviewer lane (ADR-2782). A capability may be both a runtime and a reviewer. |
|
||||
| **tier** | `core` — always active; `standard` — active when the runtime supports it; `full` — opt-in or runtime-specific. |
|
||||
| **engines.gsd** | Semver RANGE expressing host-version compatibility. A hard gate at install and at load. `—` means the capability declares no range. |
|
||||
| **engines.msd** | Semver RANGE expressing host-version compatibility. A hard gate at install and at load. `—` means the capability declares no range. |
|
||||
| **extension points** | The loop points this capability registers hooks into (from the registry's `byLoopPoint` index). `—` means it registers none (typical for runtime capabilities, whose job is surface emission). |
|
||||
| **hook kinds** | Which of `step`, `contribution`, `gate` the capability's hooks use. `—` means none. |
|
||||
| **source** | `first-party` — ships with GSD Core; `third-party` — installed from an external source via `gsd capability install`. |
|
||||
| **source** | `first-party` — ships with MSD Core; `third-party` — installed from an external source via `msd capability install`. |
|
||||
|
||||
> **On versions.** This matrix intentionally omits a per-capability `version`
|
||||
> column. First-party capabilities are versioned **in lockstep** with the GSD
|
||||
> Core package (their `capability.json` `version` always equals the GSD release
|
||||
> column. First-party capabilities are versioned **in lockstep** with the MSD
|
||||
> Core package (their `capability.json` `version` always equals the MSD release
|
||||
> version), so a per-row version would simply repeat the package version and
|
||||
> churn the committed file on every release. The stable host-compatibility
|
||||
> signal — `engines.gsd` — is shown instead. A third-party capability's exact
|
||||
> version is recorded in the per-runtime ledger (`.gsd-capabilities.json`) at
|
||||
> signal — `engines.msd` — is shown instead. A third-party capability's exact
|
||||
> version is recorded in the per-runtime ledger (`.msd-capabilities.json`) at
|
||||
> install time.
|
||||
|
||||
---
|
||||
|
||||
## Native (first-party) capabilities
|
||||
|
||||
First-party capabilities are implicitly trusted: they ship as part of the GSD
|
||||
First-party capabilities are implicitly trusted: they ship as part of the MSD
|
||||
Core package and are stamped with the package version at release (per
|
||||
ADR-1244 D6). They are not subject to the consent or integrity-pin flow applied
|
||||
to third-party capabilities.
|
||||
@@ -50,7 +50,7 @@ Feature capabilities extend what the loop does — contributing research,
|
||||
planning, execution, verification, or ship artefacts at the loop extension
|
||||
points.
|
||||
|
||||
| id | role | tier | engines.gsd | extension points | hook kinds | source |
|
||||
| id | role | tier | engines.msd | extension points | hook kinds | source |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `ai-integration` | feature | full | `>=1.6.0` | `plan:pre`, `verify:pre` | step, contribution, gate | first-party |
|
||||
| `assumption-delta` | feature | full | `>=1.6.0` | `plan:pre` | contribution | first-party |
|
||||
@@ -77,12 +77,12 @@ points.
|
||||
|
||||
### Runtime capabilities (role: runtime) — 19
|
||||
|
||||
Runtime capabilities adapt GSD to a specific AI runtime or IDE — emitting
|
||||
Runtime capabilities adapt MSD to a specific AI runtime or IDE — emitting
|
||||
skills, agents, hooks configuration, and surface files for that host. They
|
||||
typically register no loop hooks (their primary responsibility is surface
|
||||
emission), so their extension-point and hook-kind cells are `—`.
|
||||
|
||||
| id | role | tier | engines.gsd | extension points | hook kinds | source |
|
||||
| id | role | tier | engines.msd | extension points | hook kinds | source |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `antigravity` | runtime | core | `>=1.6.0` | — | — | first-party |
|
||||
| `augment` | runtime | core | `>=1.6.0` | — | — | first-party |
|
||||
@@ -107,19 +107,19 @@ emission), so their extension-point and hook-kind cells are `—`.
|
||||
### Reviewer capabilities (role: reviewer) — 4
|
||||
|
||||
Reviewer capabilities declare a cross-AI **reviewer lane** — one external CLI or
|
||||
model endpoint `/gsd-review` hands a plan to (ADR-2782 D3). They are not install
|
||||
model endpoint `/msd-review` hands a plan to (ADR-2782 D3). They are not install
|
||||
targets: they emit no skills, agents, hooks or surface files, so their
|
||||
extension-point and hook-kind cells are `—`. A host that is *also* a reviewer
|
||||
(Claude, Codex, Cursor, OpenCode, Qwen, Antigravity) keeps one manifest and
|
||||
appears under **runtime** above, carrying its lane alongside its runtime body;
|
||||
only lanes that GSD never installs into appear here.
|
||||
only lanes that MSD never installs into appear here.
|
||||
|
||||
Because a lane receives the plan text, requirements, research findings and
|
||||
`CONTEXT.md` decisions, it is a disclosed executable surface and is consent-gated
|
||||
at install like any other — see
|
||||
[the trust model](../explanation/capability-trust-model.md).
|
||||
|
||||
| id | role | tier | engines.gsd | extension points | hook kinds | source |
|
||||
| id | role | tier | engines.msd | extension points | hook kinds | source |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `coderabbit` | reviewer | full | `>=1.8.0` | — | — | first-party |
|
||||
| `llama-cpp` | reviewer | full | `>=1.8.0` | — | — | first-party |
|
||||
@@ -131,12 +131,12 @@ at install like any other — see
|
||||
## Third-party capabilities
|
||||
|
||||
This matrix is the **first-party catalogue**: it is generated from the committed
|
||||
registry and therefore lists only the capabilities that ship with GSD Core.
|
||||
registry and therefore lists only the capabilities that ship with MSD Core.
|
||||
Installed third-party capabilities are NOT written into this committed file. Once a
|
||||
user installs one via `gsd capability install <spec>` it enters the **runtime
|
||||
user installs one via `msd capability install <spec>` it enters the **runtime
|
||||
registry overlay** (ADR-1244 D2); the overlay-aware view of what is installed on a
|
||||
given machine is `gsd capability list` (see the
|
||||
[`gsd capability` command reference](gsd-capability-command.md)), which reports
|
||||
given machine is `msd capability list` (see the
|
||||
[`msd capability` command reference](msd-capability-command.md)), which reports
|
||||
first-party and installed third-party capabilities together using the same column
|
||||
fields described below, with `source` = `third-party`.
|
||||
|
||||
@@ -144,17 +144,17 @@ fields described below, with `source` = `third-party`.
|
||||
|
||||
| Column | Value |
|
||||
|---|---|
|
||||
| **id** | As declared in `capability.json`. Must not use reserved prefixes (`gsd-`, `gsd-core-`, `anthropic-`). |
|
||||
| **id** | As declared in `capability.json`. Must not use reserved prefixes (`msd-`, `msd-core-`, `anthropic-`). |
|
||||
| **role** | `feature`, `runtime`, or `reviewer`, as declared. |
|
||||
| **tier** | `core`, `standard`, or `full`, as declared. |
|
||||
| **engines.gsd** | Range from `capability.json`; verified at install and at each load. |
|
||||
| **engines.msd** | Range from `capability.json`; verified at install and at each load. |
|
||||
| **extension points** | The loop points the capability registers into, validated against the known 12 identifiers. |
|
||||
| **hook kinds** | `step`, `contribution`, and/or `gate` as declared. Disclosed in the consent summary at install. |
|
||||
| **source** | `third-party` |
|
||||
|
||||
### Community registry
|
||||
|
||||
Whether GSD operates or advertises a central community registry of third-party
|
||||
Whether MSD operates or advertises a central community registry of third-party
|
||||
capabilities is **TBD/TBA** (PRD). The matrix mechanic and all manifest fields
|
||||
ship regardless of that decision; URL/git/npm/tarball import does not depend on
|
||||
a central registry.
|
||||
@@ -171,8 +171,8 @@ and the [capability manifest reference](capability-manifest.md).
|
||||
| Field | Required | Type | Purpose |
|
||||
|---|---|---|---|
|
||||
| `version` | **Yes** | semver string | Capability version. The registry rejects manifests without it. |
|
||||
| `engines.gsd` | Recommended | semver range | Host-version compatibility gate. Enforced at install and load. |
|
||||
| `compatVersions` | No | object: cap-version → gsd-range | Graceful-downgrade table for sources that enumerate versions (git tags, registry, npm). |
|
||||
| `engines.msd` | Recommended | semver range | Host-version compatibility gate. Enforced at install and load. |
|
||||
| `compatVersions` | No | object: cap-version → msd-range | Graceful-downgrade table for sources that enumerate versions (git tags, registry, npm). |
|
||||
| `integrity` | No | `sha512-<base64>` | SHA-512 digest of the fetched bundle. Verified before extraction when present; mismatch aborts. |
|
||||
| `provenance` | No | `{ sourceRepo, commit }` | Source provenance; populated in CI for first-party/curated capabilities. |
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# CONTEXT.md schema reference
|
||||
|
||||
A per-phase `CONTEXT.md` is GSD Core's carrier for implementation decisions captured during `/gsd-discuss-phase`. It is the primary upstream input for both the research and planning agents. This page documents its structure. See [docs index](../README.md).
|
||||
A per-phase `CONTEXT.md` is MSD Core's carrier for implementation decisions captured during `/msd-discuss-phase`. It is the primary upstream input for both the research and planning agents. This page documents its structure. See [docs index](../README.md).
|
||||
|
||||
---
|
||||
|
||||
@@ -14,7 +14,7 @@ Every phase that has been through the discuss workflow produces one `CONTEXT.md`
|
||||
|
||||
For example: `.planning/phases/03-post-feed/03-CONTEXT.md`.
|
||||
|
||||
The file is produced by `write_context` in `gsd-core/workflows/discuss-phase.md` (or its PRD / ADR ingest express paths). It is never edited by hand during normal operation — the discuss-phase workflow writes it and downstream agents read it as a sealed source of truth.
|
||||
The file is produced by `write_context` in `msd-core/workflows/discuss-phase.md` (or its PRD / ADR ingest express paths). It is never edited by hand during normal operation — the discuss-phase workflow writes it and downstream agents read it as a sealed source of truth.
|
||||
|
||||
---
|
||||
|
||||
@@ -39,12 +39,12 @@ The body is divided into named XML-style blocks. The blocks appear in a fixed or
|
||||
|
||||
| Block | Purpose | Populated by | Consumed by |
|
||||
|---|---|---|---|
|
||||
| `<domain>` | States the phase boundary — what this phase delivers and what is explicitly out of scope. Anchors the scope guardrail throughout planning and execution. | `discuss-phase` (from ROADMAP.md phase goal) | `gsd-planner`, `gsd-plan-checker` (scope compliance) |
|
||||
| `<spec_lock>` | Present only when a `*-SPEC.md` was found by the `check_spec` step. Lists locked requirement counts and scope boundaries; agents are directed to read `SPEC.md` directly for full requirements. | `discuss-phase` (conditional) | `gsd-planner` (reads SPEC.md rather than re-reading requirements here) |
|
||||
| `<decisions>` | Implementation decisions captured from the discussion, keyed with `D-NN` identifiers. Categories emerge from what was actually discussed rather than a fixed taxonomy. Includes a `Claude's Discretion` sub-section for areas the user delegated. | `discuss-phase` (interactive discussion) | `gsd-planner` (locked decisions must be implemented), `gsd-plan-checker` (Dimension 7 compliance) |
|
||||
| `<canonical_refs>` | Full relative paths to every spec, ADR, feature doc, or design doc relevant to this phase. Mandatory — every CONTEXT.md must have this section. Agents must read listed files before planning or implementing. | `discuss-phase` (accumulated from ROADMAP.md refs + user references during discussion + codebase scout) | `gsd-phase-researcher`, `gsd-planner` |
|
||||
| `<code_context>` | Reusable assets, established patterns, and integration points discovered during the `scout_codebase` step. Guides agents towards existing code rather than re-implementing. | `discuss-phase` (codebase scout) | `gsd-planner`, `gsd-phase-researcher` |
|
||||
| `<specifics>` | Concrete "I want it like X" references, product comparisons, or particular examples captured verbatim during discussion. | `discuss-phase` (freeform user input) | `gsd-planner` |
|
||||
| `<domain>` | States the phase boundary — what this phase delivers and what is explicitly out of scope. Anchors the scope guardrail throughout planning and execution. | `discuss-phase` (from ROADMAP.md phase goal) | `msd-planner`, `msd-plan-checker` (scope compliance) |
|
||||
| `<spec_lock>` | Present only when a `*-SPEC.md` was found by the `check_spec` step. Lists locked requirement counts and scope boundaries; agents are directed to read `SPEC.md` directly for full requirements. | `discuss-phase` (conditional) | `msd-planner` (reads SPEC.md rather than re-reading requirements here) |
|
||||
| `<decisions>` | Implementation decisions captured from the discussion, keyed with `D-NN` identifiers. Categories emerge from what was actually discussed rather than a fixed taxonomy. Includes a `Claude's Discretion` sub-section for areas the user delegated. | `discuss-phase` (interactive discussion) | `msd-planner` (locked decisions must be implemented), `msd-plan-checker` (Dimension 7 compliance) |
|
||||
| `<canonical_refs>` | Full relative paths to every spec, ADR, feature doc, or design doc relevant to this phase. Mandatory — every CONTEXT.md must have this section. Agents must read listed files before planning or implementing. | `discuss-phase` (accumulated from ROADMAP.md refs + user references during discussion + codebase scout) | `msd-phase-researcher`, `msd-planner` |
|
||||
| `<code_context>` | Reusable assets, established patterns, and integration points discovered during the `scout_codebase` step. Guides agents towards existing code rather than re-implementing. | `discuss-phase` (codebase scout) | `msd-planner`, `msd-phase-researcher` |
|
||||
| `<specifics>` | Concrete "I want it like X" references, product comparisons, or particular examples captured verbatim during discussion. | `discuss-phase` (freeform user input) | `msd-planner` |
|
||||
| `<deferred>` | Ideas that arose in discussion but belong in other phases. Preserved so they are not lost. Includes a `Reviewed Todos` sub-section when todos were reviewed but not folded into scope. | `discuss-phase` (scope-creep redirect) | Not consumed by automated agents; human reference only |
|
||||
|
||||
---
|
||||
@@ -116,7 +116,7 @@ A CONTEXT.md where decisions survive into plans is considered compliant. A CONTE
|
||||
|
||||
## SPEC.md integration
|
||||
|
||||
When `/gsd-spec-phase` has been run before discussing a phase, the `check_spec` step finds the `*-SPEC.md` file and activates `<spec_lock>`:
|
||||
When `/msd-spec-phase` has been run before discussing a phase, the `check_spec` step finds the `*-SPEC.md` file and activates `<spec_lock>`:
|
||||
|
||||
```markdown
|
||||
<spec_lock>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> **Generated file — do not edit by hand.**
|
||||
> This page is generated from the exit-code declaration
|
||||
> (`gsd-core/bin/shared/exit-codes.json`) by `scripts/gen-exit-code-docs.cjs`
|
||||
> (`msd-core/bin/shared/exit-codes.json`) by `scripts/gen-exit-code-docs.cjs`
|
||||
> and kept honest by a drift guard in `npm run lint:generated-sync` (which runs
|
||||
> `node scripts/gen-exit-code-docs.cjs --check`). Any manual edit is overwritten
|
||||
> on the next generation run. To register a new code, add an entry to the
|
||||
@@ -17,7 +17,7 @@ See also: [ADR-3889 — one exit-code registry](../adr/3889-process-exit-contrac
|
||||
|
||||
## Registered codes (6)
|
||||
|
||||
Every process-level exit code `gsd-tools`, its hooks, and its scripts may terminate
|
||||
Every process-level exit code `msd-tools`, its hooks, and its scripts may terminate
|
||||
with, by name, meaning, and the module that owns it.
|
||||
|
||||
| code | name | meaning | owning module | authorized by |
|
||||
@@ -27,7 +27,7 @@ with, by name, meaning, and the module that owns it.
|
||||
| 66 | `NO_INPUT` | Ran; zero units were in scope, and that emptiness is known to be genuine | `generic` | ADR-3889 |
|
||||
| 69 | `UNAVAILABLE` | Could not run — prerequisite absent, input unreadable, scope unestablished | `generic` | ADR-3889 |
|
||||
| 70 | `INTERNAL` | Self-failure — crash, timeout, killed subprocess | `generic` | ADR-3889 |
|
||||
| 80 | `DEGRADED` | Ran to completion and is reporting a condition through its result payload rather than as a process failure | `gsd-tools` | ADR-3889 + ADR-2980 |
|
||||
| 80 | `DEGRADED` | Ran to completion and is reporting a condition through its result payload rather than as a process failure | `msd-tools` | ADR-3889 + ADR-2980 |
|
||||
|
||||
---
|
||||
|
||||
@@ -43,10 +43,10 @@ band first, then its registered name if it has one.
|
||||
|---|---|
|
||||
| `0`–`1` | **Free — never allocatable.** `0` is the universal "succeeded" convention and `1` is the universal "failed, no further detail" convention across nearly every CLI ecosystem. Registering either here would collide with that universal meaning instead of adding a distinct, named signal — so the registry leaves both permanently unallocated. |
|
||||
| `2` | Reserved exclusively to the Claude Code hook-protocol deny (`HOOK_DENY`) — owned by `hook-adapter` and no other module. |
|
||||
| `3`–`13` | **Node-reserved.** Node.js itself assigns meaning to this range (e.g. internal JavaScript errors, fatal exceptions, invalid argument errors) before a GSD process ever gets a chance to project its own outcome. Allocating one of these would be indistinguishable from a Node-level failure the process never intended to report. |
|
||||
| `14`–`63`, `79`, `126+` | Outside every allocatable band — not Node-reserved, but also not opened for GSD use. `126`+ additionally collides with the shell convention for "command not executable" / "signal N" (`128+N`), which a process exit code must never impersonate. |
|
||||
| `3`–`13` | **Node-reserved.** Node.js itself assigns meaning to this range (e.g. internal JavaScript errors, fatal exceptions, invalid argument errors) before a MSD process ever gets a chance to project its own outcome. Allocating one of these would be indistinguishable from a Node-level failure the process never intended to report. |
|
||||
| `14`–`63`, `79`, `126+` | Outside every allocatable band — not Node-reserved, but also not opened for MSD use. `126`+ additionally collides with the shell convention for "command not executable" / "signal N" (`128+N`), which a process exit code must never impersonate. |
|
||||
| `64`–`78` | **Generic band.** Codes any module may use for caller-facing, non-domain-specific outcomes (bad argv, no input in scope, a missing prerequisite, an internal crash). |
|
||||
| `80`–`125` | **Domain band.** Codes reserved for a specific product surface's own vocabulary — currently only `gsd-tools`' `DEGRADED` (a completed run reporting a condition through its payload rather than as a process failure). |
|
||||
| `80`–`125` | **Domain band.** Codes reserved for a specific product surface's own vocabulary — currently only `msd-tools`' `DEGRADED` (a completed run reporting a condition through its payload rather than as a process failure). |
|
||||
|
||||
## The v1/v2 exit contract
|
||||
|
||||
|
||||
@@ -35,12 +35,12 @@ contract documented in ADR-0894 (capability declaration format) and the
|
||||
|
||||
## Evaluation path
|
||||
|
||||
1. The loop-resolver (`gsd-tools loop render-hooks <point>`) renders the active
|
||||
1. The loop-resolver (`msd-tools loop render-hooks <point>`) renders the active
|
||||
gate hook (including its `check.predicate` declaration) to the workflow.
|
||||
2. The workflow gate-dispatch reads the hook in-context and, when the `check`
|
||||
shape is `predicate`, runs:
|
||||
```bash
|
||||
gsd_run check predicate --predicate '<predicate JSON>' [--phase-dir …] [--phase-number …] [--phase-req-ids …] --raw
|
||||
msd_run check predicate --predicate '<predicate JSON>' [--phase-dir …] [--phase-number …] [--phase-req-ids …] --raw
|
||||
```
|
||||
3. `check-command-router.cts:cmdCheckPredicate` parses the predicate, builds the
|
||||
production subprocess binding, and calls
|
||||
@@ -93,7 +93,7 @@ absolute is not a synonym for escaping. `${PHASE_DIR}` always interpolates the
|
||||
value — a command relying on `${PHASE_DIR}` staying relative must not assume
|
||||
that.
|
||||
|
||||
**Sandbox.** cwd = project root; env = inherited from the GSD process; killed
|
||||
**Sandbox.** cwd = project root; env = inherited from the MSD process; killed
|
||||
(SIGTERM) on timeout. The command runs as the user, on the user's machine —
|
||||
there is no sandbox boundary vs. the user's own shell. See ADR-2008 "Trust
|
||||
model".
|
||||
@@ -145,7 +145,7 @@ Reads a Markdown file with YAML frontmatter from the current phase directory (or
|
||||
The evaluator dispatches through a `KIND_TABLE`. Adding a new built-in kind is
|
||||
a one-line registration in `gate-predicate-evaluator.cts` — no workflow changes
|
||||
required, since the workflow dispatches any `check.predicate` to the same
|
||||
`gsd_run check predicate` subcommand.
|
||||
`msd_run check predicate` subcommand.
|
||||
|
||||
## Related
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ consumed verbatim by `gen:capability-registry` and validated by `capability-vali
|
||||
first) is declared as a sibling of `hostIntegration` in `capability.json`'s `runtime` body, not
|
||||
inside it — it is not researched per-CLI documentation the way the axes above are, so it carries
|
||||
no per-host `Source`/`Evidence` row. Only `commands` and `skills` are members of the vocabulary;
|
||||
`agents`/`kimi-agents` are excluded because they are not trigger-bearing (a `/gsd-<name>` a user
|
||||
`agents`/`kimi-agents` are excluded because they are not trigger-bearing (a `/msd-<name>` a user
|
||||
types) — an agent is invoked through named/`subagent_type` dispatch, the separate `dispatch`
|
||||
interface point above, never through the `command` interface point. Every shipped runtime
|
||||
descriptor declares the same value, `["skills", "commands"]` (skills wins a same-scope collision),
|
||||
@@ -63,7 +63,7 @@ required-with-default (absence resolves to that default) so a third-party descri
|
||||
before this phase keeps validating unchanged. `runtime-artifact-layout.cts`'s
|
||||
`resolveTriggerSurface` reads it to decide the winner among same-trigger candidates once scope
|
||||
rank (Install Scope Module) has already been applied. See CONTEXT.md's Runtime Artifact Layout
|
||||
Module entry and `.gsd/phase/feat-2871-trigger-resolution/40-design.md`.
|
||||
Module entry and `.msd/phase/feat-2871-trigger-resolution/40-design.md`.
|
||||
|
||||
---
|
||||
|
||||
@@ -78,14 +78,14 @@ Module entry and `.gsd/phase/feat-2871-trigger-resolution/40-design.md`.
|
||||
| stateIO | filesystem | https://code.claude.com/docs/en/sandboxing | "The sandboxed Bash tool restricts file system access, granting read and write access to the current working directory and session temp direc" |
|
||||
| transport | mcp | https://code.claude.com/docs/en/mcp | "Project-Scoped MCP Server Configuration in .mcp.json ... This JSON structure illustrates the format for a project-scoped MCP server configur" |
|
||||
| runtime | node | https://code.claude.com/docs/en/agent-sdk/typescript | "import { query } from \"@anthropic-ai/claude-agent-sdk\"; ... pathToClaudeCodeExecutable (string) - Specifies the path to the Claude Code CLI" |
|
||||
| effortSurface | argv | https://code.claude.com/docs/en/cli-reference ; `claude --help` | `--effort <level>` is a documented flag on the host's own invocation, so GSD renders the resolved universal effort straight onto the argv it spawns (#2481). |
|
||||
| effortSurface | argv | https://code.claude.com/docs/en/cli-reference ; `claude --help` | `--effort <level>` is a documented flag on the host's own invocation, so MSD renders the resolved universal effort straight onto the argv it spawns (#2481). |
|
||||
| dispatch.namedDispatch | true | https://code.claude.com/docs/en/agent-sdk/subagents | "agents: { 'code-reviewer': AgentDefinition({ description: 'Expert code reviewer.', ... }) } ... subagent_type: block.inp" |
|
||||
| dispatch.nested | true | https://code.claude.com/docs/en/sub-agents | "As of Claude Code v2.1.172, a subagent can spawn its own subagents, allowing delegated tasks to split into parallel subt" |
|
||||
| dispatch.maxDepth | 5 | https://code.claude.com/docs/en/sub-agents | "foreground subagents can spawn at any depth, blocking their parent until completion. Background subagents are limited to" |
|
||||
| dispatch.background | true | https://code.claude.com/docs/en/sub-agents | "Subagents can run in the foreground, blocking the main conversation and passing permission prompts to you, or in the bac" |
|
||||
| dispatch.subagentToolkit | full | https://code.claude.com/docs/en/sub-agents | "If all tools remain selected, the subagent inherits all tools available to the main conversation." |
|
||||
| dispatch.backgroundDispatch | false | https://code.claude.com/docs/en/sub-agents | "Background subagents are limited to a depth of five and cannot spawn further, " |
|
||||
| dispatch.isolation | harness-worktree | https://code.claude.com/docs/en/sub-agents ; Claude Code Agent tool (`Agent(isolation="worktree")`) | The Claude Code Agent tool accepts an `isolation="worktree"` harness primitive — the host's own harness creates + binds a git worktree per executor; GSD passes the flag and calls no git itself (#2584) |
|
||||
| dispatch.isolation | harness-worktree | https://code.claude.com/docs/en/sub-agents ; Claude Code Agent tool (`Agent(isolation="worktree")`) | The Claude Code Agent tool accepts an `isolation="worktree"` harness primitive — the host's own harness creates + binds a git worktree per executor; MSD passes the flag and calls no git itself (#2584) |
|
||||
| dispatch.maxConcurrency | 20 | https://code.claude.com/docs/en/sub-agents | The subagent documentation states a default concurrent-subagent limit of 20, configurable via the `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS` environment variable (#3673). |
|
||||
|
||||
Sources consulted:
|
||||
@@ -100,7 +100,7 @@ Sources consulted:
|
||||
- Context7 /websites/code_claude
|
||||
- Context7 /llmstxt/code_claude_llms_txt
|
||||
|
||||
**Cross-scope trigger shadowing and spec-root reachability (#2873, epic #2866 Phase 4, resolving #2218).** GSD's claude `artifactLayout` installs `global=[skills]` and `local=[commands, agents]` (see "Trigger precedence" above). Claude Code's own documented precedence — personal overrides project, and a same-named skill overrides a same-named command — means both rules point the same direction when a user installs both scopes: the global skill always wins the `/gsd-<name>` trigger, and the project-local `.claude/gsd-core/` spec tree the local command correctly points at becomes unreachable through that trigger, silently. GSD Core now (a) detects this at install time and from `/gsd-health` (diagnostic `W028`) and prints which scope wins — an advisory only, exit code unchanged; and (b) for claude at **global** scope only, resolves the winning skill's own workflow-spec `@`-include at runtime rather than pre-expanding it: the skill body carries an explicit imperative instruction that resolves `.claude/gsd-core/workflows/<name>.md` relative to the working directory first, falling back to `~/.claude/gsd-core/workflows/<name>.md` when no local tree exists. This is instruction-following, not the guaranteed inclusion a real `@`-include provides — it costs the agent one file read — and is deliberately confined to this one reference, in this one runtime, at this one scope: the skill's `references/`/`templates/` includes and the local scope's own emission are unchanged. See [Interpret install-shadow warnings](../how-to/interpret-install-shadow-warnings.md) and [Install on your runtime — Claude Code](../how-to/install-on-your-runtime.md#claude-code).
|
||||
**Cross-scope trigger shadowing and spec-root reachability (#2873, epic #2866 Phase 4, resolving #2218).** MSD's claude `artifactLayout` installs `global=[skills]` and `local=[commands, agents]` (see "Trigger precedence" above). Claude Code's own documented precedence — personal overrides project, and a same-named skill overrides a same-named command — means both rules point the same direction when a user installs both scopes: the global skill always wins the `/msd-<name>` trigger, and the project-local `.claude/msd-core/` spec tree the local command correctly points at becomes unreachable through that trigger, silently. MSD Core now (a) detects this at install time and from `/msd-health` (diagnostic `W028`) and prints which scope wins — an advisory only, exit code unchanged; and (b) for claude at **global** scope only, resolves the winning skill's own workflow-spec `@`-include at runtime rather than pre-expanding it: the skill body carries an explicit imperative instruction that resolves `.claude/msd-core/workflows/<name>.md` relative to the working directory first, falling back to `~/.claude/msd-core/workflows/<name>.md` when no local tree exists. This is instruction-following, not the guaranteed inclusion a real `@`-include provides — it costs the agent one file read — and is deliberately confined to this one reference, in this one runtime, at this one scope: the skill's `references/`/`templates/` includes and the local scope's own emission are unchanged. See [Interpret install-shadow warnings](../how-to/interpret-install-shadow-warnings.md) and [Install on your runtime — Claude Code](../how-to/install-on-your-runtime.md#claude-code).
|
||||
|
||||
---
|
||||
|
||||
@@ -124,14 +124,14 @@ Sources consulted:
|
||||
| dispatch.background | true | https://github.com/openai/codex/blob/main/codex-rs/core/src/tools/handlers/multi_agents_spec.rs | "spawn_agent returns the spawned agent id immediately; a separate wait_agent tool polls for final status." |
|
||||
| dispatch.subagentToolkit | full | https://developers.openai.com/codex/multi-agent | "Subagents inherit the sandbox policy and tool surface from the parent session." |
|
||||
| dispatch.backgroundDispatch | true | https://github.com/openai/codex/blob/main/codex-rs/core/templates/collab/experimental_prompt.md | "Sub-agents have access to the same set of tools as you do so you must tell them if they are allowed to spawn sub-agents themselves or not." The config (codex-rs/config/src/config_toml.rs) exposes an |
|
||||
| dispatch.isolation | orchestrator-worktree | https://learn.chatgpt.com/docs/environments/git-worktrees ; https://github.com/openai/codex/blob/main/codex-rs/utils/cli/src/shared_options.rs | "Worktrees are available only in Codex in the ChatGPT desktop app." (no native CLI worktree) + `codex exec --cd <dir>` sets an explicit working root, so GSD creates+manages the worktree and points the executor at it (#2584) |
|
||||
| dispatch.isolation | orchestrator-worktree | https://learn.chatgpt.com/docs/environments/git-worktrees ; https://github.com/openai/codex/blob/main/codex-rs/utils/cli/src/shared_options.rs | "Worktrees are available only in Codex in the ChatGPT desktop app." (no native CLI worktree) + `codex exec --cd <dir>` sets an explicit working root, so MSD creates+manages the worktree and points the executor at it (#2584) |
|
||||
| dispatch.maxConcurrency | undocumented | https://developers.openai.com/codex/config-reference | `agents.max_concurrent_threads_per_session` is a documented config key, but the reference states no numeric default — "Codex chooses the default" — so there is no single value to cite (#3673). |
|
||||
|
||||
**GSD integration status — Phase D dogfood complete (#2088, ADR-1239).** Codex installs through the `declarative` embedding adapter (`createDeclarativeAdapter` → `installRuntimeArtifacts`); the hardcoded `runtime === 'codex'`/`isCodex` projection is folded into descriptor-driven `runtime.hostBehaviors`, and install/uninstall output is byte-parity-gated at the time (`tests/fixtures/golden-install-parity/codex.json`; superseded by the differential attribution check, #2724). Three capability upgrades land, each with a test driving the user-reachable surface:
|
||||
**MSD integration status — Phase D dogfood complete (#2088, ADR-1239).** Codex installs through the `declarative` embedding adapter (`createDeclarativeAdapter` → `installRuntimeArtifacts`); the hardcoded `runtime === 'codex'`/`isCodex` projection is folded into descriptor-driven `runtime.hostBehaviors`, and install/uninstall output is byte-parity-gated at the time (`tests/fixtures/golden-install-parity/codex.json`; superseded by the differential attribution check, #2724). Three capability upgrades land, each with a test driving the user-reachable surface:
|
||||
|
||||
- **Skill root** — global skills install to the canonical `$HOME/.agents/skills` (Codex core-skills `loader.rs` user-scope root), not the deprecated `$CODEX_HOME/skills` fallback; local skills install to `<project>/.codex/skills`. The global path is declared via the global skills-kind `home: ".agents"` override, while the local kind intentionally has no home override. Pre-move global installs are migrated (stale `~/.codex/skills/gsd-*` cleaned on both install and uninstall); local installs do not remove `$HOME/.agents/skills` because those skills may be intentionally global.
|
||||
- **Hook events (corrected #2586)** — GSD registers the `SessionStart` event only, wired to `gsd-check-update.js`. The `SubagentStart`/`Stop`/`PostToolUse` (#772) + six #2088 extended events (`PreToolUse`, `PermissionRequest`, `PreCompact`, `PostCompact`, `SubagentStop`, `UserPromptSubmit`) described in earlier revisions of this doc were routed through `gsd-context-monitor.js`, which reads a remaining-context-percentage bridge file (`${TMPDIR}/claude-ctx-{session_id}.json`) that only `gsd-statusline.js` writes — a Claude-only mechanism Codex never installs. Every one of those events was therefore a guaranteed silent no-op on Codex (confirmed: `readSentinel` throws `ENOENT` on every invocation, unconditionally). #2586 stops copying/registering `gsd-context-monitor.js` on fresh installs and cleans up a pre-#2586 install's stale registrations + orphaned script on reinstall/uninstall. Agent-facing context warnings and GSD phase/lifecycle display are consequently **unsupported on Codex** (`capabilities/codex/capability.json`'s `hostBehaviors.unsupportedFeatures: ["context-warnings","phase-lifecycle-display"]`) — no working warning path existed before this change either, so nothing regresses. Native Codex `/statusline` configuration remains a separate, out-of-scope surface. (The descriptor `extendedHookEvents` field's `SubagentStop`/`Stop`/`PreCompact` value is a pre-existing, unrelated drift against the fuller event set `bin/install.js` used to register — not corrected by #2586.)
|
||||
- **Dispatch tuning** — `[agents] max_depth = 1` is written explicitly into the managed `config.toml` block, pinning the `dispatch.maxDepth: 1` axis instead of relying on codex-cli's implicit default. Because `maxDepth === 1`, `degradationFor` flattens GSD-hosted wave dispatch to single-level even though `dispatch.nested`/`background`/`backgroundDispatch` are all `true`. The block is a bare `[agents]` AgentsToml scalar table; it does **not** carry per-role `[agents.gsd-*]` sub-tables — those pointed `config_file` back at the standalone `agents/gsd-*.toml` files Codex already auto-discovers, so emitting them was a duplicate role registration (Codex logged "Ignoring malformed agent role definition: duplicate agent role name" once per agent) removed in #2406. `validateCodexConfigSchema` permits a known-scalar-only `[agents]` while still rejecting `[[agents]]` and unknown-key forms.
|
||||
- **Skill root** — global skills install to the canonical `$HOME/.agents/skills` (Codex core-skills `loader.rs` user-scope root), not the deprecated `$CODEX_HOME/skills` fallback; local skills install to `<project>/.codex/skills`. The global path is declared via the global skills-kind `home: ".agents"` override, while the local kind intentionally has no home override. Pre-move global installs are migrated (stale `~/.codex/skills/msd-*` cleaned on both install and uninstall); local installs do not remove `$HOME/.agents/skills` because those skills may be intentionally global.
|
||||
- **Hook events (corrected #2586)** — MSD registers the `SessionStart` event only, wired to `msd-check-update.js`. The `SubagentStart`/`Stop`/`PostToolUse` (#772) + six #2088 extended events (`PreToolUse`, `PermissionRequest`, `PreCompact`, `PostCompact`, `SubagentStop`, `UserPromptSubmit`) described in earlier revisions of this doc were routed through `msd-context-monitor.js`, which reads a remaining-context-percentage bridge file (`${TMPDIR}/claude-ctx-{session_id}.json`) that only `msd-statusline.js` writes — a Claude-only mechanism Codex never installs. Every one of those events was therefore a guaranteed silent no-op on Codex (confirmed: `readSentinel` throws `ENOENT` on every invocation, unconditionally). #2586 stops copying/registering `msd-context-monitor.js` on fresh installs and cleans up a pre-#2586 install's stale registrations + orphaned script on reinstall/uninstall. Agent-facing context warnings and MSD phase/lifecycle display are consequently **unsupported on Codex** (`capabilities/codex/capability.json`'s `hostBehaviors.unsupportedFeatures: ["context-warnings","phase-lifecycle-display"]`) — no working warning path existed before this change either, so nothing regresses. Native Codex `/statusline` configuration remains a separate, out-of-scope surface. (The descriptor `extendedHookEvents` field's `SubagentStop`/`Stop`/`PreCompact` value is a pre-existing, unrelated drift against the fuller event set `bin/install.js` used to register — not corrected by #2586.)
|
||||
- **Dispatch tuning** — `[agents] max_depth = 1` is written explicitly into the managed `config.toml` block, pinning the `dispatch.maxDepth: 1` axis instead of relying on codex-cli's implicit default. Because `maxDepth === 1`, `degradationFor` flattens MSD-hosted wave dispatch to single-level even though `dispatch.nested`/`background`/`backgroundDispatch` are all `true`. The block is a bare `[agents]` AgentsToml scalar table; it does **not** carry per-role `[agents.msd-*]` sub-tables — those pointed `config_file` back at the standalone `agents/msd-*.toml` files Codex already auto-discovers, so emitting them was a duplicate role registration (Codex logged "Ignoring malformed agent role definition: duplicate agent role name" once per agent) removed in #2406. `validateCodexConfigSchema` permits a known-scalar-only `[agents]` while still rejecting `[[agents]]` and unknown-key forms.
|
||||
|
||||
Sources consulted:
|
||||
- https://github.com/openai/codex (repo via gh CLI)
|
||||
@@ -170,7 +170,7 @@ Documentation gaps:
|
||||
| dispatch.background | false | https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/effect/runtime-flags.ts ; https://github.com/anomalyco/opencode/issues/29638 | "`experimentalBackgroundSubagents: enabledByExperimental(\"OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS\")` — `enabledByExperimental` falls back to the `experimental` flag, and `bool()` defaults to `false`, so the Task tool's `background` parameter is hidden from the model unless the operator opts in by env var. #29638 (OPEN) confirms the session loop still `tasks.pop()`s one subtask at a time. (#2598 — corrects #2087, whose \"v1.17 default-on in all modes\" reading does not hold against current `dev`)" |
|
||||
| dispatch.subagentToolkit | full | https://opencode.ai/docs/agents | "The 'general' subagent \"Has full tool access (except todo), so it can make file changes when needed.\"" |
|
||||
| dispatch.backgroundDispatch | false | https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/effect/runtime-flags.ts ; https://github.com/anomalyco/opencode/issues/29638 ; https://github.com/anomalyco/opencode/issues/14195 | "Concurrent dispatch requires the opt-in `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS` flag (default `false`), so it cannot be relied on. #14195: \"the session loop does `tasks.pop()` to grab a single subtask, `await`s it, then `continue`s the loop — so even 3 simultaneous Task calls run sequentially.\" Declaring `true` would overstate the capability, against the fail-closed posture negotiation is built for. (#2598 — corrects #2087)" |
|
||||
| dispatch.isolation | orchestrator-worktree | https://opencode.ai/docs/cli ; opencode.ai/docs/plugins ; opencode issues #14195/#29638/#5887 | "`opencode run --dir <path>` sets an explicit working root at the process level" — native subagent dispatch is synchronous-only, so GSD creates + manages the worktree and process-spawns the executor into it via `--dir` (#2584) |
|
||||
| dispatch.isolation | orchestrator-worktree | https://opencode.ai/docs/cli ; opencode.ai/docs/plugins ; opencode issues #14195/#29638/#5887 | "`opencode run --dir <path>` sets an explicit working root at the process level" — native subagent dispatch is synchronous-only, so MSD creates + manages the worktree and process-spawns the executor into it via `--dir` (#2584) |
|
||||
| dispatch.maxConcurrency | undocumented | not researched / no documented concurrent-subagent capacity for this axis | no authoritative source consulted for concurrent-executor capacity on this host — fails closed to `1` in negotiation (#3673) |
|
||||
|
||||
Sources consulted:
|
||||
@@ -219,10 +219,10 @@ Sources consulted:
|
||||
- https://cursor.com/docs/enterprise/llm-safety-and-controls
|
||||
- /websites/cursor (Context7)
|
||||
|
||||
**GSD integration status — Phase D dogfood complete (#2089, ADR-1239).** Cursor installs through the `imperative` embedding adapter (`createImperativeAdapter` → `installRuntimeArtifacts`); the hardcoded `runtime === 'cursor'` / `isCursor` projection is folded into descriptor-driven `runtime.hostBehaviors`, and install/uninstall output is byte-parity-gated at the time (`tests/fixtures/golden-install-parity/cursor.json`; superseded by the differential attribution check, #2724). Two capability upgrades land, each with a test driving the user-reachable surface:
|
||||
**MSD integration status — Phase D dogfood complete (#2089, ADR-1239).** Cursor installs through the `imperative` embedding adapter (`createImperativeAdapter` → `installRuntimeArtifacts`); the hardcoded `runtime === 'cursor'` / `isCursor` projection is folded into descriptor-driven `runtime.hostBehaviors`, and install/uninstall output is byte-parity-gated at the time (`tests/fixtures/golden-install-parity/cursor.json`; superseded by the differential attribution check, #2724). Two capability upgrades land, each with a test driving the user-reachable surface:
|
||||
|
||||
- **Expanded hook-bus coverage** — GSD registers all 6 managed lifecycle events in `hooks.json` beyond the original `sessionStart`/`postToolUse`: `preToolUse`, `stop`, `subagentStart`, `subagentStop` (AC4a, cite https://cursor.com/docs/hooks). The hook-bus binding is descriptor-driven via `src/host-integration-adapters/imperative-hook-bus.cts` (reads `hostBehaviors.managedHookEvents`), not a hardcoded event pair.
|
||||
- **Named/background nested subagent dispatch** — `dispatch.background`/`backgroundDispatch`/`nested` are all `true` with `maxDepth: 2`; `shouldFlattenDispatch(cursor)` returns `false` so GSD's wave-based execution drives Cursor's native background + depth-2 nested subagent dispatch instead of flattening to inline sequential calls (AC4b, cite https://cursor.com/docs/subagents + https://cursor.com/docs/sdk/typescript).
|
||||
- **Expanded hook-bus coverage** — MSD registers all 6 managed lifecycle events in `hooks.json` beyond the original `sessionStart`/`postToolUse`: `preToolUse`, `stop`, `subagentStart`, `subagentStop` (AC4a, cite https://cursor.com/docs/hooks). The hook-bus binding is descriptor-driven via `src/host-integration-adapters/imperative-hook-bus.cts` (reads `hostBehaviors.managedHookEvents`), not a hardcoded event pair.
|
||||
- **Named/background nested subagent dispatch** — `dispatch.background`/`backgroundDispatch`/`nested` are all `true` with `maxDepth: 2`; `shouldFlattenDispatch(cursor)` returns `false` so MSD's wave-based execution drives Cursor's native background + depth-2 nested subagent dispatch instead of flattening to inline sequential calls (AC4b, cite https://cursor.com/docs/subagents + https://cursor.com/docs/sdk/typescript).
|
||||
|
||||
---
|
||||
|
||||
@@ -257,10 +257,10 @@ Sources consulted:
|
||||
- https://github.com/cline/cline/blob/main/sdk/packages/llms/README.md
|
||||
- /cline/cline (Context7)
|
||||
|
||||
**GSD integration status — Phase D dogfood complete (#2090, ADR-1239).** Cline installs through the `imperative` embedding adapter (`createImperativeAdapter` → `installRuntimeArtifacts`); the hardcoded `runtime === 'cline'` / `isCline` projection is folded into descriptor-driven `runtime.hostBehaviors`, and install/uninstall output is byte-parity-gated at the time (`tests/fixtures/golden-install-parity/cline.json`; superseded by the differential attribution check, #2724). Two capability upgrades land, each with a test driving the user-reachable surface:
|
||||
**MSD integration status — Phase D dogfood complete (#2090, ADR-1239).** Cline installs through the `imperative` embedding adapter (`createImperativeAdapter` → `installRuntimeArtifacts`); the hardcoded `runtime === 'cline'` / `isCline` projection is folded into descriptor-driven `runtime.hostBehaviors`, and install/uninstall output is byte-parity-gated at the time (`tests/fixtures/golden-install-parity/cline.json`; superseded by the differential attribution check, #2724). Two capability upgrades land, each with a test driving the user-reachable surface:
|
||||
|
||||
- **`AgentPlugin.hooks.beforeTool` planning guard** — the `.clinerules/hooks/PreToolUse` file-convention hook (#787) is re-implemented as a real Cline SDK `AgentPlugin` registered through the negotiated `hookBus: host` interface point. Guard semantics are preserved exactly (fail-open, cancels write-class calls targeting `.planning/`); the SDK maps the file hook's `{cancel, errorMessage}` to `{skip, reason}`. The binding lives in `src/host-integration-adapters/cline-sdk-binding.cts` (cite https://github.com/cline/cline/blob/main/docs/sdk/plugins.mdx).
|
||||
- **`createAgentModel` per-subagent model overrides** — `DefaultGateway.createAgentModel({providerId, modelId})` is wired so GSD's `model_overrides` / `model_profile_overrides` resolution (already used for OpenCode/Codex passive hosts) applies to cline subagents (`modelMode: active`), instead of leaving model selection untouched (cite https://github.com/cline/cline/blob/main/docs/sdk/reference/gateway.mdx).
|
||||
- **`createAgentModel` per-subagent model overrides** — `DefaultGateway.createAgentModel({providerId, modelId})` is wired so MSD's `model_overrides` / `model_profile_overrides` resolution (already used for OpenCode/Codex passive hosts) applies to cline subagents (`modelMode: active`), instead of leaving model selection untouched (cite https://github.com/cline/cline/blob/main/docs/sdk/reference/gateway.mdx).
|
||||
- **Dispatch stays degraded/flat (deliberate)** — unlike cursor's dispatch upgrade, cline's `dispatch` is `maxDepth: 1`, `nested: false`, `subagentToolkit: 'read-only'`, `backgroundDispatch: false`. `shouldFlattenDispatch(cline)` returns `true` and `degradationFor('dispatch', cline)` returns `{level:'degraded', fallback:'flat dispatch — waves run inline'}`. This is NOT upgraded: cline's own docs restrict subagents to a single level with a read-only toolkit and no nested spawning, so claiming full dispatch would misrepresent the host and violate the fail-closed negotiation contract (cite https://github.com/cline/cline/blob/main/docs/features/subagents.mdx).
|
||||
|
||||
---
|
||||
@@ -312,7 +312,7 @@ Documentation gaps:
|
||||
| commandSurface | slash-file | https://github.com/alphaperseii3000/google-antigravity-docs/blob/master/google-antigravity-docs.md | "Workflows are saved as markdown files, providing a repeatable method for executing key processes. They can be invoked in the Agent using a s" |
|
||||
| modelMode | passive | https://dev.to/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7 | "Selection occurs via `-m` flag or `/model` command inside the TUI. No programmatic model request API is documented for extensions/skills" |
|
||||
| hookBus | host | https://www.aibuilderclub.com/blog/antigravity-cli-guide | "The CLI fires hooks, not the engine. These are JSON lifecycle interceptors (before tool call, after file edit, on session start)." |
|
||||
| stateIO | filesystem | live `agy` 1.1.17 install probe — https://github.com/open-gsd/gsd-core/issues/3747 | "Global skills discovery scans ~/.gemini/config/skills/: a probe skill placed there is visible to `agy`, while an identical probe skill under the configHome is not. An earlier third-party blog claim about configHome skills placement was disproved by that probe; GSD installs global skills/agents under ~/.gemini/config (#3738)" |
|
||||
| stateIO | filesystem | live `agy` 1.1.17 install probe — https://github.com/open-gsd/gsd-core/issues/3747 | "Global skills discovery scans ~/.gemini/config/skills/: a probe skill placed there is visible to `agy`, while an identical probe skill under the configHome is not. An earlier third-party blog claim about configHome skills placement was disproved by that probe; MSD installs global skills/agents under ~/.gemini/config (#3738)" |
|
||||
| transport | mcp | https://dev.to/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7 | "Both local (stdio) and remote (HTTP) Model Context Protocol servers are supported" |
|
||||
| runtime | go | https://developers.googleblog.com/an-important-update-transitioning-gemini-cli-to-antigravity-cli/ | "Built in Go, Antigravity CLI is snappier and more responsive." |
|
||||
| effortSurface | undocumented | no authoritative doc — per-host reasoning-effort survey, #2481 (`09b535ac0`) | This host's documentation states no reasoning-effort setting, so the axis carries the fail-closed sentinel rather than inheriting a profile baseline. No host-specific URL is cited because the finding is an ABSENCE: #2481 surveyed all hosts for a reasoning-effort mechanism and found one only for claude/opencode/codex. |
|
||||
@@ -339,7 +339,7 @@ Documentation gaps:
|
||||
- dispatch.nested — no documentation found on whether subagents can themselves spawn further subagents.
|
||||
- dispatch.maxDepth — no documented depth limit or explicit unbounded statement found.
|
||||
|
||||
**EoS migration status (#2096):** Migrated onto the declarative adapter. All `runtime === 'antigravity'` / `isAntigravity` / `canonical === 'antigravity'` branches folded into descriptor-driven `runtime.hostBehaviors` + `runtime.hostIntegration`: `getConfigDirFromHome` (`bin/install.js`) now branches on `configHome.kind === 'dot-home-nested'` instead of a hardcoded runtime literal; `projectLocalHookPrefix` (`src/shell-command-projection.cts`) reads `hostBehaviors.hookPathStyle` (`'raw'` → bare `dirName`, no `$CLAUDE_PROJECT_DIR` anchor); `applyAgentPathRewrites` (`src/runtime-artifact-conversion.cts`) reads `hostBehaviors.noPathRewrite` to skip the `~/.claude/` → pathPrefix rewrites; and `getProjectInstructionFile` (`src/runtime-name-policy.cts`) reads `hostBehaviors.projectInstructionFile` (`"GEMINI.md"` — Antigravity CLI's `contextFileName`, successor to the sunset Gemini CLI per #1928) instead of a hardcoded `canonical === 'antigravity'` check. The dead `isAntigravity` branches these functions previously carried are removed. `dispatch.subagentToolkit` flipped `undocumented` → `full` per the citation above (antigravity.google/docs/cli/features); `dispatch.namedDispatch`/`nested`/`maxDepth`/`backgroundDispatch` stay `undocumented` — no authoritative source states named/nested/depth-bounded dispatch or a `run_in_background`-style call-time param, so `negotiateHostCapabilities` degrades all four closed to their most-restrictive value (false/0), and `shouldFlattenDispatch` still forces antigravity's dispatch to flatten (inline) despite `dispatch.background: true`, because `backgroundDispatch` itself never reaches `true`. Two upgrades land: **UPGRADE 1 — permission-writer** (`configureAntigravityPermissions`, `runtime.permissionWriter: "antigravity"`) writes Antigravity's native `{"permissions":{"allow":[...]}}` schema (antigravity.google/docs/cli/permissions) into the same `settings.json` GSD's own hook registration writes, granting GSD's own `read_file`/`command` rules non-destructively. **UPGRADE 2 — MCP companion config** (`configureAntigravityMcpConfig`) writes a standalone `mcp_config.json` (antigravity.google/docs/cli/gcli-migration) registering the `gsd` MCP server, non-destructively preserving any other `mcpServers` entries. Both upgrades are covered by `tests/antigravity-upgrades.test.cjs`; the axis/negotiation/source-grep coverage above is in `tests/declarative-reference-antigravity.test.cjs`.
|
||||
**EoS migration status (#2096):** Migrated onto the declarative adapter. All `runtime === 'antigravity'` / `isAntigravity` / `canonical === 'antigravity'` branches folded into descriptor-driven `runtime.hostBehaviors` + `runtime.hostIntegration`: `getConfigDirFromHome` (`bin/install.js`) now branches on `configHome.kind === 'dot-home-nested'` instead of a hardcoded runtime literal; `projectLocalHookPrefix` (`src/shell-command-projection.cts`) reads `hostBehaviors.hookPathStyle` (`'raw'` → bare `dirName`, no `$CLAUDE_PROJECT_DIR` anchor); `applyAgentPathRewrites` (`src/runtime-artifact-conversion.cts`) reads `hostBehaviors.noPathRewrite` to skip the `~/.claude/` → pathPrefix rewrites; and `getProjectInstructionFile` (`src/runtime-name-policy.cts`) reads `hostBehaviors.projectInstructionFile` (`"GEMINI.md"` — Antigravity CLI's `contextFileName`, successor to the sunset Gemini CLI per #1928) instead of a hardcoded `canonical === 'antigravity'` check. The dead `isAntigravity` branches these functions previously carried are removed. `dispatch.subagentToolkit` flipped `undocumented` → `full` per the citation above (antigravity.google/docs/cli/features); `dispatch.namedDispatch`/`nested`/`maxDepth`/`backgroundDispatch` stay `undocumented` — no authoritative source states named/nested/depth-bounded dispatch or a `run_in_background`-style call-time param, so `negotiateHostCapabilities` degrades all four closed to their most-restrictive value (false/0), and `shouldFlattenDispatch` still forces antigravity's dispatch to flatten (inline) despite `dispatch.background: true`, because `backgroundDispatch` itself never reaches `true`. Two upgrades land: **UPGRADE 1 — permission-writer** (`configureAntigravityPermissions`, `runtime.permissionWriter: "antigravity"`) writes Antigravity's native `{"permissions":{"allow":[...]}}` schema (antigravity.google/docs/cli/permissions) into the same `settings.json` MSD's own hook registration writes, granting MSD's own `read_file`/`command` rules non-destructively. **UPGRADE 2 — MCP companion config** (`configureAntigravityMcpConfig`) writes a standalone `mcp_config.json` (antigravity.google/docs/cli/gcli-migration) registering the `msd` MCP server, non-destructively preserving any other `mcpServers` entries. Both upgrades are covered by `tests/antigravity-upgrades.test.cjs`; the axis/negotiation/source-grep coverage above is in `tests/declarative-reference-antigravity.test.cjs`.
|
||||
|
||||
---
|
||||
|
||||
@@ -395,12 +395,12 @@ single-sourced converters per ADR-1508 / #1675) and the unreachable
|
||||
inline agent-conversion branch (augment has been on the descriptor-agents path
|
||||
since `_DESCRIPTOR_AGENTS_RUNTIMES` was introduced, making that `if`/`else if`
|
||||
arm dead). **UPGRADE 3 — MCP companion config**
|
||||
(`mergeGsdMcpServerIntoSettings`) registers the `gsd` MCP server directly
|
||||
inside the same `settings.json` `mcpServers` block GSD's own hook
|
||||
(`mergeMsdMcpServerIntoSettings`) registers the `msd` MCP server directly
|
||||
inside the same `settings.json` `mcpServers` block MSD's own hook
|
||||
registration already writes (Augment hosts MCP in `settings.json`, unlike
|
||||
Antigravity's standalone `mcp_config.json`) — non-destructively preserving
|
||||
any other user-configured `mcpServers` entries; uninstall removes only the
|
||||
GSD-owned `gsd` entry. `settings.json` is golden-excluded
|
||||
MSD-owned `msd` entry. `settings.json` is golden-excluded
|
||||
(`HOOK_CONFIG_FILES`), so this upgrade produces no golden fixture change.
|
||||
Source-grep guard + fail-closed negotiation coverage is in
|
||||
`tests/declarative-reference-augment.test.cjs`; the dispatch/hook-bus/MCP
|
||||
@@ -442,7 +442,7 @@ Documentation gaps:
|
||||
- dispatch.nested — docs only restrict fork-type sub-agents from nesting; whether named sub-agents can themselves spawn named sub-agents is not stated.
|
||||
- dispatch.maxDepth — depth=1 is documented only for fork sub-agents; depth for named sub-agent chains is undocumented.
|
||||
|
||||
**EoS migration status (#2092):** Migrated onto the imperative adapter. All `runtime === 'qwen'` branches in `bin/install.js`, `src/install-engine.cts`, `src/runtime-artifact-conversion.cts`, and `src/runtime-hooks-surface.cts` folded into descriptor-driven `runtime.hostBehaviors`. Two upgrades land: (1) **native subagent projection** — a new `agents` artifact-layout kind projects GSD's specialist agents into `~/.qwen/agents/gsd-*.md` as native Qwen subagents via `convertClaudeAgentToQwenAgent`, emitting Qwen's own `name:`/`description:`/`tools:` (YAML block list) frontmatter schema instead of Claude Code's; cite https://qwenlm.github.io/qwen-code-docs/en/users/features/sub-agents/. (2) **`SubagentStart` hook** — wired into `extendedHookEvents` alongside the existing `SubagentStop`/`Stop`/`PreCompact` events, firing the context-monitor hook symmetrically at subagent start and completion; cite https://qwenlm.github.io/qwen-code-docs/en/users/features/hooks.
|
||||
**EoS migration status (#2092):** Migrated onto the imperative adapter. All `runtime === 'qwen'` branches in `bin/install.js`, `src/install-engine.cts`, `src/runtime-artifact-conversion.cts`, and `src/runtime-hooks-surface.cts` folded into descriptor-driven `runtime.hostBehaviors`. Two upgrades land: (1) **native subagent projection** — a new `agents` artifact-layout kind projects MSD's specialist agents into `~/.qwen/agents/msd-*.md` as native Qwen subagents via `convertClaudeAgentToQwenAgent`, emitting Qwen's own `name:`/`description:`/`tools:` (YAML block list) frontmatter schema instead of Claude Code's; cite https://qwenlm.github.io/qwen-code-docs/en/users/features/sub-agents/. (2) **`SubagentStart` hook** — wired into `extendedHookEvents` alongside the existing `SubagentStop`/`Stop`/`PreCompact` events, firing the context-monitor hook symmetrically at subagent start and completion; cite https://qwenlm.github.io/qwen-code-docs/en/users/features/hooks.
|
||||
|
||||
---
|
||||
|
||||
@@ -476,7 +476,7 @@ Sources consulted:
|
||||
- https://www.codebuddy.ai/docs/cli/settings
|
||||
- /websites/codebuddy_cn (Context7)
|
||||
|
||||
**EoS migration status (#2098):** Migrated onto the declarative adapter (dogfooded in `tests/declarative-reference-codebuddy.test.cjs`). The two remaining `isCodebuddy` branches in `bin/install.js` — a duplicate `commands/` slash-command output report, and a dead legacy agent-converter dispatch arm (unreachable since codebuddy is in `_DESCRIPTOR_AGENTS_RUNTIMES`) — were folded onto the generic `runtime.hostBehaviors.reportCommandsDir` and removed outright; `isCodebuddy` no longer appears as a live read anywhere in `bin/install.js`, `src/runtime-artifact-conversion.cts`, `src/shell-command-projection.cts`, or `src/runtime-name-policy.cts`. Cursor also used that report flag historically, but retired its parallel command surface in #2644 because Cursor skills already appear in the slash menu. Two upgrades land: (1) **extended hook events** — codebuddy's `extendedHookEvents` was previously `[]` (none wired); this PR wires all four — `SubagentStop`/`Stop`/`PreCompact`/`SubagentStart` — into `extendedHookEvents` (mirrors qwen/kimi), so an install now registers all four as hooks in `settings.json` alongside the pre-existing base session/tool events (`SessionStart`/`PreToolUse`/`PostToolUse`); cite https://www.codebuddy.ai/docs/cli/hooks. (2) **`dispatch.background`** — the descriptor already declared `true`, exceeding the `declarative-cli` profile baseline of `false`; the negotiation contract (`negotiateHostCapabilities`) now surfaces that value with no downgrade warning, documenting the legitimate deviation. Note: the CodeBuddy CLI has no background-dispatch frontmatter field on sub-agents (`agentMode`/`enabledAutoRun` are IDE-only per https://www.codebuddy.ai/docs/cli/sub-agents) — background dispatch remains a caller-side invocation parameter (`run_in_background: true`), not a field GSD's agent artifacts emit.
|
||||
**EoS migration status (#2098):** Migrated onto the declarative adapter (dogfooded in `tests/declarative-reference-codebuddy.test.cjs`). The two remaining `isCodebuddy` branches in `bin/install.js` — a duplicate `commands/` slash-command output report, and a dead legacy agent-converter dispatch arm (unreachable since codebuddy is in `_DESCRIPTOR_AGENTS_RUNTIMES`) — were folded onto the generic `runtime.hostBehaviors.reportCommandsDir` and removed outright; `isCodebuddy` no longer appears as a live read anywhere in `bin/install.js`, `src/runtime-artifact-conversion.cts`, `src/shell-command-projection.cts`, or `src/runtime-name-policy.cts`. Cursor also used that report flag historically, but retired its parallel command surface in #2644 because Cursor skills already appear in the slash menu. Two upgrades land: (1) **extended hook events** — codebuddy's `extendedHookEvents` was previously `[]` (none wired); this PR wires all four — `SubagentStop`/`Stop`/`PreCompact`/`SubagentStart` — into `extendedHookEvents` (mirrors qwen/kimi), so an install now registers all four as hooks in `settings.json` alongside the pre-existing base session/tool events (`SessionStart`/`PreToolUse`/`PostToolUse`); cite https://www.codebuddy.ai/docs/cli/hooks. (2) **`dispatch.background`** — the descriptor already declared `true`, exceeding the `declarative-cli` profile baseline of `false`; the negotiation contract (`negotiateHostCapabilities`) now surfaces that value with no downgrade warning, documenting the legitimate deviation. Note: the CodeBuddy CLI has no background-dispatch frontmatter field on sub-agents (`agentMode`/`enabledAutoRun` are IDE-only per https://www.codebuddy.ai/docs/cli/sub-agents) — background dispatch remains a caller-side invocation parameter (`run_in_background: true`), not a field MSD's agent artifacts emit.
|
||||
|
||||
---
|
||||
|
||||
@@ -513,7 +513,7 @@ Documentation gaps:
|
||||
- runtime — docs describe the CLI binary and the SDK (Node.js/Go/Python/Rust) but do not state what runtime the CLI host itself or its plugin/extension loader executes in.
|
||||
- dispatch.nested exact authoritative source is awesome-copilot.github.com (community docs) not docs.github.com.
|
||||
|
||||
**EoS migration status (#2099):** Migrated onto the declarative adapter (dogfooded in `tests/declarative-reference-copilot.test.cjs`). The residual `isCopilot` branches were folded onto descriptor-driven `runtime.hostBehaviors`: the `.agent.md` destination-suffix rename in `src/install-engine.cts` now reads `hostBehaviors.agentFileExtension`; `bin/install.js`'s two uninstall side-effect branches (repo-root `AGENTS.md` cleanup, `copilot-instructions.md`/hook cleanup) now gate on `resolveInstallPlan(runtime).installSurface === 'copilot-instructions'` (unique to copilot, so byte-identical); and the two `skipSharedHooksInstall` checks now read `hostBehaviors.skipSharedHooksInstall:true` (copilot's golden has only `hooks/gsd-session.json`, no shared `gsd-*.js` scripts). A dead legacy agent-converter dispatch arm in the inline agent-copy loop — unreachable since copilot is a member of `_DESCRIPTOR_AGENTS_RUNTIMES` — was removed outright; `isCopilot` no longer appears as a live read anywhere in `bin/install.js` or `src/install-engine.cts`. Two upgrades land: (1) **multi-event hook bus** — `buildCopilotHookConfig()` previously emitted only `sessionStart`; this PR wires four additional events — `preToolUse`/`postToolUse`/`userPromptSubmitted`/`sessionEnd` — each a static, deterministic advisory command (no node-runner invocation), so an install's `hooks/gsd-session.json` now registers all five events. (2) **`dispatch.background`** — the descriptor already declared `true`, exceeding the `declarative-cli` profile baseline of `false`; the negotiation contract (`negotiateHostCapabilities`) surfaces that value with no downgrade warning, documenting the legitimate deviation. Note: Copilot's `.agent.md` frontmatter has no background-dispatch field (fields are `description`/`infer`/`mcp-servers`/`model`/`name`/`tools`) — background dispatch remains a negotiated-contract-only axis, not a field GSD's agent artifacts emit. MCP companion tooling is out of scope for this migration (AC4 names only the two upgrades above).
|
||||
**EoS migration status (#2099):** Migrated onto the declarative adapter (dogfooded in `tests/declarative-reference-copilot.test.cjs`). The residual `isCopilot` branches were folded onto descriptor-driven `runtime.hostBehaviors`: the `.agent.md` destination-suffix rename in `src/install-engine.cts` now reads `hostBehaviors.agentFileExtension`; `bin/install.js`'s two uninstall side-effect branches (repo-root `AGENTS.md` cleanup, `copilot-instructions.md`/hook cleanup) now gate on `resolveInstallPlan(runtime).installSurface === 'copilot-instructions'` (unique to copilot, so byte-identical); and the two `skipSharedHooksInstall` checks now read `hostBehaviors.skipSharedHooksInstall:true` (copilot's golden has only `hooks/msd-session.json`, no shared `msd-*.js` scripts). A dead legacy agent-converter dispatch arm in the inline agent-copy loop — unreachable since copilot is a member of `_DESCRIPTOR_AGENTS_RUNTIMES` — was removed outright; `isCopilot` no longer appears as a live read anywhere in `bin/install.js` or `src/install-engine.cts`. Two upgrades land: (1) **multi-event hook bus** — `buildCopilotHookConfig()` previously emitted only `sessionStart`; this PR wires four additional events — `preToolUse`/`postToolUse`/`userPromptSubmitted`/`sessionEnd` — each a static, deterministic advisory command (no node-runner invocation), so an install's `hooks/msd-session.json` now registers all five events. (2) **`dispatch.background`** — the descriptor already declared `true`, exceeding the `declarative-cli` profile baseline of `false`; the negotiation contract (`negotiateHostCapabilities`) surfaces that value with no downgrade warning, documenting the legitimate deviation. Note: Copilot's `.agent.md` frontmatter has no background-dispatch field (fields are `description`/`infer`/`mcp-servers`/`model`/`name`/`tools`) — background dispatch remains a negotiated-contract-only axis, not a field MSD's agent artifacts emit. MCP companion tooling is out of scope for this migration (AC4 names only the two upgrades above).
|
||||
|
||||
---
|
||||
|
||||
@@ -552,7 +552,7 @@ Sources consulted:
|
||||
Documentation gaps:
|
||||
- dispatch.subagentToolkit — docs describe per-subagent configurable permissions (allow/ask/deny) but do not document a single default toolkit level (full vs read-only) for subagents that lack explicit permission overrides.
|
||||
|
||||
**EoS migration status (#2093):** Migrated onto the imperative adapter. All `runtime === 'kilo'` / `isKilo` logic branches in `bin/install.js`, `src/install-engine.cts`, `src/runtime-artifact-conversion.cts`, and `src/runtime-artifact-layout.cts` folded into descriptor-driven `runtime.hostBehaviors` (`finishPermissionWriter`, `skipSharedHooksInstall`, and the skills converter registry are now resolved off the descriptor, not a hardcoded Kilo check). Four upgrades land: (1) **native hook-bus plugin** — `.kilo/plugins/gsd-core.js` (byte-identical to `.opencode/plugins/gsd-core.js`, cite: Kilo is an OpenCode fork sharing the same plugin/extension event bus) bridges GSD's hook scripts onto Kilo's plugin event bus; `extensionEvents: "kilo"` reuses `OPENCODE_EXTENSION_EVENTS` verbatim. (2) **active-model routing** — `convertClaudeToKiloFrontmatter` now emits a `model:` field from the resolved `model_overrides`/`model_profile_overrides.kilo.<tier>` value instead of always stripping it (mirrors the OpenCode upgrade; #2256). (3) **MCP companion documented** — `docs/how-to/connect-gsd-mcp-server.md` covers Kilo's `mcp`-keyed config (not `mcpServers`) and its `{type:"local", command, timeout}` entry shape. (4) **named subagent dispatch** — GSD's specialist agents install as `<configDir>/agents/gsd-*.md` with `mode: subagent` frontmatter (the slug Kilo's Task tool dispatches by) and a `permission:` block. `dispatch.subagentToolkit` stays `undocumented` — no authoritative Kilo doc states a default subagent toolkit level — so `degradationFor('dispatch', …)` returns `'degraded'`, not `'full'`, by design (fail-closed negotiation, not a regression).
|
||||
**EoS migration status (#2093):** Migrated onto the imperative adapter. All `runtime === 'kilo'` / `isKilo` logic branches in `bin/install.js`, `src/install-engine.cts`, `src/runtime-artifact-conversion.cts`, and `src/runtime-artifact-layout.cts` folded into descriptor-driven `runtime.hostBehaviors` (`finishPermissionWriter`, `skipSharedHooksInstall`, and the skills converter registry are now resolved off the descriptor, not a hardcoded Kilo check). Four upgrades land: (1) **native hook-bus plugin** — `.kilo/plugins/msd-core.js` (byte-identical to `.opencode/plugins/msd-core.js`, cite: Kilo is an OpenCode fork sharing the same plugin/extension event bus) bridges MSD's hook scripts onto Kilo's plugin event bus; `extensionEvents: "kilo"` reuses `OPENCODE_EXTENSION_EVENTS` verbatim. (2) **active-model routing** — `convertClaudeToKiloFrontmatter` now emits a `model:` field from the resolved `model_overrides`/`model_profile_overrides.kilo.<tier>` value instead of always stripping it (mirrors the OpenCode upgrade; #2256). (3) **MCP companion documented** — `docs/how-to/connect-msd-mcp-server.md` covers Kilo's `mcp`-keyed config (not `mcpServers`) and its `{type:"local", command, timeout}` entry shape. (4) **named subagent dispatch** — MSD's specialist agents install as `<configDir>/agents/msd-*.md` with `mode: subagent` frontmatter (the slug Kilo's Task tool dispatches by) and a `permission:` block. `dispatch.subagentToolkit` stays `undocumented` — no authoritative Kilo doc states a default subagent toolkit level — so `degradationFor('dispatch', …)` returns `'degraded'`, not `'full'`, by design (fail-closed negotiation, not a regression).
|
||||
|
||||
---
|
||||
|
||||
@@ -595,7 +595,7 @@ Documentation gaps:
|
||||
- dispatch.subagentToolkit — no documentation for toolkit restrictions on Cascade sub-agents.
|
||||
- runtime — Windsurf IDE is Electron-based but no programmatic plugin runtime is documented to developers.
|
||||
|
||||
**EoS migration status (#2100 Stage 2 — HOOK-BRIDGE):** `hooksSurface` moved from `"none"` to `"windsurf-hooks-json"`. GSD now wires two of Cascade's documented pre-hooks with BLOCKING semantics via `.windsurf/hooks.json` (local) / `~/.codeium/windsurf/hooks.json` (global): `pre_write_code` (write-path guard — blocks a write resolving to a different git root than cwd, or into a `.git/` internals directory) and `pre_run_command` (a conservative destructive-command deny-list — whole-disk/home `rm -rf`, force-push to a protected branch). Cascade blocks via **exit code 2** (+ a stderr reason string) — a materially different protocol from Cursor's stdout-JSON `{block, reason}` hooks.json form, even though the surrounding install/reconcile infra (`writeWindsurfHooksJson`/`removeWindsurfHooksJson` in `src/runtime-hooks-surface.cts`) mirrors `writeCursorHooksJson`/`removeCursorHooksJson`'s shape. Cascade has **no context-injection channel** (no `additional_context`-style advisory response channel), so the 4 advisory hook events GSD registers on Cursor (`sessionStart`, `postToolUse`, `stop`, `subagentStart`/`subagentStop`) have no Windsurf/Cascade counterpart and are deliberately **not ported** — only the 2 events with a genuine blocking analog are wired. `installSurface` stays `profile-marker-only` (unchanged); the hook bus is wired from inside that branch, gated on `hooksSurface === 'windsurf-hooks-json'` rather than a hardcoded runtime check.
|
||||
**EoS migration status (#2100 Stage 2 — HOOK-BRIDGE):** `hooksSurface` moved from `"none"` to `"windsurf-hooks-json"`. MSD now wires two of Cascade's documented pre-hooks with BLOCKING semantics via `.windsurf/hooks.json` (local) / `~/.codeium/windsurf/hooks.json` (global): `pre_write_code` (write-path guard — blocks a write resolving to a different git root than cwd, or into a `.git/` internals directory) and `pre_run_command` (a conservative destructive-command deny-list — whole-disk/home `rm -rf`, force-push to a protected branch). Cascade blocks via **exit code 2** (+ a stderr reason string) — a materially different protocol from Cursor's stdout-JSON `{block, reason}` hooks.json form, even though the surrounding install/reconcile infra (`writeWindsurfHooksJson`/`removeWindsurfHooksJson` in `src/runtime-hooks-surface.cts`) mirrors `writeCursorHooksJson`/`removeCursorHooksJson`'s shape. Cascade has **no context-injection channel** (no `additional_context`-style advisory response channel), so the 4 advisory hook events MSD registers on Cursor (`sessionStart`, `postToolUse`, `stop`, `subagentStart`/`subagentStop`) have no Windsurf/Cascade counterpart and are deliberately **not ported** — only the 2 events with a genuine blocking analog are wired. `installSurface` stays `profile-marker-only` (unchanged); the hook bus is wired from inside that branch, gated on `hooksSurface === 'windsurf-hooks-json'` rather than a hardcoded runtime check.
|
||||
|
||||
---
|
||||
|
||||
@@ -636,13 +636,13 @@ Documentation gaps:
|
||||
- dispatch.maxDepth — no integer depth limit documented beyond one orchestrator level.
|
||||
- dispatch.subagentToolkit — docs say agents can be configured with 'callable MCP services and other capabilities' but do not state whether sub-agents receive a full vs. restricted tool set.
|
||||
|
||||
**EoS migration status (#2094):** Migrated onto the imperative adapter — partially. Two `runtime === 'trae'` string-equality branches folded into descriptor-driven `runtime.hostBehaviors`: `skipSharedHooksInstall:true` gates the shared-hooks install (Trae has no hook surface: `hooksSurface: "none"`), and the `case 'trae'` global-config-dir path-rewrite's self-alias regex is now built off the descriptor's `dirName` rather than a hardcoded `~/.trae/` literal (byte-identical output). Skills dispatch was already descriptor-driven before this migration (`artifactLayout.skills.converter: "convertClaudeCommandToTraeSkill"`, resolved by converter name, not a runtime check). **Still runtime-keyed** (not folded by #2094, matching the same posture as cursor/windsurf/cline, pending a future cross-runtime content-dispatch consolidation): `RUNTIME_CONTENT_DISPATCH.trae` in `bin/install.js` — its `md`/`js` bodies are regex-callback rewrites that cannot be reduced to a byte-identical descriptor map; and the `case 'trae':` switch arm itself in `src/runtime-artifact-conversion.cts` — the arm's *structure* (not just its self-alias regex) is boilerplate shared verbatim across 7 runtimes (`codex`, `cline`, `cursor`, `windsurf`, `augment`, `trae`, `codebuddy`) and remains a runtime-keyed `switch`. `trae` also remains in `RUNTIME_FLAG_IDS` (and `isTrae` remains in `bin/install.js`, gating only the agents-converter dispatch) pending the cross-runtime agents-converter dispatch migration — agents conversion is out of scope for #2094. One upgrade lands: **SOLO stage/trigger metadata** — every emitted `SKILL.md` now carries a `stage: workflow` frontmatter line (`runtime.hostBehaviors.soloStageMetadata`), so Trae's SOLO Agent can recognize GSD skills as workflow-stage skills for auto-invocation instead of requiring manual triggering; cite https://docs.trae.ai/ide/agent ("Agents in Trae can be called individually, or automatically called by SOLO Agent at the corresponding stage"). The field is a single fixed, best-effort/inferred GSD-side value — Trae's thin SPA docs don't publish a formal stage-metadata schema. The four `undocumented` dispatch sub-axes (`nested`, `maxDepth`, `subagentToolkit`, `backgroundDispatch`) keep dispatch flattened (`shouldFlattenDispatch` fails closed to inline) — fail-closed negotiation, not a regression.
|
||||
**EoS migration status (#2094):** Migrated onto the imperative adapter — partially. Two `runtime === 'trae'` string-equality branches folded into descriptor-driven `runtime.hostBehaviors`: `skipSharedHooksInstall:true` gates the shared-hooks install (Trae has no hook surface: `hooksSurface: "none"`), and the `case 'trae'` global-config-dir path-rewrite's self-alias regex is now built off the descriptor's `dirName` rather than a hardcoded `~/.trae/` literal (byte-identical output). Skills dispatch was already descriptor-driven before this migration (`artifactLayout.skills.converter: "convertClaudeCommandToTraeSkill"`, resolved by converter name, not a runtime check). **Still runtime-keyed** (not folded by #2094, matching the same posture as cursor/windsurf/cline, pending a future cross-runtime content-dispatch consolidation): `RUNTIME_CONTENT_DISPATCH.trae` in `bin/install.js` — its `md`/`js` bodies are regex-callback rewrites that cannot be reduced to a byte-identical descriptor map; and the `case 'trae':` switch arm itself in `src/runtime-artifact-conversion.cts` — the arm's *structure* (not just its self-alias regex) is boilerplate shared verbatim across 7 runtimes (`codex`, `cline`, `cursor`, `windsurf`, `augment`, `trae`, `codebuddy`) and remains a runtime-keyed `switch`. `trae` also remains in `RUNTIME_FLAG_IDS` (and `isTrae` remains in `bin/install.js`, gating only the agents-converter dispatch) pending the cross-runtime agents-converter dispatch migration — agents conversion is out of scope for #2094. One upgrade lands: **SOLO stage/trigger metadata** — every emitted `SKILL.md` now carries a `stage: workflow` frontmatter line (`runtime.hostBehaviors.soloStageMetadata`), so Trae's SOLO Agent can recognize MSD skills as workflow-stage skills for auto-invocation instead of requiring manual triggering; cite https://docs.trae.ai/ide/agent ("Agents in Trae can be called individually, or automatically called by SOLO Agent at the corresponding stage"). The field is a single fixed, best-effort/inferred MSD-side value — Trae's thin SPA docs don't publish a formal stage-metadata schema. The four `undocumented` dispatch sub-axes (`nested`, `maxDepth`, `subagentToolkit`, `backgroundDispatch`) keep dispatch flattened (`shouldFlattenDispatch` fails closed to inline) — fail-closed negotiation, not a regression.
|
||||
|
||||
---
|
||||
|
||||
## kimi
|
||||
|
||||
**EoS migration status (#2095):** Two upgrades landed. **Upgrade 1 — native hook bus:** `hooksSurface` moved from `"none"` to `"kimi-hooks-toml"` (`extendedHookEvents: ["SubagentStop", "Stop", "PreCompact", "SubagentStart"]`, `hookEvents: "claude"` — Kimi's 13 lifecycle events include exact-name equivalents for every Claude-dialect event GSD wires). GSD's hook scripts (session-state, phase-boundary, graphify, context monitor, the prompt/read/workflow/worktree guards, commit validation) are now registered as `[[hooks]]` entries in Kimi's own `config.toml` (default `~/.kimi/config.toml`, overridable via Kimi's own `KIMI_SHARE_DIR` env var — a directory deliberately separate from the `~/.config/agents` Agent-Skills root GSD installs into, since Kimi's docs confirm the skills search path is independent of `KIMI_SHARE_DIR`). GSD-owned entries are wrapped in `# GSD Hooks BEGIN`/`END` marker comments (`writeKimiHooksToml` / `stripKimiHooksTomlBlock` in `src/runtime-hooks-surface.cts`) so a reinstall replaces only GSD's own block, and `installSurface` deliberately stays `"profile-marker-only"` — the config.toml write is independent of the artifact-install surface. `hooks/` and `hooks/lib/` now install for kimi (the three `&& !isKimi` install-guard exclusions were removed) — but SELF-CONTAINED under kimi's own native hook root (`~/.kimi/`, alongside `config.toml`), never under the `~/.config/agents` Agent-Skills root: kimi declares `hostBehaviors.skipSharedHooksInstall:true` like Cline/Kilo/Cursor/Trae, so the shared install path never writes hooks/package.json there, and a dedicated call installs the same bundle into `resolveKimiHooksTomlDir()` instead, with `buildHookCommand` pointed at that root so the generated `[[hooks]]` command paths resolve. **Upgrade 2 — background dispatch:** `hostIntegration.dispatch.backgroundDispatch` flipped `false` → `true` (Kimi's `Agent` tool takes a call-time `run_in_background` param — same evidence as `dispatch.background` below), which flips `shouldFlattenDispatch` to `false` for kimi (may background, joining codex/cursor/opencode) — a negotiation-only axis with no install-output effect, confirmed via golden parity. Exercising the actual `run_in_background` call end-to-end is Kimi's own runtime behavior and is out of the installer's test scope; the installer's deliverable stops at the `kimi_cli.tools.agent:Agent` tool grant on the root agent YAML (`buildKimiAgentArtifacts`, only emitted when a subagent is present) plus the negotiated `backgroundDispatch` axis above — both covered by `tests/kimi-upgrades.test.cjs`. **MCP transport deferred:** kimi's `transport: mcp` axis (declared below) is descriptor-only, like every other runtime's — no runtime has installer-driven MCP registration (GSD's installer never invokes `kimi mcp add`); users register the GSD MCP companion server with Kimi CLI manually.
|
||||
**EoS migration status (#2095):** Two upgrades landed. **Upgrade 1 — native hook bus:** `hooksSurface` moved from `"none"` to `"kimi-hooks-toml"` (`extendedHookEvents: ["SubagentStop", "Stop", "PreCompact", "SubagentStart"]`, `hookEvents: "claude"` — Kimi's 13 lifecycle events include exact-name equivalents for every Claude-dialect event MSD wires). MSD's hook scripts (session-state, phase-boundary, graphify, context monitor, the prompt/read/workflow/worktree guards, commit validation) are now registered as `[[hooks]]` entries in Kimi's own `config.toml` (default `~/.kimi/config.toml`, overridable via Kimi's own `KIMI_SHARE_DIR` env var — a directory deliberately separate from the `~/.config/agents` Agent-Skills root MSD installs into, since Kimi's docs confirm the skills search path is independent of `KIMI_SHARE_DIR`). MSD-owned entries are wrapped in `# MSD Hooks BEGIN`/`END` marker comments (`writeKimiHooksToml` / `stripKimiHooksTomlBlock` in `src/runtime-hooks-surface.cts`) so a reinstall replaces only MSD's own block, and `installSurface` deliberately stays `"profile-marker-only"` — the config.toml write is independent of the artifact-install surface. `hooks/` and `hooks/lib/` now install for kimi (the three `&& !isKimi` install-guard exclusions were removed) — but SELF-CONTAINED under kimi's own native hook root (`~/.kimi/`, alongside `config.toml`), never under the `~/.config/agents` Agent-Skills root: kimi declares `hostBehaviors.skipSharedHooksInstall:true` like Cline/Kilo/Cursor/Trae, so the shared install path never writes hooks/package.json there, and a dedicated call installs the same bundle into `resolveKimiHooksTomlDir()` instead, with `buildHookCommand` pointed at that root so the generated `[[hooks]]` command paths resolve. **Upgrade 2 — background dispatch:** `hostIntegration.dispatch.backgroundDispatch` flipped `false` → `true` (Kimi's `Agent` tool takes a call-time `run_in_background` param — same evidence as `dispatch.background` below), which flips `shouldFlattenDispatch` to `false` for kimi (may background, joining codex/cursor/opencode) — a negotiation-only axis with no install-output effect, confirmed via golden parity. Exercising the actual `run_in_background` call end-to-end is Kimi's own runtime behavior and is out of the installer's test scope; the installer's deliverable stops at the `kimi_cli.tools.agent:Agent` tool grant on the root agent YAML (`buildKimiAgentArtifacts`, only emitted when a subagent is present) plus the negotiated `backgroundDispatch` axis above — both covered by `tests/kimi-upgrades.test.cjs`. **MCP transport deferred:** kimi's `transport: mcp` axis (declared below) is descriptor-only, like every other runtime's — no runtime has installer-driven MCP registration (MSD's installer never invokes `kimi mcp add`); users register the MSD MCP companion server with Kimi CLI manually.
|
||||
|
||||
| Axis | Value | Source | Evidence |
|
||||
|---|---|---|---|
|
||||
@@ -660,7 +660,7 @@ Documentation gaps:
|
||||
| dispatch.background | true | https://moonshotai.github.io/kimi-cli/en/customization/agents.html | "Subagents support foreground and background modes. The `run_in_background` parameter allows tasks to execute asynchronou" |
|
||||
| dispatch.subagentToolkit | undocumented | no authoritative doc — searched: https://moonshotai.github.io/kimi-cli/en/customization/agents.html | — |
|
||||
| dispatch.backgroundDispatch | true (#2095 Upgrade 2; was `false`) | https://moonshotai.github.io/kimi-cli/en/customization/agents.html | "Subagents support foreground and background modes. The `run_in_background` parameter allows tasks to execute asynchronously" (same evidence as dispatch.background above — the root agent's `Agent` tool call itself takes the `run_in_background` param) |
|
||||
| dispatch.isolation | orchestrator-worktree | https://github.com/moonshotai/kimi-cli/blob/main/docs/en/faq.md ; /docs/en/customization/agents.md | "`--work-dir` flag sets an explicit working directory"; concurrent "explore" subagents documented — GSD creates + manages the worktree and points the executor at it via `--work-dir` (#2584) |
|
||||
| dispatch.isolation | orchestrator-worktree | https://github.com/moonshotai/kimi-cli/blob/main/docs/en/faq.md ; /docs/en/customization/agents.md | "`--work-dir` flag sets an explicit working directory"; concurrent "explore" subagents documented — MSD creates + manages the worktree and points the executor at it via `--work-dir` (#2584) |
|
||||
| dispatch.maxConcurrency | undocumented | not researched / no documented concurrent-subagent capacity for this axis | no authoritative source consulted for concurrent-executor capacity on this host — fails closed to `1` in negotiation (#3673) |
|
||||
|
||||
Sources consulted:
|
||||
@@ -683,7 +683,7 @@ Documentation gaps:
|
||||
|
||||
> **`kimi-code` is a different product from `kimi` above — every axis below is sourced independently.** `kimi` is Moonshot's Python `kimi-cli` (`from kimi_cli.app import KimiCLI`, `~/.kimi/config.toml`, `--work-dir`); `kimi-code` is the TypeScript/Node **Kimi Code CLI** (`~/.kimi-code/config.toml`, `$KIMI_CODE_HOME`, process-cwd, `AgentSwarm`). None of the values here are inherited from the `kimi` section. See `docs/migration/kimi-to-kimi-code.md` for the user-facing split.
|
||||
|
||||
**GSD hook destination (#2755):** although `kimi` and `kimi-code` share `hooksSurface: "kimi-hooks-toml"`, they do **not** share a hooks root. GSD writes its `[[hooks]]` block, hook bundle and CommonJS marker into `~/.kimi-code/config.toml` for `kimi-code` (overridable via `KIMI_CODE_HOME`) and into `~/.kimi/config.toml` for `kimi` (overridable via `KIMI_SHARE_DIR`); each product's env var is scoped to that product and does not redirect the other. `resolveKimiHooksTomlDir({ runtime })` in `src/runtime-homes.cts` is the single seam that makes this choice, for both the install and uninstall paths. Until #2755 that function was unparameterized and every `kimi-code` install wrote into Kimi CLI's root, leaving Kimi Code with no hooks — this row is documented explicitly because its absence is what let that go unnoticed.
|
||||
**MSD hook destination (#2755):** although `kimi` and `kimi-code` share `hooksSurface: "kimi-hooks-toml"`, they do **not** share a hooks root. MSD writes its `[[hooks]]` block, hook bundle and CommonJS marker into `~/.kimi-code/config.toml` for `kimi-code` (overridable via `KIMI_CODE_HOME`) and into `~/.kimi/config.toml` for `kimi` (overridable via `KIMI_SHARE_DIR`); each product's env var is scoped to that product and does not redirect the other. `resolveKimiHooksTomlDir({ runtime })` in `src/runtime-homes.cts` is the single seam that makes this choice, for both the install and uninstall paths. Until #2755 that function was unparameterized and every `kimi-code` install wrote into Kimi CLI's root, leaving Kimi Code with no hooks — this row is documented explicitly because its absence is what let that go unnoticed.
|
||||
|
||||
| Axis | Value | Source | Evidence |
|
||||
|---|---|---|---|
|
||||
@@ -695,13 +695,13 @@ Documentation gaps:
|
||||
| transport | mcp | https://github.com/MoonshotAI/kimi-code ; /docs/en/customization/plugins.md | "AI-native MCP configuration. Add, edit, and authenticate Model Context Protocol servers conversationally with `/mcp-config`, without hand-editing JSON." Plugin manifests additionally carry an `mcpServers` field. |
|
||||
| runtime | node | https://github.com/MoonshotAI/kimi-code | "Requirements: Node.js ≥ 24.15.0, pnpm 10.33.0." The CLI is a TypeScript pnpm monorepo (`apps/kimi-code`, `packages/agent-core-v2`); hook commands are shell, and MCP servers are external processes. |
|
||||
| effortSurface | *(not declared)* | https://github.com/moonshotai/kimi-code/blob/main/apps/kimi-code/src/tui/commands/registry.ts | Kimi Code documents `/effort` (alias `/thinking`) to change reasoning effort, but only as an **interactive slash command** — there is no `--effort`-style flag on its invocation, and `-m, --model` is the only model/effort-adjacent argv. The axis vocabulary is `argv` | `none`, and neither is accurate: `none` would deny a mechanism the host does have, and `argv` would claim one it does not expose. The descriptor therefore declares no value, which negotiation degrades closed identically to the sentinel. See Documentation gaps. |
|
||||
| dispatch.namedDispatch | false | https://github.com/moonshotai/kimi-code/blob/main/docs/en/customization/agents.md ; `capabilities/kimi-code/capability.json` (`artifactLayout` — skills only) | "The system includes three built-in sub-agents: 'coder' for general software engineering tasks like file modification, 'explore' for read-only codebase navigation and summarization, and 'plan' for architecture design without file or shell access." GSD's kimi-code artifact layout installs Agent **Skills** only (no `agents` kind), so no named GSD subagent is ever registered with the host and every GSD role resolves to one of the three built-ins (`resolveDispatchType`, `src/host-integration.cts`). **This is a GSD-integration-scoped `false`, not a claim that the host lacks named agents — see Documentation gaps.** |
|
||||
| dispatch.namedDispatch | false | https://github.com/moonshotai/kimi-code/blob/main/docs/en/customization/agents.md ; `capabilities/kimi-code/capability.json` (`artifactLayout` — skills only) | "The system includes three built-in sub-agents: 'coder' for general software engineering tasks like file modification, 'explore' for read-only codebase navigation and summarization, and 'plan' for architecture design without file or shell access." MSD's kimi-code artifact layout installs Agent **Skills** only (no `agents` kind), so no named MSD subagent is ever registered with the host and every MSD role resolves to one of the three built-ins (`resolveDispatchType`, `src/host-integration.cts`). **This is a MSD-integration-scoped `false`, not a claim that the host lacks named agents — see Documentation gaps.** |
|
||||
| dispatch.nested | true | https://github.com/moonshotai/kimi-code/blob/main/docs/en/customization/agents.md | The `coder` sub-agent "can dispatch its own nested sub-agents when a task decomposes naturally." (Agent files also expose a `subagents` delegation allowlist, where `subagents: []` is what *prevents* further delegation — nesting is the default.) |
|
||||
| dispatch.maxDepth | undocumented | searched: https://github.com/moonshotai/kimi-code/blob/main/docs/en/customization/agents.md | Nesting is documented, but no maximum nesting depth is stated anywhere in the agents or tools reference. |
|
||||
| dispatch.background | true | https://github.com/moonshotai/kimi-code/blob/main/docs/en/reference/tools.md | "**`Agent`** delegates a subtask to a sub-Agent. Supports foreground execution (waiting for completion) or background execution (returning a task ID). … `run_in_background` (boolean) - Optional - Defaults to false." |
|
||||
| dispatch.subagentToolkit | built-in-only | https://github.com/moonshotai/kimi-code/blob/main/docs/en/customization/agents.md | The three built-ins carry deliberately different tool surfaces — coder "Shares most of the main Agent's toolset; can run shell commands, maintain todo lists, enter Plan mode, and invoke Agent Skills"; explore "Performs read-only operations only and does not modify any files"; plan "Even shell commands are not available". No single `full`/`read-only` value covers the set, so the `built-in-only` member applies (degrades closed to `read-only` when negotiated). |
|
||||
| dispatch.backgroundDispatch | true | https://github.com/moonshotai/kimi-code/blob/main/docs/en/reference/tools.md ; /docs/en/customization/agents.md | The `coder` built-in "can dispatch its own nested sub-agents" and the `Agent` tool's `run_in_background` is a call-time parameter available to it, so a background-dispatched sub-agent may itself dispatch further. `AgentSwarm` additionally fans out concurrently: "By default the tool ramps up concurrency without an upper limit (5 subagents start immediately, then 1 more every 700 ms); set `KIMI_CODE_AGENT_SWARM_MAX_CONCURRENCY` to a positive integer to cap how many subagents run at the same time during that ramp, or leave it unset for no cap." |
|
||||
| dispatch.isolation | orchestrator-worktree | https://github.com/moonshotai/kimi-code/blob/main/docs/en/reference/tools.md ; ADR-1239 §Codex-binding amendment | Neither `Agent` nor `AgentSwarm` exposes a working-directory/cwd parameter — sub-agents inherit the CLI's process cwd — and the CLI has no `--work-dir`-style flag (unlike `kimi`). GSD therefore creates, validates and merges the worktree itself and spawns the executor with that cwd (#2584). |
|
||||
| dispatch.isolation | orchestrator-worktree | https://github.com/moonshotai/kimi-code/blob/main/docs/en/reference/tools.md ; ADR-1239 §Codex-binding amendment | Neither `Agent` nor `AgentSwarm` exposes a working-directory/cwd parameter — sub-agents inherit the CLI's process cwd — and the CLI has no `--work-dir`-style flag (unlike `kimi`). MSD therefore creates, validates and merges the worktree itself and spawns the executor with that cwd (#2584). |
|
||||
| dispatch.maxConcurrency | undocumented | https://github.com/moonshotai/kimi-code/blob/main/docs/en/reference/tools.md | `AgentSwarm` concurrency is configurable ("set `KIMI_CODE_AGENT_SWARM_MAX_CONCURRENCY` to a positive integer to cap how many subagents run at the same time … or leave it unset for no cap") but the CLI states no bound as its OWN default — "By default the tool ramps up concurrency without an upper limit" — so there is no single default integer to cite, only a user-configurable env var (#3673). |
|
||||
|
||||
**Negotiation note.** Because `dispatch.namedDispatch` is `false`, `negotiateHostCapabilities` caps `nested`, `maxDepth`, `background` and `backgroundDispatch` to `false`/`0` in the **effective** axes for structural consistency (`src/host-integration.cts`). The declared values above are still the host-capability record the matrix exists to hold; they are what a future named-dispatch upgrade would negotiate against.
|
||||
@@ -719,7 +719,7 @@ Sources consulted:
|
||||
- /moonshotai/kimi-code (Context7)
|
||||
|
||||
Documentation gaps:
|
||||
- **dispatch.namedDispatch — host capability vs. GSD surface.** Kimi Code *does* support user-authored named agents: "Beyond the three built-in sub-agents, you can define your own agents as Markdown files", discovered across five scopes (`--agent-file` > `.kimi-code/agents/`, `.agents/agents/` > extra dirs > `$KIMI_CODE_HOME/agents/` > built-in). The axis is `false` because GSD installs **no** agent files for this host, so its reachable dispatch surface is the three built-ins — flipping the axis without also shipping agent artifacts would reintroduce the dispatch failure recorded in `docs/migration/kimi-to-kimi-code.md` ("Every workflow that called a named GSD subagent … **failed at dispatch**"). Shipping GSD agent files to kimi-code is an unbuilt capability upgrade, not a gap in the host's documentation.
|
||||
- **dispatch.namedDispatch — host capability vs. MSD surface.** Kimi Code *does* support user-authored named agents: "Beyond the three built-in sub-agents, you can define your own agents as Markdown files", discovered across five scopes (`--agent-file` > `.kimi-code/agents/`, `.agents/agents/` > extra dirs > `$KIMI_CODE_HOME/agents/` > built-in). The axis is `false` because MSD installs **no** agent files for this host, so its reachable dispatch surface is the three built-ins — flipping the axis without also shipping agent artifacts would reintroduce the dispatch failure recorded in `docs/migration/kimi-to-kimi-code.md` ("Every workflow that called a named MSD subagent … **failed at dispatch**"). Shipping MSD agent files to kimi-code is an unbuilt capability upgrade, not a gap in the host's documentation.
|
||||
- **effortSurface — a real mechanism the vocabulary cannot name.** Kimi Code documents `/effort` (alias `/thinking`) for changing reasoning effort, but only as an interactive slash command; `-m, --model` is the only model-adjacent argv on its invocation. The axis vocabulary is `argv` | `none`, and neither is accurate here — `none` denies a mechanism the host has, `argv` claims one it does not expose. Kimi Code's descriptor was created a day after #2481 added the axis and has carried no value since. Resolving this needs a vocabulary decision (an interactive-only member, mirroring the deliberate absence of a config-file member), which is a negotiation change rather than a documentation one; until then the absent value degrades closed exactly as the sentinel does.
|
||||
- **dispatch.maxDepth** — nesting is documented but no depth bound is published, so the axis carries the `undocumented` sentinel rather than a guessed integer.
|
||||
- **runtime** — the published artifact is a single bundled binary; `Node.js ≥ 24.15.0` is stated as a *development* requirement. The sources are a TypeScript/Node monorepo, so `node` is the best-supported classification, but the docs do not name a canonical plugin-execution runtime (the same ambiguity noted for `codex` above).
|
||||
@@ -761,17 +761,17 @@ Sources consulted:
|
||||
Documentation gaps:
|
||||
- dispatch.nested / dispatch.maxDepth — ZCode's subagent docs do not state whether subagents can spawn further subagents or any depth bound.
|
||||
- configHome — skills/commands/agents homes are documented (`~/.zcode/skills`, `~/.zcode/commands`, `~/.zcode/agents`); the exact settings filename under `~/.zcode` (where MCP server config is stored) is not fully documented at time of writing.
|
||||
- Maintenance note — ZCode is a young, fast-moving app (observed at v3.2.x); these axes may need revision as its on-disk config layout stabilizes. Because ZCode also natively imports skills/MCP from `~/.claude`, installing GSD to BOTH `claude` and `zcode` can surface duplicated skills inside ZCode; this overlap is expected and documented.
|
||||
- Maintenance note — ZCode is a young, fast-moving app (observed at v3.2.x); these axes may need revision as its on-disk config layout stabilizes. Because ZCode also natively imports skills/MCP from `~/.claude`, installing MSD to BOTH `claude` and `zcode` can surface duplicated skills inside ZCode; this overlap is expected and documented.
|
||||
|
||||
EoS migration status (#2101, ADR-1239): ZCode's install is fully dogfooded through the declarative adapter — its shared-hooks exclusion (previously a hardcoded `!isZcode` branch in `bin/install.js`) is now folded onto `hostBehaviors.skipSharedHooksInstall`, byte-parity with the prior install (ZCode's golden install tree has zero hook files). The two capability upgrades anticipated for ZCode both remain **blocked** on undocumented on-disk formats — `hookBus` and `transport` above stay documented-but-unimplemented pending ZCode publishing those formats, and implementing a guessed format risks a false-green descriptor, so neither upgrade is wired:
|
||||
- **Hook automation** (the plugin `Hook` component, `hookBus: host` above) — https://zcode.z.ai/en/docs/plugin documents the capability only at a high level ("Automation hooks triggered on specific events"; components are "detected from directory layout, shown as badges"). No config file format, on-disk location, event-name vocabulary, or payload schema is published, so GSD cannot faithfully wire hook events into a plugin bundle. BLOCKED (undocumented on-disk hook-config format).
|
||||
- **Hook automation** (the plugin `Hook` component, `hookBus: host` above) — https://zcode.z.ai/en/docs/plugin documents the capability only at a high level ("Automation hooks triggered on specific events"; components are "detected from directory layout, shown as badges"). No config file format, on-disk location, event-name vocabulary, or payload schema is published, so MSD cannot faithfully wire hook events into a plugin bundle. BLOCKED (undocumented on-disk hook-config format).
|
||||
- **MCP registration** (`transport: mcp` above) — https://zcode.z.ai/en/docs/mcp-services confirms servers are "stored in the .zcode configuration file of the chosen scope" and accepts both a bare `{"server-name":{...}}` map and an `{"mcpServers":{...}}` wrapper shape, but does not document the exact settings filename/path or full schema (the docs describe the UI flow, not the on-disk contract) — this is the same gap already noted under `configHome` above. BLOCKED (undocumented settings-filename/schema gap).
|
||||
|
||||
---
|
||||
|
||||
## pi
|
||||
|
||||
> pi (pi.dev) is a bun-runtime Programmatic-CLI: it exposes an in-process TypeScript `ExtensionAPI` (`registerCommand`/`registerTool`/`registerProvider`/`pi.on`) rather than a settings-file or slash-markdown surface. GSD ships a single native-extension file (`pi/gsd.cjs`) installed to `~/.pi/agent/extensions/gsd.js` (global) or `.pi/extensions/gsd.js` (local) — the programmatic-CLI peer of the OpenCode/Kilo native-plugin binding. **Sourcing note:** the citations below are the pi.dev documentation pages named in ADR-1239 Stage 1 (#2102) as the source for each axis; this environment did not have live doc-fetch access at authoring time, so the Evidence column below is a paraphrase of pi's documented extension model rather than a verbatim excerpt — a maintainer with Context7/web access should verify the exact wording before treating this section as fully cited (flagged in the #2102 PR). **Partially discharged (#2470, 2026-07-20):** pi's extension-loader contract specifically has now been read at source — `packages/coding-agent/src/core/extensions/loader.ts` in `earendil-works/pi` — confirming `discoverExtensionsInDir()` keeps only names passing `isExtensionFile()` (`.ts`/`.js`, everything else skipped silently), that accepted files load via `jiti` (CommonJS and ESM alike), and that explicit `settings.json` paths bypass the filter. The remaining axes below are still paraphrase.
|
||||
> pi (pi.dev) is a bun-runtime Programmatic-CLI: it exposes an in-process TypeScript `ExtensionAPI` (`registerCommand`/`registerTool`/`registerProvider`/`pi.on`) rather than a settings-file or slash-markdown surface. MSD ships a single native-extension file (`pi/msd.cjs`) installed to `~/.pi/agent/extensions/msd.js` (global) or `.pi/extensions/msd.js` (local) — the programmatic-CLI peer of the OpenCode/Kilo native-plugin binding. **Sourcing note:** the citations below are the pi.dev documentation pages named in ADR-1239 Stage 1 (#2102) as the source for each axis; this environment did not have live doc-fetch access at authoring time, so the Evidence column below is a paraphrase of pi's documented extension model rather than a verbatim excerpt — a maintainer with Context7/web access should verify the exact wording before treating this section as fully cited (flagged in the #2102 PR). **Partially discharged (#2470, 2026-07-20):** pi's extension-loader contract specifically has now been read at source — `packages/coding-agent/src/core/extensions/loader.ts` in `earendil-works/pi` — confirming `discoverExtensionsInDir()` keeps only names passing `isExtensionFile()` (`.ts`/`.js`, everything else skipped silently), that accepted files load via `jiti` (CommonJS and ESM alike), and that explicit `settings.json` paths bypass the filter. The remaining axes below are still paraphrase.
|
||||
|
||||
| Axis | Value | Source | Evidence |
|
||||
|---|---|---|---|
|
||||
@@ -802,13 +802,13 @@ Documentation gaps:
|
||||
- dispatch.maxDepth / dispatch.background / dispatch.backgroundDispatch — recorded as `0`/`false`/`false` (not `undocumented`) because the absence of any dispatch primitive is itself the documented ceiling, matching `shouldFlattenDispatch`'s fail-closed default.
|
||||
- This section's Evidence-column wording was authored without live Context7/web-fetch access (see the sourcing note above the table) — verify against the cited pi.dev pages before relying on it for a future capability upgrade.
|
||||
|
||||
EoS migration status (#2102 Stage 1, ADR-1239): pi lands as a NET-NEW installable runtime — pure additive descriptor + installer wiring, no prior `runtime === 'pi'` branches existed to fold. `artifactLayout` is declared empty (`global: []`, `local: []`) — pi has no skills/commands/agents layout, and installs as **PLUGIN-ONLY**: `hostBehaviors.pluginOnlyInstall: true` explicitly skips `bin/install.js`'s generic flat-commands-and-agents fallback (the legacy path Claude Code's LOCAL layout also uses), which would otherwise write inert `commands/gsd-<cmd>.md` + `agents/gsd-<name>.md` reference files no part of pi ever reads. pi's `/gsd` command and `gsd_invoke` tool are registered **programmatically** by the native extension (`pi/gsd.cjs` → `extensions/gsd.js`, mirroring OpenCode/Kilo's `nativePlugin` shape) — pi has no host-read markdown surface at all (unlike Claude/OpenCode/Kilo, which scan a `commands/`/`command/` directory), so a declarative artifact surface would be dead weight, not merely unused. `dispatch.subagentToolkit: "undocumented"` and `dispatch.backgroundDispatch: false` are both required by the capability validator's dispatch schema and reflect that pi has no documented named-dispatch primitive at all. (Stage 1 originally also set `hostBehaviors.skipSharedHooksInstall:true`, reasoning the staged `hooks/*.js` bundle would be dead weight for pi the way it genuinely is for Kilo/ZCode — **corrected in Stage 2 below**: pi's native extension DOES spawn them, so they are live, not dead, and the flag was removed.)
|
||||
EoS migration status (#2102 Stage 1, ADR-1239): pi lands as a NET-NEW installable runtime — pure additive descriptor + installer wiring, no prior `runtime === 'pi'` branches existed to fold. `artifactLayout` is declared empty (`global: []`, `local: []`) — pi has no skills/commands/agents layout, and installs as **PLUGIN-ONLY**: `hostBehaviors.pluginOnlyInstall: true` explicitly skips `bin/install.js`'s generic flat-commands-and-agents fallback (the legacy path Claude Code's LOCAL layout also uses), which would otherwise write inert `commands/msd-<cmd>.md` + `agents/msd-<name>.md` reference files no part of pi ever reads. pi's `/msd` command and `msd_invoke` tool are registered **programmatically** by the native extension (`pi/msd.cjs` → `extensions/msd.js`, mirroring OpenCode/Kilo's `nativePlugin` shape) — pi has no host-read markdown surface at all (unlike Claude/OpenCode/Kilo, which scan a `commands/`/`command/` directory), so a declarative artifact surface would be dead weight, not merely unused. `dispatch.subagentToolkit: "undocumented"` and `dispatch.backgroundDispatch: false` are both required by the capability validator's dispatch schema and reflect that pi has no documented named-dispatch primitive at all. (Stage 1 originally also set `hostBehaviors.skipSharedHooksInstall:true`, reasoning the staged `hooks/*.js` bundle would be dead weight for pi the way it genuinely is for Kilo/ZCode — **corrected in Stage 2 below**: pi's native extension DOES spawn them, so they are live, not dead, and the flag was removed.)
|
||||
|
||||
EoS migration status (#2102 Stage 2, ADR-1239): Stage 1's "in-process `gsd-core` command-routing hub" framing was aspirational and is corrected here — no fully-populated hub factory exists anywhere in gsd-core (every `createHub()` caller in the tree builds a single-family hub for its own narrow purpose), so `/gsd` and `gsd_invoke` instead dispatch via **SUBPROCESS REUSE**: `dispatchGsdCommand` (`src/shell-command-projection.cts`) spawns `gsd-core/bin/gsd-tools.cjs <family> [subcommand] ... --cwd <dir> --raw --json-errors` bounded and non-throwing, mirroring the precedent already established for the OpenCode/Kilo hook bridge (`.opencode/plugins/gsd-core.js`'s "Architecture: SUBPROCESS REUSE" header). The companion MCP server's `gsd_invoke_command` tool dispatches through the SAME shared helper (it had the identical `createHub()`-with-no-args bug). `/gsd`'s command handler is `handler(args, ctx)` (pi's real ExtensionAPI shape — a raw args string, not `execute(ctx)`); `gsd_invoke`'s tool handler is the real 5-arg `execute(toolCallId, params, signal, onUpdate, ctx)`. The event surface (`EXTENSION_EVENT_SURFACES.pi`, `src/host-integration.cts`) now declares the full ~30-event pi ExtensionAPI vocabulary (was a placeholder `['tool_call']`), and `pi/gsd.cjs` binds `session_start` (→ `gsd-ensure-canonical-path.js`), `before_agent_start` (→ `gsd-workflow-guard.js`, a forward-compatible no-op today since that hook's triggers are tool-scoped), `session_before_compact` (→ `gsd-context-monitor.js`), and `tool_call`, each as a bounded fail-open `spawnSync` subprocess (mirroring `.opencode/plugins/gsd-core.js`'s `runHook`). `modelMode: active` is realized via `pi.on('before_provider_request', ...)`, which resolves a tier through the model-catalog's now-populated `runtimeTierDefaults.pi` entries (bare anthropic ids — `claude-opus-4-8`/`claude-sonnet-5`/`claude-haiku-4-5`, matching the `claude` runtime's own ids since pi talks the anthropic API) and returns a modified payload, or `undefined` (fail-open, pi's model left untouched) when resolution comes back null — **not** `registerProvider`, which would register a new model provider rather than steering pi's existing built-in anthropic models.
|
||||
EoS migration status (#2102 Stage 2, ADR-1239): Stage 1's "in-process `msd-core` command-routing hub" framing was aspirational and is corrected here — no fully-populated hub factory exists anywhere in msd-core (every `createHub()` caller in the tree builds a single-family hub for its own narrow purpose), so `/msd` and `msd_invoke` instead dispatch via **SUBPROCESS REUSE**: `dispatchMsdCommand` (`src/shell-command-projection.cts`) spawns `msd-core/bin/msd-tools.cjs <family> [subcommand] ... --cwd <dir> --raw --json-errors` bounded and non-throwing, mirroring the precedent already established for the OpenCode/Kilo hook bridge (`.opencode/plugins/msd-core.js`'s "Architecture: SUBPROCESS REUSE" header). The companion MCP server's `msd_invoke_command` tool dispatches through the SAME shared helper (it had the identical `createHub()`-with-no-args bug). `/msd`'s command handler is `handler(args, ctx)` (pi's real ExtensionAPI shape — a raw args string, not `execute(ctx)`); `msd_invoke`'s tool handler is the real 5-arg `execute(toolCallId, params, signal, onUpdate, ctx)`. The event surface (`EXTENSION_EVENT_SURFACES.pi`, `src/host-integration.cts`) now declares the full ~30-event pi ExtensionAPI vocabulary (was a placeholder `['tool_call']`), and `pi/msd.cjs` binds `session_start` (→ `msd-ensure-canonical-path.js`), `before_agent_start` (→ `msd-workflow-guard.js`, a forward-compatible no-op today since that hook's triggers are tool-scoped), `session_before_compact` (→ `msd-context-monitor.js`), and `tool_call`, each as a bounded fail-open `spawnSync` subprocess (mirroring `.opencode/plugins/msd-core.js`'s `runHook`). `modelMode: active` is realized via `pi.on('before_provider_request', ...)`, which resolves a tier through the model-catalog's now-populated `runtimeTierDefaults.pi` entries (bare anthropic ids — `claude-opus-4-8`/`claude-sonnet-5`/`claude-haiku-4-5`, matching the `claude` runtime's own ids since pi talks the anthropic API) and returns a modified payload, or `undefined` (fail-open, pi's model left untouched) when resolution comes back null — **not** `registerProvider`, which would register a new model provider rather than steering pi's existing built-in anthropic models.
|
||||
|
||||
**Adversarial-review correction (#2102 Stage 2, post-review):** the event bridges above and the `/gsd` tokenizer's `hooks/lib/git-cmd.js` require were DEAD in a real install — Stage 1's `hostBehaviors.skipSharedHooksInstall:true` meant pi shipped NO `hooks/` directory at all, so `runHook('gsd-ensure-canonical-path.js', ...)` etc. always hit the "hook file absent → silent no-op" branch, and the tokenizer always fell back to plain whitespace-splitting. The tests masked this because they run against the dev tree, where `hooks/` genuinely exists. **Fix:** `capabilities/pi/capability.json` no longer sets `skipSharedHooksInstall` — pi is architecturally identical to OpenCode here (`hooksSurface: "none"` + a native extension that spawns the staged hooks), not to Kilo/ZCode (`hooksSurface: "none"` with NO plugin surface, where the same hooks genuinely are dead weight). pi now installs `hooks/` + `hooks/lib/` (27 entries: the same `INSTALLED_HOOK_FILES` set OpenCode gets) alongside `extensions/gsd.js`, verified end-to-end via a real `node bin/install.js --pi --global`/`--local` — `resolveEngineRoot`'s walk-up from the installed extension's own directory finds `ENGINE_ROOT/hooks/{gsd-ensure-canonical-path.js,gsd-workflow-guard.js,gsd-context-monitor.js,lib/git-cmd.js}`, and each bridge/`runHook` call exits 0 against the real installed files. `hooksSurface: "none"` + `configFormat: "none"` + `writesSharedSettings: false` are unaffected — no settings/hooks.json/config.toml is written for pi; the extension spawns hooks by absolute path, not via a config-file hook bus. `tests/fixtures/golden-install-parity/pi.json` grew from 292 → 320 entries (the 28 new `hooks/`/`hooks/lib/` files); `commands/`, `agents/`, `skills/` remain absent (`pluginOnlyInstall` is untouched — it only gates the declarative-markdown surfaces, not hooks). `tests/install-minimal-hooks.test.cjs`'s #1821 suite moved pi from the Kilo/ZCode (no-hooks) group into the OpenCode (ships-hooks) group accordingly.
|
||||
**Adversarial-review correction (#2102 Stage 2, post-review):** the event bridges above and the `/msd` tokenizer's `hooks/lib/git-cmd.js` require were DEAD in a real install — Stage 1's `hostBehaviors.skipSharedHooksInstall:true` meant pi shipped NO `hooks/` directory at all, so `runHook('msd-ensure-canonical-path.js', ...)` etc. always hit the "hook file absent → silent no-op" branch, and the tokenizer always fell back to plain whitespace-splitting. The tests masked this because they run against the dev tree, where `hooks/` genuinely exists. **Fix:** `capabilities/pi/capability.json` no longer sets `skipSharedHooksInstall` — pi is architecturally identical to OpenCode here (`hooksSurface: "none"` + a native extension that spawns the staged hooks), not to Kilo/ZCode (`hooksSurface: "none"` with NO plugin surface, where the same hooks genuinely are dead weight). pi now installs `hooks/` + `hooks/lib/` (27 entries: the same `INSTALLED_HOOK_FILES` set OpenCode gets) alongside `extensions/msd.js`, verified end-to-end via a real `node bin/install.js --pi --global`/`--local` — `resolveEngineRoot`'s walk-up from the installed extension's own directory finds `ENGINE_ROOT/hooks/{msd-ensure-canonical-path.js,msd-workflow-guard.js,msd-context-monitor.js,lib/git-cmd.js}`, and each bridge/`runHook` call exits 0 against the real installed files. `hooksSurface: "none"` + `configFormat: "none"` + `writesSharedSettings: false` are unaffected — no settings/hooks.json/config.toml is written for pi; the extension spawns hooks by absolute path, not via a config-file hook bus. `tests/fixtures/golden-install-parity/pi.json` grew from 292 → 320 entries (the 28 new `hooks/`/`hooks/lib/` files); `commands/`, `agents/`, `skills/` remain absent (`pluginOnlyInstall` is untouched — it only gates the declarative-markdown surfaces, not hooks). `tests/install-minimal-hooks.test.cjs`'s #1821 suite moved pi from the Kilo/ZCode (no-hooks) group into the OpenCode (ships-hooks) group accordingly.
|
||||
|
||||
**Superseded in part (#3023, 2026-08-07):** the bundle's directory NAME became runtime-descriptor-driven (`hostBehaviors.sharedHooksDirName`, default `hooks`); pi sets it to `gsd-hooks` because pi reserves `hooks/` as its deprecated extension directory and `checkDeprecatedExtensionDirs()` in `packages/coding-agent/src/migrations.ts` warns on bare directory existence (no emptiness check, unlike its `tools/` sibling — source read 2026-08-07); the set of staged files and every other negotiated axis is UNCHANGED (`hooksSurface: "none"`, `configFormat: "none"`, `writesSharedSettings: false`, `pluginOnlyInstall` all untouched — only the directory name moved); `pi/gsd.cjs` now resolves the bundle by probing `gsd-hooks` then `hooks` so dev checkouts and half-upgraded trees still work.
|
||||
**Superseded in part (#3023, 2026-08-07):** the bundle's directory NAME became runtime-descriptor-driven (`hostBehaviors.sharedHooksDirName`, default `hooks`); pi sets it to `msd-hooks` because pi reserves `hooks/` as its deprecated extension directory and `checkDeprecatedExtensionDirs()` in `packages/coding-agent/src/migrations.ts` warns on bare directory existence (no emptiness check, unlike its `tools/` sibling — source read 2026-08-07); the set of staged files and every other negotiated axis is UNCHANGED (`hooksSurface: "none"`, `configFormat: "none"`, `writesSharedSettings: false`, `pluginOnlyInstall` all untouched — only the directory name moved); `pi/msd.cjs` now resolves the bundle by probing `msd-hooks` then `hooks` so dev checkouts and half-upgraded trees still work.
|
||||
|
||||
## vscode
|
||||
|
||||
@@ -829,9 +829,9 @@ EoS migration status (#2102 Stage 2, ADR-1239): Stage 1's "in-process `gsd-core`
|
||||
| embeddingMode | imperative | https://code.visualstudio.com/api/references/vscode-api | The extension is loaded in-process by the extension host and calls the `vscode` namespace API directly (`vscode.commands.registerCommand`, `vscode.chat.createChatParticipant`, `vscode.lm.registerTool`) — an in-process programmatic API, not a config-file-only integration. |
|
||||
| commandSurface | palette | https://code.visualstudio.com/api/extension-guides/command | Commands are contributed via `contributes.commands` in package.json and registered with `vscode.commands.registerCommand`, surfaced through the Command Palette (and the Chat view via the chat participant) — not a markdown/TOML slash-command file format. |
|
||||
| modelMode | active | https://code.visualstudio.com/api/extension-guides/ai/language-model | The `vscode.lm` namespace lets an extension actively select a model (`vscode.lm.selectChatModels`) and send requests to it programmatically, rather than only reading a static config value. |
|
||||
| hookBus | engine | https://code.visualstudio.com/api/references/activation-events | VS Code has no cross-extension lifecycle-hook bus that GSD subscribes to; the extension host (the "engine" here, per this axis's own `host`/`engine`/`none` vocabulary) owns activation events, and GSD's own hook lifecycle runs fully in-process/engine-owned inside the extension. |
|
||||
| hookBus | engine | https://code.visualstudio.com/api/references/activation-events | VS Code has no cross-extension lifecycle-hook bus that MSD subscribes to; the extension host (the "engine" here, per this axis's own `host`/`engine`/`none` vocabulary) owns activation events, and MSD's own hook lifecycle runs fully in-process/engine-owned inside the extension. |
|
||||
| stateIO | sandboxed-storage | https://code.visualstudio.com/api/references/vscode-api#Memento | `context.globalState`/`context.workspaceState` (both `Memento`) are the extension's persistent storage surface — sandboxed key/value storage scoped to the extension, not unrestricted local filesystem access. |
|
||||
| transport | mcp | https://code.visualstudio.com/api/extension-guides/ai/mcp | VS Code 1.99 added native MCP client support; on the Web (webworker) entry, full GSD command dispatch is available through VS Code's native MCP client connecting to the GSD companion MCP server (`gsd-mcp-server`), not an in-process Node dispatch (which the web entry cannot run at all). |
|
||||
| transport | mcp | https://code.visualstudio.com/api/extension-guides/ai/mcp | VS Code 1.99 added native MCP client support; on the Web (webworker) entry, full MSD command dispatch is available through VS Code's native MCP client connecting to the MSD companion MCP server (`msd-mcp-server`), not an in-process Node dispatch (which the web entry cannot run at all). |
|
||||
| runtime | sandboxed-web | https://code.visualstudio.com/api/extension-guides/web-extensions | The `browser` entry point (`vscode/browser.js`) runs in a webworker context with no Node core modules — the Web Extension execution model VS Code documents for extensions that must run in vscode.dev/github.dev. |
|
||||
| effortSurface | undocumented | no authoritative doc — per-host reasoning-effort survey, #2481 (`09b535ac0`) | This host's documentation states no reasoning-effort setting, so the axis carries the fail-closed sentinel rather than inheriting a profile baseline. No host-specific URL is cited because the finding is an ABSENCE: #2481 surveyed all hosts for a reasoning-effort mechanism and found one only for claude/opencode/codex. |
|
||||
| dispatch.namedDispatch | true | https://code.visualstudio.com/docs/copilot/chat/chat-agent-mode#_agent-mode-tools | Registered `languageModelTools` (and the chat participant) are addressable by name — the primary agent references a tool/participant by its declared name/`toolReferenceName`, not only positionally. |
|
||||
@@ -870,7 +870,7 @@ validator/host-integration coverage ONLY — it is deliberately NOT a CLI-instal
|
||||
(`vscode/extension.js`, `vscode/browser.js`, `vscode/host-binding.js`, `vscode/package.json`) is
|
||||
distributed via the Marketplace/VSIX, not `npx --vscode` — there is no `docs/how-to/install-on-
|
||||
your-runtime.md` entry for it. Dispatch is SUBPROCESS REUSE on desktop (the same shared
|
||||
`dispatchGsdCommand` in `gsd-core/bin/lib/shell-command-projection.cjs` the pi extension and the
|
||||
`dispatchMsdCommand` in `msd-core/bin/lib/shell-command-projection.cjs` the pi extension and the
|
||||
companion MCP server use) via `vscode/extension.js`'s `main` entry (Node). The `browser` entry
|
||||
(`vscode/browser.js`) is a SEPARATE, independently zero-Node-API file: it does NOT require
|
||||
`host-binding.js` because that module's engine-lib dependencies (`state-io.cjs`,
|
||||
@@ -879,10 +879,10 @@ companion MCP server use) via `vscode/extension.js`'s `main` entry (Node). The `
|
||||
Node's `fs`/`os`/`path` at module-load time — requiring any of them from a webworker context would
|
||||
throw immediately. `browser.js` instead composes its own minimal surface directly against
|
||||
`vscode.lm`, and its command/tool/chat handlers surface an honest "full dispatch is unavailable on
|
||||
web; configure the GSD MCP server" message rather than a silent failure. The chat participant
|
||||
(`@gsd`) and Language Model Tools (a representative 3-tool set — `gsd_progress`, `gsd_workstreams`,
|
||||
`gsd_plan_phase` — matching real shipped skills that map onto a single, safe, read-only
|
||||
`gsd-tools.cjs` command) are registered on BOTH entries identically; only the dispatch behavior
|
||||
web; configure the MSD MCP server" message rather than a silent failure. The chat participant
|
||||
(`@msd`) and Language Model Tools (a representative 3-tool set — `msd_progress`, `msd_workstreams`,
|
||||
`msd_plan_phase` — matching real shipped skills that map onto a single, safe, read-only
|
||||
`msd-tools.cjs` command) are registered on BOTH entries identically; only the dispatch behavior
|
||||
differs. `#runSubagent` wiring (`registerSubagentDispatch`/`dispatchAsSubagent`, gated on
|
||||
`chat.subagents.allowInvocationsFromSubagents` availability, fail-soft on older/Insiders-gated
|
||||
hosts) adds a belt-and-suspenders `maxDepth: 5` ceiling independent of whatever VS Code's own chat
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 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
|
||||
This is the normative reference for the MSD Host-Integration Interface (ADR-1239)
|
||||
— the versioned, negotiated contract over which any host embeds MSD's
|
||||
orchestration loop. The published surface is the SDK entry
|
||||
(`src/host-integration-sdk.cts`); this document specifies every symbol on it.
|
||||
|
||||
@@ -43,8 +43,8 @@ degrades to `1` (strictly sequential) on anything other than a positive safe
|
||||
integer (missing, the `undocumented` sentinel, zero, negative, fractional, an
|
||||
unsafe integer, or a non-numeric type); there is no negotiated host/engine
|
||||
reduction the way `maxDepth` has one — the resolved value passes through
|
||||
unchanged. Its live transport (`GSD_DISPATCH_MAX_CONCURRENCY`) is read only at
|
||||
the CLI query layer (`gsd-tools query dispatch-capacity`), never inside this
|
||||
unchanged. Its live transport (`MSD_DISPATCH_MAX_CONCURRENCY`) is read only at
|
||||
the CLI query layer (`msd-tools query dispatch-capacity`), never inside this
|
||||
pure negotiation module, and takes precedence over the descriptor value, which
|
||||
in turn takes precedence over the `1` fallback.
|
||||
|
||||
@@ -88,6 +88,6 @@ differential attribution check, `tests/emitted-attribution.test.cjs`, ADR-2719).
|
||||
## 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)
|
||||
- [Tutorial: embed MSD in a new host](../tutorials/embed-msd-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)
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# Long-running operations and async external jobs
|
||||
|
||||
> **Reference** (Diátaxis). The operation-classification policy and the async
|
||||
> external-job contract that GSD executors use when a task legitimately exceeds
|
||||
> external-job contract that MSD executors use when a task legitimately exceeds
|
||||
> a child-agent timeout. The producer is the default-off `external-job`
|
||||
> Capability (#1164, part of #1105); the core loop consumes the manifest
|
||||
> (#1165 — `external_job_waiting`).
|
||||
|
||||
## 1. The problem
|
||||
|
||||
Heavy GSD phases (HPC solvers, model training, large simulations) can
|
||||
Heavy MSD phases (HPC solvers, model training, large simulations) can
|
||||
legitimately exceed short child-agent timeouts. Raising the timeout alone is
|
||||
not sufficient: it prevents legitimate subagents from being killed, but it
|
||||
also lets truly hung commands consume the whole agent budget. GSD must
|
||||
also lets truly hung commands consume the whole agent budget. MSD must
|
||||
distinguish legitimate heavy work from suspicious hangs, keep safety nets
|
||||
finite, and avoid blocking an agent turn on hours-long compute.
|
||||
|
||||
@@ -112,9 +112,9 @@ The `external-job` Capability declares its config keys in
|
||||
|---|---|---|---|
|
||||
| `external_job.enabled` | `false` | — | Capability gate (`when` on both contributions). Master toggle; default-off. |
|
||||
| `external_job.backend` | `slurm` | — | Pluggability seam (LSF/PBS/K8s future). Core never interprets it. |
|
||||
| `external_job.artifact_dir` | `Artifacts/jobs` | `GSD_EXTERNAL_JOB_ARTIFACT_DIR` | Adapter surfaces the resolved root in `submit` output. |
|
||||
| `external_job.submit_timeout_ms` | `30000` | `GSD_SLURM_SUBMIT_TIMEOUT_MS` | Adapter bounds the `sbatch` subprocess. |
|
||||
| `external_job.poll_timeout_ms` | `15000` | `GSD_SLURM_POLL_TIMEOUT_MS` | Adapter bounds the `squeue`/`sacct` subprocess. |
|
||||
| `external_job.artifact_dir` | `Artifacts/jobs` | `MSD_EXTERNAL_JOB_ARTIFACT_DIR` | Adapter surfaces the resolved root in `submit` output. |
|
||||
| `external_job.submit_timeout_ms` | `30000` | `MSD_SLURM_SUBMIT_TIMEOUT_MS` | Adapter bounds the `sbatch` subprocess. |
|
||||
| `external_job.poll_timeout_ms` | `15000` | `MSD_SLURM_POLL_TIMEOUT_MS` | Adapter bounds the `squeue`/`sacct` subprocess. |
|
||||
|
||||
Config keys live nested under `external_job` in `.planning/config.json`, e.g.:
|
||||
|
||||
@@ -131,5 +131,5 @@ to the registry default rather than producing `NaN` (no guessing).
|
||||
- **How-To:** [`../how-to/async-external-jobs.md`](../how-to/async-external-jobs.md) — using the SLURM adapter.
|
||||
- **Contract:** [`planning-artifacts.md`](./planning-artifacts.md) — the manifest stability contract.
|
||||
- **Capability manifest:** [`../../capabilities/external-job/capability.json`](../../capabilities/external-job/capability.json).
|
||||
- **Pure module:** `gsd-core/src/external-job.cts` → `gsd-core/bin/lib/external-job.cjs`.
|
||||
- **Pure module:** `msd-core/src/external-job.cts` → `msd-core/bin/lib/external-job.cjs`.
|
||||
- **Operator CLI:** `scripts/slurm-adapter.cjs`.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# `gsd capability` Command Reference
|
||||
# `msd capability` Command Reference
|
||||
|
||||
> **CLI form:** `gsd capability`
|
||||
> **CLI form:** `msd capability`
|
||||
> **Canonical ADR:** [ADR-1244](../adr/1244-capability-ecosystem.md)
|
||||
> **See also:** [Capability Manifest Reference](capability-manifest.md) · [How to develop a capability](../how-to/develop-a-capability.md) · [The capability trust model](../explanation/capability-trust-model.md)
|
||||
|
||||
The `capability` family manages the installation, upgrade, removal, and inspection of GSD capabilities — both first-party (shipped) and third-party overlays. A row for this command also appears in [docs/COMMANDS.md](../COMMANDS.md) (that file is not edited here).
|
||||
The `capability` family manages the installation, upgrade, removal, and inspection of MSD capabilities — both first-party (shipped) and third-party overlays. A row for this command also appears in [docs/COMMANDS.md](../COMMANDS.md) (that file is not edited here).
|
||||
|
||||
**Implemented:** `install`, `update`, `remove`, `list`, `outdated`, `trust`, `disable`, `enable` (plus the pre-existing `state` and `set` introspection/activation subcommands).
|
||||
|
||||
@@ -17,7 +17,7 @@ The `capability` family manages the installation, upgrade, removal, and inspecti
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability install <spec> [--integrity sha512-<hash>] [--scope global|project] [--yes] [--shared-file <rel>]…
|
||||
msd capability install <spec> [--integrity sha512-<hash>] [--scope global|project] [--yes] [--shared-file <rel>]…
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
@@ -37,13 +37,13 @@ gsd capability install <spec> [--integrity sha512-<hash>] [--scope global|projec
|
||||
|
||||
**Behaviour**
|
||||
|
||||
Resolves `<spec>` to a versioned, staged capability bundle. The pipeline is: fetch → verify integrity or SHA pin → check `engines.gsd` against the installed GSD version → disclose executable surfaces (hooks, command modules, MCP servers) and instruction surfaces (skills) → obtain consent (a declarative capability needs none; an executable one requires `--yes` — disclosed instruction surfaces do not by themselves trigger this requirement) → validate the incoming manifest against the trust invariants → extract to the scope root → write the ledger entry atomically.
|
||||
Resolves `<spec>` to a versioned, staged capability bundle. The pipeline is: fetch → verify integrity or SHA pin → check `engines.msd` against the installed MSD version → disclose executable surfaces (hooks, command modules, MCP servers) and instruction surfaces (skills) → obtain consent (a declarative capability needs none; an executable one requires `--yes` — disclosed instruction surfaces do not by themselves trigger this requirement) → validate the incoming manifest against the trust invariants → extract to the scope root → write the ledger entry atomically.
|
||||
|
||||
An overlay whose `id` uses a reserved first-party prefix (`gsd-`, `gsd-core-`, `anthropic-`) is rejected before extraction. Install never executes capability code; staging is copy-only. A declined install (executable surface, no `--yes`) writes **nothing** — no bundle, no ledger entry, no shared-file edits.
|
||||
An overlay whose `id` uses a reserved first-party prefix (`msd-`, `msd-core-`, `anthropic-`) is rejected before extraction. Install never executes capability code; staging is copy-only. A declined install (executable surface, no `--yes`) writes **nothing** — no bundle, no ledger entry, no shared-file edits.
|
||||
|
||||
A best-effort reconciliation sweep runs before the mutation to recover any crash orphans from a prior interrupted operation.
|
||||
|
||||
The ledger file (`<scope-root>/.gsd-capabilities.json`, see [Install layout](#install-layout)) records the installed version, source, integrity hash, owned files, and any fragments written into shared files.
|
||||
The ledger file (`<scope-root>/.msd-capabilities.json`, see [Install layout](#install-layout)) records the installed version, source, integrity hash, owned files, and any fragments written into shared files.
|
||||
|
||||
---
|
||||
|
||||
@@ -52,7 +52,7 @@ The ledger file (`<scope-root>/.gsd-capabilities.json`, see [Install layout](#in
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability update [<id> | --all] [--scope global|project] [--yes] [--shared-file <rel>]…
|
||||
msd capability update [<id> | --all] [--scope global|project] [--yes] [--shared-file <rel>]…
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
@@ -93,7 +93,7 @@ For third-party capabilities, a version whose executable set (hooks, command mod
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability remove <id> [--purge-data] [--scope global|project]
|
||||
msd capability remove <id> [--purge-data] [--scope global|project]
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
@@ -113,7 +113,7 @@ gsd capability remove <id> [--purge-data] [--scope global|project]
|
||||
|
||||
Reads the ledger entry for `<id>` and removes exactly: the owned files listed in `files`, and the fragments written into shared files listed in `sharedEdits` (e.g. hook registrations spliced into a `settings.json`). Shared files themselves are not deleted; only the capability's marker-isolated fragments are stripped. The ledger entry is removed atomically after all file operations complete.
|
||||
|
||||
First-party capabilities (shipped with GSD) **cannot** be removed via this subcommand — `remove` rejects a first-party `id` and points at the product uninstaller (`gsd --uninstall`).
|
||||
First-party capabilities (shipped with MSD) **cannot** be removed via this subcommand — `remove` rejects a first-party `id` and points at the product uninstaller (`msd --uninstall`).
|
||||
|
||||
---
|
||||
|
||||
@@ -122,14 +122,14 @@ First-party capabilities (shipped with GSD) **cannot** be removed via this subco
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability disable <id> [--config-dir <path>] [--runtime <r>] [--scope <s>]
|
||||
msd capability disable <id> [--config-dir <path>] [--runtime <r>] [--scope <s>]
|
||||
```
|
||||
|
||||
**Behaviour**
|
||||
|
||||
Marks the capability **inactive** in the runtime activation state — identical to `gsd capability set <id> --off`. A disabled capability stays on disk; it is excluded from the active surface and contributes no hooks, config keys, or loop extension registrations until re-enabled. This toggles the capability-state layer (the runtime config), not the install ledger.
|
||||
Marks the capability **inactive** in the runtime activation state — identical to `msd capability set <id> --off`. A disabled capability stays on disk; it is excluded from the active surface and contributes no hooks, config keys, or loop extension registrations until re-enabled. This toggles the capability-state layer (the runtime config), not the install ledger.
|
||||
|
||||
> **Scope: first-party capabilities only.** `<id>` is validated against the **build-time first-party registry** (the generated `capability-registry.cjs`). An installed **third-party overlay** — one added with `gsd capability install …` — is **not** in that registry, so `disable` rejects it with `unknown capability: "<id>"`. Deactivate an installed overlay with [`gsd capability remove <id> --scope <scope>`](#remove) instead.
|
||||
> **Scope: first-party capabilities only.** `<id>` is validated against the **build-time first-party registry** (the generated `capability-registry.cjs`). An installed **third-party overlay** — one added with `msd capability install …` — is **not** in that registry, so `disable` rejects it with `unknown capability: "<id>"`. Deactivate an installed overlay with [`msd capability remove <id> --scope <scope>`](#remove) instead.
|
||||
|
||||
`enable` reverses a disable without re-fetching.
|
||||
|
||||
@@ -140,14 +140,14 @@ Marks the capability **inactive** in the runtime activation state — identical
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability enable <id> [--config-dir <path>] [--runtime <r>] [--scope <s>]
|
||||
msd capability enable <id> [--config-dir <path>] [--runtime <r>] [--scope <s>]
|
||||
```
|
||||
|
||||
**Behaviour**
|
||||
|
||||
Clears the inactive flag for `<id>` in the runtime activation state — identical to `gsd capability set <id> --on`. On the next GSD invocation the capability is included in the active surface again, subject to its `engines.gsd` range (an incompatible capability is still skipped with a warning at load time).
|
||||
Clears the inactive flag for `<id>` in the runtime activation state — identical to `msd capability set <id> --on`. On the next MSD invocation the capability is included in the active surface again, subject to its `engines.msd` range (an incompatible capability is still skipped with a warning at load time).
|
||||
|
||||
> **Scope: first-party capabilities only.** Like `disable`, `enable` validates `<id>` against the build-time first-party registry and rejects an installed overlay with `unknown capability: "<id>"`. There is no `enable` for an installed overlay — re-install it with [`gsd capability install …`](#install) if it was removed.
|
||||
> **Scope: first-party capabilities only.** Like `disable`, `enable` validates `<id>` against the build-time first-party registry and rejects an installed overlay with `unknown capability: "<id>"`. There is no `enable` for an installed overlay — re-install it with [`msd capability install …`](#install) if it was removed.
|
||||
|
||||
---
|
||||
|
||||
@@ -156,7 +156,7 @@ Clears the inactive flag for `<id>` in the runtime activation state — identica
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability set <id> [--on | --enable | --off | --disable] [--gate <key>=<bool>]… [--config-dir <path>] [--runtime <r>] [--scope <s>]
|
||||
msd capability set <id> [--on | --enable | --off | --disable] [--gate <key>=<bool>]… [--config-dir <path>] [--runtime <r>] [--scope <s>]
|
||||
```
|
||||
|
||||
**Flags**
|
||||
@@ -177,7 +177,7 @@ gsd capability set <id> [--on | --enable | --off | --disable] [--gate <key>=<boo
|
||||
- The **enabled** axis (`--on`/`--off`) toggles whether the capability's skills are on the runtime surface (the same mechanism `disable`/`enable` use; `disable`/`enable` are thin aliases for `set … --off`/`--on`).
|
||||
- The **gate** axis (`--gate`) writes capability-owned config keys into `.planning/config.json`.
|
||||
|
||||
> **Scope: first-party capabilities only.** `set` validates `<id>` against the **build-time first-party registry** (the generated `capability-registry.cjs`); an unrecognized id — including any installed **third-party overlay** — is rejected with `unknown capability: "<id>"` and no writes are performed. `set` is for the activation/gate axes of first-party capabilities; to turn off an installed overlay use [`gsd capability remove`](#remove).
|
||||
> **Scope: first-party capabilities only.** `set` validates `<id>` against the **build-time first-party registry** (the generated `capability-registry.cjs`); an unrecognized id — including any installed **third-party overlay** — is rejected with `unknown capability: "<id>"` and no writes are performed. `set` is for the activation/gate axes of first-party capabilities; to turn off an installed overlay use [`msd capability remove`](#remove).
|
||||
|
||||
A **gate** is a dotted config key declared in the capability's `config` slice whose boolean value controls whether one of the capability's loop hooks fires. Setting a gate to `false` stops that hook running while leaving the capability surfaced; setting it to `true` re-arms it. A `--gate <key>=…` whose `<key>` is not a declared config key of `<id>`, or whose value is not boolean, is rejected and **no** writes are performed (the whole operation is validated before any state is written).
|
||||
|
||||
@@ -192,7 +192,7 @@ In `--raw` mode the full `{ capabilities, warnings, errors }` envelope is emitte
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability list [--json] [--scope global|project]
|
||||
msd capability list [--json] [--scope global|project]
|
||||
```
|
||||
|
||||
**Flags**
|
||||
@@ -228,13 +228,13 @@ Lists capabilities visible to the current session: first-party capabilities (fro
|
||||
|
||||
| Value | Meaning |
|
||||
|---|---|
|
||||
| `active` | Present and (for overlays) compatible with the running GSD version and — for project-scope overlays — backed by a user consent record on this machine. |
|
||||
| `incompatible` | An overlay whose `engines.gsd` range does not satisfy the current GSD version; skipped with a warning at load time. |
|
||||
| `inactive` | A **project-scope** overlay that is present on disk (and may have a committed-looking project ledger) but has **no user consent record on this machine** (#1459). It is *discovered but not activated*: it contributes no surfaces and runs nothing. The accompanying `reason` field explains why. Consent it by re-installing through the lifecycle (`gsd capability install … --scope project`). |
|
||||
| `active` | Present and (for overlays) compatible with the running MSD version and — for project-scope overlays — backed by a user consent record on this machine. |
|
||||
| `incompatible` | An overlay whose `engines.msd` range does not satisfy the current MSD version; skipped with a warning at load time. |
|
||||
| `inactive` | A **project-scope** overlay that is present on disk (and may have a committed-looking project ledger) but has **no user consent record on this machine** (#1459). It is *discovered but not activated*: it contributes no surfaces and runs nothing. The accompanying `reason` field explains why. Consent it by re-installing through the lifecycle (`msd capability install … --scope project`). |
|
||||
|
||||
The `reason` field is present on **overlay** rows: `null` for active/incompatible overlays and a short explanation for `inactive` ones. First-party rows omit `reason` (and `scope`/`source`/`status` are always `first-party`/`first-party`/`active`).
|
||||
|
||||
> Whether a capability has been turned off via `disable` is reported by `gsd capability state` (the activation-state view), not by `list`.
|
||||
> Whether a capability has been turned off via `disable` is reported by `msd capability state` (the activation-state view), not by `list`.
|
||||
|
||||
---
|
||||
|
||||
@@ -243,7 +243,7 @@ The `reason` field is present on **overlay** rows: `null` for active/incompatibl
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability outdated [--json] [--scope global|project]
|
||||
msd capability outdated [--json] [--scope global|project]
|
||||
```
|
||||
|
||||
**Flags**
|
||||
@@ -294,7 +294,7 @@ The per-source "update available?" matrix (ADR-1244 D6):
|
||||
|
||||
| Value | Meaning |
|
||||
|---|---|
|
||||
| `outdated` | Re-resolving the recorded source would fetch a newer version than the installed one (for an npm range, the latest version **matching the recorded range**). Run `gsd capability update <id>` to upgrade. |
|
||||
| `outdated` | Re-resolving the recorded source would fetch a newer version than the installed one (for an npm range, the latest version **matching the recorded range**). Run `msd capability update <id>` to upgrade. |
|
||||
| `current` | The installed version is the latest the recorded source would resolve to (or newer). |
|
||||
| `pinned` | The recorded source is pinned to an **immutable** ref (git `#sha:`/`#tag:`, or a bare git `#<ref>` that resolves to a tag) or an exact npm version; `update` re-resolves to the same commit/tag/version, so it can never be `outdated`. A bare git ref that resolves to a **mutable branch** is never `pinned`. |
|
||||
| `manual` | The source (a bare tarball URL) cannot be auto-checked; re-install from a new URL to upgrade. |
|
||||
@@ -318,13 +318,13 @@ Bodies are not content-scanned, at install, update, or any later point — discl
|
||||
|
||||
### `trust`
|
||||
|
||||
Manage the **user-owned consent store** (#1459) that gates project-scope third-party capability activation. The store lives at `${GSD_HOME||homedir()}/.gsd/consent.json` — **outside any repository** — and records, per `(realpath(projectRoot), capability id)`, the bundle integrity and disclosure signature you consented to **on this machine**. A project-scope overlay is inactive until such a record exists (so a forged or cloned in-repo project ledger activates nothing on its own); installing a project-scope capability through the lifecycle writes the record, and removing it revokes the record.
|
||||
Manage the **user-owned consent store** (#1459) that gates project-scope third-party capability activation. The store lives at `${MSD_HOME||homedir()}/.msd/consent.json` — **outside any repository** — and records, per `(realpath(projectRoot), capability id)`, the bundle integrity and disclosure signature you consented to **on this machine**. A project-scope overlay is inactive until such a record exists (so a forged or cloned in-repo project ledger activates nothing on its own); installing a project-scope capability through the lifecycle writes the record, and removing it revokes the record.
|
||||
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability trust list [--scope project] [--json]
|
||||
gsd capability trust revoke <id> [--project <path>]
|
||||
msd capability trust list [--scope project] [--json]
|
||||
msd capability trust revoke <id> [--project <path>]
|
||||
```
|
||||
|
||||
**`trust list`** emits a JSON array of the consent records for the current consent home:
|
||||
@@ -356,14 +356,14 @@ The `install` subcommand accepts the following source specification forms.
|
||||
| Form | Example | Adapter | `--integrity` |
|
||||
|---|---|---|---|
|
||||
| Git URL with tag | `https://github.com/org/repo.git#v1.2.0` | Git — clones/fetches at the specified tag; `#sha:<40-hex>` pins a specific commit. | **Rejected** — a clone is a directory tree, not a single hashable artifact. Pin the commit with `#sha:<commit>` instead. |
|
||||
| npm package | `npm:@org/gsd-capability-foo@^1.0.0` | npm — resolves via `npm dist-tags` / semver range; installs with `--ignore-scripts`. | Verified over the `npm pack` `.tgz` bytes (same SRI sha512 domain as a tarball). |
|
||||
| npm package | `npm:@org/msd-capability-foo@^1.0.0` | npm — resolves via `npm dist-tags` / semver range; installs with `--ignore-scripts`. | Verified over the `npm pack` `.tgz` bytes (same SRI sha512 domain as a tarball). |
|
||||
| Tarball URL | `https://host/path/cap-x.y.z.tgz` | Tarball — fetches over HTTPS. | Verified over the downloaded `.tgz` bytes. |
|
||||
| Local path | `./local/path` (or an absolute path) | Local — copies from the filesystem path. Auto-update detection is not available for this form. | **Rejected** — a local directory has no single hashable artifact; integrity pinning is not supported for local sources. |
|
||||
| Registry name | `my-cap@gsd-registry` | **Reserved — not yet implemented.** The spec form parses, but there is no first-party registry endpoint, so resolution throws and the install fails. Use a git, npm, tarball, or local source today. | n/a |
|
||||
| Registry name | `my-cap@msd-registry` | **Reserved — not yet implemented.** The spec form parses, but there is no first-party registry endpoint, so resolution throws and the install fails. Use a git, npm, tarball, or local source today. | n/a |
|
||||
|
||||
Which source forms are *permitted* is governed by the `capabilities.strict_known_registries` policy (see [Configuration](../CONFIGURATION.md) and [the capability trust model](../explanation/capability-trust-model.md)): `null`/absent is permissive, `[]` is lockdown (no third-party sources), and a host allowlist permits only matching registries. This policy is **project-scoped** — it is read from the current project's `.planning/config.json` and applied to installs run in that project regardless of `--scope`; there is no machine-wide source allowlist. (A present-but-unparseable config fails **closed** — external installs are blocked until it is fixed.)
|
||||
|
||||
All permitted forms pass through the same pipeline: fetch → verify integrity or SHA pin → check `engines.gsd` → obtain consent → validate → extract → record ledger.
|
||||
All permitted forms pass through the same pipeline: fetch → verify integrity or SHA pin → check `engines.msd` → obtain consent → validate → extract → record ledger.
|
||||
|
||||
---
|
||||
|
||||
@@ -373,7 +373,7 @@ Installed overlay capabilities are written under a **scope root** selected by `-
|
||||
|
||||
| Scope | Scope root | Bundle path | Ledger file |
|
||||
|---|---|---|---|
|
||||
| `global` | `$GSD_HOME`, defaulting to your home directory | `<root>/.gsd/capabilities/<id>/` | `<root>/.gsd-capabilities.json` |
|
||||
| `project` | the current project root | `<root>/.gsd/capabilities/<id>/` | `<root>/.gsd-capabilities.json` |
|
||||
| `global` | `$MSD_HOME`, defaulting to your home directory | `<root>/.msd/capabilities/<id>/` | `<root>/.msd-capabilities.json` |
|
||||
| `project` | the current project root | `<root>/.msd/capabilities/<id>/` | `<root>/.msd-capabilities.json` |
|
||||
|
||||
The ledger is the commit point for installs and upgrades. Its entries record the installed version, original source, integrity hash, owned files, and shared-file edits. A reconciliation sweep on the next GSD run resolves crash orphans (files on disk without a ledger entry, or ledger entries with missing files). These paths are exactly the ones the runtime registry overlay reads when composing installed capabilities, so an `install` is visible to the loop without any further step.
|
||||
The ledger is the commit point for installs and upgrades. Its entries record the installed version, original source, integrity hash, owned files, and shared-file edits. A reconciliation sweep on the next MSD run resolves crash orphans (files on disk without a ledger entry, or ledger entries with missing files). These paths are exactly the ones the runtime registry overlay reads when composing installed capabilities, so an `install` is visible to the loop without any further step.
|
||||
@@ -1,6 +1,6 @@
|
||||
# PLAN.md schema reference
|
||||
|
||||
A per-plan `PLAN.md` is GSD Core's executable unit of work — a structured document that tells an executor agent exactly what to build and how to verify it was built correctly. This page documents its structure. See [docs index](../README.md).
|
||||
A per-plan `PLAN.md` is MSD Core's executable unit of work — a structured document that tells an executor agent exactly what to build and how to verify it was built correctly. This page documents its structure. See [docs index](../README.md).
|
||||
|
||||
---
|
||||
|
||||
@@ -14,7 +14,7 @@ Plans live inside phase directories at:
|
||||
|
||||
For example: `.planning/phases/03-post-feed/03-02-PLAN.md` (Phase 3, Plan 2).
|
||||
|
||||
Plans are produced by the `gsd-planner` agent (spawned by `/gsd-plan-phase`) and consumed by `execute-phase`. A phase typically contains between one and four plans; plans within a phase are assigned to execution waves so that independent work runs in parallel.
|
||||
Plans are produced by the `msd-planner` agent (spawned by `/msd-plan-phase`) and consumed by `execute-phase`. A phase typically contains between one and four plans; plans within a phase are assigned to execution waves so that independent work runs in parallel.
|
||||
|
||||
---
|
||||
|
||||
@@ -68,7 +68,7 @@ must_haves:
|
||||
| `phase` | Yes | string | Phase identifier, e.g. `03-post-feed`. |
|
||||
| `plan` | Yes | string | Plan number within the phase, e.g. `02`. |
|
||||
| `type` | Yes | `execute` or `tdd` | `execute` for standard plans; `tdd` for test-driven plans where tests are written before implementation. |
|
||||
| `wave` | Yes | integer | Execution wave. Plans in wave 1 run in parallel (no dependencies). Plans in wave 2+ wait for all plans in the previous wave to complete. Pre-computed at plan time by `gsd-planner`. |
|
||||
| `wave` | Yes | integer | Execution wave. Plans in wave 1 run in parallel (no dependencies). Plans in wave 2+ wait for all plans in the previous wave to complete. Pre-computed at plan time by `msd-planner`. |
|
||||
| `depends_on` | Yes | array of plan IDs | Plans this plan must wait for. Empty array = wave 1. Accepts three forms, resolved in order: the full plan id (`"03-01-auth-hardening"`), the canonical phase-plan prefix (`"03-01"`), or the bare plan number (`"01"`, #3897) — which resolves to the sibling plan in the **same phase** whose canonical id ends `-01`. The bare form is in-phase only; it never resolves across phases. If two plans in the same phase share a bare form, the first one (by sorted plan-file order) wins — deterministic, but arbitrary when the collision happens, so prefer the full or canonical form when phase has any short-form collision risk. Example: `["03-01"]` means this plan runs after Plan 01 in Phase 3; from within Phase 3 itself, `["01"]` means the same thing. |
|
||||
| `files_modified` | Yes | array of paths | Every file this plan creates or modifies. Used by the plan-checker to detect same-wave file conflicts and by execute-phase for merge tracking. |
|
||||
| `files_deleted` | No | array of paths | Every file this plan deliberately **removes**. The post-wave cleanup gauntlet blocks the merge of any executor branch whose diff deletes a file — a net against a mass-deletion accident — and this field is the opt-in that names the exceptions. Matching is exact per path after separator normalization: a declared path merges, an undeclared one still blocks that plan's entry (and only that entry). There are no globs and no directory prefixes, so a declaration can never authorize more than it literally lists. Omit the field and the guard's original unconditional block stays in force, which is why absence is always the safe default (#3003). Counts toward same-wave conflict detection alongside `files_modified`: a plan deleting a file another plan in the same wave is editing is the sharpest conflict there is — one branch removes what the other is writing — so the two plans are pushed into different waves regardless of which side holds the deletion. |
|
||||
@@ -79,12 +79,12 @@ must_haves:
|
||||
| `status` | No | `superseded` | Marks a plan that was deliberately reassigned or abandoned mid-phase and will never be executed. A `status: superseded` plan is excluded from the phase's plan and summary counts, so it never holds the phase below 100%. See [Superseded plans](#superseded-plans). Any other value (or the field's absence) has no effect on counting. |
|
||||
| `estimate` | No | object | Projected execution cost: `{tokens, raw_tokens, tasks, confidence}` (#2631, [ADR-2629](../adr/2629-phase-effort-estimation-calibration.md)). `tokens` is an `estimateTokens`-scale projection with the project's calibration factor **already applied** (which is why the plan-checker passes `--calibrated` to `estimate-check` — re-applying it would square the correction); `confidence` (`low`/`med`/`high`) is **derived from the calibration sample count, never self-rated**. Additive and optional — a plan without it behaves exactly as before. A plan estimated above `workflow.smart_zone_tokens` is flagged with a split recommendation at plan time; the flag is advisory and never blocks. |
|
||||
| `must_haves` | Yes | object | Goal-backward verification criteria. See below. |
|
||||
| `agent_hint` | No | string | Per-plan specialist executor routing (#1689). Name of a subagent that shares the `gsd-executor` execution contract (reads `execute-plan.md`, atomic-commit protocol). When the named agent resolves on the active runtime (an agent file exists in the runtime's agent dir), `execute-phase` dispatches it instead of `gsd-executor`. Unset/unresolved → `gsd-executor`, byte-identical to today. Default-on via `workflow.agent_hint_routing`; set `false` to disable. See [Per-plan executor routing](#per-plan-executor-routing). |
|
||||
| `gap_closure` | Only in gap-closure mode | string, exact match | Must be exactly the literal lowercase `true` — validated as a string comparison, not a YAML boolean, so `True`, `TRUE`, `yes`, and `1` are all rejected. Required on every plan generated by `/gsd-plan-phase --gaps`, checked by the `plan-gap-closure` schema (`src/frontmatter.cts`) rather than `plan`. `/gsd-execute-phase --gaps-only` filters strictly on this field, so an omitted or wrong-valued `gap_closure` on a gap-closure plan means it is silently skipped — zero executors spawned, no error (#2847). Standard and reviews-mode plans validate against the unmodified `plan` schema, which neither requires nor checks this field (nothing rejects it as an extra field either, if present). |
|
||||
| `agent_hint` | No | string | Per-plan specialist executor routing (#1689). Name of a subagent that shares the `msd-executor` execution contract (reads `execute-plan.md`, atomic-commit protocol). When the named agent resolves on the active runtime (an agent file exists in the runtime's agent dir), `execute-phase` dispatches it instead of `msd-executor`. Unset/unresolved → `msd-executor`, byte-identical to today. Default-on via `workflow.agent_hint_routing`; set `false` to disable. See [Per-plan executor routing](#per-plan-executor-routing). |
|
||||
| `gap_closure` | Only in gap-closure mode | string, exact match | Must be exactly the literal lowercase `true` — validated as a string comparison, not a YAML boolean, so `True`, `TRUE`, `yes`, and `1` are all rejected. Required on every plan generated by `/msd-plan-phase --gaps`, checked by the `plan-gap-closure` schema (`src/frontmatter.cts`) rather than `plan`. `/msd-execute-phase --gaps-only` filters strictly on this field, so an omitted or wrong-valued `gap_closure` on a gap-closure plan means it is silently skipped — zero executors spawned, no error (#2847). Standard and reviews-mode plans validate against the unmodified `plan` schema, which neither requires nor checks this field (nothing rejects it as an extra field either, if present). |
|
||||
|
||||
### Per-plan executor routing
|
||||
|
||||
A plan can opt into a **specialist executor** by setting `agent_hint:` to the name of a subagent that shares the `gsd-executor` execution contract — it reads `execute-plan.md`, follows the atomic-commit protocol, and carries Read/Edit/Write/Bash. A Flutter specialist, for example:
|
||||
A plan can opt into a **specialist executor** by setting `agent_hint:` to the name of a subagent that shares the `msd-executor` execution contract — it reads `execute-plan.md`, follows the atomic-commit protocol, and carries Read/Edit/Write/Bash. A Flutter specialist, for example:
|
||||
|
||||
```yaml
|
||||
---
|
||||
@@ -92,7 +92,7 @@ agent_hint: well-me-flutter-engineer
|
||||
---
|
||||
```
|
||||
|
||||
At dispatch, `execute-phase` resolves the hint against the **active runtime's agent directory** (both project-local and user-global, across the runtime's filename variants — `.md`, `.agent.md`, `.toml`, …) and dispatches the named subagent via `subagent_type`. If the field is absent, blank, or the named agent does not resolve, the plan dispatches to `gsd-executor` — byte-identical to behavior without the field. Routing is gated by `workflow.agent_hint_routing` (default-on; see [CONFIGURATION](../CONFIGURATION.md#workflow-toggles)).
|
||||
At dispatch, `execute-phase` resolves the hint against the **active runtime's agent directory** (both project-local and user-global, across the runtime's filename variants — `.md`, `.agent.md`, `.toml`, …) and dispatches the named subagent via `subagent_type`. If the field is absent, blank, or the named agent does not resolve, the plan dispatches to `msd-executor` — byte-identical to behavior without the field. Routing is gated by `workflow.agent_hint_routing` (default-on; see [CONFIGURATION](../CONFIGURATION.md#workflow-toggles)).
|
||||
|
||||
The specialist agent is an ordinary agent file (e.g. `agents/well-me-flutter-engineer.md` on Claude Code); there is no separate registration manifest.
|
||||
|
||||
@@ -115,7 +115,7 @@ A phase with 13 plans, two of them `superseded`, then reads `11/11 → complete`
|
||||
|
||||
## `must_haves` field
|
||||
|
||||
`must_haves` captures what must be observably true for the phase goal to be achieved. It is derived during planning and verified after execution by the `gsd-verifier` agent.
|
||||
`must_haves` captures what must be observably true for the phase goal to be achieved. It is derived during planning and verified after execution by the `msd-verifier` agent.
|
||||
|
||||
### Sub-fields
|
||||
|
||||
@@ -159,12 +159,12 @@ Lists the workflow files associated with executing the plan. Always includes the
|
||||
|
||||
```xml
|
||||
<execution_context>
|
||||
@~/.claude/gsd-core/workflows/execute-plan.md
|
||||
@~/.claude/gsd-core/templates/summary.md
|
||||
@~/.claude/msd-core/workflows/execute-plan.md
|
||||
@~/.claude/msd-core/templates/summary.md
|
||||
</execution_context>
|
||||
```
|
||||
|
||||
These `@` paths point at the local GSD install, not at repository files. The prefix shown here (`~/.claude/gsd-core/…`) is the Claude global-install location; other runtimes and local installs resolve to their own install directory — for example `.cursor/gsd-core/…`, or an absolute project path for a `--local` install. Because the prefix is install-relative, this block is not clone-portable: a committed plan carries whichever prefix the authoring install had. Execution does not depend on it — `/gsd-execute-phase` loads the execute-plan workflow from its own installed copy — so the block records the execution context rather than resolvable repository references. Contrast `<context>` (below), whose repository-relative `@` paths resolve after a `git clone`.
|
||||
These `@` paths point at the local MSD install, not at repository files. The prefix shown here (`~/.claude/msd-core/…`) is the Claude global-install location; other runtimes and local installs resolve to their own install directory — for example `.cursor/msd-core/…`, or an absolute project path for a `--local` install. Because the prefix is install-relative, this block is not clone-portable: a committed plan carries whichever prefix the authoring install had. Execution does not depend on it — `/msd-execute-phase` loads the execute-plan workflow from its own installed copy — so the block records the execution context rather than resolvable repository references. Contrast `<context>` (below), whose repository-relative `@` paths resolve after a `git clone`.
|
||||
|
||||
### `<context>`
|
||||
|
||||
@@ -208,7 +208,7 @@ Contains one or more `<task>` elements. Every task element must carry `<name>`,
|
||||
2. **Prior-phase artifact dependency** — a generated schema, a migration's dist output, a contract file from an earlier phase. Cross-phase `depends_on` does not cross phase boundaries, so `<precondition>` is the explicit pointer.
|
||||
3. **Environment variable / runtime configuration** — a tool, API, or script the task invokes requires an env var or runtime config that exists *now*, not at plan time.
|
||||
|
||||
Full emission rules, anti-patterns ("the system is ready" is not checkable; do not use `<precondition>` for intra-plan sequencing — that is what `depends_on` is for), and the contract triad mapping: see `gsd-core/references/planner-preconditions.md`.
|
||||
Full emission rules, anti-patterns ("the system is ready" is not checkable; do not use `<precondition>` for intra-plan sequencing — that is what `depends_on` is for), and the contract triad mapping: see `msd-core/references/planner-preconditions.md`.
|
||||
|
||||
---
|
||||
|
||||
@@ -238,9 +238,9 @@ Full emission rules, anti-patterns ("the system is ready" is not checkable; do n
|
||||
|
||||
**Autonomy:** inserting a `checkpoint:decision` means the plan contains a checkpoint, so its frontmatter must set `autonomous: false`.
|
||||
|
||||
**Override:** `/gsd-plan-phase --no-reversibility-gates` (`REVERSIBILITY_GATES=false`) suppresses checkpoint insertion for intentionally-unattended runs. Ratings are still recorded and `costly` items are still flagged — the override changes what stops the run, not what the plan remembers.
|
||||
**Override:** `/msd-plan-phase --no-reversibility-gates` (`REVERSIBILITY_GATES=false`) suppresses checkpoint insertion for intentionally-unattended runs. Ratings are still recorded and `costly` items are still flagged — the override changes what stops the run, not what the plan remembers.
|
||||
|
||||
Full taxonomy, emission rules, and anti-patterns (chiefly: rating everything `one-way` produces checkpoint fatigue; prefer *removing* irreversibility over gating it): see `gsd-core/references/planner-reversibility.md`.
|
||||
Full taxonomy, emission rules, and anti-patterns (chiefly: rating everything `one-way` produces checkpoint fatigue; prefer *removing* irreversibility over gating it): see `msd-core/references/planner-reversibility.md`.
|
||||
|
||||
---
|
||||
|
||||
@@ -274,7 +274,7 @@ Full taxonomy, emission rules, and anti-patterns (chiefly: rating everything `on
|
||||
|
||||
**Optional and back-compat for the structural validator:** a plan that omits `auto_select` on every `checkpoint:decision` task still passes `verify plan-structure` — the validator only rejects a *declared* `auto_select` that doesn't match any option id. What changes is auto-mode's *runtime* behavior (escalate instead of guessing), not plan-structure validity.
|
||||
|
||||
Full behavioral reference: `gsd-core/references/checkpoints.md` → `checkpoint:decision`.
|
||||
Full behavioral reference: `msd-core/references/checkpoints.md` → `checkpoint:decision`.
|
||||
|
||||
---
|
||||
|
||||
@@ -283,7 +283,7 @@ Full behavioral reference: `gsd-core/references/checkpoints.md` → `checkpoint:
|
||||
| Type | Use | Autonomy |
|
||||
|---|---|---|
|
||||
| `auto` | Everything the executor can do independently. | Fully autonomous. |
|
||||
| `tracer` | The leading thin end-to-end slice a plan starts with by default (tracer-first) — production-quality, wired through every layer, with a real end-to-end `<verify>`. | Fully autonomous; after committing, the executor runs the tracer's `<verify>` as an early integration gate. A tracer carrying `gate="blocking-human"` STOPs for a human in every mode, auto included. Otherwise autonomous runs halt on failure before expansion, and interactive runs honor `workflow.human_verify_mode` (#3299): under the `end-of-phase` default a `<verify>` carrying only `<automated>` is re-run and, on success, expansion continues with **no** checkpoint (failure still halts); under `mid-flight`, or when the tracer carries `<human-check>`, a `checkpoint:human-verify` is presented. Full precedence chain: `gsd-core/references/checkpoints.md` → "Tracer feedback gate". |
|
||||
| `tracer` | The leading thin end-to-end slice a plan starts with by default (tracer-first) — production-quality, wired through every layer, with a real end-to-end `<verify>`. | Fully autonomous; after committing, the executor runs the tracer's `<verify>` as an early integration gate. A tracer carrying `gate="blocking-human"` STOPs for a human in every mode, auto included. Otherwise autonomous runs halt on failure before expansion, and interactive runs honor `workflow.human_verify_mode` (#3299): under the `end-of-phase` default a `<verify>` carrying only `<automated>` is re-run and, on success, expansion continues with **no** checkpoint (failure still halts); under `mid-flight`, or when the tracer carries `<human-check>`, a `checkpoint:human-verify` is presented. Full precedence chain: `msd-core/references/checkpoints.md` → "Tracer feedback gate". |
|
||||
| `checkpoint:human-verify` | Visual or functional verification that requires a human to look at a running UI or service. | Pauses execution; presents to the developer; resumes on approval. |
|
||||
| `checkpoint:decision` | Implementation choices that arose during execution and require the developer's input. | Pauses execution; presents options; resumes on selection. In auto-mode, an `auto_select="<option-id>"` attribute lets the plan name the unattended answer — see [Auto-select](#auto-select). |
|
||||
| `checkpoint:human-action` | Truly unavoidable manual steps (account creation, hardware interaction). Used sparingly. | Pauses execution; resumes on confirmation. |
|
||||
@@ -327,7 +327,7 @@ Plans that contain any checkpoint task must set `autonomous: false` in frontmatt
|
||||
|
||||
## Plan quality dimensions
|
||||
|
||||
The `gsd-plan-checker` agent reviews every PLAN.md across 12 dimensions before execution begins. A plan that fails any BLOCKER-severity check is returned to `gsd-planner` for revision (up to 3 iterations):
|
||||
The `msd-plan-checker` agent reviews every PLAN.md across 12 dimensions before execution begins. A plan that fails any BLOCKER-severity check is returned to `msd-planner` for revision (up to 3 iterations):
|
||||
|
||||
| Dimension | What it checks |
|
||||
|---|---|
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Planning artifacts reference
|
||||
|
||||
The `.planning/` directory is GSD Core's shared memory for a project. Every workflow reads from it, writes to it, and leaves an auditable trail of decisions. This page maps every file, its purpose, and which command produces or consumes it. See [docs index](../README.md).
|
||||
The `.planning/` directory is MSD Core's shared memory for a project. Every workflow reads from it, writes to it, and leaves an auditable trail of decisions. This page maps every file, its purpose, and which command produces or consumes it. See [docs index](../README.md).
|
||||
|
||||
---
|
||||
|
||||
@@ -50,34 +50,34 @@ The `.planning/` directory is GSD Core's shared memory for a project. Every work
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Canonical project identity: what it is, who it is for, core value, requirements, constraints, and key decisions. Updated throughout the project lifecycle as the product evolves. |
|
||||
| **Produced by** | `/gsd-new-project` (initial creation, including `/gsd-onboard` handoff); updated by `/gsd-complete-milestone` as decisions are validated. |
|
||||
| **Consumed by** | All planning workflows; `gsd-phase-researcher`, `gsd-planner` (context); `discuss-phase` (prior decisions); `gsd-plan-checker` (project constraints). |
|
||||
| **Produced by** | `/msd-new-project` (initial creation, including `/msd-onboard` handoff); updated by `/msd-complete-milestone` as decisions are validated. |
|
||||
| **Consumed by** | All planning workflows; `msd-phase-researcher`, `msd-planner` (context); `discuss-phase` (prior decisions); `msd-plan-checker` (project constraints). |
|
||||
|
||||
Includes an optional `## Business Context` section (Customer, Revenue model, Success metric, Strategy notes) for monetized or customer-facing projects — four one-line fields that connect business outcomes to requirement prioritization. It is deleted for internal tools, experiments, or meta workspaces, and reviewed at each milestone by `/gsd-complete-milestone` when present.
|
||||
Includes an optional `## Business Context` section (Customer, Revenue model, Success metric, Strategy notes) for monetized or customer-facing projects — four one-line fields that connect business outcomes to requirement prioritization. It is deleted for internal tools, experiments, or meta workspaces, and reviewed at each milestone by `/msd-complete-milestone` when present.
|
||||
|
||||
### `ROADMAP.md`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Milestone and phase listing with goals, requirement IDs, success criteria, and canonical references per phase. The single source of truth for what the project is building and in what order. |
|
||||
| **Produced by** | `/gsd-new-project` (initial creation, including `/gsd-onboard` handoff); updated by `/gsd-phase --insert` and `/gsd-complete-milestone`. |
|
||||
| **Consumed by** | `/gsd-discuss-phase`, `/gsd-plan-phase`, `/gsd-execute-phase`; all orchestration commands that need phase information; `gsd-planner`, `gsd-plan-checker`, `gsd-phase-researcher`. |
|
||||
| **Produced by** | `/msd-new-project` (initial creation, including `/msd-onboard` handoff); updated by `/msd-phase --insert` and `/msd-complete-milestone`. |
|
||||
| **Consumed by** | `/msd-discuss-phase`, `/msd-plan-phase`, `/msd-execute-phase`; all orchestration commands that need phase information; `msd-planner`, `msd-plan-checker`, `msd-phase-researcher`. |
|
||||
|
||||
### `REQUIREMENTS.md`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Numbered, checkable acceptance criteria for the project. Each requirement carries an ID (e.g., `AUTH-01`) that maps to roadmap phases. Marks requirements complete as phases are executed. |
|
||||
| **Produced by** | `/gsd-new-project` (initial creation, including `/gsd-onboard` handoff); requirements marked complete by `execute-phase`. |
|
||||
| **Consumed by** | `gsd-planner` (plans must address all phase requirement IDs); `gsd-plan-checker` Dimension 1 (requirement coverage); `discuss-phase` (prior requirements). |
|
||||
| **Produced by** | `/msd-new-project` (initial creation, including `/msd-onboard` handoff); requirements marked complete by `execute-phase`. |
|
||||
| **Consumed by** | `msd-planner` (plans must address all phase requirement IDs); `msd-plan-checker` Dimension 1 (requirement coverage); `discuss-phase` (prior requirements). |
|
||||
|
||||
### `STATE.md`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Living position tracker — current phase and plan, progress metrics, accumulated decisions, session continuity notes. Read at the start of every workflow run. Updated after every significant action. |
|
||||
| **Produced by** | `/gsd-new-project` (initial creation, including `/gsd-onboard` handoff); updated continuously by all phase workflows, `/gsd-pause-work`, `/gsd-resume-work`. |
|
||||
| **Consumed by** | All orchestration workflows; `/gsd-progress`; ad-hoc task execution via `/gsd-quick`; `gsd-planner` and `gsd-phase-researcher` (project decisions). |
|
||||
| **Produced by** | `/msd-new-project` (initial creation, including `/msd-onboard` handoff); updated continuously by all phase workflows, `/msd-pause-work`, `/msd-resume-work`. |
|
||||
| **Consumed by** | All orchestration workflows; `/msd-progress`; ad-hoc task execution via `/msd-quick`; `msd-planner` and `msd-phase-researcher` (project decisions). |
|
||||
|
||||
See [STATE.md schema](state-md.md) for the full field reference.
|
||||
|
||||
@@ -86,8 +86,8 @@ See [STATE.md schema](state-md.md) for the full field reference.
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Workflow configuration: model profiles, research and plan-checker toggles, git branching strategy, Nyquist validation, parallelisation settings, and per-agent model overrides. |
|
||||
| **Produced by** | `/gsd-new-project` (initial creation); `/gsd-settings` (interactive editing). |
|
||||
| **Consumed by** | Every workflow and subagent — read at init time via `gsd-tools query config-get`. |
|
||||
| **Produced by** | `/msd-new-project` (initial creation); `/msd-settings` (interactive editing). |
|
||||
| **Consumed by** | Every workflow and subagent — read at init time via `msd-tools query config-get`. |
|
||||
|
||||
See [CONFIGURATION](../CONFIGURATION.md) for the complete schema.
|
||||
|
||||
@@ -95,17 +95,17 @@ See [CONFIGURATION](../CONFIGURATION.md) for the complete schema.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Brownfield onboarding index that records artifact status, whether codebase mapping is complete, and the next recommended GSD command after first-time setup. |
|
||||
| **Produced by** | `/gsd-onboard` after `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, and `STATE.md` all exist. |
|
||||
| **Consumed by** | Humans reviewing first-time setup; future `/gsd-onboard` runs when confirming existing onboarding state. |
|
||||
| **Purpose** | Brownfield onboarding index that records artifact status, whether codebase mapping is complete, and the next recommended MSD command after first-time setup. |
|
||||
| **Produced by** | `/msd-onboard` after `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, and `STATE.md` all exist. |
|
||||
| **Consumed by** | Humans reviewing first-time setup; future `/msd-onboard` runs when confirming existing onboarding state. |
|
||||
|
||||
### `MILESTONES.md` (optional)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Historical record of completed milestones. Populated as each milestone is closed; provides an archival snapshot of what shipped and when. |
|
||||
| **Produced by** | `/gsd-complete-milestone`. |
|
||||
| **Consumed by** | `/gsd-audit-milestone`; human review. |
|
||||
| **Produced by** | `/msd-complete-milestone`. |
|
||||
| **Consumed by** | `/msd-audit-milestone`; human review. |
|
||||
|
||||
### `DECISIONS-INDEX.md` (optional)
|
||||
|
||||
@@ -120,8 +120,8 @@ See [CONFIGURATION](../CONFIGURATION.md) for the complete schema.
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Machine-readable pause state written when work is interrupted. Contains the resume point, in-progress context, and continuation instructions. Consumed exactly once — on resume. |
|
||||
| **Produced by** | `/gsd-pause-work`. |
|
||||
| **Consumed by** | `/gsd-resume-work`. |
|
||||
| **Produced by** | `/msd-pause-work`. |
|
||||
| **Consumed by** | `/msd-resume-work`. |
|
||||
|
||||
---
|
||||
|
||||
@@ -134,8 +134,8 @@ All per-phase files live under `.planning/phases/<NN>-<slug>/` where `NN` is the
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Implementation decisions captured before planning begins. Contains the phase boundary (`<domain>`), locked decisions with `D-NN` identifiers (`<decisions>`), canonical document references (`<canonical_refs>`), existing code insights (`<code_context>`), specific inspirations (`<specifics>`), and deferred ideas (`<deferred>`). |
|
||||
| **Produced by** | `/gsd-discuss-phase` (interactive discussion or PRD/ADR express paths). |
|
||||
| **Consumed by** | `gsd-phase-researcher` (what to investigate); `gsd-planner` (locked decisions); `gsd-plan-checker` Dimension 7 (context compliance). |
|
||||
| **Produced by** | `/msd-discuss-phase` (interactive discussion or PRD/ADR express paths). |
|
||||
| **Consumed by** | `msd-phase-researcher` (what to investigate); `msd-planner` (locked decisions); `msd-plan-checker` Dimension 7 (context compliance). |
|
||||
|
||||
See [CONTEXT.md schema](context-md.md) for the full field reference.
|
||||
|
||||
@@ -144,7 +144,7 @@ See [CONTEXT.md schema](context-md.md) for the full field reference.
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Human-readable audit trail of the discuss-phase session: areas discussed, options presented, selections made, deferred ideas, and items left to Claude's discretion. Not consumed by automated workflows. |
|
||||
| **Produced by** | `/gsd-discuss-phase` (`git_commit` step). |
|
||||
| **Produced by** | `/msd-discuss-phase` (`git_commit` step). |
|
||||
| **Consumed by** | Human review; retrospectives. |
|
||||
|
||||
### `<NN>-RESEARCH.md`
|
||||
@@ -152,32 +152,32 @@ See [CONTEXT.md schema](context-md.md) for the full field reference.
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Technical research findings produced before planning. Answers "What do I need to know to plan this phase well?" — covers domain analysis, patterns, risks, an Architectural Responsibility Map, and a Validation Architecture section (used by the Nyquist gate). |
|
||||
| **Produced by** | `/gsd-plan-phase` via `gsd-phase-researcher` agent. |
|
||||
| **Consumed by** | `gsd-planner` (planning inputs); `gsd-plan-checker` Dimension 7c (tier compliance), Dimension 8 (Nyquist), Dimension 11 (research resolution); `gsd-pattern-mapper` (file list source). |
|
||||
| **Produced by** | `/msd-plan-phase` via `msd-phase-researcher` agent. |
|
||||
| **Consumed by** | `msd-planner` (planning inputs); `msd-plan-checker` Dimension 7c (tier compliance), Dimension 8 (Nyquist), Dimension 11 (research resolution); `msd-pattern-mapper` (file list source). |
|
||||
|
||||
### `<NN>-VALIDATION.md`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Nyquist-inspired validation strategy derived from the `## Validation Architecture` section of RESEARCH.md. Specifies automated test coverage requirements that plans must honour. |
|
||||
| **Produced by** | `/gsd-plan-phase` (Step 5.5, when `workflow.nyquist_validation` is enabled and RESEARCH.md contains a Validation Architecture section). |
|
||||
| **Consumed by** | `gsd-plan-checker` Dimension 8 (Check 8e gate — must exist before Nyquist checks proceed); `gsd-verifier`. |
|
||||
| **Produced by** | `/msd-plan-phase` (Step 5.5, when `workflow.nyquist_validation` is enabled and RESEARCH.md contains a Validation Architecture section). |
|
||||
| **Consumed by** | `msd-plan-checker` Dimension 8 (Check 8e gate — must exist before Nyquist checks proceed); `msd-verifier`. |
|
||||
|
||||
### `<NN>-PATTERNS.md`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Codebase analog map produced by `gsd-pattern-mapper`. For each file to be created or modified this phase, identifies the closest existing analog, classifies the file's role and data flow, and extracts concrete code excerpts. Guides the planner towards consistent patterns. |
|
||||
| **Produced by** | `/gsd-plan-phase` via `gsd-pattern-mapper` agent (optional; skipped if `workflow.pattern_mapper: false`). |
|
||||
| **Consumed by** | `gsd-planner` (pattern guidance); `gsd-plan-checker` Dimension 12 (pattern compliance). |
|
||||
| **Purpose** | Codebase analog map produced by `msd-pattern-mapper`. For each file to be created or modified this phase, identifies the closest existing analog, classifies the file's role and data flow, and extracts concrete code excerpts. Guides the planner towards consistent patterns. |
|
||||
| **Produced by** | `/msd-plan-phase` via `msd-pattern-mapper` agent (optional; skipped if `workflow.pattern_mapper: false`). |
|
||||
| **Consumed by** | `msd-planner` (pattern guidance); `msd-plan-checker` Dimension 12 (pattern compliance). |
|
||||
|
||||
### `<NN>-<PP>-PLAN.md`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Executable plan for a single unit of work within the phase. Contains YAML frontmatter (wave, dependencies, files, requirements, `must_haves`), an objective, context references, XML-structured tasks with `<read_first>`, `<action>`, `<verify>`, and `<acceptance_criteria>` fields, and verification criteria. |
|
||||
| **Produced by** | `/gsd-plan-phase` via `gsd-planner` agent. One file per plan — e.g., `03-02-PLAN.md` is Phase 3, Plan 2. |
|
||||
| **Consumed by** | `/gsd-execute-phase` (executor agent reads plan and runs tasks); `gsd-plan-checker` (pre-execution quality review); `gsd-verifier` (reads `must_haves` for post-execution verification). |
|
||||
| **Produced by** | `/msd-plan-phase` via `msd-planner` agent. One file per plan — e.g., `03-02-PLAN.md` is Phase 3, Plan 2. |
|
||||
| **Consumed by** | `/msd-execute-phase` (executor agent reads plan and runs tasks); `msd-plan-checker` (pre-execution quality review); `msd-verifier` (reads `must_haves` for post-execution verification). |
|
||||
|
||||
See [PLAN.md schema](plan-md.md) for the full field reference.
|
||||
|
||||
@@ -187,7 +187,7 @@ See [PLAN.md schema](plan-md.md) for the full field reference.
|
||||
|---|---|
|
||||
| **Purpose** | Execution record written after a plan completes. Documents what was built, deviations from the plan, a self-check against acceptance criteria, and the dependency graph for the phase. |
|
||||
| **Produced by** | `execute-phase` executor agent (written at the end of each plan's execution). |
|
||||
| **Consumed by** | `/gsd-progress` (phase status); `gsd-planner` (when a subsequent plan has a genuine dependency on prior plan output); `milestone-summary`. |
|
||||
| **Consumed by** | `/msd-progress` (phase status); `msd-planner` (when a subsequent plan has a genuine dependency on prior plan output); `milestone-summary`. |
|
||||
|
||||
**`actuals` frontmatter (#2632, [ADR-2629](../adr/2629-phase-effort-estimation-calibration.md)).** When the phase's PLAN carried an `estimate`, the executor records what it actually cost:
|
||||
|
||||
@@ -198,30 +198,30 @@ actuals:
|
||||
commits: 7
|
||||
```
|
||||
|
||||
`tokens` uses the **same scale as the estimate**, not a harness-reported token count — an executor subagent cannot read its own consumption, and a ratio between two different measurement methods would measure the methods rather than the miss. `/gsd-extract-learnings` pairs each phase's estimate with its actuals via `gsd_run query estimate-calibrate`, writes `.planning/estimation-calibration.json`, and the planner applies the resulting factor to subsequent estimates. Additive and optional: a summary without `actuals` simply contributes no calibration sample.
|
||||
`tokens` uses the **same scale as the estimate**, not a harness-reported token count — an executor subagent cannot read its own consumption, and a ratio between two different measurement methods would measure the methods rather than the miss. `/msd-extract-learnings` pairs each phase's estimate with its actuals via `msd_run query estimate-calibrate`, writes `.planning/estimation-calibration.json`, and the planner applies the resulting factor to subsequent estimates. Additive and optional: a summary without `actuals` simply contributes no calibration sample.
|
||||
|
||||
### `<NN>-VERIFICATION.md`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Phase goal verification report. Checks `must_haves.truths`, `must_haves.artifacts`, and `must_haves.key_links` from all plans against the actual codebase after execution. Records `status: passed \| gaps_found \| human_needed`. A truth whose correctness depends on runtime behaviour — a state transition or a cancellation/cleanup/ordering invariant — is marked `⚠️ PRESENT_BEHAVIOR_UNVERIFIED` (not `VERIFIED`) when no test exercises it: it is excluded from `score`, counted in the `behavior_unverified` frontmatter field, and routed to `human_needed`, so a behaviour-dependent gap can no longer count toward a clean N/N. A truth that *does* reach `✓ VERIFIED` but holds for an incidental reason (`undeclared-precondition`, `incidental-ordering`, `fixture-only`) is qualified `✓ VERIFIED (coincidental-reliance)` and listed in `coincidental_reliance_items` — **advisory only**: it still counts toward `score`, does not change `status`, and emits no human-verification item (#1955). During re-verification (after a `/gsd-plan-phase --gaps` cycle), an anti-pattern blocker that is neither a carried-forward gap nor found in a file modified since the prior pass, and carries no deterministic evidence (a test run red, or another concrete reproducible artifact), is downgraded to the `advisory:` frontmatter list instead of reopening `status: gaps_found` — it does not revert a completed must-have (#3304). |
|
||||
| **Produced by** | `/gsd-verify-work` (or the verify step within `/gsd-execute-phase`). |
|
||||
| **Consumed by** | `plan-phase` closed-phase gate (a `status: passed` VERIFICATION.md marks the phase `Complete` and blocks replanning without `--force`); `/gsd-progress`; human review. |
|
||||
| **Purpose** | Phase goal verification report. Checks `must_haves.truths`, `must_haves.artifacts`, and `must_haves.key_links` from all plans against the actual codebase after execution. Records `status: passed \| gaps_found \| human_needed`. A truth whose correctness depends on runtime behaviour — a state transition or a cancellation/cleanup/ordering invariant — is marked `⚠️ PRESENT_BEHAVIOR_UNVERIFIED` (not `VERIFIED`) when no test exercises it: it is excluded from `score`, counted in the `behavior_unverified` frontmatter field, and routed to `human_needed`, so a behaviour-dependent gap can no longer count toward a clean N/N. A truth that *does* reach `✓ VERIFIED` but holds for an incidental reason (`undeclared-precondition`, `incidental-ordering`, `fixture-only`) is qualified `✓ VERIFIED (coincidental-reliance)` and listed in `coincidental_reliance_items` — **advisory only**: it still counts toward `score`, does not change `status`, and emits no human-verification item (#1955). During re-verification (after a `/msd-plan-phase --gaps` cycle), an anti-pattern blocker that is neither a carried-forward gap nor found in a file modified since the prior pass, and carries no deterministic evidence (a test run red, or another concrete reproducible artifact), is downgraded to the `advisory:` frontmatter list instead of reopening `status: gaps_found` — it does not revert a completed must-have (#3304). |
|
||||
| **Produced by** | `/msd-verify-work` (or the verify step within `/msd-execute-phase`). |
|
||||
| **Consumed by** | `plan-phase` closed-phase gate (a `status: passed` VERIFICATION.md marks the phase `Complete` and blocks replanning without `--force`); `/msd-progress`; human review. |
|
||||
|
||||
### `<NN>-UAT.md`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Persistent UAT session tracking. Records each test case, expected observable behaviour, result, and developer response across a live UAT session. Carries YAML frontmatter (`status`, `phase`, `source`, timestamps). |
|
||||
| **Produced by** | `/gsd-audit-uat` (interactive UAT session). |
|
||||
| **Consumed by** | `/gsd-audit-uat` (resume a previous UAT session). |
|
||||
| **Produced by** | `/msd-audit-uat` (interactive UAT session). |
|
||||
| **Consumed by** | `/msd-audit-uat` (resume a previous UAT session). |
|
||||
|
||||
### `.continue-here.md`
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Purpose** | Human-readable resume instructions written when work on a phase is paused. Contains context for resuming agents: critical anti-patterns, blocking issues, required reading, and the exact command to resume. |
|
||||
| **Produced by** | `/gsd-pause-work`. |
|
||||
| **Produced by** | `/msd-pause-work`. |
|
||||
| **Consumed by** | Any workflow that starts on a phase — `discuss-phase` and `plan-phase` both check for this file at entry and require the agent to demonstrate understanding of any `blocking` anti-patterns before proceeding. |
|
||||
|
||||
### `.planning/async-jobs/<job>.json`
|
||||
@@ -245,7 +245,7 @@ actuals:
|
||||
| `status` | enum | Scheduler-agnostic lifecycle state (see below). |
|
||||
| `expected_artifacts` | string[] | Paths the job is expected to produce; verified before the plan is closed. |
|
||||
| `verification_command` | string | Command that verifies the job's output before close-out. |
|
||||
| `resume_command` | string | Exact command to resume GSD reconciliation (re-enter the loop to re-check the job), e.g. `/gsd-execute-phase <phase>`. This is a GSD reconciliation entry point, not a scheduler resubmit. |
|
||||
| `resume_command` | string | Exact command to resume MSD reconciliation (re-enter the loop to re-check the job), e.g. `/msd-execute-phase <phase>`. This is a MSD reconciliation entry point, not a scheduler resubmit. |
|
||||
| `submitted_at` | string | ISO 8601 submission timestamp. |
|
||||
| `terminal_details` | object \| null | Failure/terminal-state detail; `null` while non-terminal. |
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Review and Verification Capabilities
|
||||
|
||||
This reference describes the Capability Registry declarations used by GSD review and verification features in GSD 1.5 and later. It covers the first migrated review/verification capabilities from ADR-857 Phase 6: code review, security enforcement, and Nyquist validation.
|
||||
This reference describes the Capability Registry declarations used by MSD review and verification features in MSD 1.5 and later. It covers the first migrated review/verification capabilities from ADR-857 Phase 6: code review, security enforcement, and Nyquist validation.
|
||||
|
||||
For the system design, see [ADR-857: Capability system](../adr/857-capability-system.md).
|
||||
|
||||
@@ -20,11 +20,11 @@ For the system design, see [ADR-857: Capability system](../adr/857-capability-sy
|
||||
|
||||
| Capability | Skills | Agents | Config keys |
|
||||
|---|---|---|---|
|
||||
| `code-review` | `code-review` | `gsd-code-reviewer`, `gsd-code-fixer` | `workflow.code_review`, `workflow.code_review_depth` |
|
||||
| `security` | `secure-phase` | `gsd-security-auditor` | `workflow.security_enforcement`, `workflow.security_asvs_level`, `workflow.security_block_on` |
|
||||
| `nyquist` | `validate-phase` | `gsd-nyquist-auditor` | `workflow.nyquist_validation` |
|
||||
| `code-review` | `code-review` | `msd-code-reviewer`, `msd-code-fixer` | `workflow.code_review`, `workflow.code_review_depth` |
|
||||
| `security` | `secure-phase` | `msd-security-auditor` | `workflow.security_enforcement`, `workflow.security_asvs_level`, `workflow.security_block_on` |
|
||||
| `nyquist` | `validate-phase` | `msd-nyquist-auditor` | `workflow.nyquist_validation` |
|
||||
|
||||
These keys are Capability-owned config keys. They remain valid for `.planning/config.json`, but they are not central schema keys; validation and defaults come from the generated Capability Registry. Workflows must not branch directly on the boolean activation keys. Workflows resolve activation by calling `gsd-tools loop render-hooks <point>`.
|
||||
These keys are Capability-owned config keys. They remain valid for `.planning/config.json`, but they are not central schema keys; validation and defaults come from the generated Capability Registry. Workflows must not branch directly on the boolean activation keys. Workflows resolve activation by calling `msd-tools loop render-hooks <point>`.
|
||||
|
||||
## Hook Map
|
||||
|
||||
@@ -41,41 +41,41 @@ These keys are Capability-owned config keys. They remain valid for `.planning/co
|
||||
Workflows use the active hook list from the registry:
|
||||
|
||||
```bash
|
||||
EXECUTE_POST_HOOKS_JSON=$(gsd_run loop render-hooks execute:post --raw)
|
||||
VERIFY_POST_HOOKS_JSON=$(gsd_run loop render-hooks verify:post --raw)
|
||||
EXECUTE_POST_HOOKS_JSON=$(msd_run loop render-hooks execute:post --raw)
|
||||
VERIFY_POST_HOOKS_JSON=$(msd_run loop render-hooks verify:post --raw)
|
||||
```
|
||||
|
||||
The resolver evaluates each hook's `when` key against the project config and the capability config default. If the key is absent and the capability declaration default is `true`, the hook is configured on.
|
||||
|
||||
A hook is active only when both conditions are true:
|
||||
|
||||
- The Capability is enabled by the resolved Capability State: installed by `.gsd-profile` and surfaced by `.gsd-surface.json`.
|
||||
- The Capability is enabled by the resolved Capability State: installed by `.msd-profile` and surfaced by `.msd-surface.json`.
|
||||
- The hook is configured on by its `when` key.
|
||||
|
||||
Use the diagnostic state view to inspect the same answer the workflows consume:
|
||||
|
||||
```bash
|
||||
gsd-tools capability state --config-dir ~/.claude --raw
|
||||
msd-tools capability state --config-dir ~/.claude --raw
|
||||
```
|
||||
|
||||
In that output, `configured` reflects config/default resolution, while `active` reflects final participation after install and surface state. Disabling a migrated Capability at the runtime surface removes its active hooks even when the project config default is `true`.
|
||||
|
||||
Direct command workflows self-gate the same way:
|
||||
|
||||
- `/gsd-code-review` resolves the active `execute:post` hook whose `ref.skill == "code-review"`.
|
||||
- `/gsd-secure-phase` resolves the active `verify:post` hook whose `ref.skill == "secure-phase"`.
|
||||
- `/gsd-validate-phase` resolves the active `verify:post` hook whose `ref.skill == "validate-phase"`.
|
||||
- `/msd-code-review` resolves the active `execute:post` hook whose `ref.skill == "code-review"`.
|
||||
- `/msd-secure-phase` resolves the active `verify:post` hook whose `ref.skill == "secure-phase"`.
|
||||
- `/msd-validate-phase` resolves the active `verify:post` hook whose `ref.skill == "validate-phase"`.
|
||||
|
||||
## Authoring Notes
|
||||
|
||||
When adding a review or verification capability:
|
||||
|
||||
1. Declare owned skills, agents, config keys, and hooks in `capabilities/<id>/capability.json`.
|
||||
2. Use unprefixed skill stems in `ref.skill`; workflows add the `gsd-` prefix when invoking skills.
|
||||
2. Use unprefixed skill stems in `ref.skill`; workflows add the `msd-` prefix when invoking skills.
|
||||
3. Declare `produces` and `consumes` arrays for every step and contribution hook.
|
||||
4. Use `onError: "halt"` for verification work that must stop advancement when it fails.
|
||||
5. Use a blocking `gate` for ship-time predicates that must prevent release.
|
||||
6. Regenerate `gsd-core/bin/lib/capability-registry.cjs` with `npm run gen:capability-registry`.
|
||||
6. Regenerate `msd-core/bin/lib/capability-registry.cjs` with `npm run gen:capability-registry`.
|
||||
7. Add tests that prove disabled hooks are absent from `loop render-hooks` output and that workflows do not branch directly on the capability's activation config key.
|
||||
|
||||
Do not add third-party code loading through a capability declaration. ADR-857 reserves that trust boundary for a separate design.
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
# Per-runtime skill mapping matrix
|
||||
|
||||
> **Reference** page. The authoritative source for every cell is the runtime's `capabilities/<runtime>/capability.json` `artifactLayout` descriptor, resolved by `resolveRuntimeArtifactLayout` in `gsd-core/src/runtime-artifact-layout.cts`. This page is the human-readable projection; when they disagree, the descriptor wins.
|
||||
> **Reference** page. The authoritative source for every cell is the runtime's `capabilities/<runtime>/capability.json` `artifactLayout` descriptor, resolved by `resolveRuntimeArtifactLayout` in `msd-core/src/runtime-artifact-layout.cts`. This page is the human-readable projection; when they disagree, the descriptor wins.
|
||||
>
|
||||
> **Decision record:** [ADR-1593 — Skill mapping & converter methodology across runtimes](../adr/1593-skill-mapping-converter-methodology.md). See also [ADR-3660](../adr/3660-runtime-artifact-layout-module.md) (layout owner) and [ADR-1016](../adr/1016-runtime-capability-descriptor.md) (converter enum).
|
||||
|
||||
## How to read this matrix
|
||||
|
||||
GSD ships skills (and commands/agents) as Markdown files under `commands/gsd/*.md`. Each runtime installs them via a per-runtime **layout** (where they go) and a per-runtime **converter** (how their content is rewritten). The layout is a typed `ArtifactKindDescriptor`:
|
||||
MSD ships skills (and commands/agents) as Markdown files under `commands/msd/*.md`. Each runtime installs them via a per-runtime **layout** (where they go) and a per-runtime **converter** (how their content is rewritten). The layout is a typed `ArtifactKindDescriptor`:
|
||||
|
||||
```
|
||||
{ kind, destSubpath, prefix, nesting, recursive, converter }
|
||||
```
|
||||
|
||||
- **dest** — the destination subpath under the runtime's config dir (e.g. `skills`, `skills/gsd`).
|
||||
- **prefix** — the filename/dir prefix (`gsd-` for every skill-bearing runtime).
|
||||
- **nesting** — `flat` (skills at one level) or `nested` (concrete skills nested under `gsd-ns-*` router dirs).
|
||||
- **dest** — the destination subpath under the runtime's config dir (e.g. `skills`, `skills/msd`).
|
||||
- **prefix** — the filename/dir prefix (`msd-` for every skill-bearing runtime).
|
||||
- **nesting** — `flat` (skills at one level) or `nested` (concrete skills nested under `msd-ns-*` router dirs).
|
||||
- **loader** — whether the runtime's skill loader recurses (`recursive: true` → nesting saves nothing, so the layout stays flat).
|
||||
- **converter** — the `ConverterName` (closed enum, ADR-1016) that rewrites the source command into the runtime's skill format. `null` means raw-copy (no conversion).
|
||||
|
||||
@@ -24,25 +24,25 @@ For the transform each converter applies, see [ADR-1593 §3 — converter transf
|
||||
|
||||
| Runtime | Skill dest (global) | Prefix | Nesting | Loader | Converter | Notes |
|
||||
|---------|---------------------|--------|---------|--------|-----------|-------|
|
||||
| **claude** | `skills/` | `gsd-` | flat | one-level (reverted from nested, #924) | `convertClaudeCommandToClaudeSkill` | Local scope ships commands+agents only (no `skills` kind). Plugin manifest (ADR-766) ships skills via build-generated `skills/` dir (Phase B-provide, PR #1597, merged). |
|
||||
| **codex** | `skills/` | `gsd-` | flat | unconfirmed → conservative | `convertClaudeCommandToCodexSkill` | TOML config (`configFormat: toml`). Description truncated to 180 chars (`metadata.short-description`). `sandboxTier: codex-agent-sandbox`. |
|
||||
| **opencode** | `skills/` | `gsd-` | flat | recursive (`**` glob) | `convertClaudeCommandToOpencodeSkill` | XDG config home. Shares the opencode-family converter entry point (`convertClaudeCommandToOpencodeFamilySkill`). Also ships `command` (singular) commands. |
|
||||
| **kilo** | `skills/` | `gsd-` | flat | recursive (`**` glob) | `convertClaudeCommandToKiloSkill` | OpenCode fork; same `**` glob loader. `permissionWriter: kilo`. Also ships `command` commands. |
|
||||
| **cursor** | `skills/` | `gsd-` | flat | recursive | `convertClaudeCommandToCursorSkill` | Skills are the single slash-menu and contextual invocation surface; legacy managed `commands/` copies are retired by migration 008 (#2644). `configFormat: none`. |
|
||||
| **copilot** | `skills/` | `gsd-` | flat | unconfirmed → conservative | `convertClaudeCommandToCopilotSkill` | Markdown config. Scope-aware converter (global-home vs workspace-relative). |
|
||||
| **antigravity** | `skills/` | `gsd-` | flat | non-recursive (one-level) | `convertClaudeCommandToAntigravitySkill` | `dot-home-nested` config home. Scope-aware converter. Loader confirmed: *"will not recursive scan"*. Flattened by #1614 — `agy` scans only `skills/<name>/SKILL.md`, so nesting hid sub-skills. |
|
||||
| **windsurf** | — *(no skills kind)* | `gsd-` | — | workflows | `convertClaudeCommandToWindsurfWorkflow` | Emits `.windsurf/workflows/gsd-*.md` slash-command workflows. `configFormat: none`. `installSurface: profile-marker-only`. |
|
||||
| **augment** | `skills/` | `gsd-` | nested | non-recursive (single-level) | `convertClaudeCommandToAugmentSkill` | Also ships flat `commands/`. Settings-json config. |
|
||||
| **trae** | `skills/` | `gsd-` | nested | non-recursive (flat; nesting errors) | `convertClaudeCommandToTraeSkill` | `configFormat: none`. Trae IDE (trae.ai), not trae-agent. |
|
||||
| **qwen** | `skills/` | `gsd-` | nested | non-recursive (flat readdir) | `convertClaudeCommandToClaudeSkill` | **Shares Claude's converter.** Emits numeric `priority:` (`QWEN_SKILL_PRIORITY`) for `/skills` ordering. Settings-json config. |
|
||||
| **hermes** | `skills/gsd/` | `gsd-` | nested | non-recursive (single-level probe) | `convertClaudeCommandToClaudeSkill` | **Shares Claude's converter.** `destSubpath: skills/gsd` (category dir). Emits required `version:` field. `prefix: gsd-` restored by #947. |
|
||||
| **codebuddy** | `skills/` | `gsd-` | flat | unconfirmed → conservative | `convertClaudeCommandToCodebuddySkill` | Also ships flat `commands/` via `convertClaudeCommandToCodebuddyCommand`. `dot-home` config. |
|
||||
| **cline** | `skills/` | `gsd-` | nested | non-recursive (flat `fs.readdir`) | `convertClaudeCommandToClineSkill` | **Global-only** — `local: []` (no local skill install). Targets `~/.cline/skills/<name>/SKILL.md` (Cline ≥ v3.48.0). `markdown-dir` config. |
|
||||
| **kimi** | `skills/` | `gsd-` | flat | (false) | `convertClaudeCommandToKimiSkill` | Also ships a special `kimi-agents` kind (`buildKimiAgentArtifacts`). Name normalization (`normalizeKimiSkillName`). `generic-agents-root` config. |
|
||||
| **claude** | `skills/` | `msd-` | flat | one-level (reverted from nested, #924) | `convertClaudeCommandToClaudeSkill` | Local scope ships commands+agents only (no `skills` kind). Plugin manifest (ADR-766) ships skills via build-generated `skills/` dir (Phase B-provide, PR #1597, merged). |
|
||||
| **codex** | `skills/` | `msd-` | flat | unconfirmed → conservative | `convertClaudeCommandToCodexSkill` | TOML config (`configFormat: toml`). Description truncated to 180 chars (`metadata.short-description`). `sandboxTier: codex-agent-sandbox`. |
|
||||
| **opencode** | `skills/` | `msd-` | flat | recursive (`**` glob) | `convertClaudeCommandToOpencodeSkill` | XDG config home. Shares the opencode-family converter entry point (`convertClaudeCommandToOpencodeFamilySkill`). Also ships `command` (singular) commands. |
|
||||
| **kilo** | `skills/` | `msd-` | flat | recursive (`**` glob) | `convertClaudeCommandToKiloSkill` | OpenCode fork; same `**` glob loader. `permissionWriter: kilo`. Also ships `command` commands. |
|
||||
| **cursor** | `skills/` | `msd-` | flat | recursive | `convertClaudeCommandToCursorSkill` | Skills are the single slash-menu and contextual invocation surface; legacy managed `commands/` copies are retired by migration 008 (#2644). `configFormat: none`. |
|
||||
| **copilot** | `skills/` | `msd-` | flat | unconfirmed → conservative | `convertClaudeCommandToCopilotSkill` | Markdown config. Scope-aware converter (global-home vs workspace-relative). |
|
||||
| **antigravity** | `skills/` | `msd-` | flat | non-recursive (one-level) | `convertClaudeCommandToAntigravitySkill` | `dot-home-nested` config home. Scope-aware converter. Loader confirmed: *"will not recursive scan"*. Flattened by #1614 — `agy` scans only `skills/<name>/SKILL.md`, so nesting hid sub-skills. |
|
||||
| **windsurf** | — *(no skills kind)* | `msd-` | — | workflows | `convertClaudeCommandToWindsurfWorkflow` | Emits `.windsurf/workflows/msd-*.md` slash-command workflows. `configFormat: none`. `installSurface: profile-marker-only`. |
|
||||
| **augment** | `skills/` | `msd-` | nested | non-recursive (single-level) | `convertClaudeCommandToAugmentSkill` | Also ships flat `commands/`. Settings-json config. |
|
||||
| **trae** | `skills/` | `msd-` | nested | non-recursive (flat; nesting errors) | `convertClaudeCommandToTraeSkill` | `configFormat: none`. Trae IDE (trae.ai), not trae-agent. |
|
||||
| **qwen** | `skills/` | `msd-` | nested | non-recursive (flat readdir) | `convertClaudeCommandToClaudeSkill` | **Shares Claude's converter.** Emits numeric `priority:` (`QWEN_SKILL_PRIORITY`) for `/skills` ordering. Settings-json config. |
|
||||
| **hermes** | `skills/msd/` | `msd-` | nested | non-recursive (single-level probe) | `convertClaudeCommandToClaudeSkill` | **Shares Claude's converter.** `destSubpath: skills/msd` (category dir). Emits required `version:` field. `prefix: msd-` restored by #947. |
|
||||
| **codebuddy** | `skills/` | `msd-` | flat | unconfirmed → conservative | `convertClaudeCommandToCodebuddySkill` | Also ships flat `commands/` via `convertClaudeCommandToCodebuddyCommand`. `dot-home` config. |
|
||||
| **cline** | `skills/` | `msd-` | nested | non-recursive (flat `fs.readdir`) | `convertClaudeCommandToClineSkill` | **Global-only** — `local: []` (no local skill install). Targets `~/.cline/skills/<name>/SKILL.md` (Cline ≥ v3.48.0). `markdown-dir` config. |
|
||||
| **kimi** | `skills/` | `msd-` | flat | (false) | `convertClaudeCommandToKimiSkill` | Also ships a special `kimi-agents` kind (`buildKimiAgentArtifacts`). Name normalization (`normalizeKimiSkillName`). `generic-agents-root` config. |
|
||||
|
||||
### Structural facts
|
||||
|
||||
- **All 14 skill-bearing runtimes use `prefix: "gsd-"`.** One runtime has no skills kind: Windsurf (emits `.windsurf/workflows/gsd-*.md` slash-command workflows instead — #1615).
|
||||
- **All 14 skill-bearing runtimes use `prefix: "msd-"`.** One runtime has no skills kind: Windsurf (emits `.windsurf/workflows/msd-*.md` slash-command workflows instead — #1615).
|
||||
- **Five runtimes nest** (cline, qwen, hermes, augment, trae) because their skill loaders scan one level deep — nesting drops nested concrete skills out of the eager top-level listing while keeping them readable by file path (the namespace-router contract, #69).
|
||||
- **Eight runtimes stay flat**: three because their loaders recurse (cursor, opencode, kilo — nesting saves nothing), two because nesting was reverted (claude — the Skill tool errors on unknown names rather than re-routing, #924; antigravity — `agy` scans only `skills/<name>/SKILL.md`, so nested sub-skills were unreachable, #1614), and three conservatively where the loader depth is unconfirmed (codex, copilot, codebuddy).
|
||||
- **Three runtimes share `convertClaudeCommandToClaudeSkill`** (claude, qwen, hermes). The converter branches on the `runtime` arg for per-runtime branding (Hermes `version:`, Qwen `priority:`).
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# STATE.md schema reference
|
||||
|
||||
`STATE.md` is GSD Core's living project-memory file — a single Markdown document that records where a project stands, what happened last, and what to run next. This page documents its structure. See [docs index](../README.md).
|
||||
`STATE.md` is MSD Core's living project-memory file — a single Markdown document that records where a project stands, what happened last, and what to run next. This page documents its structure. See [docs index](../README.md).
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Every project managed by GSD Core keeps one `STATE.md` at `.planning/STATE.md`. It is read at the start of every workflow and written after every significant action. The file combines:
|
||||
Every project managed by MSD Core keeps one `STATE.md` at `.planning/STATE.md`. It is read at the start of every workflow and written after every significant action. The file combines:
|
||||
|
||||
- **YAML frontmatter** — machine-readable fields consumed by the status-line hook (`parseStateMd`) and the `gsd-tools state` commands.
|
||||
- **YAML frontmatter** — machine-readable fields consumed by the status-line hook (`parseStateMd`) and the `msd-tools state` commands.
|
||||
- **Markdown body** — human-readable sections covering current position, accumulated context, session continuity, and performance metrics.
|
||||
|
||||
The file is intentionally small (target: under 100 lines). It is a digest of the project's state, not an archive.
|
||||
@@ -17,13 +17,13 @@ The file is intentionally small (target: under 100 lines). It is a digest of the
|
||||
|
||||
## YAML frontmatter
|
||||
|
||||
Frontmatter appears between `---` delimiters at the very start of the file. All fields except `gsd_state_version` and `status` are optional; fields may be absent when their data is not yet available.
|
||||
Frontmatter appears between `---` delimiters at the very start of the file. All fields except `msd_state_version` and `status` are optional; fields may be absent when their data is not yet available.
|
||||
|
||||
### Annotated example
|
||||
|
||||
```yaml
|
||||
---
|
||||
gsd_state_version: '1.0'
|
||||
msd_state_version: '1.0'
|
||||
milestone: v2.0
|
||||
milestone_name: Code Quality
|
||||
status: executing
|
||||
@@ -56,7 +56,7 @@ paused_at: null
|
||||
|
||||
| Field | Type | When populated | Purpose |
|
||||
|---|---|---|---|
|
||||
| `gsd_state_version` | string (`'1.0'`) | Always | Schema version; written on first `state.*` call by `syncStateFrontmatter`. |
|
||||
| `msd_state_version` | string (`'1.0'`) | Always | Schema version; written on first `state.*` call by `syncStateFrontmatter`. |
|
||||
| `milestone` | string (e.g. `v2.0`) | When a milestone is configured | Current milestone version, read from the project's config. |
|
||||
| `milestone_name` | string | When a milestone is configured | Human-readable milestone label (e.g. `Code Quality`). |
|
||||
| `status` | string | Always | Current lifecycle stage. Normalised by `normalizeStateStatus()` — see [status values](#status-values). |
|
||||
@@ -83,7 +83,7 @@ paused_at: null
|
||||
|
||||
| Field | Cardinality |
|
||||
|---|---|
|
||||
| `gsd_state_version` | one |
|
||||
| `msd_state_version` | one |
|
||||
| `milestone` | optional |
|
||||
| `milestone_name` | optional |
|
||||
| `current_phase` | optional |
|
||||
@@ -114,7 +114,7 @@ paused_at: null
|
||||
|
||||
### Status values
|
||||
|
||||
`normalizeStateStatus()` in `gsd-core/bin/lib/state-document.cjs` maps raw body text to these canonical values:
|
||||
`normalizeStateStatus()` in `msd-core/bin/lib/state-document.cjs` maps raw body text to these canonical values:
|
||||
|
||||
| Canonical value | Matched text (case-insensitive) |
|
||||
|---|---|
|
||||
@@ -130,10 +130,10 @@ When an orchestrator command is in flight, the convention (issue #2833) is to wr
|
||||
|
||||
| Command | `status` while in flight |
|
||||
|---|---|
|
||||
| `/gsd-discuss-phase` | `discussing` |
|
||||
| `/gsd-plan-phase` | `planning` |
|
||||
| `/gsd-execute-phase` | `executing` |
|
||||
| `/gsd-verify-work` | `verifying` |
|
||||
| `/msd-discuss-phase` | `discussing` |
|
||||
| `/msd-plan-phase` | `planning` |
|
||||
| `/msd-execute-phase` | `executing` |
|
||||
| `/msd-verify-work` | `verifying` |
|
||||
|
||||
<!-- STATE-MD-SCHEMA:START:status-lifecycle — generated by scripts/gen-state-md-docs.cjs from src/state-md-schema.cts; do not edit by hand -->
|
||||
### Status lifecycle (ADR-2207)
|
||||
@@ -154,7 +154,7 @@ Phase-completion verbs never write `Milestone complete` (the overloaded bare val
|
||||
|
||||
## Status-line rendering scenes
|
||||
|
||||
`formatGsdState()` in `hooks/gsd-statusline.js` reads the parsed frontmatter and emits the **first matching scene**. If no new lifecycle fields apply, rendering falls through to the original format byte-for-byte unchanged from v1.38.x.
|
||||
`formatMsdState()` in `hooks/msd-statusline.js` reads the parsed frontmatter and emits the **first matching scene**. If no new lifecycle fields apply, rendering falls through to the original format byte-for-byte unchanged from v1.38.x.
|
||||
|
||||
| Scene | Trigger | Display example |
|
||||
|---|---|---|
|
||||
@@ -163,11 +163,11 @@ Phase-completion verbs never write `Milestone complete` (the overloaded bare val
|
||||
| **3. Milestone complete** | `percent` is `100` OR `completed_phases == total_phases` | `v2.0 [██████████] 100% · milestone complete` |
|
||||
| **4. Default fallback** | None of the above match | `v1.9 Code Quality · executing · ph 1/5` (existing format) |
|
||||
|
||||
**Scene priority:** when both `active_phase` and `next_action` are populated, Scene 1 wins — an orchestrator is in flight, so a "next recommendation" would be misleading. This priority is enforced by check order in `formatGsdState()` and covered by the `"scene priority"` suite in `tests/gsd-statusline.test.cjs`.
|
||||
**Scene priority:** when both `active_phase` and `next_action` are populated, Scene 1 wins — an orchestrator is in flight, so a "next recommendation" would be misleading. This priority is enforced by check order in `formatMsdState()` and covered by the `"scene priority"` suite in `tests/msd-statusline.test.cjs`.
|
||||
|
||||
When `phase_id_convention` is exactly `"bracket"` and `project_code` is set,
|
||||
the full and compact renderers replace the legacy milestone/phase labels with
|
||||
the canonical identity: `[GSD.02] · [GSD.02] 05.03 executing`. They do not emit
|
||||
the canonical identity: `[MSD.02] · [MSD.02] 05.03 executing`. They do not emit
|
||||
the `vX.Y`, `Phase`, or compact `P` labels on that gated path. Any other
|
||||
convention, or a bracket config missing the metadata needed to form an ID,
|
||||
falls back to the strings shown in the table above.
|
||||
@@ -178,7 +178,7 @@ The progress bar (`[██░░░░░░░░] 20%`) is appended to the mil
|
||||
|
||||
## Frontmatter parsing constraints
|
||||
|
||||
The status-line hook uses regex-based parsing (no full YAML library), so the following constraints apply. They are tested in `tests/gsd-statusline.test.cjs`.
|
||||
The status-line hook uses regex-based parsing (no full YAML library), so the following constraints apply. They are tested in `tests/msd-statusline.test.cjs`.
|
||||
|
||||
1. **Frontmatter must start at the very first character of the file.** Anything — including comments — above the opening `---` invalidates the match. The opening `---` line must be exactly that, with no trailing spaces.
|
||||
|
||||
@@ -192,7 +192,7 @@ If a future change replaces the regex parser with a full YAML library, these con
|
||||
|
||||
## Markdown body sections
|
||||
|
||||
The body (everything after the closing `---`) follows the template in `gsd-core/templates/state.md`. The standard sections are:
|
||||
The body (everything after the closing `---`) follows the template in `msd-core/templates/state.md`. The standard sections are:
|
||||
|
||||
### Project Reference
|
||||
|
||||
@@ -216,7 +216,7 @@ Where the project stands right now:
|
||||
|
||||
Progress *history* does not belong here. It accumulates in [`### Performance Metrics`](#performance-metrics) below, which is the section designed to grow.
|
||||
|
||||
The `Status:` and `Last activity:` fields in this section are updated by GSD handlers when the existing value is a known template default (Knuth invariant: executor-authored values are preserved). The full list of known handler defaults is in `KNOWN_TEMPLATE_DEFAULTS` inside `gsd-core/bin/lib/state-document.cjs`.
|
||||
The `Status:` and `Last activity:` fields in this section are updated by MSD handlers when the existing value is a known template default (Knuth invariant: executor-authored values are preserved). The full list of known handler defaults is in `KNOWN_TEMPLATE_DEFAULTS` inside `msd-core/bin/lib/state-document.cjs`.
|
||||
|
||||
### Performance Metrics
|
||||
|
||||
@@ -229,11 +229,11 @@ Updated after each plan completion.
|
||||
|
||||
### Accumulated Context
|
||||
|
||||
**Decisions** — a summary of recent decisions affecting current work (full log lives in `PROJECT.md`). Added via `gsd-tools state add-decision`.
|
||||
**Decisions** — a summary of recent decisions affecting current work (full log lives in `PROJECT.md`). Added via `msd-tools state add-decision`.
|
||||
|
||||
**Pending Todos** — one bullet per pending todo (`- [date] [area] title — [todo file](repo-relative path) — Needs ...`, capped at 240 characters; repo-relative link keeps the cap independent of checkout path length). Captured via `/gsd-capture`.
|
||||
**Pending Todos** — one bullet per pending todo (`- [date] [area] title — [todo file](repo-relative path) — Needs ...`, capped at 240 characters; repo-relative link keeps the cap independent of checkout path length). Captured via `/msd-capture`.
|
||||
|
||||
**Blockers/Concerns** — issues affecting future work, prefixed with the originating phase. Added via `gsd-tools state add-blocker`; resolved via `gsd-tools state resolve-blocker`.
|
||||
**Blockers/Concerns** — issues affecting future work, prefixed with the originating phase. Added via `msd-tools state add-blocker`; resolved via `msd-tools state resolve-blocker`.
|
||||
|
||||
### Session Continuity
|
||||
|
||||
@@ -252,7 +252,7 @@ The phase-lifecycle fields (`active_phase`, `next_action`, `next_phases`, and `p
|
||||
- Adding any lifecycle field is opt-in — the renderer degrades gracefully when fields are absent.
|
||||
- The progress bar is opt-in even when the `progress` block exists: only `progress.percent` triggers the bar; `total_phases` and `completed_phases` alone do not.
|
||||
|
||||
The `formatGsdState #2833 backward compatibility` test suite in `tests/gsd-statusline.test.cjs` locks this guarantee; any change that breaks legacy `STATE.md` rendering will fail the suite.
|
||||
The `formatMsdState #2833 backward compatibility` test suite in `tests/msd-statusline.test.cjs` locks this guarantee; any change that breaks legacy `STATE.md` rendering will fail the suite.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Workflow fragments (reference)
|
||||
|
||||
> **Diátaxis quadrant:** Reference. This is the canonical specification of the
|
||||
> in-file `<!-- gsd:section -->` marker grammar used to fragmentize GSD workflow
|
||||
> in-file `<!-- msd:section -->` marker grammar used to fragmentize MSD workflow
|
||||
> markdown for per-runtime emission. For the surrounding seam (why it exists and
|
||||
> how it composes with the shared budget composer), see
|
||||
> [Architecture: Workflow Fragmentization and Emission](../ARCHITECTURE.md#workflow-fragmentization-and-emission-srcworkflow-fragmentscts-adr-1671)
|
||||
> and [ADR-1671](../adr/1671-dynamic-context-management-platform.md) (open
|
||||
> questions 1 and 2).
|
||||
|
||||
Workflow authors can mark one or more sections of a `gsd-core/workflows/*.md` file
|
||||
Workflow authors can mark one or more sections of a `msd-core/workflows/*.md` file
|
||||
so that `bin/install.js`'s emission path can compose them per runtime, and so that
|
||||
a separate init-time seam can select which sections apply to one concrete
|
||||
invocation — see [The manifest artifact and per-workflow
|
||||
@@ -20,13 +20,13 @@ An open marker is a line whose only content (after trimming leading/trailing
|
||||
whitespace) is:
|
||||
|
||||
```html
|
||||
<!-- gsd:section id="<id>" when="<when>" -->
|
||||
<!-- msd:section id="<id>" when="<when>" -->
|
||||
```
|
||||
|
||||
A close marker is a line whose only content is:
|
||||
|
||||
```html
|
||||
<!-- /gsd:section -->
|
||||
<!-- /msd:section -->
|
||||
```
|
||||
|
||||
- Attribute order is free and inner spacing around `=` and between attributes
|
||||
@@ -89,10 +89,10 @@ into the `--discuss`/`--research`/`--validate` facts before evaluation) and
|
||||
| `state:needs-codebase-map` | Applicable when a codebase map is needed (init-computed). |
|
||||
| `state:next-channel` | Applicable when `update.md`'s release channel is `next` — the workflow runs with `--next`, or its documented alias `--rc`. |
|
||||
| `state:phase-mvp-mode` | Applicable when the current phase's `ROADMAP.md` entry declares `**Mode:** mvp`. |
|
||||
| `state:plan-strategy-converge` | Applicable when `autonomous.md`'s planning step should route through plan-review convergence instead of `gsd-plan-phase` — the workflow runs with `--converge`, or its documented alias `--cross-ai` (`autonomous.md`'s own `PLAN_STRATEGY` resolver folds both). |
|
||||
| `state:plan-strategy-converge` | Applicable when `autonomous.md`'s planning step should route through plan-review convergence instead of `msd-plan-phase` — the workflow runs with `--converge`, or its documented alias `--cross-ai` (`autonomous.md`'s own `PLAN_STRATEGY` resolver folds both). |
|
||||
| `state:reviewer-instances-configured` | Applicable when `.planning/config.json`'s `review.reviewer_instances` is present AND non-empty. |
|
||||
| `state:ui-phase-active` | Applicable when the phase's active `plan:pre` loop hooks include the `ui-phase` step, OR the phase directory already contains a `*-UI-SPEC.md` file — see [Compound conditions are resolved in the fact, never the grammar](#compound-conditions-are-resolved-in-the-fact-never-the-grammar) below. |
|
||||
| `state:workstream-active` | Applicable when a workstream is active — `GSD_WORKSTREAM` env, falling back to the stored active-workstream pointer. |
|
||||
| `state:workstream-active` | Applicable when a workstream is active — `MSD_WORKSTREAM` env, falling back to the stored active-workstream pointer. |
|
||||
| `state:worktrees-enabled` | Applicable when `.planning/config.json`'s `workflow.use_worktrees` is enabled. |
|
||||
|
||||
This list is **closed by design** (Greenspun's Tenth Rule): left open-ended,
|
||||
@@ -161,12 +161,12 @@ of the pre-existing `cmdInitNewMilestone`.
|
||||
|
||||
An entry point can also land **ahead of** the atom it will unblock. `#3149`
|
||||
gives `debug` a dedicated `cmdInitDebug` (`init.debug`) with no vocabulary
|
||||
change at all: `/gsd-debug` previously made three separate `gsd_run`
|
||||
change at all: `/msd-debug` previously made three separate `msd_run`
|
||||
round-trips and had no `cmdInit*` of its own, so gate (2) could never be
|
||||
satisfied for any debug-scoped fact. Shipping the entry point first satisfies
|
||||
gate (2) on its own schedule and leaves gate (1) — a consuming section of at
|
||||
least 400 bytes — to the change that actually adds the section. `debug` has no
|
||||
`<!-- gsd:section -->` markers yet, so it contributes no key to
|
||||
`<!-- msd:section -->` markers yet, so it contributes no key to
|
||||
`section-manifest.json` and `init.debug`'s `section_manifest` field degrades to
|
||||
`null` (read everything) until it does.
|
||||
|
||||
@@ -197,7 +197,7 @@ of how reasonable a single compound condition looks in isolation.
|
||||
|
||||
`state:ui-phase-active` (#2994) is the same shape: `verify-work.md`'s
|
||||
`automated_ui_verification` step originally computed its own OR at RUNTIME
|
||||
(`UI_PHASE_ACTIVE` from `gsd_run loop render-hooks plan:pre` OR a `*-UI-SPEC.md`
|
||||
(`UI_PHASE_ACTIVE` from `msd_run loop render-hooks plan:pre` OR a `*-UI-SPEC.md`
|
||||
file check). `cmdInitVerifyWork` now resolves the identical disjunction ahead
|
||||
of time — `resolveLoopHooks({point: 'plan:pre', ...}).activeHooks` filtered to
|
||||
`kind === 'step' && ref.skill === 'ui-phase'`, OR'd with a `*-UI-SPEC.md`
|
||||
@@ -217,7 +217,7 @@ never `--converge`/`--cross-ai` separately.
|
||||
`discuss-phase-assumptions.md`'s own `auto_advance` step already resolves
|
||||
`--auto` OR a consolidated `check auto-mode --pick active` fact (itself
|
||||
`workflow._auto_chain_active` OR `workflow.auto_advance`) via a runtime
|
||||
`gsd_run` call before deciding whether to dispatch. `cmdInitDiscussPhaseAssumptions`
|
||||
`msd_run` call before deciding whether to dispatch. `cmdInitDiscussPhaseAssumptions`
|
||||
mirrors that identical disjunction — `options['auto'] === true ||
|
||||
readConfigJsonBoolean(cwd, ['workflow', '_auto_chain_active']) ||
|
||||
readConfigJsonBoolean(cwd, ['workflow', 'auto_advance'])` — into
|
||||
@@ -257,7 +257,7 @@ shared `context-composer.cjs` budget seam (every fragment uses the `verbatim`
|
||||
strategy, so nothing is trimmed) → re-join fragment bodies in document order.
|
||||
The marker lines themselves are never part of any fragment body, so the
|
||||
composed output — and therefore every installed runtime artifact — contains
|
||||
no `gsd:section` markers at all. An unmarked file composes to itself exactly;
|
||||
no `msd:section` markers at all. An unmarked file composes to itself exactly;
|
||||
a marked file composes to itself minus the marker line bytes.
|
||||
|
||||
Composition runs **before** the per-runtime converters (the `.claude/` →
|
||||
@@ -280,8 +280,8 @@ that emits agent content:
|
||||
All three compose **before** any path rewrite, for the same reason workflows do.
|
||||
|
||||
**What does not extend is `when=` gating.** Selection is read from
|
||||
`gsd-core/workflows/section-manifest.json`, which `gen-section-manifest.cjs`
|
||||
derives from `gsd-core/workflows/*.md` only — its shape is `{workflows: …}` and
|
||||
`msd-core/workflows/section-manifest.json`, which `gen-section-manifest.cjs`
|
||||
derives from `msd-core/workflows/*.md` only — its shape is `{workflows: …}` and
|
||||
it has no per-agent key. There is no per-agent init entry point either, so an
|
||||
agent atom has no fact to evaluate against and would fail the vocabulary's
|
||||
second admission gate ("a fact the init seam demonstrably computes at a real
|
||||
@@ -290,16 +290,16 @@ forever while *looking* like working gating — the precise failure the frozen
|
||||
vocabulary exists to prevent.
|
||||
|
||||
Agents that need to shed bytes do so by extracting reference material to
|
||||
`gsd-core/references/` behind an `@`-reference, the documented
|
||||
`msd-core/references/` behind an `@`-reference, the documented
|
||||
`DEFECT.AGENT-FILE-SIZE-CAP-BREACH` remedy — not by adding markers.
|
||||
|
||||
## Fenced and commented lookalikes are literal
|
||||
|
||||
A `<!-- gsd:section ... -->`-shaped line inside a fenced code block (three or
|
||||
A `<!-- msd:section ... -->`-shaped line inside a fenced code block (three or
|
||||
more backticks or tildes, CommonMark-style) is **not** a marker — it is
|
||||
literal fence content, because workflows document their own marker syntax in
|
||||
fenced examples (as in this page and in the workflow files themselves). The
|
||||
same applies to a `gsd:section` mention inside an unrelated HTML comment, or
|
||||
same applies to a `msd:section` mention inside an unrelated HTML comment, or
|
||||
in prose/backtick text that never opens a real one-line comment. Fence and
|
||||
comment detection run as a single interleaved left-to-right scan, mirroring
|
||||
the discipline used by the `CONTEXT.md` predicate parser
|
||||
@@ -308,18 +308,18 @@ can end it; while a comment is open, only `-->` can end it; an unclosed fence
|
||||
running to end of file is not an error — everything after it is simply
|
||||
literal.
|
||||
|
||||
The pre-existing `<!-- gsd:loop-host ... -->` marker family (consumed by
|
||||
The pre-existing `<!-- msd:loop-host ... -->` marker family (consumed by
|
||||
`scripts/gen-loop-host-contract.cjs`) is a different, already-established
|
||||
marker and is never treated as a `gsd:section` marker.
|
||||
marker and is never treated as a `msd:section` marker.
|
||||
|
||||
## The manifest artifact and per-workflow keying
|
||||
|
||||
`bin/install.js`'s emission path always composes every fragment into the
|
||||
output regardless of its `when=` value — marker lines are stripped, nothing
|
||||
else changes there. Applicability selection is a separate, later seam:
|
||||
`scripts/gen-section-manifest.cjs --write` scans `gsd-core/workflows/*.md` for
|
||||
`gsd:section` markers and generates a committed artifact,
|
||||
`gsd-core/workflows/section-manifest.json`, shaped as
|
||||
`scripts/gen-section-manifest.cjs --write` scans `msd-core/workflows/*.md` for
|
||||
`msd:section` markers and generates a committed artifact,
|
||||
`msd-core/workflows/section-manifest.json`, shaped as
|
||||
`{"workflows": {"<workflow-name>": [{"id", "when", "read"}, ...], ...}}`,
|
||||
where `<workflow-name>` is a source `.md` file's basename without extension
|
||||
and `read` is the POSIX-normalized, repo-root-relative path of the step file
|
||||
@@ -377,20 +377,20 @@ that were actually seen.
|
||||
|
||||
Fifteen workflows carry markers today, all of them the workflows with a
|
||||
dedicated `cmdInit*` entry point (see [The manifest artifact](#the-manifest-artifact-and-per-workflow-keying)
|
||||
above): `gsd-core/workflows/execute-phase.md` (the #2930/Phase-3 pilot),
|
||||
`gsd-core/workflows/plan-phase.md` (#2993, epic #1671 Phase 6.2),
|
||||
`gsd-core/workflows/progress.md`, `gsd-core/workflows/new-project.md`,
|
||||
`gsd-core/workflows/quick.md`, `gsd-core/workflows/new-milestone.md` (those
|
||||
four, #2994, epic #1671 Phase 6.3), `gsd-core/workflows/verify-work.md`
|
||||
(also #2994, epic #1671 Phase 6.3), `gsd-core/workflows/code-review.md` /
|
||||
`gsd-core/workflows/complete-milestone.md` (a further #2994 amendment, epic
|
||||
#1671 Phase 6.3), `gsd-core/workflows/autonomous.md` (a still further
|
||||
#2994 amendment, epic #1671 Phase 6.3), `gsd-core/workflows/review.md` /
|
||||
`gsd-core/workflows/discuss-phase-assumptions.md` (a still further #2994
|
||||
above): `msd-core/workflows/execute-phase.md` (the #2930/Phase-3 pilot),
|
||||
`msd-core/workflows/plan-phase.md` (#2993, epic #1671 Phase 6.2),
|
||||
`msd-core/workflows/progress.md`, `msd-core/workflows/new-project.md`,
|
||||
`msd-core/workflows/quick.md`, `msd-core/workflows/new-milestone.md` (those
|
||||
four, #2994, epic #1671 Phase 6.3), `msd-core/workflows/verify-work.md`
|
||||
(also #2994, epic #1671 Phase 6.3), `msd-core/workflows/code-review.md` /
|
||||
`msd-core/workflows/complete-milestone.md` (a further #2994 amendment, epic
|
||||
#1671 Phase 6.3), `msd-core/workflows/autonomous.md` (a still further
|
||||
#2994 amendment, epic #1671 Phase 6.3), `msd-core/workflows/review.md` /
|
||||
`msd-core/workflows/discuss-phase-assumptions.md` (a still further #2994
|
||||
amendment, epic #1671 Phase 6.3), and finally
|
||||
`gsd-core/workflows/docs-update.md` / `gsd-core/workflows/update.md` /
|
||||
`gsd-core/workflows/transition.md` (the LAST #2994 amendment, epic #1671
|
||||
Phase 6.3 — none of these three carried a `gsd_run query init.*` call before
|
||||
`msd-core/workflows/docs-update.md` / `msd-core/workflows/update.md` /
|
||||
`msd-core/workflows/transition.md` (the LAST #2994 amendment, epic #1671
|
||||
Phase 6.3 — none of these three carried a `msd_run query init.*` call before
|
||||
this slice). Every one of the 13 workflows ADR-1671 targeted is now on the
|
||||
fragment model; the marker grammar and composer seam remain general-purpose
|
||||
across any future workflow file, but no further rollout is scheduled.
|
||||
@@ -408,7 +408,7 @@ across any future workflow file, but no further rollout is scheduled.
|
||||
|
||||
`progress.md` marks two sections: `forensic-audit` (`flag:--forensic`, #2994
|
||||
forensic audit) and `mvp-display` (`state:phase-mvp-mode`). `mvp-display`'s
|
||||
own body used to re-resolve its own gating fact via a `gsd_run query
|
||||
own body used to re-resolve its own gating fact via a `msd_run query
|
||||
phase.mvp-mode` call — circular, since a section's body re-deriving the exact
|
||||
condition that gated its own inclusion is self-disabling the moment the init
|
||||
seam's computation and the body's computation drift. `cmdInitProgress` now
|
||||
@@ -449,7 +449,7 @@ workstream mode) stays OUTSIDE the marker, directly after it, for the same
|
||||
reason every other flag-absent/state-false fallback in this document does.
|
||||
`cmdInitNewMilestone` computes both `workstreamActive` and `flatMode` from
|
||||
the SAME authoritative source `cmdInitProgress` already established
|
||||
(`GSD_WORKSTREAM` env, falling back to the stored active-workstream
|
||||
(`MSD_WORKSTREAM` env, falling back to the stored active-workstream
|
||||
pointer). Because Step 4 (where the marker lives) runs well before
|
||||
`new-milestone.md`'s pre-existing `init.new-milestone` call (Step 7, kept
|
||||
AFTER Step 6's phase archival so its `phase_dir_count`/`roadmap_exists`
|
||||
@@ -469,7 +469,7 @@ guard) moves into the step file — the false-branch note ("When `MVP_MODE=false
|
||||
directly after it, because gating it away with the rest of the section would
|
||||
delete the exact text needed on every invocation where the atom is `false`
|
||||
(the common, non-MVP case). Unlike `progress.md`'s `mvp-display`, `verify-work.md`
|
||||
keeps its own `MVP_MODE=$(gsd_run query phase.mvp-mode ...)` runtime resolver
|
||||
keeps its own `MVP_MODE=$(msd_run query phase.mvp-mode ...)` runtime resolver
|
||||
(in the unconditional `initialize` step, not inside the gated section) — it is
|
||||
not circular/self-disabling the way `progress.md`'s inline resolver was,
|
||||
because the un-marked false-branch note and the step-file prose both still
|
||||
@@ -478,7 +478,7 @@ consumer outside the gate.
|
||||
|
||||
`code-review.md` marks two sections: `structural-pre-pass` (`state:fallow-enabled`)
|
||||
and `dispatch-fix` (`flag:--fix`). `structural-pre-pass`'s own body used to
|
||||
re-resolve its own gating fact via four `gsd_run query config-get
|
||||
re-resolve its own gating fact via four `msd_run query config-get
|
||||
code_quality.fallow.*` calls — circular, for the same reason `progress.md`'s
|
||||
pre-hoist `mvp-display` was: a section's body re-deriving the exact condition
|
||||
that gated its own inclusion is self-disabling the moment the init seam's
|
||||
@@ -501,7 +501,7 @@ than a raw `--fix` token scan.
|
||||
|
||||
`complete-milestone.md` marks one section: `git-tag` (`state:git-create-tag`).
|
||||
The `git_tag` step's own `<config-check>` sub-tag used to re-resolve
|
||||
`git.create_tag` via `gsd-tools.cjs query config-get` to decide whether to
|
||||
`git.create_tag` via `msd-tools.cjs query config-get` to decide whether to
|
||||
skip the step — again a section (here, a whole step) gating its own inclusion
|
||||
on a fact its own body computed. `cmdInitCompleteMilestone` now resolves it
|
||||
once (`detectGitCreateTag`, `src/init.cts`, fail-OPEN default `true` — an
|
||||
@@ -597,13 +597,13 @@ divergence-prone workspace-glob scan — the SAME detector that already backs
|
||||
`update.md` marks one section: `channel-banner` (`state:next-channel`) — the
|
||||
"Only when `TAG=next`" channel-banner paragraph in `compare_versions`.
|
||||
`update.md` previously called NO `init.*` command at all; it resolves
|
||||
`gsd-tools.cjs` itself via a bespoke `PREFERRED_CONFIG_DIR`/
|
||||
`PREFERRED_RUNTIME`-aware `$GSD_TOOLS` cascade (`get_installed_version`,
|
||||
`msd-tools.cjs` itself via a bespoke `PREFERRED_CONFIG_DIR`/
|
||||
`PREFERRED_RUNTIME`-aware `$MSD_TOOLS` cascade (`get_installed_version`,
|
||||
~lines 13-45) because the update workflow must run before any install can be
|
||||
assumed resolvable. The new `init.update` call REUSES that already-resolved
|
||||
`$GSD_TOOLS` (dual `.cjs`/PATH-shim invocation style, matching the
|
||||
`$MSD_TOOLS` (dual `.cjs`/PATH-shim invocation style, matching the
|
||||
pre-existing `update-context` call) rather than copying the canonical
|
||||
launcher preamble — both resolutions assign the identical `$GSD_TOOLS` shell
|
||||
launcher preamble — both resolutions assign the identical `$MSD_TOOLS` shell
|
||||
variable, and the canonical preamble would silently clobber the value later
|
||||
steps (`backup_custom_files`, `restore_custom_files`) still depend on.
|
||||
`cmdInitUpdate`'s `nextChannel` fact (`--next` OR its documented alias
|
||||
@@ -612,17 +612,17 @@ steps (`backup_custom_files`, `restore_custom_files`) still depend on.
|
||||
stays byte-identical — issue #815's regression test
|
||||
(`tests/update-workflow.test.cjs`) asserts that literal
|
||||
case-statement text remains in the workflow, since the npm dist-tag
|
||||
selection has to run in the workflow's own shell before any `gsd_run`
|
||||
selection has to run in the workflow's own shell before any `msd_run`
|
||||
round-trip.
|
||||
|
||||
`transition.md` marks one section: `workstream-collision-check`
|
||||
(`state:workstream-active`) — an internal workflow (it has no user-facing
|
||||
slash command of its own) that previously called NO `init.*` command at
|
||||
all. It already establishes `gsd_run()` via the canonical launcher preamble
|
||||
all. It already establishes `msd_run()` via the canonical launcher preamble
|
||||
in its `update_roadmap_and_state` step, before this call's insertion point
|
||||
in `offer_next_phase`, so no second preamble copy is needed. The section's
|
||||
body previously re-derived its own gating condition via an inline `gsd_run
|
||||
query workstream.list --raw` call wrapped in `if [ -n "$GSD_WORKSTREAM" ]`
|
||||
body previously re-derived its own gating condition via an inline `msd_run
|
||||
query workstream.list --raw` call wrapped in `if [ -n "$MSD_WORKSTREAM" ]`
|
||||
— the identical condition that now backs the section's own admission (the
|
||||
same resolver-in-body hazard `code-review.md`'s `structural-pre-pass` and
|
||||
`complete-milestone.md`'s `git-tag` documented). `cmdInitTransition` hoists
|
||||
@@ -631,7 +631,7 @@ this via `getOtherActiveWorkstreamInventories` (`src/workstream-inventory.cts`
|
||||
as the step's own prose described (excludes the current workstream and any
|
||||
workstream whose status contains "milestone complete" or "archived",
|
||||
case-insensitively), exposed as `other_active_workstreams`; the step body is
|
||||
now a pure JSON consumer with no `gsd_run` call of its own.
|
||||
now a pure JSON consumer with no `msd_run` call of its own.
|
||||
|
||||
**`plan-phase.md` was originally retargeted away from the #2930 pilot,
|
||||
then fragmentized here once the blocker cleared.** Issue #2930's own
|
||||
@@ -642,7 +642,7 @@ gate (`tests/phase6-capstone-conformance.test.cjs`'s `PRE_PHASE6`, an
|
||||
ADR-857 Phase-6 completion property) and could not absorb any marker
|
||||
overhead at all. #2993 resolves this **because fragmentizing is net-negative
|
||||
on host source, not net-positive**: each gated body moves from always-inline
|
||||
prose to a `gsd-core/workflows/plan-phase/steps/<id>.md` step file, leaving
|
||||
prose to a `msd-core/workflows/plan-phase/steps/<id>.md` step file, leaving
|
||||
only a ~200 B conditional-read stub behind — the six extractions trim
|
||||
`plan-phase.md` from 94,483 B to 87,575 B, moving the file from 36 B of
|
||||
`PRE_PHASE6` headroom to roughly 7,000 B, well clear of the cap.
|
||||
@@ -672,6 +672,6 @@ question 1's resolution for the full record.
|
||||
- `src/section-manifest.cts` — the pure `when=` evaluator (`selectSections`,
|
||||
`InvocationFacts`) consumed by the init seam.
|
||||
- `scripts/gen-section-manifest.cjs` — generates the committed
|
||||
`gsd-core/workflows/section-manifest.json` artifact from markers.
|
||||
`msd-core/workflows/section-manifest.json` artifact from markers.
|
||||
- `src/init.cts` — `buildSectionManifestField` and the fifteen wired
|
||||
`cmdInit*` entry points.
|
||||
|
||||
Reference in New Issue
Block a user