Gas Town dolt-archive 插件实战:基于 JSONL + Git + Dolt 推送的三层离站数据备份方案
Gas Town dolt-archive 插件实战基于 JSONL Git Dolt 推送的三层离站数据备份方案【免费下载链接】gastownGas Town - multi-agent workspace manager项目地址: https://gitcode.com/GitHub_Trending/ga/gastown导读dolt-archive是 Gas Townmulti-agent workspace manager中负责将生产数据带离本机的数据安全类插件它先为每个生产数据库导出人类可读、可 diff 的 JSONL 快照再将其提交并推送到 GitHub 备份仓库最后通过dolt push把数据库本体复制到 GitHub/DoltHub 远端。读完本文你将掌握该插件的四步归档流程、全部配置变量与命令行参数、run.sh脚本的具体实现细节以及如何将其接入 Gas Town 的插件调度体系gate 冷却、运行记录、失败升级来构建可验证的离站备份链路。插件定位为什么需要三层离站备份Gas Town 以 Dolt 作为唯一存储后端详见 dolt-storage.md一个 Dolt SQL server 通过 MySQL 协议在 3307 端口服务所有数据库数据目录位于~/gt/.dolt-data/其中hq/town 级 beads、gastown/rig beadsgt-*前缀等都是生产库。Dolt 本身提供 Git 式版本能力但本地仓库损坏、机器丢失、误删后提交图仍保留等场景都需要把数据复制到另一台机器上。dolt-archive的答案是把备份拆成三层逐层加固见 plugin.md 顶部描述JSONL 导出—— 人类可读的快照不依赖任何存储后端是最末端的恢复层文档注明在 Clown Show #13 事故中正是靠它救回数据Git push—— 将 JSONL 文件提交进备份 Git 仓库并推送到 GitHubDolt push—— 若配置了远端用 Dolt 原生复制能力把整个数据库推到 GitHub/DoltHub。设计上的硬性约束是JSONL 是最后手段的恢复层无论其他两层是否工作都必须持续维护。这与 dolt-storage.md 中Ledger 平面由 JSONL 导出 → git push 到 GitHub 提供持久记录的定位完全一致。插件采用plugin.mdTOML frontmatter 说明正文run.sh确定性脚本的组合plugin.md中的 frontmatter 定义调度与追踪元数据正文描述三层备份策略run.sh是实际执行体不依赖 AI 解释即可运行。元数据解剖gate 与 tracking 配置 name dolt-archive description Offsite backup: JSONL snapshots to git, dolt push to GitHub/DoltHub version 1 [gate] type cooldown duration 1h [tracking] labels [plugin:dolt-archive, category:data-safety] digest true [execution] timeout 15m notify_on_failure true severity critical 对照 internal/plugin/types.go 中定义的插件 schema[gate] type cooldownduration 1h表示冷却门查询账本上该插件的运行 wisp若一小时内没有运行过则放行gate 类型还有cron/condition/event/manual见 plugin-system.md 的 Gate Types 表[tracking] labels每次运行生成的 wisp 会带上plugin:dolt-archive、category:data-safety标签供后续检索、计数与失败率统计digest true运行 wisp 纳入每日 digest 汇总[execution] timeout 15m单次执行上限 15 分钟notify_on_failure trueseverity critical失败时按 critical 级别升级告警。对比同目录下的 dolt-backup/plugin.md它做的是本机文件系统备份dolt backup sync15 分钟冷却、severityhigh而 dolt-archive 专注离站复制两者互补。dolt-backup 的run.sh中先比对 HEAD hash 跳过未变库、失败才升级的做法也可作为理解 dolt-archive 计数逻辑的参照。配置变量总览plugin.md给出的核心配置如下DOLT_DATA_DIR$GT_TOWN_ROOT/.dolt-data PROD_DBS(hq gt mo) JSONL_EXPORT_DIR$GT_TOWN_ROOT/.dolt-archive/jsonl DOLT_HOST${GT_DOLT_HOST:-127.0.0.1} DOLT_PORT${GT_DOLT_PORT:-3307} DOLT_USERroot对照 run.sh 的实际默认值与语义变量默认值说明DOLT_HOST${GT_DOLT_HOST:-${DOLT_HOST:-127.0.0.1}}Dolt server 主机Gas Town 通过GT_DOLT_HOST统一注入见 dolt-storage.md 环境变量表gt 会把GT_DOLT_HOST翻译为BEADS_DOLT_SERVER_HOST传给子进程DOLT_PORT${GT_DOLT_PORT:-${DOLT_PORT:-3307}}端口Gas Town 默认 3307DOLT_USERroot无密码连接DOLT_DATA_DIR$HOME/gt/.dolt-data各数据库目录的父目录每个子目录对应一个库JSONL_EXPORT_DIR$HOME/gt/.dolt-archive/jsonlJSONL 快照输出目录BACKUP_REPO$HOME/gt/.dolt-archive/gitGit 备份仓库PROD_DBS自动发现未显式指定时通过SHOW DATABASES自动发现并排除系统库与测试库information_schema、mysql、dolt_cluster、testdb_、beads_t、beads_pt、doctest_run.sh 支持三个命令行参数--help可查看完整用法./run.sh # 默认自动发现库执行全流程 ./run.sh --databases hq,gt # 只归档指定库逗号分隔 ./run.sh --skip-git # 跳过 Git push 步骤 ./run.sh --skip-dolt-push # 跳过 Dolt 原生推送注意run.sh中DOLT_DATA_DIR默认$HOME/gt/.dolt-data与 plugin.md 中$GT_TOWN_ROOT/.dolt-data的差异脚本层面默认指向~/gt若 daemon 以GT_TOWN_ROOT启动参考 dolt-backup/run.sh 的注释非~/gt根目录的 town 曾因此报 No databases found应以环境变量覆盖为准。Step 1JSONL 导出最后手段恢复层这是整个链路中唯一不可失败的一步。流程为为每个生产库生成带时间戳的快照文件、更新-latest.jsonl符号链接、按库保留最近 24 份快照并清理更旧的。主路径bd exportplugin.md 版本plugin.md 中的导出脚本以bd export为主路径mkdir -p $JSONL_EXPORT_DIR for DB in ${PROD_DBS[]}; do EXPORT_FILE$JSONL_EXPORT_DIR/${DB}-$(date %Y%m%d-%H%M).jsonl LATEST_LINK$JSONL_EXPORT_DIR/${DB}-latest.jsonl echo Exporting $DB... # Use bd export if available, otherwise query directly if bd export --db $DB --format jsonl $EXPORT_FILE 2/dev/null; then LINE_COUNT$(wc -l $EXPORT_FILE | tr -d ) FILE_SIZE$(du -h $EXPORT_FILE | cut -f1) echo $DB: $LINE_COUNT issues exported ($FILE_SIZE) # Update latest symlink ln -sf $EXPORT_FILE $LATEST_LINK EXPORTED$((EXPORTED 1)) else # Fallback: query Dolt directly for issue data dolt sql -q SELECT * FROM issues ORDER BY id \ --host $DOLT_HOST --port $DOLT_PORT -u $DOLT_USER \ -d $DB --no-auto-commit --result-format json \ $EXPORT_FILE 2/dev/null ... fi done关键点快照文件按${DB}-%Y%m%d-%H%M命名天然可排序、可 diff每个库维护一个-latest.jsonl符号链接指向最新快照供后续 Git push 步骤直接读取导出的行数、文件大小会被打印方便核对导出是否完整导出失败时打印 WARN 并删除残缺文件计入EXPORT_FAILED。生产实现Dolt SQL 直查run.sh 版本实际的 run.sh 更保守也更可靠它不依赖bd export而是先检查该库是否有issues表没有就跳过例如 gastown 配置库再直接用 Dolt SQL 导出# Skip databases without an issues table (e.g. gastown config DB) if ! dolt_query $DB SHOW TABLES LIKE issues 2/dev/null | grep -q issues; then log $DB: skipped (no issues table) continue fi # Export via Dolt SQL (reliable for all databases with an issues table) if dolt_query_json $DB SELECT * FROM issues ORDER BY id $EXPORT_FILE 2/dev/null [[ -s $EXPORT_FILE ]]; then LINE_COUNT$(wc -l $EXPORT_FILE | tr -d ) log $DB: exported via SQL ($LINE_COUNT lines) ln -sf $(basename $EXPORT_FILE) $LATEST_LINK EXPORTED$((EXPORTED 1)) else log WARN: $DB export failed rm -f $EXPORT_FILE EXPORT_FAILED$((EXPORT_FAILED 1)) EXPORT_ERRORS${EXPORT_ERRORS}${DB} fi脚本中的两个 SQL 助手封装了连接参数dolt_query以 CSV 格式执行查询tail -n 2去掉表头、tr -d \r去掉回车dolt_query_json以 JSON 格式执行查询用于导出所有 stderr 都重定向到临时日志文件mktemp /tmp/dolt-archive-stderr.XXXXXXEXIT trap 清理保证脚本自身输出干净、可被 dog 直接采集。--use-db $DB指定目标库--no-tls -p 对应无密码的 root 连接约定参见 dolt-storage.md 的 Connection 说明。导出的内容是issues表全量数据——这正是 Gas Town 的通用 bead 表任务、消息、agent、门禁等都以 issues 行承载schema 见 dolt-storage.md 的CREATE TABLE issues。由于快照是整表快照而非增量JSONL 恢复时可以直接重建全部行这也是它作为最后手段恢复层的关键属性。快照裁剪每库保留 24 份for DB in ${PROD_DBS[]}; do SNAPSHOTS$(ls -t $JSONL_EXPORT_DIR/${DB}-2*.jsonl 2/dev/null | tail -n 25) if [ -n $SNAPSHOTS ]; then echo $SNAPSHOTS | xargs rm -f echo Pruned old $DB snapshots fi donels -t按时间倒序排列tail -n 25取出第 25 份及更旧的快照并删除——即每个库保留最近 24 份约一天两次导出的话可覆盖两周。配合 1 小时冷却 gate24 份意味着至少保留一天的全部归档记录为恢复提供多个可回退时间点。Step 2Git commit 与 pushGitHub 备份仓库第二步把最新 JSONL 快照复制进本地备份 Git 仓库提交后推送到 GitHub。先决条件是存在备份仓库$HOME/gt/.dolt-archive/git且已配置origin远端BACKUP_REPO$HOME/gt/.dolt-archive/git if [ -d $BACKUP_REPO/.git ]; then cd $BACKUP_REPO # Copy latest JSONL files for DB in ${PROD_DBS[]}; do LATEST$JSONL_EXPORT_DIR/${DB}-latest.jsonl if [ -f $LATEST ]; then cp $(readlink $LATEST || echo $LATEST) $BACKUP_REPO/${DB}.jsonl fi done # Check for changes if git diff --quiet git diff --staged --quiet; then echo No changes to commit else git add *.jsonl git commit -m Archive snapshot $(date %Y-%m-%d-%H%M) \ --authorGas Town Archive archivegastown.local 2/dev/null # Check if remote exists before pushing if git remote get-url origin /dev/null 21; then if git push origin main 2/dev/null; then GIT_PUSHEDtrue echo Pushed to GitHub else echo WARN: Git push to remote failed (check GitHub credentials/permissions) fi else echo WARN: No git remote configured for backup repo echo To set up: cd $BACKUP_REPO git remote add origin github-url fi fi else echo No git backup repo at $BACKUP_REPO — skipping git push echo To set up: git init $BACKUP_REPO cd $BACKUP_REPO git remote add origin url fi几个值得注意的实现细节通过readlink解析-latest.jsonl符号链接拿到真实快照文件再复制避免把符号链接本身提交进仓库提交前用git diff --quiet git diff --staged --quiet判断是否有变化无变化则跳过避免生成空提交提交作者固定为Gas Town Archive archivegastown.local保证备份历史来源可辨识远端不存在或推送失败都只是 WARN 降级不阻断后续步骤——因为 JSONL 已经在本机留存Git 层只是第二道防线run.sh 版本通过--skip-git参数可整体跳过本步git push origin main失败时不再输出额外的凭证提示行为更安静。若仓库尚未初始化文档给出了两种自举方式git init $BACKUP_REPO后配置远端或在已有仓库中git remote add origin url。Step 3Dolt 原生推送GitHub/DoltHub 远端第三步对每个生产库执行dolt push把数据库本体含完整提交历史复制到 GitHub 或 DoltHub 远端。核心逻辑是跳过没有.dolt目录的库、跳过未配置远端dolt remote -v为空的库然后对每个远端名逐个推送每个远端限时 120 秒for DB in ${PROD_DBS[]}; do DB_DIR$DOLT_DATA_DIR/$DB if [ ! -d $DB_DIR/.dolt ]; then echo $DB: no .dolt directory, skipping continue fi REMOTES$(cd $DB_DIR dolt remote -v 2/dev/null | grep -v ^$ | head -5) if [ -z $REMOTES ]; then echo $DB: no remotes configured, skipping dolt push continue fi echo $DB: pushing to remotes... cd $DB_DIR for REMOTE_NAME in $(dolt remote -v 2/dev/null | awk {print $1} | sort -u); do if timeout 120 dolt push $REMOTE_NAME main 2/dev/null; then echo $REMOTE_NAME: pushed DOLT_PUSHED$((DOLT_PUSHED 1)) else echo $REMOTE_NAME: FAILED DOLT_PUSH_FAILED$((DOLT_PUSH_FAILED 1)) fi done done要点远端列表通过awk {print $1} | sort -u提取远端名并去重一个库可配置多个远端例如同时推 GitHub 与 DoltHubtimeout 120防止某个远端卡死拖垮整个归档周期一个远端失败只计数、继续推其余远端符合尽量多复制一份的容错思路与 dolt-storage.md 的 Remote Push 章节呼应Gas Town 使用 git 协议远端gitssh://gitgithub.com/...这类远端有 git-remote-cache 缓存开销且比 DoltHub 原生协议慢DoltHub 原生远端属于规划中Wasteland commons 方向。若本地与远端历史已分叉例如灾后恢复场景需要先gt dolt sync --force覆盖远端见 dolt.go 的命令帮助gt dolt sync会停服后推送再重启--force用于首次强制推送。Step 4远端可访问性验证归档不能推出去就算完第四步从远端角度验证数据确实到达且可读。验证分两条线Git 备份仓库验证先git ls-remote origin HEAD确认远端可达再浅克隆到临时目录逐库核对 JSONL 文件存在并统计行数if [ -d $BACKUP_REPO/.git ]; then echo Verifying git remote... if cd $BACKUP_REPO git ls-remote origin HEAD /dev/null 21; then TEMP_CLONE$(mktemp -d) if git clone --depth 1 origin $TEMP_CLONE 2/dev/null; then for DB in ${PROD_DBS[]}; do if [ -f $TEMP_CLONE/${DB}.jsonl ]; then REMOTE_COUNT$(wc -l $TEMP_CLONE/${DB}.jsonl | tr -d ) echo git: $DB verified ($REMOTE_COUNT lines in remote) VERIFY_PASSED$((VERIFY_PASSED 1)) else echo git: $DB MISSING from remote VERIFY_FAILED$((VERIFY_FAILED 1)) fi done else echo git: Clone verification failed VERIFY_FAILED$((VERIFY_FAILED 1)) fi rm -rf $TEMP_CLONE ...Dolt 远端验证对每个配置了远端的库尝试读取dolt log REMOTE/main -n 1——只要有一个远端能读到 main 分支的提交记录即认为该库验证通过for REMOTE in $REMOTE_HEADS; do if dolt log $REMOTE/main -n 1 /dev/null 21; then echo dolt: $DB on $REMOTE verified VERIFY_PASSED$((VERIFY_PASSED 1)) break fi done验证的意义在于远端可达 ≠ 数据到达。git ls-remote 浅克隆 行数核对能发现推送成功但文件缺失/为空的静默失败dolt log remote/main能发现远端无提交记录的情况。最终输出Verified: N passed, M failed汇总。结果记录与失败升级归档周期结束后脚本汇总四步的计数并写入账本ledgerSUMMARYArchive: jsonl$EXPORTED/$((EXPORTED EXPORT_FAILED)), git${GIT_PUSHED}, dolt_push$DOLT_PUSHED/$((DOLT_PUSHED DOLT_PUSH_FAILED)), verify$VERIFY_PASSED/$((VERIFY_PASSED VERIFY_FAILED)) echo $SUMMARY RESULTsuccess if [ $EXPORT_FAILED -gt 0 ] || [ $DOLT_PUSH_FAILED -gt 0 ] || [ $VERIFY_FAILED -gt 0 ]; then RESULTwarning fi gt plugin record-run --plugin dolt-archive --result $RESULT \ --title $SUMMARY --description $SUMMARY /dev/null 21 || true结果判定规则值得注意只要 JSONL 导出、Dolt 推送、远端验证任一环节有失败计数整体结果即为warningGit push 失败GIT_PUSHEDfalse不计入warning 判定——因为 JSONL 快照本身仍在本机这是对JSONL 是最后手段恢复层定位的贯彻gt plugin record-run写入的运行 wisp 带plugin:dolt-archive标签冷却 gate 正是靠查询这类 wisp 判断是否放行参见 plugin-system.md 的 wisp 状态查询方式run.sh 版本在record-run失败时用|| true容忍避免记录环节影响归档本身。当 JSONL 导出失败时脚本升级告警并强调其不可替代性if [ $EXPORT_FAILED -gt 0 ]; then gt escalate JSONL export failed for $EXPORT_FAILED databases \ --severity critical \ --reason JSONL is our last-resort recovery layer. $EXPORT_FAILED databases failed to export. firun.sh 版本在此基础上补充了失败库名单$EXPORT_ERRORS帮助值班者快速定位同时只有EXPORT_FAILED 0或DOLT_PUSH_FAILED 0才置为 warning——因为 Git 层失败已被判定为可容忍。与 Gas Town 插件体系的对接dolt-archive 遵循 Gas Town 标准插件格式详见 plugin-system.md 与 internal/plugin/scanner.go发现放在 town 级~/gt/plugins/下即被全局扫描若某 rig 有同名插件则 rig 级覆盖 town 级DiscoverAll()按 name 去重执行方式scanner 发现 plugin.md 旁存在 run.sh 时会置HasRunScript truedaemon 或gt dog dispatch通过FormatMailBody()见 internal/plugin/types.go生成指令时会要求 dog直接执行bash run.sh而非让 AI 解释 markdown 正文——这正是确定性脚本、可复制、可审计的保障调度cooldowngate 保证 1 小时内最多跑一次执行超时 15 分钟由[execution] timeout约束可观测每次运行以 wisp 形式落账digest true使其纳入每日摘要category:data-safety标签让同类备份插件dolt-backup、dolt-snapshots可被统一检索。恢复视角这些层各能救什么备份层内容恢复粒度依赖JSONL 快照issues 表全量数据含时间戳多版本行级重建可回退到任一份快照仅需 dolt/bd 客户端 快照文件不依赖任何后端Git 备份仓库JSONL 文件的历史提交文件级可 diff 任意两次归档GitHub 远端可达性Dolt 远端完整数据库含提交历史库级还原远端配置 dolt push成功JSONL 层最能体现离站价值它不依赖 Dolt 服务器、不依赖 Git 远端只要归档目录在另一台机器上或 Git 仓库被拉到另一台机器灾后就能重建数据。这也是文档反复强调Always maintain it regardless of whether the other layers work的原因。而 Dolt 层则额外保留了全部提交历史支持dolt_diff()、AS OF等时间旅行查询见 dolt-storage.md 的 Dolt-Specific Capabilities 表适合需要审计与回滚的深度恢复。部署与运行建议综合 plugin.md 与 run.sh 的实现落地时建议按以下顺序检查确认 Dolt server 就绪gt dolt status应列出所有生产库连接参数可用GT_DOLT_HOST/GT_DOLT_PORT覆盖默认 127.0.0.1:3307初始化 Git 备份仓库一次性git init $HOME/gt/.dolt-archive/git并配置origin否则 Step 2 会静默跳过为每个库配置 Dolt 远端一次性cd $DOLT_DATA_DIR/db dolt remote add origin url否则 Step 3 会跳过该库先干跑验证bash run.sh --skip-git --skip-dolt-push只导出 JSONL检查快照行数与-latest.jsonl链接全量运行并核对 SUMMARYbash run.sh观察jsonl...、gittrue/false、dolt_push...、verify...四项计数任一非零失败都应处理确认自动调度生效插件位于 town/rig 的plugins/目录后由 Deacon 巡逻周期扫描、冷却 gate 限频、失败按severity critical升级。参考链接插件定义与四步流程确定性执行脚本 run.shDolt 存储架构数据目录、连接、远端推送与生命周期插件系统设计frontmatter schema、gate 类型、wisp 状态插件扫描与解析实现scanner.go插件类型定义Gate/Tracking/Execution schemagt dolt sync 命令帮助同族备份插件dolt-backup本机文件系统备份同族备份插件dolt-snapshotsconvoy 边界打标签【免费下载链接】gastownGas Town - multi-agent workspace manager项目地址: https://gitcode.com/GitHub_Trending/ga/gastown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考