* feat(#1754): CLI version-skew detection — warn when a global install shadows project-local GSD Addresses #1754 (approved-enhancement). Detects when the running gsd-tools.cjs is outside the project root while a project-local install exists — the shadowing scenario from #1748 where a stale global canary CLI (retired @gsd-build/sdk) silently overrides project-local GSD. Implementation (Node CLI entry-point, not shell snippet — avoids bloating 93 workflow files past their size caps): - src/cli-skew-check.cts: pure function checkCliSkew({resolvedPath, projectRoot, projectLocalExists}) → string|null. Compares paths via path.relative; returns a warning when the resolved CLI is outside the project root AND a project-local install exists. Includes @gsd-build/sdk removal hint when the path matches. No I/O (pure), no gsd-sdk literal (avoids bug-2801 lint). - gsd-core/bin/gsd-tools.cjs: wired at startup via the existing findProjectRoot resolver. Non-blocking (try/catch; advisory stderr warning, never gates). - eslint.config.mjs: registers the new ADR-457 generated artifact in the ignores. - tests: 6-case suite (skew/no-skew/legacy/normalization); all green. - Golden fixtures regenerated (UPDATE_GOLDEN=1) for the new compiled artifact. - docs/how-to/update-gsd.md: Diátaxis reference note for the skew warning. Full suite: 3354 pass, 0 regressions (1 pre-existing local AGENTS.md failure). lint:ci green. Closes #1754 * chore(#1754): backfill changeset pr placeholder * chore(#1754): regenerate INVENTORY-MANIFEST for the new cli-skew-check source module --------- Co-authored-by: review-bot <review-bot@gsd>
48 lines
1.9 KiB
TypeScript
48 lines
1.9 KiB
TypeScript
'use strict';
|
|
|
|
/**
|
|
* cli-skew-check.cts — CLI version-skew detection (#1754).
|
|
*
|
|
* Pure function: compares the resolved gsd-tools.cjs path to the project root.
|
|
* If the resolved CLI is OUTSIDE the project root while a project-local install
|
|
* EXISTS, returns a warning string (the caller writes it to stderr). Non-blocking.
|
|
*
|
|
* Catches the shadowing scenario from #1748: a stale global canary CLI (e.g.
|
|
* from the retired @gsd-build/sdk) shadowing the project-local GSD install.
|
|
*
|
|
* The function is PURE (no I/O) — the caller provides the resolved path, the
|
|
* project root, and whether a project-local install exists. This makes it
|
|
* trivially testable without filesystem setup.
|
|
*/
|
|
|
|
import path from 'node:path';
|
|
|
|
/**
|
|
* Check for CLI version skew.
|
|
*
|
|
* @param opts.resolvedPath - The absolute path of the running gsd-tools.cjs (__filename).
|
|
* @param opts.projectRoot - The project root (from findProjectRoot), or null if no project.
|
|
* @param opts.projectLocalExists - Whether a project-local gsd-tools.cjs exists.
|
|
* @returns A warning string if skew is detected, or null if no skew.
|
|
*/
|
|
export function checkCliSkew(opts: {
|
|
resolvedPath: string;
|
|
projectRoot: string | null;
|
|
projectLocalExists: boolean;
|
|
}): string | null {
|
|
const { resolvedPath, projectRoot, projectLocalExists } = opts;
|
|
|
|
// No project context or no project-local install → no skew possible.
|
|
if (!projectRoot || !projectLocalExists) return null;
|
|
|
|
// If the resolved CLI is under the project root, it IS a project-local install.
|
|
const rel = path.relative(projectRoot, resolvedPath);
|
|
if (!rel.startsWith('..')) return null;
|
|
|
|
// Resolved CLI is outside project root while a project-local install exists → SKEW.
|
|
const hint = resolvedPath.includes('@gsd-build')
|
|
? ' If @gsd-build/sdk: npm uninstall -g @gsd-build/sdk'
|
|
: '';
|
|
return `⚠ GSD: ${resolvedPath} may shadow project-local GSD.${hint}`;
|
|
}
|