一句话结论
BEST_MINDS_BOARD_* / BEST_MINDS_BOARD_PUBLISH_*;
执行侧先在临时 staging 上脱敏、补尾和扫泄露,再调用旧的 publish-board.mjs 真正部署。
- 代码当前默认值是
injectMode=minimal、enforceEnding=0、freezeLegacy=1、relatedRuntime=1、备份默认开启。 - 最近一串真实运行日志记录的是
injectMode=full、enforceEnding=true,现在已经可以归因到ship-prod.sh这类调用入口显式覆盖,而不是 wrapper 默认值自身漂移。 - “配置隔离”在 root 选择上已经收紧:当前代码只走
args.root → BEST_MINDS_BOARD_PRIVATE_ROOT → BEST_MINDS_BOARD_PRIVATE_CANONICAL_ROOT → 默认路径;但桥接阶段仍会主动回写 legacy 变量名给旧发布器。
当前可验证事实
[REDACTED_LOCAL_PATH]private-publish/latest.json + last-success.jsonhttps://board.zondev.top时序图 1 · 配置逻辑
时序图 2 · 执行逻辑
publish-board.mjs 完成;private wrapper 负责 staging 脱敏、门禁、回写和备份闭环。
理想 vs 现实 Gap
1. 控制面单一真源
- 理想:private skill 文档、private wrapper 默认值、生产调用入口三者口径一致。
- 现实:wrapper 默认仍是
minimal + enforceEnding=0,但生产入口7_AGENT/openclaw/web-ship/scripts/ship-prod.sh和7_AGENT/openclaw/topic-deploy/scripts/ship-prod.sh显式导出full + enforceEnding=1。 - Gap:控制面不是“一个真源”,而是“skill 文档 + wrapper 默认 + caller override”三层叠加。
2. 配置隔离
- 理想:私有链路只吃
BEST_MINDS_BOARD_PRIVATE_*,完全不碰 legacy 变量。 - 现实:root 选择已经不再读取
BEST_MINDS_BOARD_ROOT;但进入桥接后仍会把 private 解析结果重新映射为BEST_MINDS_BOARD_*和BEST_MINDS_BOARD_PUBLISH_*。 - Gap:入口层已经私有化,执行层仍是兼容化而非纯私有化。
3. 执行面独立性
- 理想:private publish 自己就是完整的数据面和发布面。
- 现实:真正上线仍靠
publish-board.mjs做 slim staging、Vercel deploy、inspect 和公开 URL 抽取。 - Gap:private wrapper 更像 orchestration shell,不是独立发布器。
4. 运行时可解释性
- 理想:看一次日志就能反推出“这次为什么是这个配置”。
- 现实:现在除了
private-publish/latest.json,成功态还会额外写last-success.json,并记录 live verify 结果;但“是谁覆盖了默认值”仍要翻.ship-logs。 - Gap:运行结果更清楚了,但 override provenance 仍然分散,排障链条还没完全收口。
关键观察
当前代码默认
root优先级:args.root → BEST_MINDS_BOARD_PRIVATE_ROOT → BEST_MINDS_BOARD_PRIVATE_CANONICAL_ROOT → 默认路径backupGit/backupPush/backupStrict默认都为开启injectMode=minimal,enforceEnding=0,freezeLegacy=1,relatedRuntime=1,liveVerify=1
生产模式参考运行
- 2026-03-14 一串 prod-pattern run 都显示:
injectMode=full、enforceEnding=true、backupPush=true - 2026-03-15 的推荐配置实跑则明确落成:
injectMode=minimal、enforceEnding=0、liveVerify=1 - 这说明“最近为什么看起来总是 full + strict”依然是 caller policy,不是 wrapper 默认值回弹
private 与 legacy 的边界
- private wrapper 在自身入口只读
BEST_MINDS_BOARD_PRIVATE_*与 canonical root - 一旦进入桥接阶段,它仍会主动把 private 解析结果写回老变量名,喂给
rebuild-board.mjs和publish-board.mjs - 所以它现在是“入口私有化,执行兼容化”,不是完全脱离 legacy
导致偏差的真实入口
7_AGENT/openclaw/web-ship/scripts/ship-prod.sh:显式导出BEST_MINDS_BOARD_PRIVATE_ENFORCE_ENDING=1与BEST_MINDS_BOARD_PRIVATE_INJECT_MODE=full7_AGENT/openclaw/topic-deploy/scripts/ship-prod.sh:同样显式导出这两个覆盖值- 所以最近一串
private-publish/history/*.json落成full + strict,是 caller policy,不是 wrapper 静态默认
这份说明针对 2026-03-15 当前代码和 2026-03-14 最近一次真实运行记录。最重要的结论不是“谁对谁错”,而是:
现在系统已经能跑,但控制面仍然不是单一真源。若你要,我下一步可以把这两张图继续扩成“异常分支图”,把
dry-run、allow-leaks、ending gate 失败、backup strict 失败 4 条分支单独画出来。
门禁补齐 · 四个原则视图
要点 1 · Root 隔离先于兼容
第一性原则是先把 root 入口锁死,再谈兼容 legacy。否则 private skill 的边界会被旧环境变量重新打穿。
要点 2 · Private wrapper 仍是桥,不是岛
它没有自带独立 deploy data plane,而是把 private 解析后的结果翻译给旧发布器去执行,这决定了它仍要和 legacy 共存。
要点 3 · 线上验收必须落在 deploy 之后
正确的收口不是“脚本退出 0 就算成功”,而是 deploy 完以后继续验证 CANONICAL_URL 和 LATEST_REPORT_URL 的真实 HTTP 状态。
要点 4 · latest 与 last-success 要分开
失败态覆盖 latest.json 是合理的,但成功态必须单独保留,否则排障时会把“最后一次运行”和“最后一次成功”混成一个概念。