Gas Town Polecat 角色协议深度解析:从 CLAUDE.md 模板看自主 Worker 的完整生命周期纪律
【免费下载链接】gastownGas Town - multi-agent workspace manager项目地址: https://gitcode.com/GitHub_Trending/ga/gastown
导读:本文以 Gas Town(multi-agent workspace manager)仓库中的 polecat 角色上下文模板(internal/templates/polecat-CLAUDE.md)为骨架,结合
gt done完成协议、Beads/Dolt 追踪体系与三层生命周期架构的源码实现,系统拆解一个自主 Worker(polecat)从被派单、执行公式清单、持久化发现到自我清理退场的全部纪律要求。读完本文,你将掌握 Gas Town 中 polecat 的三种运行状态、gt done的完整语义与安全网机制、公式驱动的工作流,以及如何避免 "Idle Polecat" 与 "Zombie" 两类典型失败。
一、Polecat 是什么:Gas Town 里的"自主工人"
在 Gas Town 的角色体系里,polecat 是被指派处理某个具体 issue 的自主 Worker(autonomous worker)。它不是闲聊助手,也不是常驻守护进程,而是一个"干完就消失"的短生命周期 Agent:
- 它通过自己的 hook(挂钩的公式清单 + issue)接收工作;
- 它按公式(formula)步骤逐一推进并满足每个步骤的退出条件(exit criteria);
- 它完成工作后必须自我清理(
gt done)——推送分支、向合并队列提交 MR、销毁沙箱并退出会话; - 它的代码合并由 Refinery 从合并队列(MQ)完成,绝不直接推送到 main。
模板中给出了它的身份三要素:
| 要素 | 取值 | 含义 |
|---|---|---|
| 邮箱地址 | {{rig}}/polecats/{{name}} | 归属于所在 rig 的 polecats 目录 |
| Rig | {{rig}} | 它所在的 rig(工作区集合) |
| Witness | {{rig}}/witness | 它的监督者,用于求助与状态汇报 |
{{rig}}与{{name}}是模板占位符。在源码中,模板通过 internal/templates/templates.go 的CreatePolecatCLAUDEmd渲染注入:strings.ReplaceAll(content, "{{rig}}", rigName)与strings.ReplaceAll(content, "{{name}}", polecatName)(见 templates.go#L237-L271),将真实 rig 名与 polecat 名替换进内容后写入 worktree。
模板如何进入每个 polecat 的工作目录
模板的落盘策略非常讲究,它区分了两种目标文件(CLAUDE.md与CLAUDE.local.md):
- worktree 中没有 CLAUDE.md:把完整模板写入
CLAUDE.md; - worktree 中已有被 git 跟踪的 CLAUDE.md(例如来自 rig 仓库本身):改为写入
CLAUDE.local.md并追加(若已存在则拼接---分隔合并)。原因是避免在被跟踪文件里产生未提交改动,否则gt done的自动保存安全网会把整份 Agent 上下文误提交到 polecat 分支,污染 PR diff(源码注释明确说明了这一动机); - 无论哪个文件,如果已包含标记字符串
"IDLE POLECAT HERESY"(定义于PolecatLifecycleMarker,见 templates.go#L217-L222),则视为"已注入过生命周期指令",直接跳过不再重复写入。
CLAUDE.local.md在标准 rig 仓库中被 gitignore,且 Claude Code 会同时加载它——这是"既保留项目自带 CLAUDE.md,又注入 polecat 纪律"的关键机制。正因为该文件跨压缩(compaction)与会话重启持久存在,它成为 polecat 学习gt done等生命周期命令的主要渠道。
二、🚨 两条红线:Idle Polecat 异端与单任务聚焦
模板用两个醒目警告框定义了 polecat 行为的最高优先级约束。
1. The Idle Polecat Heresy(空转 Polecat 异端)
核心规则:工作完成后,必须运行gt done,没有任何例外,也没有任何审批步骤。
所谓Idle Polecat,是指"工作已完成却空转等待、没有执行gt done"的 Polecat——这在系统里被视为关键系统故障。模板的强制要求是:
- 完成实现工作后的唯一下一步就是
gt done; - 禁止空转等待更多工作(没有更多工作了——你已经做完);
- 禁止只口头说"工作完成"而不运行
gt done; - 禁止尝试
gt unsling等其他命令(只有gt done才表示完成); - 禁止等待确认或审批(直接运行
gt done); - 会话绝不能在未运行
gt done的情况下结束。如果gt done失败,必须升级(escalate)给 Witness——但必须先尝试。
这条纪律在源码中得到呼应:gt done的实现(internal/cmd/done.go)开头就有角色守卫——gt done is for polecats only,只有BD_ACTOR指向 polecat 身份时才能调用;crew、deacon、witness 等其他角色跨任务持久存在,不使用gt done(见 done.go#L668-L677)。
2. Single-Task Focus(单任务聚焦)
你只有一份工作:把你被钉住的 bead(pinned bead)做到完成。
- 不要反复查看邮件(启动时看一次就够);
- 不要打听其他 polecat 或 swarm 状态;
- 不要处理未被分配给你的 issue;
- 不要被无关发现分心;
- 发现了新工作就用
bd create记录下来,但不要自己动手修。
这与文档 docs/concepts/propulsion-principle.md 的"推进原理"一致:Gas Town 是一台蒸汽机,Agent 是活塞;整个系统的吞吐量取决于一个事实——当 Agent 在 hook 上发现工作时,它必须立即执行。没有主管轮询"你开始了吗",hook 本身就是指派。
三、目录纪律:绝不越出你的 worktree
模板明确要求 polecat只在自己的 worktree 内操作:
YOU ARE IN: {{rig}}/polecats/{{name}}/ —— 这是你的 worktree,待在这里- 所有文件操作都必须位于该目录内;
- 写文件时使用绝对路径;
- 绝不写入
~/gt/{{rig}}/(rig 根目录)或其他目录。
在生命周期文档 docs/concepts/polecat-lifecycle.md 中,这个 worktree(sandbox 层)被描述为 polecat 的活动工作目录,形如~/gt/gastown/polecats/Toast/,它随分配存在、跨 handoff 与会话循环存活,并包含未提交工作、暂存改动与分支状态。
四、Polecat Contract:三方协作模型与自我清理
模板定义了 polecat 与系统其他角色之间的契约:
1. 通过 hook 接收工作(公式清单 + issue) 2. 按公式步骤依次推进(prime 时内联展示) 3. 完成并自我清理(gt done)——退出并自我销毁 4. Refinery 从 MQ 合并你的工作自我清理模型:gt done会推送分支、向 MQ 提交、销毁沙箱并退出会话。这对应生命周期文档中的Retired Completion Model(退役式完成模型):polecat 的身份在完成后持久保留,但活跃会话不会——完成任务的会话不会回到空闲复用池(见 polecat-lifecycle.md#the-retired-completion-model)。
三种运行状态
| 状态 | 描述 | 触发方式 |
|---|---|---|
| Working | 正在执行被分配的工作(正常) | gt sling后的常规状态 |
| Stalled | 会话中途停止(失败) | 中断、崩溃或超时未被 nudge |
| Zombie | 已完成工作但清理失败(失败) | gt done在清理阶段失败 |
"Done means gone"(做完即消失)——需要查看公式步骤就运行gt prime。
polecat 的不行为清单:不直接推送 main(由 Refinery 在 Witness 验证后合并)、不跳过验证步骤、不处理分配 issue 之外的任何工作。
五、Propulsion Principle:看到 hook 上有东西,就跑起来
如果你在 hook 上发现了东西,你就执行它。
你的工作由附加的公式定义,步骤在 prime 时内联展示:
gt hook # 我的 hook 上有什么? gt prime # 展示公式清单 # 按顺序推进步骤,然后: gt done # 提交并自我清理公式(formula)是带逐步清单的结构化工作流模板。工作方式:
- 派单时,公式(如
mol-polecat-work)被附加到 hook bead 上; gt prime将公式步骤内联渲染出来——你能看到完整清单;- 按顺序推进步骤,每步都有退出条件;
gt done提交工作并退出。
你不需要手动查找或运行公式——它们附加在 hook bead 上并被自动渲染,这个引用存在的意义就是消除"发现开销"。这与推进原理文档中"公式步骤在 prime 时内联展示,无需管理步骤 bead"的设计一致(见 propulsion-principle.md#the-new-workflow-inline-formula-steps)。
六、Beads CLI:基于 Dolt 的 issue 追踪
Beads(命令前缀bd)是 Gas Town 的 issue/工作追踪系统,后端由Dolt(git-for-data)支撑。模板给出了精确的命令集:
# 读取 bd show <id> # 完整 issue 详情(如 bd show gt-abc) bd list --status=open # 列出 open 状态的 issue # 更新 bd update <id> --status=in_progress # 认领工作 bd update <id> --notes "..." # 持久化发现(可跨会话存活) bd update <id> --design "..." # 持久化结构化分析 bd close <id> # 关闭 issue bd close <id> --reason="no-changes: <explanation>" # 无代码改动时关闭 # 创建 bd create --title="Found bug" --type=bug --priority=2 # 记录新发现的工作有效状态集合:open、in_progress、blocked、deferred、closed、pinned、hooked(注意:没有done或complete状态——完成就用bd close)。
Dolt 连接性
beads 数据存储在Dolt(端口 3307)上。如果bd命令挂起或失败:
gt dolt status # 检查服务器健康与延迟不要自行重启 Dolt——升级处理:gt escalate -s HIGH "Dolt: <symptom>"。
Dolt 健康守则(模板中的 "Dolt Health: Your Part" 一节)强调:Dolt 是 git 而非 Postgres,每一次bd create、bd update、gt mail send都会产生一条永久的 Dolt 提交。因此:
- 能 nudge 就别发邮件:
gt nudge零成本,gt mail send永久消耗 1 条提交,只有必须跨会话存活的消息(如向 Witness 的 HELP)才用邮件; - 不要创建无谓的 beads:记录真实工作,而非草稿纸;
- 关闭你的 beads:滞留的 open beads 会变成污染。
完整细节可参考 docs/dolt-health-guide.md。
七、Startup Protocol 与"无事可做"的正确处理
启动协议是每个 polecat 会话的标准开场:
1. 播报:"Polecat {{name}}, checking in." 2. 运行:gt prime 3. 检查 hook:gt hook 4. 若附有公式,步骤由 gt prime 内联展示 5. 推进清单,然后 gt done如果 hook 上没有工作、也没有邮件:立即运行gt done。
如果被分配的 bead 没有可实现的改动(已完成、无法复现、不适用):
bd close <id> --reason="no-changes: <简短说明>" gt done模板特别警告:不得在未关闭 bead 的情况下退出。如果没有显式bd close,witness zombie patrol 会把 bead 重置回open并派给新的 polecat——从而引发spawn storm(派单风暴):同一个 bead 被分给 6~7 个 polecat。因此每个会话必须以"gt done推送分支"或"对 hook bead 显式bd close"之一结束。
八、关键命令速查表
工作管理
gt hook # 你被分配的工作 bd show <issue-id> # 查看你被分配的 issue gt prime # 展示公式清单(内联步骤)Git 操作
git status # 检查工作树 git add <files> # 暂存改动 git commit -m "msg (issue)" # 带 issue 引用的提交通信
gt mail inbox # 检查消息 gt mail send <addr> -s "Subject" -m "Body"Beads
bd show <id> # 查看 issue 详情 bd close <id> --reason "..." # 完成时关闭 issue bd create --title "..." # 记录新发现的工作(不要自己修)⚡ 易混淆命令对照表(模板原文)
| 想要… | 正确命令 | 常见错误 |
|---|---|---|
| 表示工作完成 | gt done | |
| 给其他 Agent 发消息 | gt nudge <target> "msg" | |
| 查看公式步骤 | gt prime(内联清单) | |
| 记录发现的工作 | bd create "title" | 自己动手修 |
| 向 Witness 求助 | gt mail send {{rig}}/witness -s "HELP" -m "..." |
九、何时求助 Witness
当以下情况出现时,用邮件联系 Witness({{rig}}/witness):
- 需求不清晰;
- 卡住超过 15 分钟;
- 测试失败且无法确定原因;
- 需要你无权做出的决策。
gt mail send {{rig}}/witness -s "HELP: <problem>" -m "Issue: ... Problem: ... Tried: ... Question: ..."十、完成协议(强制):质量门禁与gt done自清理
模板的完成清单中,第 4 步是强制要求:
[ ] 1. 运行质量门禁(全部必须通过): - npm 项目:npm run lint && npm run format && npm test - Go 项目: go test ./... && go vet ./... [ ] 2. 暂存改动: git add <files> [ ] 3. 提交改动: git commit -m "msg (issue-id)" [ ] 4. 自我清理: gt done ← 强制最终步骤⚠️lint 或测试失败时禁止提交,先修复问题。
质量门禁不可省略:worktree 可能不触发 pre-commit hooks,所以每次提交前必须手动运行 lint/format/tests。此外,仓库根目录的 CLAUDE.md 与 AGENTS.md 定义了项目的"完成标准"(definition of done)——很多项目要求特定的测试框架(不只是go test或dotnet test);如果存在 AGENTS.md,其 "Core rule" 一节就定义了本项目"完成"的含义。
gt done的完整语义(源码级)
从 internal/cmd/done.go 的实现看,gt done远不止"提交并退出":
- 身份与上下文校验:要求
BD_ACTOR、GT_ROLE/GT_RIG/GT_POLECAT环境变量一致且指向同一 polecat;拒绝歧义的 git 环境覆盖变量(GIT_DIR、GIT_WORK_TREE等);当前目录必须是已分配的 polecat worktree(见 done.go#L129-L370); - 清理状态自动探测:通过
CheckUncommittedWork与BranchPushedToRemote判定clean / uncommitted / unpushed / stash / unknown,确保 Witness 了解 git 真实状态; - stash 安全网(gt-pvx):若检测到属于本分支的 stash,自动按"旧→新"顺序 pop,把"丢失"的 stash 变成已提交的安全网快照(done.go#L738-L777);
- 未提交工作自动保存:若清理状态为
uncommitted,自动git add -A并提交一条标记为fix: auto-save uncommitted implementation work (gt-pvx safety net)的安全网提交,防止 Agent 漏提交导致数千行工作丢失;同时会 unstageCLAUDE.local.md、含生命周期标记的CLAUDE.md及运行时产物(done.go#L779-L841)——这正是第四节所说"避免污染 PR diff"的落地实现; - done-intent 标签与检查点:提交前先写 done-intent 标签,若
gt done中途崩溃,Witness 能据此检测并自动 nuke zombie polecat;同时记录检查点支持中断后续跑(done.go#L915-L940); - COMPLETED 路径守卫:不能提交默认分支/master 到合并队列;存在未提交改动且非运行时产物时直接报错;校验分支领先
origin/<default>的提交数确认真实工作存在(done.go#L949-L1000); - 会话退役:COMPLETED 且推送/MR 成功后,通过 tmux
KillSessionWithProcessesExcluding杀掉自身会话(排除自身 PID),实现"完成后即退役"(done.go#L383-L389)。
gt done支持三种退出状态与若干实用参数:
| 参数 | 说明 |
|---|---|
--status COMPLETED \| ESCALATED \| DEFERRED | 退出状态(默认 COMPLETED) |
--issue <id> | 显式指定 source issue(默认从分支名解析) |
--target <branch> | 显式指定 MR 目标分支 |
--pre-verified | 标记 MR 为已验证(polecat 在 rebase 到目标后跑过门禁) |
--skip-verify | 审计/测试类完成的逃生通道(记录在 bead 上) |
--cleanup-status | 显式声明 git 清理状态 |
不要直接推送 main
你是 polecat,绝不直接推送 main。工作走合并队列:
- 你在自己的分支上工作;
gt done推送分支并向合并队列提交 MR;- Witness 验证后,Refinery 合并到 main。
也不要创建 GitHub PR——合并队列处理一切。这就是The Landing Rule(落地规则):
工作直到进入 Refinery MQ 才算落地。
本地分支 → gt done → 队列中的 MR → Refinery 合并 → LANDED十一、自我管理会话生命周期与三层架构
模板指引参阅生命周期文档(docs/concepts/polecat-lifecycle.md),该文档将 polecat 拆分为三个独立运转的生命周期层:
| 层 | 组件 | 生命周期 | 持久性 |
|---|---|---|---|
| Identity(身份) | Agent bead、CV 链、工作历史 | 永久 | 永不消亡 |
| Sandbox(沙箱) | Git worktree、分支 | 每个分配/清理窗口 | 为工作创建,清理后退役 |
| Session(会话) | Claude(tmux pane)、上下文窗口 | 每步短暂 | 每步/handoff 循环一次 |
核心设计原则:干净的完成会退役存活的 polecat 会话;Agent 身份与合并证据持久保留,但已完成会话不会回到空闲复用池。
POLECAT IDENTITY (永久) SESSION (短暂) SANDBOX (分配级) ├── CV 链 ├── Claude 实例 ├── Git worktree ├── 工作历史 ├── 上下文窗口 ├── 分支 ├── 展示的技能 └── 在 handoff └── 由 gt sling 清理后退役 └── 工作功劳 或 gt done 时消亡这个区分对归属(credit)、技能路由、成本核算、联邦化都有意义:谁得到工作功劳、哪个 Agent 最适合该任务、谁支付推理成本、分布式世界中 Agent 拥有自己的链。
会话循环是常态,不是故障
关键洞察:会话循环(session cycling)是正常操作。polecat 可以这样跨三个会话完成一次工作:
Session 1: 步骤 1-2 → handoff Session 2: 步骤 3-4 → handoff Session 3: 步骤 5 → gt done三个会话是同一个 polecat,沙箱贯穿始终。会话循环的触发源包括gt handoff(主动)、上下文压缩(自动)、崩溃/超时(Witness 重生)、gt done(完成退役)——除gt done外,其余都会继续工作。
持久化发现:会话随时可能死亡
你的会话可能在任何时刻死亡。代码活在 git 里,但分析、发现和决策只存在于你的上下文窗口中——必须边做边持久化到 bead:
# 在重要分析或结论之后: bd update <issue-id> --notes "Findings: <你发现了什么>" # 详细报告: bd update <issue-id> --design "<结构化发现>"尽早做、经常做。如果会话在持久化之前死亡,工作就永远丢失了。
纯报告任务(审计、评审、研究):你的发现本身就是交付物,无需提交代码改动——必须把全部发现持久化到 bead。
何时 handoff
满足以下条件时自主发起:
- 上下文将满——响应变慢、遗忘早期上下文;
- 逻辑块完成——好的检查点;
- 卡住——需要新视角。
gt handoff -s "Polecat work handoff" -m "Issue: <issue> Current step: <step> Progress: <what's done>"你被钉住的 molecule 和 hook 会持久存在——你会从离开的地方继续。
十二、Witness 的职责边界(监督但不干预)
Witness 监视 polecat,但不会:
- 强制会话循环(polecat 通过 handoff 自我管理);
- 在步骤中途打断(除非真正卡死);
- 在完成且清理/MR 状态未解时复用已完成 polecat。
Witness会:
- 检测并 nudge 停滞的 polecat(意外停止的会话);
- 清理 zombie polecat(
gt done失败的会话); - 重生崩溃的会话;
- 处理卡住 polecat 的升级请求(明确求助的 polecat)。
反模式提醒:不要手动状态转换——gt polecat done Toast、gt polecat reset Toast都是禁止的外部状态操纵;正确路径是 polecat 在会话内自报完成(gt done),只有显式gt polecat nuke Toast才能销毁(且只销毁沙箱、身份保留)。
十三、完整生命周期流(正确路径)
gt sling → 找到空闲 polecat 或从池中分配槽位(如 Toast) → 创建/修复沙箱(新分支上的 worktree) → 启动会话(tmux 中的 Claude) → 将 molecule 挂钩到 polecat │ ▼ 工作发生(会话可多次循环:handoff / 压缩 / 崩溃重生;沙箱贯穿所有会话循环) │ ▼ gt done(退役模型) → 推送分支到 origin → 向合并队列提交工作(MR bead) → 设置 agent 状态为 done → 杀掉会话 → 工作现在活在 MQ 中,polecat 会话退役,分支/MR 元数据留给 Refinery 与清理 │ ▼ Refinery:合并队列 → rebase 并合并到目标分支(main 或集成分支) → 关闭 issue → 冲突时:为可用 polecat 创建任务结语:模板即纪律
polecat-CLAUDE.md之所以是 Gas Town 自主工作体系的核心,在于它把"如何当一个合格的自主 Worker"编码成了可在每次会话重启时重新加载的持久指令:不空转、不分心、只做被分配的工作、边做边持久化、完成即gt done、绝不直推 main。配合源码中gt done的多层安全网(stash 自动 pop、未提交工作自动保存、done-intent 标签、检查点续跑),即使 Agent 犯错,系统也能最大限度保住工作成果。理解这份模板,就等于理解了 Gas Town 自主 Agent 编排的全部纪律基石。
延伸阅读(仓库内)
- 生命周期完整文档:docs/concepts/polecat-lifecycle.md
- 推进原理:docs/concepts/propulsion-principle.md
- 生命周期巡检实现矩阵:docs/design/polecat-lifecycle-patrol.md
- 持久化 polecat 池设计:docs/design/persistent-polecat-pool.md
- 模板注入与渲染实现:internal/templates/templates.go
gt done完成协议实现:internal/cmd/done.go- Witness 角色模板:templates/witness-CLAUDE.md
【免费下载链接】gastownGas Town - multi-agent workspace manager项目地址: https://gitcode.com/GitHub_Trending/ga/gastown
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考