@ranger1/dx 0.1.99 → 0.1.100

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.
@@ -1,203 +0,0 @@
1
- ---
2
- name: autospec
3
- description: 设计文档到实施计划的全自动流水线。仅在用户显式调用时触发(如 /autospec),不通过关键词自动触发。将已讨论好的设计方案依次执行:写设计文档 → critic 审核修复 → 写实施计划 → critic 审核修复 → 自动开始 subagent-driven 执行 → git-pr-ship 交付 PR。
4
- ---
5
-
6
- # spec-to-plan:设计文档 → 审核 → 实施计划 → 审核 → 执行 → 交付 PR
7
-
8
- 六步全自动流水线。用户在 brainstorming 阶段讨论好目标和方案后显式调用,后续全部自动完成,无需人工干预。
9
-
10
- ## 输入
11
-
12
- `/spec-to-plan <topic-slug>`
13
-
14
- - `topic-slug`:文件命名用,如 `chat-instruction-admin`
15
- - 当前对话中必须已包含充分的设计上下文(目标、方案、数据模型、API、技术决策等)
16
-
17
- ## 输出
18
-
19
- - 审核后的设计文档:`docs/superpowers/specs/YYYY-MM-DD-<topic-slug>-design.md`
20
- - 审核后的实施计划:`docs/superpowers/plans/YYYY-MM-DD-<topic-slug>.md`
21
- - 自动进入 subagent-driven 执行模式
22
-
23
- ## 执行流程
24
-
25
- 严格按顺序执行五步,中间不暂停、不询问用户。
26
-
27
- ---
28
-
29
- ### Step 1:撰写设计文档
30
-
31
- 从当前对话上下文中提取所有已确认的设计决策,写入设计文档。不臆造未讨论过的需求。
32
-
33
- **路径**:`docs/superpowers/specs/YYYY-MM-DD-<topic-slug>-design.md`
34
-
35
- **结构**(按需裁剪,无内容的章节不写):
36
-
37
- ```markdown
38
- # <功能名称>
39
-
40
- ## 背景
41
- ## 数据模型
42
- ## API 设计
43
- ## 缓存策略
44
- ## 前端改造
45
- ## 必要的集成步骤
46
- ## Seed 数据
47
- ## 模块结构
48
- ## 不做的事
49
- ```
50
-
51
- **自检**:写完后扫描——无 TBD/TODO、章节不矛盾、范围聚焦、无歧义。发现问题直接修。
52
-
53
- ---
54
-
55
- ### Step 2:审核设计文档
56
-
57
- 派出 `oh-my-claudecode:critic` subagent 审核。
58
-
59
- **Prompt**:
60
-
61
- ```
62
- 请以挑刺的角度审核这份设计文档,结合项目实际代码验证每一个设计决策。
63
-
64
- 文档路径:<spec-path>
65
-
66
- 审核要点:
67
- 1. 数据模型:字段命名、ID 策略、@map/@@map 是否匹配项目惯例
68
- 2. 模块结构:目录组织是否与现有模块一致
69
- 3. API 设计:路由前缀、鉴权、分页 DTO 继承是否符合惯例
70
- 4. 缓存:CacheService 方法签名是否正确
71
- 5. 前端:store 组织、API 调用模式、组件层级是否匹配实际代码
72
- 6. 集成步骤:是否遗漏 ErrorCode、Swagger、RBAC、api-contracts、菜单注册等
73
- 7. Seed:入口注册、幂等策略是否正确
74
-
75
- 每个发现给出具体文件路径和代码证据。
76
- 分为:错误(必须修复)、遗漏(建议补充)、建议(可选优化)。
77
- ```
78
-
79
- **处理结果**:读取 critic 返回,逐一修复设计文档。错误和遗漏全部修复,建议类酌情采纳。不改变已与用户确认的设计决策,只修事实性错误和惯例偏差。
80
-
81
- ---
82
-
83
- ### Step 3:撰写实施计划
84
-
85
- 基于审核后的设计文档写实施计划。
86
-
87
- **路径**:`docs/superpowers/plans/YYYY-MM-DD-<topic-slug>.md`
88
-
89
- **头部**(固定格式):
90
-
91
- ```markdown
92
- # <功能名称> Implementation Plan
93
-
94
- > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development to implement this plan task-by-task.
95
-
96
- **Goal:** 一句话
97
- **Architecture:** 2-3 句
98
- **Tech Stack:** 关键技术
99
- **Spec:** <spec-path>
100
-
101
- ---
102
- ```
103
-
104
- **Task 结构**:
105
-
106
- ```markdown
107
- ### Task N: <组件名>
108
-
109
- **Files:**
110
- - Create: `exact/path`
111
- - Modify: `exact/path`
112
-
113
- - [ ] **Step 1: 描述**
114
- (完整代码块)
115
-
116
- - [ ] **Step 2: 验证**
117
- Run: `命令`
118
- Expected: 预期
119
-
120
- - [ ] **Step 3: Commit**
121
- ```
122
-
123
- **要求**:
124
- - 每步完整代码,禁止 TBD/TODO/"类似 Task N"
125
- - import 路径准确(基于 Step 2 审核已验证的惯例)
126
- - Task 按依赖顺序排列
127
- - 粒度 2-5 分钟每 Task
128
-
129
- **自检**:spec 每个章节有对应 Task、无占位符、类型和方法名前后一致。
130
-
131
- ---
132
-
133
- ### Step 4:审核实施计划
134
-
135
- 派出 `oh-my-claudecode:critic` subagent 审核。
136
-
137
- **Prompt**:
138
-
139
- ```
140
- 请以挑刺的角度审核这份实施计划,结合项目实际代码验证每一个代码片段。
141
-
142
- 计划路径:<plan-path>
143
- 设计文档:<spec-path>
144
-
145
- 审核要点:
146
- 1. Import 路径:每个 import 在项目中是否真实存在
147
- 2. 路由冲突:参数路由 (:id) 和固定路由的顺序
148
- 3. API 方法名:Zodios 等生成的方法命名是否匹配惯例
149
- 4. 测试基建:E2E setup 是否匹配项目 fixtures
150
- 5. Seed 入口:注册方式是否匹配项目结构
151
- 6. Store 注册:前端 store 根注册方式是否正确
152
- 7. 页面路由:文件路径能否自动注册路由
153
- 8. DTO/Exception:构造函数签名、方法名是否匹配实际 API
154
- 9. 遗漏:spec 中的需求是否全部覆盖
155
-
156
- 每个发现给出具体文件路径和代码证据。
157
- 分为:错误(必须修复)、遗漏(建议补充)、建议(可选优化)。
158
- ```
159
-
160
- **处理结果**:读取 critic 返回,逐一修复实施计划。错误和遗漏全部修复。
161
-
162
- ---
163
-
164
- ### Step 5:自动开始执行
165
-
166
- 四步文档工作完成后,直接调用 `superpowers:subagent-driven-development` skill,传入实施计划路径,开始 Task-by-Task 的 subagent 执行。
167
-
168
- 不询问用户选择执行方式,直接以 subagent-driven 模式启动。
169
-
170
- 输出简短状态通知:
171
-
172
- ```
173
- 设计文档:<spec-path>(已审核修复)
174
- 实施计划:<plan-path>(已审核修复,共 N 个 Task)
175
- 正在以 subagent-driven 模式开始执行...
176
- ```
177
-
178
- ---
179
-
180
- ### Step 6:调用 git-pr-ship 交付 PR
181
-
182
- subagent-driven 执行全部 Task 完成并通过验证后,直接调用 `git-pr-ship` skill,进入 PR 交付流程。
183
-
184
- 前置条件(执行阶段应已满足,若未满足先补齐):
185
- - 全部 Task 已完成并勾选
186
- - 代码变更已提交到当前功能分支
187
- - lint、构建、相关测试已通过
188
-
189
- 不询问用户,直接以 `git-pr-ship` 流程收口:整理提交、推送分支、创建 PR。
190
-
191
- 输出简短状态通知:
192
-
193
- ```
194
- 实施已全部完成并验证通过。
195
- 正在调用 git-pr-ship 交付 PR...
196
- ```
197
-
198
- ## 注意事项
199
-
200
- - 设计文档内容完全来自对话上下文,不臆造未讨论过的需求
201
- - critic 修复只改事实错误和惯例偏差,不改变用户已确认的设计决策
202
- - 如果 critic 发现的问题数量极多(>10 个错误级),在修复后可考虑再跑一轮 critic 确认
203
- - 整个流程对用户透明——每步开始时输出一行状态(如"正在撰写设计文档..."),但不等待确认
@@ -1,430 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- MAX_ROUNDS=3
5
- while [[ $# -gt 0 ]]; do
6
- case "$1" in
7
- --max-rounds)
8
- MAX_ROUNDS="${2:-3}"
9
- shift 2
10
- ;;
11
- *)
12
- shift
13
- ;;
14
- esac
15
- done
16
-
17
- if ! [[ "$MAX_ROUNDS" =~ ^[0-9]+$ ]] || [[ "$MAX_ROUNDS" -lt 1 ]]; then
18
- echo "[doctor] --max-rounds 必须是正整数" >&2
19
- exit 2
20
- fi
21
-
22
- CACHE_ROOT="${PWD}/.cache/doctor"
23
- mkdir -p "$CACHE_ROOT"
24
- CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
25
-
26
- LAST_CHECK_DIR=""
27
- DX_FORCE_OK=0
28
- DX_FORCE_MSG=""
29
-
30
- run_silent() {
31
- "$@" >/dev/null 2>&1
32
- }
33
-
34
- detect_pkg_manager() {
35
- if command -v brew >/dev/null 2>&1; then echo "brew"; return; fi
36
- if command -v apt-get >/dev/null 2>&1; then echo "apt"; return; fi
37
- if command -v dnf >/dev/null 2>&1; then echo "dnf"; return; fi
38
- if command -v yum >/dev/null 2>&1; then echo "yum"; return; fi
39
- if command -v pacman >/dev/null 2>&1; then echo "pacman"; return; fi
40
- echo "none"
41
- }
42
-
43
- install_python3() {
44
- local pm
45
- pm="$(detect_pkg_manager)"
46
- case "$pm" in
47
- brew)
48
- brew install python
49
- ;;
50
- apt)
51
- sudo apt-get update && sudo apt-get install -y python3 python3-venv python3-pip
52
- ;;
53
- dnf)
54
- sudo dnf install -y python3 python3-pip
55
- ;;
56
- yum)
57
- sudo yum install -y python3 python3-pip
58
- ;;
59
- pacman)
60
- sudo pacman -Sy --noconfirm python
61
- ;;
62
- *)
63
- echo "未检测到可用包管理器,无法安装 python3" >&2
64
- return 1
65
- ;;
66
- esac
67
- }
68
-
69
- ensure_python_alias() {
70
- local py3 target_dir target py_major
71
- py3="$(command -v python3 || true)"
72
- if [[ -z "$py3" ]]; then
73
- echo "python3 不存在,无法创建 python 别名" >&2
74
- return 1
75
- fi
76
-
77
- if command -v python >/dev/null 2>&1; then
78
- py_major="$(python -c 'import sys; print(sys.version_info[0])' 2>/dev/null || true)"
79
- if [[ "$py_major" == "3" ]]; then
80
- return 0
81
- fi
82
- fi
83
-
84
- # 避免污染系统/工具链目录,统一落到用户态目录。
85
- target_dir="$HOME/.local/bin"
86
- mkdir -p "$target_dir"
87
- target="$target_dir/python"
88
- ln -sf "$py3" "$target"
89
-
90
- if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
91
- export PATH="$HOME/.local/bin:$PATH"
92
- fi
93
-
94
- py_major="$(python -c 'import sys; print(sys.version_info[0])' 2>/dev/null || true)"
95
- [[ "$py_major" == "3" ]]
96
- }
97
-
98
- install_rg() {
99
- local pm
100
- pm="$(detect_pkg_manager)"
101
- case "$pm" in
102
- brew)
103
- brew install ripgrep
104
- ;;
105
- apt)
106
- sudo apt-get update && sudo apt-get install -y ripgrep
107
- ;;
108
- dnf)
109
- sudo dnf install -y ripgrep
110
- ;;
111
- yum)
112
- sudo yum install -y ripgrep
113
- ;;
114
- pacman)
115
- sudo pacman -Sy --noconfirm ripgrep
116
- ;;
117
- *)
118
- echo "未检测到可用包管理器,无法安装 rg" >&2
119
- return 1
120
- ;;
121
- esac
122
- }
123
-
124
- install_pnpm() {
125
- if command -v pnpm >/dev/null 2>&1; then
126
- return 0
127
- fi
128
-
129
- if command -v npm >/dev/null 2>&1; then
130
- npm install -g pnpm@latest
131
- elif command -v brew >/dev/null 2>&1; then
132
- brew install pnpm
133
- else
134
- echo "缺少 npm/brew,无法安装 pnpm" >&2
135
- return 1
136
- fi
137
- }
138
-
139
- persist_user_local_bin_path() {
140
- local line='export PATH="$HOME/.local/bin:$PATH"'
141
- local rc
142
- for rc in "$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.profile"; do
143
- if [[ -f "$rc" ]]; then
144
- if ! grep -F "$line" "$rc" >/dev/null 2>&1; then
145
- printf '\n%s\n' "$line" >>"$rc"
146
- fi
147
- fi
148
- done
149
- }
150
-
151
- expose_dx_globally() {
152
- local source_dx="$1"
153
- local target_dir target_path
154
-
155
- if [[ ! -x "$source_dx" ]]; then
156
- echo "dx 源可执行文件不存在:$source_dx" >&2
157
- return 1
158
- fi
159
-
160
- target_dir=""
161
- if [[ -w "/usr/local/bin" ]]; then
162
- target_dir="/usr/local/bin"
163
- elif [[ -w "/opt/homebrew/bin" ]]; then
164
- target_dir="/opt/homebrew/bin"
165
- else
166
- target_dir="$HOME/.local/bin"
167
- mkdir -p "$target_dir"
168
- if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
169
- export PATH="$HOME/.local/bin:$PATH"
170
- fi
171
- persist_user_local_bin_path
172
- fi
173
-
174
- target_path="$target_dir/dx"
175
- ln -sf "$source_dx" "$target_path"
176
- command -v dx >/dev/null 2>&1
177
- }
178
-
179
- ensure_agent_browser() {
180
- # 优先使用用户态 pnpm,减少全局权限问题。
181
- if command -v pnpm >/dev/null 2>&1; then
182
- pnpm add -g agent-browser@latest
183
- elif command -v npm >/dev/null 2>&1; then
184
- npm install -g agent-browser@latest
185
- elif command -v brew >/dev/null 2>&1; then
186
- brew install agent-browser
187
- else
188
- echo "缺少 npm/pnpm/brew,无法安装 agent-browser" >&2
189
- return 1
190
- fi
191
-
192
- if ! command -v agent-browser >/dev/null 2>&1; then
193
- local pnpm_bin npm_prefix
194
- pnpm_bin="$(pnpm bin -g 2>/dev/null || true)"
195
- npm_prefix="$(npm prefix -g 2>/dev/null || true)"
196
- echo "agent-browser 安装后仍不可用,请检查 PATH(pnpm: ${pnpm_bin:-N/A},npm: ${npm_prefix:-N/A}/bin)" >&2
197
- return 1
198
- fi
199
-
200
- if ! run_silent agent-browser install; then
201
- run_silent agent-browser install --with-deps || {
202
- echo "agent-browser Chromium 安装失败" >&2
203
- return 1
204
- }
205
- fi
206
- }
207
-
208
- force_dx() {
209
- local pnpm_bin dx_installed dx_cmd
210
- if ! install_pnpm; then
211
- DX_FORCE_OK=0
212
- DX_FORCE_MSG="pnpm 不可用,无法执行 dx 强制初始化"
213
- return 1
214
- fi
215
-
216
- if pnpm add -g @ranger1/dx@latest >/dev/null 2>&1; then
217
- pnpm_bin="$(pnpm bin -g 2>/dev/null || true)"
218
- dx_installed=""
219
- if [[ -n "$pnpm_bin" && -x "$pnpm_bin/dx" ]]; then
220
- dx_installed="$pnpm_bin/dx"
221
- elif command -v dx >/dev/null 2>&1; then
222
- dx_installed="$(command -v dx)"
223
- fi
224
-
225
- if [[ -z "$dx_installed" ]]; then
226
- DX_FORCE_OK=0
227
- DX_FORCE_MSG="dx 安装后未找到可执行文件(pnpm bin: ${pnpm_bin:-N/A})"
228
- return 1
229
- fi
230
-
231
- if ! expose_dx_globally "$dx_installed"; then
232
- DX_FORCE_OK=0
233
- DX_FORCE_MSG="dx 已安装但未能暴露为全局命令(pnpm bin: ${pnpm_bin:-N/A})"
234
- return 1
235
- fi
236
-
237
- dx_cmd="$(command -v dx || true)"
238
- if [[ -n "$dx_cmd" ]] && dx initial >/dev/null 2>&1; then
239
- DX_FORCE_OK=1
240
- DX_FORCE_MSG="已安装并暴露全局 dx(${dx_cmd}),并执行 dx initial"
241
- return 0
242
- fi
243
-
244
- DX_FORCE_OK=0
245
- DX_FORCE_MSG="dx 已暴露为全局命令但 dx initial 执行失败(dx: ${dx_cmd:-N/A})"
246
- return 1
247
- fi
248
-
249
- DX_FORCE_OK=0
250
- DX_FORCE_MSG="强制命令执行失败:pnpm add -g @ranger1/dx@latest"
251
- return 1
252
- }
253
-
254
- write_check_file() {
255
- local key="$1" ok="$2" ver="$3" msg="$4" file="$5"
256
- printf '%s|%s|%s|%s\n' "$key" "$ok" "$ver" "$msg" >"$file"
257
- }
258
-
259
- read_field() {
260
- local key="$1" field="$2"
261
- local f="$LAST_CHECK_DIR/${key}.res"
262
- if [[ ! -f "$f" ]]; then
263
- echo ""
264
- return 0
265
- fi
266
- awk -F'|' -v idx="$field" '{print $idx}' "$f"
267
- }
268
-
269
- check_ok() {
270
- local key="$1"
271
- [[ "$(read_field "$key" 2)" == "1" ]]
272
- }
273
-
274
- run_parallel_checks() {
275
- local round="$1"
276
- local dir="$CACHE_ROOT/round-${round}"
277
- mkdir -p "$dir"
278
-
279
- (
280
- if command -v python3 >/dev/null 2>&1; then
281
- write_check_file "python3" "1" "$(python3 --version 2>&1 | head -n1)" "ok" "$dir/python3.res"
282
- else
283
- write_check_file "python3" "0" "" "python3 未安装" "$dir/python3.res"
284
- fi
285
- ) &
286
-
287
- (
288
- if command -v python >/dev/null 2>&1; then
289
- local py_ver py_major
290
- py_ver="$(python --version 2>&1 | head -n1)"
291
- py_major="$(python -c 'import sys; print(sys.version_info[0])' 2>/dev/null || true)"
292
- if [[ "$py_major" == "3" ]]; then
293
- write_check_file "python_alias" "1" "$py_ver" "ok" "$dir/python_alias.res"
294
- else
295
- write_check_file "python_alias" "0" "$py_ver" "python 存在但不是 Python 3" "$dir/python_alias.res"
296
- fi
297
- else
298
- write_check_file "python_alias" "0" "" "python 别名不可用" "$dir/python_alias.res"
299
- fi
300
- ) &
301
-
302
- (
303
- if command -v pnpm >/dev/null 2>&1; then
304
- write_check_file "pnpm" "1" "pnpm $(pnpm --version 2>/dev/null | head -n1)" "ok" "$dir/pnpm.res"
305
- else
306
- write_check_file "pnpm" "0" "" "pnpm 未安装" "$dir/pnpm.res"
307
- fi
308
- ) &
309
-
310
- (
311
- if command -v dx >/dev/null 2>&1; then
312
- local v
313
- v="$(dx --version 2>/dev/null | head -n1 || true)"
314
- if [[ -z "$v" ]]; then
315
- v="$(dx -v 2>/dev/null | head -n1 || true)"
316
- fi
317
- write_check_file "dx" "1" "${v:-dx (版本未知)}" "ok" "$dir/dx.res"
318
- else
319
- write_check_file "dx" "0" "" "dx 未安装" "$dir/dx.res"
320
- fi
321
- ) &
322
-
323
- (
324
- if command -v agent-browser >/dev/null 2>&1; then
325
- write_check_file "agent_browser" "1" "$(agent-browser --version 2>/dev/null | head -n1)" "ok" "$dir/agent_browser.res"
326
- else
327
- write_check_file "agent_browser" "0" "" "agent-browser 未安装" "$dir/agent_browser.res"
328
- fi
329
- ) &
330
-
331
- (
332
- if command -v rg >/dev/null 2>&1; then
333
- write_check_file "rg" "1" "$(rg --version 2>/dev/null | head -n1)" "ok" "$dir/rg.res"
334
- else
335
- write_check_file "rg" "0" "" "rg 未安装" "$dir/rg.res"
336
- fi
337
- ) &
338
-
339
- wait
340
- LAST_CHECK_DIR="$dir"
341
- }
342
-
343
- all_good() {
344
- local keys="python3 python_alias pnpm dx agent_browser rg"
345
- local k
346
- for k in $keys; do
347
- if ! check_ok "$k"; then
348
- return 1
349
- fi
350
- done
351
- [[ "$DX_FORCE_OK" == "1" ]]
352
- }
353
-
354
- print_report() {
355
- local round="$1"
356
- echo
357
- echo "===== Doctor 报告(第 ${round} 轮)====="
358
- printf '%-14s | %-4s | %-40s | %s\n' "检查项" "状态" "版本" "说明"
359
- printf '%-14s-+-%-4s-+-%-40s-+-%s\n' "--------------" "----" "----------------------------------------" "------------------------------"
360
-
361
- local keys="python3 python_alias pnpm dx agent_browser rg"
362
- local k ok txt ver msg
363
- for k in $keys; do
364
- ok="$(read_field "$k" 2)"
365
- txt="FAIL"
366
- [[ "$ok" == "1" ]] && txt="PASS"
367
- ver="$(read_field "$k" 3)"
368
- msg="$(read_field "$k" 4)"
369
- printf '%-14s | %-4s | %-40s | %s\n' "$k" "$txt" "$ver" "$msg"
370
- done
371
-
372
- if [[ "$DX_FORCE_OK" == "1" ]]; then
373
- printf '%-14s | %-4s | %-40s | %s\n' "dx_force" "PASS" "@ranger1/dx@latest" "$DX_FORCE_MSG"
374
- else
375
- printf '%-14s | %-4s | %-40s | %s\n' "dx_force" "FAIL" "@ranger1/dx@latest" "$DX_FORCE_MSG"
376
- fi
377
-
378
- if command -v node >/dev/null 2>&1; then
379
- echo "node: $(node -v 2>/dev/null | head -n1)"
380
- fi
381
- if command -v npm >/dev/null 2>&1; then
382
- echo "npm: $(npm -v 2>/dev/null | head -n1)"
383
- fi
384
- }
385
-
386
- for round in $(seq 1 "$MAX_ROUNDS"); do
387
- echo "[doctor] 第 ${round}/${MAX_ROUNDS} 轮:并行检测"
388
- run_parallel_checks "$round"
389
-
390
- echo "[doctor] 第 ${round}/${MAX_ROUNDS} 轮:修复阶段"
391
-
392
- if ! check_ok "python3"; then
393
- echo "[doctor] 安装 python3"
394
- install_python3 || true
395
- fi
396
-
397
- if ! check_ok "python_alias"; then
398
- echo "[doctor] 建立 python -> python3 调用能力"
399
- ensure_python_alias || true
400
- fi
401
-
402
- if ! check_ok "rg"; then
403
- echo "[doctor] 安装 rg"
404
- install_rg || true
405
- fi
406
-
407
- if ! check_ok "agent_browser"; then
408
- echo "[doctor] 安装/升级 agent-browser 并安装 Chromium"
409
- ensure_agent_browser || true
410
- else
411
- echo "[doctor] agent-browser 已存在,执行升级与 Chromium 安装"
412
- ensure_agent_browser || true
413
- fi
414
-
415
- echo "[doctor] 强制执行 dx 安装与初始化"
416
- force_dx || true
417
-
418
- echo "[doctor] 第 ${round}/${MAX_ROUNDS} 轮:复检"
419
- run_parallel_checks "${round}-post"
420
- print_report "$round"
421
-
422
- if all_good; then
423
- echo "[doctor] 全部检查通过"
424
- exit 0
425
- fi
426
-
427
- done
428
-
429
- echo "[doctor] 达到最大轮次 ${MAX_ROUNDS},仍有未通过项"
430
- exit 1