@fatecannotbealtered-/jira-cli 1.0.6 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,641 @@
1
+ # 面向 Agent 的 CLI 工具设计规范
2
+
3
+
4
+ 本文定义本仓库 CLI 在被 AI Agent 调用时必须遵守的机器契约。目标是让 Agent 能稳定调用、可靠解析、可恢复重试,并避免任何非交互场景下的阻塞或误写。
5
+
6
+ ## 1. 核心铁律
7
+
8
+ 1. stdout 是契约:默认输出单个合法 JSON 文档,禁止混入日志、进度、提示、颜色控制符。
9
+ 2. stderr 是旁路:进度、警告、调试、错误说明全部写 stderr。
10
+ 3. 机器优先:默认 `--format json`;`text` 仅供人读;`raw` 仅用于裸字节、日志、diff 等原样透传。
11
+ 4. 非交互安全:写操作不得等待键盘输入,必须使用 `--dry-run` + `--confirm <token>`。
12
+ 5. 确定性:相同输入产生相同结构输出;字段名、字段顺序、schema 版本保持稳定。
13
+ 6. 最小惊扰:查询不改变状态;写操作在缺少有效 confirm token 时必须失败而不是继续执行。
14
+ 7. 可恢复:错误码、exit code、`retryable` 必须足够稳定,让 Agent 能决定是否重试、回退或请求用户介入。
15
+
16
+ ## 2. 全局参数
17
+
18
+ | 参数 | 说明 |
19
+ |--------------------------|--------------------------------|
20
+ | `--format json/text/raw` | 输出格式,默认 `json` |
21
+ | `--json` | `--format json` 的兼容别名,不推荐新调用使用 |
22
+ | `--fields <a,b,c>` | 仅返回指定字段,降低 token(查询命令) |
23
+ | `--compact` | 紧凑 JSON 输出,去除冗余空白(查询命令) |
24
+ | `--dry-run` | 模拟写操作,返回变更预览与 `confirm_token` |
25
+ | `--confirm <token>` | 携带 dry-run 返回的 token 真正执行写操作 |
26
+ | `--quiet` | 抑制 stderr 上的进度/提示,不抑制错误 |
27
+
28
+ `update` 命令可以按工具增加 `--target-version` 或 `--channel` 等参数,但必须保留统一生命周期参数:`--check`、`--dry-run`、`--confirm <token>`。
29
+
30
+ 格式职责:
31
+
32
+ - `json`:结构化机器输出,默认格式,也是唯一推荐给 Agent 的格式。
33
+ - `text`:人类可读,可以变化,禁止程序解析。
34
+ - `raw`:未包装 bytes / log / diff,原样透传,不使用 JSON envelope。
35
+
36
+ ## 3. 统一输出 Envelope
37
+
38
+ 成功与失败使用同形结构。Agent 只需要先判断 `ok`。
39
+
40
+ 成功:
41
+
42
+ ```json
43
+ {
44
+ "ok": true,
45
+ "schema_version": "1.0",
46
+ "data": {},
47
+ "meta": {
48
+ "duration_ms": 0
49
+ }
50
+ }
51
+ ```
52
+
53
+ 失败:
54
+
55
+ ```json
56
+ {
57
+ "ok": false,
58
+ "schema_version": "1.0",
59
+ "error": {
60
+ "code": "E_NOT_FOUND",
61
+ "message": "human readable message",
62
+ "details": {},
63
+ "retryable": false
64
+ },
65
+ "meta": {
66
+ "duration_ms": 0
67
+ }
68
+ }
69
+ ```
70
+
71
+ 约定:
72
+
73
+ - 所有 JSON 响应必须包含 `ok` 与 `schema_version`。
74
+ - `data` 始终是命令的业务载荷;不要把业务字段提升到 envelope 顶层。
75
+ - `error.code` 使用稳定的语义化枚举,统一以 `E_` 开头。
76
+ - `error.message` 给人读,Agent 不应解析。
77
+ - `error.details` 放结构化上下文,必须脱敏。
78
+ - `error.retryable` 决定 Agent 是否可以自动退避重试。
79
+ - `meta.duration_ms` 记录命令执行耗时。
80
+ - 破坏性 schema 变更必须升级 `schema_version` 主版本。
81
+
82
+ ## 4. stdout / stderr 规则
83
+
84
+ - stdout 在 `json` 模式下只能出现一个 JSON 文档,或在明确流式命令中输出 NDJSON。
85
+ - stderr 可输出进度、警告、诊断。
86
+ - `json` 模式下出错时,失败 envelope 就是 stdout 上那个唯一的 JSON 文档——Agent 永远解析 stdout 并检查 `ok`,不从 stderr 抓取;stderr 可以补充人类可读的错误说明。
87
+ - `--quiet` 只能抑制 stderr 上的非错误信息。
88
+ - 不允许在 JSON stdout 前后打印 banner、提示语、进度条或颜色码。
89
+ - stdout / stderr 一律 **UTF-8 编码,不带 BOM**,换行用 `\n`,确保跨平台(尤其 Windows)Agent 可稳定解析。
90
+
91
+ ## 5. 流式输出(NDJSON)
92
+
93
+ 大输出、日志流、订阅流、批量逐项结果使用 NDJSON。每行必须是独立合法 JSON,便于流式消费、降内存、可中断:
94
+
95
+ ```jsonl
96
+ {"ok":true,"schema_version":"1.0","type":"item","data":{}}
97
+ {"ok":true,"schema_version":"1.0","type":"item","data":{}}
98
+ {"ok":true,"schema_version":"1.0","type":"summary","data":{"count":2}}
99
+ ```
100
+
101
+ 约定:
102
+
103
+ - 普通查询默认使用单 JSON envelope。
104
+ - 只有命令语义明确是 log / stream / subscribe / 批量流式输出时才使用 NDJSON。
105
+ - NDJSON 行必须包含 `ok`、`schema_version`、`type`。
106
+ - 结束行建议使用 `type: "summary"`。
107
+ - 真正的二进制或纯文本透传走 `--format raw`,不要包成巨型单 JSON。
108
+
109
+ ## 6. Exit Code 语义表
110
+
111
+ | Code | 含义 | Agent 行为 |
112
+ |------|--------------------|------------------------|
113
+ | 0 | 成功 | 继续 |
114
+ | 1 | 通用错误 | 读取 error envelope 判断 |
115
+ | 2 | 参数/用法错误 | 不重试,修正参数 |
116
+ | 3 | 资源不存在 | 不重试 |
117
+ | 4 | 权限/认证/配置失败 | 不重试,提示凭证或权限 |
118
+ | 5 | 需确认但缺少 token | 走 dry-run 获取 token 后重试 |
119
+ | 6 | 前置条件冲突或 token 失效 | 重新读取状态后重试 |
120
+ | 7 | 可重试瞬时错误(网络/限流/服务端) | 退避后重试 |
121
+ | 8 | 超时 | 退避后重试 |
122
+ | 9 | 需人工介入(见 §15.3,可选) | 转述给用户,待其完成后跑 `resume` |
123
+
124
+ 错误码与 exit code 必须一致:
125
+
126
+ - `E_USAGE` / `E_VALIDATION` -> 2
127
+ - `E_NOT_FOUND` -> 3
128
+ - `E_AUTH` / `E_FORBIDDEN` / `E_CONFIG` -> 4
129
+ - `E_CONFIRMATION_REQUIRED` -> 5
130
+ - `E_CONFLICT` -> 6
131
+ - `E_NETWORK` / `E_RATE_LIMITED` / `E_SERVER` -> 7
132
+ - `E_TIMEOUT` -> 8
133
+ - `E_HUMAN_REQUIRED` -> 9(可选,仅启用 §15.3 时)
134
+
135
+ ## 7. 写操作流程(dry-run -> confirm)
136
+
137
+ 写命令第一步必须支持 `--dry-run`,返回预览与 token:
138
+
139
+ ```json
140
+ {
141
+ "ok": true,
142
+ "schema_version": "1.0",
143
+ "data": {
144
+ "preview": {
145
+ "changes": [
146
+ {
147
+ "action": "delete",
148
+ "resource": "mail",
149
+ "id": "123",
150
+ "before": {},
151
+ "after": null
152
+ }
153
+ ]
154
+ },
155
+ "confirm_token": "ct_9f2a...",
156
+ "expires_at": "2026-06-05T12:00:00Z"
157
+ },
158
+ "meta": {
159
+ "duration_ms": 0
160
+ }
161
+ }
162
+ ```
163
+
164
+ 第二步携带 token 执行:
165
+
166
+ ```bash
167
+ tool resource delete --id 123 --confirm ct_9f2a...
168
+ ```
169
+
170
+ confirm token 约定:
171
+
172
+ - token 必须绑定操作内容哈希,包括命令路径、参数、目标资源 ID、调用账号、权限上下文。
173
+ - 哈希必须用机器本地密钥做 HMAC(如 `~/.<tool>/confirm.secret`,首次使用时生成,权限 `0600`),使 token 无法通过重算公开哈希凭空铸造——它只能来自同一台机器上一次真实的 `--dry-run`。
174
+ - 能获取资源版本时,也应绑定资源版本、etag、changekey 或 updated_at,防止状态漂移。
175
+ - token 必须有过期时间,`expires_at` 使用 ISO 8601 UTC。
176
+ - token 过期、操作参数变化、目标状态变化时,执行命令返回 `E_CONFLICT`,exit code 6。
177
+ - 缺少 token 时返回 `E_CONFIRMATION_REQUIRED`,exit code 5。
178
+ - dry-run 不得产生外部副作用,但可以读取状态用于构造 preview。
179
+
180
+ ## 8. 查询、分页与字段选择
181
+
182
+ 查询命令默认支持:
183
+
184
+ - `--fields <a,b,c>`:只返回指定字段,支持 dotted path 时需在 reference 中声明。
185
+ - `--compact`:压缩 JSON 空白。
186
+ - `--limit`:限制返回条数。
187
+ - `--cursor` 或 `--offset`:分页游标或偏移。
188
+
189
+ 分页返回建议:
190
+
191
+ ```json
192
+ {
193
+ "items": [],
194
+ "count": 0,
195
+ "next_cursor": null,
196
+ "has_more": false
197
+ }
198
+ ```
199
+
200
+ 约定:
201
+
202
+ - 所有 ID 使用字符串,即使底层是数字。
203
+ - 所有时间使用 ISO 8601 UTC。
204
+ - 列表顺序必须稳定;默认排序规则应在 reference 中声明。
205
+ - 查询命令不得因为缺少可选过滤条件而进入交互询问。
206
+
207
+ ## 9. 幂等性与并发安全
208
+
209
+ 写命令应尽量支持幂等语义:
210
+
211
+ - 创建类命令建议支持 `--request-id` 或 `--idempotency-key`。
212
+ - 重试同一个 idempotency key 不应重复创建资源。
213
+ - 更新/删除类命令应在 dry-run 中记录目标资源版本。
214
+ - confirm 时发现版本变化必须返回 `E_CONFLICT`。
215
+ - 批量写操作应返回逐项结果,不要因为单项失败隐藏其他项状态。
216
+
217
+ 批量写结果建议:
218
+
219
+ ```json
220
+ {
221
+ "results": [
222
+ {
223
+ "id": "1",
224
+ "ok": true,
225
+ "action": "deleted"
226
+ },
227
+ {
228
+ "id": "2",
229
+ "ok": false,
230
+ "error": {
231
+ "code": "E_NOT_FOUND"
232
+ }
233
+ }
234
+ ],
235
+ "summary": {
236
+ "ok_count": 1,
237
+ "error_count": 1
238
+ }
239
+ }
240
+ ```
241
+
242
+ ## 10. 敏感信息与审计
243
+
244
+ - password、token、secret、authorization header、cookie 不得出现在 stdout、stderr、error.details、audit log。
245
+ - dry-run preview 必须脱敏敏感字段。
246
+ - reference/context/doctor 不得泄露明文凭证。
247
+ - context 可以报告凭证是否存在,但只能用布尔值或脱敏摘要。
248
+ - audit log 应记录命令路径、脱敏参数、调用账号、时间、exit code、duration。
249
+ - `--quiet` 不应关闭审计。
250
+
251
+ ## 11. 自描述命令(reference / context / doctor / changelog)
252
+
253
+ ### reference
254
+
255
+ 声明工具能力、命令、参数、输出 schema、错误码、权限等级,供 Agent 先理解能力。
256
+
257
+ ```json
258
+ {
259
+ "ok": true,
260
+ "schema_version": "1.0",
261
+ "data": {
262
+ "tool": "tool-name",
263
+ "version": "1.0.0",
264
+ "release_readiness": {
265
+ "level": "beta",
266
+ "fcc_required": true,
267
+ "fcc_status": "verified",
268
+ "mock_upstream_required": true,
269
+ "mock_upstream_status": "verified",
270
+ "live_smoke_required_for_stable": true,
271
+ "live_smoke_status": "missing",
272
+ "reason": "Stable requires recorded live smoke/E2E evidence.",
273
+ "required_evidence": [
274
+ "functional_contract_coverage_100",
275
+ "mock_upstream_contract_tests",
276
+ "recorded_live_smoke_for_stable"
277
+ ]
278
+ },
279
+ "commands": [
280
+ {
281
+ "path": "resource delete",
282
+ "type": "write",
283
+ "description": "Delete a resource",
284
+ "params": [
285
+ {
286
+ "name": "id",
287
+ "type": "string",
288
+ "required": true,
289
+ "multiple": false
290
+ }
291
+ ],
292
+ "output_schema": {}
293
+ }
294
+ ],
295
+ "exit_codes": {}
296
+ },
297
+ "meta": {
298
+ "duration_ms": 0
299
+ }
300
+ }
301
+ ```
302
+
303
+ `release_readiness` 是机器可读的发布门禁字段。每个 AI 原生 CLI 的
304
+ `reference` 都必须包含:
305
+
306
+ - `level`:`stable`、`beta` 或 `unpublishable`。
307
+ - `stable`:FCC 达到 100%;mock upstream / contract tests 覆盖外部行为;
308
+ 且该 release candidate 至少有一次可追溯的真实环境 smoke/E2E 记录。
309
+ - `beta`:FCC 达到 100%,mock upstream / contract tests 完整,但缺少真实
310
+ smoke/E2E 记录,或项目明确声明暂不具备真实 E2E 条件。
311
+ - `unpublishable`:任一公开行为缺少命令级测试,或 mock upstream / contract
312
+ tests 只覆盖 happy path,未覆盖失败、鉴权、分页、空结果、限流等行为。
313
+ - `fcc_status`、`mock_upstream_status`、`live_smoke_status` 使用
314
+ `verified`、`missing`、`not_applicable` 或 `unknown`;`stable` 对必需项不得
315
+ 使用 `missing` 或 `unknown`。
316
+ - `required_evidence[]` 列出 Agent 或发布脚本信任该等级前应检查的证据。
317
+
318
+ ### context
319
+
320
+ 报告当前运行环境、配置、目标、凭证状态。
321
+
322
+ ```json
323
+ {
324
+ "ok": true,
325
+ "schema_version": "1.0",
326
+ "data": {
327
+ "env": "prod",
328
+ "account": "user@example.com",
329
+ "config": {},
330
+ "credentials": {
331
+ "configured": true
332
+ }
333
+ },
334
+ "meta": {
335
+ "duration_ms": 0
336
+ }
337
+ }
338
+ ```
339
+
340
+ ### doctor
341
+
342
+ 环境与风险体检,每项给出可执行修复建议。
343
+
344
+ ```json
345
+ {
346
+ "ok": true,
347
+ "schema_version": "1.0",
348
+ "data": {
349
+ "checks": [
350
+ {
351
+ "check": "auth",
352
+ "status": "pass",
353
+ "fix": null
354
+ },
355
+ {
356
+ "check": "network",
357
+ "status": "fail",
358
+ "fix": "set HTTP_PROXY or check VPN"
359
+ },
360
+ {
361
+ "check": "release_readiness",
362
+ "status": "warn",
363
+ "fix": "record live smoke/E2E evidence before declaring stable"
364
+ }
365
+ ]
366
+ },
367
+ "meta": {
368
+ "duration_ms": 0
369
+ }
370
+ }
371
+ ```
372
+
373
+ `doctor` 必须包含 `check: "release_readiness"`,并与 `reference` 报告同一个
374
+ 发布等级。`stable` 使用 `pass`,有意声明的 `beta` 使用 `warn`,
375
+ `unpublishable` 或自称 `stable` 但证据缺失时使用 `fail`。非 `pass` 状态应给出
376
+ 可执行的 `fix`。
377
+
378
+ ### changelog
379
+
380
+ 报告**版本之间发生了什么变化**,让自更新后的 Agent 能补齐认知,而不是继续用旧套路。这是 `reference`(描述当前能力)在时间维度上的补充。
381
+
382
+ ```bash
383
+ tool changelog # 全部版本变更
384
+ tool changelog --since 1.0.3 # 只返回比 1.0.3 新的版本
385
+ ```
386
+
387
+ ```json
388
+ {
389
+ "ok": true,
390
+ "schema_version": "1.0",
391
+ "data": {
392
+ "current_version": "1.1.0",
393
+ "since": "1.0.3",
394
+ "entries": [
395
+ {
396
+ "version": "1.1.0",
397
+ "date": "2026-06-07",
398
+ "changes": {
399
+ "added": [
400
+ "..."
401
+ ],
402
+ "changed": [
403
+ "..."
404
+ ],
405
+ "fixed": []
406
+ }
407
+ }
408
+ ]
409
+ },
410
+ "meta": {
411
+ "duration_ms": 0
412
+ }
413
+ }
414
+ ```
415
+
416
+ 约定:
417
+
418
+ - **单一真相源**:`changelog` 输出从 `CHANGELOG.md` 派生(构建时按 `## [version]` 段落嵌入二进制),不另维护数据。与 release-notes 同源。
419
+ - `--since <version>` 只返回严格高于该版本的条目,供「上次见过 X 版本」的 Agent 拉增量。
420
+ - 变更分类沿用 Keep a Changelog:`added` / `changed` / `fixed` / `deprecated` / `removed` / `security`。
421
+ - 自更新成功后,工具应在结果中提示 Agent 运行 `changelog --since <旧版本>`(见 §14)。
422
+
423
+ ## 12. 命令设计约定
424
+
425
+ 1. 用最短命令完成明确任务,减少组合复杂度。
426
+ 2. 查询命令默认支持 `--fields` 与 `--compact` 降 token。
427
+ 3. 写命令必须支持 `--dry-run` 与 `--confirm`。
428
+ 4. 命名采用 `<noun> <verb>` 或 `<verb> <noun>` 风格,并在全局统一。
429
+ 5. 不要求 Agent 解析帮助文本;`--help` 给人看,机器能力通过 `reference` 暴露。
430
+ 6. 所有时间用 ISO 8601 UTC;所有 ID 用字符串。
431
+ 7. 命令失败时优先返回结构化错误,不输出半截成功 payload。
432
+ 8. 命令参数应避免二义性;布尔值用 flag,枚举值用有限选项。
433
+
434
+ ## 13. 功能契约覆盖率与发布门禁
435
+
436
+ 功能契约覆盖率(Functional Contract Coverage,FCC)是发布阻断标准:Agent
437
+ 能依赖的每一个公开行为,都必须有自动化命令级测试覆盖。代码行覆盖率或分支覆盖率是有用的工程指标,但它是辅助指标,不能替代缺失的功能契约测试。
438
+
439
+ 公开功能契约包括以下位置声明的任何行为:
440
+
441
+ - `README.md` / `README_zh.md`、`SKILL.md` 或 Skill reference 页面;
442
+ - `tool reference`、`--help`、`context`、`doctor`、`changelog`、`update` 输出;
443
+ - JSON envelope 字段、命令输出 schema、全局参数、错误码、exit code、retryable、stdout/stderr 边界;
444
+ - 已记录的配置/环境变量、凭证处理、写操作安全、自更新校验、Skill 同步和 `_untrusted` 安全承诺。
445
+
446
+ 每个公开命令或契约至少覆盖:
447
+
448
+ - 成功路径;
449
+ - 缺失/非法参数;
450
+ - 配置缺失、认证缺失或权限失败(适用时);
451
+ - 上游 API 失败、网络失败、限流或超时(适用时);
452
+ - JSON envelope 形状、输出 schema、exit code、stdout/stderr 边界;
453
+ - 非交互行为:不提示、不阻塞,写命令使用 `--dry-run` -> `--confirm <token>`;
454
+ - 每个影响可观察行为的 bug fix 都必须带回归测试。
455
+
456
+ `FCC = 100%` 的含义:
457
+
458
+ - 公开契约中列出的每个命令、参数、输出、错误行为,都映射到至少一个自动化测试,或明确标注为不适用;
459
+ - 命令级测试验证 CLI 边界,而不仅仅测试内部 helper;
460
+ - 生成代码、版本常量、构建元数据或不可达平台保护分支可以从数字覆盖率中排除,但如果它们是文档化公开行为,就不能从 FCC 中排除;
461
+ - 存在已知 FCC 缺口时,不得打发布 tag。
462
+ - `fcc_status: "verified"` 必须有机器背书——枚举守卫测试:从 `reference` 实时输出枚举全部叶子命令,逐一断言存在命令级测试调用。状态诚实声明为 `missing` 时守卫跳过;不补测试就把声明翻成 `verified` 会让守卫立刻失败(模板自带该守卫)。
463
+
464
+ CI 应在每个 PR 上运行单测和命令级测试。数字覆盖率门槛可以按仓库逐步抬升,但发布标准是绝对的:公开功能契约必须被覆盖。
465
+
466
+ ### 发布就绪等级
467
+
468
+ 发布就绪比「测试通过」更严格:
469
+
470
+ - **Stable**:FCC 达到 100%;mock upstream / contract tests 覆盖成功、
471
+ 参数校验、配置/认证/权限失败、上游/网络/限流/超时失败、空结果、分页、输出
472
+ schema、exit code、stdout/stderr 边界;并且该 release candidate 至少有一次
473
+ 真实环境 smoke/E2E 记录。
474
+ - **Beta**:FCC 达到 100%,mock upstream / contract tests 具备同等行为宽度,
475
+ 但缺少真实环境 smoke/E2E 记录,或项目明确声明暂不具备真实 E2E 条件。
476
+ - **Unpublishable**:任何公开命令、参数、输出或错误行为缺少命令级测试,或
477
+ mock upstream 测试只覆盖 happy path。
478
+
479
+ `reference.release_readiness` 和 `doctor.checks[]` 是这道门禁的机器可读出口。
480
+ 仓库可以选择不发布 `beta` 产物,但没有上述真实证据时不得自称 `stable`。
481
+
482
+ ## 14. 版本与兼容策略
483
+
484
+ - `schema_version` 表示输出 schema 版本,不等同于工具版本。
485
+ - 破坏性 schema 变更升级主版本,例如 `1.x` -> `2.0`。
486
+ - 非破坏性新增字段可以保持主版本不变。
487
+ - 废弃字段应先保留兼容期,并在 reference 中标记 deprecated。
488
+ - 兼容别名可以存在,但不应作为新文档推荐用法。
489
+ - Agent 应优先依据 `reference`,而不是 `--help` 或 README。
490
+
491
+ ### 版本协商(工具版本 ↔ Skill 期望)
492
+
493
+ Skill 是写它那天的能力快照,二进制版本一漂就可能错位:按 v1.1 写的 Skill 碰上 v1.0 二进制,会静默调用不存在的命令。
494
+
495
+ - 工具必须能报告自身版本:`tool --version` 与 `context.data.version`。
496
+ - Skill 在 frontmatter 声明最低兼容版本(见 SKILL-SPEC `requires.min_version`)。
497
+ - `doctor` 应有一项检查「当前版本是否满足声明的最低版本」,不满足时给出 `fix`(升级命令),状态 `fail`。
498
+
499
+ ### 自更新与 Skill 同步闭环
500
+
501
+ 带 `self-update` 的工具,更新成功后**必须打通两条更新链**:
502
+
503
+ 1. 二进制或包本身是最新;
504
+ 2. 内置 Agent Skill 目录也是最新,最终状态等同于运行 `npx skills add <repo> -y -g`。
505
+
506
+ 用户首次安装 Skill 仍使用 `npx skills add ...`;CLI 二进制不能暴露单独的 `install-skill` 命令。但在 update 生命周期中,工具需要负责完整更新:要么同步整个 `skills/<tool>/` 目录,要么在结果中显式返回 `skill_sync_status` 与 `skill_sync_command`,让 Agent 在使用新能力前完成同步。
507
+
508
+ update 必须遵守的契约:
509
+
510
+ - `update --check` 只读。返回当前/目标版本、安装方式、是否有二进制/包更新、Skill 同步是否需要或可用、checksum/签名材料是否可用。
511
+ - `update --dry-run` 返回完整变更预览:二进制/包更新、Skill 目录同步、checksum/签名校验,以及 `confirm_token`。
512
+ - `update --confirm <token>` 执行更新。替换本地文件或运行包管理器前,必须先完成 release 完整性校验。
513
+ - 更新成功后,返回 `previous_version`、`current_version`、`skill_sync_status`,以及足够审计的校验元数据。
514
+ - 如果二进制/包更新成功但 Skill 同步失败,必须返回非成功或部分成功状态,并给出 `skill_sync_command`;Agent 在 Skill 同步完成前不得使用新文档能力。
515
+
516
+ 版本通知契约:
517
+
518
+ - `update --check` 主动检查最新 release,并刷新本地更新通知缓存。
519
+ - `doctor` 可以用较短超时主动检查;网络失败本身不得导致 `doctor` 失败。
520
+ - `context` 和 `--help` 只读取本地缓存,不得访问远程 registry 或 GitHub。
521
+ - 有可用更新时,JSON 命令数据中包含 `notices[]`,字段包括
522
+ `type: "update_available"`、当前/最新版本、安装方式、
523
+ `recommended_command`、已知 release URL、检查时间和机器可读的下一步。文本/help 输出可追加一句简短提示。
524
+
525
+ release 校验基线:
526
+
527
+ - 按 `checksums.txt` 校验归档/包;checksum 不匹配、缺失 checksum 文件、或缺少当前归档条目,都必须失败关闭。
528
+ - 已签名 release 应由 tagged GitHub Actions release workflow 使用 Sigstore/Cosign keyless 模式签署 `checksums.txt`。验证端应绑定到预期仓库 workflow 身份和 GitHub OIDC issuer。
529
+ - update 结果携带 `signature_status`(一个短字符串说明发布完整性在哪里被验证:如 `verified`、`not_checked`、`handled_by_npm_installer`、`manual_release_verification_required`)与 `signature_verified`(仅当本地 Sigstore 验证真实执行且成功时为 true)。不能把 checksum 校验伪装成签名校验。
530
+
531
+ - `update --confirm <token>` 成功后,结果 `data` 中返回 `previous_version` 与 `current_version`。
532
+ - 同时在结果中提示:`run "changelog --since <previous_version>" to see what changed`。
533
+ - Agent 约定:自更新后、继续干活前,先读 `changelog --since <旧版本>`(见 SKILL-SPEC 配方)。
534
+
535
+ ## 15. 可选模式(按需启用)
536
+
537
+ 以下三种模式**不是人人必做**:工具用得上就照这里实现,用不上就忽略,零负担。它们让规范随工具复杂度伸缩——简单工具保持轻,复杂工具不必重新发明轮子。每条都标了「何时适用」。
538
+
539
+ ### 15.1 凭证生命周期(令牌会过期时)
540
+
541
+ **何时适用**:凭证不是静态的,而是会过期 / 需刷新的——OAuth access_token(微信公众号约 2h)、cookie / session(小红书)、临时 STS 凭证等。静态用户名密码的工具跳过本节。
542
+
543
+ - `context.data.credentials` 除「配没配」外,应报告**有效性与过期信息**(脱敏):
544
+
545
+ ```json
546
+ {
547
+ "credentials": {
548
+ "configured": true,
549
+ "valid": true,
550
+ "expires_at": "2026-06-07T12:00:00Z",
551
+ "refreshable": true
552
+ }
553
+ }
554
+ ```
555
+
556
+ - 令牌过期且不可自动刷新时,操作返回 `E_AUTH`(exit 4),`details` 指明需重新认证。
557
+ - 可自动刷新的工具应**透明刷新**,不让 Agent 操心;刷新失败再降级为 `E_AUTH`。
558
+ - `doctor` 增一项 `check: "credentials"`,对临近过期给 `warn` + 续期 `fix`。
559
+ - 刷新令牌、secret 一律脱敏,绝不出现在 stdout / stderr / details。
560
+
561
+ ### 15.2 异步任务生命周期(长任务:提交 -> 轮询 -> 取结果)
562
+
563
+ **何时适用**:操作不能同步返回结果——SQL 异步执行 / 审批(Archery)、批量群发、采集 / 爬取任务、大导出。同步即得结果的命令跳过本节。
564
+
565
+ - 提交命令立即返回 `job_id` 与状态,不阻塞:
566
+
567
+ ```json
568
+ {
569
+ "ok": true,
570
+ "schema_version": "1.0",
571
+ "data": {
572
+ "job_id": "job_abc123",
573
+ "status": "pending",
574
+ "poll": "tool job status --id job_abc123",
575
+ "result": "tool job result --id job_abc123"
576
+ },
577
+ "meta": { "duration_ms": 12 }
578
+ }
579
+ ```
580
+
581
+ - 状态查询返回稳定枚举:`pending` / `running` / `succeeded` / `failed` / `cancelled`,并带进度(如 `progress`、`eta_seconds`)。
582
+ - 结果与状态分开取:`succeeded` 后用 `result` 命令拉数据(大结果走 NDJSON / `--format raw`)。
583
+ - `failed` 的结果用标准 error envelope,`retryable` 指明能否重试整个任务。
584
+ - 写类长任务的提交仍走 `dry-run → confirm`;confirm 后才落 `job_id`。
585
+
586
+ ### 15.3 人工介入检查点(需要人来扫码 / 验证码 / 审批时)
587
+
588
+ **何时适用**:流程中途必须由人完成某步——扫码登录 / 验证码(小红书)、审批人放行(Archery)、二次确认等。全自动工具跳过本节。
589
+
590
+ - 卡在人工步骤时,**不阻塞、不瞎试**,返回专用信号让 Agent 把球踢给用户:
591
+
592
+ ```json
593
+ {
594
+ "ok": false,
595
+ "schema_version": "1.0",
596
+ "error": {
597
+ "code": "E_HUMAN_REQUIRED",
598
+ "message": "Scan the QR code to continue",
599
+ "details": { "action": "scan_qr", "resume": "tool login resume --id sess_1", "qr_path": "/tmp/qr.png" },
600
+ "retryable": false
601
+ },
602
+ "meta": { "duration_ms": 30 }
603
+ }
604
+ ```
605
+
606
+ - `E_HUMAN_REQUIRED` 用 exit code `9`(在既有 0–8 之外新增;不复用 `4`,以区分「凭证错」与「等人动作」)。
607
+ - `details.action` 用稳定枚举说明需要人做什么,`details.resume` 给出人工完成后的续跑命令。
608
+ - Agent 约定:收到 `E_HUMAN_REQUIRED` → 向用户转述 `message` 与所需动作 → 等用户完成 → 跑 `resume`,不自动重试。
609
+
610
+ ## 16. 设计检查清单
611
+
612
+ > 标 `(可选)` 的仅当对应可选模式启用时才需勾。
613
+
614
+ - [ ] 默认 `--format json`
615
+ - [ ] stdout 仅含合法 JSON / NDJSON,无污染
616
+ - [ ] 日志与进度全部走 stderr
617
+ - [ ] 成功/失败同形 envelope,含 `ok` 与 `schema_version`
618
+ - [ ] `error` 含语义化 `code`、`details`、`retryable`
619
+ - [ ] exit code 分层且与 `retryable` 一致
620
+ - [ ] 写命令具备 dry-run / confirm-token 闭环
621
+ - [ ] confirm token 绑定操作参数、账号、权限上下文和资源版本
622
+ - [ ] 提供 `reference` / `context` / `doctor`
623
+ - [ ] 提供 `changelog [--since]`,与 CHANGELOG/release-notes 同源
624
+ - [ ] 工具可报告自身版本(`--version` 与 `context.version`)
625
+ - [ ] `reference` 报告 `release_readiness`,`doctor` 检查它
626
+ - [ ] (含 self-update 时)实现 `update --check` / `--dry-run` / `--confirm`
627
+ - [ ] (含 self-update 时)release 完整性被校验,签名状态显式返回
628
+ - [ ] (含 self-update 时)整个 Skill 目录同步纳入 update 结果
629
+ - [ ] (含 self-update 时)更新后回传 previous/current 版本并提示读 changelog
630
+ - [ ] 查询命令支持 `fields` / `compact`
631
+ - [ ] 列表命令支持分页或明确说明无需分页
632
+ - [ ] README / Skill / reference / help / context / doctor / changelog / update 中声明的公开行为达到 100% 功能契约覆盖率
633
+ - [ ] Stable release 有真实环境 smoke/E2E 记录;否则工具声明为 `beta`
634
+ - [ ] 所有时间为 ISO 8601 UTC
635
+ - [ ] 所有 ID 为字符串
636
+ - [ ] 敏感信息全链路脱敏
637
+ - [ ] schema 变更有版本与兼容策略
638
+ - [ ] stdout/stderr 为 UTF-8 无 BOM
639
+ - [ ] (可选·令牌过期)`context`/`doctor` 报告凭证有效性与过期,刷新失败降级 `E_AUTH`
640
+ - [ ] (可选·长任务)提交返回 `job_id` + 状态枚举,状态/结果分离
641
+ - [ ] (可选·需人工)卡人工步骤返回 `E_HUMAN_REQUIRED`(exit 9)+ `resume`,不自动重试