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.
GSD 1.6.0 opens the capability platform (ADR-857) to **third-party authors**. Developers can write a capability, publish it at a URL, and any GSD user can `import` it, keep it `up to date`, and `remove` it cleanly — with versioned manifests, host-compatibility checks, and an explicit trust gate for capabilities that run code. A generated **capability matrix** documents every capability (native and third-party) and gives authors a place to plug in.
MSD 1.6.0 opens the capability platform (ADR-857) to **third-party authors**. Developers can write a capability, publish it at a URL, and any MSD user can `import` it, keep it `up to date`, and `remove` it cleanly — with versioned manifests, host-compatibility checks, and an explicit trust gate for capabilities that run code. A generated **capability matrix** documents every capability (native and third-party) and gives authors a place to plug in.
## 2. Problem & opportunity
ADR-857 made GSD extensible *in principle* — 12 loop extension points, 32 capabilities — but the platform is closed: the registry is build-time-only, capabilities are unversioned, and there is no per-capability install/upgrade/remove. A solo developer cannot share the capability they built, and cannot adopt one someone else built, without forking GSD or routing a PR through the maintainer.
ADR-857 made MSD extensible *in principle* — 12 loop extension points, 32 capabilities — but the platform is closed: the registry is build-time-only, capabilities are unversioned, and there is no per-capability install/upgrade/remove. A solo developer cannot share the capability they built, and cannot adopt one someone else built, without forking MSD or routing a PR through the maintainer.
The opportunity: turn an internal architecture into an **ecosystem**, where the long tail of stack-specific and house-style capabilities lives *outside* the core repo — reducing maintainer burden while expanding what GSD can do for any given user.
The opportunity: turn an internal architecture into an **ecosystem**, where the long tail of stack-specific and house-style capabilities lives *outside* the core repo — reducing maintainer burden while expanding what MSD can do for any given user.
## 3. Personas
| Persona | Goal | Today's pain |
|---|---|---|
| **Capability author** (solo dev who extends GSD) | Ship a reusable capability (a deploy gate, a house-style review step, a domain planner contribution) once and reuse it everywhere | No distribution path; must fork GSD or upstream a PR for every change |
| **Capability consumer** (solo dev using GSD) | Add a community/team capability to a project in one step, and keep it current | No install path; no version surface; no clean removal |
| **Maintainer** | Grow GSD's reach without absorbing every extension as permanent core maintenance | Every useful idea becomes an upstream PR and forever-maintenance |
| **Capability author** (solo dev who extends MSD) | Ship a reusable capability (a deploy gate, a house-style review step, a domain planner contribution) once and reuse it everywhere | No distribution path; must fork MSD or upstream a PR for every change |
| **Capability consumer** (solo dev using MSD) | Add a community/team capability to a project in one step, and keep it current | No install path; no version surface; no clean removal |
| **Maintainer** | Grow MSD's reach without absorbing every extension as permanent core maintenance | Every useful idea becomes an upstream PR and forever-maintenance |
| **Team lead / enterprise admin** | Constrain which capability sources are allowed | No allowlist; no trust controls |
## 4. Goals
- **G1.** A capability author can publish a capability at a Git URL (or npm/tarball/registry) and a consumer can install it with one command.
- **G2.** Capabilities are versioned; consumers can see when an update exists and apply it deliberately.
- **G3.** Host↔capability compatibility is explicit (`engines.gsd`) and enforced, with graceful downgrade where possible.
- **G3.** Host↔capability compatibility is explicit (`engines.msd`) and enforced, with graceful downgrade where possible.
- **G4.** Installing a capability that runs code (hooks/MCP/command modules) requires informed, explicit consent and integrity verification — and never runs code at install time.
- **G5.** Capabilities can be upgraded atomically and removed cleanly (files + shared-config fragments), with no orphaned state.
- **G6.** A capability matrix documents every capability and gives third parties a documented way to be listed.
@@ -49,10 +49,10 @@ The opportunity: turn an internal architecture into an **ecosystem**, where the
## 6. Scope (1.6.0)
**In scope:** versioned `capability.json`; runtime registry overlay; `gsd capability install|update|outdated|remove|disable|list`; source resolver (registry/git/npm/tarball/local); capability ledger; trust/integrity/consent gate; native version stamping; registry-driven dispatch for third-party command families; the generated capability matrix; the full diataxis documentation set.
**In scope:** versioned `capability.json`; runtime registry overlay; `msd capability install|update|outdated|remove|disable|list`; source resolver (registry/git/npm/tarball/local); capability ledger; trust/integrity/consent gate; native version stamping; registry-driven dispatch for third-party command families; the generated capability matrix; the full diataxis documentation set.
**Out of scope (explicit non-goals for 1.6.0):**
- **Operating a hosted central community registry.** The *manifest* and *matrix mechanic* ship; whether GSD runs/advertises a curated registry is **TBD/TBA** (see §8). URL/git import does not depend on it.
- **Operating a hosted central community registry.** The *manifest* and *matrix mechanic* ship; whether MSD runs/advertises a curated registry is **TBD/TBA** (see §8). URL/git import does not depend on it.
- **Sandboxing third-party code.** Out of reach technically; the trust model is consent + integrity + reversibility (ADR-1244 D5).
- **Automated malware scanning / safety scorecards.** A possible follow-up if a curated registry is adopted; not in 1.6.0.
@@ -61,7 +61,7 @@ The opportunity: turn an internal architecture into an **ecosystem**, where the
## 7. Functional requirements (product-level)
- **FR1.** `install <spec>` accepts registry/git(#tag,#sha)/npm/tarball/local specs; shows a pre-install summary (name, version, author, artifact counts, **executable surfaces**, context-cost note) and requires consent for non-trusted sources.
- **FR2.** `engines.gsd` incompatibility blocks with a clear message and offers the newest `compatVersions`-compatible version when the source enumerates versions.
- **FR2.** `engines.msd` incompatibility blocks with a clear message and offers the newest `compatVersions`-compatible version when the source enumerates versions.
- **FR3.** `outdated` lists installed capabilities with an available update (per the documented per-source support matrix); `update [--all]` applies updates atomically.
- **FR4.** `remove <id>` deletes exactly what the ledger recorded (files + shared-config fragments) and prompts before deleting persistent capability data; `disable <id>` toggles off without removing files.
- **FR5.** `list` shows installed capabilities with version, source, tier, and enabled/disabled state.
@@ -70,7 +70,7 @@ The opportunity: turn an internal architecture into an **ecosystem**, where the
## 8. Open questions / decisions deferred
- **OQ1 — Advertise a community registry? (TBD/TBA).** The mechanic (versioned manifests + matrix + registry source adapter) ships. The product decision to *operate/advertise* a curated `gsd-capabilities-community` registry — with its review, scanning, and trust implications — is deferred to a follow-up. Recommendation when revisited: separate "official" (curated) from "community" (consented) sources, mirroring Claude Code's marketplace split.
- **OQ1 — Advertise a community registry? (TBD/TBA).** The mechanic (versioned manifests + matrix + registry source adapter) ships. The product decision to *operate/advertise* a curated `msd-capabilities-community` registry — with its review, scanning, and trust implications — is deferred to a follow-up. Recommendation when revisited: separate "official" (curated) from "community" (consented) sources, mirroring Claude Code's marketplace split.
- **OQ2 — Provenance enforcement.** SHOULD for first-party/curated now; whether to *require* provenance for any listed third-party capability is tied to OQ1.
- **OQ3 — Inter-capability dependency resolution depth.** 1.6.0 validates `requires` closure remains satisfiable on install/upgrade; full npm-style transitive version resolution is a candidate follow-up.
@@ -82,4 +82,4 @@ The opportunity: turn an internal architecture into an **ecosystem**, where the
## 10. Release & rollout
Phased per ADR-1244 (manifest versioning → overlay → resolver+ledger → trust gate → dispatch → docs/matrix). Documentation ships with the implementing phase. The advertising decision (OQ1) is explicitly a separate, later call — 1.6.0 ships the capability to import from any URL and the documentation mechanic, not a GSD-run storefront.
Phased per ADR-1244 (manifest versioning → overlay → resolver+ledger → trust gate → dispatch → docs/matrix). Documentation ships with the implementing phase. The advertising decision (OQ1) is explicitly a separate, later call — 1.6.0 ships the capability to import from any URL and the documentation mechanic, not a MSD-run storefront.
# PRD: CJS↔SDK hard seam — Shared-Module migration
- **Status:** Superseded by [ADR-0174](../adr/0174-retire-gsd-sdk-package-boundary.md) (2026-05-23) — historical migration plan; the CJS↔SDK seam and its hand-sync tooling were retired with the `@opengsd/gsd-sdk` package boundary
- **Status:** Superseded by [ADR-0174](../adr/0174-retire-msd-sdk-package-boundary.md) (2026-05-23) — historical migration plan; the CJS↔SDK seam and its hand-sync tooling were retired with the `@opengsd/gsd-sdk` package boundary
@@ -11,7 +11,7 @@ The ADR defines the target architecture — one source of truth per Shared Modul
## Problem statement
The CJS↔SDK boundary in `open-gsd/gsd-core` is structurally permeable. Multiple Shared Modules — STATE.md Document Module, Workstream Inventory Module, and several others — exist today as **hand-synced pairs** of `.cjs` and `.ts` files with character-identical implementations. Constants (`CONFIG_DEFAULTS`, `VALID_CONFIG_KEYS`) are likewise defined twice. The boundary is policed only by:
The CJS↔SDK boundary in `golem15com/msd-core` is structurally permeable. Multiple Shared Modules — STATE.md Document Module, Workstream Inventory Module, and several others — exist today as **hand-synced pairs** of `.cjs` and `.ts` files with character-identical implementations. Constants (`CONFIG_DEFAULTS`, `VALID_CONFIG_KEYS`) are likewise defined twice. The boundary is policed only by:
- A naming-parity test (`tests/config-schema-sdk-parity.test.cjs`)
- Output-parity golden tests for read-only handlers (`sdk/src/golden/read-only-parity.integration.test.ts`)
@@ -35,13 +35,13 @@ The fix is mechanical: for every hand-synced pair, replace one side with a gener
## Non-goals
- Removing the CJS CLI. `gsd-tools` continues to exist for shell-script back-compat. (Its dispatcher delegates to the SDK runtime bridge after Phase 5; the external CLI contract is unchanged.)
- Removing the CJS CLI. `msd-tools` continues to exist for shell-script back-compat. (Its dispatcher delegates to the SDK runtime bridge after Phase 5; the external CLI contract is unchanged.)
- Defining a Verify Module before the verify surface has a shared Interface. Verify-surface deepening is precondition work for a future enhancement.
## Approach
The repo already has a working precedent for shared CJS/SDK Modules: `sdk/scripts/gen-command-aliases.ts` emits both `sdk/src/query/command-aliases.generated.ts` and `gsd-core/bin/lib/command-aliases.generated.cjs` from a single TypeScript source. `sdk/scripts/check-command-aliases-fresh.mjs` is the CI freshness gate that fails when either generated file drifts from the source. This PRD generalizes that pattern to every Shared Module.
The repo already has a working precedent for shared CJS/SDK Modules: `sdk/scripts/gen-command-aliases.ts` emits both `sdk/src/query/command-aliases.generated.ts` and `msd-core/bin/lib/command-aliases.generated.cjs` from a single TypeScript source. `sdk/scripts/check-command-aliases-fresh.mjs` is the CI freshness gate that fails when either generated file drifts from the source. This PRD generalizes that pattern to every Shared Module.
For each Shared Module being migrated:
@@ -66,7 +66,7 @@ Phases are sized to ship in one to two PRs each. Each phase has its own GitHub i
**Scope:**
- Promote `sdk/src/query/state-document.ts` to `sdk/src/state/index.ts` (implemented).
- Write `sdk/scripts/gen-state-document.ts` that emits `gsd-core/bin/lib/state-document.generated.cjs` (and optionally re-exports the TS form at its existing location).
- Write `sdk/scripts/gen-state-document.ts` that emits `msd-core/bin/lib/state-document.generated.cjs` (and optionally re-exports the TS form at its existing location).
- Write `sdk/scripts/check-state-document-fresh.mjs` modeled on `check-command-aliases-fresh.mjs`.
- Replace `bin/lib/state-document.cjs` content with a thin re-export from `state-document.generated.cjs`. Keep the existing filename so callers (e.g. `workstream-inventory.cjs:16`) don't need to update imports.
- Wire `check-state-document-fresh.mjs` into CI alongside `check-command-aliases-fresh.mjs`.
@@ -90,7 +90,7 @@ Phases are sized to ship in one to two PRs each. Each phase has its own GitHub i
- Add a **Configuration Module** entry to `CONTEXT.md` first. Definition: "Module owning config load, legacy-key normalization, defaults merge, and explicit on-disk migration for `.planning/config.json`." Interface and invariants per ADR §6.
- Extract `CONFIG_DEFAULTS`, `VALID_CONFIG_KEYS`, `DYNAMIC_KEY_PATTERNS`, `RUNTIME_STATE_KEYS` to two data manifests: `sdk/shared/config-schema.manifest.json` and `sdk/shared/config-defaults.manifest.json`. Precedent: `sdk/shared/model-catalog.json`.
- Write the Configuration Module source at `sdk/src/config/index.ts`. Implementation imports the two manifests and exports `loadConfig`, `normalizeLegacyKeys`, `mergeDefaults`, `migrateOnDisk`.
- Write `sdk/scripts/gen-configuration.ts` to emit `gsd-core/bin/lib/configuration.generated.cjs` and (if needed) `sdk/src/query/config-schema.generated.ts`.
- Write `sdk/scripts/gen-configuration.ts` to emit `msd-core/bin/lib/configuration.generated.cjs` and (if needed) `sdk/src/query/config-schema.generated.ts`.
- Replace the inline implementations in `bin/lib/core.cjs:loadConfig` (lines 220–243, 434–449, 485) and `bin/lib/config.cjs` (the validation surface) with thin Adapters over the generated Module. Delete the inline `CONFIG_DEFAULTS`, the false-positive warning at `core.cjs:444-449`, and the duplicated `_deepMergeConfig`.
- Replace `sdk/src/config.ts:mergeDefaults` (lines 192–218) with a re-export from the new Module.
@@ -113,7 +113,7 @@ Phases are sized to ship in one to two PRs each. Each phase has its own GitHub i
**Scope:**
- Write the Workstream Inventory Builder source at `sdk/src/workstream/builder.ts`. Pure function: takes a list of directory entries plus per-workstream STATE.md text plus plan-scan results and returns the typed `WorkstreamPhaseInventory`/`WorkstreamInventory` projection. No fs reads.
- Write `sdk/scripts/gen-workstream-inventory-builder.ts` to emit `gsd-core/bin/lib/workstream-inventory-builder.generated.cjs` and `sdk/src/query/workstream-inventory-builder.generated.ts`.
- Write `sdk/scripts/gen-workstream-inventory-builder.ts` to emit `msd-core/bin/lib/workstream-inventory-builder.generated.cjs` and `sdk/src/query/workstream-inventory-builder.generated.ts`.
- Refactor `bin/lib/workstream-inventory.cjs` to a sync Reader Adapter: does `fs.readdirSync` + `readFileSync` of STATE.md, calls the Builder. The projection logic is removed.
- Refactor `sdk/src/query/workstream-inventory.ts` to an async Reader Adapter: same shape, async I/O, calls the Builder.
@@ -149,24 +149,24 @@ Phases are sized to ship in one to two PRs each. Each phase has its own GitHub i
### Phase 5 — CJS Command Router Adapter: delegate to the SDK runtime bridge
**Why fifth.** Phases 1–4 collapse drift in *shared* logic. Phase 5 collapses drift in *parallel* logic — the per-side state/verify/init/phase/roadmap/validate handler implementations on the CJS side. After Phase 5, every canonical command running via `gsd-tools` executes the same SDK handler that `gsd-sdk query` executes, in-process, with no subprocess hop. The seam becomes a real wall.
**Why fifth.** Phases 1–4 collapse drift in *shared* logic. Phase 5 collapses drift in *parallel* logic — the per-side state/verify/init/phase/roadmap/validate handler implementations on the CJS side. After Phase 5, every canonical command running via `msd-tools` executes the same SDK handler that `msd-sdk query` executes, in-process, with no subprocess hop. The seam becomes a real wall.
**Scope:**
- Amend the existing `CJS Command Router Adapter Module` CONTEXT.md entry to document runtime-bridge delegation.
- Expose a synchronous-friendly entry on `QueryRuntimeBridge` for CJS callers. Today `QueryRuntimeBridge.execute()` is async; the bridge gains a `executeForCjs(input) → { exitCode, stdoutChunks, stderrLines }` synchronous wrapper that runs the dispatch under `deasync` or a controlled `runUntil` semantic. (Toolchain choice resolved in the Phase 5 issue; if synchronous bridging is not viable, fall back to `Atomics.wait` on a worker channel — never `gsd-sdk` subprocess.)
- Expose a synchronous-friendly entry on `QueryRuntimeBridge` for CJS callers. Today `QueryRuntimeBridge.execute()` is async; the bridge gains a `executeForCjs(input) → { exitCode, stdoutChunks, stderrLines }` synchronous wrapper that runs the dispatch under `deasync` or a controlled `runUntil` semantic. (Toolchain choice resolved in the Phase 5 issue; if synchronous bridging is not viable, fall back to `Atomics.wait` on a worker channel — never `msd-sdk` subprocess.)
- Replace each canonical-family `handlers` map in `bin/lib/*-command-router.cjs` with a generated delegate emitter that, per subcommand, calls `executeForCjs({ canonical, argv, env, cwd })` and writes the result through the existing CJS output Adapter.
- For each canonical command family in order — `state.*`, `verify.*`, `phase.*`, `phases.*`, `validate.*`, `roadmap.*`, `init.*`, `frontmatter.*`, `config.*`, plus the non-family commands listed in `sdk/src/query/command-manifest.non-family.ts` — migrate one family per sub-PR. Run the golden parity matrix per family before merging.
- Delete CJS-side handler files (or shrink to delegates) for each migrated family: `state.cjs`, `verify.cjs`, `init.cjs`, `phase.cjs`, `phases.cjs`, `validate.cjs`, `roadmap.cjs`, `milestone.cjs`, `frontmatter.cjs`, `config.cjs` write paths, plan-scan handlers, etc. The pure-transform Shared Modules from Phases 1–4 remain untouched; only the per-family handler entry points are replaced.
- CJS-only Module handlers (`graphify`, `gsd2-import`, `schema-detect`, `fallow-runner`, `intel`, `drift`, `installer-migrations`) keep their in-process CJS implementations. They are not in the canonical family registry and do not route through the SDK runtime bridge.
- Extend `sdk/src/golden/golden.integration.test.ts` to verify identical exit code + stdout chunks + stderr lines between `gsd-tools <family> <subcommand>` (now delegated) and `gsd-sdk query <canonical>` for every canonical command in the manifest.
- Extend `sdk/src/golden/golden.integration.test.ts` to verify identical exit code + stdout chunks + stderr lines between `msd-tools <family> <subcommand>` (now delegated) and `msd-sdk query <canonical>` for every canonical command in the manifest.
- [ ]`QueryRuntimeBridge.executeForCjs` (or equivalent) ships with the synchronous semantics resolved in the phase issue.
- [ ] Every canonical command family in `command-manifest.*.ts` routes via `executeForCjs`. CJS-only commands continue to route via the existing CJS handler.
- [ ] Each per-family CJS handler file (`state.cjs`, `verify.cjs`, …) contains no command-specific logic — only the delegate wiring or has been deleted entirely.
- [ ] Golden parity matrix verifies output equivalence across `gsd-tools` and `gsd-sdk` for every canonical command. No regressions in workflow markdown that calls `gsd-tools`.
- [ ] Subprocess overhead per `gsd-tools` invocation does not increase (the bridge is in-process, not a `gsd-sdk` subprocess).
- [ ] Golden parity matrix verifies output equivalence across `msd-tools` and `msd-sdk` for every canonical command. No regressions in workflow markdown that calls `msd-tools`.
- [ ] Subprocess overhead per `msd-tools` invocation does not increase (the bridge is in-process, not a `msd-sdk` subprocess).
**Rollback (per family):** Each family's PR is independently revertible. The CJS handler files for an un-migrated family remain on disk in git history; if a family's delegation regresses, revert that family's PR and the CJS-side handler is restored.
@@ -177,7 +177,7 @@ Phases are sized to ship in one to two PRs each. Each phase has its own GitHub i
- Write `scripts/lint-shared-module-handsync.cjs`. Greps for any pair of files at `gsd-core/bin/lib/<name>.cjs` and `sdk/src/query/<name>.ts` (or `sdk/src/<name>.ts`) where neither file matches `*.generated.*` and the pair is not on an explicit allow-list. Allow-list documents the cooperating-sibling exceptions (e.g. routing files where the implementations are structurally different).
- Write `scripts/lint-shared-module-handsync.cjs`. Greps for any pair of files at `msd-core/bin/lib/<name>.cjs` and `sdk/src/query/<name>.ts` (or `sdk/src/<name>.ts`) where neither file matches `*.generated.*` and the pair is not on an explicit allow-list. Allow-list documents the cooperating-sibling exceptions (e.g. routing files where the implementations are structurally different).
- Verify each Shared Module from Phases 1–4 has its own freshness check wired to CI.
- Verify Phase 5's golden parity matrix covers every canonical command family.
- Add CODEOWNERS rules for `sdk/src/<module>/**` for each Shared Module source-of-truth directory, for `sdk/shared/*.manifest.json`, and for `sdk/src/query-runtime-bridge.ts` (the Phase 5 boundary). Architecture-team review required.
@@ -198,18 +198,18 @@ Phases are sized to ship in one to two PRs each. Each phase has its own GitHub i
### Backwards compatibility
The CJS public CLI surface (`gsd-tools <subcommand>`) does not change. Flags, exit codes, stdout shapes preserved. Every phase replaces internal implementations behind the existing Module Interfaces; the external contracts are pinned by the existing golden parity suite plus the new fixture matrices.
The CJS public CLI surface (`msd-tools <subcommand>`) does not change. Flags, exit codes, stdout shapes preserved. Every phase replaces internal implementations behind the existing Module Interfaces; the external contracts are pinned by the existing golden parity suite plus the new fixture matrices.
### Performance
No subprocess overhead anywhere. The generated `.cjs` files are `require`-able CommonJS modules; the SDK consumes the TS source directly. Module load cost adds ≤ 10 ms per `require` across all phases combined.
Phase 5 specifically preserves the in-process model: `QueryRuntimeBridge.executeForCjs` runs the SDK handler in the same Node process as the CJS dispatcher. No `gsd-sdk` subprocess is invoked. Synchronous bridging adds at most a handful of microseconds per call vs the previous direct CJS handler invocation, dominated by the existing dispatch policy overhead.
Phase 5 specifically preserves the in-process model: `QueryRuntimeBridge.executeForCjs` runs the SDK handler in the same Node process as the CJS dispatcher. No `msd-sdk` subprocess is invoked. Synchronous bridging adds at most a handful of microseconds per call vs the previous direct CJS handler invocation, dominated by the existing dispatch policy overhead.
### Build/install pipeline impact
- Each generator runs at build time on the developer machine (and in CI for the freshness check). No runtime generator execution.
- The published `@opengsd/gsd-core` package already includes both `gsd-core/bin/` and `sdk/dist/`. The generated `.cjs` files are committed to the repo (like `command-aliases.generated.cjs` today), so the install flow is unchanged — no on-install code generation.
- The published `@golem15/msd-core` package already includes both `msd-core/bin/` and `sdk/dist/`. The generated `.cjs` files are committed to the repo (like `command-aliases.generated.cjs` today), so the install flow is unchanged — no on-install code generation.
-`npm run build:sdk` continues to do what it does. Generators are invoked via `npm run gen:<module>` per the existing precedent.
| Generator output drifts from source between commits | Medium | `check-<module>-fresh.mjs` per Module catches this at PR time. Precedent already in use for command-aliases. |
| A Shared Module's TS source uses features not expressible in CommonJS output | Low | Generator emits a CJS-compatible subset (no ESM-only syntax in source). Existing `gen-command-aliases.ts` template covers this. |
| Phase 2's removal of inline `_deepMergeConfig` changes a subtle merge semantic | Medium | Golden parity matrix is the test. If `_deepMergeConfig` and the new Module disagree on a fixture, the matrix fails and the new Module is amended before merge. |
| `migrateOnDisk` rollout silently changes user-visible behavior on upgrade | Medium | `migrateOnDisk` is explicit and opt-in; installer calls it once on next upgrade, with a release-note entry. Standalone command `gsd-tools migrate-config` for manual invocation. |
| `migrateOnDisk` rollout silently changes user-visible behavior on upgrade | Medium | `migrateOnDisk` is explicit and opt-in; installer calls it once on next upgrade, with a release-note entry. Standalone command `msd-tools migrate-config` for manual invocation. |
| CODEOWNERS rule slows down architecture-team responsiveness | Medium | Apply CODEOWNERS only to source-of-truth directories and manifests. Adapters and `.generated.*` files remain open. Architecture team commits to a ≤ 24 h SLA. |
| Phase 3's audit surfaces more pairs than expected, scope creeps | Medium | Each non-Phase-1/2 Module is scope-checked in its phase issue. Pairs that don't fit cleanly are deferred with a documented reason. |
| Phase 5's synchronous-bridging mechanism (`executeForCjs`) has no clean shape — `deasync` is C++-bound, `Atomics.wait` requires a Worker, refactoring every SDK handler to be sync is huge | High | Phase 5 spike resolves this before any family migration. If no clean mechanism exists, Phase 5 is descoped to the families whose SDK handlers are already synchronous, and the remainder shift to a follow-up enhancement. |
| Phase 5 family migrations regress observable CJS output (exit codes, stdout/stderr shape) | Medium | Golden parity matrix per family is the gate. A family's PR cannot merge until the matrix is green across every canonical command in that family. |
| Phase 5 changes startup time because the SDK runtime bridge eagerly loads more handlers than the previous CJS routers | Low | Lazy-load handlers behind the bridge (already the SDK's model). Measure `time gsd-tools state load` before/after migration; fail the family PR if median latency regresses >20 ms. |
| Phase 5 changes startup time because the SDK runtime bridge eagerly loads more handlers than the previous CJS routers | Low | Lazy-load handlers behind the bridge (already the SDK's model). Measure `time msd-tools state load` before/after migration; fail the family PR if median latency regresses >20 ms. |
### Open questions (resolved before the phase that depends on them)
This directory contains Product Requirements Documents (PRDs) for GSD.
This directory contains Product Requirements Documents (PRDs) for MSD.
A PRD captures the **what** and **why** of a feature before implementation begins. ADRs (in `docs/adr/`) capture the **how** of architectural decisions. The two complement each other: a PRD makes the case for a feature and defines acceptance criteria; an ADR records the architectural mechanism chosen to deliver it.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.