- Replace fileURLToPath(import.meta.url) with import.meta.dirname across
scripts and extensions
- Rename parsers-legacy.ts → parsers.ts
- Remove deleted plan/spec docs (cicd-pipeline)
- Update package.json engines and deps across workspace packages
- Update web/package-lock.json
💘 Generated with Crush
Assisted-by: GLM-5.1 via Crush <crush@charm.land>
18 KiB
故障排查
/sf doctor
内置诊断工具会校验 .sf/ 的完整性:
/sf doctor
它会检查:
- 文件结构和命名约定
- roadmap ↔ slice ↔ task 的引用完整性
- 完成状态是否一致
- Git worktree 健康状态(仅 worktree 和 branch 模式;none 模式跳过)
- 过期锁文件和孤儿运行时记录
常见问题
自动模式在同一个单元上循环
症状: 同一个工作单元(例如 research-slice 或 plan-slice)被反复派发,直到触发 dispatch 上限。
原因:
- 崩溃后的缓存过期:内存中的文件列表没有反映新产物
- LLM 没有生成预期的 artifact 文件
解决: 先运行 /sf doctor 修复状态,然后执行 /sf auto 恢复。如果问题持续存在,检查预期 artifact 文件是否确实已经写到磁盘。
自动模式因 “Loop detected” 停止
原因: 同一个单元连续两次没有生成预期 artifact。
解决: 检查 task plan 是否足够清晰。如果 plan 存在歧义,先手动澄清,再执行 /sf auto 恢复。
Worktree 中出现了错误文件
症状: Planning 产物或代码被写到了错误目录。
原因: LLM 把内容写回了主仓库,而不是 worktree。
解决: 该问题已在 v2.14+ 修复。如果你仍在旧版本,请更新。现在 dispatch prompt 已包含明确的工作目录指令。
安装后出现 command not found: sf
症状: npm install -g sf-run 成功,但系统找不到 sf。
原因: npm 的全局 bin 目录没有加入 shell 的 $PATH。
解决:
# 找出 npm 安装二进制的目录
npm prefix -g
# 输出:/opt/homebrew(Apple Silicon)或 /usr/local(Intel Mac)
# 如果缺失,把 bin 目录加入 PATH
echo 'export PATH="$(npm prefix -g)/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
临时方案: 直接执行 npx sf-run,或使用 $(npm prefix -g)/bin/sf。
常见原因:
- Homebrew Node:理论上
/opt/homebrew/bin应该在 PATH 里,但如果 shell profile 没有初始化 Homebrew,就可能缺失 - 版本管理器(nvm、fnm、mise):全局 bin 路径是按版本区分的,需确保版本管理器正确初始化
- oh-my-zsh:
gitfast插件会把sfalias 到git svn dcommit。可通过alias sf检查,并在需要时取消 alias
npm install -g sf-run 失败
常见原因:
- 缺少 workspace packages:已在 v2.10.4+ 修复
- Linux 上
postinstall卡住(Playwright--with-deps触发 sudo):已在 v2.3.6+ 修复 - Node.js 版本过低:要求 ≥ 24.0.0
自动模式中的 provider 错误
症状: 自动模式因为 provider 错误暂停(限流、服务端错误、认证失败)。
SF 的处理方式(v2.26):
| 错误类型 | 自动恢复? | 延迟 |
|---|---|---|
Rate limit(429、too many requests) |
✅ 是 | retry-after 头或默认 60 秒 |
Server error(500、502、503、overloaded) |
✅ 是 | 30 秒 |
Auth / billing(unauthorized、invalid key) |
❌ 否 | 需要手动恢复 |
对于瞬时错误,SF 会短暂停顿后自动继续。对于永久性错误,建议配置 fallback models:
models:
execution:
model: claude-sonnet-4-6
fallbacks:
- openrouter/minimax/minimax-m2.5
Headless 模式: sf headless auto 在进程崩溃时会自动重启整个进程(默认 3 次,带指数退避)。与 provider 错误自动恢复配合后,能支持真正的夜间无人值守运行。
常见的 provider 配置问题(role 错误、streaming 错误、model ID 不匹配)见 Provider 设置指南:常见坑点。
达到预算上限
症状: 自动模式因 “Budget ceiling reached” 暂停。
解决: 提高偏好设置中的 budget_ceiling,或者切换到 budget token profile 降低每个工作单元成本,然后再执行 /sf auto 恢复。
过期锁文件
症状: 自动模式无法启动,提示另一个会话正在运行。
解决: SF 会自动检测过期锁:如果持有锁的 PID 已死亡,则在下次 /sf auto 时清理并重新获取锁。它也会处理 proper-lockfile 崩溃后遗留的 .sf.lock/ 目录。如果自动恢复失败,可手动删除 .sf/auto.lock 和 .sf.lock/:
rm -f .sf/auto.lock
rm -rf "$(dirname .sf)/.sf.lock"
Git merge 冲突
症状: Worktree merge 在 .sf/ 文件上失败。
解决: SF 会自动解决 .sf/ 运行时文件上的冲突。对于代码文件的内容冲突,LLM 会先获得一次 fix-merge 会话进行自动修复;若失败,则需要手动解决。
Pre-dispatch 提示 milestone integration branch 已不存在
症状: 自动模式或 /sf doctor 报告某个 milestone 记录的 integration branch 已经不在 git 中。
这意味着什么: 该 milestone 的 .sf/milestones/<MID>/<MID>-META.json 里仍然记录着启动时的 branch,但该 branch 之后被重命名或删除了。
当前行为:
- 如果 SF 能确定性地恢复到一个安全 branch,就不会再直接 hard-stop 自动模式
- 安全回退的顺序是:
- 显式配置且存在的
git.main_branch - 仓库自动检测到的默认 integration branch(例如
main或master)
- 显式配置且存在的
- 在这种情况下,
/sf doctor会给出 warning,而/sf doctor fix会把过期的 metadata 改写为当前有效 branch - 如果无法确定安全回退 branch,SF 仍会阻止继续运行
解决:
- 先执行
/sf doctor fix,在安全回退很明显时自动改写过期 metadata - 如果 SF 仍然阻塞,则请重新创建缺失 branch,或更新 git 偏好设置,让
git.main_branch指向一个真实存在的 branch
写 .sf/ 文件时出现瞬时 EBUSY / EPERM / EACCES
症状: 在 Windows 上,自动模式或 doctor 在更新 .sf/ 文件时偶发 EBUSY、EPERM 或 EACCES。
原因: 杀毒软件、索引器、编辑器或文件监视器可能会在 SF 执行原子 rename 的瞬间,短暂锁住目标文件或临时文件。
当前行为: SF 现在会对这类瞬时 rename 失败做短时、有上界的退避重试;这样既能覆盖短暂锁竞争,也不会因为真正的文件系统问题而无限挂起。
解决:
- 重新执行操作;大多数瞬时锁竞争会很快自行解除
- 如果错误持续,关闭可能占用该文件的工具后再试
- 如果反复失败,运行
/sf doctor,确认仓库状态依旧健康,并记录具体路径与错误码
Node v24 Web 启动失败
症状: 在 Node v24 上执行 sf --web 时,报 ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING。
原因: Node v24 修改了对 node_modules 的 type stripping 行为,导致 Next.js Web 构建失败。
解决: 已在 v2.42.0+ 修复(#1864)。升级到最新版本。
孤儿 Web server 进程
症状: sf --web 因端口 3000 已被占用而失败,但实际上并没有运行中的 SF 会话。
原因: 上一次 Web server 退出时未能清理进程。
解决: 已在 v2.42.0+ 修复。现在 SF 会自动清理过期的 Web server 进程。如果你还在旧版本,可手动终止孤儿进程:lsof -ti:3000 | xargs kill。
非 JS 项目被 worktree health check 阻挡
症状: 在不使用 Node.js 的项目(例如 Rust、Go、Python)中,worktree health check 失败或阻塞自动模式。
原因: 在 v2.42.0 之前,worktree health check 只识别 JavaScript 生态。
解决: 已在 v2.42.0+ 修复(#1860)。现在 health check 已支持 17+ 生态。升级到最新版本。
德语 / 非英语 locale 下的 git 错误
症状: 当系统 locale 不是英语(例如德语)时,Git 命令失败或输出异常。
原因: SF 之前假设 git 输出永远是英文。
解决: 已在 v2.42.0+ 修复。现在所有 git 命令都会强制 LC_ALL=C,从而无论系统 locale 如何,都保证 git 输出一致为英文。
MCP Client 问题
mcp_servers 显示没有已配置 servers
症状: mcp_servers 报告没有配置任何 server。
常见原因:
- 当前项目里不存在
.mcp.json或.sf/mcp.json - 配置文件不是合法 JSON
- 你是在另一个项目目录中配置的 server,但当前启动 SF 的目录不同
解决:
- 把 server 配置加到
.mcp.json或.sf/mcp.json - 确认文件能被正常解析为 JSON
- 重新执行
mcp_servers(refresh=true)
mcp_discover 超时
症状: mcp_discover 因超时失败。
常见原因:
- Server 进程启动了,但没有完成 MCP 握手
- 配置的命令指向一个启动时会卡住的脚本
- Server 正在等待某个不可用依赖或后端服务
解决:
- 在 SF 外部直接运行该命令,确认 server 能真正启动
- 检查后端 URL 或依赖服务是否可达
- 如果是本地自定义 server,确认它使用的是 MCP SDK 或正确的 stdio 协议实现
mcp_discover 报 connection closed
症状: mcp_discover 立即失败,并提示连接被关闭。
常见原因:
- 可执行文件路径错误
- 脚本路径错误
- 缺失运行时依赖
- Server 在响应前就崩溃了
解决:
- 确认
command和args路径正确且尽量使用绝对路径 - 手动运行命令,查看导入 / 运行时错误
- 检查配置中的解释器或运行时在当前机器上是否存在
mcp_call 因缺少必填参数失败
症状: MCP tool 已成功发现,但调用时因缺少必填字段而校验失败。
常见原因:
- 调用形状写错了
- 目标 server 的 tool schema 已更新
- 你调用的是旧 server 定义或旧分支构建
解决:
- 重新执行
mcp_discover(server="name"),确认实际要求的参数名 - 按
mcp_call(server="name", tool="tool_name", args={...})的形式调用 - 如果你正在开发 SF 本身,在 schema 变更后重新执行
npm run build
本地 stdio server 手动可用,但在 SF 中不可用
症状: 手动执行 server 命令没有问题,但 SF 连接不上。
常见原因:
- Server 依赖某些 SF 不会继承的 shell 状态
- 相对路径只有在另一个 working directory 中才成立
- 需要的环境变量存在于你的 shell 中,但没有写进 MCP 配置
解决:
- 对
command和脚本参数都使用绝对路径 - 把所需环境变量写进 MCP 配置的
env块 - 有必要时,在 server 定义里显式设置
cwd
Session lock 被另一个终端中的 /sf 抢走
症状: 在第二个终端运行 /sf(step mode)时,正在运行的自动模式会话失去了锁。
解决: 已在 v2.36.0 修复。现在裸 /sf 不会再从运行中的自动模式会话手里抢 session lock。升级到最新版本。
Worktree 中的提交落到了 main,而不是 milestone/<MID> 分支
症状: 自动模式在 worktree 中提交时,最终落在了 main,而不是 milestone/<MID>。
解决: 已在 v2.37.1 修复。现在 dispatch 前会重新校正 CWD,并在失败时清理过期 merge 状态。升级到最新版本。
Extension loader 因 subpath export 错误而失败
症状: 扩展加载时报 Cannot find module,并且错误信息引用了 npm subpath exports。
原因: Extension loader 中的动态导入过去无法解析 npm subpath exports(例如 @pkg/foo/bar)。
解决: 已在 v2.38+ 修复。现在 extension loader 会自动解析 npm subpath exports,并为动态导入创建 node_modules symlink。升级到最新版本。
恢复流程
重置自动模式状态
rm .sf/auto.lock
rm .sf/completed-units.json
然后执行 /sf auto,从当前磁盘状态重新开始。
重置路由历史
如果自适应模型路由给出了糟糕的结果,可以清空路由历史:
rm .sf/routing-history.json
完整重建状态
/sf doctor
Doctor 会从磁盘上的 plan 和 roadmap 文件重建 STATE.md,并修复检测到的不一致项。
获取帮助
- GitHub Issues: github.com/sf-build/SF/issues
- Dashboard:
Ctrl+Alt+G或/sf status,查看实时诊断信息 - Forensics:
/sf forensics,用于对自动模式失败做结构化事后分析 - Session logs:
.sf/activity/中包含用于崩溃取证的 JSONL 会话转储
iTerm2 专属问题
Ctrl+Alt 快捷键触发了错误动作(例如 Ctrl+Alt+G 打开了外部编辑器,而不是 SF dashboard)
症状: 按下 Ctrl+Alt+G 后,会触发外部编辑器提示(Ctrl+G),而不是 SF dashboard。其它 Ctrl+Alt 快捷键也表现得像它们对应的 Ctrl-only 快捷键。
原因: iTerm2 默认的 Left Option Key 设置是 “Normal”,这会吞掉 Ctrl+Alt 组合中的 Alt 修饰键。终端实际只收到了 Ctrl,所以 Ctrl+Alt+G 最终变成 Ctrl+G。
解决: 在 iTerm2 中进入 Profiles → Keys → General,把 Left Option Key 改成 Esc+。这样 Alt / Option 会发送 escape 前缀,终端应用就能正确识别 Ctrl+Alt 快捷键。
Windows 专属问题
Windows 上 LSP 返回 ENOENT(MSYS2 / Git Bash)
症状: LSP 初始化因 ENOENT 失败,或者把 /c/Users/... 这类 POSIX 路径错误地解析为 C:\Users\...。
原因: MSYS2 / Git Bash 中的 which 命令返回的是 POSIX 风格路径,而 Node.js 的 spawn() 无法正确解析。
解决: 已在 v2.29+ 修复,Windows 现在改用 where.exe。升级到最新版本。
构建 WXT / 浏览器扩展时出现 EBUSY
症状: 构建浏览器扩展时出现 EBUSY: resource busy or locked, rmdir .output/chrome-mv3。
原因: Chromium 浏览器仍然从构建输出目录加载着该扩展,导致目录无法删除。
解决: 关闭浏览器中的该扩展,或者在 WXT 配置里使用不同的 outDirTemplate,避开被锁住的目录。
数据库问题
“SF database is not available”
症状: sf_decision_save(及其别名 sf_save_decision)、sf_requirement_update(及其别名 sf_update_requirement)或 sf_summary_save(及其别名 sf_save_summary)报这个错误。
原因: SQLite 数据库未初始化。这个问题会出现在 v2.29 之前的手动 /sf 会话(非自动模式)中。
解决: 已在 v2.29+ 修复。现在数据库会在第一次 tool call 时自动初始化。升级到最新版本。
Verification 问题
Verification gate 因 shell 语法错误失败
症状: 在 verification 阶段出现 stderr: /bin/sh: 1: Syntax error: "(" unexpected。
原因: 某个描述性字符串(例如 All 10 checks pass (build, lint))被误当成 shell 命令执行。这通常发生在 task plans 的 verify: 字段里写了 prose,而不是实际命令。
解决: 已在 v2.29+ 修复,现在偏好命令会先通过 isLikelyCommand() 过滤。请确保偏好中的 verification_commands 只包含合法 shell 命令,而不是文字描述。
LSP(Language Server Protocol)
“LSP isn't available in this workspace”
SF 会根据项目文件自动检测 language servers(例如 package.json → TypeScript、Cargo.toml → Rust、go.mod → Go)。如果没有检测到 server,agent 会跳过 LSP 功能。
查看状态:
lsp status
它会显示哪些 servers 已经激活;如果一个都没找到,也会说明原因,包括发现了哪些项目标记、但缺失了哪些 server 命令。
常见修复方式:
| 项目类型 | 安装命令 |
|---|---|
| TypeScript / JavaScript | npm install -g typescript-language-server typescript |
| Python | pip install pyright 或 pip install python-lsp-server |
| Rust | rustup component add rust-analyzer |
| Go | go install golang.org/x/tools/gopls@latest |
安装完成后,执行 lsp reload 即可重新检测,无需重启 SF。
Notifications
macOS 上通知不显示
症状: 偏好中已设置 notifications.enabled: true,但自动模式期间没有任何桌面通知(没有 milestone 完成提示、预算预警或错误通知),同时日志里也没有报错。
原因: SF 在 macOS 上会把 osascript display notification 作为回退方案。这个命令的通知归属你的终端应用(Ghostty、iTerm2、Alacritty、Kitty、Warp 等)。如果该终端应用在 System Settings → Notifications 中没有权限,macOS 会静默丢弃通知,而 osascript 仍然返回 0,不会报错。
很多终端应用只有在成功送出过至少一条通知后,才会出现在通知设置面板里,这就形成了“先能通知,系统才给你配置通知”的鸡生蛋蛋生鸡问题。
推荐修复方式: 安装 terminal-notifier,它会注册为独立的 Notification Center 应用:
brew install terminal-notifier
SF 在检测到 terminal-notifier 可用时会自动优先使用它。首次使用时,macOS 会弹出通知权限请求,这是预期行为。
替代修复方式: 进入 System Settings → Notifications,为你的终端应用启用通知。如果终端应用不在列表中,可以先在 Terminal.app 中手动发送一条测试通知,注册出 “Script Editor”:
osascript -e 'display notification "test" with title "SF"'
验证: 完成任一修复后,用下面命令测试:
terminal-notifier -title "SF" -message "working!" -sound Glass