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:
@@ -52,7 +52,7 @@ const {
|
||||
|
||||
const SUITES = ['all', 'unit', 'integration', 'install', 'security', 'slow', 'qa'];
|
||||
|
||||
// ADR-457 build-at-publish: gsd-core/bin/lib/*.cjs is generated from
|
||||
// ADR-457 build-at-publish: msd-core/bin/lib/*.cjs is generated from
|
||||
// src/*.cts and gitignored, so on a clean checkout (fresh CI, before any build)
|
||||
// the artifact is absent — yet test files require it. This is the universal
|
||||
// chokepoint every test path funnels through (test:unit, --files-from, direct
|
||||
@@ -60,19 +60,19 @@ const SUITES = ['all', 'unit', 'integration', 'install', 'security', 'slow', 'qa
|
||||
//
|
||||
// Strategy (incremental + re-emit-on-missing, closes both #969 failure modes):
|
||||
// 1. Run tsc incrementally (fast ~380ms no-op when sources unchanged).
|
||||
// 2. Verify every src/*.cts (non-.d.cts) maps to a non-empty gsd-core/bin/lib/*.cjs.
|
||||
// 2. Verify every src/*.cts (non-.d.cts) maps to a non-empty msd-core/bin/lib/*.cjs.
|
||||
// 3. If any expected .cjs is missing or zero-bytes (persistent-mirror scenario:
|
||||
// tsc no-ops because tsbuildinfo looks current even though the file was deleted),
|
||||
// delete the tsbuildinfo and run tsc ONCE MORE (clean re-emit), then re-verify.
|
||||
//
|
||||
// Common case: fast incremental no-op. Stale/deleted-output case: detected by
|
||||
// the cheap existsSync loop and force-rebuilt. Paths resolve from __dirname so
|
||||
// it works regardless of GSD_TEST_DIR / temp-dir cwd.
|
||||
// it works regardless of MSD_TEST_DIR / temp-dir cwd.
|
||||
function ensureBuiltArtifacts(overrides = {}) {
|
||||
const { existsSync, readdirSync, statSync, unlinkSync } = require('fs');
|
||||
const root = overrides.root || join(__dirname, '..');
|
||||
const srcDir = overrides.srcDir || join(root, 'src');
|
||||
const outDir = overrides.outDir || join(root, 'gsd-core', 'bin', 'lib');
|
||||
const outDir = overrides.outDir || join(root, 'msd-core', 'bin', 'lib');
|
||||
const tsBuildInfoPath = overrides.tsBuildInfoPath || join(root, 'tsconfig.build.tsbuildinfo');
|
||||
const tsconfigPath = overrides.tsconfigPath || join(root, 'tsconfig.build.json');
|
||||
const tscBin = require.resolve('typescript/bin/tsc');
|
||||
@@ -80,7 +80,7 @@ function ensureBuiltArtifacts(overrides = {}) {
|
||||
|
||||
// Build the 1:1 map of expected output paths from src/*.cts sources.
|
||||
// Excludes *.d.cts (declaration-only files that produce no output).
|
||||
// Handles subdirectories (e.g. src/installer-migrations/*.cts → gsd-core/bin/lib/installer-migrations/*.cjs).
|
||||
// Handles subdirectories (e.g. src/installer-migrations/*.cts → msd-core/bin/lib/installer-migrations/*.cjs).
|
||||
function gatherExpectedOutputs() {
|
||||
const expected = [];
|
||||
function scan(dir, relBase) {
|
||||
@@ -102,11 +102,11 @@ function ensureBuiltArtifacts(overrides = {}) {
|
||||
return expectedPaths.filter(p => !existsSync(p) || statSync(p).size === 0);
|
||||
}
|
||||
|
||||
// #996 placed the tsbuildinfo inside gsd-core/bin/ (a copied/shipped tree), which
|
||||
// #996 placed the tsbuildinfo inside msd-core/bin/ (a copied/shipped tree), which
|
||||
// raced install-test copies. It now lives at the repo root. Best-effort purge any
|
||||
// stale bin-local copy so persistent workspaces/mirrors self-heal (no-op on a temp
|
||||
// override root or a clean checkout).
|
||||
const legacyTsBuildInfo = join(root, 'gsd-core', 'bin', 'tsconfig.build.tsbuildinfo');
|
||||
const legacyTsBuildInfo = join(root, 'msd-core', 'bin', 'tsconfig.build.tsbuildinfo');
|
||||
try { if (existsSync(legacyTsBuildInfo)) unlinkSync(legacyTsBuildInfo); } catch { /* best-effort */ }
|
||||
|
||||
// Step 1: incremental build (fast no-op when sources unchanged).
|
||||
@@ -380,17 +380,17 @@ function defaultMaxUnmeasuredPerChunk(platform) {
|
||||
// place and every future fixture reintroduces the hazard, while a run-private
|
||||
// root + between-chunk sweep caps peak usage for every fixture at once.
|
||||
|
||||
const RUN_TEMP_ROOT_PREFIX = 'gsd-test-run-';
|
||||
const RUN_TEMP_ROOT_PREFIX = 'msd-test-run-';
|
||||
// Children the runner itself keeps alive across chunks — the sweep must spare
|
||||
// them (GSD_HOME's nested-spawn REUSE contract; the chunk-diagnostics events dir).
|
||||
const RESERVED_TEMP_PREFIXES = ['gsd-test-home-', 'gsd-run-tests-events-'];
|
||||
// them (MSD_HOME's nested-spawn REUSE contract; the chunk-diagnostics events dir).
|
||||
const RESERVED_TEMP_PREFIXES = ['msd-test-home-', 'msd-run-tests-events-'];
|
||||
|
||||
/**
|
||||
* Create (or reuse) this run's private temp root and repoint the env at it.
|
||||
*
|
||||
* TMPDIR/TEMP/TMP all move, so every `mkdtempSync(os.tmpdir())` in a spawned
|
||||
* test child lands inside the root — that is what makes a sweep scoped and
|
||||
* safe. IDEMPOTENT exactly like the GSD_HOME sandbox below: a nested run-tests
|
||||
* safe. IDEMPOTENT exactly like the MSD_HOME sandbox below: a nested run-tests
|
||||
* spawn (tests/run-tests-harness.test.cjs) inherits the root via env and must
|
||||
* REUSE it, never mkdtemp a fresh root per invocation. An operator's TMPDIR
|
||||
* redirect (the tmpfs workaround) keeps working: the root is created INSIDE the
|
||||
@@ -489,7 +489,7 @@ function assertTempRootBounded(root, limit) {
|
||||
}
|
||||
|
||||
// Per-file measured durations, regenerated by scripts/gen-test-timings.cjs from
|
||||
// gsd-test reporter event streams. Overridable so tests can inject a synthetic
|
||||
// msd-test reporter event streams. Overridable so tests can inject a synthetic
|
||||
// table instead of depending on the real suite's cost profile.
|
||||
const DEFAULT_TIMINGS_PATH = join(__dirname, '..', 'tests', 'test-timings.json');
|
||||
// Must track SCHEMA_VERSION in scripts/gen-test-timings.cjs.
|
||||
@@ -1079,7 +1079,7 @@ function analyzeChunkEvents(eventsPath) {
|
||||
try {
|
||||
raw = readFileSync(eventsPath, 'utf8');
|
||||
} catch {
|
||||
// The events file never existed — either GSD_RUN_TESTS_EVENTS_FILE never
|
||||
// The events file never existed — either MSD_RUN_TESTS_EVENTS_FILE never
|
||||
// resolved to a writable path, or the reporter module never loaded in the
|
||||
// child at all (the `reporter:init` marker below is the reporter's very
|
||||
// FIRST action, before any test can run, so its absence pins the failure
|
||||
@@ -1204,8 +1204,8 @@ function main() {
|
||||
throw new ExitError(2);
|
||||
}
|
||||
|
||||
const testDir = process.env.GSD_TEST_DIR
|
||||
? process.env.GSD_TEST_DIR
|
||||
const testDir = process.env.MSD_TEST_DIR
|
||||
? process.env.MSD_TEST_DIR
|
||||
: join(__dirname, '..', 'tests');
|
||||
|
||||
const allFiles = walkTestFiles(testDir, '').sort();
|
||||
@@ -1332,9 +1332,9 @@ function main() {
|
||||
return 0;
|
||||
}
|
||||
// Empty suite/default run: this means discovery or the suite filter is broken.
|
||||
// Allow GSD_ALLOW_EMPTY_SUITE=1 as an escape hatch (downgrades to a warning).
|
||||
if (process.env.GSD_ALLOW_EMPTY_SUITE === '1') {
|
||||
console.error(`run-tests: WARNING: 0 test files selected for suite "${suite || 'all'}" — discovery or suite filter may be broken (GSD_ALLOW_EMPTY_SUITE=1 suppressed the error)`);
|
||||
// Allow MSD_ALLOW_EMPTY_SUITE=1 as an escape hatch (downgrades to a warning).
|
||||
if (process.env.MSD_ALLOW_EMPTY_SUITE === '1') {
|
||||
console.error(`run-tests: WARNING: 0 test files selected for suite "${suite || 'all'}" — discovery or suite filter may be broken (MSD_ALLOW_EMPTY_SUITE=1 suppressed the error)`);
|
||||
return 0;
|
||||
}
|
||||
console.error(`run-tests: ERROR: 0 test files selected for suite "${suite || 'all'}" — discovery or suite filter is broken`);
|
||||
@@ -1350,16 +1350,16 @@ function main() {
|
||||
ensureBuiltHooks();
|
||||
|
||||
// Hermeticity: in-process tests resolve `.planning` via planningDir(cwd), which
|
||||
// honours GSD_PROJECT/GSD_WORKSTREAM. A developer shell inside a GSD workstream
|
||||
// exports GSD_WORKSTREAM, which would redirect fixture STATE.md reads away from
|
||||
// honours MSD_PROJECT/MSD_WORKSTREAM. A developer shell inside a MSD workstream
|
||||
// exports MSD_WORKSTREAM, which would redirect fixture STATE.md reads away from
|
||||
// each <tmp>/.planning and silently diverge from the clean CI/Docker env. Strip
|
||||
// them so the local runner matches CI; tests that need them set them explicitly.
|
||||
delete process.env.GSD_PROJECT;
|
||||
delete process.env.GSD_WORKSTREAM;
|
||||
delete process.env.MSD_PROJECT;
|
||||
delete process.env.MSD_WORKSTREAM;
|
||||
delete process.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS;
|
||||
|
||||
// #4020: bound the run's temp footprint BEFORE any sandbox below mkdtemps, so
|
||||
// every child allocation (fixtures, GSD_HOME, events) lands inside one root
|
||||
// every child allocation (fixtures, MSD_HOME, events) lands inside one root
|
||||
// that is swept between chunks and removed on exit. Announced on stderr so an
|
||||
// operator (and tests/run-tests-temp-root.test.cjs) can observe it.
|
||||
const runTempRoot = setupRunTempRoot();
|
||||
@@ -1383,7 +1383,7 @@ function main() {
|
||||
// every ancestor of every selected file that lies INSIDE the run root.
|
||||
const sweepProtectSet = computeSweepProtectSet(selected, runTempRoot);
|
||||
|
||||
// Sandbox the overlay home so the loader's global scan ($GSD_HOME/.gsd/capabilities)
|
||||
// Sandbox the overlay home so the loader's global scan ($MSD_HOME/.msd/capabilities)
|
||||
// cannot read a developer's real installed capabilities during tests (ADR-1244 D2).
|
||||
// IDEMPOTENT: a nested run-tests spawn (e.g. tests/run-tests-harness.test.cjs)
|
||||
// inherits this sandbox via env — it must REUSE it, never mkdtemp a fresh dir per
|
||||
@@ -1392,9 +1392,9 @@ function main() {
|
||||
const { mkdtempSync } = require('fs');
|
||||
const { join: _join, basename: _basename } = require('path');
|
||||
const { tmpdir } = require('os');
|
||||
const _gh = process.env.GSD_HOME;
|
||||
if (!_gh || !_basename(_gh).startsWith('gsd-test-home-')) {
|
||||
process.env.GSD_HOME = mkdtempSync(_join(tmpdir(), 'gsd-test-home-'));
|
||||
const _gh = process.env.MSD_HOME;
|
||||
if (!_gh || !_basename(_gh).startsWith('msd-test-home-')) {
|
||||
process.env.MSD_HOME = mkdtempSync(_join(tmpdir(), 'msd-test-home-'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1604,7 +1604,7 @@ function main() {
|
||||
// human one so a chunk timeout can name the file that was in flight (see
|
||||
// scripts/lib/ndjson-reporter.cjs for the full contract writeup, its
|
||||
// Node-docs citation, and — load-bearing — why it writes via
|
||||
// `fs.appendFileSync` to a path passed through GSD_RUN_TESTS_EVENTS_FILE
|
||||
// `fs.appendFileSync` to a path passed through MSD_RUN_TESTS_EVENTS_FILE
|
||||
// instead of yielding strings for Node to pipe through
|
||||
// `--test-reporter-destination`: that destination is backed by an
|
||||
// `fs.WriteStream`, which BUFFERS, and execFileSync's timeout SIGKILLs the
|
||||
@@ -1631,7 +1631,7 @@ function main() {
|
||||
// each chunk gets its own events file inside it so a diagnostic read never
|
||||
// races with, or is polluted by, another chunk's events. Deleted on the
|
||||
// success path; kept only long enough to read back on a timeout.
|
||||
const eventsDir = mkdtempSync(join(tmpdir(), 'gsd-run-tests-events-'));
|
||||
const eventsDir = mkdtempSync(join(tmpdir(), 'msd-run-tests-events-'));
|
||||
// #3889: Node documents `--test-reporter`'s value as "a string similar to
|
||||
// those used in import() statements" (https://nodejs.org/api/test.html#--test-reporter),
|
||||
// NOT a bare filesystem path — a bare absolute path is not a portable
|
||||
@@ -1652,12 +1652,12 @@ function main() {
|
||||
// close to that ceiling.
|
||||
const eventsPathFor = (i) => join(eventsDir, `chunk-${String(i).padStart(3, '0')}.ndjson`);
|
||||
// Fixed argv for every chunk: the events path moved to the environment
|
||||
// (GSD_RUN_TESTS_EVENTS_FILE, set per-chunk below in execFileSync's `env`),
|
||||
// (MSD_RUN_TESTS_EVENTS_FILE, set per-chunk below in execFileSync's `env`),
|
||||
// which does NOT count toward the Windows 32,767-char argv ceiling — only
|
||||
// this fixed sink destination does.
|
||||
//
|
||||
// The ndjson reporter yields nothing and ignores its own destination — the
|
||||
// durable write path is GSD_RUN_TESTS_EVENTS_FILE above — but Node still
|
||||
// durable write path is MSD_RUN_TESTS_EVENTS_FILE above — but Node still
|
||||
// opens this destination as a real fs.WriteStream and fsyncs it on close,
|
||||
// so it MUST be a regular file. os.devNull (a character device on every
|
||||
// platform) fails that fsync with EINVAL, crashing every chunk, not just
|
||||
@@ -1724,18 +1724,18 @@ function main() {
|
||||
// different evidence.
|
||||
const chunkTimeoutMs = positiveNumberEnv(process.env.RUN_TESTS_CHUNK_TIMEOUT_MS, 600000);
|
||||
|
||||
// #2665: snapshot GSD's install footprint in every LIVE runtime config dir
|
||||
// #2665: snapshot MSD's install footprint in every LIVE runtime config dir
|
||||
// before a single test runs. The suite must not write there; the check after
|
||||
// the chunk loop is what makes a violation loud instead of silent. See
|
||||
// scripts/live-config-guard.cjs for why the scope is narrow (it is deliberately
|
||||
// NOT under scripts/lib/, which the installer copies to users wholesale).
|
||||
const liveConfigGuardEnabled = process.env.GSD_SKIP_LIVE_CONFIG_GUARD !== '1';
|
||||
const liveConfigGuardEnabled = process.env.MSD_SKIP_LIVE_CONFIG_GUARD !== '1';
|
||||
let liveConfigRoots = [];
|
||||
let liveConfigExtras = [];
|
||||
let liveConfigBefore = null;
|
||||
if (liveConfigGuardEnabled) {
|
||||
liveConfigRoots = resolveLiveConfigRoots();
|
||||
// #2665 round 3: $GSD_HOME/.gsd, and one native config.toml per non-registry
|
||||
// #2665 round 3: $MSD_HOME/.msd, and one native config.toml per non-registry
|
||||
// config-home descriptor (Kimi CLI's and, since #2755, Kimi Code's), are live
|
||||
// write surfaces that are not runtime config ROOTS, so they are invisible to the
|
||||
// line above. Watched independently — and note the OR: the extras alone are
|
||||
@@ -1766,7 +1766,7 @@ function main() {
|
||||
],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
env: { ...process.env, GSD_RUN_TESTS_EVENTS_FILE: chunkEventsPath },
|
||||
env: { ...process.env, MSD_RUN_TESTS_EVENTS_FILE: chunkEventsPath },
|
||||
timeout: chunkTimeoutMs,
|
||||
},
|
||||
);
|
||||
@@ -1930,7 +1930,7 @@ function main() {
|
||||
console.error(formatViolations(violations));
|
||||
// Reports by default; fails only under opt-in strict mode. See the
|
||||
// SEVERITY note in scripts/live-config-guard.cjs for why.
|
||||
if (process.env.GSD_STRICT_LIVE_CONFIG_GUARD === '1' && firstFailureExit === 0) {
|
||||
if (process.env.MSD_STRICT_LIVE_CONFIG_GUARD === '1' && firstFailureExit === 0) {
|
||||
firstFailureExit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user