ARTICLE DETAIL

资讯详情

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

gsd-core 安装器迁移模块:为每个受支持运行时接入基线扫描、原子回滚与锁保护的升级管线

gsd-core 安装器迁移模块:为每个受支持运行时接入基线扫描、原子回滚与锁保护的升级管线 【免费下载链接】gsd-coreGit. Ship. Done - Core项目地址https://gitcode.com/gh_mirrors/ge/gsd-core点击查看免费下载本篇技术指南以 gsd-core 仓库中的安装器迁移Installer Migration模块为核心讲解 GSD 如何把迁移机制接入所有受支持运行时的正常安装流程首次安装基线扫描、折叠式操作报告、被阻止操作的防护、事务式回滚、安装状态持久化以及在包物化之前用锁保护的执行。读完本文你将掌握迁移记录Migration Record的编写契约、全部动作类型与作者护栏、执行引擎的调用链与锁/日志/回滚机制并能在实际为 GSD 新增或维护迁移时直接上手。背景为什么安装器需要迁移层GSD 安装器在模块落地之前已经处理多种升级行为替换 GSD 托管的命令、技能、Agent、Hook 与引擎文件替换前备份本地修改过的托管文件保留已知的用户自有产物清理旧 Hook 文件与注册重写运行时特定的配置格式回滚部分失败的 Codex 安装。这些行为分散在各安装分支中可以处理孤立修复但让功能退役变得危险一次发布改动可能从包中移除某个文件却在已安装目录留下过期副本或者误删恰好位于 GSD 托管目录下的用户自建文件。迁移层存在的意义正是把升级行为变得显式、可评审、可重复。它在每个受支持运行时的正常安装/更新入口接入统一的迁移运行器在包物化之前完成规划、报告、安全应用与状态持久化。设计目标见 docs/installer-migrations.md包括默认保护用户数据、退役时移除过期 GSD 托管文件、破坏性动作先展示再执行、记录已应用迁移避免重复执行、为每个运行时提供相同的安全模型、把迁移编写成本压到足够低以便贡献者使用。模块有明确的非目标它不是通用包管理器不是数据库迁移系统不会自动推断所有历史安装布局不会删除任意用户文件也不会一步替换现有安装变换。核心概念与术语迁移层建立在四类文件所有权判定之上托管文件Managed file由 GSD 安装并记录在安装清单gsd-file-manifest.json中的文件。未改动时可自动替换本地改动过则必须备份或合并。用户自有文件User-owned file由用户工作流或用户直接创建维护的文件。绝不能因为它位于 GSD 目录下就被删除。未知文件Unknown file位于安装根目录下、不在清单中、也无法归类为用户自有的文件。除非迁移用带证据的检测器证明它是过期 GSD 产物否则一律保留。迁移Migration版本化的变更集可检查当前安装、产出计划并在安全检查通过后应用该计划。计划Plan提议的文件系统与配置动作列表只描述将要发生什么及原因不改写磁盘因此可安全展示给用户。日志Journal每次运行的应用动作与回滚数据记录用于失败安装尽量恢复运行前状态。状态文件清单与安装状态迁移层复用既有文件清单并新增一个安装状态记录。文件清单gsd-file-manifest.json清单保留为所有权基线记录安装的 GSD 版本、安装模式、写入它的运行时与作用域以及发行版自有文件的哈希{ manifestVersion: 2, version: 1.9.2, timestamp: 2026-08-10T00:00:00.000Z, mode: full, runtime: claude, scope: local, files: { gsd-core/VERSION: sha256-hex…, commands/gsd-plan-phase.md: sha256-hex… } }字段含义manifestVersion本文档的 schema 版本。缺失 ⇒ 版本 1即 #2872 之前写入的清单。version写入清单的 GSD包版本——不是 schema 版本两者刻意分离。timestampISO-8601 写入时间。modefull或minimal。runtime本次安装目标运行时claude、codex……schema 2 新增。scopeglobal或localschema 2 新增。files相对路径 → SHA-256仅发行版自有文件。runtime与scope的引入#2872让读取方可以直接回答哪些表面已安装、位于哪个作用域、属于哪个运行时而无需从文件所在目录反推。schema 2 之前全局与本地安装会把两份清单写入两个永不合并、永不交叉读取的目录。schema 1 清单被无错读取且绝不要求重装。readInstallManifest会把manifestVersion: 1连同runtime: null、scope: null一并上报所有消费方把字段缺失视为未声明而非未安装。新版本 GSD 写入的manifestVersion原样上报而不拒绝——一台机器上并存两个 GSD 版本是受支持状态——因此消费方应分支于 2而非 2。该实现位于 readInstallManifest其中normalizeManifestVersion只接受有限整数 1作为版本声明其余一律读作1。清单的不变式是严格的发行版自有文件必须被清单追踪用户自有文件被保留且不出现在清单哈希中一个路径不能同时属于两者。安装状态gsd-install-state.json安装器在清单旁写入gsd-install-state.json只承载迁移记账——运行时的版本、作用域、模式仍在清单中{ schemaVersion: 1, appliedMigrations: [ { id: 2026-05-11-codex-hooks-layout, packageVersion: 1.50.0, checksum: sha256:..., appliedAt: 2026-05-11T00:00:00.000Z } ] }实现中InstallState仅包含{ schemaVersion, appliedMigrations }camelCase见 src/installer-migrations.cts。状态文件使用严格原子写入atomicWriteInstallState先写临时文件再retryRenameSync改名落位绝不留下半写状态。校验和由迁移定义计算migrationChecksum缺省为sha256:前缀的序列化摘要。已应用的迁移永不重跑因此校验和漂移在运行时被容忍收集进plan.checksumDrift并在下次写入状态时调和reconcileDriftedChecksums而不是中止用户升级issue #670。已发布迁移体不可变这一规则由 CI 中提交的校验和基线测试tests/installer-migrations.test.cjs强制执行若要改变已发布迁移的行为应新增 fix-forward 迁移 id而不是编辑已发布体。迁移记录元数据契约与作者护栏每个迁移导出一个普通记录加纯规划逻辑。必填字段validateInstallerMigrationRecord 强制module.exports { id: 2026-05-11-runtime-layout-example, title: Move legacy commands into runtime skills, description: Move legacy runtime command files into the generated skill layout., introducedIn: 1.50.0, runtimes: [claude, codex, antigravity], scopes: [global, local], destructive: true, plan(ctx) { return []; } };安装器迁移作者护栏模块拒绝缺失id、title、description、introducedIn、scopes、destructive或plan的记录。runtimes仅对刻意全运行时共享的迁移保持可选但scopes必须显式防止作者无意中扩大本地/全局行为。plan(ctx)接收安装上下文运行时、作用域、目标目录、旧清单、安装状态、包清单与文件系统助手返回动作数组且不得改写磁盘。规划阶段可用的助手谓词包括isManaged(relPath)、isUserOwned(relPath)、hashMatchesManifest(relPath)、exists(relPath)、readJson(relPath)、readToml(relPath)。动作类型执行器拥有的原语迁移只产出少量动作类型执行器统一拥有变更、备份、回滚与上报支持的动作集合见 applyInstallerMigrationPlan 的白名单校验。remove-managed仅当路径已知为 GSD 托管且与旧清单一致或迁移提供了针对旧 GSD 属形状的专用检测器时才移除。作者护栏每个remove-managed动作必须带ownershipEvidence说明证明 GSD 所有权的清单条目、生成标记或专用检测器。用于退役 Hook、旧生成 Agent、废弃命令文件与过期运行时生成产物。backup-and-remove因文件与旧清单不一致而在删除前先备份托管路径用户会得到清晰报告并可检查备份。用于退役用户可能打过补丁的托管文件。规划阶段会自动升级当remove-managed遇到managed-modified分类时升级为backup-and-remove遇到unknown分类时升级为preserve-userplanInstallerMigrations。remove-empty-dir仅通过fs.rmdirSync移除目录节点——绝不用递归删除fs.rmSync、{ recursive: true }、{ force: true }。执行器在调用前立即重查空状态仍含任何条目的目录按成功非错误结果skipped-not-empty原样保留而不是被清扫。这是刻意弱于递归删除原语的实现该框架刻意不提供递归删除见 docs/adr/0008-installer-migration-module.md 的 2026-08-07 修订。额外护栏目标不得是符号链接从不跟随、从不穿透删除目标 realpath 必须严格解析在配置目录 realpath 之内且不得等于配置目录本身任何意外失败EACCES、EBUSY、检查与调用之间被并发移除都降级为left-in-place而非抛错。作者护栏同remove-managed必须带ownershipEvidence。该动作解决宿主运行时保留目录名字的场合如 pi 的hooks/#3023宿主检查的是目录存在本身而非内容留一个空壳目录会让告警永远触发。实现见 evaluateRemoveEmptyDir。move-managed把托管路径移动到新的托管路径。若源文件被本地修改过动作升级为backup-and-move或冲突。用于命令目录迁入技能等布局迁移。rewrite-config / rewrite-json通过解析器或既有结构助手重写结构化配置文件字符串替换仅限有换行与排序变体测试的窄范围标记块。初始执行器支持rewrite-json迁移用readJson(relPath)读取 JSON在动作中返回下一个解析值可设deleteIfEmpty: true让剩余结构为空时删除文件。执行器拥有磁盘写入、日志条目、回滚快照与运行时/作用域过滤。作者护栏每个rewrite-json动作必须带ownershipEvidence且迁移记录必须带runtimeContract引用运行时配置契约注册表。Codexhooks.json的清理迁移 002是典型用例——GSD 能证明单个生成 Hook 命令的所有权却不能证明整个文件。preserve-user / record-baseline / baseline-preserve-user / prompt-userpreserve-user声明路径为用户自有并须在周边目录替换中存活所有权未建立时非交互应用会阻塞直到交互式基线迁移记录显式用户选择。record-baseline把清单托管文件记入首次基线而不改动它仅首次基线扫描器可用。baseline-preserve-user把在已知安装表面发现的用户自有或未知文件记入基线而不改动未知文件默认此动作除非它们看起来像需要显式用户选择的退役 GSD 生成产物。prompt-user在交互模式下停止非交互破坏性迁移并询问提示必须给出具体选择保留、备份、移除、移动默认保留。用于分类有歧义、猜测可能丢数据的场景。执行流程从规划到物化的调用链安装器在物化新包载荷之前运行迁移。标准流程docs/installer-migrations.md构建安装上下文读取旧清单与安装状态为可能触及的路径构建运行前快照按运行时、作用域与应用状态发现待处理迁移向每个待处理迁移询问计划合并计划并校验以 dry-run 形式打印计划应用安全的非交互动作对歧义动作提示或停止写入新包载荷写入新清单与安装状态上报备份、保留文件、移除的过期文件与跳过的动作。Phase 4 的安装集成把这个流程接入每个受支持运行时的正常安装/更新入口Claude Code、Antigravity、Augment、Cline、CodeBuddy、Codex、Copilot、Cursor、Hermes Agent、Kilo、OpenCode、Qwen Code、Trae、Windsurf。安装器以baselineScan: true调用同一迁移运行器上报计划动作行在物化前应用安全非交互动作仅在包物化与收尾成功后持久化安装状态运行器返回被阻塞的用户选择动作时在写入新包文件之前失败。核心引擎位于 src/installer-migrations.cts约 1200 行规划/应用/回滚/锁/日志引擎。入口runInstallerMigrationsL1193-L1254串起三段先acquireInstallMigrationLock取锁再planInstallerMigrations规划无动作时仅markPendingMigrationsApplied落账有阻塞动作时原样返回blocked列表否则applyInstallerMigrationPlan执行并返回可调用的rollback句柄finally中释放锁释放失败按主错误路径压制或抛出。安装器侧的关键消费点包括 install-engine.cts读清单files、installed-surface-resolver.cts读清单与清单名、retired-artifact-cleanup.cts退役产物清理、runtime-artifact-layout.cts按managed-pristine分类判断覆盖与 user-artifact-staging.cts复用符号链接保留复制原语。对 OpenCode 家族的既有安装install-engine.cts 中的_migrateLegacyOpencodeCommandDir在物化前把旧单数command/目录迁往复数commands/#2329仅删除旧清单中记录且未变或本地修改过的command/file任何未能证明清单托管的用户内容原样保留空目录只在无残留后才移除。若任一应用步骤失败执行器用日志恢复尽可能多的已修改路径rollbackAppliedMigrationResult逆序遍历日志动作用copyPreservingSymlink从回滚根恢复字节符号链接快照按链接本身恢复绝不读取被指内容随后恢复安装状态字节并清理日志与备份树。回滚绝不删除本次运行未创建或未修改的文件。回滚是尽力而为但不完整时必须响亮报错rollbackFailures逐条列出。锁保护的执行acquireInstallMigrationLocksrc/installer-migrations.cts#L591-L676以gsd-install-migration.lock为互斥点默认超时 30 秒DEFAULT_LOCK_TIMEOUT_MS。要点以openSync(lockPath, wx)独占创建锁文件负载通过该独占描述符写入{ pid, acquiredAt }避免二次按路径打开造成的 TOCTOUCWE-367窗口写后立即关闭句柄保证 Windows 上释放闭包能 unlink 未被占用句柄的文件遇到EEXIST时读锁内 PID 做陈旧锁回收持有者死亡ESRCH或同进程重入则尝试 unlink 后重试仅当 unlink 真正成功才继续避免静默失败造成死循环超时后抛出installer migration lock is held附持有 PID 与时间释放用unlinkSync而非rmSync({ force: true })让 Windows EPERM 不被吞掉失败以带failures数组的错误抛出。测试侧对应断言包括 tests/installer-migrations.test.cjs持有锁时拒绝运行lockTimeoutMs: 0立即超时以及模拟 unlink 失败后上报锁释放失败。Dry run同一个规划器迁移运行器支持 dry-run打印计划后不做任何更改退出。输出按风险分组将保留、将替换未改托管文件、将移除过期托管文件、将备份本地修改文件、需要用户选择、被阻塞。同一规划器同时驱动 dry-run 与应用不允许存在独立的仅预览代码路径——这保证了预览即真实。首次基线迁移分类旧安装的逃生通道首个迁移应分类既有安装而非修复每种历史布局docs/installer-migrations.md。步骤读当前清单如有→ 扫描已知运行时安装表面 → 把文件分类为托管/用户自有/未知 → 上报不在当前清单中的过期 GSD 形状文件 → 为歧义文件提供动作而非删除 → 分类成功后写入安装状态。Phase 3 实现了门控基线记录2026-05-11-first-time-baseline-scansrc/installer-migrations/000-first-time-baseline.cts。运行器仅在安装器传baselineScan: true时才触发首次扫描不带该标志时发现过程对普通迁移运行安全基线记录规划零动作。基线动作契约record-baseline清单托管文件baseline-preserve-user已知用户自有文件与不像过期 GSD 生成产物的未知文件prompt-user无法被清单证明的过期 GSD 形状产物。实现细节值得注意RUNTIME_SURFACES记录了每个运行时的安装表面Claude 的commands/gsd、Codex 的config.toml、pi 的extensions等scanBaselineFiles递归遍历表面目录INTERNAL_TOP_LEVEL_NAMES跳过清单/状态/日志等内部文件isUserOwnedBaselinePath把skills/与agents/下非gsd-前缀条目、USER_OWNED_PATHS中的偏好文件判为用户自有isKnownGeneratedAgentPath对照仓库agents/目录里的gsd-*.md文件名集合判断生成 AgentisStaleGsdLookingPath识别gsd[-_]前缀的疑似过期产物并投给prompt-user。动作按record-baseline baseline-preserve-user 其余排序后输出保证基线可读。运行时配置契约注册表注册表是触及宿主运行时配置的迁移的事实来源docs/installer-migrations.md。每行记录WhatGSD 安装的调用、Agent、技能、规则、Hook 或配置表面、Where安装器瞄准的全局与本地根、When安装/升级/卸载/迁移触点、Who周边用户配置的所有权边界、Why上游加载器契约或当前 GSD 兼容垫片。迁移作者在产出rewrite-config、move-managed或破坏性清理动作前必须阅读对应行。注册表规则运行时提供 JSON/JSONC/TOML/YAML 时一律用结构化解析器标记块重写需换行与排序测试不声称混合配置文件的所有权只拥有生成条目、生成文件与显式标记块未知用户配置即使位于 GSD 托管运行时根内也要保留运行时文档/CLI schema/加载器行为变化时更新上游快照日期与版本注记源受限行按高风险处理重写这些运行时的迁移需要新主源或带测试的安装器级探针。已落地迁移一览每个已落地迁移对应src/installer-migrations/中的一个记录完整表见 docs/installer-migrations.mdID文件引入版本作用域破坏性摘要2026-05-11-first-time-baseline-scan000-first-time-baseline.cts1.50.0global, local否在破坏性迁移前记录既有安装的分类基线。2026-05-11-legacy-orphan-files001-legacy-orphan-files.cts1.50.0global, local是移除清单托管的旧孤儿 Hook 文件hooks/gsd-notify.sh、hooks/statusline.js。2026-05-11-codex-legacy-hooks-json002-codex-legacy-hooks-json.cts1.50.0global, local是在config.toml迁移后移除 Codexhooks.json中的旧 GSD Hook 注册。2026-06-02-rename-get-shit-done-to-gsd-core003-rename-get-shit-done-to-gsd-core.cts1.2.0global, local是重命名为gsd-core/#604后移除旧get-shit-done/目录中的托管文件用户新增文件保留。2026-06-09-prune-stale-pristine-get-shit-done004-prune-stale-pristine-snapshots.cts1.4.3global, local是移除迁移 003 遗留的gsd-pristine/get-shit-done/快照#934。2026-07-17-opencode-baseline-commands-dir005-opencode-baseline-commands-dir.cts1.7.0global, local否首次扫描中把 OpenCodecommands/复数既有文件纳入基线修复 000 只覆盖旧command/别名的问题。2026-07-20-pi-extension-cjs-to-js006-pi-extension-cjs-to-js.cts1.7.1global, local是移除 #2470 前 pi 安装遗留的extensions/gsd.cjs本地修改版备份而非删除未入清单的gsd.cjs按用户文件保留。2026-07-28-retire-config-root-commonjs-marker007-retire-config-root-commonjs-marker.cts1.8.0global, local是当configRoot/package.json恰为 pre-#2544 的{type:commonjs}标记时移除以内容精确匹配而非清单证明所有权。2026-07-29-cursor-retire-commands-surface008-cursor-retire-commands-surface.cts1.8.1global, local是移除 Cursor 安装中清单托管的commands/gsd-*.md#2644 重复条目修改版备份未入清单文件保留。2026-08-07-pi-retire-reserved-hooks-dir009-pi-retire-reserved-hooks-dir.cts1.9.2global, local是移除 pi 旧hooks/下托管文件并在清空后移除目录本身共享 Hook 包改装gsd-hooks/#3023首个使用remove-empty-dir的迁移。2026-08-26-antigravity-retire-confighome-artifacts010-antigravity-retire-confighome-artifacts.cts1.11.0global是移除 Antigravity configHome~/.gemini/antigravity{,-ide,-cli}下清单托管的skills/gsd-*/与agents/gsd-*.md仅全局作用域。这些迁移的写法印证了动作类型护栏例如 006 在头部逐条回答作者清单问题退役对象、所有权证明、用户修改怎么办、缺失怎么办、影响运行时/作用域、非交互是否安全而 009 用remove-empty-dir解决目录名存在本身触发宿主告警的场景可对照 006-pi-extension-cjs-to-js.cts 与 009-pi-retire-reserved-hooks-dir.cts 阅读。编写新迁移的实战流程当特性移除或移动安装产物时PR 必须包含docs/installer-migrations.md迁移记录dry-run 计划输出测试应用行为测试本地修改托管文件测试变更路径附近的用户自有文件测试若迁移影响用户可见安装行为更新发布说明。作者必须在迁移文件中回答退役哪个旧产物/配置形状如何证明它是 GSD 所有用户修改过怎么办缺失怎么办影响哪个运行时与作用域非交互安装中是否安全测试矩阵要求覆盖docs/installer-migrations.md无旧状态的全新安装、清单匹配的重装、有待处理迁移的升级、本地修改托管文件、GSD 目录下的未知文件、被清空目录下的用户自有文件、失败应用回滚、全局/本地作用域如适用、路径序列化时的 Windows 分隔符、配置文件重写时的 CRLF 输入。核心断言可在 tests/installer-migrations.test.cjs 中找到阻塞过期 GSD 形状基线产物prompt-user、未知文件默认保留、无阻塞计划的应用带日志与状态更新、回滚恢复文件与安装状态、锁占用拒绝运行、模拟 unlink 失败上报释放失败、应用失败清理回滚与备份产物。实施顺序docs/installer-migrations.md抽取清单与用户自有列表的所有权助手 → 安装状态读写 → 记录发现与校验和计算 → 仅规划器 dry-run → 带日志的 executor → 把孤儿 Hook/文件清理移植为首个显式迁移 → 移植一次结构化配置重写 → 既有安装基线分类器 → 要求影响安装的 PR 在移动/重命名/退役产物时带迁移。该序列保持首个实现小既有安装器继续物化文件迁移运行器接管清理、分类与可评审的破坏性变更。安全模型默认保护、显式删除安全策略docs/installer-migrations.md可归纳为三条所有权绝不删除未知文件除非迁移含证明其为过期 GSD 产物的特定检测器。修改检测路径在旧清单中时哈希匹配 未改托管文件可替换哈希不匹配 本地修改托管文件须备份缺失 用户已删应保持删除除非迁移明确需要重建。用户自有产物定义一次被保留逻辑与清单写入逻辑共同消费新增用户自有产物必须带证明其跨重装保留且不出现在清单中的回归测试。配置文件运行时配置是混合所有权GSD 可能拥有标记块、生成 Agent 段或 Hook 条目但不拥有整个文件除非文件是 GSD 专属创建。配置迁移只应移除或重写被拥有的部分。路径安全上所有动作路径先经normalizeRelPath拒绝绝对路径与任何..段再由ensureInsideConfig用词法谓词tryWithinRootLexical做纵深防御src/installer-migrations.cts符号链接托管路径被当作链接快照/恢复/备份绝不解析被指内容copyPreservingSymlink。这解释了为何回滚即使对被替换为链接的托管路径也不会把链接目标字节泄入备份树。结语安装器迁移模块把 GSD 的升级安全从分散的一次性清理块收敛为可评审、可回滚、可复现的版本化管线基线扫描负责把旧安装分类清楚折叠式动作报告让破坏性动作在物化前可见被阻塞动作以 fail-closed 保护用户数据事务式回滚与安装状态持久化保证失败可恢复锁保护确保多进程安装互斥。核心引擎与全部已落地迁移均可在仓库中直接阅读src/installer-migrations.cts、src/installer-migration-authoring.cts、src/installer-migrations/、tests/installer-migrations.test.cjs设计与契约见 docs/installer-migrations.md、docs/adr/0008-installer-migration-module.md 与 docs/features/installer-migrations.md。赞分享【免费下载链接】gsd-coreGit. Ship. Done - Core项目地址https://gitcode.com/gh_mirrors/ge/gsd-core点击查看免费下载相关推荐GSD Core 安装器迁移 003升级时安全清理遗留 get-shit-done/ 运行时目录的完整实现解析GSD Core 安装器迁移 003升级时安全清理遗留 get shit done/ 运行时目录的完整实现解析 GSD Coreopengsd/gsd cArchiSteamFarm容器安全镜像扫描与运行时保护ArchiSteamFarm容器安全镜像扫描与运行时保护 你是否在部署ArchiSteamFarm容器时遇到过安全隐患本文将从镜像构建安全、运行时防护和漏洞后端kubespray容器安全镜像扫描与运行时安全保护kubespray容器安全镜像扫描与运行时安全保护 前言容器安全的重要性与挑战 在云原生时代容器技术已成为应用部署的主流方式。然而随着容器化应用的广泛采云原生容器编排DevOps运维上一篇LovelyMem vs 传统取证工具为什么它是内存分析的最佳选择下一篇Meteor-Ionic 模态框和弹出层创建优雅的用户交互体验创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表