资讯动态

Gas Town Wisp Reaper 实战:gt reaper 跨 Dolt 数据库的过期 Wisp 与 Issue 清理全流程解析

发布时间:2026/9/13 19:28:16 来源:尧图企业网站定制
Gas Town Wisp Reaper 实战gt reaper 跨 Dolt 数据库的过期 Wisp 与 Issue 清理全流程解析【免费下载链接】gastownGas Town - multi-agent workspace manager项目地址: https://gitcode.com/GitHub_Trending/ga/gastownGas Towngastown中的 Wisp 是存储在各 Dolt 数据库里的工作单元长期运行后 open/closed 记录会持续积累需要定期清理。本文基于仓库中的斜杠命令定义 reaper.md完整讲解 Wisp Reaper 的直接执行流程Dolt 健康检查、数据库发现、扫描候选项、收割reap、清除purge、Issue 自动关闭auto-close与异常上报并结合 internal/reaper/reaper.go 的源码实现、mol-dog-reaper 配方 和 daemon 巡逻逻辑说明每个参数、每条 SQL 操作背后的行为与安全边界读完你可以独立执行并解读完整的清理周期。1. Reaper 的定位直接执行的 mol-dog-reaper 周期在 Gas Town 的多智能体体系中Wisp Reaper 是一条基础设施清理链路负责三件事Reap收割把超过最大年龄、且父 Molecule 已关闭或已丢失/孤儿化的 open Wisp 置为 closedPurge清除物理删除超过保留期的已关闭 Wisp 与旧邮件mail行不可逆Auto-close自动关闭把长期无更新、且不属于 P0/P1、Epic、存在活跃依赖的 Issue 自动关闭。该周期有两种执行方式。常规情况下由 daemon 的wisp_reaper巡逻每小时触发一次先为mol-dog-reaper配方“倒”一个 molecule再通过gt sling派发一条 Dog 执行公式名常量定义见 constants.goDog 读取 mol-dog-reaper.formula.toml 中的步骤描述调用gt reaperCLI 辅助命令完成各步 SQL 操作。而本文主角——.claude/commands/reaper.md定义的斜杠命令——是不经过 Dog 派发的直接执行路径由 Agent 按命令文档中的 7 个步骤直接依次调用gt reaper各子命令运行的是与配方完全相同的周期。这与 CLI 中gt reaper run的定位一致其帮助文本明确写道“This is the inline fallback for when Dog dispatch is unavailable”见 cmd/reaper.go。命令文件头部的 frontmatter 界定了 Agent 的权限与入参description: Run the wisp reaper — scan, reap, purge, and auto-close stale beads across all Dolt databases allowed-tools: Bash(gt reaper:*), Bash(gt escalate:*), Bash(gt dolt status:*) argument-hint: [--dry-run]即 Agent 只被允许调用gt reaper:*、gt escalate:*、gt dolt status:*三类命令唯一的可选参数是--dry-run报告将发生的变化但不实际修改数据。2. 参数与默认值命令阈值、CLI 默认值与配方变量的对照.claude/commands/reaper.md中给出的默认值表如下这些是该命令在执行步骤中显式传入的阈值参数默认值说明max_age24hWisp 年龄超过该值则被收割关闭purge_age72h已关闭 Wisp 超过该值则被清除删除stale_issue_age168h陈旧超过该值的 Issue 被自动关闭mail_delete_age72h已关闭邮件超过该值则被清除alert_threshold3000触发升级上报的 open Wisp 数量dolt_port3307Dolt 服务器端口需要注意一个容易混淆的点gt reaperCLI 自身的 flag 默认值与此表不同。从 cmd/reaper.go 的init()注册逻辑看FlagCLI 默认值说明--max-age24h收割前的 Wisp 最大年龄--purge-age168h7 天清除前已关闭 Wisp 的最大年龄--mail-age168h7 天清除前已关闭邮件的最大年龄--stale-age720h30 天自动关闭前的 Issue 最大陈旧时长--db-delay250ms数据库之间的间隔降低 Dolt 负载--host/--port从 town 配置解析缺省127.0.0.1:3307Dolt 服务端点--dry-run/--json/--dbfalse/false/预览模式 / JSON 输出 / 指定单一数据库mol-dog-reaper 配方的 vars 段 与 CLI 默认值保持一致max_age 24h、purge_age 168h、stale_issue_age 720h、mail_delete_age 168h、alert_threshold 3000、dry_run 空、databases 空即自动发现、db_delay 250ms。也就是说斜杠命令文档中的 72h/168h 是命令提示词内固化并显式传入的保守阈值而非 CLI 缺省值——直接裸跑gt reaper run时会用 7 天/30 天的宽默认值。另外 daemon 的内联回退路径daemon/wisp_reaper.go使用defaultStaleIssueAge 7 * 24 * time.Hour168h与 7 天的删除/邮件年龄巡逻间隔默认 1 小时均可通过 daemon 配置中的WispReaper段interval、max_age、delete_age、databases、dry_run覆盖。3. Step 1验证 Dolt 服务器健康清理周期以只读检查开始gt dolt status若服务器不健康或不可达必须停止并升级上报而不是硬闯后续步骤gt escalate Reaper blocked: Dolt server unhealthy -s HIGH这一步是后续所有数据库操作的前置闸门。Reaper 对 Dolt 的连接参数在 OpenDB 中构造DSN 形如roottcp(host:port)/dbname?parseTimetruetimeout5sreadTimeout..writeTimeout..连接超时固定 5 秒读写超时由调用方指定scan/reap 用 10 秒purge/run 用 30 秒。4. Step 2发现目标数据库gt reaper databases --json该命令列出 Dolt 服务器上的全部生产数据库期望看到hq、beads、gastown以及各 rig 的专属库。底层 DiscoverDatabases 的行为细节以 5 秒超时执行SHOW DATABASES过滤系统库information_schema、mysql过滤测试污染库——前缀为testdb_、beads_t、beads_pt、doctest_的库名被跳过见 testPollutionPrefixes若查询失败或结果为空回退到静态列表DefaultDatabases [hq]。源码注释说明旧名gt/bd已因 GH#2385 移除因为现代 town 使用hq与 rig 专属库名保留旧名会导致“幻影数据库”错误。所有库名还会经过 ValidateDBName 的正则校验仅允许字母、数字、下划线、连字符^[a-zA-Z0-9_-]$防止库名注入。5. Step 3扫描每个数据库的候选项对 Step 2 返回的每个数据库执行gt reaper scan --dbname --port3307 \ --max-age24h --purge-age72h \ --mail-age72h --stale-age168h \ --jsonScan 只做统计、不修改任何数据其ScanResult的 JSON 字段比命令文档列出的更细reap_candidates符合关闭条件的 open Wisp 数molecule_step_candidatesomitempty父 Molecule 已关闭的 step-wisp 数这类 Wisp 走独立快速通道与reap_candidates互斥不重复计数purge_candidates超过 purge_age 的已关闭 Wisp 数mail_candidates带gt:message标签且关闭超过 mail_age 的邮件数stale_candidates符合自动关闭条件的陈旧 Issue 数open_wisps该库 open 状态open/hooked/in_progress的 Wisp 总数anomalies异常数组如dangling_parent_ref存在指向已清除/缺失父节点的 Wisp 依赖记录。命令文档的判定规则是若所有库的open_wisps合计超过3000记录并准备升级上报若所有库均无候选项报告 “nothing to reap” 并停止。3000 这个阈值不是随意取的。DefaultAlertThreshold 的注释 解释了调整缘由open Wisp 总数主要由健康的近期 Wisp 构成忙碌 town 观测稳态约 1966 条旧值 800 低于健康水位导致每次扫描都误报 HIGH提高到 3000 后告警才真正跟踪“失控增长”见 hq-57jr8。CLI 在多库汇总输出时也会检查该阈值并打印 WARNINGcmd/reaper.go。两个工程细节值得注意扫描前的 Schema 门禁每个库先经 HasReaperSchema 检查wisps、issues、wisp_dependencies三张表及相关列是否齐备缺失则跳过该库部分初始化的库很常见。性能优化reap 候选判定曾用 3 个逐行相关EXISTS子查询在 1800 已关闭 Wisp 时产生 O(n*m) 成本引发 CPU 尖峰与连接超时gt-wvd2/gt-jd1z。现在改为 parentExcludeJoin 的 LEFT JOIN 反连接模式子查询只跑一次再哈希连接复杂度降为 O(nm)。语义不变——“排除拥有 open 父节点的 Wisp”等价于“无父子依赖孤儿、父已 closed、父行缺失悬空引用”三类候选。6. Step 4收割过期 Wisp对存在 reap 候选的每个数据库执行gt reaper reap --dbname --port3307 --max-age24h [--dry-run] --json关键行为约定scan 与 reap 的数量不一致是正常的。在扫描与收割之间的窗口内witness 会并发关闭死亡 polecat 会话对应的 Wisp因此 reap 实际关闭数通常小于 scan 报告数。命令文档明确指示不要因为 scan reap 而升级上报只对真实错误升级。这一点在配方文件的 Anomaly Detection 一节中也被列为“NOT anomalies”措辞几乎一致。Reap 的资格判定与执行策略与 Scan 的计数语义严格对齐资格条件状态为open/hooked/in_progresscreated_at早于now - max_ageissue_type ! agentAgent 类 Wisp 具有持久身份永不收割且父节点已关闭/缺失step-wisp 快速通道父 Molecule 已closed的 step-wispissue_type ! agent不受 max_age 限制、立即关闭通过 closedMoleculeStepSubquery 单独识别并批量处理批量 UPDATE以DefaultBatchSize 100为一批“SELECT id ... LIMIT 100 → UPDATE ... WHERE id IN (...)”避免在大表上长时间持有写锁整体上下文超时放宽到 2 分钟Dolt 提交语义先SET autocommit 0批量 UPDATE 后必须显式COMMIT把改动刷入 Dolt working set——因为DOLT_COMMIT作用于 working set若不先 COMMIT 会看到 “nothing to commit”随后CALL DOLT_COMMIT(-Am, reaper: close N wisps in db)持久化。若提交报 “nothing to commit”working set 被还原到与 HEAD 一致时属预期情形则静默忽略其他错误以异常上报任何未提交路径都会ROLLBACK兜底。7. Step 5清除旧的已关闭 Wisp 与邮件对存在 purge 候选的每个数据库执行gt reaper purge --dbname --port3307 \ --purge-age72h --mail-age72h [--dry-run] --jsonPurge 是周期中唯一不可逆的操作分两个子过程清除已关闭 WisppurgeClosedWisps目标是status closed且closed_at早于now - purge_age的 Wisp。注意源码特意不做父节点检查——已过删除保留期的已关闭 Wisp 无条件可删早期的相关子查询检查正是 gt-wvd2 性能事故的来源。删除按 100 条一批进行每批依次清理辅助表wisp_labels、wisp_comments、wisp_events、wisp_dependencies再按主键删除主表行随后 batchDeleteRows 还会清理反向依赖引用wisp_dependencies.depends_on_wisp_id、dependencies.depends_on_wisp_id防止产生悬空的父引用。删除完成后同样走COMMIT→DOLT_COMMIT(--allow-empty, -Am, ...)持久化失败则记录dolt_commit_failed异常——这正是命令文档要求重点观察的异常类型出现它意味着被清除的数据可能没有持久化。清除旧邮件purgeOldMail邮件在 Dolt 中表现为带gt:message标签的 Issue 行条件为statusclosed且closed_at早于now - mail_age辅助清理labels/comments/events/dependencies表。若目标库根本没有issues/labels表beads 数据存放在独立 Dolt 实例上的部署形态按isTableNotFound判断优雅跳过而不是报错。8. Step 6自动关闭陈旧 Issue对存在 stale 候选的每个数据库执行gt reaper auto-close --dbname --port3307 \ --stale-age168h [--dry-run] --json命令文档给出的安全边界是“Auto-close从不触碰P0/P1 Issue、Epic 或存在活跃依赖的 Issue。”AutoClose 的 SQL 把这些边界落得更细只处理status IN (open,in_progress)且updated_at早于now - stale_age的 Issuepriority 1——即排除 P0/P1数字越小优先级越高issue_type NOT IN (epic,convoy)——Convoy 被排除有明确事故背景其生命周期由 tracked-bead 状态驱动gt convoy check/refinery post-mergetracks关系是非阻塞的依赖排除保护不了它若在 tracked 项仍 open 时按陈旧度关掉 convoy会把它从派发跟踪中孤立并引发重复派发hq-qouv/hq-shb1 事故见 hq-jnap 注释排除带gt:standing-orders、gt:keep、gt:role、gt:rig标签的 Issuestanding-order 类标签不应被陈旧度淘汰;双向依赖排除既排除“依赖 open/in_progress 目标”的 Issue也排除“被 open/in_progress Issue 依赖”的 Issue。实现上有两个值得注意的技术决策两步式 SELECT-then-UPDATEMySQL 不允许在UPDATE中对同一张表做自引用子查询Error 1093Dolt 在 dolthub/dolt#10600 下也不可靠因此先 SELECT 出候选 id 与标题、内存中构建ClosedEntry日志id、title、age_days、database再按 id 批量 UPDATE关闭留痕UPDATE 会写入close_reason stale:auto-closed by reaper便于事后审计区分人工关闭与自动关闭dry-run 模式则只输出closed_entries明细与closed计数不做任何修改。9. Step 7生成报告与异常升级周期收尾要求按固定格式输出汇总## Reaper Report **Databases scanned**: N **Wisps reaped**: N (stale open wisps closed) **Wisps purged**: N (old closed wisps deleted) **Mail purged**: N (old closed mail deleted) **Issues auto-closed**: N (stale issues past 168h) **Open wisps remaining**: N **Anomalies**: list or none若发现异常执行升级上报gt escalate Reaper anomalies detected -s MEDIUM -m anomaly details从 reaper.go 的Anomaly结构type/message/count看实际会出现的异常类型包括dangling_parent_refscan 阶段悬空父引用、sql_commit_failedSQL 事务未刷入 working set、dolt_commit_failedDolt 持久化失败。配方的 Anomaly Detection 一节 还补充了两类应当人工关注的信号reap 候选数突然激增暗示 Wisp 生命周期出问题、open Wisp 数突破 alert_threshold。10. 扩展视角gt reaper run与 daemon 巡逻如何复用同一套代码理解命令文档后再回看另外两条执行路径会清晰很多gt reaper runcmd/reaper.go一条命令串起 scan → reap → purge → auto-close → report 的完整内联周期输出与各子命令一致的汇总含[DRY RUN]前缀、closed-molecule steps 附加计数、open 超阈值的 WARNING。命令文档的 7 步流程本质上就是把gt reaper run拆成 Agent 可逐步审查的形式。daemon 巡逻daemon/wisp_reaper.goreapWisps()每小时被调度一次先把巡逻配置换算成配方变量max_age/purge_age/stale_issue_age/mail_delete_age/alert_threshold必要时附dry_run、databases倒出mol-dog-reapermolecule 用于可观测性跟踪然后经gt sling mol-dog-reaper deacon/dogs --var ...派发 Dog 执行配方派发失败才回退到reapWispsInline。内联回退在标准四步之外还有两条“快速通道”以 1 小时为年龄阈值调用 ClosePluginReceipts关闭type:plugin-run标签的插件运行回执和 ClosePluginDispatches关闭 daemon 派发给 Dog 的Plugin:前缀指令邮件——这两类一次性记录如果只等 7 天的 auto-close 才会堆积到数百条。配方比命令文档多的一个convoy-check步骤gt convoy check按 tracked-bead 状态而非陈旧度关闭已完成 convoy也只在 Dog/内联路径中执行命令文档的 7 步流程不包含它。11. 执行前提与操作要点小结环境前提Dolt 服务器可达默认127.0.0.1:3307可经GT_DOLT_HOST/GT_DOLT_PORT或 town 配置覆盖目标库具备wisps/issues/wisp_dependencies完整 schema建议顺序先--dry-run全量预览 → 确认候选计数合理 → 实跑purge 不可逆务必先核对purge_candidates多库场景--db可传逗号分隔的多个库名自动发现之外的显式列表库间默认间隔--db-delay 250ms以降低 Dolt 负载升级纪律Dolt 不健康时用-s HIGH阻断并上报scan/reap 计数不一致不升级真实错误与anomalies出现时用-s MEDIUM上报关键源码索引命令定义 .claude/commands/reaper.md、核心实现 internal/reaper/reaper.go、CLI 入口 internal/cmd/reaper.go、配方 internal/formula/formulas/mol-dog-reaper.formula.toml、daemon 巡逻 internal/daemon/wisp_reaper.go。【免费下载链接】gastownGas Town - multi-agent workspace manager项目地址: https://gitcode.com/GitHub_Trending/ga/gastown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价