@minniexcode/codex-switch 0.1.0 → 0.1.2

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.
Files changed (68) hide show
  1. package/README.AI.md +141 -110
  2. package/README.CN.md +215 -179
  3. package/README.md +224 -183
  4. package/dist/app/add-provider.js +16 -23
  5. package/dist/app/bridge.js +2 -1
  6. package/dist/app/edit-provider.js +30 -65
  7. package/dist/app/get-current-profile.js +15 -3
  8. package/dist/app/get-status.js +11 -8
  9. package/dist/app/list-config-profiles.js +3 -1
  10. package/dist/app/list-providers.js +10 -4
  11. package/dist/app/remove-provider.js +52 -19
  12. package/dist/app/run-doctor.js +26 -29
  13. package/dist/app/setup-codex.js +3 -3
  14. package/dist/app/show-config.js +3 -1
  15. package/dist/app/switch-provider.js +38 -6
  16. package/dist/cli/output.js +29 -19
  17. package/dist/commands/handlers.js +3 -2
  18. package/dist/commands/help.js +3 -3
  19. package/dist/commands/registry.js +29 -29
  20. package/dist/domain/config.js +293 -209
  21. package/dist/domain/providers.js +8 -0
  22. package/dist/domain/runtime-state.js +15 -15
  23. package/dist/domain/setup.js +3 -1
  24. package/dist/interaction/interactive.js +2 -2
  25. package/dist/runtime/codex-version.js +7 -0
  26. package/dist/runtime/copilot-adapter.js +326 -70
  27. package/dist/runtime/copilot-bridge-worker.js +27 -2
  28. package/dist/runtime/copilot-bridge.js +192 -10
  29. package/dist/runtime/copilot-cli.js +7 -0
  30. package/dist/runtime/copilot-installer.js +59 -1
  31. package/dist/runtime/copilot-sdk-loader.js +4 -1
  32. package/dist/storage/config-repo.js +6 -14
  33. package/docs/Design/codex-switch-v0.1.0-design.md +32 -152
  34. package/docs/Design/codex-switch-v0.1.1-design.md +22 -0
  35. package/docs/Design/codex-switch-v0.1.2-design.md +65 -0
  36. package/docs/PRD/codex-switch-prd-v0.1.0.md +65 -217
  37. package/docs/PRD/codex-switch-prd-v0.1.1.md +26 -0
  38. package/docs/PRD/codex-switch-prd-v0.1.2.md +41 -0
  39. package/docs/Reference/codex-config-reference.md +41 -0
  40. package/docs/Reference/codex-config-reference.zh-CN.md +41 -0
  41. package/docs/Tests/testing.md +1 -1
  42. package/docs/cli-usage.md +290 -223
  43. package/docs/codex-switch-command-design.md +2 -2
  44. package/docs/codex-switch-product-overview.md +18 -13
  45. package/docs/codex-switch-product-research.md +2 -2
  46. package/docs/codex-switch-technical-architecture.md +84 -1115
  47. package/package.json +2 -2
  48. package/docs/Design/codex-switch-copilot-integration-design.md +0 -517
  49. package/docs/Design/codex-switch-v0.0.10-design.md +0 -669
  50. package/docs/Design/codex-switch-v0.0.11-design.md +0 -824
  51. package/docs/Design/codex-switch-v0.0.12-design.md +0 -343
  52. package/docs/Design/codex-switch-v0.0.4-design.md +0 -874
  53. package/docs/Design/codex-switch-v0.0.5-design.md +0 -932
  54. package/docs/Design/codex-switch-v0.0.6-design.md +0 -708
  55. package/docs/Design/codex-switch-v0.0.7-design.md +0 -862
  56. package/docs/Design/codex-switch-v0.0.8-design.md +0 -132
  57. package/docs/Design/codex-switch-v0.0.9-design.md +0 -182
  58. package/docs/Design/codex-switch-v0.0.9-to-v0.0.12-roadmap.md +0 -413
  59. package/docs/PRD/codex-switch-prd-v0.0.10.md +0 -406
  60. package/docs/PRD/codex-switch-prd-v0.0.11.md +0 -577
  61. package/docs/PRD/codex-switch-prd-v0.0.12.md +0 -279
  62. package/docs/PRD/codex-switch-prd-v0.0.5-to-v0.1.0.md +0 -446
  63. package/docs/PRD/codex-switch-prd-v0.0.8.md +0 -62
  64. package/docs/PRD/codex-switch-prd-v0.0.9.md +0 -166
  65. package/docs/PRD/codex-switch-prd.md +0 -650
  66. package/docs/Tests/test-report-0.0.5.md +0 -163
  67. package/docs/Tests/test-report-0.0.7.md +0 -118
  68. package/docs/Tests/testing-bridge-v0.0.9.md +0 -367
@@ -1,669 +0,0 @@
1
- # codex-switch `0.0.10` 设计文档
2
-
3
- ## 文档信息
4
-
5
- - 文档类型:详细设计文档
6
- - 适用版本:`0.0.10`
7
- - 目标范围:`0.0.9 -> 0.0.10`
8
- - 对应 PRD:[`../PRD/codex-switch-prd-v0.0.10.md`](../PRD/codex-switch-prd-v0.0.10.md)
9
- - 关联上一版设计:[`./codex-switch-v0.0.9-design.md`](./codex-switch-v0.0.9-design.md)
10
-
11
- ## 1. 文档目标
12
-
13
- 本设计文档用于把 `0.0.10` 的 hardening 范围收口到“实现者无需再补关键决策”的程度。文档必须直接回答以下问题:
14
-
15
- - `migrate` 在进入交互前,如何先判断哪些 profile 可 adopt、哪些不可 adopt、失败时如何对外表达
16
- - `doctor` 与 `status` 的当前公开结构到底是什么,哪些字段稳定,哪些旧说法需要删除
17
- - `backups list` 与 `rollback` 的稳定 JSON 载荷和失败语义是什么
18
- - runtime state 应如何安全读取,哪些路径该宽容,哪些路径该严格
19
- - 发布前需要检查哪些版本与产物一致性问题
20
-
21
- 本设计只覆盖 `0.0.10` design 文件本身,不顺手扩写 README、roadmap、PRD 或代码实现细节之外的未来方案。
22
-
23
- ## 2. 版本定位
24
-
25
- `0.0.10` 是边界收口版本,不是命令面扩展版本。
26
-
27
- 它的定位不是继续发明新的状态层、聚合 schema 或自动化迁移协议,而是围绕当前已经存在的实现模型,消除文档承诺和代码事实之间的偏差,让以下几条线稳定下来:
28
-
29
- - `migrate` 的 adoptability 前置检查与交互边界
30
- - `doctor` / `status` 的公开契约和诊断边界
31
- - backup / rollback 的恢复契约
32
- - Copilot runtime state 的安全读路径
33
- - release correctness 的最低发布门槛
34
-
35
- ## 3. 设计原则
36
-
37
- `0.0.10` 必须遵循以下原则:
38
-
39
- 1. 以当前实现契约为事实源,不回引已经与代码脱节的旧概念。
40
- 2. 不把 `auth.json` 重新定义为 provider secret mirror。
41
- 3. 不引入 `status.health.*`、并行诊断结构或新的大 JSON 输出族。
42
- 4. 命令错误码与 `doctor` issue code 是两层契约,命名应尽量对齐,但不能混为一体。
43
- 5. 文档中的“稳定字段”要少而明确;面向人类阅读的 reason/message 文本允许演进,但结构边界必须固定。
44
-
45
- ## 4. 数据边界与公开契约
46
-
47
- ### 4.1 文件角色
48
-
49
- - `providers.json`
50
- - 管理态 registry
51
- - 是 managed state 的 SSOT
52
- - 记录 provider 名称、profile 绑定以及 runtime-backed provider 的持久化配置
53
- - `config.toml`
54
- - 运行态路由投影
55
- - 表达当前 active profile 与 `model_providers.<name>` runtime 路由
56
- - 允许出现尚未被 `providers.json` 接管的 live state
57
- - `auth.json`
58
- - 独立 auth state 文件
59
- - 只在 `status` / `doctor` 中做存在性、可解析性与基础元数据读取
60
- - 不是 provider secret mirror,也不是 managed provider ownership 的证明
61
- - runtime state
62
- - 指 Copilot bridge 的本地运行态文件,当前落在 `copilot-bridge-state.json`
63
- - 用于 bridge 运行状况探测、stale state 判断和 direct provider 场景的安全读取
64
- - 不纳入 managed backup 的强事务边界
65
- - backups
66
- - 用于恢复 managed files
67
- - 不承诺恢复运行中 bridge 进程,也不承诺恢复外部 Copilot 登录态
68
-
69
- ### 4.2 契约分层
70
-
71
- - 命令返回中的 `error.code`
72
- - 面向 CLI 调用方
73
- - 用于表达命令失败原因,例如 `INVALID_ARGUMENT`、`BACKUP_NOT_FOUND`
74
- - `doctor.data.issues[].code`
75
- - 面向诊断域
76
- - 用于表达系统状态问题,例如 `AUTH_JSON_INVALID`、`BRIDGE_STATE_STALE`
77
-
78
- 二者可能名称相近,但并不等价。例如:
79
-
80
- - `MIGRATE_NO_ADOPTABLE_PROFILES` 是命令错误码,不是 `doctor` issue code
81
- - `AUTH_JSON_INVALID` 当前既可能出现在内部错误归一化路径中,也可能作为 `doctor` issue code 出现,但语义仍以“诊断问题”优先,不应被重新包装成 auth mirror 协议
82
-
83
- ## 5. `migrate` 详细设计
84
-
85
- ### 5.1 设计目标
86
-
87
- `migrate` 在 `0.0.10` 的重点不是新增自动化导入能力,而是把交互式 adopt 路径做扎实。命令需要先判断“能不能迁”,再决定“如何迁”。
88
-
89
- ### 5.2 adoptability 前置检查
90
-
91
- 交互流程前必须先完成 adoptability 预检查。该检查以当前 config consistency 模型为边界,围绕 unmanaged profile 是否已经具备成为 managed provider 的最小条件展开。
92
-
93
- 稳定输出字段:
94
-
95
- - `availableProfiles`
96
- - `adoptableProfiles`
97
- - `blockingReasonsByProfile`
98
-
99
- 其中:
100
-
101
- - `availableProfiles` 表示当前 `config.toml` 中可见 profile 集合
102
- - `adoptableProfiles` 表示通过最小 adopt 条件检查的 profile 集合
103
- - `blockingReasonsByProfile` 是面向人类可读的诊断映射;字段存在本身是稳定契约,但 reason 文本不承诺固定枚举
104
-
105
- 阻塞原因必须逐项对齐现有 config consistency 模型,至少覆盖:
106
-
107
- - 缺 `model`
108
- - 缺 `model_provider`
109
- - `model_provider` 名称与 profile 不匹配
110
- - 缺 `model_providers.<name>` section
111
- - 缺 `base_url`
112
- - 缺 `env_key`
113
-
114
- ### 5.3 无可 adopt profile 的失败语义
115
-
116
- `0.0.10` 正式引入并固定以下命令错误码:
117
-
118
- - `MIGRATE_NO_ADOPTABLE_PROFILES`
119
-
120
- 它用于表达:命令在进入 strategy prompt、profile 选择和 provider 详情收集之前,就已经判断出没有任何 profile 满足 adopt 前提。
121
-
122
- 示例:
123
-
124
- ```json
125
- {
126
- "error": {
127
- "code": "MIGRATE_NO_ADOPTABLE_PROFILES",
128
- "message": "No adoptable profiles were found for migrate.",
129
- "details": {
130
- "availableProfiles": ["copilot", "openai"],
131
- "adoptableProfiles": [],
132
- "blockingReasonsByProfile": {
133
- "copilot": ["model_provider is missing."],
134
- "openai": ["model_providers.openai.base_url is missing."]
135
- }
136
- }
137
- }
138
- }
139
- ```
140
-
141
- ### 5.4 非交互式 `migrate` 的边界
142
-
143
- `0.0.10` 不引入完整的非交互式 `migrate` profile 选择和 secret 注入参数。
144
-
145
- 因此需要保留两条失败路径的分工:
146
-
147
- - `MIGRATE_NO_ADOPTABLE_PROFILES`
148
- - 表示输入状态本身不满足 adopt 前提
149
- - 失败发生在交互需求之前
150
- - `INVALID_ARGUMENT`
151
- - 表示当前 release 仍要求 interactive TTY 才能完成 profile 选择和 provider details 收集
152
- - 即使存在 adoptable profiles,也不能把非交互调用伪装成受支持 contract
153
-
154
- 非交互错误仍可继续暴露:
155
-
156
- - `availableProfiles`
157
- - `adoptableProfiles`
158
- - 面向用户的 suggestion 文案
159
-
160
- 但文档不应把这些细节提升成“已支持自动化 migrate”的承诺。
161
-
162
- ### 5.5 空 registry 场景
163
-
164
- 当 `providers.json` 已存在但 registry 为空时:
165
-
166
- - 跳过 `merge` / `overwrite` prompt
167
- - 对外不新增额外 schema
168
- - 内部按 `overwrite` 语义继续即可
169
-
170
- 该决策的目的不是改变最终结果,而是去掉没有决策价值的交互。
171
-
172
- ### 5.6 与当前实现的衔接
173
-
174
- 当前 `migrate` 主要落在:
175
-
176
- - `src/commands/handlers.ts`
177
- - `src/app/setup-codex.ts`
178
- - `src/domain/setup.ts`
179
-
180
- `0.0.10` 的实现约束是:
181
-
182
- - adoptability 预检查前置到交互入口之前
183
- - 交互层只负责选择 adoptable profiles 和收集缺失 provider details
184
- - app 层继续负责最终 mutation、backup、post-doctor 复检
185
-
186
- ## 6. `doctor` 与 `status` 详细设计
187
-
188
- ### 6.1 `doctor` 的主诊断结构
189
-
190
- `doctor` 继续以 `doctor.data.issues[]` 作为主诊断面,不新增并行结构。
191
-
192
- 单项 issue 的目标结构保持:
193
-
194
- - `code`
195
- - `message`
196
- - 与该问题直接相关的附加字段
197
-
198
- 示例:
199
-
200
- ```json
201
- {
202
- "code": "AUTH_JSON_INVALID",
203
- "message": "Failed to parse auth.json.",
204
- "file": "C:\\Users\\name\\.codex\\auth.json"
205
- }
206
- ```
207
-
208
- ### 6.2 `doctor` 诊断域边界
209
-
210
- `0.0.10` 中允许且应清晰表达的诊断域包括:
211
-
212
- - config / providers consistency
213
- - active profile 未受管
214
- - shared profile reference
215
- - `model_provider` / `base_url` / `env_key` 缺失或不一致
216
- - `AUTH_JSON_INVALID`
217
- - 仅在 auth 文件存在但不可解析时出现
218
- - Codex runtime probe
219
- - `CODEX_NOT_INSTALLED`
220
- - `CODEX_VERSION_UNSUPPORTED`
221
- - `CODEX_LOGIN_FAILED`
222
- - Copilot / bridge 诊断
223
- - `COPILOT_SDK_MISSING`
224
- - `COPILOT_AUTH_REQUIRED`
225
- - `BRIDGE_STATE_MISSING`
226
- - `BRIDGE_STATE_STALE`
227
- - `PROVIDER_BASE_URL_MISMATCH`
228
- - `BRIDGE_HEALTHCHECK_FAILED`
229
-
230
- ### 6.3 `doctor` 明确不做的事
231
-
232
- - 不检查 `auth.json` 与 active provider 的 key/value mirror 一致性
233
- - 不报告 `auth mirror mismatch` 一类问题码
234
- - 不发明新的 `doctor.health.*` 或第二套自动化诊断 schema
235
-
236
- ### 6.4 `status` 的当前事实边界
237
-
238
- `status` 保持当前 JSON shape,不新增 `health.overall`、`health.summary` 等字段。
239
-
240
- `status.data` 继续围绕以下字段表达:
241
-
242
- - `currentProfile`
243
- - `currentProfileMapped`
244
- - `provider`
245
- - `activeProviderResolvable`
246
- - `activeProviderCandidates`
247
- - `runtimeProvider`
248
- - `copilotSdk`
249
- - `copilotAuth`
250
- - `copilotBridge`
251
- - `copilotRuntimeState`
252
- - `liveState`
253
- - `auth`
254
- - `configProfiles`
255
- - `issues`
256
- - `storage`
257
-
258
- ### 6.5 `status.data.auth` 的稳定 shape
259
-
260
- `status.data.auth` 在 `0.0.10` 中固定为中性文件状态摘要:
261
-
262
- - `exists`
263
- - `valid`
264
- - `parseError`
265
- - `authMode`
266
-
267
- 示例:
268
-
269
- ```json
270
- {
271
- "exists": true,
272
- "valid": true,
273
- "parseError": null,
274
- "authMode": "session"
275
- }
276
- ```
277
-
278
- 该结构不包含:
279
-
280
- - provider ownership
281
- - managed key 列表
282
- - auth mirror 是否与当前 provider 一致的结论
283
-
284
- ### 6.6 `status.data.storage` 的稳定 shape
285
-
286
- `status.data.storage` 在 `0.0.10` 中固定为:
287
-
288
- - `managementSSOT`
289
- - `runtimeMirrors`
290
- - `authStateFile`
291
- - `rollbackState`
292
-
293
- 示例:
294
-
295
- ```json
296
- {
297
- "managementSSOT": "providers.json",
298
- "runtimeMirrors": ["config.toml"],
299
- "authStateFile": "auth.json",
300
- "rollbackState": "backups/latest.json"
301
- }
302
- ```
303
-
304
- ### 6.7 direct provider 与脏 runtime state
305
-
306
- `status` / `doctor` 需要能在 direct provider 场景下稳定输出,即使本地存在 stale 或损坏的 Copilot runtime state,也不应因为“读到不可信运行态文件”而导致整个读路径崩溃。
307
-
308
- 设计目标不是新增公共输出 schema,而是把问题包装回现有:
309
-
310
- - `copilotRuntimeState`
311
- - `copilotBridge`
312
- - `doctor.data.issues[]`
313
- - `warnings`
314
-
315
- ## 7. backup / rollback 详细设计
316
-
317
- ### 7.1 `backups list` 稳定载荷
318
-
319
- `backups list` 的稳定列表项写死为:
320
-
321
- - `backupId`
322
- - `createdAt`
323
- - `reason`
324
- - `files`
325
- - `backupPath`
326
-
327
- 单项示例:
328
-
329
- ```json
330
- {
331
- "backupId": "20260511-221457-switch",
332
- "createdAt": "2026-05-11T22:14:57.000Z",
333
- "reason": "switch",
334
- "files": ["config.toml", "providers.json"],
335
- "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221457-switch"
336
- }
337
- ```
338
-
339
- 当前实现额外返回的 `count` 应在设计中明确标为命令层派生便利字段,而不是 PRD 级主契约。它可以保留,但不应成为外部集成的唯一依赖项。
340
-
341
- ### 7.2 manifest 异常的列表行为
342
-
343
- 当 `backups/` 下存在损坏或不完整的历史项时:
344
-
345
- - 命令应继续返回其余有效备份
346
- - `warnings` 用于提示 `manifest.json` 缺失或非法
347
- - 只有在没有任何有效备份可列出时,才失败为 `BACKUP_NOT_FOUND`
348
-
349
- ### 7.3 `rollback` 成功载荷
350
-
351
- `rollback` 的稳定成功载荷为:
352
-
353
- - `restoredFiles`
354
- - `backupId`
355
- - `backupPath`
356
-
357
- 示例:
358
-
359
- ```json
360
- {
361
- "data": {
362
- "restoredFiles": ["config.toml", "providers.json"],
363
- "backupId": "20260511-221457-switch",
364
- "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221457-switch"
365
- }
366
- }
367
- ```
368
-
369
- 对 `rollback latest` 路径,`backupId` 可以为 `null`,但仍需返回 `backupPath` 与 `restoredFiles`。
370
-
371
- ### 7.4 `rollback` 路径区分
372
-
373
- 必须在设计稿中明确两条路径:
374
-
375
- 1. `rollback`
376
- - 读取 `backups/latest.json`
377
- - 适合“恢复最近一次受管变更”
378
- 2. `rollback <backupId>`
379
- - 按显式历史目录加载对应 manifest
380
- - 适合恢复指定时间点
381
-
382
- ### 7.5 `rollback` 失败语义
383
-
384
- `0.0.10` 先收口到两类失败:
385
-
386
- - `BACKUP_NOT_FOUND`
387
- - `ROLLBACK_FAILED`
388
-
389
- 其中:
390
-
391
- - `BACKUP_NOT_FOUND`
392
- - latest manifest 不存在
393
- - 指定 `backupId` 不存在
394
- - backups 目录不存在或没有有效备份
395
- - `ROLLBACK_FAILED`
396
- - latest manifest 读取失败
397
- - 指定 manifest 读取失败
398
- - manifest 指向的备份文件缺失
399
- - restore 过程中 copy/delete 失败
400
-
401
- 如果后续版本要继续细分,只能选择以下一种路径:
402
-
403
- - 新增更具体的 `error.code`
404
- - 维持主错误码不变,但在 `details.reason` 或 `details.cause` 中细分
405
-
406
- 不能同时模糊地引入一组既不像命令错误码、又不像诊断 issue code 的中间状态。
407
-
408
- ## 8. runtime state 与恢复边界
409
-
410
- ### 8.1 设计选择
411
-
412
- runtime state 的设计选择是:
413
-
414
- - 新增安全检查与诊断包装
415
- - 不直接发明新的公共输出 schema
416
-
417
- ### 8.2 读取策略分层
418
-
419
- 建议把运行态读取分成两类路径:
420
-
421
- - safe inspection helper
422
- - 供 `status`、`doctor`、direct provider 相关只读路径使用
423
- - 遇到脏 runtime state 时,返回可解释的空值、warning 或 issue,而不是直接崩溃
424
- - stricter loader
425
- - 供 bridge lifecycle 路径使用
426
- - 在 `bridge start/stop/status` 等需要高置信度状态的场景中维持严格校验
427
-
428
- 这样可以保证:
429
-
430
- - 诊断类命令足够稳健
431
- - bridge 生命周期命令仍保留必要的严格性
432
- - direct provider 读路径不会被无关的 stale runtime state 连带打崩
433
-
434
- ### 8.3 与 backup / rollback 的关系
435
-
436
- runtime state 继续保持在 managed backup 事务外:
437
-
438
- - backup 不承诺捕获 `copilot-bridge-state.json`
439
- - rollback 不承诺恢复 bridge 进程
440
- - `doctor` / `status` 负责解释运行态是否 stale、missing 或 mismatch
441
-
442
- ## 9. release correctness
443
-
444
- `0.0.10` 需要把以下内容纳入发布正确性检查:
445
-
446
- - CLI `--version` 必须与 `package.json` 一致
447
- - README 与公开文档中的版本字样应与本次发布版本一致
448
- - `npm pack` 作为发布前 sanity check 执行
449
-
450
- 这里的设计选择是:
451
-
452
- - `npm pack` 是 preflight,不是默认测试流的一部分
453
- - 版本一致性检查属于 release correctness,不等同于功能测试
454
-
455
- ## 10. 公开接口 / 契约变化
456
-
457
- `0.0.10` 需要在设计稿中单独固定以下公开变化:
458
-
459
- - `status.data.auth` 是中性文件状态,不含 provider ownership 或 managed key 列表
460
- - `doctor` 不再承诺任何 `auth mirror mismatch` 类问题码
461
- - `backups list` 的稳定 JSON 载荷固定为 `backupId`、`createdAt`、`reason`、`files`、`backupPath`
462
- - `rollback` 的稳定成功载荷固定为 `restoredFiles`、`backupId`、`backupPath`
463
- - `MIGRATE_NO_ADOPTABLE_PROFILES` 是命令错误码,不是 `doctor` / `status` issue code
464
- - 本版明确不引入 `status.health.*` 契约
465
-
466
- ## 11. 模块设计与代码落点
467
-
468
- 本版按行为分组说明代码落点,而不是逐文件抄清单。
469
-
470
- ### 11.1 命令流与交互前置检查
471
-
472
- 主要落点:
473
-
474
- - `src/commands/handlers.ts`
475
- - `src/interaction/interactive.ts`
476
-
477
- 职责:
478
-
479
- - 解析 `migrate`、`rollback` 等命令的交互边界
480
- - 在进入 prompt 前完成 adoptability 预检查
481
- - 空 registry 时跳过无意义策略 prompt
482
- - 在 help / human output 中同步更准确的失败说明
483
-
484
- ### 11.2 诊断与状态聚合
485
-
486
- 主要落点:
487
-
488
- - `src/app/get-status.ts`
489
- - `src/app/run-doctor.ts`
490
- - `src/storage/auth-repo.ts`
491
- - runtime state 读取辅助
492
-
493
- 职责:
494
-
495
- - 聚合 config/providers consistency、auth state、runtime probe、bridge probe
496
- - 固定 `status.data.auth` 与 `status.data.storage` shape
497
- - 继续沿用 `doctor.data.issues[]` 作为主诊断面
498
-
499
- ### 11.3 恢复与运行态边界
500
-
501
- 主要落点:
502
-
503
- - `src/storage/backup-repo.ts`
504
- - `src/app/rollback-backup.ts`
505
- - `src/storage/runtime-state-repo.ts`
506
- - bridge runtime helper
507
-
508
- 职责:
509
-
510
- - 保持 backup manifest 校验、list、restore 语义一致
511
- - 明确 latest 与显式 `backupId` 的 rollback 路径
512
- - 在读路径上对 runtime state 做安全包装,在生命周期路径上保留严格加载
513
-
514
- ### 11.4 人类可读输出与帮助文本
515
-
516
- 主要落点:
517
-
518
- - `src/commands/registry.ts`
519
- - `src/cli/output.ts`
520
- - 相关 help 文案与错误消息
521
-
522
- 职责:
523
-
524
- - 让 `migrate` 非交互失败信息更直接
525
- - 让 `doctor` / `status` 的字段说明不再暗示 auth mirror 模型
526
- - 让 `backups list` / `rollback` 的对外说明与真实载荷对齐
527
-
528
- ## 12. 示例片段
529
-
530
- ### 12.1 `status.data.auth`
531
-
532
- ```json
533
- {
534
- "exists": true,
535
- "valid": false,
536
- "parseError": "Failed to parse auth.json.",
537
- "authMode": null
538
- }
539
- ```
540
-
541
- ### 12.2 `status.data.storage`
542
-
543
- ```json
544
- {
545
- "managementSSOT": "providers.json",
546
- "runtimeMirrors": ["config.toml"],
547
- "authStateFile": "auth.json",
548
- "rollbackState": "backups/latest.json"
549
- }
550
- ```
551
-
552
- ### 12.3 `backups list` 单项
553
-
554
- ```json
555
- {
556
- "backupId": "20260511-221457-migrate",
557
- "createdAt": "2026-05-11T22:14:57.000Z",
558
- "reason": "migrate",
559
- "files": ["providers.json", "config.toml"],
560
- "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221457-migrate"
561
- }
562
- ```
563
-
564
- ### 12.4 `rollback` success
565
-
566
- ```json
567
- {
568
- "data": {
569
- "restoredFiles": ["providers.json", "config.toml"],
570
- "backupId": null,
571
- "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221457-migrate"
572
- }
573
- }
574
- ```
575
-
576
- ### 12.5 `MIGRATE_NO_ADOPTABLE_PROFILES`
577
-
578
- ```json
579
- {
580
- "error": {
581
- "code": "MIGRATE_NO_ADOPTABLE_PROFILES",
582
- "message": "No adoptable profiles were found for migrate.",
583
- "details": {
584
- "availableProfiles": ["work-openai"],
585
- "adoptableProfiles": [],
586
- "blockingReasonsByProfile": {
587
- "work-openai": [
588
- "model_provider must match the profile name.",
589
- "model_providers.work-openai.env_key is missing."
590
- ]
591
- }
592
- }
593
- }
594
- }
595
- ```
596
-
597
- ### 12.6 `doctor.data.issues[]` 单项
598
-
599
- ```json
600
- {
601
- "code": "BRIDGE_STATE_STALE",
602
- "message": "Copilot bridge runtime state exists for a provider that is not the current active profile.",
603
- "activeProfile": "openai",
604
- "runtimeProvider": "copilot",
605
- "runtimeProfile": "copilot"
606
- }
607
- ```
608
-
609
- ## 13. 测试设计
610
-
611
- 测试设计按当前测试组织展开,重点覆盖以下内容。
612
-
613
- ### 13.1 `migrate`
614
-
615
- - 0 adoptable profiles 时直接失败为 `MIGRATE_NO_ADOPTABLE_PROFILES`
616
- - `providers.json` 已存在但 registry 为空时跳过策略 prompt
617
- - 非交互失败继续走 `INVALID_ARGUMENT`,并带清晰 suggestion
618
- - `blockingReasonsByProfile` 覆盖以下阻塞类型:
619
- - 缺 `model`
620
- - 缺 `model_provider`
621
- - `model_provider` 名称不匹配
622
- - 缺 `model_providers.<name>`
623
- - 缺 `base_url`
624
- - 缺 `env_key`
625
-
626
- ### 13.2 `doctor` / `status`
627
-
628
- - `AUTH_JSON_INVALID`
629
- - config/profile/provider consistency
630
- - `COPILOT_SDK_MISSING`
631
- - `COPILOT_AUTH_REQUIRED`
632
- - `BRIDGE_STATE_MISSING`
633
- - `BRIDGE_STATE_STALE`
634
- - `PROVIDER_BASE_URL_MISMATCH`
635
- - `BRIDGE_HEALTHCHECK_FAILED`
636
- - direct provider 下脏 runtime state 仍能稳定输出
637
-
638
- ### 13.3 backup / rollback
639
-
640
- - invalid or missing manifest warnings
641
- - `BACKUP_NOT_FOUND`
642
- - `ROLLBACK_FAILED`
643
- - restore missing backup file
644
- - `rollback latest`
645
- - 显式 `rollback <backupId>`
646
-
647
- ### 13.4 release correctness
648
-
649
- - built CLI `--version`
650
- - `package.json` version
651
- - README 版本标注一致性
652
- - `npm pack` preflight
653
-
654
- ## 14. 完成标准
655
-
656
- `0.0.10` 设计工作完成时,必须满足:
657
-
658
- 1. 文档中不再出现 `auth mirror`、`auth mirror mismatch`、`status.health.*` 等与当前实现冲突的硬承诺。
659
- 2. `migrate`、`doctor`、`status`、`backups list`、`rollback` 的公共契约可以直接从设计稿读出,而不需要回查旧 PRD 或猜测代码行为。
660
- 3. runtime state 被明确定位为“安全检查与诊断包装对象”,而不是新的强事务 managed state。
661
- 4. 发布前检查明确包含 CLI 版本、打包产物与公开文档版本标注三类一致性校验。
662
-
663
- ## 15. 发布前检查
664
-
665
- 发布 `0.0.10` 前至少执行:
666
-
667
- 1. 验证 `node dist/cli.js --version` 与 `package.json` 一致。
668
- 2. 验证公开文档中的版本字样没有停留在旧版本或提前承诺未来 schema。
669
- 3. 执行 `npm pack`,确认发布包可生成,且文档、构建产物和 CLI 入口完整。