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:
Jakub Zych
2026-10-06 01:47:40 +02:00
parent fe069b2a56
commit a9a7a328e6
2763 changed files with 78465 additions and 78434 deletions

View File

@@ -5,11 +5,11 @@
- **Epic:** [#857](https://github.com/open-gsd/gsd-core/issues/857) (Capability system) — rollout phase 4d
- **Amends:** [ADR-894](894-capability-declaration-format.md) (adds the deferred `commands` field)
- **Realizes:** [ADR-857](857-capability-system.md) decision 7 (in-tree code modules become Capabilities via an opened `runCommand` entrypoint)
- **Builds on:** [ADR-0012](0012-command-routing-hub.md) / [ADR-0174](0174-retire-gsd-sdk-package-boundary.md) (CommandRoutingHub)
- **Builds on:** [ADR-0012](0012-command-routing-hub.md) / [ADR-0174](0174-retire-msd-sdk-package-boundary.md) (CommandRoutingHub)
## Context
ADR-857 decision 7 reserved a `commands`/`module` field so in-tree code modules (`graphify`, `intel`, `audit`) could "become Capabilities by registering their query family through an **opened `gsd-tools.cjs` entrypoint (registry) over the current hardcoded switch**." ADR-894 fixed the `capability.json` format but **deferred** the `commands` field. This ADR designs it.
ADR-857 decision 7 reserved a `commands`/`module` field so in-tree code modules (`graphify`, `intel`, `audit`) could "become Capabilities by registering their query family through an **opened `msd-tools.cjs` entrypoint (registry) over the current hardcoded switch**." ADR-894 fixed the `capability.json` format but **deferred** the `commands` field. This ADR designs it.
The current dispatch reality:
@@ -18,11 +18,11 @@ The current dispatch reality:
- **The CommandRoutingHub (ADR-0012, simplified by ADR-0174) is stateless.** `createHub({ cjsRegistry, manifest })` is constructed *per dispatch* with an inline `family → subcommand → handler` table and exposes only `{ dispatch }`. There is **no** `register()` API and no persistent family registry. Each of the 12 routers builds a one-shot hub via `routeHubCommandFamily` and discards it. The hub's value is its uniform Result contract (`UnknownCommand`/`InvalidArgs`/`HandlerRefusal`/`HandlerFailure`), manifest-backed subcommand validation, arg-shape coercion, and observability.
- The registry and `capability.json` have **no `commands` field** today (confirmed absent).
Two distinct "command" kinds exist and must not be conflated: **gsd-tools CLI subcommands** (internal, invoked by workflows via `gsd_run`) and **slash-commands/skills** (`commands/gsd/*.md`, agent-facing). This ADR is about the **former** — the CLI subcommand families that code-module features own. Skills are already a capability contribution (`skills`).
Two distinct "command" kinds exist and must not be conflated: **msd-tools CLI subcommands** (internal, invoked by workflows via `msd_run`) and **slash-commands/skills** (`commands/msd/*.md`, agent-facing). This ADR is about the **former** — the CLI subcommand families that code-module features own. Skills are already a capability contribution (`skills`).
## Decision
> **Core principle (grilled):** the codebase already has the right abstraction — the **router**. The 12 `route*Command` functions each own a family's subcommand dispatch + arg parsing, and each already routes through the hub via `routeCjsCommandFamily`. A capability command family is therefore **just a router, discovered via the registry instead of hardcoded** into gsd-tools' requires + switch. The registry's job is *discovery*, not re-implementing routing. This is the minimal change and reuses the proven abstraction wholesale — there is no new handler/arg convention.
> **Core principle (grilled):** the codebase already has the right abstraction — the **router**. The 12 `route*Command` functions each own a family's subcommand dispatch + arg parsing, and each already routes through the hub via `routeCjsCommandFamily`. A capability command family is therefore **just a router, discovered via the registry instead of hardcoded** into msd-tools' requires + switch. The registry's job is *discovery*, not re-implementing routing. This is the minimal change and reuses the proven abstraction wholesale — there is no new handler/arg convention.
### 1. A `commands` contribution on the `feature` role — no new role
@@ -32,8 +32,8 @@ A capability declares the CLI command families it owns, alongside its existing `
// capability.json (feature role) — new optional field
"commands": [
{
"family": "graphify", // the top-level gsd-tools command this capability owns
"module": "graphify.cjs", // first-party in-tree module under gsd-core/bin/lib/
"family": "graphify", // the top-level msd-tools command this capability owns
"module": "graphify.cjs", // first-party in-tree module under msd-core/bin/lib/
"router": "routeGraphifyCommand", // exported router fn (same shape as the 12 host routers)
"subcommands": ["query", "status"] // OPTIONAL — doc/introspection metadata only; NOT used for dispatch
}
@@ -41,7 +41,7 @@ A capability declares the CLI command families it owns, alongside its existing `
```
- **`family`** — the top-level command string (single ownership across all capabilities).
- **`module`** — a first-party path resolved relative to `gsd-core/bin/lib/`. Third-party / out-of-tree modules are **out of scope** (ADR-857 decision 7); they require their own trust/load ADR.
- **`module`** — a first-party path resolved relative to `msd-core/bin/lib/`. Third-party / out-of-tree modules are **out of scope** (ADR-857 decision 7); they require their own trust/load ADR.
- **`router`** — the exported function with the standard router signature `({ args, cwd, raw, error }) => void` — identical to `routeInitCommand` et al. It owns its own subcommand list, arg parsing, and `defaultSubcommand` internally, exactly as the 12 existing routers do.
- **`subcommands`** — optional, doc/introspection only; dispatch does not consult it (the router owns subcommand resolution).
@@ -86,14 +86,14 @@ This makes collision **structurally impossible**: a command is dispatched by its
### 5. First-party only; third-party deferred
`module` is confined to `gsd-core/bin/lib/` and `require`d in-process — the same trust level as the host's own handlers. Loading out-of-tree / third-party command modules carries a distinct trust/load/build/security surface and is **deferred to its own ADR** (mirroring the runtime third-party deferral in ADR-857 branch 8). The seam is built so that door can be opened later additively.
`module` is confined to `msd-core/bin/lib/` and `require`d in-process — the same trust level as the host's own handlers. Loading out-of-tree / third-party command modules carries a distinct trust/load/build/security surface and is **deferred to its own ADR** (mirroring the runtime third-party deferral in ADR-857 branch 8). The seam is built so that door can be opened later additively.
### 6. Staged rollout — `graphify` is the first *real* cutover (the pilot), not a synthetic fixture
A synthetic fixture proves the *plumbing* but not the *model*; only a real command exercises router extraction, the full capability bundle (command + skill + config gate + tier), and registry multiplicity. The maintainer also wants a user-testable artifact. So the pilot is a real cutover, chosen for minimum risk:
1. **Build phase (4d-impl):** add the `commands` schema + the `commandFamilies` index + the real `dispatchCapabilityCommand` in the `default` case, **and** cut over **`graphify`** as the first capability that owns a command family — in one cohesive migration:
- a `graphify` capability bundling its command (`family: graphify`, a new first-party `graphify-command-router.cjs` extracted from the inline `case` sub-switch), its existing skill (`commands/gsd/graphify.md`), its config gate (`isGraphifyEnabled`), and `tier: full`;
- a `graphify` capability bundling its command (`family: graphify`, a new first-party `graphify-command-router.cjs` extracted from the inline `case` sub-switch), its existing skill (`commands/msd/graphify.md`), its config gate (`isGraphifyEnabled`), and `tier: full`;
- remove the `case 'graphify':` arm so dispatch flows `default → registry → routeGraphifyCommand`;
- **equivalence tests** proving every `graphify <sub>` invocation (incl. the `--budget` flag and the hidden `build snapshot`) behaves identically old-path vs new-path.
- `graphify` is the safest first target: zero workflow hot-path blast radius (no core workflow invokes it via bash — the skill drives it), smallest handler (496 LOC / 4 subcommands), already has a skill + cluster + config gate, and is `full`-only so the 4c install/surface consumption stays a no-op.
@@ -105,7 +105,7 @@ A synthetic fixture proves the *plumbing* but not the *model*; only a real comma
### Validation invariants (enforced by the generator)
- **Single family ownership** — a `family` is owned by exactly one capability.
- **First-party module** — `module` resolves under `gsd-core/bin/lib/`; no traversal.
- **First-party module** — `module` resolves under `msd-core/bin/lib/`; no traversal.
- **Router presence** — `router` is a non-empty string; its existence as an export is verified at load (and may be lint-checked).
- **Prototype-pollution guards** at every dynamic-key site (the repo's CodeQL barrier), as with the other registry indexes.