refactor(#1277): T1 — decouple agent-install-check + git-base-branch from the core spine (#1280)

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 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-15 15:46:41 -04:00
committed by GitHub
parent 0a856f06cd
commit 54420bae9e
6 changed files with 20 additions and 56 deletions

View File

@@ -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,

View File

@@ -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 ────────────────────────────────────────────────────────────────

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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:<non-empty string>}', (t) => {
const dir = createTempGitProject('gsd-wt-info-');
t.after(() => cleanup(dir));