mirror of
https://github.com/garrytan/gstack.git
synced 2026-08-09 15:56:02 +02:00
fix: routing E2E stops writing to user's ~/.claude/skills/
installSkills() was copying SKILL.md files to both project-level (.claude/skills/ in tmpDir) and user-level (~/.claude/skills/). Writing to the user's real install fails when symlinks point to different worktrees or dangling targets (ENOENT on copyFileSync). Now installs to project-level only. The test already sets cwd to the tmpDir, so project-level discovery works. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
4201a55c68
commit
600b2237e7
@@ -60,10 +60,9 @@ if (evalsEnabled && process.env.EVALS_TIER) {
|
|||||||
// --- Helper functions ---
|
// --- Helper functions ---
|
||||||
|
|
||||||
/** Copy all SKILL.md files for auto-discovery.
|
/** Copy all SKILL.md files for auto-discovery.
|
||||||
* Install to BOTH project-level (.claude/skills/) AND user-level (~/.claude/skills/)
|
* Installs to project-level (.claude/skills/) only. Writing to the user's
|
||||||
* because Claude Code discovers skills from both locations. In CI containers,
|
* ~/.claude/skills/ is unsafe: it may contain symlinks from the real gstack
|
||||||
* $HOME may differ from the working directory, so we need both paths to ensure
|
* install that point to different worktrees or dangling targets. */
|
||||||
* the Skill tool appears in Claude's available tools list. */
|
|
||||||
function installSkills(tmpDir: string) {
|
function installSkills(tmpDir: string) {
|
||||||
const skillDirs = [
|
const skillDirs = [
|
||||||
'', // root gstack SKILL.md
|
'', // root gstack SKILL.md
|
||||||
@@ -73,24 +72,16 @@ function installSkills(tmpDir: string) {
|
|||||||
'gstack-upgrade', 'humanizer',
|
'gstack-upgrade', 'humanizer',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Install to both project-level and user-level skill directories
|
const targetBase = path.join(tmpDir, '.claude', 'skills');
|
||||||
const homeDir = process.env.HOME || os.homedir();
|
|
||||||
const installTargets = [
|
|
||||||
path.join(tmpDir, '.claude', 'skills'), // project-level
|
|
||||||
path.join(homeDir, '.claude', 'skills'), // user-level (~/.claude/skills/)
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const skill of skillDirs) {
|
for (const skill of skillDirs) {
|
||||||
const srcPath = path.join(ROOT, skill, 'SKILL.md');
|
const srcPath = path.join(ROOT, skill, 'SKILL.md');
|
||||||
if (!fs.existsSync(srcPath)) continue;
|
if (!fs.existsSync(srcPath)) continue;
|
||||||
|
|
||||||
const skillName = skill || 'gstack';
|
const skillName = skill || 'gstack';
|
||||||
|
const destDir = path.join(targetBase, skillName);
|
||||||
for (const targetBase of installTargets) {
|
fs.mkdirSync(destDir, { recursive: true });
|
||||||
const destDir = path.join(targetBase, skillName);
|
fs.copyFileSync(srcPath, path.join(destDir, 'SKILL.md'));
|
||||||
fs.mkdirSync(destDir, { recursive: true });
|
|
||||||
fs.copyFileSync(srcPath, path.join(destDir, 'SKILL.md'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a CLAUDE.md with explicit routing instructions.
|
// Write a CLAUDE.md with explicit routing instructions.
|
||||||
|
|||||||
Reference in New Issue
Block a user