gstack GBrain Sync 错误手册:BRAIN_SYNC 每条报错的问题、原因与源码级修复路径
2026/9/7 16:50:02 网站建设 项目流程

gstack GBrain Sync 错误手册:BRAIN_SYNC 每条报错的问题、原因与源码级修复路径

【免费下载链接】gstackUse Garry Tan's exact Claude Code setup: 23 opinionated tools that serve as CEO, Designer, Eng Manager, Release Manager, Doc Engineer, and QA项目地址: https://gitcode.com/GitHub_Trending/gs/gstack

gstack 的 GBrain sync 会把~/.gstack/下的一份精选记忆(learnings、plans、designs、retros)推送到私有 git 仓库,实现跨机器的记忆同步。由于同步链路涉及队列、git 认证、密钥扫描和 egress 收据等多层机制,失败形态也比较多。本文以仓库内的 docs/gbrain-sync-errors.md 为骨架,逐条覆盖每条报错的 Problem / Cause / Fix,并对照 bin/gstack-brain-sync、bin/gstack-brain-restore、bin/gstack-artifacts-init、lib/egress-receipt.ts 等源码,说明每条报错实际由哪段逻辑触发、修复命令背后的状态文件是什么,方便你在排障时直接定位。

如何检索错误信息

docs/gbrain-sync-errors.md 本身就是一个错误索引:按BRAIN_SYNC:前缀冒号后的关键字,或命令输出中的二进制名来检索。需要说明两点检索前提:

  • 并非所有消息都带BRAIN_SYNC:前缀。密钥扫描与 push 失败由gstack-brain-sync打印并保留BRAIN_SYNC:前缀(见 bin/gstack-brain-sync 与 bin/gstack-brain-sync),而 egress 收据失败以gstack: brain-sync push NOT sent开头,init/restore 失败则以各自的命令名开头。
  • 跨机器的“检测到远端仓库”提示,在当前源码的 preamble(bin/gstack-skill-start)中已打印为ARTIFACTS_SYNC: artifacts repo detected: <url>并附带run 'gstack-brain-restore'的指引;文档中记录的BRAIN_SYNC: brain repo detected: <url>是该提示的历史前缀。两者指的是同一事件,检索时都可能出现。

排查任何同步问题时,先运行gstack-brain-sync --status:它输出最近一次状态(JSON 格式的~/.gstack/.brain-sync-status.json,由 write_status 写入)、队列深度、最近一次成功 push 的时间和当前隐私模式。状态码包括idle(空队列)、ok(推送成功)、blocked(密钥扫描命中)、push_failed(含EGRESS_RECEIPT_FAILED等失败细节)。

错误一:BRAIN_SYNC: brain repo detected: <url>

问题。这台机器上存在~/.gstack-artifacts-remote.txt(或其从别的机器拷贝来的旧名~/.gstack-brain-remote.txt),但本地~/.gstack/.git还不存在。

原因。你在另一台机器上已经配置过 GBrain sync(gstack-artifacts-init会把远端 URL 写到该 txt 文件),而这台机器的 gstack 状态尚未恢复。

修复。

gstack-brain-restore

它会克隆仓库到暂存目录、校验仓库形状、把被跟踪文件拷入~/.gstack/、把.git挪到位,并重新注册合并驱动器(源码见 bin/gstack-brain-restore)。如果不希望在这台机器上恢复,可以用配置键永久忽略提示:

gstack-config set artifacts_sync_mode_prompted true

该键在 bin/gstack-config 中有默认值false;另外注意当前 preamble 的检测分支只在“URL 文件存在 且~/.gstack/.git缺失 且artifacts_sync_modeoff”三者同时成立时才打印这条提示(bin/gstack-skill-start),其提示文案也提供了另一种永久关闭方式gstack-config set artifacts_sync_mode off

错误二:BRAIN_SYNC: blocked: <pattern-family>:<snippet>

问题。密钥扫描器在某个已暂存文件里发现了凭证形态的内容,同步中止;队列被完整保留,什么都没被 push。

原因。提交前的密钥模式之一命中了文件内容——通常是 AWS key、GitHub token、OpenAI key、PEM 块、JWT 或嵌在 JSON 里的 bearer token。

源码证据。扫描器是 secret_scan_stdin,它对git diff --cached的增量内容逐模式匹配,命中时输出<family>:<snippet>(snippet 截断到 30 字符)。六个模式族分别是:

模式族正则覆盖
aws-access-keyAKIA+ 16 位大写字母数字
github-tokenghp_/gho_/ghu_/ghs_/ghr_前缀或github_pat_
openai-keysk-前缀
pem-block-----BEGIN ... -----
jwteyJ...三段式
bearer-token-jsonJSON 中authorization/api_key/apikey/token/secret/password字段后的 16 位以上值,可选Bearer/Basic/Token前缀

命中后的处理路径在 bin/gstack-brain-sync:git reset HEAD -- .撤销暂存、写blocked状态、把BRAIN_SYNC: blocked: ...打到 stderr 并退出 0——所以 skill 本身不会崩溃,只是这一轮同步跳过。

修复(三选一)。

  1. 确属真实密钥:编辑该文件删掉密钥,然后重新运行任意 skill 触发重试。

  2. 误报(例如你的 learnings 里本来就包含一段想发布的 GitHub token 示例字符串):

    gstack-brain-sync --skip-file <path>

    该命令把路径追加进~/.gstack/.brain-skip.txt(去重,见 subcmd_skip_file),永久排除此路径;未来的 writer 不再入队它,已入队的记录在下一轮 drain 时被丢弃(归类为dropped.skipped)。

  3. 放弃整批同步(推倒重来):

    gstack-brain-sync --drop-queue --yes

    清空 spool 队列(~/.gstack/.brain-queue.d/下每个记录一个文件)以及遗留的单文件队列,不做任何提交;后续的写入会正常重新填充队列(subcmd_drop_queue)。

另外,gstack-brain-restore和 init 都会往~/.gstack/.git/hooks/pre-commit装一个同源模式的钩子(bin/gstack-brain-restore),所以即使你绕过 skill 手动git commit这个仓库,同样的扫描也会拦住。

错误三:BRAIN_SYNC: push failed: auth.

问题。git push 被拒,原因是你对远端的认证过期或缺失。

原因。当前凭据下远端不可达(token 过期、SSH key 未配置、账号被移除等)。

源码证据。push 失败后脚本先检查错误文本是否匹配auth|permission|403|401|forbidden(bin/gstack-brain-sync);命中则跳过重试,按 origin URL 给出针对性提示——remote_auth_hint 对github.com/@github.*建议gh auth status(必要时gh auth refresh),对gitlab建议glab auth status,其余建议检查git remote -v与凭据助手。

修复。按你的远端刷新认证:

  • GitHubgh auth status(需要时gh auth refresh
  • GitLabglab auth status
  • 其他git remote -v,检查 SSH key 或 credential helper

修复后运行任意 skill 即可自动重试——注意被 auth 卡住的 push 并不会丢数据:本地 commit 仍然存在,且脚本开头有一个“未推送 commit 检测器”(bin/gstack-brain-sync)会在后续边界以至少 10 分钟节流自动重推,前提是未推送的 commit 全部由gstack-brain-sync自己创建。

错误四:BRAIN_SYNC: push failed: <first-line-of-error>

问题。非 auth 原因的 push 失败,冒号后面是 git 错误输出的第一行。

原因。可能是网络问题、被拒的 push(远端领先,比如另一台机器先推了)、服务器 500、或仓库权限被回收。

源码证据。失败处理链在 bin/gstack-brain-sync:先尝试一次 fetch +merge --no-edit origin/<branch>再重推(JSONL 文件有专门的jsonl-append合并驱动器、markdown 用 union 合并,见 bin/gstack-brain-restore 注册的 git config),仍失败才落到这条状态。每次 fetch/重推也都是“收据先行、失败即拒”的 egress 操作。

修复。~/.gstack/.brain-sync-status.json里的完整消息,或者手动执行:

cd ~/.gstack && git status && git push origin HEAD

以查看 git 的完整报错。队列在任何 push 尝试后都会清空(记录移交给本地 commit),本地 commit 仍然在,下一次 skill 运行会重试 push。

错误五:gstack: brain-sync push NOT sent — the egress receipt could not be written

问题。push 在离开本机之前就被拒绝了。每次 brain-sync push 在发送前都会向 egress ledger(~/.gstack/security/egress.jsonl)写一条防篡改收据,这是 fail-closed 的:收据写不进去,就什么都不发送、不做本地 commit、队列完整保留,下次运行整体重试。gstack-brain-sync --status会把失败细节标为EGRESS_RECEIPT_FAILED

原因。~/.gstack/security/不可写(收据写入器会在目录缺失时创建它,所以单纯缺失不是原因)、磁盘满、或GSTACK_HOME指向了只读位置。

源码证据。这条消息来自 bash 侧的拒发打印函数 _gstack_egress_refusal;被拒的调用点在 bin/gstack-brain-sync——收据先于 commit 写入,写失败就 exit 1,队列原样保留。收据本体的实现在 lib/egress-receipt.ts:

  • ledger 路径为<home>/security/egress.jsonl,文件权限强制 0600(egressLedgerPath、appendChained);
  • 每条记录带prev字段(上一行原始内容的 sha256,第一行为空串),形成哈希链,verifyLedger会重算全链(verifyLedger);
  • 收据是内容无关的(content-free):只记录 sink、host、payload class、字节数与 sha256,git 场景下 sha256 为 null(git 进程持有字节);
  • 所有字段长度上限 512 字节、尾部读取窗口 4KB,保证哈希链永远能完整取到上一行(lib/egress-receipt.ts)。

修复。

mkdir -p ~/.gstack/security && chmod -R u+w ~/.gstack/security

然后运行任意 skill(或gstack-brain-sync --once)重试。之后可以用gstack-egress list查看 ledger 内容、gstack-egress verify校验哈希链(bin/gstack-egress,verify检测到篡改时以退出码 3 结束;注意它检测的是就地编辑、重排和链中删除,不检测尾部截断或整个文件被删——这是文档明确声明的威胁模型边界)。

错误六:gstack-artifacts-init: ~/.gstack/ is already a git repo pointing at: <url>

问题。你试图用一个与现有远端不一致的 URL 执行 init,命令拒绝覆盖。

原因。你之前已经用另一个远端跑过gstack-artifacts-init

源码证据。冲突判断在 bin/gstack-artifacts-init:它把两边 URL 各自规范化为 HTTPS 形式后再比较(存的远端通常是 SSH 形态,输入通常是 HTTPS 形态,规范化后同库不同写法不会误报冲突);确属不同仓库才打印本错误并给出git -C ~/.gstack remote set-url origin <url>的建议。

修复(二选一)。

  • 沿用现有远端:不带--remote运行gstack-artifacts-init,或传入匹配的 URL;
  • 切换远端:git -C ~/.gstack remote set-url origin <url>(命令自己的建议),或先gstack-brain-uninstall再用新 URL 重新 init。两种方式都不会删除你的数据。

错误七:Remote not reachable via SSH: <url>

问题。init 阶段无法连通 git 远端来验证可达性。

原因。URL 拼写错误、缺少认证、或网络问题。

修复。手动测试:

git ls-remote <url>

如果失败,依次检查:URL 拼写;GitHub 的gh auth status;GitLab 的glab auth status;私有网络 / VPN / DNS。

错误八:Failed to create or find '<name>'. Try --remote <url>.

问题。通过gh repo create自动建仓失败,且gh repo view也找不到该仓库。

原因。gh未认证、同名仓库已属于他人、或账号触达配额限制。

源码证据。这条消息在 GitHub 路径(bin/gstack-artifacts-init)和 GitLab 路径(bin/gstack-artifacts-init)各打印一次:repo create失败后先回退尝试repo view取 URL(仓库可能早已存在),拿不到 URL 才报此错。

修复。

gh auth status

未认证就gh auth login。若是仓库名冲突,换一个名字:

gstack-artifacts-init --remote git@github.com:YOURUSER/custom-name.git

--remote显式给定时会跳过整个自动建仓流程,见 bin/gstack-artifacts-init 的参数解析。)

错误九:gstack-brain-restore: ~/.gstack/.git already points at <url>

问题。你试图从一个与现有 git 配置不一致的 URL 恢复。

原因。之前用别的远端 init 过,留下了过期的.git

源码证据。安全门在 bin/gstack-brain-restore:~/.gstack/.git已存在且 origin 与新 URL 不一致时直接拒绝,防止覆盖。

修复。gstack-brain-uninstall,再重新执行gstack-brain-restore <url>。(如果.git已存在且远端匹配,restore 会退化为 fetch + fast-forward,见 bin/gstack-brain-restore。)

错误十:gstack-brain-restore: ~/.gstack/ has existing allowlisted files that would be clobbered

问题。你要执行 restore,但~/.gstack/里已经有会被覆盖的 learnings 或 plans。

原因。两种可能:(a) 这台机器在开启 sync 之前就积累了本地状态;(b) 一次失败的 restore 留下了部分状态。

源码证据。restore 用 Python 遍历~/.gstack/,把本地文件与远端.brain-allowlist的 glob 逐一匹配,列出最多 5 个冲突路径(bin/gstack-brain-restore)。

修复(三选一)。

  1. 这台机器的状态应该成为新真相:改用gstack-artifacts-init而不是 restore——它会以本机状态为基础创建一个全新的 brain 仓库;
  2. 想采用远端、丢弃本机状态:先备份~/.gstack/projects/,删除冲突文件后重跑 restore;
  3. 想合并:没有自动合并。手动把~/.gstack/里的 learnings 拷到一台已开启 sync 的机器上运行中的 gstack,再回来执行 restore。

错误十一:gstack-brain-restore: <url> does not look like a gstack-brain repo

问题。克隆成功了,但仓库缺少.brain-allowlist.gitattributes

原因。你把 restore 指向了一个普通 git 仓库,或者有人把 brain 仓库里的规范配置删掉了。

源码证据。形状校验在 bin/gstack-brain-restore:两个文件缺一不可,否则拒绝继续。

修复。核实 URL。若 URL 正确,运行gstack-artifacts-init --remote <url>重新播种规范配置。

不是报错但常见:明明该同步却什么都没同步

文档专门把这种“无错误信息”的静默状态列为一个 gotcha,排查顺序如下:

  1. gstack-brain-sync --status—— 模式是否为off?(off时 sync_active 直接返回假,--once是静默 no-op。)
  2. ~/.gstack/.git是否存在?
  3. gstack-config get artifacts_sync_mode—— 应为fullartifacts-only
  4. 你期望同步的文件是否在 allowlist 内?cat ~/.gstack/.brain-allowlist
  5. 隐私类别过滤——若模式是artifacts-only,行为类文件(timelines、developer-profile)被刻意跳过。

以上都没问题,再强制排干一次:

gstack-brain-sync --discover-new gstack-brain-sync --once

--discover-new按 allowlist 遍历~/.gstack/,用mtime:size游标(~/.gstack/.brain-discover-cursor)发现变更并入队(subcmd_discover_new);--once走完整 drain:迁移遗留队列 → 快照 spool → 分类(skip/allowlist/隐私模式/存在性四道过滤,见 compute_paths_to_stage)→ 暂存 → 密钥扫描 → egress 收据 → commit → push。值得注意的两个静默点:分类阶段如果隐私地图文件损坏,脚本会“持有一切、什么都不暂存”(宁可不同步也不猜测,会打一条 warning);空队列是常态,--once在空队列时直接写idle状态退出,正常耗时小于 1 秒。

附录:状态文件速查

排障时高频用到的~/.gstack/下状态文件(前缀均可被GSTACK_HOME环境变量覆盖):

文件作用
.brain-sync-status.json最近一次 drain 的状态(idle/ok/blocked/push_failed+ 消息),--status直接读它
.brain-queue.d/同步队列 spool,每记录一个<epoch>-<pid>-<uniq>.json文件;quarantine/子目录存放不可解析的记录
.brain-allowlist允许同步的 glob 白名单;凭据、机器态、question-preferences 等一律不在其中
.brain-skip.txt--skip-file写入的永久排除路径
.brain-privacy-map.json文件 →artifact/behavioral类别映射,供隐私模式过滤
.brain-last-push/.brain-last-pull最近成功 push / 每日 pull 的时间戳(pull 节流 24 小时)
.brain-worktree-last-advancegbrain 索引 worktree 的每日推进节流戳
security/egress.jsonlegress 收据 ledger(0600,哈希链),gstack-egress list/verify查看

这些机制的设计背景(白名单而非黑名单、skill 边界同步而非守护进程、JSONL 合并驱动器、一次性隐私询问门)可继续参阅 docs/gbrain-sync.md;收据链路的完整单元测试见 test/egress-receipt.test.ts 与 test/egress-receipt-wiring.test.ts,后者固定了哪些 sink 必须写收据。

【免费下载链接】gstackUse Garry Tan's exact Claude Code setup: 23 opinionated tools that serve as CEO, Designer, Eng Manager, Release Manager, Doc Engineer, and QA项目地址: https://gitcode.com/GitHub_Trending/gs/gstack

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询