ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

GSD 代码库漂移检测门(codebase_drift_gate):execute-phase 执行后的结构一致性守护

GSD 代码库漂移检测门(codebase_drift_gate):execute-phase 执行后的结构一致性守护 GSD 代码库漂移检测门codebase_drift_gateexecute-phase 执行后的结构一致性守护【免费下载链接】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导读在 spec-driven 开发流程中execute-phase完成一个阶段phase的全部计划后、进入验证verify之前代码库的实际结构往往已经与规划阶段生成的.planning/codebase/STRUCTURE.md结构图产生偏差——新增的目录、barrel 导出、数据库迁移和路由模块没有被反映到规划文档中。get-shit-doneGSD为此实现了codebase_drift_gate问题 #2003一个契约上非阻塞non-blocking by contract的漂移检测门它扫描最后一次映射提交last_mapped_commit以来的结构性变更根据阈值决定是仅打印警告还是自动触发gsd-codebase-mapper子代理重绘规划上下文而任何内部错误都不会导致阶段失败。读完本文你将掌握该门的完整 JSON 契约、warn与auto-remap两种分支的行为差异、两个workflow.drift_*配置键的语义以及从 CLI 命令到纯函数库drift.cjs的底层实现链路。门在流程中的位置与设计契约codebase_drift_gate位于 execute-phase 工作流 中紧跟在schema_drift_gate数据库 schema 漂移检测之后、verify_phase_goal之前运行位置见 execute-phase.md#L1439-L1448。它专门针对结构层的漂移与 schema 门形成互补schema 门防的是“类型通过但数据库不同步”的误报验证而 codebase 门防的是“规划上下文陈旧、后续阶段基于过期结构图做计划”的隐性偏差。核心契约只有一条该门永不失败阶段。任何内部错误缺少 STRUCTURE.md、git 不可用、SDK 调用失败、子代理 spawn 失败都必须回退并继续执行verify_phase_goal绝不允许阻塞、弹提示或中断流程。这一点在 drift.cjs 头部注释 中被明确设计为库层保证检测器对畸形输入永不抛异常统一返回{ skipped: true }结果。第一行命令SDK 调用与 JSON 契约门的第一步是调用 GSD SDK 的 verify 命令族DRIFT$(gsd-tools verify codebase-drift 2/dev/null || echo {skipped:true,reason:sdk-failed})命令失败非零退出或 stderr 输出时用echo兜底注入一个skipped: true的 JSON保证后续解析始终有合法输入。||分支的兜底正是“非阻塞契约”的第一道保险。随后解析 JSON 中的以下字段字段类型含义skippedboolean是否跳过检测无 STRUCTURE.md、非 git 仓库、内部异常reasonstring跳过或失败的原因标识action_requiredboolean是否达到阈值、需要采取行动directivewarn/auto-remap/none触发行动后应执行的动作类型spawn_mapperboolean是否需要派生gsd-codebase-mapper子代理affected_pathsstring[]受影响的顶层路径前缀供--paths使用elementsobject[]每个漂移元素categorypaththresholdnumber实际生效的阈值actionwarn/auto-remap实际生效的动作模式last_mapped_commitstring | nullSTRUCTURE.md frontmatter 中记录的最后映射提交messagestring面向用户/编排者的提示消息这个 JSON 形状与 verify.cjs 中cmdVerifyCodebaseDrift的输出 一一对应可在源码中逐一核对。三条执行路径路径一跳过skipped: true当满足以下任一条件时门直接进入跳过分支.planning/codebase/STRUCTURE.md不存在no-structure-mdSTRUCTURE.md 存在但读取失败cannot-read-structure-md: …当前目录不是 git 仓库not-a-git-repogit diff无法计算基线差异git-diff-failedSDK 调用失败或库内部抛出异常sdk-failed/exception: …。对应动作仅记录一行日志Codebase drift check skipped: {reason}然后继续verify_phase_goal。不提示用户、不阻塞。这些 reason 在 verify.cjs#L1302-L1362 的 CLI 层和各 skip 分支中均有明确来源。路径二directive warn当action_required为true且配置的drift_action为warn默认值时门原样打印message字段。消息格式由 drift.cjs 的buildMessage生成Codebase drift detected: {N} structural element(s) since last mapping. New directories: - {path} New barrel exports: - {path} New migrations: - {path} New route modules: - {path} Run /gsd:map-codebase --paths {affected_paths} to refresh planning context.关键细节消息中给出的斜杠命令不是硬编码的而是通过runtime-slash.cjs的formatGsdSlash按当前运行时claude、codex、gemini等动态格式化的见 drift.cjs#L263-L267。打印完毕后继续verify_phase_goal——不阻塞、不派生任何东西。路径三directive auto-remap当drift_action配置为auto-remap时门不仅要提示还要自动刷新规划上下文。分两步第一步加载 mapper 代理的技能包。注意执行器executor与 mapper 是两个不同的代理init_context步骤中 executors 的AGENT_SKILLS是gsd-executor的不能复用AGENT_SKILLS_MAPPER$(gsd-sdk query agent-skills gsd-codebase-mapper)第二步按模板派生gsd-codebase-mapper子代理并传入--paths提示Agent( subagent_typegsd-codebase-mapper, descriptionIncremental codebase remap (drift), promptFocus: arch Todays date: {date} --paths {affected_paths joined by comma} Refresh STRUCTURE.md and ARCHITECTURE.md scoped to the listed paths only. Stamp last_mapped_commit in each documents frontmatter. ${AGENT_SKILLS_MAPPER} )Focus: arch说明本次重映射只做架构/结构视图--paths将漂移文件折叠后的路径前缀如packages/foo、src拼接传入让 mapper 只重绘受影响区域实现增量 remap完成后要求给每份文档的 frontmatter 盖上last_mapped_commit使基线前移。ORCHESTRATOR RULE — CODEX RUNTIME在调用 Agent() 后立即停止当前任务的工作不要继续读文件、改代码或跑测试等待子代理返回结果。这是为了防止重复工作、冲突编辑与上下文浪费只有拿到子代理结果后才恢复。该规则与 execute-phase.md 中 executor 派生处的同款规则 一脉相承是整个编排器对子代理并发的基本纪律。结果处理spawn 失败或 mapper 报错 → 记录Codebase drift auto-remap failed: {reason}继续verify_phase_goal。阶段不会因 remap 失败而失败。remap 成功 → 记录Codebase drift auto-remap completed for paths: {affected_paths}继续verify_phase_goal。两个配置键阈值与动作门的可调行为收敛到两个配置键均位于workflow命名空间其在 CONFIGURATION.md 与 config-schema.manifest.json 中有正式登记配置键类型默认值语义workflow.drift_thresholdinteger3触发行动所需的最小漂移元素数量新增目录、barrel 导出、迁移、路由模块各计为元素workflow.drift_actionstringwarn超过阈值后的动作warn打印提示建议手动运行/gsd:map-codebase --paths …或auto-remap自动派生 mapper 代理增量重绘配置键的解析逻辑在 verify.cjs#L1380-L1385const threshold Number.isInteger(config?.workflow?.drift_threshold) config.workflow.drift_threshold 1 ? config.workflow.drift_threshold : 3; const action config?.workflow?.drift_action auto-remap ? auto-remap : warn;两个键都是容错读取阈值必须是 1的整数否则回退默认值 3action 只有精确等于字符串auto-remap才生效其余一律回退warn。这与 drift.cjs 纯函数中的同款防御 保持一致——库层与 CLI 层各自独立校验任一层的非法配置都不会让门崩溃。底层实现drift.cjs 纯函数库门的全部检测逻辑收敛在 drift.cjs 中它被刻意设计为纯库只接收解析好的输入、返回结构化结果git 调用、配置读取与 mapper 派生由 CLI/工作流层负责。四种漂移分类classifyFiledrift.cjs#L76-L83按正则规则将新增文件归类为四种元素类别匹配规则源码常量示例barrel(packages\|apps)/name/src/index.(ts\|tsx\|js\|mjs\|cjs)packages/foo/src/index.tsmigrationsupabase/migrations/*.sql、prisma/migrations/*、drizzle/meta/*、drizzle/migrations/*、src/migrations/*、db/migrations/*、migrations/*supabase/migrations/20240101_init.sqlroute(apps\|packages)/*/src/routes/*、src/routes/*、src/api/*、(apps\|packages)/*/src/api/*apps/web/src/routes/journal.tsnew_dir无特定规则匹配且路径前缀未出现在 STRUCTURE.md 中newpkg/src/thing.ts去重与优先级每个文件至多计一次当同一文件命中多个类别时按migration route barrel new_dir的优先级取最具体者CATEGORY_PRIORITYdrift.cjs#L42。例如supabase/migrations/x.sql即使路径前缀未映射也只计为一个migration元素不会重复计数。已映射判定isPathMappeddrift.cjs#L93-L105采用子串匹配而非结构化解析STRUCTURE.md 是自由格式 Markdown只要文档中提到src/lib/检查structureMd.includes(src/lib)即可判定该前缀已映射。判定按“最长前缀到最短前缀”逐层尝试最后回退到顶层目录名带/或反引号包裹两种形态。阈值判定与受影响路径折叠detectDriftdrift.cjs#L124-L219统计漂移元素总数elements.length threshold时置actionRequired true并按action决定directive与spawnMapper。chooseAffectedPathsdrift.cjs#L279-L294将漂移文件路径折叠为去重排序的顶层前缀monorepo 布局apps/*、packages/*取深度 2如packages/foo普通布局取深度 1如src——这正是传入 mapper--paths的路径集合。frontmatter 基线last_mapped_commit检测基线不是固定 HEAD而是写在文档自身的 frontmatter 中的last_mapped_commitdrift.cjs#L339-L374。readMappedCommit从.planning/codebase/STRUCTURE.md读取该键CLI 层verify.cjs#L1342-L1351用git diff last_mapped_commit HEAD --name-status计算增量若未记录或用git cat-file验证不可达则回退到 empty-tree SHA4b825dc6…做全量对比。writeMappedCommit则在 mapper 重绘后把新 HEAD 与last_mapped_at时间戳盖回 frontmatter形成闭环。这种“基线附着在文件上、随 git 移动存活、无需 sidecar JSON”的设计是 map-codebase 工作流 与漂移检测共享的约定。路径消毒与异常兜底sanitizePathsdrift.cjs#L301-L311用保守白名单SAFE_PATH_REdrift.cjs#L66过滤拼入 mapper prompt 的路径只允许仓库相对路径组件字母数字、连字符、下划线、点拒绝绝对路径、含..穿越或 shell 元字符的路径。detectDrift整体包裹在 try/catch 中drift.cjs#L215-L218任何异常都返回skipped: true——这是“永不失败阶段”的最后一层保险。测试覆盖drift-detection.test.cjs 验证的行为契约drift-detection.test.cjs667 行对库与 CLI 双面覆盖可直接作为行为契约清单阅读分类单元测试barrelpackages/apps 两种、supabase/prisma/drizzle 迁移、路由模块apps/*/src/routes、src/api、普通源码文件返回null阈值门控2 个元素低于默认阈值 3 不触发动作达到/超过阈值才触发去重优先级同一文件只计一次、取最具体类别warnvsauto-remap两种 action 下的directive、spawnMapper、消息内容差异last_mapped_commit往返writeMappedCommit→readMappedCommit的前后一致性以及缺失文件时创建仅含 frontmatter 的最小文件--paths透传chooseAffectedPaths折叠结果与 mapper 提示拼接正确性优雅失败路径无 STRUCTURE.md、非 git 仓库、异常输入下均返回skipped: true而非抛错。这些测试用例与本文描述的 JSON 契约、配置回退逻辑一一对应是理解门行为最权威的参照物。使用建议日常开发默认保持warn仅在阶段末尾提示漂移人工决定何时用/gsd:map-codebase --paths …刷新规划上下文开销为零、无副作用。对变更频繁的 monorepo 可启用auto-remap当新增模块频繁、人工刷新容易遗漏时让门自动派生 mapper 增量重绘STRUCTURE.md与ARCHITECTURE.md保证后续 plan-phase 始终基于新鲜的结构图。调低阈值捕获早期漂移若希望更敏感地感知结构变化可将workflow.drift_threshold设为 1 或 2追求稳定期低噪声则维持默认 3。无论配置如何都不必担心阶段失败门的所有分支最终都汇聚回verify_phase_goal它本质是一个“永远温柔提示、永不硬阻断”的结构健康检查器。【免费下载链接】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),仅供参考
返回列表