feat(#1754): CLI version-skew detection — warn when a global install shadows project-local GSD (#1755)
* 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>
This commit is contained in:
47
src/cli-skew-check.cts
Normal file
47
src/cli-skew-check.cts
Normal file
@@ -0,0 +1,47 @@
|
||||
'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}`;
|
||||
}
|
||||
Reference in New Issue
Block a user