v26.9.15 to v26.9.0

1 added, 1 removed. Audit A to A.

---
name: jwb-cli-contract
description: Use when 设计、新增或审查 jobws 命令行命令时,需要遵守本工作台既有的 CLI 契约(退出码三态、两段式写入、stdout/stderr 纪律、默认行为兼容)。English triggers:CLI design, command contract, clig.dev, exit codes, two-phase write, breaking change.
compatibility: jobws 指仓库内的 python tools/jobws.py(在仓库根运行);面向「开发 / 扩展本仓库」的场景;Python 3.12+。
license: MIT
metadata:
- version: 26.9.15
+ version: 26.9.0
---
# jobws CLI 契约(新增命令时照此办)
外部参考:clig.dev 的原则。本文件是**本仓库已落地的口径**——与代码及其测试冲突时,
以代码为准,并回来更新本文件。
## 退出码(三态,不可挪用)
| 码 | 含义 |
|---|---|
| 0 | 成功(只读命令即使结果为空也返回 0) |
| 1 | 业务失败(校验不过、令牌不可用、冲突……) |
| 2 | 用法或配置错误(参数不对、工作区不可用、旧入口迁移提示) |
## 写入必须是两段式(硬闸门)
- 写类命令默认直接执行,但必须提供 `--preview`:只校验、只给差异表与一次性令牌;
- 落盘统一走 `jobws apply <令牌>`——**不**在原命令里加 `--yes` 之类跳过确认的口;
- 令牌:一次性(apply 先取走再执行)、默认 10 分钟、绑定工作区与载荷指纹;
- 预览阶段不碰工作区一个字节(测试按文件字节断言);
- 新增写入口时:在协议层注册表登记「操作名 → 落盘函数」,并同步 CLI / MCP /
网页端三面——只改一面等于三面口径漂移。
## stdout / stderr 纪律
- stdout 只放结果(表格、令牌、记录 id);诊断与进度走 stderr;
- **stdio MCP 场景下 stdout 是协议通道**——任何调试 print 都可能破坏会话;
- 机器可读的关键行(如令牌)保持固定格式,人可读提示与它分行。
## 默认行为与兼容
- 新增能力用**新增分支**承载(如 `--preview`);旧路径默认行为不变——这是本仓库
对「非破坏性」的默认防线;改名级别的大迁移单独开版本讲清迁移步骤;
- 参数名、子命令、退出码一经发布即契约;要改按破坏性流程走(Release 给迁移步骤)。
## 帮助与发现
- `jobws --help` 列全部命令;`jobws <cmd> --help` 显示子命令与参数——新增命令后
两处都要对(入口里 `add_help=False` 的转发模式已固化);
- 旧脚本被直接运行时必须给迁移提示(exit 2),不静默退出、也不留旧别名。
## 常用约定
- `--workspace` 在多个命令里是**顶层选项**:写在子命令之后会被判 unrecognized;
- 参数沿用既有风格(长选项、连字符分隔);一次任务只做一件事;
- 错误信息写「怎么办」而不只写「哪里错」,涉及的命令要可直接复制执行。
## 常见错误
| 错误 | 后果 | 正确做法 |
|---|---|---|
| 写命令没有预览入口 | 用户对自己的数据失去确认权 | 加 `--preview`,走令牌 |
| 从 stdout 打调试日志 | stdio MCP 会话被污染 | 日志走 stderr |
| 改了默认输出格式 | 既有脚本解析失败 | 格式变更按破坏性流程 |
| 只改 CLI 面漏掉 MCP / 网页端 | 三面口径漂移 | 一处登记、三面同步 |
| 新增命令后忘更新帮助 | 用户找不到入口 | 跑一次 `--help` 对账 |