ARTICLE DETAIL

资讯详情

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

gsd-core `detect-custom-files` 修复:`/gsd-update` 不再静默销毁用户自定义 Skills

gsd-core `detect-custom-files` 修复:`/gsd-update` 不再静默销毁用户自定义 Skills 【免费下载链接】gsd-coreGit. Ship. Done - Core项目地址https://gitcode.com/gh_mirrors/ge/gsd-core点击查看免费下载导读本篇技术文章围绕 gsd-core 仓库中的变更集.changeset/archived/wise-rams-gather.md对应 PR #3318 / issue #3317展开深入解析一次影响数据安全的缺陷修复SDK 移植版本中的detect-custom-files工具遗漏了GSD_MANAGED_DIRS中的skills/目录导致用户在config-dir/skills/name/下自定义的技能文件在/gsd-update更新时被静默删除且不会进入gsd-user-files-backup/备份。读完本文你将完整理解 gsd-core 的用户自定义文件检测、备份与恢复链路掌握该修复的实现原理、测试覆盖与边界防护并能在自己的部署中验证该行为。一、变更集原文与问题本质变更集记录如下detect-custom-filesnow scansskills/— SDK port omittedskillsfromGSD_MANAGED_DIRS, so user-added skills underconfig-dir/skills/name/were never detected and got silently destroyed during/gsd-update(no entry written togsd-user-files-backup/). One-line parity withbin/gsd-tools.cjs. (#3317)它揭示了两个关键事实缺陷成因SDK 移植SDK port在维护受管目录清单GSD_MANAGED_DIRS时遗漏了skills使得detect-custom-files根本不会遍历skills/目录后果/gsd-update的干净安装clean-install阶段会整体擦除受管目录未被检测到的用户自定义技能会随目录被静默销毁且不产生任何备份记录。这一行修复的本质是对齐让 SDK 移植版本的受管目录清单与bin/gsd-tools.cjs及其安装树中的gsd-core/bin/gsd-tools.cjs保持一致。二、背景更新流程如何保护用户自定义文件要理解这个 bug 的严重性先要理解 gsd-core 更新链路中受管目录 / 清单 / 检测 / 备份四个环节的协作关系。2.1 受管目录与文件清单gsd-core 安装器bin/install.js在安装完成后会写入gsd-file-manifest.json见writeManifestbin/install.js。该清单以相对路径为键、以文件内容的 SHA256 哈希为值记录这次安装由 GSD 官方交付了哪些文件generateManifest。与此同时以下目录被定义为 GSD 受管目录更新时会被整体擦除并重写整目录接管whole-managedgsd-core/、commands/gsd/—— 递归扫描其中所有文件前缀接管prefix-managedagents/、共享 hooks 目录默认hooks/pi 等运行时为gsd-hooks/、skills/—— 只扫描以gsd-开头的顶层条目。2.2detect-custom-files的职责detect-custom-files是gsd-tools的一个子命令位于 gsd-core/bin/gsd-tools.cjs安装树内的实际实现与 bin/gsd-tools.cjs仓库根目录的 SDK 源。它的判定规则很简单磁盘上存在、但不在gsd-file-manifest.json中的文件即用户自行添加、安装器不了解的文件——这些文件会在下一次干净安装时被删除因此必须先被发现并备份。2.3 更新工作流中的调用点/gsd-update工作流gsd-core/workflows/update.md在backup_custom_files步骤中调用该子命令gsd-core/workflows/update.mdCUSTOM_JSON if [ -f $GSD_TOOLS ] [ -n $RUNTIME_DIR ]; then CUSTOM_JSON$(node $GSD_TOOLS detect-custom-files --config-dir $RUNTIME_DIR 2/dev/null) fi if [ -z $CUSTOM_JSON ]; then CUSTOM_JSON{custom_files:[],custom_count:0} fiRUNTIME_DIR是解析出的配置目录例如~/.config/opencode、~/.gemini/antigravity等运行时各自的配置根检测结果以 JSON 输出随后被解析出custom_count当CUSTOM_COUNT 0时每个自定义文件被复制到$RUNTIME_DIR/gsd-user-files-backup/gsd-core/workflows/update.md并提示用户Found N custom file(s) inside GSD-managed directories. These have been backed up to gsd-user-files-backup/ before the update. Youll be offered a restore once the new version is installed.工作流文档还特别强调了一个实践教训bug #1997不要用 bash 路径截取${filepath#$RUNTIME_DIR/}或内联node -e require()来解析相对路径因为当$RUNTIME_DIR未设置时这些写法会静默失败造成CUSTOM_COUNT0的假阴性——这正是本变更集所修复 bug 的同类风险检测盲区等于静默数据丢失。三、缺陷分析为什么漏掉skills/会导致静默销毁在修复之前SDK 移植版本的受管目录清单缺少skills。后果链如下/gsd-update触发干净安装安装器按受管目录递归擦除skills/下的全部内容由于detect-custom-files从不扫描skills/用户添加的skills/gsd-name/SKILL.md不会被列为自定义文件因此不会写入gsd-user-files-backup/备份条目擦除完成后用户技能永久丢失且无任何恢复入口。这是典型的静默数据丢失silent data loss错误不报错、不告警、不留备份只有在用户下次需要该技能时才会发现。需要说明的细节是skills/目录本身是 gsd-core 自 v1.39.0 技能整合skill consolidation#2790后成为受管根的。测试文件 tests/update-custom-backup.test.cjs 中对此有明确注释After v1.39.0 skill consolidation (#2790), skills/ became a GSD-managed root. GSD_MANAGED_DIRS was missing skills, so user-added GSD-prefixed skill directories like skills/gsd-custom-skill/SKILL.md were never walked and got wipedtests/update-custom-backup.test.cjs。也就是说这个 bug 是目录升格为受管根与受管目录清单未同步更新错位产生的回归。四、修复实现routeDetectCustomFiles与受管目录清单4.1 受管目录清单的源码形态修复后的清单位于 gsd-core/bin/gsd-tools.cjs// GSD-managed directories to scan for user-added files. Whole-owned // roots are wiped recursively; shared runtime roots are pruned by the // same gsd-* top-level prefix used by install.js _removeGsdEntries. const GSD_WHOLE_MANAGED_DIRS [ gsd-core, path.join(commands, gsd), ]; const GSD_PREFIX_MANAGED_DIRS [ agents, ...resolveSharedHooksDirCandidates(resolvedConfigDir), skills, ];skills被归入前缀管理prefix-managed一类与agents/、hooks 目录同级这与安装器_removeGsdEntries使用相同的gsd-*顶层前缀剪枝策略见源码注释。4.2 前缀选择性扫描对应的扫描逻辑gsd-core/bin/gsd-tools.cjsfor (const managedDir of GSD_PREFIX_MANAGED_DIRS) { const absDir path.join(resolvedConfigDir, managedDir); if (!fs.existsSync(absDir)) continue; for (const entry of fs.readdirSync(absDir, { withFileTypes: true })) { if (!entry.name.startsWith(gsd-)) continue; collectCustomFiles(path.join(absDir, entry.name), resolvedConfigDir, manifestKeys, customFiles); } }这带来一个重要的语义细节不是skills/下所有文件都算自定义。skills/gsd-planner/、skills/gsd-...GSD 官方技能以gsd-前缀开头且已登记在 manifest 中——不会出现在custom_files中skills/gsd-my-custom-skill/SKILL.md用户新增、不在 manifest 中——会被检测并备份skills/gstack-one/等非gsd-前缀的技能——不会被扫描因为安装器也不会删除它们shared skills 由安装器保留见测试注释 #1325。这种前缀选择性是修复正确性的核心detect-custom-files必须与安装器的删除行为精确对偶——只备份那些即将被擦除的文件既不漏报数据丢失也不误报把官方技能当作自定义文件造成永久误报这一点在 bin/install.js 附近有专门注释提及。4.3 输出契约命令成功时输出gsd-core/bin/gsd-tools.cjs{ custom_files: [skills/gsd-my-custom-skill/SKILL.md, ...], custom_count: 1, manifest_found: true, manifest_version: 1.40.0 }边界行为--config-dir缺失或目录不存在报用法错误并退出非零无gsd-file-manifest.json返回{ custom_files: [], custom_count: 0, manifest_found: false }——与 install.jssaveLocalPatches在无清单时的行为一致manifest 解析失败返回manifest_found: false并带error: manifest parse error。五、测试验证skills/扫描的行为契约该修复的回归测试集中在 tests/update-custom-backup.test.cjs与主题直接相关的用例包括测试验证点scans skills/ directory and detects custom gsd-prefixed skills not in manifest (#2942, #1325)tests/update-custom-backup.test.cjsskills/gsd-my-custom-skill/SKILL.md被列为自定义文件manifest 中已有的skills/gsd-planner/SKILL.md不被误报does not report non-gsd shared skills, hooks, or prior backups (#1325)tests/update-custom-backup.test.cjs非gsd-前缀技能、既有备份目录gsd-user-files-backup/skills/均不参与检测折叠自 bug-2942 的skills/ directory missing from GSD_MANAGED_DIRS系列tests/update-custom-backup.test.cjs检测自定义gsd-前缀技能、不检测共享技能、custom_count与custom_files.length一致、manifest_found语义agents/ and skills/ scanning is unaffected by the hooks-dir resolution changetests/update-custom-backup.test.cjs#3023 的 hooks 目录名解析改造不影响agents/与skills/扫描测试文件头部注释tests/update-custom-backup.test.cjs说明该测试面向detect-custom-files子命令的更新工作流备份检测#1997因此这批测试同时覆盖了备份、恢复restore-custom-files#1854、兼容性扫描与对抗性输入等更广的契约。六、纵深修复背后的完整保护链路本变更集只修了检测一环但围绕它的完整机制值得一并理解因为它们共同决定了用户文件在更新中不丢失6.1 恢复restore-custom-files检测与备份只是第一步恢复由 gsd-core/bin/gsd-tools.cjs 中的restore-custom-files完成对应 issue #1854。它支持两种模式plan默认遍历gsd-user-files-backup/执行兼容性检查不写任何文件--apply在 plan 的基础上把合格条目复制回原位置。关键不变量源码注释明确列出备份永不删除、已交付文件不被覆盖、已存在的不同文件不被覆盖、单个失败不中断整体、绝不写出配置目录之外。6.2 兼容性扫描恢复前会对每个备份文件执行对新版本的兼容性预检scanRestoreCompatibilitygsd-core/bin/gsd-tools.cjs因为自定义技能最常见的两种 GSD 引用在版本升级中可能改名gsd-core/workflows/foo.md这类对交付文件的引用正则gsd-core/...\.(md|cjs|js|json|sh)/gsd:plan-phase这类 slash 命令引用。两者缺失都会产生 advisory 警告不阻断恢复仅随报告输出。此外SKILL.md、agents/、commands/属于 frontmatter 驱动的表面缺少name/description字段的备份文件会被标记为恢复后不可用。扫描文件上限为 1 MiBRESTORE_SCAN_MAX_BYTES超限文件仍可恢复、只是跳过内容扫描。6.3 安全防护恢复路径对符号链接采取比常规assertWithinRoot更严格的策略collectBackupEntries拒绝遍历符号链接isSymlinkPath/hasSymlinkedAncestor双重检查确保写入不会穿透链接落到配置目录之外gsd-core/bin/gsd-tools.cjs。测试中甚至覆盖了skills/gsd-$(touch pwned);id/SKILL.md这类恶意路径注入与ATTACKER CONTENT 覆盖攻击场景tests/update-custom-backup.test.cjs。6.4 hooks 目录名的动态解析清单中 hooks 目录不是硬编码的resolveSharedHooksDirCandidatesgsd-core/bin/gsd-tools.cjs会读取安装器写入的configDir/gsd-core/.gsd-runtime标记#2297再查已交付的 capability registry./lib/capability-registry.cjs中该运行时的hostBehaviors.sharedHooksDirName默认hookspi 运行时为gsd-hooks。这是 #3023 对抗性评审发现的同类 bug 修复硬编码hooks会让重命名后的共享 hooks 树对检测完全不可见。当运行时无法判定时采用返回所有已知候选名的非对称降级——多扫是安全的不存在的目录会被跳过、manifest 中的文件不会被误报少扫才是真正的 bug。七、如何在本地复现与验证detect-custom-files是独立 CLI 子命令无需触发完整更新即可验证。以仓库内的安装树实现为例# 1. 构造一个最小配置目录包含 manifest 与一个用户自定义技能 mkdir -p /tmp/gsd-demo/skills/gsd-my-custom-skill printf # Demo Skill\n /tmp/gsd-demo/skills/gsd-my-custom-skill/SKILL.md printf {files: {skills/gsd-planner/SKILL.md: abc}} /tmp/gsd-demo/gsd-file-manifest.json # 2. 运行检测使用仓库内实现 node gsd-core/bin/gsd-tools.cjs detect-custom-files --config-dir /tmp/gsd-demo预期输出应包含custom_files: [skills/gsd-my-custom-skill/SKILL.md]且custom_count: 1同时不会误报 manifest 中已有的skills/gsd-planner/SKILL.md。若将自定义技能改为非gsd-前缀目录如skills/gstack-one/则不会被报告——因为安装器同样不会删除它。若需走完整链路可参考/gsd-update工作流的backup_custom_files步骤实现gsd-core/workflows/update.md与配套的restore-custom-files恢复步骤。八、小结wise-rams-gather这一行变更集修复了一个典型的清单漂移类回归当skills/升格为受管根后SDK 移植版本的GSD_MANAGED_DIRS未能同步导致/gsd-update静默销毁用户自定义技能且不留备份。修复通过将skills纳入前缀管理的受管目录扫描清单使detect-custom-files与安装器的删除行为精确对偶——既覆盖了用户新增的gsd-*技能又不会误报官方技能或非gsd-前缀的共享技能。配合gsd-user-files-backup/备份、restore-custom-files恢复、兼容性预检与符号链接防护gsd-core 在版本升级场景下对用户自定义文件的保护形成了检测—备份—恢复—校验的完整闭环。赞分享【免费下载链接】gsd-coreGit. Ship. Done - Core项目地址https://gitcode.com/gh_mirrors/ge/gsd-core点击查看免费下载相关推荐gsd-core 修复 buildStateFrontmatter 嵌套 plans 布局计数progress 计数器不再被静默回写gsd core 修复 buildStateFrontmatter 嵌套 plans 布局计数progress 计数器不再被静默回写 本文聚焦 gsd corget-shit-done 自定义文件保护机制详解detect-custom-files 扫描逻辑与 skills/ 目录静默丢失修复get shit done 自定义文件保护机制详解 detect custom files 扫描逻辑与 skills/ 目录静默丢失修复 本篇文章以 get人工智能AI 应用提示工程开发工具工作流自动化AI Agentgsd-core 并发锁修复acquireStateLock 不再静默吞掉非 EEXIST 错误杜绝 STATE.md 丢失更新gsd core 并发锁修复acquireStateLock 不再静默吞掉非 EEXIST 错误杜绝 STATE.md 丢失更新 导读 本篇文章围绕 gsd上一篇分布式多级缓存框架layering-cache为高并发场景设计的监控友好型解决方案下一篇轻量级对话界面Ollama Web UI Lite 技术概述创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表