get-shit-done 的 Graphify 自动更新钩子:主分支 HEAD 前进后自动重建代码知识图谱
get-shit-done 的 Graphify 自动更新钩子主分支 HEAD 前进后自动重建代码知识图谱【免费下载链接】get-shit-doneA light-weight and powerful meta-prompting, context engineering and spec-driven development system for Claude Code by TÂCHES.项目地址: https://gitcode.com/GitHub_Trending/getshi/get-shit-done本文围绕 get-shit-done 仓库的 changeset 文档 .changeset/3347747-graphify-auto-update-hook.mdPR 3557关闭 issue #3347展开讲清「知识图谱消费方始终拿到最新语义关系」这一机制的完整设计新增的graphify.auto_update配置项、捆绑的 PostToolUse 钩子hooks/gsd-graphify-update.sh的八道触发闸门、.last-build-status.json状态文件的三态生命周期以及gsd-planner/gsd-phase-researcher如何零改动地感知自动重建状态。读完你可以完整理解该功能的配置方式、触发条件、失败面设计以及从钩子到状态消费端的源码级调用链。问题背景图谱的生产与消费之间存在静默漂移get-shit-done 的 Graphify 子系统会把项目代码构建成知识图谱落在.planning/graphs/graph.json并被gsd-planner与gsd-phase-researcher在每一步的load_graph_context阶段自动消费但在此之前图谱的生产是手动的每次会话最多跑一次/gsd:graphify build。也就是说图谱被自动消费、却被手动生产每多一次 commit生产者与消费者之间的差距就静默地扩大一点。原有的stale: true标注只能告诉消费方「文件 mtime 老了」无法区分三种状态自动重建钩子正在跑、刚才失败了、还是根本没人跑过。changeset 文档给出的核心意图正是消除这个盲区new config keygraphify.auto_update(defaultfalse) and bundled PostToolUse hookhooks/gsd-graphify-update.shkeep the.planning/graphs/graph.jsonconsumed bygsd-plannerandgsd-phase-researchercurrent without manual/gsd:graphify buildruns.设计原则是opt-ingraphify.auto_update默认false未开启的用户升级后行为完全不变开启后钩子在主分支上发生 HEAD 前进的 git 操作之后以脱离父进程的后台子进程方式执行graphify update .钩子本身永远同步快速返回、绝不阻塞用户可见的工具调用。配置项graphify.enabled 与 graphify.auto_update自动更新由两个布尔配置项联合控制均位于项目的.planning/config.json配置键类型默认值含义graphify.enabledbooleanfalse启用项目知识图谱/gsd:graphifygraphify.auto_updatebooleanfalse主分支 HEAD 前进后自动重建图谱两者必须同时为true钩子才会动作见 docs/CONFIGURATION.md 中graphify.auto_update的参数说明以及 get-shit-done/workflows/settings.md 中的配置清单。在交互式设置入口/gsd:settings中graphify.auto_update以「Graph auto-update」问题呈现且条件可见只有当用户选择的graphify.enabled为 on 时才会出现该问题若graphify.enabled为 off则省略该问题并保留配置中已有的graphify.auto_update值不做覆盖。settings 工作流原文规定Conditional visibility — graphify.auto_update:This question is shown only when the users chosengraphify.enabledvalue is on. Ifgraphify.enabledis off, omit thegraphify.auto_updatequestion and preserve the existinggraphify.auto_updatevalue in config (do not overwrite). Implementation: ask Graphify first; only ask Graph auto-update when Graphify is enabled.配置落盘后形如{ graphify: { enabled: true, auto_update: true } }钩子实现hooks/gsd-graphify-update.sh 的八道触发闸门捆绑的钩子是 hooks/gsd-graphify-update.sh一个匹配 Bash 工具的 PostToolUse 钩子。它的文件头注释完整列出了闸门设计按快速失败顺序排列每一道都削减「常见不派发路径」上的工作Gate 1— stdin 载荷存在且tool_name Bash钩子从 stdin 读取工具调用 JSON用 Node 解析出tool_name与tool_input.command非 Bash 调用直接exit 0Gate 2— 命令是「推进 HEAD 的 git 操作」直接 shell 形式匹配git commit/git merge/git pull/git rebase --continue/git cherry-pick子串或精确的gsd-sdk query commit命令形态。之所以要匹配后者是因为 SDK 命令内部调用 git、命令行中从未出现字面量git commit见 issues #3653Gate 3—$CI环境变量未设置或为空CI 中抑制Gate 4— 当前目录在一个 git 仓库内git rev-parse --git-dir验证Gate 5— 当前分支等于默认分支优先读.planning/config.json的git.base_branch覆盖值否则按main/master/trunk依次探测Gate 6—.planning/config.json同时满足graphify.enabled true graphify.auto_update trueGate 7—graphify可执行文件在PATH上否则静默退出Gate 8— 没有正在进行的重建读取锁文件.planning/graphs/.rebuild.lock中的 PID 并用kill -0探活进程存活则退出进程已死陈旧锁则容忍并继续。闸门 2 与闸门 5 的关键代码节选自 gsd-graphify-update.sh# Gate 2 — HEAD-advancing git op (shell-direct or exact gsd-sdk query commit) case $COMMAND in *git commit*|*git merge*|*git pull*|*git rebase --continue*|*git cherry-pick*) ;; *gsd-sdk query commit|*gsd-sdk query commit *) ;; *) exit 0 ;; esac ... CURRENT_BRANCH$(git rev-parse --abbrev-ref HEAD 2/dev/null || echo ) [ $CURRENT_BRANCH $DEFAULT_BRANCH ] || exit 0注意「rebase --continue匹配、但裸rebase不匹配」的细节只有git rebase --continue才代表 rebase 序列真正落盘推进了 HEAD普通git rebase启动时未必前进 HEAD。状态文件三态生命周期的 .last-build-status.json当八道闸门全部通过钩子先同步写入初始状态文件再把真正的重建工作派发到脱离的子进程。状态文件.planning/graphs/.last-build-status.json的结构节选自 planner-graphify-auto-update.md{ ts: 2026-05-15T14:02:23Z, status: running, exit_code: null, duration_ms: null, head_at_build: commit-sha, graphify_version: null }字段说明tsUTC 时间戳ISO 8601statusrunning/ok/failed三态exit_coderunning时为null终态时为graphify update .的退出码duration_ms重建耗时毫秒running时为nullhead_at_build重建启动时记录的 HEAD SHAgraphify_version预留字段当前恒为null同步写 running再脱离派发gsd-graphify-update.sh 中钩子在派发前用 Node 写出status: running的初始状态携带head_at_build这样下一次 planner 调用即使赶在重建完成之前也能看到「正在进行中」的信号。随后它以后台作业方式启动hooks/lib/gsd-graphify-rebuild.shbash $REBUILD_SCRIPT \ $STATUS_FILE \ $LOCK_FILE \ $HEAD_SHA \ $MS_START \ $GRAPHIFY_BIN \ /dev/null /dev/null 21 REBUILD_PID$! echo $REBUILD_PID $LOCK_FILE disown $REBUILD_PID 2/dev/null || true这里有一个刻意的并发设计钩子把重建进程以普通后台作业启动、通过$!同步捕获 PID 并在钩子返回之前写入锁文件。源码注释解释了动机——消除一个启动竞态如果让子进程自己写锁观察方比如测试清理逻辑在「锁不存在」时无法区分「子进程还没启动」和「子进程已经结束」。锁由父进程同步落盘后锁的存在性本身就是可靠的进行中信号。重建执行器gsd-graphify-rebuild.sh脱离的 hooks/lib/gsd-graphify-rebuild.sh 负责真正的重建流程为把自己的 PID 写入LOCK_FILE并设置trap ... EXIT保证任何退出路径都清理锁在项目根目录执行graphify update .cwd 继承自调用方捕获退出码仅在成功时复制产物graphify-out/graph.json→.planning/graphs/graph.jsongraph.html与GRAPH_REPORT.md一并复制并把新图谱另存为.planning/graphs/.last-build-snapshot.json供后续graphifyDiff拓扑对比使用。失败路径保留上一份有效图谱绝不落盘半成品计算duration_ms重写状态文件为okgraphify退出码 0或failed携带exit_code。消费端如何感知零提示词改动的 stale 折叠changeset 文档强调planner 与 researcher 的load_graph_context步骤现在会把自动重建状态与既有的陈旧度标注一起呈现——包括 issue 评审中认定的必备失败面场景auto-rebuild FAILED at {ts}; context is from the prior build。实现位于 get-shit-done/bin/lib/graphify.cjs 的graphifyStatus()它读取.last-build-status.json把running/failed两个状态折叠进既有的stale: true信号// Auto-update status (#3347) const statusPath path.join(planningDir, graphs, .last-build-status.json); const lastBuildAutoUpdate fs.existsSync(statusPath) ? safeReadJson(statusPath) : null; const autoUpdateStale lastBuildAutoUpdate (lastBuildAutoUpdate.status failed || lastBuildAutoUpdate.status running); return { ... stale: age STALE_MS || Boolean(autoUpdateStale), ... last_build_auto_update: lastBuildAutoUpdate || null, };planner 和 researcher 的step nameload_graph_context块中本来就执行node ... graphify status并且已有一条规则If the status response hasstale: true, note for later: Graph is{age_hours}hold — treat semantic relationships as approximate.因此这条既有规则现在会额外覆盖三种情况引自 planner-graphify-auto-update.md触发条件用户看到的效果自动重建状态 failed既有「按近似对待」提示触发因为stale: true完整last_build_auto_update对象退出码 / 耗时 / commit SHA随 JSON 返回自动重建状态 running同上——下一次 planner 调用知道图谱正在重建中在脱离进程完成前按近似对待状态 ok且 mtime 24h标注静默——图谱新鲜且最近一次自动重建成功状态文件缺失静默操作者未 opt-in或开启后尚未发生过推进 HEAD 的 git 操作这套设计的三个考量见参考文档无 planner 侧提示词改动折叠进stale: true复用了既有规则agents/gsd-planner.md不新增任何内容该文件已接近 48K 的分解大小上限测试钉住接缝行为tests/graphify-auto-update.test.cjs针对graphifyStatus在 status failed/running/ok/ 文件缺失四种情况下的行为做回归断言向后兼容不读last_build_auto_update的旧调用方看到的 JSON 形状不变stale同时反映 mtime 与自动重建状态。触发条件全景与可验证边界把散落在 changeset、源码与测试中的行为约束汇总成一张判定表场景钩子行为工具调用不是 Bash如 Read/EditGate 1 拦截exit 0Bash 命令不含 commit/merge/pull/rebase --continue/cherry-pick/gsd-sdk query commit形态Gate 2 拦截$CI已设置Gate 3 拦截CI-aware非 git 仓库Gate 4 拦截当前分支 ≠ 默认分支git.base_branch覆盖否则main/master/trunkGate 5 拦截graphify.enabled或graphify.auto_update为 falseGate 6 拦截graphify不在 PATHGate 7 拦截静默退出已有重建在跑锁 PID 存活kill -0探活Gate 8 拦截陈旧锁进程已死容忍并继续全部通过同步写running状态 → 锁文件落 PID → 脱离派发graphify update .无论哪条路径钩子总是返回 0永不阻塞用户可见的工具调用——这是文件头注释明确声明的契约Returns 0 in all cases. Never blocks the user-facing tool call.。验证边界可以落到 tests/graphify-auto-update.test.cjs该测试文件在临时目录中模拟.planning/config.json与钩子执行断言各种闸门组合下.planning/graphs/.last-build-status.json是否产生并验证「graphify.auto_update默认必须为falseopt-inissue #3347 验收条件」。更完整的端到端行为矩阵命令形态匹配、CI 抑制、分支判定、锁语义可以沿该测试文件与 hooks/gsd-graphify-update.sh 的闸门注释逐条对照。实战路径从手动 build 到自动保鲜对于已启用 Graphify 的项目启用自动更新的最短路径是确认graphify已安装且在 PATH 上构建流程的graphifyBuild()会做安装检查安装指引见 get-shit-done/bin/lib/graphify.cjs 中给出的uv pip install graphifyy graphify install运行/gsd:settings在 Features 分区先开启 Graphify再回答条件出现的「Graph auto-update」问题为 on——或直接把graphify.enabled与graphify.auto_update写入项目.planning/config.json此后在默认分支上的git commit/git merge/git pull/git rebase --continue/git cherry-pick以及gsd-sdk query commit形态的 SDK 提交会自动触发脱离式重建观察保鲜效果.planning/graphs/.last-build-status.json会经历running → ok/failed的状态迁移而gsd-planner/gsd-phase-researcher的load_graph_context输出中stale与last_build_auto_update字段即为其状态面。适用前提与限制该机制仅在默认分支上触发feature 分支上的提交不会触发重建$CI环境下被抑制graphify update .的产物只有退出码为 0 才会覆盖.planning/graphs/失败时消费者看到的是上一份有效图谱加上failed标注「auto-rebuild FAILED at {ts}; context is from the prior build」语义不会出现半成品图谱。对于多分支并行、长 rebase 会话较多的团队这正是把「图谱陈旧度」从隐性漂移变成显式可观测状态的关键一步。【免费下载链接】get-shit-doneA light-weight and powerful meta-prompting, context engineering and spec-driven development system for Claude Code by TÂCHES.项目地址: https://gitcode.com/GitHub_Trending/getshi/get-shit-done创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考