diff --git a/gsd-core/bin/gsd-tools.cjs b/gsd-core/bin/gsd-tools.cjs index 8b0421da8..7e33347e6 100755 --- a/gsd-core/bin/gsd-tools.cjs +++ b/gsd-core/bin/gsd-tools.cjs @@ -298,13 +298,11 @@ async function main() { // Optional workstream override for parallel milestone work. // Priority: --ws flag > GSD_WORKSTREAM env var > session/shared pointer > null. - let ws = null; let workstreamContext = null; try { workstreamContext = resolveActiveWorkstream(cwd, args, process.env, { getStored: getActiveWorkstream, }); - ws = workstreamContext.ws; args = workstreamContext.args; // Set env var so all modules (planningDir, planningPaths) auto-resolve workstream paths. applyResolvedWorkstreamEnv(workstreamContext, process.env); diff --git a/scripts/affected-tests-lib.cjs b/scripts/affected-tests-lib.cjs index 2918e4232..c0ba24d5b 100644 --- a/scripts/affected-tests-lib.cjs +++ b/scripts/affected-tests-lib.cjs @@ -442,7 +442,7 @@ function resolveBaseRef() { * security), so every concrete match that pickAffectedTests put into `selected` * belongs to one of those suites and will be exercised by running all three. */ -function resolveRunPlan({ changedFiles, selected, widenRequired, criticalPath, noChanges }) { +function resolveRunPlan({ changedFiles: _changedFiles, selected, widenRequired, criticalPath, noChanges }) { if (noChanges) { return { mode: 'suite', suite: 'unit' }; } diff --git a/scripts/changeset/cli.cjs b/scripts/changeset/cli.cjs index 5875b0c9d..ee8749ccf 100755 --- a/scripts/changeset/cli.cjs +++ b/scripts/changeset/cli.cjs @@ -17,7 +17,7 @@ const fs = require('node:fs'); const path = require('node:path'); -const { parseFragment, FRAGMENT_ERROR } = require('./parse.cjs'); +const { parseFragment } = require('./parse.cjs'); const { renderChangelog } = require('./render.cjs'); const { serializeChangelog, parseChangelog } = require('./serialize.cjs'); const { renderGithubReleaseNotes } = require('./github-release-notes.cjs'); diff --git a/scripts/check-env.cjs b/scripts/check-env.cjs index 4d51fb867..2ce274764 100644 --- a/scripts/check-env.cjs +++ b/scripts/check-env.cjs @@ -27,7 +27,7 @@ const fs = require('fs'); const path = require('path'); -const { execFileSync, spawnSync } = require('child_process'); +const { spawnSync } = require('child_process'); // On Windows, npm ships as npm.cmd (a batch wrapper); spawnSync without // shell:true requires the exact filename including extension. diff --git a/scripts/ci-rebase-check.cjs b/scripts/ci-rebase-check.cjs index 5e8923570..6cfcbb04c 100644 --- a/scripts/ci-rebase-check.cjs +++ b/scripts/ci-rebase-check.cjs @@ -11,8 +11,7 @@ // Exit 0 = merged cleanly (or merge was a no-op). // Exit 1 = merge conflict or fetch failure. -const { execFileSync, execSync } = require('child_process'); -const path = require('path'); +const { execFileSync } = require('child_process'); function run(cmd, args, opts) { try { @@ -50,11 +49,9 @@ if (token && repo) { } // Fetch base branch with retry. -let fetched = false; for (let attempt = 1; attempt <= 3; attempt++) { const result = run('git', ['fetch', 'origin', baseBranch]); if (result) { - fetched = true; break; } if (attempt === 3) { diff --git a/scripts/ci-test-scope.cjs b/scripts/ci-test-scope.cjs index 299491b2b..f81c384a2 100644 --- a/scripts/ci-test-scope.cjs +++ b/scripts/ci-test-scope.cjs @@ -3,7 +3,6 @@ const { execFileSync } = require('child_process'); const { existsSync, readdirSync, appendFileSync } = require('fs'); -const { join } = require('path'); const RULES = [ { diff --git a/scripts/gen-research-agents.cjs b/scripts/gen-research-agents.cjs index 9512668b8..6ff6de3ea 100644 --- a/scripts/gen-research-agents.cjs +++ b/scripts/gen-research-agents.cjs @@ -133,7 +133,7 @@ function checkAgent(profile) { return ['agent file not found: ' + agentPath]; } - const { fields, body } = parseAgentFile(agentPath); + const { fields } = parseAgentFile(agentPath); const fullContent = fs.readFileSync(agentPath, 'utf8'); // (a) frontmatter fields diff --git a/scripts/strip-prose-atrefs.cjs b/scripts/strip-prose-atrefs.cjs index fb4b2b2f0..45c3ac7f1 100644 --- a/scripts/strip-prose-atrefs.cjs +++ b/scripts/strip-prose-atrefs.cjs @@ -30,7 +30,7 @@ const DRY_RUN = process.argv.includes('--dry-run'); const ROOT = path.join(__dirname, '..'); const COMMANDS_DIR = path.join(ROOT, 'commands', 'gsd'); -const AT_PATH_PATTERN = /@(?:~|\$HOME)\/.+?gsd-core\/[^\s`\)]+/; +const AT_PATH_PATTERN = /@(?:~|\$HOME)\/.+?gsd-core\/[^\s`)]+/; const mkAtRe = () => new RegExp(AT_PATH_PATTERN.source, 'g'); function transformLine(line) { diff --git a/scripts/sync-runtime-launcher.cjs b/scripts/sync-runtime-launcher.cjs index 9c4dc9059..fc52ceec4 100644 --- a/scripts/sync-runtime-launcher.cjs +++ b/scripts/sync-runtime-launcher.cjs @@ -96,9 +96,6 @@ function removeResolverLines(lines, preamble) { const result = []; let i = 0; - // Build a set of preamble lines for fast lookup (to strip previously-inserted preambles) - const preambleLineSet = new Set(preamble); - while (i < lines.length) { const line = lines[i]; const trimmed = line.trim(); diff --git a/src/command-routing-hub.cts b/src/command-routing-hub.cts index 4fd6d91d8..eb57c6699 100644 --- a/src/command-routing-hub.cts +++ b/src/command-routing-hub.cts @@ -271,7 +271,7 @@ function createHub({ cjsRegistry, manifest, logger }: HubOptions = {}): { dispat } // err variant: already has kind + typed payload // Double-cast through unknown to satisfy strict index-signature check. - return hubResult as unknown as Record; // eslint-disable-line @typescript-eslint/no-unsafe-return + return hubResult as unknown as Record; } /** diff --git a/src/config.cts b/src/config.cts index f3bbf04af..a0eb45f7c 100644 --- a/src/config.cts +++ b/src/config.cts @@ -679,7 +679,6 @@ function cmdConfigSetModelProfile(cwd: string, profile: string | undefined, raw: error(`Usage: config-set-model-profile <${VALID_PROFILES.join('|')}>`); } - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion const normalizedProfile = profile!.toLowerCase().trim(); if (!VALID_PROFILES.includes(normalizedProfile)) { error(`Invalid profile '${String(profile)}'. Valid profiles: ${VALID_PROFILES.join(', ')}`); diff --git a/src/graphify.cts b/src/graphify.cts index 4bc068b19..d8432cfb6 100644 --- a/src/graphify.cts +++ b/src/graphify.cts @@ -33,7 +33,7 @@ function isGraphifyEnabled(planningDir: string): boolean { (config.graphify as Record).enabled === true ) return true; return false; - } catch (_e) { + } catch { return false; } } @@ -230,7 +230,7 @@ function safeReadJson(filePath: string): Graph | null { try { if (!fs.existsSync(filePath)) return null; return JSON.parse(fs.readFileSync(filePath, 'utf8')) as Graph; - } catch (_e) { + } catch { return null; } } diff --git a/src/intel.cts b/src/intel.cts index 8b4d8c958..f9ccb5a5c 100644 --- a/src/intel.cts +++ b/src/intel.cts @@ -61,7 +61,7 @@ function isIntelEnabled(planningDir: string): boolean { (config.intel as Record).enabled === true ) return true; return false; - } catch (_e) { + } catch { return false; } } @@ -104,7 +104,7 @@ function safeReadJson(filePath: string): IntelData | null { const raw = platformReadSync(filePath); if (raw === null) return null; return JSON.parse(raw) as IntelData; - } catch (_e) { + } catch { return null; } } @@ -118,7 +118,7 @@ function hashFile(filePath: string): string | null { const content = platformReadSync(filePath); if (content === null) return null; return crypto.createHash('sha256').update(content).digest('hex'); - } catch (_e) { + } catch { return null; } } @@ -175,22 +175,6 @@ function matchesInValue(value: unknown, lowerTerm: string): boolean { return false; } -/** - * Search for a term in arch.md text content. - * Returns matching lines. - */ -function searchArchMd(filePath: string, term: string): string[] { - try { - const content = platformReadSync(filePath); - if (content === null) return []; - const lowerTerm = term.toLowerCase(); - const lines = content.split(/\r?\n/); - return lines.filter(line => line.toLowerCase().includes(lowerTerm)); - } catch (_e) { - return []; - } -} - // ─── Public API ────────────────────────────────────────────────────────────── interface IntelQueryResult { diff --git a/src/research-provider.cts b/src/research-provider.cts index 0c89edc20..3a2c27d69 100644 --- a/src/research-provider.cts +++ b/src/research-provider.cts @@ -12,7 +12,6 @@ // Types // --------------------------------------------------------------------------- -type ProviderKind = 'docs' | 'web' | 'scrape'; type ConfidenceLevel = 'HIGH' | 'MEDIUM' | 'LOW'; interface ProviderWaterfall { diff --git a/src/roadmap-upgrade.cts b/src/roadmap-upgrade.cts index cf091d3b5..6f07b0ad4 100644 --- a/src/roadmap-upgrade.cts +++ b/src/roadmap-upgrade.cts @@ -27,9 +27,6 @@ const MIGRATED_PHASE_HEADING_RE = /^#{2,4}\s*(?:\[[^\]]+\]\s*)?Phase\s+\d+-\d{2} // The optional bracket-token prefix (e.g., [GSD]) must be tested before the emoji group. const MILESTONE_HEADING_RE = /^##\s+(?:\[[^\]]+\]\s+|Roadmap\s+|[✅🚧]\s*)?v(\d+)\.(\d+)(?:\s|:)/iu; -// Matches checklist phase references: - [ ] **Phase N:** or - [x] **Phase N:** (also decimal) -const CHECKLIST_PHASE_RE = /^(\s*-\s*\[[ x]\]\s*\*{0,2})Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:/gi; - // ─── Types ──────────────────────────────────────────────────────────────────── interface ParsedPhaseEntry { @@ -199,19 +196,6 @@ function buildNewDirName(oldDirName: string, newId: string, projectCode: string return projectCode ? `${projectCode}-${newBase}` : newBase; } -/** - * Read project_code from config.json if present. - */ -function readProjectCode(configPath: string): string | null { - try { - const raw = fs.readFileSync(configPath, 'utf8'); - const parsed = JSON.parse(raw) as Record; - return typeof parsed['project_code'] === 'string' ? parsed['project_code'] : null; - } catch { - return null; - } -} - // ─── computeMigrationPlan ───────────────────────────────────────────────────── /** diff --git a/src/workstream-inventory.cts b/src/workstream-inventory.cts index 8cafdee39..9068c9d37 100644 --- a/src/workstream-inventory.cts +++ b/src/workstream-inventory.cts @@ -17,7 +17,7 @@ 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 { toPosixPath, readSubdirectories } = core; +const { readSubdirectories } = core; // eslint-disable-next-line @typescript-eslint/no-require-imports import planScan = require('./plan-scan.cjs'); // eslint-disable-next-line @typescript-eslint/no-require-imports @@ -163,7 +163,6 @@ function getOtherActiveWorkstreamInventories(cwd: string, excludeWs: string): Wo .filter(inventory => !isCompletedInventory(inventory.status)); } -// Re-export toPosixPath for compatibility (used by callers indirectly through core) export = { countPhaseFiles, countRoadmapPhases, diff --git a/tests/4-phase-complete-cjs-regression.test.cjs b/tests/4-phase-complete-cjs-regression.test.cjs index 943e5f1d0..29f50f480 100644 --- a/tests/4-phase-complete-cjs-regression.test.cjs +++ b/tests/4-phase-complete-cjs-regression.test.cjs @@ -192,8 +192,6 @@ function extractFrontmatterField(stateContent, fieldName) { // Capture stdout from cmdPhaseComplete (it calls output() which writes to stdout) function capturePhaseComplete(cwd, phaseNum) { - const { execFileSync } = require('child_process'); - const TOOLS = path.join(__dirname, '..', 'gsd-core', 'bin', 'gsd-tools.cjs'); // We invoke gsd-tools directly for the full CJS path, but with GSD_DISABLE_SDK_BRIDGE=1 // to force the CJS implementation. Since no env var disables bridge, we call cmdPhaseComplete // directly and redirect output capture. diff --git a/tests/agent-install-validation.test.cjs b/tests/agent-install-validation.test.cjs index f378b495d..17c03a858 100644 --- a/tests/agent-install-validation.test.cjs +++ b/tests/agent-install-validation.test.cjs @@ -25,7 +25,7 @@ const EXPECTED_AGENTS = Object.keys(MODEL_PROFILES); * We use --cwd to point at the project, and GSD_INSTALL_DIR env to override * the agents directory location for testing. */ -function createAgentsDir(configDir, agentNames = []) { +function _createAgentsDir(configDir, agentNames = []) { const agentsDir = path.join(configDir, AGENTS_DIR_NAME); fs.mkdirSync(agentsDir, { recursive: true }); for (const name of agentNames) { diff --git a/tests/analyze-dependencies.test.cjs b/tests/analyze-dependencies.test.cjs index e796d8af0..90859ec6f 100644 --- a/tests/analyze-dependencies.test.cjs +++ b/tests/analyze-dependencies.test.cjs @@ -3,7 +3,7 @@ // IS what the runtime loads. Testing text content tests the deployed contract. // Per CONTRIBUTING.md exception matrix. -const { test, describe, beforeEach, afterEach } = require('node:test'); +const { test, describe } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); diff --git a/tests/autonomous-ui-steps.test.cjs b/tests/autonomous-ui-steps.test.cjs index 9c851557f..28205874b 100644 --- a/tests/autonomous-ui-steps.test.cjs +++ b/tests/autonomous-ui-steps.test.cjs @@ -6,7 +6,7 @@ * for phases with frontend indicators. */ -const { describe, it, test, beforeEach } = require('node:test'); +const { describe, test, beforeEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); diff --git a/tests/backwards-compat-phase-id.test.cjs b/tests/backwards-compat-phase-id.test.cjs index 0013572bc..60426b931 100644 --- a/tests/backwards-compat-phase-id.test.cjs +++ b/tests/backwards-compat-phase-id.test.cjs @@ -24,7 +24,7 @@ const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); -const { createTempProject, cleanup, runGsdTools, captureConsole } = require('./helpers.cjs'); +const { createTempProject, cleanup, captureConsole } = require('./helpers.cjs'); const { getMilestonePhaseFilter } = require('../gsd-core/bin/lib/core.cjs'); // ─── helpers ───────────────────────────────────────────────────────────────── diff --git a/tests/bug-131-release-tarball-smoke-explicit-home.test.cjs b/tests/bug-131-release-tarball-smoke-explicit-home.test.cjs index 996725bb3..d84d79e18 100644 --- a/tests/bug-131-release-tarball-smoke-explicit-home.test.cjs +++ b/tests/bug-131-release-tarball-smoke-explicit-home.test.cjs @@ -25,7 +25,7 @@ const path = require('node:path'); const { execFileSync } = require('node:child_process'); // The helpers under test. -const { runNpm, isolatedNpmEnv, cleanup } = require('./helpers.cjs'); +const { isolatedNpmEnv, cleanup } = require('./helpers.cjs'); // Resolve a filesystem path to its canonical (symlink-free) form even if the // leaf does not exist yet (e.g. ~/.npm before npm has written its cache). diff --git a/tests/bug-211-launcher-home-fallback.test.cjs b/tests/bug-211-launcher-home-fallback.test.cjs index bc8e287ac..fe4909953 100644 --- a/tests/bug-211-launcher-home-fallback.test.cjs +++ b/tests/bug-211-launcher-home-fallback.test.cjs @@ -87,7 +87,6 @@ describe('bug-211: launcher ~/.claude home fallback', () => { // in the same directory as gsd-tools, create a dedicated shim dir with a // symlink to node only (no gsd-tools there). const nodeBin = execFileSync('which', ['node'], { encoding: 'utf8' }).trim(); - const nodeBinDir = path.dirname(nodeBin); const systemPaths = (process.env.PATH || '/usr/bin:/bin') .split(path.delimiter) .filter((p) => { diff --git a/tests/bug-2136-sh-hook-version.test.cjs b/tests/bug-2136-sh-hook-version.test.cjs index bcf045db3..e24f107f5 100644 --- a/tests/bug-2136-sh-hook-version.test.cjs +++ b/tests/bug-2136-sh-hook-version.test.cjs @@ -45,7 +45,7 @@ const os = require('os'); const { execFileSync } = require('child_process'); const HOOKS_DIR = path.join(__dirname, '..', 'hooks'); -const CHECK_UPDATE_FILE = path.join(HOOKS_DIR, 'gsd-check-update.js'); +const _CHECK_UPDATE_FILE = path.join(HOOKS_DIR, 'gsd-check-update.js'); const WORKER_FILE = path.join(HOOKS_DIR, 'gsd-check-update-worker.js'); const INSTALL_SCRIPT = path.join(__dirname, '..', 'bin', 'install.js'); const BUILD_SCRIPT = path.join(__dirname, '..', 'scripts', 'build-hooks.js'); @@ -142,11 +142,11 @@ describe('bug #2136 part 2: stale-hook detector handles bash comment syntax', () // "(?:\/\/|#)" directly in source. const hasBashAlternative = src.includes('(?:\\/\\/|#)') || // escaped form (old template-literal style) - src.includes('(?:\/\/|#)'); // direct form in plain JS worker + src.includes('(?://|#)'); // direct form in plain JS worker assert.ok( hasBashAlternative, 'gsd-check-update-worker.js version regex must include an alternative for bash "#" comments. ' + - 'Expected to find (?:\\/\\/|#) or (?:\/\/|#) in the source. ' + + 'Expected to find (?:\\/\\/|#) or (?://|#) in the source. ' + 'The original "//" only regex causes bash hooks to always report hookVersion: "unknown"' ); }); diff --git a/tests/bug-2256-model-overrides-transport.test.cjs b/tests/bug-2256-model-overrides-transport.test.cjs index 6b40ac7ee..f6f6e37dc 100644 --- a/tests/bug-2256-model-overrides-transport.test.cjs +++ b/tests/bug-2256-model-overrides-transport.test.cjs @@ -17,7 +17,6 @@ const { test, describe, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); -const os = require('os'); const isWindows = process.platform === 'win32'; diff --git a/tests/bug-2470-update-md-claude-path.test.cjs b/tests/bug-2470-update-md-claude-path.test.cjs index 2c315ba38..83cc17a32 100644 --- a/tests/bug-2470-update-md-claude-path.test.cjs +++ b/tests/bug-2470-update-md-claude-path.test.cjs @@ -35,7 +35,7 @@ describe('update.md — no bare ~.claude path references (#2470)', () => { assert.strictEqual( matches, null, - `update.md must not contain bare ~/\.claude (without trailing slash) — installer scanner flags these as unresolved path refs: ${JSON.stringify(matches)}` + `update.md must not contain bare ~/.claude (without trailing slash) — installer scanner flags these as unresolved path refs: ${JSON.stringify(matches)}` ); }); }); diff --git a/tests/bug-2530-valid-config-keys.test.cjs b/tests/bug-2530-valid-config-keys.test.cjs index ecb5c732b..53e30ef53 100644 --- a/tests/bug-2530-valid-config-keys.test.cjs +++ b/tests/bug-2530-valid-config-keys.test.cjs @@ -13,7 +13,6 @@ const { describe, test } = require('node:test'); const assert = require('node:assert/strict'); -const path = require('node:path'); const { createTempProject, cleanup, runGsdTools } = require('./helpers.cjs'); const { VALID_CONFIG_KEYS, isValidConfigKey } = require('../gsd-core/bin/lib/config-schema.cjs'); diff --git a/tests/bug-2543-gsd-slash-namespace.test.cjs b/tests/bug-2543-gsd-slash-namespace.test.cjs index 72cc2d34c..e4b7cba81 100644 --- a/tests/bug-2543-gsd-slash-namespace.test.cjs +++ b/tests/bug-2543-gsd-slash-namespace.test.cjs @@ -49,14 +49,6 @@ const COMMANDS_DIR = path.join(ROOT, 'commands', 'gsd'); // // Expand this list only if a new runtime-emitter module is introduced AND the // bug-3584 test is updated to cover it. -const RUNTIME_EMITTER_EXCLUDES = new Set([ - // Primary runtime-slash emitter (bug-3584 canonical contract): - path.join(ROOT, 'gsd-core', 'bin', 'lib', 'runtime-slash.cjs'), - // phase-lifecycle-policy.ts emits runtime-persisted slash references (bug-3584): - path.join(ROOT, 'gsd-core', 'bin', 'lib', 'phase-lifecycle-policy.ts'), - // Generated CJS files match the TS source's emitted form — never hand-edited: - // (matched below by .generated.cjs extension — see collectFiles exclusion) -]); const SEARCH_DIRS = [ // NOTE: gsd-core/bin/lib is intentionally EXCLUDED from SEARCH_DIRS. diff --git a/tests/bug-2760-codex-install-defensive.test.cjs b/tests/bug-2760-codex-install-defensive.test.cjs index 0517494c6..6e9fcd85e 100644 --- a/tests/bug-2760-codex-install-defensive.test.cjs +++ b/tests/bug-2760-codex-install-defensive.test.cjs @@ -40,8 +40,6 @@ const { install, validateCodexConfigSchema, hasUserNamespacedAotHooks, - stripGsdFromCodexConfig, - installCodexConfig, parseTomlToObject, } = require('../bin/install.js'); @@ -222,7 +220,7 @@ describe('#2760 defect 3 — Hooks AoT preservation across install/uninstall/rei runCodexInstall(codexHome); const content = readCodexConfig(codexHome); - const parsed = parseTomlToObject(content); + parseTomlToObject(content); const hooksJsonCommands = readHooksSessionStartCommands(codexHome); const gsdHandlers = hooksJsonCommands.filter((cmd) => /gsd-check-update/.test(cmd)); @@ -233,7 +231,7 @@ describe('#2760 defect 3 — Hooks AoT preservation across install/uninstall/rei writeCodexConfig(codexHome, ''); runCodexInstall(codexHome); runCodexInstall(codexHome); // second install - const content = readCodexConfig(codexHome); + readCodexConfig(codexHome); const hooksJsonCommands = readHooksSessionStartCommands(codexHome); const gsdHandlers = hooksJsonCommands.filter((cmd) => /gsd-check-update/.test(cmd)); diff --git a/tests/bug-2794-opencode-model-profile-overrides.test.cjs b/tests/bug-2794-opencode-model-profile-overrides.test.cjs index d00b6d7cb..97b53f648 100644 --- a/tests/bug-2794-opencode-model-profile-overrides.test.cjs +++ b/tests/bug-2794-opencode-model-profile-overrides.test.cjs @@ -26,12 +26,8 @@ const { describe, test, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); -const os = require('node:os'); - const { readGsdRuntimeProfileResolver, - readGsdEffectiveModelOverrides, - convertClaudeToOpencodeFrontmatter, install, } = require('../bin/install.js'); diff --git a/tests/bug-2808-skill-hyphen-name.test.cjs b/tests/bug-2808-skill-hyphen-name.test.cjs index 2cadae339..efdc0a8ce 100644 --- a/tests/bug-2808-skill-hyphen-name.test.cjs +++ b/tests/bug-2808-skill-hyphen-name.test.cjs @@ -34,7 +34,7 @@ const path = require('node:path'); const { cleanup, createTempDir } = require('./helpers.cjs'); const ROOT = path.join(__dirname, '..'); -const { convertClaudeCommandToClaudeSkill, installRuntimeArtifacts, uninstallRuntimeArtifacts, skillFrontmatterName } = +const { convertClaudeCommandToClaudeSkill, installRuntimeArtifacts, skillFrontmatterName } = require(path.join(ROOT, 'bin', 'install.js')); const { diff --git a/tests/bug-2992-check-latest-version.test.cjs b/tests/bug-2992-check-latest-version.test.cjs index f32bc4cc4..adb41e724 100644 --- a/tests/bug-2992-check-latest-version.test.cjs +++ b/tests/bug-2992-check-latest-version.test.cjs @@ -1,10 +1,9 @@ 'use strict'; process.env.GSD_TEST_MODE = '1'; -const { test, describe, before, after } = require('node:test'); +const { test, describe } = require('node:test'); const assert = require('node:assert/strict'); const path = require('node:path'); -const cp = require('node:child_process'); const ROOT = path.join(__dirname, '..'); const { checkLatestVersion, CHECK_REASON, PACKAGE_NAME } = require( diff --git a/tests/bug-3037-gemini-duplicate-commands.test.cjs b/tests/bug-3037-gemini-duplicate-commands.test.cjs index 92a40b564..313c5be30 100644 --- a/tests/bug-3037-gemini-duplicate-commands.test.cjs +++ b/tests/bug-3037-gemini-duplicate-commands.test.cjs @@ -28,7 +28,6 @@ const { test, describe, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); -const os = require('node:os'); const { createTempDir, cleanup } = require('./helpers.cjs'); const { install } = require('../bin/install.js'); diff --git a/tests/bug-3126-global-skills-base-runtime-path.test.cjs b/tests/bug-3126-global-skills-base-runtime-path.test.cjs index d606261dc..e1088b624 100644 --- a/tests/bug-3126-global-skills-base-runtime-path.test.cjs +++ b/tests/bug-3126-global-skills-base-runtime-path.test.cjs @@ -27,7 +27,6 @@ const { getGlobalConfigDir, getGlobalSkillsBase, getGlobalSkillDir, - getGlobalSkillDisplayPath, } = require(path.join(ROOT, 'gsd-core', 'bin', 'lib', 'runtime-homes.cjs')); // Helper: run fn with an env var temporarily set diff --git a/tests/bug-3128-roadmap-plan-count-slug-layout.test.cjs b/tests/bug-3128-roadmap-plan-count-slug-layout.test.cjs index 223595526..7f3ba934b 100644 --- a/tests/bug-3128-roadmap-plan-count-slug-layout.test.cjs +++ b/tests/bug-3128-roadmap-plan-count-slug-layout.test.cjs @@ -18,7 +18,6 @@ const { describe, test } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); -const os = require('node:os'); const path = require('node:path'); const ROOT = path.join(__dirname, '..'); @@ -33,14 +32,6 @@ const planScanLib = path.join(ROOT, 'gsd-core', 'bin', 'lib', 'plan-scan.cjs'); // The simplest correct seam: inspect the source for the regex pattern and // validate with a synthetic directory that the manager path returns correct counts. -// Build a temporary phase directory with the slug layout -function makeTempPhase(files) { - const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-3128-')); - for (const f of files) { - fs.writeFileSync(path.join(dir, f), `# ${f}\n`); - } - return dir; -} // Import countPhasePlansAndSummaries by monkey-patching: we inline the // fixed filter logic and verify it matches the file on disk. diff --git a/tests/bug-3135-capture-backlog-workflow.test.cjs b/tests/bug-3135-capture-backlog-workflow.test.cjs index 4d0f85241..c982f01c9 100644 --- a/tests/bug-3135-capture-backlog-workflow.test.cjs +++ b/tests/bug-3135-capture-backlog-workflow.test.cjs @@ -25,7 +25,6 @@ const path = require('node:path'); const ROOT = path.join(__dirname, '..'); const WORKFLOW = path.join(ROOT, 'gsd-core', 'workflows', 'add-backlog.md'); const COMMANDS_DIR = path.join(ROOT, 'commands', 'gsd'); -const WORKFLOWS_DIR = path.join(ROOT, 'gsd-core', 'workflows'); // ─── #3135: add-backlog workflow ───────────────────────────────────────────── diff --git a/tests/bug-3242-state-update-progress-trample.test.cjs b/tests/bug-3242-state-update-progress-trample.test.cjs index d94034724..5ceb8837d 100644 --- a/tests/bug-3242-state-update-progress-trample.test.cjs +++ b/tests/bug-3242-state-update-progress-trample.test.cjs @@ -104,7 +104,7 @@ describe('#3242 Bug A: body-only state.update preserves curated progress frontma cleanup(tmpDir); }); - test('state.update "Last Activity" does not overwrite progress.completed_plans', (t) => { + test('state.update "Last Activity" does not overwrite progress.completed_plans', (_t) => { const statePath = path.join(tmpDir, '.planning', 'STATE.md'); fs.writeFileSync(statePath, buildStateWithCuratedProgress({ completedPlans: 22, @@ -220,7 +220,7 @@ describe('#3242 Bug B: progress.percent reflects phase fraction when ROADMAP dec cleanup(tmpDir); }); - test('12 declared phases / 6 realized / 6/6 plans done → percent is 50, not 100', (t) => { + test('12 declared phases / 6 realized / 6/6 plans done → percent is 50, not 100', (_t) => { const statePath = path.join(tmpDir, '.planning', 'STATE.md'); // Body: 6 realized phases visible to disk scan. @@ -273,7 +273,7 @@ describe('#3242 Bug B: progress.percent reflects phase fraction when ROADMAP dec ); }); - test('all phases realized: percent equals plan fraction (no artificial cap)', (t) => { + test('all phases realized: percent equals plan fraction (no artificial cap)', (_t) => { const statePath = path.join(tmpDir, '.planning', 'STATE.md'); fs.writeFileSync(statePath, [ diff --git a/tests/bug-3285-codex-hooks-state-allowed.test.cjs b/tests/bug-3285-codex-hooks-state-allowed.test.cjs index 9c2f1ab13..b2ed9b67f 100644 --- a/tests/bug-3285-codex-hooks-state-allowed.test.cjs +++ b/tests/bug-3285-codex-hooks-state-allowed.test.cjs @@ -26,7 +26,6 @@ const os = require('os'); const { execFileSync } = require('child_process'); const { validateCodexConfigSchema, install } = require('../bin/install.js'); -const installModule = require('../bin/install.js'); const { cleanup } = require('./helpers.cjs'); if (previousGsdTestMode === undefined) { diff --git a/tests/bug-3288-model-catalog-install-path.test.cjs b/tests/bug-3288-model-catalog-install-path.test.cjs index 4cda25002..4f7d7837d 100644 --- a/tests/bug-3288-model-catalog-install-path.test.cjs +++ b/tests/bug-3288-model-catalog-install-path.test.cjs @@ -29,7 +29,6 @@ const { describe, test, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); -const os = require('node:os'); const REPO_ROOT = path.join(__dirname, '..'); const MODEL_CATALOG_CJS = path.join(REPO_ROOT, 'gsd-core', 'bin', 'lib', 'model-catalog.cjs'); diff --git a/tests/bug-3523-cjs-loadconfig-branching-strategy-warning.test.cjs b/tests/bug-3523-cjs-loadconfig-branching-strategy-warning.test.cjs index 00562212b..11bbdc1d0 100644 --- a/tests/bug-3523-cjs-loadconfig-branching-strategy-warning.test.cjs +++ b/tests/bug-3523-cjs-loadconfig-branching-strategy-warning.test.cjs @@ -31,7 +31,7 @@ * "no warning" pattern from #2687). */ -const { describe, test, afterEach, before } = require('node:test'); +const { describe, test, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); diff --git a/tests/bug-3537-padded-id-against-unpadded-roadmap.test.cjs b/tests/bug-3537-padded-id-against-unpadded-roadmap.test.cjs index def22af89..ed4fefe22 100644 --- a/tests/bug-3537-padded-id-against-unpadded-roadmap.test.cjs +++ b/tests/bug-3537-padded-id-against-unpadded-roadmap.test.cjs @@ -20,7 +20,7 @@ 'use strict'; -const { describe, test, beforeEach, afterEach } = require('node:test'); +const { describe, test } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); diff --git a/tests/bug-3541-installer-migration-prompt-user-resolution.test.cjs b/tests/bug-3541-installer-migration-prompt-user-resolution.test.cjs index 47c193e51..b4f0887a6 100644 --- a/tests/bug-3541-installer-migration-prompt-user-resolution.test.cjs +++ b/tests/bug-3541-installer-migration-prompt-user-resolution.test.cjs @@ -25,7 +25,6 @@ const { describe, test, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); -const crypto = require('node:crypto'); const { runInstallerMigrations, @@ -36,10 +35,6 @@ const { } = require('../gsd-core/bin/lib/installer-migration-report.cjs'); const { createTempDir, cleanup } = require('./helpers.cjs'); -function sha256(content) { - return crypto.createHash('sha256').update(content).digest('hex'); -} - function writeFile(root, relPath, content) { const fullPath = path.join(root, relPath); fs.mkdirSync(path.dirname(fullPath), { recursive: true }); diff --git a/tests/bug-3571-configuration-manifest-install-path.test.cjs b/tests/bug-3571-configuration-manifest-install-path.test.cjs index c1b988935..376c1cfc2 100644 --- a/tests/bug-3571-configuration-manifest-install-path.test.cjs +++ b/tests/bug-3571-configuration-manifest-install-path.test.cjs @@ -11,7 +11,6 @@ process.env.GSD_TEST_MODE = '1'; const { describe, test, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); -const os = require('node:os'); const path = require('node:path'); const REPO_ROOT = path.join(__dirname, '..'); diff --git a/tests/bug-3582-codex-skills-materialized.test.cjs b/tests/bug-3582-codex-skills-materialized.test.cjs index 9fbe51596..ac6ae112d 100644 --- a/tests/bug-3582-codex-skills-materialized.test.cjs +++ b/tests/bug-3582-codex-skills-materialized.test.cjs @@ -38,7 +38,6 @@ const { test, describe, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); -const os = require('os'); const { install, getCodexSkillAdapterHeader } = require('../bin/install.js'); const { parseFrontmatter, createTempDir, cleanup } = require('./helpers.cjs'); diff --git a/tests/bug-3610-installer-migration-bundled-hooks-classification.test.cjs b/tests/bug-3610-installer-migration-bundled-hooks-classification.test.cjs index d30913b72..fb5576104 100644 --- a/tests/bug-3610-installer-migration-bundled-hooks-classification.test.cjs +++ b/tests/bug-3610-installer-migration-bundled-hooks-classification.test.cjs @@ -27,7 +27,6 @@ const { describe, test, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); -const crypto = require('node:crypto'); const { runInstallerMigrations, diff --git a/tests/bug-3659-applysurface-prune-skill-dirs.test.cjs b/tests/bug-3659-applysurface-prune-skill-dirs.test.cjs index 067ede288..4feda3126 100644 --- a/tests/bug-3659-applysurface-prune-skill-dirs.test.cjs +++ b/tests/bug-3659-applysurface-prune-skill-dirs.test.cjs @@ -84,7 +84,7 @@ function createFixtureWithUserGsdDir() { describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disable', () => { test('(a) disabled cluster gsd-* dirs are removed from skills dir', (t) => { - const { configDir, skillsDir, gsdExplore, gsdHelp } = createFixture(); + const { configDir, gsdExplore, gsdHelp } = createFixture(); t.after(() => cleanup(configDir)); // Surface state at configDir (= ~/.claude), NOT at skillsDir (= ~/.claude/skills). @@ -116,7 +116,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab }); test('(b) gsd-* dirs in retained clusters are preserved', (t) => { - const { configDir, skillsDir, gsdHelp } = createFixture(); + const { configDir, gsdHelp } = createFixture(); t.after(() => cleanup(configDir)); // Disable a cluster that does NOT include help (core_loop has help) @@ -138,7 +138,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab }); test('(c) non-gsd user dirs are untouched', (t) => { - const { configDir, skillsDir, userSkill } = createFixture(); + const { configDir, userSkill } = createFixture(); t.after(() => cleanup(configDir)); writeSurface(configDir, { @@ -163,7 +163,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab }); test('(d) idempotence: running applySurface twice produces identical on-disk state', (t) => { - const { configDir, skillsDir, gsdExplore, gsdHelp, userSkill } = createFixture(); + const { configDir, skillsDir, gsdExplore, userSkill } = createFixture(); t.after(() => cleanup(configDir)); writeSurface(configDir, { @@ -212,7 +212,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab // 2. gsd-help/ — GSD-owned, disabled cluster → REMOVED // 3. my-custom-skill/ — user-owned, no gsd- prefix → PRESERVED // 4. gsd-mything/ — prefix match but NOT in manifest → PRESERVED (Finding 1 fix) - const { configDir, skillsDir, gsdExplore, gsdHelp, userSkill, userGsdDir } = + const { configDir, gsdExplore, gsdHelp, userSkill, userGsdDir } = createFixtureWithUserGsdDir(); t.after(() => cleanup(configDir)); diff --git a/tests/bug-3683-workflow-colon-namespace-leak.test.cjs b/tests/bug-3683-workflow-colon-namespace-leak.test.cjs index 26ff91a2f..4732c715b 100644 --- a/tests/bug-3683-workflow-colon-namespace-leak.test.cjs +++ b/tests/bug-3683-workflow-colon-namespace-leak.test.cjs @@ -42,7 +42,7 @@ const { cleanup } = require('./helpers.cjs'); const REPO_ROOT = path.resolve(__dirname, '..'); const INSTALL_PATH = path.join(REPO_ROOT, 'bin', 'install.js'); -const install = require(INSTALL_PATH); +require(INSTALL_PATH); const { readCmdNames } = require(path.join(REPO_ROOT, 'scripts', 'fix-slash-commands.cjs')); // --------------------------------------------------------------------------- @@ -400,7 +400,6 @@ describe('bug #3683 — workflow/reference colon-namespace leak (Claude local in describe('G — negative: staged gemini workflows preserve colon-namespace refs', () => { let tmpDir; const cmdNames = readCmdNames(); - const rosterRegex = buildRosterRegex(cmdNames); before(() => { tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-3683-gem-')); diff --git a/tests/bug-3691-annotate-deps-plans-block-variants.test.cjs b/tests/bug-3691-annotate-deps-plans-block-variants.test.cjs index f6b48e1a5..06841655d 100644 --- a/tests/bug-3691-annotate-deps-plans-block-variants.test.cjs +++ b/tests/bug-3691-annotate-deps-plans-block-variants.test.cjs @@ -83,7 +83,7 @@ describe('bug #3691 — Bug 1: Plans-block detection with inline summary', () => let tmpDir; afterEach(() => cleanup(tmpDir)); - test('Plans: N plans (inline count after colon) is detected as a Plans-block', (t) => { + test('Plans: N plans (inline count after colon) is detected as a Plans-block', (_t) => { // Pre-fix: `Plans:\s*\n` requires bare newline — fails for "Plans: 2 plans\n" // Post-fix: `Plans:[^\n]*\n` accepts any text after the colon const roadmap = [ @@ -117,7 +117,7 @@ describe('bug #3691 — Bug 1: Plans-block detection with inline summary', () => assert.ok(written.includes('Wave'), 'wave annotation must appear in ROADMAP.md'); }); - test('Plans: N plans across N waves (longer inline text) is detected', (t) => { + test('Plans: N plans across N waves (longer inline text) is detected', (_t) => { const roadmap = [ '# Roadmap', '', @@ -144,7 +144,7 @@ describe('bug #3691 — Bug 1: Plans-block detection with inline summary', () => 'Plans-block with "N plans across N waves" inline text must be detected'); }); - test('**Plans:** (bold markdown wrapper) is detected as a Plans-block', (t) => { + test('**Plans:** (bold markdown wrapper) is detected as a Plans-block', (_t) => { // Bold wrapper: `**Plans:** 3 plans across 2 waves` const roadmap = [ '# Roadmap', @@ -170,7 +170,7 @@ describe('bug #3691 — Bug 1: Plans-block detection with inline summary', () => '**Plans:** bold-wrapped header must be detected as a Plans-block'); }); - test('bare Plans: (no inline text, legacy format) still works after fix', (t) => { + test('bare Plans: (no inline text, legacy format) still works after fix', (_t) => { // Regression guard: the fix must not break the working case const roadmap = [ '# Roadmap', @@ -205,7 +205,7 @@ describe('bug #3691 — Bug 3: decimal plan IDs (e.g. 02.3-01-PLAN.md) parse cor let tmpDir; afterEach(() => cleanup(tmpDir)); - test('decimal plan ID 02.3-01 is captured fully and matched to the correct wave', (t) => { + test('decimal plan ID 02.3-01 is captured fully and matched to the correct wave', (_t) => { // Pre-fix: `[\w-]+?` stops at `.` → captures `02` only → planData.find misses → wave = 1 for all // Post-fix: `[\w.-]+?` captures `02.3-01` → planData.find resolves → correct wave written const roadmap = [ @@ -238,7 +238,7 @@ describe('bug #3691 — Bug 3: decimal plan IDs (e.g. 02.3-01-PLAN.md) parse cor assert.ok(/Wave 2/.test(written), 'Wave 2 header must appear in output'); }); - test('combined fixture: decimal phase + bold Plans: header (both bugs together)', (t) => { + test('combined fixture: decimal phase + bold Plans: header (both bugs together)', (_t) => { // Exercises Bug 1 (bold **Plans:** header) AND Bug 3 (decimal IDs) simultaneously. // This is the exact ROADMAP fragment from the issue report. const roadmap = [ @@ -280,7 +280,7 @@ describe('review fix F3 — leading-dot plan ID is rejected (defensive guard)', let tmpDir; afterEach(() => cleanup(tmpDir)); - test('checklist line with leading-dot plan ID is skipped and does not silently default to wave 1', (t) => { + test('checklist line with leading-dot plan ID is skipped and does not silently default to wave 1', (_t) => { // Guards: `.invalid-PLAN.md` would be captured as `.invalid` by the `[\w.-]+?` regex // (since `.` is now included), which starts with a dot — an invalid ID. // Without the guard, planData.find() misses it and wave defaults to 1, silently @@ -327,7 +327,7 @@ describe('review fix F4 — adversarial test gaps', () => { let tmpDir; afterEach(() => cleanup(tmpDir)); - test('001.10-PLAN.md multi-decimal leading-zero ID is captured fully and wave-assigned correctly', (t) => { + test('001.10-PLAN.md multi-decimal leading-zero ID is captured fully and wave-assigned correctly', (_t) => { // Guards regression of Bug 3: `[\w-]+?` would stop at the first `.` and // capture `001` instead of `001.10`, which never matches any planData entry. // Post-fix `[\w.-]+?` must capture `001.10` in full. @@ -357,7 +357,7 @@ describe('review fix F4 — adversarial test gaps', () => { 'wave 2 dependency must be resolved from full 001.10-02 ID (not truncated to 001)'); }); - test('**Plans:** (bold, no trailing text) is matched and checklist is processed', (t) => { + test('**Plans:** (bold, no trailing text) is matched and checklist is processed', (_t) => { // Guards the bare-bold variant: `**Plans:**` with nothing after the colon. // The `[^\n]*` quantifier accepts zero chars so this should already work, // but this test would fail if `\*{0,2}Plans\*{0,2}` regressed to require no stars. diff --git a/tests/bug-3707-locked-worktree-cleanup.test.cjs b/tests/bug-3707-locked-worktree-cleanup.test.cjs index fdd2383e0..ee1b1f0c6 100644 --- a/tests/bug-3707-locked-worktree-cleanup.test.cjs +++ b/tests/bug-3707-locked-worktree-cleanup.test.cjs @@ -16,7 +16,6 @@ const { cleanup } = require('./helpers.cjs'); const { executeWorktreeWaveCleanupPlan, - planWorktreeWaveCleanup, reapOrphanWorktrees, } = require('../gsd-core/bin/lib/worktree-safety.cjs'); diff --git a/tests/bug-3735-profiles-core-includes-surface.test.cjs b/tests/bug-3735-profiles-core-includes-surface.test.cjs index ff7a1b96c..6f810a6af 100644 --- a/tests/bug-3735-profiles-core-includes-surface.test.cjs +++ b/tests/bug-3735-profiles-core-includes-surface.test.cjs @@ -13,7 +13,6 @@ const assert = require('node:assert/strict'); const path = require('path'); const { - PROFILES, resolveProfile, loadSkillsManifest, } = require('../gsd-core/bin/lib/install-profiles.cjs'); diff --git a/tests/bug-3739-gap-checker-padded-prefix-context.test.cjs b/tests/bug-3739-gap-checker-padded-prefix-context.test.cjs index b3b98b040..c6b078f51 100644 --- a/tests/bug-3739-gap-checker-padded-prefix-context.test.cjs +++ b/tests/bug-3739-gap-checker-padded-prefix-context.test.cjs @@ -21,20 +21,10 @@ const fs = require('fs'); const path = require('path'); const { runGsdTools, createTempProject, cleanup } = require('./helpers.cjs'); -const REPO_ROOT = path.join(__dirname, '..'); - describe('bug #3739 — gap-analysis padded-prefix CONTEXT.md', () => { let tmpDir; let phaseDir; - function writeRequirements(ids) { - const lines = ids.map((id, i) => `- [ ] **${id}** Requirement ${i + 1}`); - fs.writeFileSync( - path.join(tmpDir, '.planning', 'REQUIREMENTS.md'), - `# Requirements\n\n${lines.join('\n')}\n` - ); - } - function writeContextAs(filename, decisions) { const dLines = decisions.map(d => `- **${d.id}:** ${d.text}`).join('\n'); fs.writeFileSync( diff --git a/tests/bug-376-claude-js-hook-gsd-rewriter.test.cjs b/tests/bug-376-claude-js-hook-gsd-rewriter.test.cjs index 5ef1fea04..12d66b7b1 100644 --- a/tests/bug-376-claude-js-hook-gsd-rewriter.test.cjs +++ b/tests/bug-376-claude-js-hook-gsd-rewriter.test.cjs @@ -32,7 +32,6 @@ const { cleanup } = require('./helpers.cjs'); const REPO_ROOT = path.resolve(__dirname, '..'); const INSTALL_PATH = path.join(REPO_ROOT, 'bin', 'install.js'); const HOOKS_DIST_DIR = path.join(REPO_ROOT, 'hooks', 'dist'); -const HOOKS_SRC_DIR = path.join(REPO_ROOT, 'hooks'); // --------------------------------------------------------------------------- // Helpers diff --git a/tests/bug-3784-gsd-settings-model-profile-ui-omits-adaptive.test.cjs b/tests/bug-3784-gsd-settings-model-profile-ui-omits-adaptive.test.cjs index 245108796..36ddfb7c6 100644 --- a/tests/bug-3784-gsd-settings-model-profile-ui-omits-adaptive.test.cjs +++ b/tests/bug-3784-gsd-settings-model-profile-ui-omits-adaptive.test.cjs @@ -184,7 +184,6 @@ describe('bug #3784: settings.md model profile UI exposes all 5 profiles', () => // commit bd53925f fixed a duplicate '{' introduced by 35fc1d21 when the model-profile // AskUserQuestion was split into Q1+Q2. This test guards against a recurrence. let depth = 0; - const maxDepth = 0; for (const ch of presentBlock) { if (ch === '{') { depth++; } if (ch === '}') { depth--; } diff --git a/tests/bug-474-clock-seam-date-determinism.test.cjs b/tests/bug-474-clock-seam-date-determinism.test.cjs index e1efa2403..9d3f0d328 100644 --- a/tests/bug-474-clock-seam-date-determinism.test.cjs +++ b/tests/bug-474-clock-seam-date-determinism.test.cjs @@ -14,7 +14,7 @@ * the clock seam (in-process, using makeFakeClock — no subprocess needed). */ -const { describe, it, test, before, after } = require('node:test'); +const { describe, test, before, after } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); diff --git a/tests/bug-492-effort-manifest-fallback.test.cjs b/tests/bug-492-effort-manifest-fallback.test.cjs index 478d5e31a..4e504dd56 100644 --- a/tests/bug-492-effort-manifest-fallback.test.cjs +++ b/tests/bug-492-effort-manifest-fallback.test.cjs @@ -4,9 +4,8 @@ process.env.GSD_TEST_MODE = "1"; const { describe, test, beforeEach, afterEach } = require("node:test"); const assert = require("node:assert/strict"); -const path = require("path"); const { createTempProject, cleanup } = require("./helpers.cjs"); -const { resolveEffortInternal, CONFIG_DEFAULTS } = require("../gsd-core/bin/lib/core.cjs"); +const { resolveEffortInternal } = require("../gsd-core/bin/lib/core.cjs"); const { CONFIG_DEFAULTS: CANONICAL_CONFIG_DEFAULTS } = require("../gsd-core/bin/lib/configuration.cjs"); describe("#492 manifest effort fallback", () => { diff --git a/tests/bug-570-codex-leak-scanner.test.cjs b/tests/bug-570-codex-leak-scanner.test.cjs index 127035a25..e0ad8b186 100644 --- a/tests/bug-570-codex-leak-scanner.test.cjs +++ b/tests/bug-570-codex-leak-scanner.test.cjs @@ -30,7 +30,6 @@ const { execFileSync } = require('node:child_process'); const { install, - writeManifest, convertClaudeCommandToCodexSkill, } = require('../bin/install.js'); const { createTempDir, cleanup, captureConsole } = require('./helpers.cjs'); diff --git a/tests/changeset-cli.test.cjs b/tests/changeset-cli.test.cjs index 852354122..03ed3b5e5 100644 --- a/tests/changeset-cli.test.cjs +++ b/tests/changeset-cli.test.cjs @@ -93,7 +93,7 @@ function runExtract(args = [], changelogText = null) { } describe('changeset cli extract: version-range changelog extraction (#3496)', () => { - test('exits 2 with no output when no versions fall in range', (t) => { + test('exits 2 with no output when no versions fall in range', (_t) => { const r = runExtract(['--from', '1.5.15', '--to', '1.5.15', '--json'], EXTRACT_CHANGELOG); assert.equal(r.status, 2, `expected exit 2 for empty range, stderr=${r.stderr}`); // F11: assert JSON structure is present and releases is empty array @@ -101,7 +101,7 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () assert.strictEqual(r.json.releases.length, 0, 'releases must be empty array on exit 2'); }); - test('extracts versions strictly after from and up to and including to', (t) => { + test('extracts versions strictly after from and up to and including to', (_t) => { const r = runExtract(['--from', '1.5.13', '--to', '1.5.15', '--json'], EXTRACT_CHANGELOG); assert.equal(r.status, 0, `stderr=${r.stderr}`); assert.ok(r.json, 'stdout must be valid JSON'); @@ -112,7 +112,7 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () assert.ok(!versions.includes('1.5.10'), '1.5.10 must NOT be in range (below from)'); }); - test('accepts v-prefixed version arguments', (t) => { + test('accepts v-prefixed version arguments', (_t) => { const r = runExtract(['--from', 'v1.5.13', '--to', 'v1.5.15', '--json'], EXTRACT_CHANGELOG); assert.equal(r.status, 0, `stderr=${r.stderr}`); assert.ok(r.json, 'stdout must be valid JSON'); @@ -122,7 +122,7 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () assert.ok(!versions.includes('1.5.13')); }); - test('captures multi-line bullets in extracted range', (t) => { + test('captures multi-line bullets in extracted range', (_t) => { const r = runExtract(['--from', '1.5.13', '--to', '1.5.14', '--json'], EXTRACT_CHANGELOG); assert.equal(r.status, 0, `stderr=${r.stderr}`); const release = r.json.releases.find((rel) => rel.version === '1.5.14'); @@ -132,7 +132,7 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () assert.ok(prs.includes(102), 'multi-line bullet pr=102 must be captured'); }); - test('emits markdown text (non-JSON) when --json is not passed', (t) => { + test('emits markdown text (non-JSON) when --json is not passed', (_t) => { // Without --json the output is human-readable markdown, not JSON. // Assert on structural facts derivable from the text: exactly the two // matched releases appear as ## headers, using parseChangelog so we @@ -149,13 +149,13 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () assert.ok(!versions.includes('1.5.13'), '1.5.13 must not appear in output (excluded by --from)'); }); - test('missing --from or --to emits usage and exits non-zero', (t) => { + test('missing --from or --to emits usage and exits non-zero', (_t) => { const r = runExtract(['--from', '1.0.0'], EXTRACT_CHANGELOG); assert.notEqual(r.status, 0); assert.ok(r.stderr.length > 0 || r.stdout.length > 0, 'must emit usage text'); }); - test('rejects malformed --from semver (non-numeric component) with exit 1', (t) => { + test('rejects malformed --from semver (non-numeric component) with exit 1', (_t) => { const r = runExtract(['--from', '1.41.x', '--to', '1.5.15', '--json'], EXTRACT_CHANGELOG); assert.equal(r.status, 1, `expected exit 1 for malformed --from, stderr=${r.stderr}`); assert.ok(r.json, 'stdout must be valid JSON on error'); @@ -163,7 +163,7 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () assert.ok(r.json.error.includes('--from'), 'error must mention --from'); }); - test('rejects malformed --to semver (alphabetic) with exit 1', (t) => { + test('rejects malformed --to semver (alphabetic) with exit 1', (_t) => { const r = runExtract(['--from', '1.5.13', '--to', 'foo', '--json'], EXTRACT_CHANGELOG); assert.equal(r.status, 1, `expected exit 1 for malformed --to, stderr=${r.stderr}`); assert.ok(r.json, 'stdout must be valid JSON on error'); @@ -171,7 +171,7 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () assert.ok(r.json.error.includes('--to'), 'error must mention --to'); }); - test('preserves bullets without PR trailer in extracted output', (t) => { + test('preserves bullets without PR trailer in extracted output', (_t) => { // Fixture with one no-PR bullet and one PR bullet. const CHANGELOG_NO_PR = [ '# Changelog', @@ -196,7 +196,7 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () }); // F2: pre-release entries must be excluded from range queries - test('F2: pre-release entry 1.0.0-rc.1 is excluded from range --from 0.9.9 --to 1.0.0', (t) => { + test('F2: pre-release entry 1.0.0-rc.1 is excluded from range --from 0.9.9 --to 1.0.0', (_t) => { const CHANGELOG_WITH_PRERELEASE = [ '# Changelog', '', @@ -228,7 +228,7 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () }); // F3: linked-header format ## [1.42.1](url) - date must parse date correctly - test('F3: linked-header ## [1.42.1](url) - date parses date correctly', (t) => { + test('F3: linked-header ## [1.42.1](url) - date parses date correctly', (_t) => { const CHANGELOG_LINKED = [ '# Changelog', '', @@ -255,7 +255,7 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () }); // F4: nested bullets must remain as separate bullets, not fold into parent - test('F4: nested bullets are not folded into parent bullet', (t) => { + test('F4: nested bullets are not folded into parent bullet', (_t) => { const CHANGELOG_NESTED = [ '# Changelog', '', @@ -283,7 +283,7 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () }); // F5+F6: 4-part headers and v-prefix in-file headers - test('F5+F6: 4-part version in CHANGELOG is skipped, v-prefixed version parses without v', (t) => { + test('F5+F6: 4-part version in CHANGELOG is skipped, v-prefixed version parses without v', (_t) => { const CHANGELOG_EDGE = [ '# Changelog', '', @@ -324,7 +324,7 @@ describe('changeset cli extract: version-range changelog extraction (#3496)', () // F1: workflows/update.md must reference the extract subcommand invocation. // allow-test-rule: reads a product workflow .md file (not CJS source) to verify // the user-facing instruction was wired; there is no behavioural runtime to invoke. - test('F1: workflows/update.md contains concrete extract subcommand invocation', (t) => { + test('F1: workflows/update.md contains concrete extract subcommand invocation', (_t) => { const workflowPath = path.join(ROOT, 'gsd-core', 'workflows', 'update.md'); const workflowText = fs.readFileSync(workflowPath, 'utf8'); // The invocation is: node "$GSD_DIR/gsd-core/scripts/changeset/cli.cjs" extract diff --git a/tests/claude-skills-migration.test.cjs b/tests/claude-skills-migration.test.cjs index 23813d3df..fbfd8e0fb 100644 --- a/tests/claude-skills-migration.test.cjs +++ b/tests/claude-skills-migration.test.cjs @@ -25,7 +25,6 @@ const ROOT = path.join(__dirname, '..'); const { convertClaudeCommandToClaudeSkill, writeManifest, - install, installRuntimeArtifacts, uninstallRuntimeArtifacts, } = require(path.join(ROOT, 'bin', 'install.js')); diff --git a/tests/clock-seam.test.cjs b/tests/clock-seam.test.cjs index 43a5593a2..dfa98b058 100644 --- a/tests/clock-seam.test.cjs +++ b/tests/clock-seam.test.cjs @@ -34,12 +34,11 @@ const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const os = require('node:os'); -const { spawnSync } = require('node:child_process'); const { makeFakeClock } = require('./helpers/clock.cjs'); const { acquireStateLock, releaseStateLock, readModifyWriteStateMd } = require('../gsd-core/bin/lib/state.cjs'); const { withPlanningLock } = require('../gsd-core/bin/lib/planning-workspace.cjs'); -const { createTempProject, cleanup, runGsdTools, TOOLS_PATH } = require('./helpers.cjs'); +const { createTempProject, cleanup, runGsdTools } = require('./helpers.cjs'); // ───────────────────────────────────────────────────────────────────────────── // 1. Fake-clock proof: acquireStateLock accepts and uses the clock seam @@ -209,10 +208,6 @@ describe('withPlanningLock clock seam', () => { // Clock that advances past lockTimeout on every sleep call so the while // condition trips immediately after the first retry. let nowValue = 0; - const clock = { - now() { return nowValue; }, - sleep(ms) { nowValue += ms + 11000; }, // jump past lockTimeout on every sleep - }; // withPlanningLock exits the while loop (timeout), deletes the lock, then // calls runWithHeldLock() which tries writeFileSync with { flag: 'wx' }. diff --git a/tests/code-review-command.test.cjs b/tests/code-review-command.test.cjs index 349415453..487c35c80 100644 --- a/tests/code-review-command.test.cjs +++ b/tests/code-review-command.test.cjs @@ -10,7 +10,7 @@ * wired into config, templates, and the ship workflow. */ -const { describe, test, beforeEach, afterEach } = require('node:test'); +const { describe, test } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); diff --git a/tests/concurrency-safety.test.cjs b/tests/concurrency-safety.test.cjs index 3d0725a17..9dff9ecc0 100644 --- a/tests/concurrency-safety.test.cjs +++ b/tests/concurrency-safety.test.cjs @@ -20,7 +20,6 @@ const { test, describe, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); -const os = require('os'); const { runGsdTools, createTempProject, cleanup } = require('./helpers.cjs'); const { normalizeContent } = require('../gsd-core/bin/lib/shell-command-projection.cjs'); @@ -31,13 +30,6 @@ const normalizeMd = (input) => normalizeContent('test.md', input).content; // ─── Helpers ──────────────────────────────────────────────────────────────── -function writeMinimalRoadmap(tmpDir, phases = ['1']) { - const lines = phases.map(n => `### Phase ${n}: Phase ${n} Description`).join('\n'); - fs.writeFileSync( - path.join(tmpDir, '.planning', 'ROADMAP.md'), - `# Roadmap\n\n${lines}\n` - ); -} function writeMinimalStateMd(tmpDir, content) { const defaultContent = content || `# Session State\n\n## Current Position\n\nPhase: 1\n`; @@ -47,22 +39,6 @@ function writeMinimalStateMd(tmpDir, content) { ); } -function writeMinimalProjectMd(tmpDir) { - const sections = ['## What This Is', '## Core Value', '## Requirements']; - const content = sections.map(s => `${s}\n\nContent here.\n`).join('\n'); - fs.writeFileSync( - path.join(tmpDir, '.planning', 'PROJECT.md'), - `# Project\n\n${content}` - ); -} - -function writeValidConfigJson(tmpDir, overrides = {}) { - const base = { model_profile: 'balanced', commit_docs: true }; - fs.writeFileSync( - path.join(tmpDir, '.planning', 'config.json'), - JSON.stringify({ ...base, ...overrides }, null, 2) - ); -} /** * Generate a 50-phase project structure for stress testing. diff --git a/tests/copilot-install.test.cjs b/tests/copilot-install.test.cjs index b97271832..86aff0d9a 100644 --- a/tests/copilot-install.test.cjs +++ b/tests/copilot-install.test.cjs @@ -891,8 +891,6 @@ describe('Copilot content conversion - engine files', () => { // ─── Copilot instructions merge/strip ────────────────────────────────────────── describe('Copilot instructions merge/strip', () => { - let tmpDir; - const gsdContent = '- Follow project conventions\n- Use structured workflows'; function makeGsdBlock(content) { @@ -1127,7 +1125,7 @@ describe('Copilot manifest and patches fixes', () => { fs.mkdirSync(skillDir, { recursive: true }); fs.writeFileSync(path.join(skillDir, 'SKILL.md'), '# Test Skill\n\nA test skill.'); - const manifest = writeManifest(tmpDir, 'copilot'); + writeManifest(tmpDir, 'copilot'); // Check manifest file was written const manifestPath = path.join(tmpDir, 'gsd-file-manifest.json'); diff --git a/tests/core.test.cjs b/tests/core.test.cjs index 9b51147bf..750625ddd 100644 --- a/tests/core.test.cjs +++ b/tests/core.test.cjs @@ -22,9 +22,7 @@ const { resolveModelInternal, escapeRegex, generateSlugInternal, - normalizePhaseName, reapStaleTempFiles, - comparePhaseNum, pathExistsInternal, getMilestoneInfo, getMilestonePhaseFilter, diff --git a/tests/cursor-reviewer.test.cjs b/tests/cursor-reviewer.test.cjs index e185cd528..a62c073f2 100644 --- a/tests/cursor-reviewer.test.cjs +++ b/tests/cursor-reviewer.test.cjs @@ -29,11 +29,11 @@ describe('Cursor CLI reviewer in /gsd-review (#1960)', () => { describe('review.md workflow', () => { const reviewPath = path.join(ROOT, 'gsd-core', 'workflows', 'review.md'); - let content; + let _content; test('review.md exists', () => { assert.ok(fs.existsSync(reviewPath), 'review.md should exist'); - content = fs.readFileSync(reviewPath, 'utf-8'); + _content = fs.readFileSync(reviewPath, 'utf-8'); }); test('contains cursor CLI detection via command -v cursor-agent', () => { @@ -220,7 +220,6 @@ describe('Cursor CLI reviewer in /gsd-review (#1960)', () => { }); test('mentions Cursor in the review section', () => { - const c = fs.readFileSync(jaPath, 'utf-8'); assert.ok( /Cursor/i.test(fs.readFileSync(jaPath, 'utf-8')), 'docs/ja-JP/FEATURES.md should mention Cursor in the review section' @@ -254,7 +253,6 @@ describe('Cursor CLI reviewer in /gsd-review (#1960)', () => { }); test('mentions Cursor in the review section', () => { - const c = fs.readFileSync(koPath, 'utf-8'); assert.ok( /Cursor/i.test(fs.readFileSync(koPath, 'utf-8')), 'docs/ko-KR/FEATURES.md should mention Cursor in the review section' diff --git a/tests/dispatch/trace-correlation.test.cjs b/tests/dispatch/trace-correlation.test.cjs index 4f4d224b0..6c8a8ee1c 100644 --- a/tests/dispatch/trace-correlation.test.cjs +++ b/tests/dispatch/trace-correlation.test.cjs @@ -181,7 +181,7 @@ describe('trace correlation — end-to-end parentTraceId propagation', () => { const allEvents = readJsonl(isolatedAuditPath); assert.equal(allEvents.length, 3, 'must have 3 events total (root + valid child + invalid child)'); - const [root, validChild, invalidChild] = allEvents; + const [, validChild, invalidChild] = allEvents; // Valid child carries the correct parentTraceId assert.strictEqual(validChild.parentTraceId, rootTraceId, diff --git a/tests/docs-parity-live-registry.test.cjs b/tests/docs-parity-live-registry.test.cjs index fc241a2bb..c45ba5a35 100644 --- a/tests/docs-parity-live-registry.test.cjs +++ b/tests/docs-parity-live-registry.test.cjs @@ -309,10 +309,6 @@ describe('getLiveCommandTokens() — helper contract', () => { test('contains exactly 3 tokens per slug (slash, colon, dollar)', () => { const result = getLiveCommandTokens(); // Every /gsd-slug should have a matching /gsd:slug and $gsd-slug - let tokenCount = 0; - for (const token of result) { - if (token.startsWith('/gsd-')) tokenCount++; - } const slashTokens = [...result].filter(t => t.startsWith('/gsd-')); for (const slash of slashTokens) { const slug = slash.slice('/gsd-'.length); diff --git a/tests/enh-2430-learnings-consumption.test.cjs b/tests/enh-2430-learnings-consumption.test.cjs index 92902e1aa..d1a70501f 100644 --- a/tests/enh-2430-learnings-consumption.test.cjs +++ b/tests/enh-2430-learnings-consumption.test.cjs @@ -35,7 +35,7 @@ describe('enh-2430 Part A — plan-phase LEARNINGS.md context load', () => { test('plan-phase.md LEARNINGS load is inside the 1M context-window gate', () => { content = content || readWorkflow('plan-phase.md'); - const windowBlock = content.match(/\$\{CONTEXT_WINDOW >= 500000[\s\S]*?\` : ''\}/); + const windowBlock = content.match(/\$\{CONTEXT_WINDOW >= 500000[\s\S]*?` : ''\}/); assert.ok(windowBlock, 'CONTEXT_WINDOW gate block must exist'); assert.ok( windowBlock[0].includes('LEARNINGS.md'), @@ -62,7 +62,7 @@ describe('enh-2430 Part A — plan-phase LEARNINGS.md context load', () => { test('plan-phase.md LEARNINGS load includes Depends-on chain', () => { content = content || readWorkflow('plan-phase.md'); - const dependsSection = content.match(/Depends on.*?(\n.*?)+/); + content.match(/Depends on.*?(\n.*?)+/); assert.ok( content.includes('LEARNINGS.md from any phases listed in'), 'plan-phase.md must load LEARNINGS.md for Depends on chain phases' diff --git a/tests/enh-2447-roadmap-wave-deps.test.cjs b/tests/enh-2447-roadmap-wave-deps.test.cjs index cd2163e45..7aec5ddd5 100644 --- a/tests/enh-2447-roadmap-wave-deps.test.cjs +++ b/tests/enh-2447-roadmap-wave-deps.test.cjs @@ -8,7 +8,7 @@ * Tests for ROADMAP wave dependency surfacing (#2447). */ -const { test, describe, beforeEach, afterEach } = require('node:test'); +const { test, describe, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); diff --git a/tests/feat-3024-dynamic-routing.test.cjs b/tests/feat-3024-dynamic-routing.test.cjs index 947a97754..86ce52fc1 100644 --- a/tests/feat-3024-dynamic-routing.test.cjs +++ b/tests/feat-3024-dynamic-routing.test.cjs @@ -46,8 +46,6 @@ const { test, describe, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); -const os = require('node:os'); - const { resolveModelInternal, resolveModelForTier, diff --git a/tests/feat-3593-cli-negative-config.test.cjs b/tests/feat-3593-cli-negative-config.test.cjs index 1d80694c7..46c612006 100644 --- a/tests/feat-3593-cli-negative-config.test.cjs +++ b/tests/feat-3593-cli-negative-config.test.cjs @@ -285,7 +285,7 @@ for (const payload of SHELL_PAYLOADS) { // ─── Cross-cutting: --cwd points at a non-existent path ──────────────────── -test('--cwd pointing at a non-existent path fails with a typed usage reason', (t) => { +test('--cwd pointing at a non-existent path fails with a typed usage reason', (_t) => { const nonExistent = path.join(require('os').tmpdir(), 'cli-neg-no-such-dir-' + Date.now() + '-' + Math.random()); assert.equal(fs.existsSync(nonExistent), false, 'pre-check: path must not exist'); const result = runCli(['--cwd', nonExistent, 'config-get', 'model_profile'], { cwd: process.cwd() }); diff --git a/tests/feat-3595-fs-fault-injection-atomic-write.test.cjs b/tests/feat-3595-fs-fault-injection-atomic-write.test.cjs index a155d2759..6e4e20b69 100644 --- a/tests/feat-3595-fs-fault-injection-atomic-write.test.cjs +++ b/tests/feat-3595-fs-fault-injection-atomic-write.test.cjs @@ -37,8 +37,6 @@ const { test, mock } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); -const os = require('node:os'); - const { platformWriteSync, platformEnsureDir, @@ -83,7 +81,7 @@ test('platformWriteSync recovers when renameSync fails (EXDEV cross-device fallb // Simulate rename failing once (e.g. cross-device move on a CI runner // with overlayfs). The fallback path must write the content directly. let renameCalls = 0; - const renameMock = mock.method(fs, 'renameSync', (src, dest) => { + const renameMock = mock.method(fs, 'renameSync', (_src, _dest) => { renameCalls++; const err = new Error('EXDEV: cross-device link not permitted'); err.code = 'EXDEV'; diff --git a/tests/feat-443-effort-fast-mode.test.cjs b/tests/feat-443-effort-fast-mode.test.cjs index 2041466e3..d9f56a83f 100644 --- a/tests/feat-443-effort-fast-mode.test.cjs +++ b/tests/feat-443-effort-fast-mode.test.cjs @@ -19,7 +19,7 @@ const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); -const { createTempProject, createTempDir, cleanup, runGsdTools } = require('./helpers.cjs'); +const { createTempProject, cleanup, runGsdTools } = require('./helpers.cjs'); const { resolveEffortInternal, diff --git a/tests/feat-49-model-policy-presets.test.cjs b/tests/feat-49-model-policy-presets.test.cjs index 9e0583383..e034ee83a 100644 --- a/tests/feat-49-model-policy-presets.test.cjs +++ b/tests/feat-49-model-policy-presets.test.cjs @@ -55,7 +55,6 @@ const { test, describe, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); -const os = require('node:os'); // ─── Imports (will fail until implementation exists) ──────────────────────── // resolveModelPolicy is a new internal function that must be exported from core.cjs. diff --git a/tests/frontmatter.test.cjs b/tests/frontmatter.test.cjs index 20347d123..6acb7cae0 100644 --- a/tests/frontmatter.test.cjs +++ b/tests/frontmatter.test.cjs @@ -16,7 +16,6 @@ const { reconstructFrontmatter, spliceFrontmatter, parseMustHavesBlock, - FRONTMATTER_SCHEMAS, } = require('../gsd-core/bin/lib/frontmatter.cjs'); // ─── extractFrontmatter ───────────────────────────────────────────────────── diff --git a/tests/graphify-visualization.test.cjs b/tests/graphify-visualization.test.cjs index ee0a7aad4..b4b3dfc6a 100644 --- a/tests/graphify-visualization.test.cjs +++ b/tests/graphify-visualization.test.cjs @@ -214,7 +214,7 @@ describe('mvp-viz', () => { function parseSkillFrontmatter(text) { const lines = text.split(/\r?\n/); const out = {}; - let activeKey = null; + let _activeKey = null; let activeList = null; for (const raw of lines) { const listItem = raw.match(/^\s+-\s+(.+?)\s*$/); @@ -227,11 +227,11 @@ describe('mvp-viz', () => { const [, key, rawValue] = kv; const value = rawValue.trim(); if (value === '') { - activeKey = key; + _activeKey = key; activeList = []; out[key] = activeList; } else { - activeKey = null; + _activeKey = null; activeList = null; out[key] = value; } @@ -365,7 +365,7 @@ describe('regressions', () => { function parseBug3166SkillFrontmatter(text) { const lines = text.split(/\r?\n/); const out = {}; - let activeKey = null; + let _activeKey = null; let activeList = null; for (const raw of lines) { const listItem = raw.match(/^\s+-\s+(.+?)\s*$/); @@ -378,11 +378,11 @@ describe('regressions', () => { const [, key, rawValue] = kv; const value = rawValue.trim(); if (value === '') { - activeKey = key; + _activeKey = key; activeList = []; out[key] = activeList; } else { - activeKey = null; + _activeKey = null; activeList = null; out[key] = value; } diff --git a/tests/gsd2-import.test.cjs b/tests/gsd2-import.test.cjs index 0699ad97b..16a26a34d 100644 --- a/tests/gsd2-import.test.cjs +++ b/tests/gsd2-import.test.cjs @@ -4,14 +4,13 @@ // Reads .md/.json/.yml product files whose deployed text IS what the // runtime loads — testing text content tests the deployed contract. -const { describe, it, test, beforeEach, afterEach } = require('node:test'); +const { describe, test, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const { createTempDir, cleanup, runGsdTools } = require('./helpers.cjs'); const { - findGsd2Root, parseSlicesFromRoadmap, parseMilestoneTitle, parseTaskTitle, diff --git a/tests/hardcoded-paths.test.cjs b/tests/hardcoded-paths.test.cjs index b9277299f..ed7b84533 100644 --- a/tests/hardcoded-paths.test.cjs +++ b/tests/hardcoded-paths.test.cjs @@ -55,7 +55,7 @@ const sourceFiles = sourceDirs.flatMap(collectSourceFiles); * Scan files for a pattern, skipping comment lines. * Returns an array of human-readable failure strings. */ -function scanFiles(files, pattern, description) { +function scanFiles(files, pattern, _description) { const failures = []; for (const file of files) { const content = fs.readFileSync(file, 'utf8'); diff --git a/tests/health-validation.test.cjs b/tests/health-validation.test.cjs index e59eb5dbc..b542bcdeb 100644 --- a/tests/health-validation.test.cjs +++ b/tests/health-validation.test.cjs @@ -354,7 +354,6 @@ describe('stateReplaceFieldWithFallback field-miss warning', () => { } roadmapContent += '\n'; for (let i = 1; i <= 50; i++) { - const pad = String(i).padStart(2, '0'); roadmapContent += `### Phase ${i}: Feature ${i}\n\n**Goal:** Build feature ${i}\n**Plans:** 1 plans\n\n`; } fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), roadmapContent); diff --git a/tests/helpers-cleanup.test.cjs b/tests/helpers-cleanup.test.cjs index 16b6e517e..b876c5e9a 100644 --- a/tests/helpers-cleanup.test.cjs +++ b/tests/helpers-cleanup.test.cjs @@ -9,7 +9,6 @@ const { test } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); -const os = require('os'); const { cleanup, createTempDir } = require('./helpers.cjs'); diff --git a/tests/install-minimal-hooks.test.cjs b/tests/install-minimal-hooks.test.cjs index 3d2e4b6ce..4a6d1fa1c 100644 --- a/tests/install-minimal-hooks.test.cjs +++ b/tests/install-minimal-hooks.test.cjs @@ -44,8 +44,6 @@ const { shouldInstallSkill, stageSkillsForMode, cleanupStagedSkills, - loadSkillsManifest, - resolveProfile, } = require('../gsd-core/bin/lib/install-profiles.cjs'); const { diff --git a/tests/install-path-detection.test.cjs b/tests/install-path-detection.test.cjs index 1d033bb2b..d6dbe731a 100644 --- a/tests/install-path-detection.test.cjs +++ b/tests/install-path-detection.test.cjs @@ -10,7 +10,7 @@ 'use strict'; -const { test, describe, before, after } = require('node:test'); +const { test, describe, before } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const os = require('os'); diff --git a/tests/install.test.cjs b/tests/install.test.cjs index 352a29e9f..3ac6e72c8 100644 --- a/tests/install.test.cjs +++ b/tests/install.test.cjs @@ -48,7 +48,6 @@ const { const { RUNTIME_META, - SKILL_RUNTIMES, stripAnsi, walk, } = require('./helpers/install-shared.cjs'); diff --git a/tests/installer-migration-install-integration.test.cjs b/tests/installer-migration-install-integration.test.cjs index 6d431d924..2f4f79dc4 100644 --- a/tests/installer-migration-install-integration.test.cjs +++ b/tests/installer-migration-install-integration.test.cjs @@ -174,14 +174,6 @@ function assertHasGsdDirectory(root, relPath) { ); } -function assertNoGsdDirectoryEntries(root, relPath) { - assert.equal( - listDirNames(root, relPath).some((name) => name.startsWith('gsd-')), - false, - `${relPath} should not contain generated GSD entries` - ); -} - function assertFreshInstallContract(runtime, targetDir) { const contract = RUNTIME_INSTALL_CONTRACTS[runtime]; assert.ok(contract, `missing runtime install contract for ${runtime}`); diff --git a/tests/installer-migration-rename-gsd-core.test.cjs b/tests/installer-migration-rename-gsd-core.test.cjs index 3bfa06369..d2e2b53d6 100644 --- a/tests/installer-migration-rename-gsd-core.test.cjs +++ b/tests/installer-migration-rename-gsd-core.test.cjs @@ -13,7 +13,7 @@ * 5. unknown user file under legacy dir -> baseline-preserve-user (NOT removed) */ -const { describe, test, before } = require('node:test'); +const { describe, test } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const os = require('node:os'); diff --git a/tests/intel.test.cjs b/tests/intel.test.cjs index 9dfe78ef9..1a388dd13 100644 --- a/tests/intel.test.cjs +++ b/tests/intel.test.cjs @@ -25,7 +25,6 @@ const { intelApiSurface, ensureIntelDir, isIntelEnabled, - INTEL_FILES, } = require('../gsd-core/bin/lib/intel.cjs'); // ─── Helpers ──────────────────────────────────────────────────────────────── @@ -49,7 +48,7 @@ function writeIntelJson(planningDir, filename, data) { ); } -function writeIntelMd(planningDir, filename, content) { +function _writeIntelMd(planningDir, filename, content) { const intelPath = path.join(planningDir, 'intel'); fs.mkdirSync(intelPath, { recursive: true }); fs.writeFileSync(path.join(intelPath, filename), content, 'utf8'); diff --git a/tests/lint-test-file-count.test.cjs b/tests/lint-test-file-count.test.cjs index c16bcc8e5..c34b12bad 100644 --- a/tests/lint-test-file-count.test.cjs +++ b/tests/lint-test-file-count.test.cjs @@ -9,8 +9,6 @@ const { describe, test } = require('node:test'); const assert = require('node:assert/strict'); -const fs = require('fs'); -const os = require('os'); const path = require('path'); const { spawnSync } = require('child_process'); diff --git a/tests/locking-bugs-1909-1916-1925-1927.test.cjs b/tests/locking-bugs-1909-1916-1925-1927.test.cjs index 8d99a39cb..caf8f2418 100644 --- a/tests/locking-bugs-1909-1916-1925-1927.test.cjs +++ b/tests/locking-bugs-1909-1916-1925-1927.test.cjs @@ -19,15 +19,10 @@ const { test, describe, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); -const os = require('os'); -const { execFileSync, execSync, spawn } = require('child_process'); -const { promisify } = require('util'); -const { exec } = require('child_process'); +const { spawn } = require('child_process'); const { runGsdTools, createTempProject, cleanup, TOOLS_PATH } = require('./helpers.cjs'); -const execAsync = promisify(exec); - // ───────────────────────────────────────────────────────────────────────────── // Helpers // ───────────────────────────────────────────────────────────────────────────── diff --git a/tests/milestone-summary.test.cjs b/tests/milestone-summary.test.cjs index 672e31c26..07a0e1171 100644 --- a/tests/milestone-summary.test.cjs +++ b/tests/milestone-summary.test.cjs @@ -163,9 +163,6 @@ describe('milestone-summary command structure', () => { }); describe('milestone-summary artifact path resolution', () => { - const { createTempProject, cleanup } = require('./helpers.cjs'); - let tmpDir; - test('archived milestone paths point to milestones/ directory', () => { const content = fs.readFileSync(workflowPath, 'utf-8'); // Archived roadmap path should be under milestones/ @@ -326,7 +323,7 @@ describe('milestone-summary git stats resilience', () => { // ───────────────────────────────────────────────────────────────────────────── describe('audit.cjs module (#2158)', () => { - const { createTempProject: createTP, cleanup: cleanTP, runGsdTools: run } = require('./helpers.cjs'); + const { createTempProject: createTP, cleanup: cleanTP } = require('./helpers.cjs'); let tmpDir; beforeEach(() => { tmpDir = createTP('audit-test'); }); diff --git a/tests/next-up-clear-order.test.cjs b/tests/next-up-clear-order.test.cjs index 83932eadd..405c41c38 100644 --- a/tests/next-up-clear-order.test.cjs +++ b/tests/next-up-clear-order.test.cjs @@ -17,7 +17,6 @@ const { test, describe } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); -const glob = require('path'); const GSD_ROOT = path.join(__dirname, '..', 'gsd-core'); const UI_BRAND = path.join(GSD_ROOT, 'references', 'ui-brand.md'); diff --git a/tests/observability/event.test.cjs b/tests/observability/event.test.cjs index c07932f75..9572116d3 100644 --- a/tests/observability/event.test.cjs +++ b/tests/observability/event.test.cjs @@ -7,7 +7,7 @@ * observable behaviour (return values). No mocks, no vacuous truths. */ -const { describe, test, beforeEach, afterEach } = require('node:test'); +const { describe, test } = require('node:test'); const assert = require('node:assert/strict'); const { diff --git a/tests/observability/hub-logger-integration.test.cjs b/tests/observability/hub-logger-integration.test.cjs index 6bc2d1536..8e6b0d995 100644 --- a/tests/observability/hub-logger-integration.test.cjs +++ b/tests/observability/hub-logger-integration.test.cjs @@ -22,12 +22,10 @@ const os = require('os'); const { createHub, - ERROR_KINDS, } = require('../../gsd-core/bin/lib/command-routing-hub.cjs'); const { createDefaultLogger, - createNoOpLogger, } = require('../../gsd-core/bin/lib/observability/logger.cjs'); const { cleanup } = require('../helpers.cjs'); diff --git a/tests/package-legitimacy-gate.test.cjs b/tests/package-legitimacy-gate.test.cjs index 53bfc18ca..186d1d609 100644 --- a/tests/package-legitimacy-gate.test.cjs +++ b/tests/package-legitimacy-gate.test.cjs @@ -105,7 +105,7 @@ function normalizeTokens(text) { return text .toLowerCase() .replace(/https?:\/\//g, ' ') - .replace(/[\[\]]/g, '') + .replace(/[[\]]/g, '') .replace(/[^a-z0-9{}:_-]+/g, ' ') .trim() .split(/\s+/) diff --git a/tests/package-name-single-source.test.cjs b/tests/package-name-single-source.test.cjs index 4a50948a6..8d3f5ba21 100644 --- a/tests/package-name-single-source.test.cjs +++ b/tests/package-name-single-source.test.cjs @@ -21,7 +21,6 @@ const { test } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); -const { execSync } = require('node:child_process'); const ROOT = path.join(__dirname, '..'); const LITERAL = '@opengsd/gsd-core'; diff --git a/tests/phase-command-router.test.cjs b/tests/phase-command-router.test.cjs index 8896fe913..ff320d896 100644 --- a/tests/phase-command-router.test.cjs +++ b/tests/phase-command-router.test.cjs @@ -104,7 +104,7 @@ describe('phase-command-router — CLI arg translation (CJS path)', () => { test('routes phase add-batch: --descriptions JSON array parses correctly', () => { const calls = []; const phase = makePhase({ - cmdPhaseAddBatch: (cwd, descriptions, raw) => calls.push({ descriptions }), + cmdPhaseAddBatch: (cwd, descriptions, _raw) => calls.push({ descriptions }), }); routePhaseCommand({ @@ -121,7 +121,7 @@ describe('phase-command-router — CLI arg translation (CJS path)', () => { test('routes phase add-batch: positional args used when --descriptions absent', () => { const calls = []; const phase = makePhase({ - cmdPhaseAddBatch: (cwd, descriptions, raw) => calls.push({ descriptions }), + cmdPhaseAddBatch: (cwd, descriptions, _raw) => calls.push({ descriptions }), }); routePhaseCommand({ @@ -162,7 +162,7 @@ describe('phase-command-router — CLI arg translation (CJS path)', () => { test('routes phase remove: --force flag sets opts.force:true', () => { const calls = []; const phase = makePhase({ - cmdPhaseRemove: (cwd, phaseNum, opts, raw) => calls.push({ opts }), + cmdPhaseRemove: (cwd, phaseNum, opts, _raw) => calls.push({ opts }), }); routePhaseCommand({ phase, args: ['phase', 'remove', '--force', '03'], cwd: '/p', raw: false, error: (m) => { throw new Error(m); } }); @@ -402,7 +402,7 @@ describe('phase-command-router — integration: real hub + CJS phase handler', ( test('dispatches phase add-batch through real hub with --descriptions', () => { const calls = []; const phase = makePhase({ - cmdPhaseAddBatch: (cwd, descriptions, raw) => calls.push({ descriptions }), + cmdPhaseAddBatch: (cwd, descriptions, _raw) => calls.push({ descriptions }), }); let errorMsg = null; diff --git a/tests/phase.test.cjs b/tests/phase.test.cjs index c1c01ccea..08f0e0a7b 100644 --- a/tests/phase.test.cjs +++ b/tests/phase.test.cjs @@ -20,7 +20,7 @@ const fs = require('fs'); const path = require('path'); const os = require('node:os'); const { execFileSync } = require('node:child_process'); -const { runGsdTools, createTempProject, createTempDir, cleanup } = require('./helpers.cjs'); +const { runGsdTools, createTempProject, cleanup } = require('./helpers.cjs'); const GSD_TOOLS_BIN = path.resolve(__dirname, '..', 'gsd-core', 'bin', 'gsd-tools.cjs'); diff --git a/tests/plan-review-convergence.test.cjs b/tests/plan-review-convergence.test.cjs index de6effa4d..cbf880f3b 100644 --- a/tests/plan-review-convergence.test.cjs +++ b/tests/plan-review-convergence.test.cjs @@ -29,7 +29,6 @@ const path = require('path'); const COMMAND_PATH = path.join(__dirname, '..', 'commands', 'gsd', 'plan-review-convergence.md'); const WORKFLOW_PATH = path.join(__dirname, '..', 'gsd-core', 'workflows', 'plan-review-convergence.md'); -const SCHEMA_PATH = path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'config-schema.cjs'); const CONFIG_DOC_PATH = path.join(__dirname, '..', 'docs', 'CONFIGURATION.md'); // ─── Command source ──────────────────────────────────────────────────────── diff --git a/tests/policy-shell-pinning.test.cjs b/tests/policy-shell-pinning.test.cjs index 38b171df3..82cea9f67 100644 --- a/tests/policy-shell-pinning.test.cjs +++ b/tests/policy-shell-pinning.test.cjs @@ -5,7 +5,6 @@ const assert = require('node:assert/strict'); const path = require('path'); const { - POLICY, VIOLATION, inspectWorkflow, runPolicyLint, diff --git a/tests/profile-output.test.cjs b/tests/profile-output.test.cjs index de326fb04..ec3c15b27 100644 --- a/tests/profile-output.test.cjs +++ b/tests/profile-output.test.cjs @@ -156,7 +156,7 @@ describe('generate-claude-md command', () => { const outputPath = path.join(tmpDir, 'CLAUDE.md'); fs.writeFileSync(outputPath, '# Custom CLAUDE.md\n\nUser content.\n'); - const result = runGsdTools(['generate-claude-md', '--output', outputPath, '--auto', '--raw'], tmpDir); + runGsdTools(['generate-claude-md', '--output', outputPath, '--auto', '--raw'], tmpDir); // Should merge, not overwrite const content = fs.readFileSync(outputPath, 'utf-8'); assert.ok(content.length > 0, 'should still have content'); diff --git a/tests/profile-pipeline.test.cjs b/tests/profile-pipeline.test.cjs index 70cd50f7d..1b576fc95 100644 --- a/tests/profile-pipeline.test.cjs +++ b/tests/profile-pipeline.test.cjs @@ -9,7 +9,6 @@ const { test, describe, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); -const os = require('os'); const { runGsdTools, createTempDir, createTempProject, cleanup } = require('./helpers.cjs'); // ─── scan-sessions ──────────────────────────────────────────────────────────── diff --git a/tests/prompt-budget.test.cjs b/tests/prompt-budget.test.cjs index 2a8ae039d..6e2a44ae5 100644 --- a/tests/prompt-budget.test.cjs +++ b/tests/prompt-budget.test.cjs @@ -84,7 +84,7 @@ describe('prompt-budget', () => { requirements: null, }; - const { prompt, metadata } = applyBudget({ sections, budget: 200 }); + const { metadata } = applyBudget({ sections, budget: 200 }); // context drops first per spec (priority 6), research second (priority 7) assert.deepEqual(metadata.omitted, ['context', 'research']); @@ -183,7 +183,7 @@ describe('prompt-budget', () => { requirements: bigContent, }; - const { prompt, metadata } = applyBudget({ sections, budget: 200 }); + const { metadata } = applyBudget({ sections, budget: 200 }); assert.deepEqual(metadata.omitted, ['context', 'research', 'requirements']); assert.equal(metadata.noteInjected, true); @@ -237,7 +237,7 @@ describe('prompt-budget', () => { requirements: null, }; - const { prompt, metadata } = applyBudget({ sections, budget: 145 }); + const { metadata } = applyBudget({ sections, budget: 145 }); // Research must be dropped (it caused the pressure) assert.ok(metadata.omitted.includes('research'), 'research must be omitted'); diff --git a/tests/prompt-injection-scan.test.cjs b/tests/prompt-injection-scan.test.cjs index f6f795de0..4027bbb04 100644 --- a/tests/prompt-injection-scan.test.cjs +++ b/tests/prompt-injection-scan.test.cjs @@ -29,7 +29,7 @@ const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); -const { scanForInjection, INJECTION_PATTERNS } = require('../gsd-core/bin/lib/security.cjs'); +const { scanForInjection } = require('../gsd-core/bin/lib/security.cjs'); // ─── Configuration ────────────────────────────────────────────────────────── diff --git a/tests/reapply-patches.test.cjs b/tests/reapply-patches.test.cjs index 6404175f0..db7832e3f 100644 --- a/tests/reapply-patches.test.cjs +++ b/tests/reapply-patches.test.cjs @@ -7,7 +7,7 @@ * Closes: #1469 */ -const { test, describe, before, beforeEach, afterEach } = require('node:test'); +const { test, describe, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); @@ -381,7 +381,7 @@ describe('reapply-patches gated hunk verification (#1999)', () => { // assert it both names the table and defines an explicit gate // condition tied to the `verified` column. const content = fs.readFileSync(workflowPath, 'utf8'); - const step5Match = content.match(/^##\s+Step 5[^\n]*\n([\s\S]*?)(?=^##\s|\Z)/m); + const step5Match = content.match(/^##\s+Step 5[^\n]*\n([\s\S]*?)(?=^##\s|Z)/m); assert.ok(step5Match, 'reapply-patches workflow must contain a "## Step 5" section'); const step5 = step5Match[1]; assert.ok( @@ -405,7 +405,7 @@ describe('reapply-patches gated hunk verification (#1999)', () => { test('Step 5 also halts when the Hunk Verification Table is absent (Step 4 produced nothing)', () => { // Independent gate: missing-table is a separate halt path from any-no-row. const content = fs.readFileSync(workflowPath, 'utf8'); - const step5Match = content.match(/^##\s+Step 5[^\n]*\n([\s\S]*?)(?=^##\s|\Z)/m); + const step5Match = content.match(/^##\s+Step 5[^\n]*\n([\s\S]*?)(?=^##\s|Z)/m); assert.ok(step5Match, 'Step 5 section must exist'); const step5 = step5Match[1]; const handlesAbsent = /(table is absent|table is missing|missing.*table|absent.*table)/i.test(step5); diff --git a/tests/schema-drift.test.cjs b/tests/schema-drift.test.cjs index 9905134b9..a17ea9217 100644 --- a/tests/schema-drift.test.cjs +++ b/tests/schema-drift.test.cjs @@ -9,7 +9,7 @@ const { test, describe, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); -const { createTempProject, createTempGitProject, cleanup, runGsdTools } = require('./helpers.cjs'); +const { createTempGitProject, cleanup, runGsdTools } = require('./helpers.cjs'); // ─── Unit: detectSchemaFiles ───────────────────────────────────────────────── diff --git a/tests/secret-scan-lint.test.cjs b/tests/secret-scan-lint.test.cjs index 748c84bfe..8dd6a4ff6 100644 --- a/tests/secret-scan-lint.test.cjs +++ b/tests/secret-scan-lint.test.cjs @@ -32,7 +32,7 @@ // protocol. Migrating to a parsed IR would add ceremony without changing // what is verified — the strings ARE the typed surface. -const { describe, test, before, after } = require('node:test'); +const { describe, test } = require('node:test'); const assert = require('node:assert/strict'); const { execFileSync, spawnSync } = require('child_process'); const fs = require('fs'); @@ -99,25 +99,6 @@ function runSecretScan(fileContent, extraArgs = []) { } } -/** - * Run secret-scan.sh --dir [extraArgs] and count effective exclusions - * by checking how many files in a known fixture set are skipped vs scanned. - * Uses spawnSync with a generous timeout for large directories. - */ -function runSecretScanDir(dirPath, extraArgs = []) { - const args = ['--dir', dirPath, ...extraArgs]; - const result = spawnSync(SECRET_SCAN, args, { - encoding: 'utf-8', - timeout: 60000, - cwd: PROJECT_ROOT, - }); - return { - status: result.status !== null ? result.status : 1, - stdout: result.stdout || '', - stderr: result.stderr || '', - }; -} - // ─── Script Existence ───────────────────────────────────────────────────────── describe('secret-scan-lint.sh script exists and is executable', { skip: IS_WINDOWS }, () => { diff --git a/tests/security-prompt-injection.test.cjs b/tests/security-prompt-injection.test.cjs index d009f10b5..d96feba81 100644 --- a/tests/security-prompt-injection.test.cjs +++ b/tests/security-prompt-injection.test.cjs @@ -213,7 +213,7 @@ describe('workstream-name-policy: hostile names are slugified or rejected', () = // of toWorkstreamSlug is a name the rest of the system already trusts. assert.match(slug, /^[a-z0-9][a-z0-9._-]*$|^$/, `slug shape for ${c.label}: ${JSON.stringify(slug)}`); // And it never contains shell metacharacters or path separators. - assert.doesNotMatch(slug, /[$`;&|<>\\\/]/, `slug must not echo shell metacharacters: ${JSON.stringify(slug)}`); + assert.doesNotMatch(slug, /[$`;&|<>\\/]/, `slug must not echo shell metacharacters: ${JSON.stringify(slug)}`); }); } }); diff --git a/tests/security-scan.test.cjs b/tests/security-scan.test.cjs index f50b03c59..ac93714b0 100644 --- a/tests/security-scan.test.cjs +++ b/tests/security-scan.test.cjs @@ -32,9 +32,9 @@ // Migrating these to a parsed IR would add ceremony without changing // what is verified — the strings ARE the typed surface. -const { describe, test, before, after } = require('node:test'); +const { describe, test } = require('node:test'); const assert = require('node:assert/strict'); -const { execFileSync, execSync, spawnSync } = require('child_process'); +const { execFileSync, spawnSync } = require('child_process'); const fs = require('fs'); const os = require('os'); const path = require('path'); @@ -563,7 +563,7 @@ describe('security-scan.yml workflow', () => { test('workflow does not use direct github context in run commands', () => { const content = fs.readFileSync(workflowPath, 'utf-8'); // Extract only run: blocks and check they don't contain ${{ }} - const runBlocks = content.match(/run:\s*\|?\s*\n([\s\S]*?)(?=\n\s*-|\n\s*\w+:|\Z)/g) || []; + const runBlocks = content.match(/run:\s*\|?\s*\n([\s\S]*?)(?=\n\s*-|\n\s*\w+:|Z)/g) || []; for (const block of runBlocks) { assert.ok( !block.includes('${{'), diff --git a/tests/settings-integrations.test.cjs b/tests/settings-integrations.test.cjs index c561388ca..6d3cd031d 100644 --- a/tests/settings-integrations.test.cjs +++ b/tests/settings-integrations.test.cjs @@ -41,10 +41,6 @@ const WORKFLOW_PATH = path.join(REPO_ROOT, 'gsd-core', 'workflows', 'settings-in const SKILL_PATH = path.join(REPO_ROOT, '.claude', 'skills', 'gsd-settings-integrations.md'); const SETTINGS_WORKFLOW_PATH = path.join(REPO_ROOT, 'gsd-core', 'workflows', 'settings.md'); -function readIfExists(p) { - try { return fs.readFileSync(p, 'utf-8'); } catch { return null; } -} - // ─── Artifacts ─────────────────────────────────────────────────────────────── describe('#2529 artifacts', () => { diff --git a/tests/settings-jsonc.test.cjs b/tests/settings-jsonc.test.cjs index 0ba175e89..bd1f0121a 100644 --- a/tests/settings-jsonc.test.cjs +++ b/tests/settings-jsonc.test.cjs @@ -13,7 +13,7 @@ * Closes: #1461 */ -const { test, describe, beforeEach, afterEach } = require('node:test'); +const { test, describe } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); diff --git a/tests/shell-command-projection-dispatch.test.cjs b/tests/shell-command-projection-dispatch.test.cjs index abc39df4d..e4ff7f613 100644 --- a/tests/shell-command-projection-dispatch.test.cjs +++ b/tests/shell-command-projection-dispatch.test.cjs @@ -192,7 +192,7 @@ describe('platformWriteSync', () => { assert.ok(fs.statSync(filePath).isFile()); }); - test('mtime advances on re-write', (t) => { + test('mtime advances on re-write', (_t) => { const filePath = path.join(tmpDir, 'output.md'); platformWriteSync(filePath, '# First\n'); const mtimeBefore = fs.statSync(filePath).mtimeMs; diff --git a/tests/temp-subdir.test.cjs b/tests/temp-subdir.test.cjs index 08c7ec1d0..939fa9c86 100644 --- a/tests/temp-subdir.test.cjs +++ b/tests/temp-subdir.test.cjs @@ -6,7 +6,7 @@ * directly to os.tmpdir(). */ -const { test, describe, beforeEach, afterEach } = require('node:test'); +const { test, describe, beforeEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); diff --git a/tests/thinking-model-guidance.test.cjs b/tests/thinking-model-guidance.test.cjs index e7ff0e0d6..383b0078f 100644 --- a/tests/thinking-model-guidance.test.cjs +++ b/tests/thinking-model-guidance.test.cjs @@ -20,7 +20,7 @@ const AGENTS_DIR = path.join(__dirname, '..', 'agents'); const THINKING_CONTEXTS = ['debug', 'execution', 'planning', 'research', 'verification']; // Sections present in #1791-style content (named models with anti-patterns, not generic schema) -const REQUIRED_SECTIONS = [ +const _REQUIRED_SECTIONS = [ '## Conflict Resolution', '## When NOT to Think', ]; @@ -40,7 +40,7 @@ const NAMED_MODELS = { }; // Sequencing rules are documented in Conflict Resolution sections -const SEQUENCING_CONTEXTS = ['debug', 'execution', 'planning', 'research', 'verification']; +const _SEQUENCING_CONTEXTS = ['debug', 'execution', 'planning', 'research', 'verification']; // Gap Closure Mode is only in planning const GAP_CLOSURE_CONTEXT = 'planning'; diff --git a/tests/windows-robustness.test.cjs b/tests/windows-robustness.test.cjs index f1e8c5f3b..c913e1abf 100644 --- a/tests/windows-robustness.test.cjs +++ b/tests/windows-robustness.test.cjs @@ -85,9 +85,6 @@ function findUnguardedInfoCommands(code) { // ─── Workflow Shell Robustness ──────────────────────────────────────────────── describe('workflow shell robustness', () => { - const workflowFiles = fs.readdirSync(WORKFLOWS_DIR) - .filter(f => f.endsWith('.md')); - // Key workflow files that must have || true guards on informational commands const criticalWorkflows = [ 'resume-project.md', diff --git a/tests/workflow-guard-registration.test.cjs b/tests/workflow-guard-registration.test.cjs index 29a1a4f9d..60fc4c6fb 100644 --- a/tests/workflow-guard-registration.test.cjs +++ b/tests/workflow-guard-registration.test.cjs @@ -88,7 +88,6 @@ describe('hook registration completeness anti-pattern guard', () => { for (const hook of jsHooks) { // Each JS hook should have a buildHookCommand or 'node ' command construction // that references the hook filename (not just the gsdHooks array or uninstall filter) - const hookBase = hook.replace('.js', ''); const lines = content.split('\n').filter(line => line.includes(hook) && (line.includes('buildHookCommand') || line.includes("'node '")) diff --git a/tests/workflow-shell-pinning.test.cjs b/tests/workflow-shell-pinning.test.cjs index 2626c2c27..7d1e8a3a1 100644 --- a/tests/workflow-shell-pinning.test.cjs +++ b/tests/workflow-shell-pinning.test.cjs @@ -118,14 +118,14 @@ function findViolations(filePath) { let inDefaultsBlock = false; // currently inside a `defaults:` mapping let inDefaultsRunBlock = false; // currently inside `defaults: run:` let defaultsBlockOwner = null; // 'workflow' or 'job' - let defaultsBlockCol = null; // column of the `defaults:` key + let _defaultsBlockCol = null; // column of the `defaults:` key // Strategy/matrix tracking - let inStrategyBlock = false; - let inMatrixBlock = false; - let inMatrixOsBlock = false; - let strategyCol = null; - let matrixCol = null; + let _inStrategyBlock = false; + let _inMatrixBlock = false; + let _inMatrixOsBlock = false; + let _strategyCol = null; + let _matrixCol = null; // Step tracking let stepIndent = null; // indent level of the `- name:/run:/uses:` items @@ -178,7 +178,7 @@ function findViolations(filePath) { inDefaultsBlock = true; inDefaultsRunBlock = false; defaultsBlockOwner = 'workflow'; - defaultsBlockCol = 0; + _defaultsBlockCol = 0; continue; } @@ -216,9 +216,9 @@ function findViolations(filePath) { // Reset sub-section tracking inDefaultsBlock = false; inDefaultsRunBlock = false; - inStrategyBlock = false; - inMatrixBlock = false; - inMatrixOsBlock = false; + _inStrategyBlock = false; + _inMatrixBlock = false; + _inMatrixOsBlock = false; continue; } @@ -229,7 +229,7 @@ function findViolations(filePath) { inDefaultsBlock = true; inDefaultsRunBlock = false; defaultsBlockOwner = 'job'; - defaultsBlockCol = 4; + _defaultsBlockCol = 4; continue; } @@ -248,7 +248,7 @@ function findViolations(filePath) { // ── Step list detection ─────────────────────────────────────────────── const stepStartMatch = line.match( - /^(\s+)-\s+(name|run|uses|shell|if|id|env|with|continue-on-error|timeout-minutes|working-directory)\s*[:\|]/, + /^(\s+)-\s+(name|run|uses|shell|if|id|env|with|continue-on-error|timeout-minutes|working-directory)\s*[:|]/, ); if (stepStartMatch) { const thisIndent = stepStartMatch[1].length; diff --git a/tests/workspace.test.cjs b/tests/workspace.test.cjs index df387a81a..a9319853e 100644 --- a/tests/workspace.test.cjs +++ b/tests/workspace.test.cjs @@ -9,7 +9,6 @@ const { test, describe, beforeEach, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); -const os = require('os'); const { execSync } = require('child_process'); const { runGsdTools, createTempProject, createTempDir, cleanup } = require('./helpers.cjs'); const { detectChildRepos } = require('../gsd-core/bin/lib/init.cjs'); @@ -328,7 +327,7 @@ describe('workspace command files', () => { function parseCommandFile(filePath) { // Strip UTF-8 BOM if present (some editors inject on save under Windows); // a BOM byte at offset 0 defeats the ^--- anchor, making fmMatch null. - const raw = fs.readFileSync(filePath, 'utf8').replace(/^/, ''); + const raw = fs.readFileSync(filePath, 'utf8').replace(/^\ufeff/, ''); const fmMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/); assert.ok(fmMatch, `${path.basename(filePath)} must start with a YAML frontmatter block`); const fm = {}; diff --git a/tests/workstream.test.cjs b/tests/workstream.test.cjs index 18dbfd0d5..d5dca0bec 100644 --- a/tests/workstream.test.cjs +++ b/tests/workstream.test.cjs @@ -9,20 +9,11 @@ const fs = require('fs'); const os = require('os'); const path = require('path'); const { runGsdTools, cleanup } = require('./helpers.cjs'); -const { createFixture, seedWorkstream, writeState } = require('./fixtures/index.cjs'); +const { createFixture, seedWorkstream } = require('./fixtures/index.cjs'); const { migrateToWorkstreams, getOtherActiveWorkstreams } = require('../gsd-core/bin/lib/workstream.cjs'); // ─── Helper ────────────────────────────────────────────────────────────────── -function createProjectWithState(tmpDir, roadmap, state) { - if (roadmap) { - fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), roadmap, 'utf-8'); - } - if (state) { - writeState(tmpDir, state); - } -} - function createFailingTtyEnv(tmpDir) { const binDir = path.join(tmpDir, 'fake-bin'); const markerFile = path.join(tmpDir, 'tty-invoked.log'); diff --git a/tests/worktree.test.cjs b/tests/worktree.test.cjs index 6be02bb2a..bcadb25b0 100644 --- a/tests/worktree.test.cjs +++ b/tests/worktree.test.cjs @@ -34,14 +34,14 @@ const EXECUTE_PLAN_PATH = path.join(REPO_ROOT, 'gsd-core', 'workflows', 'execute const QUICK_PATH = path.join(REPO_ROOT, 'gsd-core', 'workflows', 'quick.md'); const EXECUTOR_AGENT_PATH = path.join(REPO_ROOT, 'agents', 'gsd-executor.md'); const DIAGNOSE_PATH = path.join(REPO_ROOT, 'gsd-core', 'workflows', 'diagnose-issues.md'); -const GIT_INTEGRATION_PATH = path.join(REPO_ROOT, 'gsd-core', 'references', 'git-integration.md'); +const _GIT_INTEGRATION_PATH = path.join(REPO_ROOT, 'gsd-core', 'references', 'git-integration.md'); const WORKTREE_BRANCH_CHECK_FRAGMENT = path.join(REPO_ROOT, 'gsd-core', 'references', 'worktree-branch-check.md'); const isWindows = process.platform === 'win32'; // ─── Helpers ────────────────────────────────────────────────────────────────── -function extractNamedBlock(markdown, blockName) { +function _extractNamedBlock(markdown, blockName) { const open = `<${blockName}>`; const close = ``; const start = markdown.indexOf(open); @@ -55,7 +55,7 @@ function extractNamedBlock(markdown, blockName) { * Extract all fenced code blocks (```...```) from a markdown chunk. * Returns array of { lang, body } objects. */ -function extractFencedCodeBlocks(markdown) { +function _extractFencedCodeBlocks(markdown) { const blocks = []; const lines = markdown.split('\n'); let inFence = false; @@ -87,7 +87,7 @@ function extractFencedCodeBlocks(markdown) { * and `VAR=$(cmd ...)` assignments by extracting the inner command. This is intentionally * simple — adequate for asserting on the presence of well-known git invocations. */ -function shellStatements(script) { +function _shellStatements(script) { const statements = []; const lines = script.split('\n'); for (let raw of lines) { @@ -120,7 +120,7 @@ function shellStatements(script) { * Find the line index of the first command matching a predicate. * Returns -1 when not found. */ -function findCommandIndex(statements, predicate) { +function _findCommandIndex(statements, predicate) { for (let i = 0; i < statements.length; i++) { if (predicate(statements[i])) return i; }