refactor: centralize skills directory constants in skill-discovery.js

Export SKILLS_DIR, CLAUDE_SKILLS_DIR, PI_SKILLS_DIR from skill-discovery.js
instead of repeating join(homedir(), ...) inline across 5 files.

Consumers updated:
- preferences-skills.js: replace 2 inline join(homedir()...) with SKILLS_DIR/CLAUDE_SKILLS_DIR
- skill-health.js: replace 2 inline join(homedir()...) with constants; remove homedir import
- skill-catalog.js: replace 2 inline join(homedir()...) with constants; remove homedir import
- skill-telemetry.js: replace 4 inline join(homedir()...) with constants; remove homedir import

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Mikael Hugo 2026-05-11 14:39:10 +02:00
parent ec224f96ac
commit 8a7f6de782
5 changed files with 17 additions and 20 deletions

View file

@ -9,6 +9,7 @@ import { homedir } from "node:os";
import { isAbsolute, join } from "node:path"; import { isAbsolute, join } from "node:path";
import { validatePreferences } from "./preferences-validation.js"; import { validatePreferences } from "./preferences-validation.js";
import { sfHome } from "./sf-home.js"; import { sfHome } from "./sf-home.js";
import { CLAUDE_SKILLS_DIR, SKILLS_DIR } from "./skill-discovery.js";
/** /**
* Get skill search directories in priority order for resolution. * Get skill search directories in priority order for resolution.
* *
@ -19,10 +20,10 @@ import { sfHome } from "./sf-home.js";
*/ */
export function getSkillSearchDirs(cwd) { export function getSkillSearchDirs(cwd) {
const dirs = [ const dirs = [
{ dir: join(homedir(), ".agents", "skills"), method: "user-skill" }, { dir: SKILLS_DIR, method: "user-skill" },
{ dir: join(cwd, ".agents", "skills"), method: "project-skill" }, { dir: join(cwd, ".agents", "skills"), method: "project-skill" },
// Claude Code official skill directories // Claude Code official skill directories
{ dir: join(homedir(), ".claude", "skills"), method: "user-skill" }, { dir: CLAUDE_SKILLS_DIR, method: "user-skill" },
{ dir: join(cwd, ".claude", "skills"), method: "project-skill" }, { dir: join(cwd, ".claude", "skills"), method: "project-skill" },
]; ];
// Legacy fallback — read skills from old SF directory only if migration hasn't completed // Legacy fallback — read skills from old SF directory only if migration hasn't completed

View file

@ -13,9 +13,9 @@
*/ */
import { execFile } from "node:child_process"; import { execFile } from "node:child_process";
import { existsSync } from "node:fs"; import { existsSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path"; import { join } from "node:path";
import { showNextAction } from "../shared/tui.js"; import { showNextAction } from "../shared/tui.js";
import { CLAUDE_SKILLS_DIR, SKILLS_DIR } from "./skill-discovery.js";
// ─── Curated Catalog ────────────────────────────────────────────────────────── // ─── Curated Catalog ──────────────────────────────────────────────────────────
export const SKILL_CATALOG = [ export const SKILL_CATALOG = [
// ── Swift (language-level — any Swift project) ──────────────────────────── // ── Swift (language-level — any Swift project) ────────────────────────────
@ -961,8 +961,8 @@ export async function installPacksBatched(packs, onProgress) {
*/ */
export function isPackInstalled(pack) { export function isPackInstalled(pack) {
const skillsDirs = [ const skillsDirs = [
join(homedir(), ".agents", "skills"), SKILLS_DIR,
join(homedir(), ".claude", "skills"), CLAUDE_SKILLS_DIR,
]; ];
return pack.skills.every((name) => return pack.skills.every((name) =>
skillsDirs.some((dir) => existsSync(join(dir, name, "SKILL.md"))), skillsDirs.some((dir) => existsSync(join(dir, name, "SKILL.md"))),

View file

@ -12,9 +12,9 @@ import { homedir } from "node:os";
import { join } from "node:path"; import { join } from "node:path";
/** Skills directories — skills.sh ecosystem + Claude Code official + legacy Pi */ /** Skills directories — skills.sh ecosystem + Claude Code official + legacy Pi */
const SKILLS_DIR = join(homedir(), ".agents", "skills"); export const SKILLS_DIR = join(homedir(), ".agents", "skills");
const CLAUDE_SKILLS_DIR = join(homedir(), ".claude", "skills"); export const CLAUDE_SKILLS_DIR = join(homedir(), ".claude", "skills");
const PI_SKILLS_DIR = join(homedir(), ".pi", "agent", "skills"); export const PI_SKILLS_DIR = join(homedir(), ".pi", "agent", "skills");
/** Snapshot of skill names at autonomous mode start */ /** Snapshot of skill names at autonomous mode start */
let baselineSkills = null; let baselineSkills = null;
/** /**

View file

@ -13,10 +13,10 @@
* research identified as critical for skill quality. * research identified as critical for skill quality.
*/ */
import { existsSync, statSync } from "node:fs"; import { existsSync, statSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path"; import { join } from "node:path";
import { formatCost, formatTokenCount, loadLedgerFromDisk } from "./metrics.js"; import { formatCost, formatTokenCount, loadLedgerFromDisk } from "./metrics.js";
import { detectStaleSkills } from "./skill-telemetry.js"; import { detectStaleSkills } from "./skill-telemetry.js";
import { CLAUDE_SKILLS_DIR, SKILLS_DIR } from "./skill-discovery.js";
// ─── Constants ──────────────────────────────────────────────────────────────── // ─── Constants ────────────────────────────────────────────────────────────────
/** Default staleness threshold in days */ /** Default staleness threshold in days */
@ -168,8 +168,8 @@ export function formatSkillDetail(basePath, skillName) {
} }
// Check for SKILL.md existence — search both ecosystem and Claude Code directories // Check for SKILL.md existence — search both ecosystem and Claude Code directories
const candidatePaths = [ const candidatePaths = [
join(homedir(), ".agents", "skills", skillName, "SKILL.md"), join(SKILLS_DIR, skillName, "SKILL.md"),
join(homedir(), ".claude", "skills", skillName, "SKILL.md"), join(CLAUDE_SKILLS_DIR, skillName, "SKILL.md"),
]; ];
const skillPath = candidatePaths.find((p) => existsSync(p)); const skillPath = candidatePaths.find((p) => existsSync(p));
if (skillPath) { if (skillPath) {

View file

@ -11,9 +11,9 @@
* 3. At unit completion, getAndClearSkills() returns the loaded list for metrics * 3. At unit completion, getAndClearSkills() returns the loaded list for metrics
*/ */
import { existsSync, readdirSync } from "node:fs"; import { existsSync, readdirSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path"; import { join } from "node:path";
import { sfHome } from "./sf-home.js"; import { sfHome } from "./sf-home.js";
import { CLAUDE_SKILLS_DIR, SKILLS_DIR } from "./skill-discovery.js";
// ─── In-memory state ────────────────────────────────────────────────────────── // ─── In-memory state ──────────────────────────────────────────────────────────
/** Skills available in the system prompt for the current unit */ /** Skills available in the system prompt for the current unit */
@ -27,11 +27,9 @@ const activelyLoadedSkills = new Set();
* Called before each unit starts to establish the baseline for telemetry. * Called before each unit starts to establish the baseline for telemetry.
*/ */
export function captureAvailableSkills() { export function captureAvailableSkills() {
const skillsDir = join(homedir(), ".agents", "skills");
const claudeSkillsDir = join(homedir(), ".claude", "skills");
const legacyDir = join(sfHome(), "agent", "skills"); const legacyDir = join(sfHome(), "agent", "skills");
const names = listSkillNames(skillsDir); const names = listSkillNames(SKILLS_DIR);
const claudeNames = listSkillNames(claudeSkillsDir); const claudeNames = listSkillNames(CLAUDE_SKILLS_DIR);
// Include skills still in the legacy directory only if migration hasn't completed // Include skills still in the legacy directory only if migration hasn't completed
const legacyMigrated = existsSync(join(legacyDir, ".migrated-to-agents")); const legacyMigrated = existsSync(join(legacyDir, ".migrated-to-agents"));
const legacyNames = legacyMigrated ? [] : listSkillNames(legacyDir); const legacyNames = legacyMigrated ? [] : listSkillNames(legacyDir);
@ -101,14 +99,12 @@ export function detectStaleSkills(units, thresholdDays) {
const cutoff = Date.now() - thresholdDays * 24 * 60 * 60 * 1000; const cutoff = Date.now() - thresholdDays * 24 * 60 * 60 * 1000;
const stale = []; const stale = [];
// Check all installed skills, not just those with usage data // Check all installed skills, not just those with usage data
const skillsDir = join(homedir(), ".agents", "skills");
const claudeSkillsDir = join(homedir(), ".claude", "skills");
const legacyDir = join(sfHome(), "agent", "skills"); const legacyDir = join(sfHome(), "agent", "skills");
const legacyMigrated = existsSync(join(legacyDir, ".migrated-to-agents")); const legacyMigrated = existsSync(join(legacyDir, ".migrated-to-agents"));
const legacyNames = legacyMigrated ? [] : listSkillNames(legacyDir); const legacyNames = legacyMigrated ? [] : listSkillNames(legacyDir);
const installedSet = new Set([ const installedSet = new Set([
...listSkillNames(skillsDir), ...listSkillNames(SKILLS_DIR),
...listSkillNames(claudeSkillsDir), ...listSkillNames(CLAUDE_SKILLS_DIR),
...legacyNames, ...legacyNames,
]); ]);
const installed = [...installedSet]; const installed = [...installedSet];