@tongzi/patcht
Patch Maintenance
patcht 是面向长期跟随第三方 Git 上游的二次开发补丁台账。1.0 的核心边界是:日常开发由用户自行完成,Skill 只在事后登记、跨版本维护和已有项目补录时介入;所有长流程由机器状态、事件、审批记录和可恢复事务持久化。
安装边界
全局只安装普通终端 CLI,不向 Pi、Codex 或 ~/.agents/skills 注册 Skill。真正的 Skill、仓库规则和宿主适配器只由 patcht init 安装:从官方项目开始时安装到新建的补丁 worktree;导入已有二开项目时安装到原二开仓库。外层容器和官方仓库工作树都不会识别本 Skill。
本地打包安装:
npm pack
npm install -g ./tongzi-patcht-1.0.0.tgz
patcht --help
公开发布后可直接安装:
npm install -g @tongzi/patcht
首次项目初始化必须从终端运行 CLI。不要使用 pi install 安装本包;那不是本项目的分发边界。初始化完成并进入安装了框架的补丁 worktree 或原二开项目后,后续登记、维护和补录流程才由项目级 Skill 接管。
四个使用场景
- 初始化官方项目:从终端运行
patcht init,克隆或使用现有官方仓库,确认官方 ref 和版本名称,从不可变 commit 创建带版本名称的 sibling worktree,再向新 worktree 安装.patch/、仓库规则、项目级 Skill 和宿主适配器。新克隆的官方仓库使用稳定的<仓库名>--official目录并 detached 到选定基线。初始化不创建任务。 - 登记已完成开发:从上次批准的登记检查点到当前冻结 HEAD 分析 Diff,按功能语义建议一个或多个补丁;用户确认分组后生成补丁候选,最终批准后入账并归档。
- 维护到官方新版本:确认目标 ref 和版本名称,fetch 后从新官方 commit 创建
<工作区名>--patch-<版本名称>sibling worktree,逐补丁分析兼容性;受管理的稳定官方目录切换为目标 commit 的 detached HEAD,旧版本 worktree 保持不变。用户决定保留、适配、官方吸收、废弃或继续处理冲突,完成验证后批准归档。 - 登记已有二开项目:先从终端初始化,冻结安装框架前的二开 HEAD,克隆同级官方仓库并记录官方基线;初始化仍不创建任务。框架直接安装到原二开项目,随后项目级 Skill 把官方基线与冻结 HEAD 的差异按功能分组补建台账。
首次初始化是唯一需要用户直接运行的 CLI 步骤。运行 patcht init 后选择“从官方项目开始”或“导入已有二开项目”,输入官方仓库地址,再直接回车使用远程默认分支最新提交,或输入区分大小写的精确 Tag。随后确认版本名称:精确 Tag 默认使用 Tag 名;默认分支没有 Tag 事实时默认使用 commit-<短 SHA>,也可输入其他显示名称。若版本名称与远程同名 Tag 指向不同 commit,CLI 会拒绝初始化。预览会分开显示版本名称、官方 Tag、ref 和不可变 commit。
初始化后,用户不需要记忆内部命令;在安装了框架的项目中对 AI 说“登记补丁”“维护到 vX.Y.Z”或“登记已有二开项目”即可。CLI 是 AI 的内部可靠执行层。
从用户选定的空项目目录开始克隆时,该目录作为外层容器。全局 CLI 在容器中创建官方仓库和补丁 worktree 两个同级子目录,只向补丁 worktree 安装项目能力:
项目目录/
├── official-repo--official/ # 稳定官方目录,detached 到当前选定官方版本
└── official-repo--patch-v1.0.0/ # 当前补丁 worktree
场景 3 会复用同一个官方仓库和 Git 对象库,不在旧 worktree 名称后继续拼接。维护到多个版本后的布局为:
项目目录/
├── official-repo--official/ # detached 到最近选择的目标官方 commit
├── official-repo--patch-v1.0.0/ # 旧版本,保持不变
└── official-repo--patch-v1.1.0/ # 新版本维护 worktree
版本名称用于分支和目录显示;官方 ref 与不可变 commit 才是源码事实。受管理官方工作树必须保持干净,场景 3 完整创建新任务后才切换其 detached HEAD;创建失败时恢复原 HEAD 并清理新分支和 worktree。
已有二开项目初始化后的目标布局如下。CLI 通过 Git 根目录识别项目,不根据普通文件夹数量猜测;存在多个候选 Git 仓库时要求用户选择:
项目目录/
├── custom-repo/ # 原二开项目,安装框架
└── official-repo--official/ # 官方仓库克隆,不安装框架
高级或自动化调用仍可显式提供参数:
patcht init --clone <url> --target <项目目录>/<仓库名>--official --base-ref <ref> --version-name <版本> --workspace-name <仓库名>
patcht init --custom-repo <二开项目> --clone <url> --target <官方仓库目录> --base-ref <ref> --version-name <版本>
已有官方 Git 仓库仍可通过 patcht init --repo <path> --base-ref <ref> 初始化,不要求调整其所在目录。执行前默认显示预览;交互终端确认后执行,也可使用 --dry-run 只预览或 --yes 非交互执行。平台默认 all,可显式使用 --platform pi|codex|none。
GitHub 代理处理
向导使用系统中的 git 访问远程仓库,并按以下顺序选择代理:
- 保留用户已有的
http_proxy、https_proxy或all_proxy环境变量。 - 保留目标仓库 URL 已命中的 Git
http.proxy配置。 - Windows 上两者都不存在时,读取当前用户的系统代理开关和实际
ProxyServer;支持单一 HTTP/mixed 端口、按 HTTP/HTTPS 分项的端口以及 SOCKS 端口,只向本次 CLI 进程及其 Git 子进程注入,不修改 Git 全局配置。 - 代理软件使用 TUN 模式时,Git 直接连接即可,无需额外代理变量。
因此,使用会开启 Windows 系统代理的 Clash、Xray 等软件时,端口由代理软件动态设置,用户不需要把端口写入 patcht。CLI 会在联网前显示本次自动采用的代理地址,但不会显示代理凭据。
浏览器扩展中的代理无法被终端可靠发现;PAC 自动配置也不能只靠静态端口解析。如果代理软件既没有开启系统代理也没有开启 TUN,需要在当前 PowerShell 会话中显式提供 HTTP/mixed 端口:
$env:http_proxy = "http://127.0.0.1:10808"
$env:https_proxy = "http://127.0.0.1:10808"
git ls-remote --symref https://github.com/OWNER/REPOSITORY.git HEAD
patcht init
端口应替换为代理软件当前显示的端口。若软件只提供 SOCKS 端口,则使用 $env:all_proxy = "socks5h://127.0.0.1:端口";socks5h 会让域名也通过代理解析。需要持久绑定 GitHub 时,仍可使用 Git 的 URL 级配置:
git config --global http.https://github.com.proxy http://127.0.0.1:10808
git config --global --get-urlmatch http.proxy https://github.com/
撤销该持久配置:
git config --global --unset-all http.https://github.com.proxy
初始化后的结构
仓库根目录/
├── AGENTS.md
├── .agents/skills/patch-maintenance/SKILL.md
├── .codex/
│ ├── hooks.json
│ └── hooks/patch-context.mjs
├── .pi/
│ └── extensions/patch-maintenance/
│ ├── index.js
│ └── package.json
└── .patch/
├── .version
├── .managed-files.json
├── config.json
├── upstream.json
├── state.json
├── workflow-definition.json
├── workflow.md
├── schemas/
├── scripts/
├── task/ # 当前 worktree 中的真实任务目录
├── archive/YYYY-MM/ # 用户最终批准后的完整任务证据
├── patches/
│ ├── catalog.json
│ └── PM-xxxx-*/
├── history/versions/ # 跨版本结果的轻量、可重建索引
├── reports/
└── runtime/ # AI 生成的临时输入,不是事实源
Git common dir 还保存 patch-maintenance/tasks.json 和项目锁,用于跨 worktree 定位唯一活动任务;它们不替代 .patch/task/<id>/ 的任务事实。AGENTS.md 保存项目级强制边界,.agents/skills/patch-maintenance/ 是 Codex 与 Pi 共用的 Skill;.codex/ 和 .pi/ 分别放置宿主适配器,不是第二套事实源。
任务与审批
只有三种任务:patch-registration、version-maintenance、customization-registration。统一状态为:
analyzing -> awaiting_decision -> executing -> verifying -> awaiting_approval -> archived
任一活动分析/决策/执行/验证状态 -> blocked -> 声明的恢复状态
awaiting_approval -> recovery_required -> archived
任务最少包含 task.json、progress.json、events.jsonl、plan.md、analysis.md、verification.json 和 decisions.json;登记任务增加 proposal.json 与文件/hunk 证据,维护任务增加 assessment.json 和 recommendations.json,完成候选增加 result.json 与 candidate.md,最终批准增加 approval.json 和 transaction.json。所有文件随任务一起归档,因此会话压缩或新开会话不会丢失进度。
平台适配结论
需要宿主适配层,但职责必须很窄:Codex Hook 在 SessionStart 和 UserPromptSubmit 注入,Pi Extension 在 before_agent_start 注入;两者都调用 .patch/scripts/lib/context-injection.mjs,读取项目级任务索引并校验真实任务文件。有任务才注入 worktree、类型、状态、当前步骤、下一动作、待决策和必读路径,没有任务时完全静默。适配层不修改任务、不判断步骤已完成,也不替代人工批准。
Doctor 的文件检查和自检不能证明宿主已信任项目。Codex 使用 /hooks 核对实际加载状态;Pi 核对启动头或 pi config -l,信任或文件变化后可运行 /reload。
历史版本策略
不在仓库内部保存“完整项目副本”。完整副本会重复 Git 数据、放大仓库并引入递归和忽略规则问题。每次新版本维护记录官方基线、最终 commit、稳定补丁 ID、规范化补丁哈希和决策;需要查看历史源码时,从记录的 commit 创建仓库外 sibling worktree,可无损恢复完整项目。
开发与验证
node scripts/patch-maintenance.mjs --help
node tests/package.mjs
node tests/cli-package.mjs
node tests/integration.mjs
node tests/safety.mjs
node tests/v3.mjs
所有文本使用 UTF-8。写命令默认只预览,只有 AI 核对事实后才加入 --apply。