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:
@@ -26,7 +26,7 @@ Synthesis of the four platform lenses: `adr-456-test-rigor`, `coverage-mutation`
|
||||
- **Property-based testing** via fast-check with a pinned seed (`tests/helpers/fast-check-setup.cjs`, seed=42) — 9 `*.property.test.cjs` files exist and run reproducibly.
|
||||
- **Mutation testing** — Stryker is configured (`stryker.config.mjs`) and wired into a PR-gating workflow (`.github/workflows/mutation.yml`) that shards per changed module.
|
||||
- **Custom ESLint rules** — `no-source-grep`, `no-magic-sleep-in-tests`, `no-elapsed-assertion`, `no-raw-rmsync-in-tests`, plus `no-only-tests` — exist and are unit-tested via RuleTester (`tests/eslint-rules.test.cjs`).
|
||||
- **Env hermeticity** — `scripts/run-tests.cjs` deletes `GSD_PROJECT`/`GSD_WORKSTREAM` before spawning child test processes (mitigates the ambient-env hazard recorded in MEMORY.md).
|
||||
- **Env hermeticity** — `scripts/run-tests.cjs` deletes `MSD_PROJECT`/`MSD_WORKSTREAM` before spawning child test processes (mitigates the ambient-env hazard recorded in MEMORY.md).
|
||||
- **Line-coverage gate** — `c8 --lines 70` (lib) enforced in CI as part of the unit lane.
|
||||
|
||||
### (b) ENFORCED vs aspirational
|
||||
@@ -60,7 +60,7 @@ Synthesis of the four platform lenses: `adr-456-test-rigor`, `coverage-mutation`
|
||||
| `no-only-tests` coverage | Wired `error`, untested | Add RuleTester valid/invalid cases + an integration assertion it fires | **P1** |
|
||||
| `no-tautological-assert` rule | None | New ~30-line local rule flagging `assert.ok(true)`/`assert.ok(1)` in `tests/**` | **P1** |
|
||||
| Fail-on-zero-executed | Exits 0 on empty suite | Exit 1 by default; gate the empty-suite allowance behind `RUN_TESTS_ALLOW_EMPTY_SUITE=1` | **P2** |
|
||||
| Shared-`GSD_TEMP_DIR` isolation | reap tests write to global `os.tmpdir()/gsd` | Redirect via the existing `dir` option to per-test tmpdirs; lint against writing to the shared path without cleanup | **P2** |
|
||||
| Shared-`MSD_TEMP_DIR` isolation | reap tests write to global `os.tmpdir()/msd` | Redirect via the existing `dir` option to per-test tmpdirs; lint against writing to the shared path without cleanup | **P2** |
|
||||
| Build-artifact preflight in artifact-dependent tests | Top-level `require()` of gitignored `.cjs` hard-crashes on clean worktree | `before()` `existsSync` guard with a clear "run npm run build:lib" message | **P2** |
|
||||
|
||||
### ADR-456 compliance — per mandate
|
||||
@@ -93,10 +93,10 @@ ADR-456 defines four test-rigor mandates. Compliance is **partial on all four**:
|
||||
| 0011b Review Default Reviewers (PRD) | Draft | 5 | partial | partial | partial | covered | infos-path + `--all`+flags edge untested; build-artifact dependency |
|
||||
| 0011c Review Default Reviewers | Proposed | 4 | covered | partial | partial | covered | Mid-tier risks (infos, empty-selection) missing; build-artifact dependency |
|
||||
| 0012 Command Routing Hub | Superseded (0174) | 5 | covered | partial | covered | covered | Hub well-covered; `uat-passed` adapter arg-shape gap; 3 redundant tests |
|
||||
| 15 Autonomous Cross-AI Convergence | Proposed | 8 | partial | partial | partial | partial | **Primary surface (`/gsd-progress --next --auto --converge`) has zero coverage** |
|
||||
| 15 Autonomous Cross-AI Convergence | Proposed | 8 | partial | partial | partial | partial | **Primary surface (`/msd-progress --next --auto --converge`) has zero coverage** |
|
||||
| 22 Plan Drift Guard | Proposed | 6 | partial | partial | covered | covered | Severity mapping, authority auto-upgrade, rung≥3 hard-block untested |
|
||||
| 58 Runtime Install Policy | Accepted | 7 | covered | partial | partial | covered | Strong projection coverage; purity guarantee + sandboxTier-invalid untested |
|
||||
| 0174 Retire gsd-sdk Package | Accepted | 12 | covered | covered | covered | covered | Strong & behavioral; init-composer trace + tsc-output invariant gaps |
|
||||
| 0174 Retire msd-sdk Package | Accepted | 12 | covered | covered | covered | covered | Strong & behavioral; init-composer trace + tsc-output invariant gaps |
|
||||
| 218 Release Version Validation | Accepted | **0** | missing | missing | missing | na | **ZERO TESTS — entirely unprotected (regex lives only in release.yml bash)** |
|
||||
| 227 Input Validation Shape | Accepted | 5 | covered | covered | partial | partial | **All 5 test files silently excluded from npm test (subdir blind spot)** |
|
||||
| 230 Next Integration Branch | Proposed | 5 | partial | partial | partial | covered | Most critical seams untested; 2 files misattributed (unrelated features) |
|
||||
@@ -120,11 +120,11 @@ ADR-456 defines four test-rigor mandates. Compliance is **partial on all four**:
|
||||
|
||||
**ADR-218 (Release Version Validation) — ZERO attributed tests.** This is the most acute hole. Both ADR decisions — the leading-zero-rejecting format regex (`^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.0$`) and the npm duplicate-version precheck — live exclusively in a bash `run:` block in `.github/workflows/release.yml`. No test exercises either. The `1.01.0` incident that motivated the ADR caused an irrecoverable production divergence, and nothing prevents a reversion to the old broken regex. `issue-version-gate.test.cjs` is a superficially-related but wholly separate feature. **This is a critical gap in a high-blast-radius zone.**
|
||||
|
||||
**ADR-227 (Input Validation Shape) — 5 tests that never run.** All five attributed files live in `tests/observability/` and `tests/dispatch/`, which `scripts/run-tests.cjs:269` never enters (flat `readdirSync`). The tests are individually high quality (8 boundary/negative UUID-v4 cases, real file I/O, per-test isolation) but are silently excluded from `npm test`, CI, and gsd-test. ADR-227's two-layer validation guarantee — the correlation-poisoning and log-blowup classes it was written to prevent — is effectively unguarded until the runner is fixed.
|
||||
**ADR-227 (Input Validation Shape) — 5 tests that never run.** All five attributed files live in `tests/observability/` and `tests/dispatch/`, which `scripts/run-tests.cjs:269` never enters (flat `readdirSync`). The tests are individually high quality (8 boundary/negative UUID-v4 cases, real file I/O, per-test isolation) but are silently excluded from `npm test`, CI, and msd-test. ADR-227's two-layer validation guarantee — the correlation-poisoning and log-blowup classes it was written to prevent — is effectively unguarded until the runner is fixed.
|
||||
|
||||
**ADR-0006 (Planning-Path Projection) — critical handler-consumption gap.** The ADR's single most important invariant — that `cmdInitExecutePhase/PlanPhase/PhaseOp/MilestoneOp` route through `planningPaths().planning` rather than flat `path.join(cwd, '.planning')` — has no regression test. The banned `.planning/projects/<project>` form also has no guard.
|
||||
|
||||
**ADR-15 (Autonomous Cross-AI Convergence) — primary surface untested.** The ADR's designated primary operator surface, `/gsd-progress --next --auto --converge`, is both unimplemented and untested; the existing `cross-ai-execution.test.cjs` tests a *different* feature (execute-phase delegation) and is misattributed.
|
||||
**ADR-15 (Autonomous Cross-AI Convergence) — primary surface untested.** The ADR's designated primary operator surface, `/msd-progress --next --auto --converge`, is both unimplemented and untested; the existing `cross-ai-execution.test.cjs` tests a *different* feature (execute-phase delegation) and is misattributed.
|
||||
|
||||
**ADR-0011a / 0011b / 0011c (Skill Surface / Review Default Reviewers).** Source modules (`install-profiles.cjs`, `surface.cjs`, `clusters.cjs`, `review-reviewer-selection.cjs`, `config-schema.cjs`) are gitignored build artifacts absent from a clean worktree; all attributed tests throw `MODULE_NOT_FOUND` without a prior `npm run build:lib`. CI's pretest hook covers this, but isolated runs and fresh worktrees fail confusingly.
|
||||
|
||||
@@ -140,7 +140,7 @@ Only entries whose adversarial verification confirmed `finalVerdict === "retire"
|
||||
|
||||
| File | Location | Why worthless | Confirmed by verification |
|
||||
|---|---|---|---|
|
||||
| `tests/enh-2790-skill-consolidation.test.cjs` | Lines 127–157 — 4 "has a name: field" spot-checks | Assert only `fm.name.length > 0`; `command-contract.test.cjs` already enforces the stricter `/^gsd[:-]/` prefix on all 67 files. Renaming `gsd-capture`→`capture` (the exact regression) passes these but is caught by command-contract. Cannot go red for the bug class the ADR exists to prevent. | **Yes** — verified `command-contract.test.cjs:44-54` covers these 4 files more strictly; deletion creates no coverage gap. |
|
||||
| `tests/enh-2790-skill-consolidation.test.cjs` | Lines 127–157 — 4 "has a name: field" spot-checks | Assert only `fm.name.length > 0`; `command-contract.test.cjs` already enforces the stricter `/^msd[:-]/` prefix on all 67 files. Renaming `msd-capture`→`capture` (the exact regression) passes these but is caught by command-contract. Cannot go red for the bug class the ADR exists to prevent. | **Yes** — verified `command-contract.test.cjs:44-54` covers these 4 files more strictly; deletion creates no coverage gap. |
|
||||
| `tests/command-routing-hub.test.cjs` | Lines 134–137 — "constructs successfully with only cjsRegistry" | Duplicate of the construction test at 71–75; asserts only `typeof hub.dispatch === 'function'` with no dispatch. `createHub` does zero registry-dependent branching at construction. | **Yes** — verified identical assertion; populated-registry dispatch path covered by the happy-path block at line 142. |
|
||||
| `tests/command-routing-hub.test.cjs` | Lines 515–519 — "ERROR_KINDS.UnknownCommand === result.kind" | The identical assertion appears at 9 other sites (222, 234, 245, 256, 360, 393, 410, 422, 518). Same code path covered at 414–424. No unique setup/edge/field. | **Yes** — verified superset coverage by lines 384–424 + the constant-stability test at 521–526. |
|
||||
| `tests/no-cjs-sdk-handsync-tooling.test.cjs` | All 3 tests (lines 26–53) | Assert absence of `lint-shared-module-handsync.cjs` / allowlist JSON that **never existed on main** (CONTEXT.md:693 confirms). Can only go red if someone manually drops those exact files. No behavioral coverage. | **Yes** — verified the real retired artifacts (`cjs-sdk-bridge.cjs`, `sdk/`) are covered by `bug-190`; these guard ADR-text-only artifacts. |
|
||||
@@ -159,7 +159,7 @@ All `redesign` + `keep-but-improve` verdicts, **plus the 6 retire-candidates tha
|
||||
| `tests/review-reviewer-selection.test.cjs` | Lines 17–27 KNOWN_REVIEWER_SLUGS | Tests a compiled-CJS constant's shape. Verification found the slug membership DOES drive `resolveReviewerSelection`'s warn/drop logic at runtime — it's the only guard against silent slug-list drift. | Collapse to one behavioral test: `resolveReviewerSelection` with a config'd known slug yields no warning + slug in `selected`; an unknown slug yields a warning. |
|
||||
| `tests/enh-191-retire-sdk-package.test.cjs` | Lines 52–58 AGENTS.md absence | Off-topic for SDK retirement, but NOT valueless: `bin/install.js:~10963` writes a root `AGENTS.md` on local Copilot install; this is the only guard against that artifact committing. | Extract to a repo-layout governance test (e.g. `tests/repo-layout.test.cjs`); rename to state the real invariant (no ad-hoc root instruction file vs CONTEXT.md/ADRs); link the copilot install path. |
|
||||
| `tests/capability-registry.test.cjs` | Lines 558–584 drift test | Steps 2–3 are a file-I/O tautology and skip the real `--check` path (`stripGeneratedComment` + `normalizeLineEndings`). But it is the only unit-level coverage of the drift-comparison pipeline. | Call the actual comparison expression: assert a stale version survives both `stripGeneratedComment` and `normalizeLineEndings` and is detected; assert a comment-only-timestamp change is NOT flagged after stripping. |
|
||||
| `tests/verify-test-quality.test.cjs` | 3 describes (disabled / circular / assertion-strength detection) | Self-referential: define a regex inline, write a matching fixture, assert the regex matches — cannot go red for any production change. The detector lives as prose in `verify-phase` (workflow, retired in #1892). | Replace with a structural guard reading `gsd-core/workflows/verify-phase (retired in #1892)`: assert the `audit_test_quality` step tag exists and contains the skip-pattern, circular-detection, and assertion-strength-table markers. |
|
||||
| `tests/verify-test-quality.test.cjs` | 3 describes (disabled / circular / assertion-strength detection) | Self-referential: define a regex inline, write a matching fixture, assert the regex matches — cannot go red for any production change. The detector lives as prose in `verify-phase` (workflow, retired in #1892). | Replace with a structural guard reading `msd-core/workflows/verify-phase (retired in #1892)`: assert the `audit_test_quality` step tag exists and contains the skip-pattern, circular-detection, and assertion-strength-table markers. |
|
||||
|
||||
#### Other redesign / keep-but-improve (high-signal selection)
|
||||
|
||||
@@ -179,14 +179,14 @@ All `redesign` + `keep-but-improve` verdicts, **plus the 6 retire-candidates tha
|
||||
| `tests/clusters.test.cjs` | Lines 50–58 | `assert.ok(utilitySize >= skills.length || true)` — `|| true` makes it vacuous. | Remove `|| true`; assert a meaningful lower bound (`utilitySize >= 5`). |
|
||||
| `tests/model-profiles.test.cjs` | Lines 115–122 | Test titled "resolution order: override > profile > default" exercises no override and asserts nothing about override behavior. | Use a temp project with `config.model_overrides`, call `resolveModelInternal`, assert override > profile > default explicitly. |
|
||||
| `tests/active-workstream-store.unit.test.cjs` | Lines 361–364 | `assert.ok(key === null || typeof key === 'string')` — disjunction always passes; env-dependent. | Clear `TTY`/`SSH_TTY` in `beforeEach`; assert `strictEqual(key, null)`, or skip when a real TTY is present. |
|
||||
| `tests/feat-488-effort-sync.test.cjs` | Lines 177–219 | Does not redirect `GSD_HOME`; resolved effort depends on the dev's real `~/.gsd`; degrades to a type-only check. | Set `GSD_HOME=tmpHome`; assert `result.synced === 1` and `changes[0].to === 'low'`. |
|
||||
| `tests/bug-492-effort-manifest-fallback.test.cjs` | Lines 20–48 | Mutates the module-level `CANONICAL_CONFIG_DEFAULTS` singleton — independence violation; races under parallel runs. | Drive the same path via a tmpHome `~/.gsd/defaults.json` rather than mutating shared module state. |
|
||||
| `tests/feat-488-effort-sync.test.cjs` | Lines 177–219 | Does not redirect `MSD_HOME`; resolved effort depends on the dev's real `~/.msd`; degrades to a type-only check. | Set `MSD_HOME=tmpHome`; assert `result.synced === 1` and `changes[0].to === 'low'`. |
|
||||
| `tests/bug-492-effort-manifest-fallback.test.cjs` | Lines 20–48 | Mutates the module-level `CANONICAL_CONFIG_DEFAULTS` singleton — independence violation; races under parallel runs. | Drive the same path via a tmpHome `~/.msd/defaults.json` rather than mutating shared module state. |
|
||||
| `tests/issue-766-plugin-manifest.test.cjs` | Section C, "claude plugin validate --strict" | Permanently skipped when the `claude` binary is absent (i.e. on CI) — the only full-schema gate never runs. | Install the claude CLI in a CI step, OR validate `plugin.json` against a snapshotted JSON schema unconditionally. |
|
||||
| `tests/cross-ai-execution.test.cjs` | Entire file | Misattributed to ADR-15; tests a different feature (`workflow.cross_ai_execution`). Also a shared-mutable `let content` independence issue. | Leave the file for its real feature; create `tests/adr-15-plan-strategy-seam.test.cjs` for the actual converge seam; hoist `content` to a single module-level read. |
|
||||
| `tests/issue-844-manifest-version-sync.test.cjs` | Describe A (33–127) | Order-dependent shared `tmpRoot` across setup/assert/cleanup tests. | Refactor to a single test with per-test `before()/after()` tmpRoot allocation. |
|
||||
| `tests/plan-review-convergence.test.cjs` | Lines 688–692 | Four `workflow.includes(verdict)` whole-file substring checks — pass even if verdicts move to dead/comment text. | Extract the source-grounding section slice; assert each verdict + its severity mapping (AMBIGUOUS→MEDIUM, UNCHECKABLE→INFO) inside that slice. |
|
||||
| `tests/feat-3594-parser-property-style.test.cjs` | Lines 119–135 | `assert.ok(elapsedMs < 2000)` wall-clock; escapes `no-elapsed-assertion` via the variable name. | Replace with a call-count metric (instrument char comparisons, assert O(n)); or raise bound to 10000ms as a stopgap. |
|
||||
| `tests/core.test.cjs` | Lines 1834–1879 (`reapStaleTempFiles`) | Writes to the global shared `os.tmpdir()/gsd`; races with `temp-subdir.test.cjs` under concurrency. | Use a per-test isolated tmpdir via the existing `{ dir }` option; clean up in `afterEach`. |
|
||||
| `tests/core.test.cjs` | Lines 1834–1879 (`reapStaleTempFiles`) | Writes to the global shared `os.tmpdir()/msd`; races with `temp-subdir.test.cjs` under concurrency. | Use a per-test isolated tmpdir via the existing `{ dir }` option; clean up in `afterEach`. |
|
||||
|
||||
---
|
||||
|
||||
@@ -199,7 +199,7 @@ All `redesign` + `keep-but-improve` verdicts, **plus the 6 retire-candidates tha
|
||||
3. **Add tests for ADR-218** (zero coverage today): extract the release-version regex and npm-duplicate precheck into a testable `.cjs` helper (or a `source-text-is-the-product` workflow assertion on `release.yml`), and assert `1.01.0`/`01.0.0` are rejected, valid versions pass, and the duplicate-version step exists and is wired before the publish jobs.
|
||||
4. **Retire the 5 verified-worthless tests** (see Retire table): `enh-2790` name spot-checks (127–157), `command-routing-hub` lines 134–137 and 515–519, `no-cjs-sdk-handsync-tooling` (all 3), `runtime-artifact-layout` cline edge-case (319–323).
|
||||
5. **Redesign the 6 downgraded retire-candidates** (do NOT delete): `bug-3135` (delete only the broad block, keep content tests), both `review-reviewer-selection` tests, `enh-191` AGENTS.md (extract to governance test), `capability-registry` drift test, `verify-test-quality` (replace with structural workflow guard).
|
||||
6. **Close the ADR-0006 critical gap**: add a regression test that `init execute-phase/plan-phase/phase-op/milestone-op` return workstream-scoped paths under `GSD_WORKSTREAM`, plus a guard against the banned `.planning/projects/<project>` form.
|
||||
6. **Close the ADR-0006 critical gap**: add a regression test that `init execute-phase/plan-phase/phase-op/milestone-op` return workstream-scoped paths under `MSD_WORKSTREAM`, plus a guard against the banned `.planning/projects/<project>` form.
|
||||
|
||||
### P1 — high priority (rigor enforcement + concentrated weakness)
|
||||
|
||||
@@ -210,12 +210,12 @@ All `redesign` + `keep-but-improve` verdicts, **plus the 6 retire-candidates tha
|
||||
11. **Add `no-only-tests` RuleTester coverage** and extend `no-elapsed-assertion` to catch `Date.now()-start` and computed-variable (`elapsedMs`) patterns.
|
||||
12. **Add a branch-coverage floor** (`--branches 60`) and a per-file branch floor for the UNMUTATED critical modules.
|
||||
13. **De-flake the clock-coupled tests**: `phase.test.cjs:4362` (60s window → ISO-date assertion), `bug-3707` (pin epoch), `context-utilization.property.test.cjs:187` (`fc.integer` not `Math.random`).
|
||||
14. **Add the ADR-15 primary-surface tests** (`/gsd-progress --next --auto --converge`) and re-attribute `cross-ai-execution.test.cjs` to its real feature.
|
||||
14. **Add the ADR-15 primary-surface tests** (`/msd-progress --next --auto --converge`) and re-attribute `cross-ai-execution.test.cjs` to its real feature.
|
||||
|
||||
### P2 — follow-up (robustness & hygiene)
|
||||
|
||||
15. **Fail-on-zero-executed** in `run-tests.cjs` (exit 1 on empty suite by default; gate the allowance behind an env flag).
|
||||
16. **Isolate the shared `GSD_TEMP_DIR` reap tests** (`core.test.cjs:1834-1879`, `temp-subdir.test.cjs`) via the existing `{ dir }` option + `afterEach` cleanup.
|
||||
16. **Isolate the shared `MSD_TEMP_DIR` reap tests** (`core.test.cjs:1834-1879`, `temp-subdir.test.cjs`) via the existing `{ dir }` option + `afterEach` cleanup.
|
||||
17. **Add build-artifact `before()` guards** to artifact-dependent suites (ADR-3524 subjects, ADR-0011 family) so a clean worktree fails with a clear "run npm run build:lib" message instead of a top-level crash.
|
||||
18. **Strengthen the strong-but-incomplete ADRs**: ADR-443 end-to-end effort propagation, ADR-0656 slopcheck "cannot-lower" + scrape-dispatch, ADR-0009's 3 absent ADR-listed test files, ADR-766 `agents`-absence assertion + post-#770 hook drift.
|
||||
19. **Add `.gitignore` ↔ `eslint.config.mjs` ignore-list parity test** (ADR-457) so a migration that updates one list but not the other is caught.
|
||||
|
||||
Reference in New Issue
Block a user