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

@@ -30,9 +30,9 @@
* stays hard-coded, so a dest change still fails loud.
*
* ── The trap this table exists to avoid ─────────────────────────────────────
* The repo contains `skills/gsd-<stem>/SKILL.md` (71 dirs) that LOOK like the source
* The repo contains `skills/msd-<stem>/SKILL.md` (71 dirs) that LOOK like the source
* of the emitted `skills/` family. They are not: scripts/gen-plugin-skills.cjs
* GENERATES them from commands/gsd/*.md, and the installer stages from commands/gsd/
* GENERATES them from commands/msd/*.md, and the installer stages from commands/msd/
* directly (src/install-profiles.cts:637-708). Attributing emitted skills to repo
* skills/ would be false attribution that still passes totality — the exact residual
* risk ADR-2719 records. The spot-check tests pin this pair.
@@ -59,14 +59,14 @@ const { MANIFEST_FAMILIES, runMinimalInstall, buildParityManifest } = require('.
const EXPECTED_MANIFEST_COUNT = MANIFEST_FAMILIES.length;
// ─── Emitted roots ────────────────────────────────────────────────────────────
// Longest-first: `skills/gsd` (hermes category dir) must win over `skills` for
// `skills/gsd/...`, and `.agents/skills` must win over `.agents`.
// Longest-first: `skills/msd` (hermes category dir) must win over `skills` for
// `skills/msd/...`, and `.agents/skills` must win over `.agents`.
const SKILLS_ROOTS = ['skills/gsd', '.agents/skills', 'skills'];
const SKILLS_ROOTS = ['skills/msd', '.agents/skills', 'skills'];
const HOOKS_ROOTS = ['.kimi-code/hooks', '.kimi/hooks', 'hooks'];
/** Source-of-truth command dir every skill/command surface converts from. */
const COMMANDS_SRC = 'commands/gsd';
const COMMANDS_SRC = 'commands/msd';
/** Installer source file that emits the Cline/AGENTS.md instruction bodies as
* code literals (buildClineRulesBody / buildClineAgentsMdBody /
@@ -168,7 +168,7 @@ const AGENT_TRANSFORM_SRCS = [
// #3738: antigravity's global skills pass through the antigravity converter
// (src/runtime-artifact-conversion.cts, mirrored hand-authored in bin/install.js
// per ADR-1508), whose rewrites — e.g. ~/.claude/skills/ → ~/.gemini/config/skills/
// — can move emitted bytes with NO commands/gsd source changing. Declaring the
// — can move emitted bytes with NO commands/msd source changing. Declaring the
// transform here attributes that ripple class permanently, the same way
// AGENT_TRANSFORM_SRCS does for agents; scoped to runtime 'antigravity' so a
// converter change never blankets the other skills runtimes' attribution.
@@ -179,7 +179,7 @@ const ANTIGRAVITY_SKILL_TRANSFORM_SRCS = [
// #4002: zcode's command AND skill bodies flow through `_applyRuntimeRewrites`
// (converter: null — the rewrite pass is their only path-rewriting step), so a
// converter change moves emitted bytes with no commands/gsd source changing.
// converter change moves emitted bytes with no commands/msd source changing.
// Same permanent-attribution shape as ANTIGRAVITY_SKILL_TRANSFORM_SRCS (#3738),
// scoped to runtime 'zcode' for the same reason.
const ZCODE_BODY_TRANSFORM_SRCS = [
@@ -214,7 +214,7 @@ const SOURCE_PREFIX_SUFFIX = '/';
* stem (src/install-profiles.cts:696 joins `stem`, not `prefix + stem`).
*/
function stripSkillPrefix(dirName) {
return dirName.startsWith('gsd-') ? dirName.slice(4) : dirName;
return dirName.startsWith('msd-') ? dirName.slice(4) : dirName;
}
/**
@@ -227,10 +227,10 @@ function nativePluginDescriptor(runtime) {
// rather than at module load for callers that never touch this family.
let registry;
try {
registry = require('../../gsd-core/bin/lib/capability-registry.cjs');
registry = require('../../msd-core/bin/lib/capability-registry.cjs');
} catch (err) {
throw new Error(
'emitted-provenance: cannot load gsd-core/bin/lib/capability-registry.cjs ' +
'emitted-provenance: cannot load msd-core/bin/lib/capability-registry.cjs ' +
`(run \`npm run build\` first): ${err.message}`,
);
}
@@ -282,18 +282,18 @@ function nativePluginDescriptor(runtime) {
const PROVENANCE_RULES = [
// ── Verbatim engine payload ────────────────────────────────────────────────
{
id: 'gsd-core-verbatim',
id: 'msd-core-verbatim',
// Markdown payloads pass through copyWithPathReplacement's audience
// filter for non-Copilot runtimes. Non-Markdown payloads remain byte-for-
// byte copies, but one rule has one kind; the match-specific transform
// list below keeps the causal attribution precise.
kind: 'derived',
roots: ['gsd-core'],
// Enumerated subdirs, NOT `.+`: a new gsd-core/<subdir> must fail totality
roots: ['msd-core'],
// Enumerated subdirs, NOT `.+`: a new msd-core/<subdir> must fail totality
// loudly rather than being absorbed silently. Also keeps this mutually
// exclusive with the two synthesized gsd-core top-level files below.
// exclusive with the two synthesized msd-core top-level files below.
pattern: /^(workflows|references|templates|contexts|bin)\/.+$/,
sources: (m) => [`gsd-core/${m[0]}`],
sources: (m) => [`msd-core/${m[0]}`],
transforms: (m, ctx) => (
m[0].endsWith('.md') && RUNTIME_NOTE_FILTERED_FAMILIES.has(ctx.runtime)
? RUNTIME_NOTE_FILTER_TRANSFORM_SRCS
@@ -301,17 +301,17 @@ const PROVENANCE_RULES = [
),
},
{
id: 'gsd-core-commands-corpus',
id: 'msd-core-commands-corpus',
kind: 'rewrite',
roots: ['gsd-core'],
pattern: /^commands\/gsd\/(.+)$/,
sources: (m) => [`commands/gsd/${m[1]}`],
roots: ['msd-core'],
pattern: /^commands\/msd\/(.+)$/,
sources: (m) => [`commands/msd/${m[1]}`],
transforms: [INSTALL_ENGINE_SRC, INSTALLER_SRC],
},
{
id: 'gsd-core-agents-corpus',
id: 'msd-core-agents-corpus',
kind: 'rewrite',
roots: ['gsd-core'],
roots: ['msd-core'],
pattern: /^agents\/(.+)$/,
sources: (m) => [`agents/${m[1]}`],
transforms: [INSTALL_ENGINE_SRC, INSTALLER_SRC],
@@ -330,7 +330,7 @@ const PROVENANCE_RULES = [
id: 'agents-verbatim',
// #2757 (was `identity`): measured against origin/next's own committed fixtures,
// the SAME emitted agents/<name>.md hashes DIFFERENTLY per runtime (e.g. codex vs
// claude for gsd-nyquist-auditor.md) — impossible for a true verbatim copy.
// claude for msd-nyquist-auditor.md) — impossible for a true verbatim copy.
// Verified empirically by installing every runtime and diffing the output against
// the raw repo source: no runtime reproduces it byte-for-byte. Every one rewrites
// frontmatter quoting and the hardcoded `.claude/` self-reference
@@ -340,15 +340,15 @@ const PROVENANCE_RULES = [
// per-runtime `kind`) and why this wholesale reclassification was chosen instead.
kind: 'derived',
roots: ['agents'],
// Excludes `gsd.md`: that is Kimi's ROOT agent, built from a code literal and
// Excludes `msd.md`: that is Kimi's ROOT agent, built from a code literal and
// NOT a repo agent file. Without the exclusion it matched here and resolved to
// `agents/gsd.md`, which does not exist — a false attribution that still passed
// `agents/msd.md`, which does not exist — a false attribution that still passed
// totality, i.e. the exact residual ADR-2719 records. Every repo agent is
// `gsd-<name>.md`, so excluding the bare `gsd.md` is precise.
// `msd-<name>.md`, so excluding the bare `msd.md` is precise.
// `.agent.md` is likewise excluded — Copilot emits a RENAMED copy
// (`<name>.agent.md`) whose source is `agents/<name>.md`; matching it here
// resolved to a file that does not exist. Same false-attribution class.
pattern: /^(?!gsd\.md$)(?!.*\.agent\.md$)[^/]+\.md$/,
pattern: /^(?!msd\.md$)(?!.*\.agent\.md$)[^/]+\.md$/,
sources: (m) => [`agents/${m[0]}`],
transforms: AGENT_TRANSFORM_SRCS,
},
@@ -401,7 +401,7 @@ const PROVENANCE_RULES = [
// Attribute to the REPO source a PR actually edits, not the build artifact.
// Excludes Copilot's hook-registration JSON (next rule) — that is a code
// literal, not a built script, and attributing it here resolved to a
// nonexistent `hooks/gsd-session.json`. `package.json` is excluded for the
// nonexistent `hooks/msd-session.json`. `package.json` is excluded for the
// same reason (the #2544 `commonjs-marker` rule below): there is no
// `hooks/package.json` in the repo to attribute to.
//
@@ -414,11 +414,11 @@ const PROVENANCE_RULES = [
// (HOOKS_WINDOWS_SHIM_SRC, src/runtime-hooks-surface.cts). The `.cmd` bytes
// are `@ECHO OFF\r\n@SETLOCAL\r\n@<runner> <script> %*\r\n` — built from the
// install-time interpreter token and the absolute install path, plus a
// hardcoded literal filename (e.g. `gsd-check-update.js`) baked into that
// hardcoded literal filename (e.g. `msd-check-update.js`) baked into that
// same source file. The wrapped `.js` file's NAME flows into the `.cmd`
// bytes; its CONTENT never does — see the `sources` comment below for why
// that rules out attributing to `hooks/<name>.js`.
pattern: /^(?!gsd-session\.json$|package\.json$).+$/,
pattern: /^(?!msd-session\.json$|package\.json$).+$/,
// `package.json` (the CommonJS marker) is excluded here and owned by the
// dedicated `commonjs-marker` rule below. #2717 attributed it inside THIS
// rule, routing it to HOOKS_WINDOWS_SHIM_SRC because at that point
@@ -447,11 +447,11 @@ const PROVENANCE_RULES = [
{
id: 'commonjs-marker',
kind: 'code-derived',
// Every root GSD stages its own `.js` files into and therefore pins to
// Every root MSD stages its own `.js` files into and therefore pins to
// CommonJS: the hooks roots, plus the native plugin/extension dirs.
roots: [...HOOKS_ROOTS, 'plugins', 'extensions'],
// #2544: a `{"type":"commonjs"}` module-type marker, written as a code
// literal so Node's ancestor walk resolves GSD's staged `.js` files as
// literal so Node's ancestor walk resolves MSD's staged `.js` files as
// CommonJS under an ambient `"type": "module"`. Like the Copilot
// registration JSON above it is emitted, never built — there is no
// `hooks/package.json` or `plugins/package.json` in the repo, so the
@@ -497,12 +497,12 @@ const PROVENANCE_RULES = [
},
{
// #3023: pi renames the shared hooks bundle's staged directory from the
// default `hooks/` to `gsd-hooks/` (hostBehaviors.sharedHooksDirName,
// default `hooks/` to `msd-hooks/` (hostBehaviors.sharedHooksDirName,
// bin/install.js's resolveSharedHooksDirName). Same family as `hooks-built`
// above (built from hooks/ via scripts/build-hooks.js), staged under a
// different root for exactly one runtime — a dedicated, `runtimes`-scoped
// rule keeps that pi-only rename from ever being able to shadow another
// host's `(rel, runtime)` pair, rather than folding 'gsd-hooks' into the
// host's `(rel, runtime)` pair, rather than folding 'msd-hooks' into the
// shared HOOKS_ROOTS list `hooks-built`/`commonjs-marker` both key off.
// `package.json` (the CommonJS marker) is excluded here and owned by the
// dedicated `pi-shared-hooks-commonjs-marker` rule below, mirroring how
@@ -510,19 +510,19 @@ const PROVENANCE_RULES = [
id: 'pi-shared-hooks-built',
kind: 'derived',
runtimes: new Set(['pi']),
roots: ['gsd-hooks'],
roots: ['msd-hooks'],
pattern: /^(?!package\.json$).+$/,
sources: (m) => [`hooks/${m[0]}`],
},
{
// Companion to `pi-shared-hooks-built`: the CommonJS-mode marker written
// into pi's renamed `gsd-hooks/` root by the same installSharedHooksBundle
// into pi's renamed `msd-hooks/` root by the same installSharedHooksBundle
// call the generic `commonjs-marker` rule attributes for the `hooks/`
// family. Kept as its own pi-scoped rule for the same reason as above.
id: 'pi-shared-hooks-commonjs-marker',
kind: 'code-derived',
runtimes: new Set(['pi']),
roots: ['gsd-hooks'],
roots: ['msd-hooks'],
pattern: /^package\.json$/,
sources: () => [COMMONJS_MARKER_SRC, INSTALLER_SRC],
},
@@ -534,11 +534,11 @@ const PROVENANCE_RULES = [
// by HOOK_CONFIG_FILES because they embed a platform-varying node-runner
// command), this one is platform-stable and stays in the manifest
// (src/runtime-hooks-surface.cts:73,89).
pattern: /^gsd-session\.json$/,
pattern: /^msd-session\.json$/,
sources: () => [CLINE_BODY_SRC],
},
// ── Skill / command surfaces — all convert from commands/gsd/*.md ──────────
// ── Skill / command surfaces — all convert from commands/msd/*.md ──────────
{
id: 'skills-from-commands',
kind: 'rewrite',
@@ -577,7 +577,7 @@ const PROVENANCE_RULES = [
id: 'flat-commands-from-commands',
kind: 'rewrite',
roots: ['commands', 'command'],
pattern: /^gsd-([^/]+)\.md$/,
pattern: /^msd-([^/]+)\.md$/,
sources: (m) => [`${COMMANDS_SRC}/${m[1]}.md`],
// #4482: OpenCode command bodies pass through its command converter.
// #4002: zcode command bodies pass through _applyRuntimeRewrites with
@@ -596,7 +596,7 @@ const PROVENANCE_RULES = [
roots: ['plugins', 'extensions'],
pattern: /^[^/]+\.(js|cjs|mjs)$/,
// Source is per-runtime (opencode -> .opencode/…, kilo -> .kilo/…,
// pi -> pi/gsd.cjs), so attribution is a function of (rel, runtime).
// pi -> pi/msd.cjs), so attribution is a function of (rel, runtime).
sources: (m, ctx) => {
const np = nativePluginDescriptor(ctx.runtime);
if (!np || !np.source) {
@@ -616,15 +616,15 @@ const PROVENANCE_RULES = [
id: 'cline-rules-code-derived',
kind: 'code-derived',
roots: ['.clinerules'],
pattern: /^(gsd\.md|hooks\/PreToolUse)$/,
pattern: /^(msd\.md|hooks\/PreToolUse)$/,
sources: () => [CLINE_BODY_SRC],
},
// #3547 removed `agents-md-code-derived` (roots: ['.agents'],
// ^AGENTS\.md$) and `synthesized-gsd-defaults` (^\.gsd/defaults\.json$):
// ^AGENTS\.md$) and `synthesized-msd-defaults` (^\.msd/defaults\.json$):
// both paths only appeared in a manifest while the harness collapsed
// configDir onto the sandbox HOME, walking HOME-level siblings
// (cline's ~/.agents/AGENTS.md, every non-Claude runtime's
// ~/.gsd/defaults.json). With the harness installing into each runtime's
// ~/.msd/defaults.json). With the harness installing into each runtime's
// real global subdirectory those files sit outside the walked configDir,
// the rules matched nothing, and the totality guard's dead-rule arm fired
// — exactly as designed. The files are still written, still covered by the
@@ -633,7 +633,7 @@ const PROVENANCE_RULES = [
{
id: 'hermes-category-description',
kind: 'code-derived',
roots: ['skills/gsd'],
roots: ['skills/msd'],
pattern: /^DESCRIPTION\.md$/,
sources: () => [INSTALLER_SRC],
},
@@ -645,7 +645,7 @@ const PROVENANCE_RULES = [
// (src/runtime-artifact-layout.cts:303), and the YAML additionally enumerates
// every staged subagent — so adding or removing an agents/*.md legitimately
// moves this file too. Both sources are declared.
pattern: /^gsd\.(yaml|md)$/,
pattern: /^msd\.(yaml|md)$/,
sources: () => [KIMI_ROOT_AGENT_SRC, 'agents/'],
},
@@ -658,7 +658,7 @@ const PROVENANCE_RULES = [
// `{"type":"commonjs"}` CommonJS-mode marker as the root one, written into
// each Kimi product's separate hooks root (installSharedHooksBundle; the
// per-runtime root split is #2755).
pattern: /^(\.gsd-profile|package\.json|\.kimi(-code)?\/package\.json|gsd-core\/VERSION|gsd-core\/\.gsd-runtime)$/,
pattern: /^(\.msd-profile|package\.json|\.kimi(-code)?\/package\.json|msd-core\/VERSION|msd-core\/\.msd-runtime)$/,
sources: () => [],
},
{
@@ -675,8 +675,8 @@ const PROVENANCE_RULES = [
/**
* Reject an emitted key that could escape the repo once turned into a source path.
*
* Two rules (`gsd-core-verbatim`, `scripts-verbatim`) capture a whole tail with
* `.+` rather than `[^/]+`, so a key like `gsd-core/workflows/../../../etc/passwd`
* Two rules (`msd-core-verbatim`, `scripts-verbatim`) capture a whole tail with
* `.+` rather than `[^/]+`, so a key like `msd-core/workflows/../../../etc/passwd`
* would otherwise produce a source path that `path.join(REPO_ROOT, src)` resolves
* OUTSIDE the repo. Nothing reachable today exploits it — real manifest keys come
* from installer output and the only consumer is an `fs.existsSync` probe — but