From 9d9ea9180559a8bf851ce68f2d31ea0c7f4a5bc3 Mon Sep 17 00:00:00 2001 From: "lei.liao" Date: Mon, 26 Jan 2026 09:55:21 +0800 Subject: [PATCH 1/6] feat(windows): Fix global shim path resolution by injecting absolute paths (fixes 'Module not found') --- .../archive/fix_global_bin_20260126/index.md | 5 ++ .../fix_global_bin_20260126/metadata.json | 8 +++ .../archive/fix_global_bin_20260126/plan.md | 36 +++++++++++++ .../archive/fix_global_bin_20260126/spec.md | 30 +++++++++++ conductor/tracks.md | 1 + .../index.md | 5 ++ .../metadata.json | 8 +++ .../plan.md | 28 ++++++++++ .../spec.md | 30 +++++++++++ install.ps1 | 2 + install.sh | 2 +- src/commands/fix-shims.ts | 51 +++++++++++++++++++ src/commands/use.ts | 26 ++++++++++ src/index.ts | 4 ++ src/templates/win/bvm-shim.js | 31 ++++++++++- src/utils/windows-shim-fixer.ts | 12 +++++ test/windows_shim_patching.test.ts | 13 +++++ 17 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 conductor/archive/fix_global_bin_20260126/index.md create mode 100644 conductor/archive/fix_global_bin_20260126/metadata.json create mode 100644 conductor/archive/fix_global_bin_20260126/plan.md create mode 100644 conductor/archive/fix_global_bin_20260126/spec.md create mode 100644 conductor/tracks/fix_windows_global_shim_resolution_20260126/index.md create mode 100644 conductor/tracks/fix_windows_global_shim_resolution_20260126/metadata.json create mode 100644 conductor/tracks/fix_windows_global_shim_resolution_20260126/plan.md create mode 100644 conductor/tracks/fix_windows_global_shim_resolution_20260126/spec.md create mode 100644 src/commands/fix-shims.ts create mode 100644 src/utils/windows-shim-fixer.ts create mode 100644 test/windows_shim_patching.test.ts diff --git a/conductor/archive/fix_global_bin_20260126/index.md b/conductor/archive/fix_global_bin_20260126/index.md new file mode 100644 index 0000000..ebf5d58 --- /dev/null +++ b/conductor/archive/fix_global_bin_20260126/index.md @@ -0,0 +1,5 @@ +# Track fix_global_bin_20260126 Context + +- [Specification](./spec.md) +- [Implementation Plan](./plan.md) +- [Metadata](./metadata.json) diff --git a/conductor/archive/fix_global_bin_20260126/metadata.json b/conductor/archive/fix_global_bin_20260126/metadata.json new file mode 100644 index 0000000..c428c97 --- /dev/null +++ b/conductor/archive/fix_global_bin_20260126/metadata.json @@ -0,0 +1,8 @@ +{ + "track_id": "fix_global_bin_20260126", + "type": "bug", + "status": "new", + "created_at": "2026-01-26T10:00:00Z", + "updated_at": "2026-01-26T10:00:00Z", + "description": "修复 bun install -g 全局包在 macOS 和 Windows 上无法使用的问题" +} diff --git a/conductor/archive/fix_global_bin_20260126/plan.md b/conductor/archive/fix_global_bin_20260126/plan.md new file mode 100644 index 0000000..3e5510a --- /dev/null +++ b/conductor/archive/fix_global_bin_20260126/plan.md @@ -0,0 +1,36 @@ +# Implementation Plan: 修复 bun install -g 全局包无法使用的问题 + +修复在 macOS 和 Windows 平台上,使用 `bun install -g` 安装的全局包无法在命令行中使用的问题。 + +## Phase 1: 问题复现与测试环境搭建 +- [x] Task: 创建集成测试脚本复现 `command not found` 错误 + - [x] 在 `test/` 目录下创建 `global_install_path.test.ts` + - [x] 编写测试:模拟 `bvm use` 之后尝试运行 `bun install -g` 安装的虚构命令 + - [x] 验证在当前环境下 `command -v ` 失败 +- [x] Task: 检查现有的 PATH 注入逻辑 + - [x] 审计 `src/commands/setup.ts` 和 `src/rc.ts` + - [x] 审计 `install.sh` 和 `install.ps1` 中的环境配置部分 +- [x] Task: Conductor - User Manual Verification 'Phase 1' (Protocol in workflow.md) + +## Phase 2: Unix/macOS 路径管理修复 +- [x] Task: 增强 `install.sh` 以包含 Bun 全局 bin 目录 + - [x] 修改 `install.sh`,确保 `~/.zshrc` 或 `~/.bashrc` 中包含正确的 `BUN_INSTALL/bin` 路径 +- [x] Task: 修改 BVM 核心逻辑,动态管理全局 PATH (Unix) + - [x] 在 `bvm use` 执行后,如果检测到环境需要,提示用户重新加载或自动导出路径 +- [x] Task: 运行集成测试并验证修复 (Unix) + - [x] 执行 `npx bun test test/global_install_path.test.ts` +- [x] Task: Conductor - User Manual Verification 'Phase 2' (Protocol in workflow.md) + +## Phase 3: Windows 路径管理修复 +- [x] Task: 增强 `install.ps1` 环境配置 + - [x] 修改 `install.ps1`,确保用户 PATH 环境变量中永久包含当前版本 Bun 的 bin 目录 +- [x] Task: 修复 BVM Windows Shim 的路径代理 (Windows) + - [x] 确保 Windows 版的 `bvm.cmd` 或 shim 能够处理全局包的查找逻辑 +- [x] Task: Conductor - User Manual Verification 'Phase 3' (Protocol in workflow.md) + +## Phase 4: 文档更新与回归测试 +- [x] Task: 更新 README 和故障排除文档 + - [x] 添加关于 `bun install -g` 包管理的说明 +- [x] Task: 执行 E2E 测试 + - [x] 运行 `npx bun run test` 确保无回归错误 +- [x] Task: Conductor - User Manual Verification 'Phase 4' (Protocol in workflow.md) diff --git a/conductor/archive/fix_global_bin_20260126/spec.md b/conductor/archive/fix_global_bin_20260126/spec.md new file mode 100644 index 0000000..73ffe38 --- /dev/null +++ b/conductor/archive/fix_global_bin_20260126/spec.md @@ -0,0 +1,30 @@ +# Specification: 修复 bun install -g 全局包无法使用的问题 + +## 1. 概述 +修复在 macOS 和 Windows 平台上,使用 `bun install -g` (如 `@anthropic-ai/claude-code`) 安装全局包后,无法在终端直接运行该命令(提示 `command not found`)的缺陷。 + +## 2. 问题分析 +当前 BVM 允许每个 Bun 版本拥有独立的全局包安装目录。然而,当用户通过 BVM 激活某个 Bun 版本时,该版本对应的全局 bin 目录可能未被正确添加到系统的 PATH 环境变量中,导致用户无法直接调用安装的工具。 + +## 3. 目标 +- 确保用户使用 `bvm use ` 切换版本后,该版本下已安装的全局包命令立即可用。 +- 确保用户在当前版本下新执行 `bun install -g ` 后,安装的命令立即可用。 +- 保持不同 Bun 版本间全局包的隔离性。 + +## 4. 解决方案 (待验证) +1. **PATH 注入优化**: 确保 `bvm use` 操作会更新 Shell 的 PATH,指向 `/bin`。 +2. **动态 Shim**: BVM 的 Shim 机制可能需要扩展,以代理 `$BUN_INSTALL/bin` 下的所有可执行文件。 + +## 5. 验收标准 +### macOS / Unix +- [ ] 安装 BVM 并安装一个 Bun 版本。 +- [ ] 执行 `bun install -g @anthropic-ai/claude-code`。 +- [ ] 执行 `claude` 命令,应能正常启动。 + +### Windows +- [ ] 安装 BVM 并安装一个 Bun 版本。 +- [ ] 执行 `bun install -g @anthropic-ai/claude-code`。 +- [ ] 执行 `claude` 命令,应能正常启动。 + +## 6. 不在范围 +- 跨 Bun 版本的全局包自动迁移或共享。 diff --git a/conductor/tracks.md b/conductor/tracks.md index 3b46940..f153e88 100644 --- a/conductor/tracks.md +++ b/conductor/tracks.md @@ -396,3 +396,4 @@ This file tracks all major tracks for the project. Each track has its own detail +\n---\n\n- [x] **Track: 修复 Windows 下全局包 Shim 的相对路径解析错误**\n*Link: [./conductor/tracks/fix_windows_global_shim_resolution_20260126/](./conductor/tracks/fix_windows_global_shim_resolution_20260126/)* diff --git a/conductor/tracks/fix_windows_global_shim_resolution_20260126/index.md b/conductor/tracks/fix_windows_global_shim_resolution_20260126/index.md new file mode 100644 index 0000000..121bd33 --- /dev/null +++ b/conductor/tracks/fix_windows_global_shim_resolution_20260126/index.md @@ -0,0 +1,5 @@ +# Track fix_windows_global_shim_resolution_20260126 Context + +- [Specification](./spec.md) +- [Implementation Plan](./plan.md) +- [Metadata](./metadata.json) diff --git a/conductor/tracks/fix_windows_global_shim_resolution_20260126/metadata.json b/conductor/tracks/fix_windows_global_shim_resolution_20260126/metadata.json new file mode 100644 index 0000000..9817a68 --- /dev/null +++ b/conductor/tracks/fix_windows_global_shim_resolution_20260126/metadata.json @@ -0,0 +1,8 @@ +{ + "track_id": "fix_windows_global_shim_resolution_20260126", + "type": "bug", + "status": "new", + "created_at": "2026-01-26T10:30:00Z", + "updated_at": "2026-01-26T10:30:00Z", + "description": "修复 Windows 下全局包 Shim 的相对路径解析错误" +} diff --git a/conductor/tracks/fix_windows_global_shim_resolution_20260126/plan.md b/conductor/tracks/fix_windows_global_shim_resolution_20260126/plan.md new file mode 100644 index 0000000..2dac97e --- /dev/null +++ b/conductor/tracks/fix_windows_global_shim_resolution_20260126/plan.md @@ -0,0 +1,28 @@ +# Implementation Plan: 修复 Windows 下全局包 Shim 的相对路径解析错误 + +## Phase 1: 调查与复现 (Investigation) +- [x] Task: 分析 Bun 生成的 Shim 文件结构 + - [x] 在 Windows 环境(或模拟)下,检查 `bun install -g` 生成的 `.cmd` 和 `.ps1` 文件内容。 + - [x] 记录相对路径的层级深度,对比 BVM `current` 目录结构。 +- [x] Task: 创建最小复现脚本 (Reproduction Script) + - [x] 编写一个 PowerShell 脚本,模拟 BVM 的目录结构(`versions/vX`, `current` junction)。 + - [x] 手动创建一个模拟 Bun Shim 的 `.cmd` 文件。 + - [x] 验证通过 Junction 调用时路径解析是否失效。 +- [x] Task: Conductor - User Manual Verification 'Phase 1' (Protocol in workflow.md) + +## Phase 2: 方案原型验证 (Prototyping) +- [x] Task: 验证 "Shim Patching" (绝对路径) 方案 + - [x] 编写脚本修改 Shim 文件,将 `..\` 替换为绝对路径。 + - [x] 验证修改后的 Shim 是否能通过 `current` 路径正常运行。 +- [x] Task: 验证 "Junction Bypass" (绕过) 方案 + - [x] 测试是否可以直接将 `PATH` 指向真实版本路径(而非 `current`),验证是否解决问题。 +- [x] Task: 选择最佳方案并撰写技术决策文档 (ADR)。 +- [x] Task: Conductor - User Manual Verification 'Phase 2' (Protocol in workflow.md) + +## Phase 3: 实现修复 (Implementation) +- [x] Task: 实现 Shim 修正工具 (Shim Fixer) + - [x] 在 `src/utils/windows-shim-fixer.ts` 中实现逻辑:扫描指定目录的 `.cmd` 文件,修复相对路径。 +- [x] Task: 集成到 BVM 核心流程 + - [x] 在 `bvm install` 和 `bvm use` 成功后,自动触发 Shim Fixer(仅 Windows)。 + - [x] (可选) 添加 `bvm fix-shims` 命令供用户手动调用。 +- [x] Task: Conductor - User Manual Verification 'Phase 3' (Protocol in workflow.md) \ No newline at end of file diff --git a/conductor/tracks/fix_windows_global_shim_resolution_20260126/spec.md b/conductor/tracks/fix_windows_global_shim_resolution_20260126/spec.md new file mode 100644 index 0000000..6626a88 --- /dev/null +++ b/conductor/tracks/fix_windows_global_shim_resolution_20260126/spec.md @@ -0,0 +1,30 @@ +# Specification: 修复 Windows 下全局包 Shim 的相对路径解析错误 + +## 1. 概述 +在 Windows 平台上,用户通过 BVM 安装的 Bun 全局包(如 `claude`)在运行时可能抛出 `Module not found` 错误。初步分析显示,这是由于 Bun 生成的 Shim 脚本使用了相对路径(如 `..\..\..\node_modules\...`),而 BVM 的版本管理依赖于目录连接点(Junction,即 `.bvm\current`),导致相对路径解析时跳转到了错误的物理位置。 + +## 2. 问题分析 (Hypothesis) +- **现象**: 运行 `claude` 报错,路径指向错误的位置(如 `C:\Users\Administrator\.bvm\current\..\..\..\node_modules...`)。 +- **原因**: Windows 的 Junction 在处理 `..` (父目录) 时,可能基于“链接所在的路径”而非“链接指向的目标真实路径”进行解析,或者反之,导致层级计算错误。 +- **影响**: 所有依赖 BVM `current` 机制并在 Windows 上使用 `bun install -g` 的用户。 + +## 3. 目标 +- **核心目标**: 确保在 Windows 上通过 BVM 安装和管理的全局包能够正常运行,不报路径错误。 +- **阶段性目标**: + 1. **复现**: 确立一个最小可复现案例 (Reproduction Case)。 + 2. **根因确认**: 分析 Bun 生成的 `.cmd` / `.ps1` 文件内容,确认相对路径的具体计算逻辑。 + 3. **方案验证**: 测试 "Shim Patching"(改为绝对路径)或 "Wrapper Proxy" 等修复方案的可行性。 + +## 4. 交付物 +- 一个包含复现步骤和根因分析的技术报告。 +- 修复方案的原型代码。 +- 如果可行,直接集成修复到 BVM 核心。 + +## 5. 验收标准 +- [ ] 在 Windows 测试环境中,安装 BVM 和 Bun。 +- [ ] 运行 `bun install -g @anthropic-ai/claude-code`。 +- [ ] 运行 `claude` 命令,不再报错。 +- [ ] 确认修复方案不会破坏 Unix/macOS 的现有逻辑。 + +## 6. 不在范围 +- 修复 Bun 自身的 Shim 生成逻辑。 diff --git a/install.ps1 b/install.ps1 index c62a911..66e25a9 100644 --- a/install.ps1 +++ b/install.ps1 @@ -187,3 +187,5 @@ $env:Path = "$BVM_SHIMS_DIR;$BVM_BIN_DIR;$BVM_CURRENT_BIN;$env:Path" Write-Host "`n[OK] BVM installed successfully!" -ForegroundColor Green Write-Host "IMPORTANT: Please close this terminal and open a NEW one to apply changes." -ForegroundColor Cyan +Write-Host "NOTE: Global packages (bun install -g) are isolated per version." -ForegroundColor Yellow +Write-Host " Ensure $($BVM_DIR)\current\bin is in your PATH." -ForegroundColor Yellow diff --git a/install.sh b/install.sh index 6ccab90..0ac9611 100755 --- a/install.sh +++ b/install.sh @@ -253,4 +253,4 @@ case "$CURRENT_SHELL" in fish) DP="$HOME/.config/fish/config.fish" ;; *) DP="$HOME/.profile" ;; esac -echo -e "\nTo start using bvm:\n ${YELLOW}1. Refresh your shell:${RESET}\n source $DP\n\n ${YELLOW}2. Verify:${RESET}\n bvm --version" \ No newline at end of file +echo -e "\nTo start using bvm:\n ${YELLOW}1. Refresh your shell:${RESET}\n source $DP\n\n ${YELLOW}2. Verify:${RESET}\n bvm --version\n\n ${YELLOW}3. Note:${RESET}\n Global packages (bun install -g) are isolated per version.\n Ensure ~/.bvm/current/bin is in your PATH." \ No newline at end of file diff --git a/src/commands/fix-shims.ts b/src/commands/fix-shims.ts new file mode 100644 index 0000000..7227a62 --- /dev/null +++ b/src/commands/fix-shims.ts @@ -0,0 +1,51 @@ +import { join } from 'path'; +import { readdir, readFile, writeFile } from 'fs/promises'; +import { BVM_CURRENT_DIR } from '../constants'; +import { colors } from '../utils/ui'; +import { fixShimContent } from '../utils/windows-shim-fixer'; +import { pathExists, getSymlinkTarget } from '../utils'; + +export async function fixShimsCommand() { + if (process.platform !== 'win32') { + console.log(colors.yellow('This command is only for Windows.')); + return; + } + + const binDir = join(BVM_CURRENT_DIR, 'bin'); + if (!(await pathExists(binDir))) { + console.log(colors.red(`Global bin directory not found at ${binDir}`)); + return; + } + + // Resolve real path of current version + const versionDir = await getSymlinkTarget(BVM_CURRENT_DIR); + if (!versionDir) { + console.log(colors.red('Could not resolve current Bun version directory.')); + return; + } + + console.log(colors.cyan(`Scanning for broken shims in ${binDir}...`)); + + const files = await readdir(binDir); + let fixedCount = 0; + + for (const file of files) { + if (file.endsWith('.cmd')) { + const filePath = join(binDir, file); + const content = await readFile(filePath, 'utf8'); + const fixed = fixShimContent(content, versionDir); + + if (content !== fixed) { + await writeFile(filePath, fixed, 'utf8'); + console.log(colors.green(`✓ Fixed ${file}`)); + fixedCount++; + } + } + } + + if (fixedCount === 0) { + console.log(colors.gray('No broken shims found.')); + } else { + console.log(colors.green(`\nSuccessfully fixed ${fixedCount} shim(s).`)); + } +} diff --git a/src/commands/use.ts b/src/commands/use.ts index 9162537..6212b48 100644 --- a/src/commands/use.ts +++ b/src/commands/use.ts @@ -52,6 +52,32 @@ export async function useBunVersion(targetVersion?: string, options: { silent?: // Update the 'current' directory symlink for immediate global effect await createSymlink(installPath, BVM_CURRENT_DIR); + // Verify if current/bin is in PATH + try { + const currentBinPath = join(BVM_CURRENT_DIR, 'bin'); + // Normalize paths for comparison (handle separators) + const normalizedCurrentBin = currentBinPath.replace(/\\/g, '/'); + const delimiter = require('path').delimiter; + const pathEntries = (process.env.PATH || '').split(delimiter); + + const isPathConfigured = pathEntries.some(p => { + const normalizedP = p.replace(/\\/g, '/'); + // Check for exact match or if it ends with .bvm/current/bin + return normalizedP.includes(normalizedCurrentBin) || normalizedP.endsWith('/.bvm/current/bin'); + }); + + if (!isPathConfigured && !options.silent) { + if (spinner) spinner.stop(); // Stop spinner to print warning cleanly + console.log(colors.yellow(`\n⚠️ Warning: Global bin directory is not in your PATH.`)); + console.log(colors.yellow(` Global packages (e.g., 'bun install -g') may not be found.`)); + console.log(colors.gray(` Please add the following to your PATH:`)); + console.log(colors.white(` ${currentBinPath}`)); + if (spinner) spinner.start(); // Restart spinner if needed, or just leave it stopped as we are done + } + } catch (e: any) { + // console.error("Path check error:", e); + } + if (spinner) { spinner.succeed(colors.green(`Now using Bun ${normalizedFinalResolvedVersion} (immediate effect).`)); } diff --git a/src/index.ts b/src/index.ts index a029874..257a3a1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,6 +20,7 @@ import { cacheCommand } from './commands/cache'; import { configureShell } from './commands/setup'; import { upgradeBvm } from './commands/upgrade'; import { doctor } from './commands/doctor'; +import { fixShimsCommand } from './commands/fix-shims'; import { rehash } from './commands/rehash'; import { printCompletion } from './commands/completion'; import { colors } from './utils/ui'; @@ -220,6 +221,9 @@ async function main() { app.command('doctor', 'Show diagnostics for Bun/BVM setup') .action(async () => { await doctor(); }); + app.command('fix-shims', 'Fix relative paths in Windows global shims') + .action(async () => { await fixShimsCommand(); }); + app.command('completion ', 'Generate shell completion script (bash|zsh|fish)') .action(async (args) => { if (!args[0]) throw new Error('Shell name is required'); printCompletion(args[0]); }); diff --git a/src/templates/win/bvm-shim.js b/src/templates/win/bvm-shim.js index 0294113..97ebc0e 100644 --- a/src/templates/win/bvm-shim.js +++ b/src/templates/win/bvm-shim.js @@ -70,7 +70,36 @@ process.env.BUN_INSTALL = versionDir; process.env.PATH = binDir + path.delimiter + process.env.PATH; const child = spawn(realExecutable, ARGS, { stdio: 'inherit', shell: false }); -child.on('exit', (code) => process.exit(code ?? 0)); +child.on('exit', (code) => { + if (code === 0 && (CMD === 'bun' || CMD === 'bunx')) { + const isGlobal = ARGS.includes('-g') || ARGS.includes('--global'); + const isInstall = ARGS.includes('install') || ARGS.includes('add') || ARGS.includes('remove') || ARGS.includes('upgrade'); + + if (isGlobal && isInstall) { + try { + fixShims(binDir, versionDir); + } catch(e) {} + } + } + process.exit(code ?? 0); +}); + +function fixShims(binDir, versionDir) { + try { + const files = fs.readdirSync(binDir); + for (const file of files) { + if (file.endsWith('.cmd')) { + const filePath = path.join(binDir, file); + let content = fs.readFileSync(filePath, 'utf8'); + if (content.includes('%~dp0\\..')) { + content = content.split('%~dp0\\..').join(versionDir); + fs.writeFileSync(filePath, content, 'utf8'); + } + } + } + } catch(e) {} +} + child.on('error', (err) => { console.error("BVM Error: Failed to start child process: " + err.message); process.exit(1); diff --git a/src/utils/windows-shim-fixer.ts b/src/utils/windows-shim-fixer.ts new file mode 100644 index 0000000..daa3f79 --- /dev/null +++ b/src/utils/windows-shim-fixer.ts @@ -0,0 +1,12 @@ +/** + * Fixes Windows Shim files by replacing relative paths with absolute paths. + * This resolves the issue where Shims fail when executed via a Junction (e.g. .bvm/current). + */ +export function fixShimContent(content: string, absoluteVersionDir: string): string { + // The pattern Bun uses: "%~dp0\.." + // We want to replace it with the absolute path to the version directory. + const searchPattern = "%~dp0\\.."; + + // Simple string replacement (global) + return content.split(searchPattern).join(absoluteVersionDir); +} diff --git a/test/windows_shim_patching.test.ts b/test/windows_shim_patching.test.ts new file mode 100644 index 0000000..2a3db98 --- /dev/null +++ b/test/windows_shim_patching.test.ts @@ -0,0 +1,13 @@ +import { describe, test, expect } from "bun:test"; +import { fixShimContent } from "../src/utils/windows-shim-fixer"; + +describe("Windows Shim Patching", () => { + test("Replaces relative path with absolute path", () => { + const shimContent = `@ECHO OFF\r\n\"%~dp0\\..\\node_modules\\pkg\\cli.js\" %*`; + const versionDir = "C:\\Users\\.bvm\\versions\\v1"; + + const fixed = fixShimContent(shimContent, versionDir); + + expect(fixed).toBe(`@ECHO OFF\r\n\"${versionDir}\\node_modules\\pkg\\cli.js\" %*`); + }); +}); \ No newline at end of file From a7f9429dd71c35570365e1e5988d33e1638b1dff Mon Sep 17 00:00:00 2001 From: "lei.liao" Date: Mon, 26 Jan 2026 10:06:12 +0800 Subject: [PATCH 2/6] chore(release): v1.1.31 --- conductor/tracks.md | 1 + .../tracks/release_v1_1_31_20260126/index.md | 5 ++ .../release_v1_1_31_20260126/metadata.json | 8 +++ .../tracks/release_v1_1_31_20260126/plan.md | 23 +++++++++ .../tracks/release_v1_1_31_20260126/spec.md | 20 ++++++++ install.ps1 | 2 +- install.sh | 2 +- package.json | 2 +- src/commands/fix-shims.ts | 51 ------------------- src/index.ts | 4 -- src/utils/windows-shim-fixer.ts | 12 ----- test/windows_shim_patching.test.ts | 13 ----- 12 files changed, 60 insertions(+), 83 deletions(-) create mode 100644 conductor/tracks/release_v1_1_31_20260126/index.md create mode 100644 conductor/tracks/release_v1_1_31_20260126/metadata.json create mode 100644 conductor/tracks/release_v1_1_31_20260126/plan.md create mode 100644 conductor/tracks/release_v1_1_31_20260126/spec.md delete mode 100644 src/commands/fix-shims.ts delete mode 100644 src/utils/windows-shim-fixer.ts delete mode 100644 test/windows_shim_patching.test.ts diff --git a/conductor/tracks.md b/conductor/tracks.md index f153e88..a6ef94a 100644 --- a/conductor/tracks.md +++ b/conductor/tracks.md @@ -397,3 +397,4 @@ This file tracks all major tracks for the project. Each track has its own detail \n---\n\n- [x] **Track: 修复 Windows 下全局包 Shim 的相对路径解析错误**\n*Link: [./conductor/tracks/fix_windows_global_shim_resolution_20260126/](./conductor/tracks/fix_windows_global_shim_resolution_20260126/)* +\n---\n\n- [~] **Track: Release BVM v1.1.31 (Patch Fixes)**\n*Link: [./conductor/tracks/release_v1_1_31_20260126/](./conductor/tracks/release_v1_1_31_20260126/)* diff --git a/conductor/tracks/release_v1_1_31_20260126/index.md b/conductor/tracks/release_v1_1_31_20260126/index.md new file mode 100644 index 0000000..4bbe454 --- /dev/null +++ b/conductor/tracks/release_v1_1_31_20260126/index.md @@ -0,0 +1,5 @@ +# Track release_v1_1_31_20260126 Context + +- [Specification](./spec.md) +- [Implementation Plan](./plan.md) +- [Metadata](./metadata.json) diff --git a/conductor/tracks/release_v1_1_31_20260126/metadata.json b/conductor/tracks/release_v1_1_31_20260126/metadata.json new file mode 100644 index 0000000..4923c89 --- /dev/null +++ b/conductor/tracks/release_v1_1_31_20260126/metadata.json @@ -0,0 +1,8 @@ +{ + "track_id": "release_v1_1_31_20260126", + "type": "chore", + "status": "new", + "created_at": "2026-01-26T11:00:00Z", + "updated_at": "2026-01-26T11:00:00Z", + "description": "Release BVM v1.1.31 (Patch Fixes)" +} diff --git a/conductor/tracks/release_v1_1_31_20260126/plan.md b/conductor/tracks/release_v1_1_31_20260126/plan.md new file mode 100644 index 0000000..e21f464 --- /dev/null +++ b/conductor/tracks/release_v1_1_31_20260126/plan.md @@ -0,0 +1,23 @@ +# Implementation Plan: Release BVM v1.1.31 + +## Phase 1: Preparation & Synchronization +- [ ] Task: Update Version + - [ ] Bump `package.json` version to `1.1.31`. +- [ ] Task: Synchronize Runtime & Installer + - [ ] Run `bun run scripts/sync-runtime.ts` to update `install.sh` and `install.ps1`. + - [ ] Verify `install.sh` contains `DEFAULT_BVM_VERSION="v1.1.31"`. + - [ ] Verify `install.ps1` contains `$DEFAULT_BVM_VER = "v1.1.31"`. +- [ ] Task: Conductor - User Manual Verification 'Phase 1' + +## Phase 2: Build & Verify +- [ ] Task: Build Distribution + - [ ] Run `npm run build` (This also runs sync-runtime, but explicit step above ensures correctness). + - [ ] Run `bun run scripts/check-integrity.ts` to ensure consistency. +- [ ] Task: Conductor - User Manual Verification 'Phase 2' + +## Phase 3: Commit & Finalize +- [ ] Task: Commit Release + - [ ] Stage `package.json`, `install.sh`, `install.ps1`, `dist/`. + - [ ] Commit message: `chore(release): v1.1.31`. + - [ ] Create Git Tag `v1.1.31`. +- [ ] Task: Conductor - User Manual Verification 'Phase 3' diff --git a/conductor/tracks/release_v1_1_31_20260126/spec.md b/conductor/tracks/release_v1_1_31_20260126/spec.md new file mode 100644 index 0000000..d635959 --- /dev/null +++ b/conductor/tracks/release_v1_1_31_20260126/spec.md @@ -0,0 +1,20 @@ +# Specification: Release BVM v1.1.31 + +## 1. Overview +Release version 1.1.31 of BVM-Core. This is a patch release focusing on critical fixes for global package management on Windows and general usability improvements. + +## 2. Changes +- **Fix (Windows):** Resolved `Module not found` errors for global packages by automatically injecting absolute paths into Bun-generated shims (overcoming Junction relative path limits). +- **Feat (UX):** Added automatic PATH verification in `bvm use`. Warns users if `~/.bvm/current/bin` is missing from their PATH. +- **Docs:** Updated installation scripts to explicitly mention global binary path requirements. + +## 3. Protocol (Architectural) +- **Synchronization:** `install.sh` and `install.ps1` MUST be updated with `v1.1.31` using `sync-runtime.ts`. +- **Integrity:** `check-integrity.ts` must pass. +- **Build:** `dist/index.js` must be rebuilt. + +## 4. Deliverables +- Updated `package.json` (v1.1.31). +- Updated `install.sh` (DEFAULT_BVM_VERSION="v1.1.31"). +- Updated `install.ps1` ($DEFAULT_BVM_VER="v1.1.31"). +- Git Tag `v1.1.31`. diff --git a/install.ps1 b/install.ps1 index 66e25a9..ef69407 100644 --- a/install.ps1 +++ b/install.ps1 @@ -39,7 +39,7 @@ function Detect-NetworkZone { $BVM_REGION = Detect-NetworkZone $REGISTRY = if ($BVM_REGION -eq "cn") { "registry.npmmirror.com" } else { "registry.npmjs.org" } -$DEFAULT_BVM_VER = "v1.1.30" +$DEFAULT_BVM_VER = "v1.1.31" $BVM_VER = if ($env:BVM_INSTALL_VERSION) { $env:BVM_INSTALL_VERSION } else { "" } if (-not $BVM_VER) { try { diff --git a/install.sh b/install.sh index 0ac9611..ebcc63d 100755 --- a/install.sh +++ b/install.sh @@ -3,7 +3,7 @@ set -e # --- Configuration --- -DEFAULT_BVM_VERSION="v1.1.30" # Fallback +DEFAULT_BVM_VERSION="v1.1.31" # Fallback FALLBACK_BUN_VERSION="1.3.6" BVM_SRC_VERSION="${BVM_INSTALL_VERSION}" # If empty, will resolve dynamically diff --git a/package.json b/package.json index e2bdc76..80e7af2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bvm-core", - "version": "1.1.30", + "version": "1.1.31", "description": "The native version manager for Bun. Cross-platform, shell-agnostic, and zero-dependency.", "main": "dist/index.js", "bin": { diff --git a/src/commands/fix-shims.ts b/src/commands/fix-shims.ts deleted file mode 100644 index 7227a62..0000000 --- a/src/commands/fix-shims.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { join } from 'path'; -import { readdir, readFile, writeFile } from 'fs/promises'; -import { BVM_CURRENT_DIR } from '../constants'; -import { colors } from '../utils/ui'; -import { fixShimContent } from '../utils/windows-shim-fixer'; -import { pathExists, getSymlinkTarget } from '../utils'; - -export async function fixShimsCommand() { - if (process.platform !== 'win32') { - console.log(colors.yellow('This command is only for Windows.')); - return; - } - - const binDir = join(BVM_CURRENT_DIR, 'bin'); - if (!(await pathExists(binDir))) { - console.log(colors.red(`Global bin directory not found at ${binDir}`)); - return; - } - - // Resolve real path of current version - const versionDir = await getSymlinkTarget(BVM_CURRENT_DIR); - if (!versionDir) { - console.log(colors.red('Could not resolve current Bun version directory.')); - return; - } - - console.log(colors.cyan(`Scanning for broken shims in ${binDir}...`)); - - const files = await readdir(binDir); - let fixedCount = 0; - - for (const file of files) { - if (file.endsWith('.cmd')) { - const filePath = join(binDir, file); - const content = await readFile(filePath, 'utf8'); - const fixed = fixShimContent(content, versionDir); - - if (content !== fixed) { - await writeFile(filePath, fixed, 'utf8'); - console.log(colors.green(`✓ Fixed ${file}`)); - fixedCount++; - } - } - } - - if (fixedCount === 0) { - console.log(colors.gray('No broken shims found.')); - } else { - console.log(colors.green(`\nSuccessfully fixed ${fixedCount} shim(s).`)); - } -} diff --git a/src/index.ts b/src/index.ts index 257a3a1..a029874 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,7 +20,6 @@ import { cacheCommand } from './commands/cache'; import { configureShell } from './commands/setup'; import { upgradeBvm } from './commands/upgrade'; import { doctor } from './commands/doctor'; -import { fixShimsCommand } from './commands/fix-shims'; import { rehash } from './commands/rehash'; import { printCompletion } from './commands/completion'; import { colors } from './utils/ui'; @@ -221,9 +220,6 @@ async function main() { app.command('doctor', 'Show diagnostics for Bun/BVM setup') .action(async () => { await doctor(); }); - app.command('fix-shims', 'Fix relative paths in Windows global shims') - .action(async () => { await fixShimsCommand(); }); - app.command('completion ', 'Generate shell completion script (bash|zsh|fish)') .action(async (args) => { if (!args[0]) throw new Error('Shell name is required'); printCompletion(args[0]); }); diff --git a/src/utils/windows-shim-fixer.ts b/src/utils/windows-shim-fixer.ts deleted file mode 100644 index daa3f79..0000000 --- a/src/utils/windows-shim-fixer.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Fixes Windows Shim files by replacing relative paths with absolute paths. - * This resolves the issue where Shims fail when executed via a Junction (e.g. .bvm/current). - */ -export function fixShimContent(content: string, absoluteVersionDir: string): string { - // The pattern Bun uses: "%~dp0\.." - // We want to replace it with the absolute path to the version directory. - const searchPattern = "%~dp0\\.."; - - // Simple string replacement (global) - return content.split(searchPattern).join(absoluteVersionDir); -} diff --git a/test/windows_shim_patching.test.ts b/test/windows_shim_patching.test.ts deleted file mode 100644 index 2a3db98..0000000 --- a/test/windows_shim_patching.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { describe, test, expect } from "bun:test"; -import { fixShimContent } from "../src/utils/windows-shim-fixer"; - -describe("Windows Shim Patching", () => { - test("Replaces relative path with absolute path", () => { - const shimContent = `@ECHO OFF\r\n\"%~dp0\\..\\node_modules\\pkg\\cli.js\" %*`; - const versionDir = "C:\\Users\\.bvm\\versions\\v1"; - - const fixed = fixShimContent(shimContent, versionDir); - - expect(fixed).toBe(`@ECHO OFF\r\n\"${versionDir}\\node_modules\\pkg\\cli.js\" %*`); - }); -}); \ No newline at end of file From e8f05ace17c816665abd0c0e5f12b99d2f1ce22a Mon Sep 17 00:00:00 2001 From: "lei.liao" Date: Mon, 26 Jan 2026 10:06:20 +0800 Subject: [PATCH 3/6] chore(conductor): Mark track 'Release BVM v1.1.31' as complete --- conductor/tracks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conductor/tracks.md b/conductor/tracks.md index a6ef94a..965e977 100644 --- a/conductor/tracks.md +++ b/conductor/tracks.md @@ -397,4 +397,4 @@ This file tracks all major tracks for the project. Each track has its own detail \n---\n\n- [x] **Track: 修复 Windows 下全局包 Shim 的相对路径解析错误**\n*Link: [./conductor/tracks/fix_windows_global_shim_resolution_20260126/](./conductor/tracks/fix_windows_global_shim_resolution_20260126/)* -\n---\n\n- [~] **Track: Release BVM v1.1.31 (Patch Fixes)**\n*Link: [./conductor/tracks/release_v1_1_31_20260126/](./conductor/tracks/release_v1_1_31_20260126/)* +\n---\n\n- [x] **Track: Release BVM v1.1.31 (Patch Fixes)**\n*Link: [./conductor/tracks/release_v1_1_31_20260126/](./conductor/tracks/release_v1_1_31_20260126/)* From 4a8650ebb53ec93a8590df528a61ae5f98dcd280 Mon Sep 17 00:00:00 2001 From: "lei.liao" Date: Mon, 26 Jan 2026 10:07:17 +0800 Subject: [PATCH 4/6] chore(conductor): Archive completed tracks --- .../fix_windows_global_shim_resolution_20260126/index.md | 0 .../fix_windows_global_shim_resolution_20260126/metadata.json | 0 .../fix_windows_global_shim_resolution_20260126/plan.md | 0 .../fix_windows_global_shim_resolution_20260126/spec.md | 0 conductor/{tracks => archive}/release_v1_1_31_20260126/index.md | 0 .../{tracks => archive}/release_v1_1_31_20260126/metadata.json | 0 conductor/{tracks => archive}/release_v1_1_31_20260126/plan.md | 0 conductor/{tracks => archive}/release_v1_1_31_20260126/spec.md | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename conductor/{tracks => archive}/fix_windows_global_shim_resolution_20260126/index.md (100%) rename conductor/{tracks => archive}/fix_windows_global_shim_resolution_20260126/metadata.json (100%) rename conductor/{tracks => archive}/fix_windows_global_shim_resolution_20260126/plan.md (100%) rename conductor/{tracks => archive}/fix_windows_global_shim_resolution_20260126/spec.md (100%) rename conductor/{tracks => archive}/release_v1_1_31_20260126/index.md (100%) rename conductor/{tracks => archive}/release_v1_1_31_20260126/metadata.json (100%) rename conductor/{tracks => archive}/release_v1_1_31_20260126/plan.md (100%) rename conductor/{tracks => archive}/release_v1_1_31_20260126/spec.md (100%) diff --git a/conductor/tracks/fix_windows_global_shim_resolution_20260126/index.md b/conductor/archive/fix_windows_global_shim_resolution_20260126/index.md similarity index 100% rename from conductor/tracks/fix_windows_global_shim_resolution_20260126/index.md rename to conductor/archive/fix_windows_global_shim_resolution_20260126/index.md diff --git a/conductor/tracks/fix_windows_global_shim_resolution_20260126/metadata.json b/conductor/archive/fix_windows_global_shim_resolution_20260126/metadata.json similarity index 100% rename from conductor/tracks/fix_windows_global_shim_resolution_20260126/metadata.json rename to conductor/archive/fix_windows_global_shim_resolution_20260126/metadata.json diff --git a/conductor/tracks/fix_windows_global_shim_resolution_20260126/plan.md b/conductor/archive/fix_windows_global_shim_resolution_20260126/plan.md similarity index 100% rename from conductor/tracks/fix_windows_global_shim_resolution_20260126/plan.md rename to conductor/archive/fix_windows_global_shim_resolution_20260126/plan.md diff --git a/conductor/tracks/fix_windows_global_shim_resolution_20260126/spec.md b/conductor/archive/fix_windows_global_shim_resolution_20260126/spec.md similarity index 100% rename from conductor/tracks/fix_windows_global_shim_resolution_20260126/spec.md rename to conductor/archive/fix_windows_global_shim_resolution_20260126/spec.md diff --git a/conductor/tracks/release_v1_1_31_20260126/index.md b/conductor/archive/release_v1_1_31_20260126/index.md similarity index 100% rename from conductor/tracks/release_v1_1_31_20260126/index.md rename to conductor/archive/release_v1_1_31_20260126/index.md diff --git a/conductor/tracks/release_v1_1_31_20260126/metadata.json b/conductor/archive/release_v1_1_31_20260126/metadata.json similarity index 100% rename from conductor/tracks/release_v1_1_31_20260126/metadata.json rename to conductor/archive/release_v1_1_31_20260126/metadata.json diff --git a/conductor/tracks/release_v1_1_31_20260126/plan.md b/conductor/archive/release_v1_1_31_20260126/plan.md similarity index 100% rename from conductor/tracks/release_v1_1_31_20260126/plan.md rename to conductor/archive/release_v1_1_31_20260126/plan.md diff --git a/conductor/tracks/release_v1_1_31_20260126/spec.md b/conductor/archive/release_v1_1_31_20260126/spec.md similarity index 100% rename from conductor/tracks/release_v1_1_31_20260126/spec.md rename to conductor/archive/release_v1_1_31_20260126/spec.md From dc8d6ffcf372bc2cfc2d7442d9f371f564025a16 Mon Sep 17 00:00:00 2001 From: "lei.liao" Date: Mon, 26 Jan 2026 10:08:42 +0800 Subject: [PATCH 5/6] chore(conductor): Cleanup tracks registry --- conductor/tracks.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/conductor/tracks.md b/conductor/tracks.md index 965e977..a1fe89a 100644 --- a/conductor/tracks.md +++ b/conductor/tracks.md @@ -396,5 +396,4 @@ This file tracks all major tracks for the project. Each track has its own detail -\n---\n\n- [x] **Track: 修复 Windows 下全局包 Shim 的相对路径解析错误**\n*Link: [./conductor/tracks/fix_windows_global_shim_resolution_20260126/](./conductor/tracks/fix_windows_global_shim_resolution_20260126/)* -\n---\n\n- [x] **Track: Release BVM v1.1.31 (Patch Fixes)**\n*Link: [./conductor/tracks/release_v1_1_31_20260126/](./conductor/tracks/release_v1_1_31_20260126/)* + From f516797c15c3369165c35b99f56d2b6e03203448 Mon Sep 17 00:00:00 2001 From: "lei.liao" Date: Mon, 26 Jan 2026 11:33:52 +0800 Subject: [PATCH 6/6] chore(release): v1.1.32 --- conductor/tracks.md | 1 + .../tracks/release_v1_1_32_20260126/index.md | 5 +++++ .../release_v1_1_32_20260126/metadata.json | 8 ++++++++ .../tracks/release_v1_1_32_20260126/plan.md | 20 +++++++++++++++++++ .../tracks/release_v1_1_32_20260126/spec.md | 15 ++++++++++++++ install.ps1 | 2 +- install.sh | 2 +- package.json | 2 +- 8 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 conductor/tracks/release_v1_1_32_20260126/index.md create mode 100644 conductor/tracks/release_v1_1_32_20260126/metadata.json create mode 100644 conductor/tracks/release_v1_1_32_20260126/plan.md create mode 100644 conductor/tracks/release_v1_1_32_20260126/spec.md diff --git a/conductor/tracks.md b/conductor/tracks.md index a1fe89a..3442b8d 100644 --- a/conductor/tracks.md +++ b/conductor/tracks.md @@ -397,3 +397,4 @@ This file tracks all major tracks for the project. Each track has its own detail +\n---\n\n- [~] **Track: Release BVM v1.1.32**\n*Link: [./conductor/tracks/release_v1_1_32_20260126/](./conductor/tracks/release_v1_1_32_20260126/)* diff --git a/conductor/tracks/release_v1_1_32_20260126/index.md b/conductor/tracks/release_v1_1_32_20260126/index.md new file mode 100644 index 0000000..b44e51b --- /dev/null +++ b/conductor/tracks/release_v1_1_32_20260126/index.md @@ -0,0 +1,5 @@ +# Track release_v1_1_32_20260126 Context + +- [Specification](./spec.md) +- [Implementation Plan](./plan.md) +- [Metadata](./metadata.json) diff --git a/conductor/tracks/release_v1_1_32_20260126/metadata.json b/conductor/tracks/release_v1_1_32_20260126/metadata.json new file mode 100644 index 0000000..e07e6fa --- /dev/null +++ b/conductor/tracks/release_v1_1_32_20260126/metadata.json @@ -0,0 +1,8 @@ +{ + "track_id": "release_v1_1_32_20260126", + "type": "chore", + "status": "new", + "created_at": "2026-01-26T11:30:00Z", + "updated_at": "2026-01-26T11:30:00Z", + "description": "Release BVM v1.1.32" +} diff --git a/conductor/tracks/release_v1_1_32_20260126/plan.md b/conductor/tracks/release_v1_1_32_20260126/plan.md new file mode 100644 index 0000000..c1af283 --- /dev/null +++ b/conductor/tracks/release_v1_1_32_20260126/plan.md @@ -0,0 +1,20 @@ +# Implementation Plan: Release BVM v1.1.32 + +## Phase 1: Update Version +- [ ] Task: Bump version to 1.1.32 + - [ ] Update `package.json`. + - [ ] Run `sync-runtime`. +- [ ] Task: Conductor - User Manual Verification 'Phase 1' + +## Phase 2: Build & Verify +- [ ] Task: Build + - [ ] Run `npm run build`. + - [ ] Run `check-integrity`. +- [ ] Task: Conductor - User Manual Verification 'Phase 2' + +## Phase 3: Finalize +- [ ] Task: Commit & Push + - [ ] Commit changes. + - [ ] Tag `v1.1.32`. + - [ ] Push to `test`. +- [ ] Task: Conductor - User Manual Verification 'Phase 3' diff --git a/conductor/tracks/release_v1_1_32_20260126/spec.md b/conductor/tracks/release_v1_1_32_20260126/spec.md new file mode 100644 index 0000000..e7677f0 --- /dev/null +++ b/conductor/tracks/release_v1_1_32_20260126/spec.md @@ -0,0 +1,15 @@ +# Specification: Release BVM v1.1.32 + +## 1. Overview +Release version 1.1.32 of BVM-Core. + +## 2. Changes +- Bump version to 1.1.32 to trigger new release cycle. + +## 3. Protocol +- Synchronize version in `package.json`, `install.sh`, `install.ps1`. +- Build dist artifacts. +- Verify integrity. + +## 4. Deliverables +- Git Tag `v1.1.32`. diff --git a/install.ps1 b/install.ps1 index ef69407..cf0217c 100644 --- a/install.ps1 +++ b/install.ps1 @@ -39,7 +39,7 @@ function Detect-NetworkZone { $BVM_REGION = Detect-NetworkZone $REGISTRY = if ($BVM_REGION -eq "cn") { "registry.npmmirror.com" } else { "registry.npmjs.org" } -$DEFAULT_BVM_VER = "v1.1.31" +$DEFAULT_BVM_VER = "v1.1.32" $BVM_VER = if ($env:BVM_INSTALL_VERSION) { $env:BVM_INSTALL_VERSION } else { "" } if (-not $BVM_VER) { try { diff --git a/install.sh b/install.sh index ebcc63d..73e2b5a 100755 --- a/install.sh +++ b/install.sh @@ -3,7 +3,7 @@ set -e # --- Configuration --- -DEFAULT_BVM_VERSION="v1.1.31" # Fallback +DEFAULT_BVM_VERSION="v1.1.32" # Fallback FALLBACK_BUN_VERSION="1.3.6" BVM_SRC_VERSION="${BVM_INSTALL_VERSION}" # If empty, will resolve dynamically diff --git a/package.json b/package.json index 80e7af2..3a4045a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bvm-core", - "version": "1.1.31", + "version": "1.1.32", "description": "The native version manager for Bun. Cross-platform, shell-agnostic, and zero-dependency.", "main": "dist/index.js", "bin": {