ARTICLE DETAIL

资讯详情

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

Gas Town 持久化 Polecat 池设计解析:身份、沙箱、会话三层生命周期分离与实施现状

Gas Town 持久化 Polecat 池设计解析:身份、沙箱、会话三层生命周期分离与实施现状 Gas Town 持久化 Polecat 池设计解析身份、沙箱、会话三层生命周期分离与实施现状【免费下载链接】gastownGas Town - multi-agent workspace manager项目地址: https://gitcode.com/GitHub_Trending/ga/gastown导读本文基于 docs/design/persistent-polecat-pool.md 设计文档系统梳理 Gas Town 多智能体工作区管理器中Polecat 工人持久身份 临时会话的池化设计为什么要把身份 / 沙箱 / 会话三层生命周期拆开、池状态机如何流转、池大小如何配置、gt sling与gt done如何围绕池协同以及 Refinery / Witness 如何接管完成后的分支与 MR 状态。读完你将掌握 persistent polecat pool 的完整设计脉络、rig.config.json中的池配置语义、各实施阶段的真实落地情况并能在 internal/cmd/polecat.go、internal/polecat/manager.go 等源码中定位到对应实现。一、问题背景三个概念在生命周期中被混为一谈设计文档开篇Issuegt-lpop指出了一个核心问题在早期的 Polecat 生命周期模型中三个生命周期完全不同的概念被当作一个整体对待概念生命周期旧行为Identity身份长生命周期名字、CV、账本在 nuke 时被销毁Sandbox沙箱按任务分配worktree、branch在 nuke 时被销毁Session会话瞬时Claude 上下文窗口 Polecat 的生命周期这种一损俱损的耦合带来了一连串后果Polecat 在推送前被 nuke 时工作进行中丢失由于被销毁的 worktree 无人清理累积了219 条陈旧的远端分支每次任务分配都要重新创建 worktree约 5 秒派发缓慢能力记录CV、完成历史丢失无法为后续任务路由与成本核算提供依据空闲的 Polecat 被当成浪费而遭到 nuke。核心教训是销毁一个会话session不应该销毁一个工人的身份identity也不应该销毁承载工作的沙箱sandbox。这一认知直接催生了下面的三层分离设计。二、设计核心三层生命周期分离设计文档给出的目标模型如下IDENTITY (persistent) Name: furiosa Agent bead: gt-gastown-polecat-furiosa CV: work history, languages, completion rate Lifecycle: created once, never destroyed (unless explicitly retired) SANDBOX (per-assignment, reusable) Worktree: polecats/furiosa/gastown/ Branch: polecat/furiosa/issuetimestamp Lifecycle: synced to main between assignments, not destroyed SESSION (ephemeral) Tmux: gt-gastown-furiosa Claude context: cycles on compaction/handoff Lifecycle: independent of identity and sandbox三层各自独立运作配合gt polecat命令的自我描述persistent identity, ephemeral sessions见 internal/cmd/polecat.go 中polecatCmd的 Long 说明要点如下身份层agent bead、CV 链工作历史、语言、完成率永久保留除非显式退役否则永不销毁沙箱层git worktree 与分支按任务分配任务间可复用——从当前 main 创建新分支即可不需要反复 worktree add/remove会话层tmux 中的 Claude 上下文是瞬时的随压缩compaction与 handoff 周期性地更替与会话、沙箱完全解耦。补充文档 docs/concepts/polecat-lifecycle.md 对三层给出了更细的层归纳Identity 层agent bead CV 链 邮箱归属永久、Session 层Claude/tmux按 step/handoff 循环、Sandbox 层worktree任务期间持久清理后退役、Slot 层名称分配polecats/Name/路径、gt-gastown-Nametmux 会话、gastown/polecats/Name归属标识。池状态机设计文档给出的池状态流转┌──────────┐ ┌───►│ IDLE │◄──── sync sandbox to main │ └────┬─────┘ clear hook │ │ gt sling │ ▼ │ ┌──────────┐ │ │ WORKING │◄──── session active, hook set │ └────┬─────┘ │ │ work complete │ ▼ │ ┌──────────┐ └────┤ DONE │──── push branch, submit MR └──────────┘需要特别注意的现行差异文档明确标注——This historical design described IDLE reuse after DONE. Current behavior retires clean completed sessions instead of returning them to the idle reuse pool.该历史设计描述的是 DONE 之后回到 IDLE 复用现行行为是干净完成的会话直接退役不再回到空闲复用池。这与 docs/concepts/polecat-lifecycle.md 中退休式完成模型Retired Completion Model一致IDLE → WORKING → DONE快乐路径上没有空闲复用Polecat 完成工作后由清理/Refinery 接管分支与 MR 状态。三、池管理配置、初始化、派发与完成池大小配置rig.config.json池是按 rig 固定大小的配置在rig.config.json中{ polecat_pool_size: 4, polecat_names: [furiosa, nux, toast, slit] }源码中对应的结构体字段位于 internal/rig/manager.goL109-L113// Persistent polecat pool configuration. // PolecatPoolSize is the number of persistent polecats to create with pool init. // PolecatNames optionally specifies fixed names (overrides theme-based naming). PolecatPoolSize int json:polecat_pool_size,omitempty PolecatNames []string json:polecat_names,omitemptypolecat_pool_size池的目标数量omitempty语义下省略即不生效polecat_names可选的固定名字列表覆盖基于主题的命名。初始化创建 N 个持久化 Polecat设计文档给出了两种初始化路径gt rig add创建 rig 时按配置初始化池gt polecat pool init rig为既有 rig 创建 N 个带有身份和 worktree 的 Polecat初始状态为 IDLE。在当前的源码中该命令以gt polecat pool-init rig的形式注册于 internal/cmd/polecat.gopolecatPoolInitCmdL299-L325支持--size与--dry-run两个参数。runPolecatPoolInitL2310 起实现了文档描述的全部语义且明确了参数优先级--size标志polecatPoolInitSize 0时覆盖一切rig.config.json中的polecat_pool_sizerigCfg.PolecatPoolSize 0默认值 4。名字来源也有两级优先级polecat_names若在 rig 配置中指定→ rig 的 name pool 主题默认mad-max。默认主题定义在 internal/polecat/namepool.goDefaultTheme mad-maxL26内置主题列表从furiosa, nux, slit, rictus...开始此外还有minerals、wasteland等主题。设计文档示例中的furiosa / nux / toast / slit正是 mad-max 主题的前几个名字。几个值得注意的实现细节与设计文档只创建新 Polecat、保留既有者的约定一致已存在的 Polecat 会被保留pool-init只补齐到目标池大小L2334-L2342 先mgr.List()收集 existingNames每个新建的 Polecat 在创建后通过SetAgentStateWithRetry(name, idle)置为 idle 状态L2405--dry-run只打印将要创建的名字而不实际创建L2381-L2387创建完成后会同步 hookssyncRigHooks确保所有 polecat 的 settings.json 反映最新默认值L2416-L2424。设计文档的状态表将gt polecat pool initcommand标注为 DEFERRED但从当前源码看该命令已实现注册文档亦注明Polecats are allocated on-demand bygt slingvia capacity allocation. Pool size enforcement is a future optimization, not a blocker.——即池大小强制执行仍是未来优化当前以gt sling的按需容量分配为主。派发与完成派发gt sling bead rig分配容量、挂接工作并在全新工作分支上启动会话。源码层面internal/cmd/sling.go 中有容量快照输出Polecat capacity reserved (%d free of %d)而分支创建由 internal/polecat/manager.go 的buildBranchNameL560完成——默认格式为polecat/name/issuetimestamp也可通过 rig 配置polecat_branch_template自定义模板模板支持{user}、{year}、{month}、{name}、{issue}、{description}、{timestamp}等变量。完成当一个 Polecat 完成工作后按文档定义的顺序执行将分支推送到 origin提交 MR若存在代码变更清除 hook_bead将状态置为 DONE保留分支/MR 元数据供 Refinery 评审退役当前活动会话。这套完成即退役retired completion的流程在 internal/witness/handlers.go 的HandlePolecatDoneL139中得到印证POLECAT_DONE消息处理中有 MR 挂起时创建 cleanup wisp 并向 Refinery 发送MERGE_READY无 MR 时直接确认完成并让 Polecat 转为 idle不 nuke。四、沙箱退役DONE 转换只有分支操作没有 worktree 重建设计文档强调完成工作后gt done保留分支与 handoff 元数据远端分支不删除git push origin polecat/furiosa/issuesuffix # Refinery/review and cleanup own the remaining branch/worktree state新任务 sling 时只在既有 worktree上做分支操作# Create fresh branch from current main git checkout -b polecat/furiosa/new-issuetimestamp # Start working没有 worktree add/remove只有既有 worktree 上的分支操作——这正是把派发耗时从约 5 秒的 worktree 创建降低为毫秒级分支切换的关键。补充文档 docs/concepts/polecat-lifecycle.md 也强调worktree如~/gt/gastown/polecats/Toast/在任务期间跨 handoff/会话循环持续存在gt done不同步回 main、不删除分支未提交的工作、暂存变更、分支状态在活动期间都保存在其中。五、Refinery 集成无改动 一条新增设计文档对 Refinery 的定位是零改动仅补一步从 polecat 分支看到 MR评审并合并到 main新增合并后删除远端 polecat 分支。Polecat 在gt done时不会在本地把分支切回 main分支/MR 元数据保留给 Refinery 评审与后续清理。这构成了完整的清理管线POLECAT_DONE → MERGE_READY → MERGED在 internal/witness/handlers.go 与 internal/refinery/engineer.go 中实现Polecat branch always deleted after merge已标注 SHIPPED。六、Witness 集成巡逻行为的三条规则Witness 对池内 Polecat 的巡逻行为已上线遵循三条规则空闲即健康看到 idle Polecat → 判定健康状态跳过不 nuke卡住检测Polecat 处于 WORKING 状态过久 →升级escalate而非 nuke死会话检测会话死亡但状态仍是 WORKING →重启会话而非 nuke Polecat。这套restart-first policy重启优先不自动 nuke在 internal/witness/handlers.go 中有多处实现注释佐证如gt-dsgp: Uses restart-first policy. Instead of nuking polecats, restarts their ...。空闲 Polecat 的heresy fix跳过健康空闲项同样标注为 SHIPPED。与之配套的僵尸/卡住/孤儿检测与清理管线也在 internal/witness/handlers.go 与 internal/polecat/manager.go 中实现。七、Nuke 的角色转变从日常操作到保留手段设计文档明确gt polecat nuke只保留给异常场景——Polecat 的 worktree 已不可修复地损坏需要回收磁盘空间rig 退役。它应当是罕见且手动的操作而非正常流程的一部分。当前源码中gt polecat nukeinternal/cmd/polecat.go L171-L199也印证了这一收紧命令会先执行一系列安全检查cleanup_status 非 dirty/unknown、无未推送/未提交/暂存变更、无 open MR、hook 上无工作只有--force才会绕过并明确警告 LOSES WORK。这与idle 即健康、死会话只重启不 nuke的池化管理哲学一致。八、分支污染解决方案与一次性清理分支归属模型引入完成即退役后远端分支有了清晰的归属方活动分支Polecat 正对其 WORKING已合并分支Refinery 合并后删除废弃分支由 cleanup/recovery 在获得持久化 handoff 证据后决定。那 219 条陈旧分支的根源正是被 nuke 的 Polecat 从未清理过。现行模型下分支生命周期由 Refinery/recovery 管理而非gt done中的本地分支删除。一次性清理脚本针对存量 219 条陈旧分支设计文档给出了一键清理命令删除不属于活跃 Polecat 的全部远端 polecat 分支# Delete all remote polecat branches that dont belong to active polecats git branch -r | grep origin/polecat/ | grep -v furiosa/gt-ziiu | grep -v nux/gt-uj16 \ | sed s/origin\/// | xargs -I{} git push origin --delete {}实际使用时需把grep -v中的白名单替换为当前活跃 Polecat 的分支前缀。此外仓库还提供了更安全的日常工具gt polecat prune rig仅删除已完全合并的分支--remote可同时清理远端与gt polecat gc rig清理孤儿分支与旧时间戳分支仅保留每个 Polecat 的当前分支均支持--dry-run预览见 internal/cmd/polecat.go。九、实施阶段与落地状态设计文档以五个阶段记录了从止血到池化的推进路径阶段内容状态Phase 1Stop the bleedingWitness 不再 nuke 空闲 Polecatgt done转 DONE 并退役会话Refinery 合并后删远端分支SHIPPEDPhase 2Pool initializationgt polecat pool init rig创建 N 个持久 Polecat池大小配置在 rig.config.jsonworktree 为活跃工作创建、清理后退役DEFERRED当前按需分配池大小强制为未来优化Phase 3Sandbox syncDONE 不再把 worktree 同步回 main干净完成设置 done-state handoff 并退役会话SUPERSEDED被退休式完成模型取代Phase 4Session independence会话循环不影响 Polecat 状态死会话由 Witness 重启restart-firsthandoff 跨会话保留身份gt handoff对所有角色可用SHIPPEDPhase 5One-time cleanup合并后清理 polecat 分支PARTIALLY SHIPPED合并后分支清理已落地PR #2436/#2437 关闭Refinery 合并后通知 Mayor、池对账ReconcilePool未实现组件级状态总览文档原始表格组件状态关键文件gt done推送、MR/PR handoff、done-state 会话退役SHIPPEDinternal/cmd/done.gogt sling容量分配、分支准备SHIPPEDinternal/cmd/sling.go、internal/cmd/polecat_spawn.gogt handoff会话循环、所有角色SHIPPEDinternal/cmd/handoff.goWitness 巡逻僵尸、陈旧、孤儿检测SHIPPEDinternal/witness/handlers.go、internal/polecat/manager.go清理管线POLECAT_DONE → MERGE_READY → MERGEDSHIPPEDinternal/witness/handlers.go、internal/refinery/engineer.go空闲 Polecat heresy fix跳过健康空闲SHIPPEDinternal/witness/handlers.goRestart-first 策略不自动 nukeSHIPPEDinternal/polecat/manager.go合并后始终删除 polecat 分支SHIPPEDinternal/refinery/engineer.goRefinery 合并后通知 MayorNOT SHIPPED—池大小强制DEFERRED—ReconcilePool()DEFERRED—gt polecat pool init命令DEFERRED—两个值得注意的设计文档与当前源码的时间差以源码为准ReconcilePool()文档状态表标注未实现但当前 internal/polecat/manager.goL1977已实现ReconcilePool/reconcilePoolInternal/ReconcilePoolWith——它遵循 ZFCZero-False-Config原则从文件系统目录与 tmux 会话推导池的 InUse 状态而非单独追踪并会杀死无目录的孤儿会话、清理孤儿 polecat 状态每次分配前都会调用gt polecat pool init文档标注 DEFERRED但命令实际已以gt polecat pool-init rig注册并实现上文已述。十、快速上手与源码导航如果你要在自己的 rig 上实践这套池化设计推荐路径# 1. 在 rig.config.json 中配置池可选固定名字 # { polecat_pool_size: 4, polecat_names: [furiosa, nux, toast, slit] } # 2. 初始化持久化池先预览再执行 gt polecat pool-init rig --dry-run gt polecat pool-init rig # 3. 查看池内状态会话是否存活、状态、可复用性 gt polecat list rig gt polecat status rig/furiosa # 4. 派发与完成 gt sling gt-xyz rig # 容量分配 分支准备 启动会话 gt done # 在 polecat 会话内推送分支、提交 MR、置 done、退役会话 # 5. 日常分支维护均可 --dry-run 预览 gt polecat prune rig --remote gt polecat gc rig补充文档 docs/concepts/polecat-lifecycle.md 从退休式完成模型的视角与本文互为印证并提供了 docs/design/polecat-lifecycle-patrol.md 作为实现细节与巡逻协调的延伸阅读docs/concepts/identity.md 进一步阐述身份/CV 链在 HOP 模型中的地位。需要深入源码时优先阅读 internal/polecat/manager.go池对账与生命周期、internal/polecat/namepool.go主题命名与内置名字池、internal/cmd/polecat.go全部gt polecat子命令以及 internal/witness/handlers.goPOLECAT_DONE/MERGE_READY/MERGED 清理管线。【免费下载链接】gastownGas Town - multi-agent workspace manager项目地址: https://gitcode.com/GitHub_Trending/ga/gastown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表