From 54420bae9ea4a7e061a2d269546f10e402e98473 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Mon, 15 Jun 2026 15:46:41 -0400 Subject: [PATCH] =?UTF-8?q?refactor(#1277):=20T1=20=E2=80=94=20decouple=20?= =?UTF-8?q?agent-install-check=20+=20git-base-branch=20from=20the=20core?= =?UTF-8?q?=20spine=20(#1280)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First leaf-migration tranche of epic #1267 (after T0 #1268). Migrate the via-core callers of the two leaves T0 created to import from the leaf modules directly, and stop core re-exporting their symbols: - checkAgentsInstalled: docs.cts, verify.cts, init.cts -> agent-install-check.cjs - gitWorktreeInfoInternal: init.cts -> git-base-branch.cjs - getAgentsDir had no external via-core caller (internal to the leaf) core no longer re-exports getAgentsDir / checkAgentsInstalled / gitWorktreeInfoInternal; the now-unused agent-install-check + git-base-branch requires are dropped from core; the shim-identity assertions for these are deleted (behaviour tests retained). Convergence lint stays green (0 new). No behaviour change. Closes #1277 Co-authored-by: Claude Opus 4.8 --- src/core.cts | 10 +------- src/docs.cts | 5 +++- src/init.cts | 8 +++++-- src/verify.cts | 4 +++- tests/agent-install-check.test.cjs | 38 ++++-------------------------- tests/git-base-branch.test.cjs | 11 +-------- 6 files changed, 20 insertions(+), 56 deletions(-) diff --git a/src/core.cts b/src/core.cts index 9b0589105..adb7382e7 100644 --- a/src/core.cts +++ b/src/core.cts @@ -51,10 +51,6 @@ const { import phaseLocatorModule = require('./phase-locator.cjs'); const { searchPhaseInDir, findPhaseInternal, getArchivedPhaseDirs } = phaseLocatorModule; import { findProjectRoot } from './project-root.cjs'; -// eslint-disable-next-line @typescript-eslint/no-require-imports -import agentInstallCheck = require('./agent-install-check.cjs'); -// eslint-disable-next-line @typescript-eslint/no-require-imports -import gitBaseBranch = require('./git-base-branch.cjs'); // ─── Config Loader Module (extracted from core, ADR-857 phase 2e / #885) ───── // eslint-disable-next-line @typescript-eslint/no-require-imports @@ -123,8 +119,7 @@ const { // ─── Agent installation validation (#1371) ─────────────────────────────────── // getAgentsDir and checkAgentsInstalled moved to agent-install-check.cjs (T0 #1268). -// The destructured bindings above (from agentInstallCheck) make them available to -// core-internal callers; core.cjs re-exports both symbols by reference for back-compat. +// Re-exports removed in T1 (#1277); callers import directly from agent-install-check.cjs. // ─── Model alias resolution ─────────────────────────────────────────────────── // RUNTIME_OVERRIDE_TIERS, _warnedConfigKeys, _warnUnknownProfileOverrides, and @@ -192,7 +187,6 @@ export = { resolveModelPolicy, KNOWN_PROVIDERS, pathExistsInternal, - gitWorktreeInfoInternal: gitBaseBranch.gitWorktreeInfoInternal, generateSlugInternal, getMilestoneInfo, getMilestonePhaseFilter, @@ -219,8 +213,6 @@ export = { filterSummaryFiles, getPhaseFileStats, readSubdirectories, - getAgentsDir: agentInstallCheck.getAgentsDir, - checkAgentsInstalled: agentInstallCheck.checkAgentsInstalled, timeAgo, pruneOrphanedWorktrees: worktreeSafety.pruneOrphanedWorktrees, inspectWorktreeHealth, diff --git a/src/docs.cts b/src/docs.cts index a181aabff..196e5093e 100644 --- a/src/docs.cts +++ b/src/docs.cts @@ -14,7 +14,10 @@ import fs from 'node:fs'; import path from 'node:path'; // eslint-disable-next-line @typescript-eslint/no-require-imports import core = require('./core.cjs'); -const { output, loadConfig, resolveModelInternal, pathExistsInternal, toPosixPath, checkAgentsInstalled } = core; +const { output, loadConfig, resolveModelInternal, pathExistsInternal, toPosixPath } = core; +// eslint-disable-next-line @typescript-eslint/no-require-imports +import agentInstallCheck = require('./agent-install-check.cjs'); +const { checkAgentsInstalled } = agentInstallCheck; import { platformReadSync } from './shell-command-projection.cjs'; // ─── Constants ──────────────────────────────────────────────────────────────── diff --git a/src/init.cts b/src/init.cts index 286921dca..e70a07e46 100644 --- a/src/init.cts +++ b/src/init.cts @@ -25,6 +25,12 @@ import { validatePath, loadTrustedGlobalRoots } from './security.cjs'; import { getGlobalSkillDir, getGlobalSkillDisplayPath, getGlobalSkillsBase } from './runtime-homes.cjs'; // eslint-disable-next-line @typescript-eslint/no-require-imports -- frontmatter.cjs is an export= CommonJS module import frontmatterMod = require('./frontmatter.cjs'); +// eslint-disable-next-line @typescript-eslint/no-require-imports -- agent-install-check.cjs is an export= CommonJS module +import agentInstallCheck = require('./agent-install-check.cjs'); +const { checkAgentsInstalled } = agentInstallCheck; +// eslint-disable-next-line @typescript-eslint/no-require-imports -- git-base-branch.cjs is an export= CommonJS module +import gitBaseBranch = require('./git-base-branch.cjs'); +const { gitWorktreeInfoInternal } = gitBaseBranch; const { loadConfig, @@ -34,7 +40,6 @@ const { findPhaseInternal, getRoadmapPhaseInternal, pathExistsInternal, - gitWorktreeInfoInternal, generateSlugInternal, getMilestoneInfo, getMilestonePhaseFilter, @@ -44,7 +49,6 @@ const { toPosixPath, output, error, - checkAgentsInstalled, phaseTokenMatches, } = core; diff --git a/src/verify.cts b/src/verify.cts index 9ec1a7aa2..225d22e84 100644 --- a/src/verify.cts +++ b/src/verify.cts @@ -28,6 +28,9 @@ import { PACKAGE_NAME } from './package-identity.cjs'; import { formatGsdSlash, resolveRuntime } from './runtime-slash.cjs'; import { detectSchemaFiles, checkSchemaDrift } from './schema-detect.cjs'; import { isCanonicalPlanningFile } from './artifacts.cjs'; +// eslint-disable-next-line @typescript-eslint/no-require-imports -- agent-install-check.cjs is an export= CommonJS module +import agentInstallCheck = require('./agent-install-check.cjs'); +const { checkAgentsInstalled } = agentInstallCheck; const { loadConfig, @@ -40,7 +43,6 @@ const { extractCurrentMilestone, output, error, - checkAgentsInstalled, CONFIG_DEFAULTS, inspectWorktreeHealth, } = core; diff --git a/tests/agent-install-check.test.cjs b/tests/agent-install-check.test.cjs index 69ea849ec..8cafa7cef 100644 --- a/tests/agent-install-check.test.cjs +++ b/tests/agent-install-check.test.cjs @@ -1,15 +1,14 @@ 'use strict'; /** - * Agent Install Check Module — relocation tests (#1268 T0) + * Agent Install Check Module — behaviour tests (#1268 T0, T1 #1277) * * Seam: gsd-core/bin/lib/agent-install-check.cjs * Interface: getAgentsDir, checkAgentsInstalled * * Verifies: - * 1. Object identity — core re-exports by reference (not re-wrapped) - * 2. getAgentsDir behaviour: GSD_AGENTS_DIR override, claude path, non-claude path - * 3. checkAgentsInstalled behaviour against temp dirs via GSD_AGENTS_DIR: + * 1. getAgentsDir behaviour: GSD_AGENTS_DIR override, claude path, non-claude path + * 2. checkAgentsInstalled behaviour against temp dirs via GSD_AGENTS_DIR: * - missing dir → agents_installed:false, missing_agents = all expected * - existing-but-empty dir → installed_agents:[], agents_installed:false * - no manifest → completeness skipped (incomplete_agents empty) @@ -26,15 +25,11 @@ const { createTempDir, cleanup } = require('./helpers.cjs'); const AGENT_INSTALL_CHECK_PATH = path.join( __dirname, '..', 'gsd-core', 'bin', 'lib', 'agent-install-check.cjs' ); -const CORE_PATH = path.join( - __dirname, '..', 'gsd-core', 'bin', 'lib', 'core.cjs' -); const RUNTIME_HOMES_PATH = path.join( __dirname, '..', 'gsd-core', 'bin', 'lib', 'runtime-homes.cjs' ); const agentInstallCheck = require(AGENT_INSTALL_CHECK_PATH); -const core = require(CORE_PATH); const { getGlobalConfigDir } = require(RUNTIME_HOMES_PATH); // Get EXPECTED_AGENTS from model-profiles (same source of truth) @@ -66,27 +61,7 @@ afterEach(() => { } }); -// ─── 1. Object identity ─────────────────────────────────────────────────────── - -describe('agent-install-check: object identity with core re-exports', () => { - test('core.getAgentsDir === agentInstallCheck.getAgentsDir (by reference)', () => { - assert.strictEqual( - core.getAgentsDir, - agentInstallCheck.getAgentsDir, - 'core.getAgentsDir must be the same function reference as agentInstallCheck.getAgentsDir' - ); - }); - - test('core.checkAgentsInstalled === agentInstallCheck.checkAgentsInstalled (by reference)', () => { - assert.strictEqual( - core.checkAgentsInstalled, - agentInstallCheck.checkAgentsInstalled, - 'core.checkAgentsInstalled must be the same function reference as agentInstallCheck.checkAgentsInstalled' - ); - }); -}); - -// ─── 2. getAgentsDir behaviour ──────────────────────────────────────────────── +// ─── 1. getAgentsDir behaviour ──────────────────────────────────────────────── describe('getAgentsDir', () => { test('GSD_AGENTS_DIR override takes priority', () => { @@ -96,10 +71,7 @@ describe('getAgentsDir', () => { }); test('claude runtime returns __dirname-relative path', () => { - // getAgentsDir('claude') from both module and core must agree const fromModule = agentInstallCheck.getAgentsDir('claude'); - const fromCore = core.getAgentsDir('claude'); - assert.strictEqual(fromModule, fromCore); // Should end with /agents assert.ok(fromModule.endsWith(path.sep + 'agents') || fromModule.endsWith('/agents'), `Expected path to end with /agents, got: ${fromModule}`); @@ -124,7 +96,7 @@ describe('getAgentsDir', () => { }); }); -// ─── 3. checkAgentsInstalled behaviour ─────────────────────────────────────── +// ─── 2. checkAgentsInstalled behaviour ─────────────────────────────────────── describe('checkAgentsInstalled', () => { let tmpDir; diff --git a/tests/git-base-branch.test.cjs b/tests/git-base-branch.test.cjs index 064fd8e3f..66ce0964e 100644 --- a/tests/git-base-branch.test.cjs +++ b/tests/git-base-branch.test.cjs @@ -260,21 +260,12 @@ describe('#1146: git.base-branch resolver', () => { }); }); -// ─── gitWorktreeInfoInternal: relocation identity + behaviour (#1268 T0) ───── +// ─── gitWorktreeInfoInternal: behaviour (#1268 T0, T1 #1277) ───────────────── const gitBaseBranch = require(path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'git-base-branch.cjs')); -const core = require(path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'core.cjs')); const { createTempGitProject, createTempDir } = require('./helpers.cjs'); describe('#1268 gitWorktreeInfoInternal: relocation to git-base-branch', () => { - test('core.gitWorktreeInfoInternal === gitBaseBranch.gitWorktreeInfoInternal (by reference)', () => { - assert.strictEqual( - core.gitWorktreeInfoInternal, - gitBaseBranch.gitWorktreeInfoInternal, - 'core.gitWorktreeInfoInternal must be the same function reference as gitBaseBranch.gitWorktreeInfoInternal' - ); - }); - test('gitWorktreeInfoInternal(createTempGitProject()) returns {inside:true, worktreeRoot:}', (t) => { const dir = createTempGitProject('gsd-wt-info-'); t.after(() => cleanup(dir));