create-dwy 0.19.1 → 0.20.0

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 (98) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/package.json +1 -1
  3. package/src/cli-help.js +28 -2
  4. package/src/sync-all.js +95 -583
  5. package/src/sync-codex.js +14 -7
  6. package/src/sync-opencode.js +8 -22
  7. package/src/sync.js +60 -149
  8. package/src/tab-multiselect.js +15 -53
  9. package/templates/ai-tools/CHANGELOG.md +195 -0
  10. package/templates/ai-tools/CLAUDE.md +39 -58
  11. package/templates/ai-tools/VERSION +1 -1
  12. package/templates/ai-tools/hooks/Git/pre-git-commit-ai-signature-check.sh +5 -4
  13. package/templates/ai-tools/rules/Android/dwy-android-core.md +147 -13
  14. package/templates/ai-tools/rules/Android/dwy-android-layering.md +142 -0
  15. package/templates/ai-tools/rules/Android/dwy-android-mvp.md +55 -0
  16. package/templates/ai-tools/rules/Android/dwy-android-support-only.md +2 -0
  17. package/templates/ai-tools/rules/Docker/dwy-docker.md +23 -1
  18. package/templates/ai-tools/rules/Flutter/dwy-flutter-core.md +2 -0
  19. package/templates/ai-tools/rules/Flutter/dwy-flutter-testing.md +1 -1
  20. package/templates/ai-tools/rules/HarmonyOS/dwy-arkts-ui-build.md +12 -8
  21. package/templates/ai-tools/rules/Python/dwy-python-backend.md +4 -43
  22. package/templates/ai-tools/rules/Python/dwy-python-layering.md +169 -0
  23. package/templates/ai-tools/rules/Vue/dwy-vue-core.md +11 -49
  24. package/templates/ai-tools/rules/Vue/dwy-vue-layering.md +153 -0
  25. package/templates/ai-tools/rules/iOS/dwy-apple-layering.md +133 -0
  26. package/templates/ai-tools/rules/iOS/dwy-swift-core.md +2 -0
  27. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-code-craft.md +83 -0
  28. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-dependency-freshness.md +27 -66
  29. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-git-commit.md +8 -219
  30. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-oss-commercial-license.md +27 -123
  31. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-prod-branch.md +31 -0
  32. package/templates/ai-tools/rules//346/225/260/346/215/256/345/272/223/dwy-postgres.md +17 -10
  33. package/templates/ai-tools/rules//346/225/260/346/215/256/345/272/223/dwy-redis.md +6 -3
  34. package/templates/ai-tools/skills/Docker/dwy-deploy-first/SKILL.md +14 -14
  35. package/templates/ai-tools/skills/Docker/dwy-deploy-first/references/chapter-01-mirrors.md +2 -2
  36. package/templates/ai-tools/skills/Docker/dwy-docker/SKILL.md +21 -13
  37. package/templates/ai-tools/skills/Docker/dwy-docker/references/ask-templates.md +13 -12
  38. package/templates/ai-tools/skills/Docker/dwy-docker/references/templates.md +3 -1
  39. package/templates/ai-tools/skills/Docker/dwy-docker/references/version-rules.md +10 -6
  40. package/templates/ai-tools/skills/Docker/dwy-docker/scripts/query_dockerhub.py +21 -6
  41. package/templates/ai-tools/skills/Docker/dwy-docker/scripts/scan_images.sh +2 -2
  42. package/templates/ai-tools/skills/Docker/dwy-mirror-source/SKILL.md +44 -30
  43. package/templates/ai-tools/skills/Docker/dwy-mirror-source/references/dockerfile-snippets.md +2 -0
  44. package/templates/ai-tools/skills/Docker/dwy-mirror-source/references/mirror-providers.md +8 -8
  45. package/templates/ai-tools/skills/Docker/dwy-mirror-source/scripts/apply_mirrors.py +14 -1
  46. package/templates/ai-tools/skills/Docker/dwy-mirror-source/scripts/check_mirrors.py +4 -0
  47. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/SKILL.md +8 -6
  48. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/digest/python-sdk.md +3 -3
  49. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/digest/stream-engine.md +2 -2
  50. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/anti-patterns.md +3 -1
  51. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/change-checklist.md +4 -4
  52. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/lethal-violations.md +5 -5
  53. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/perf-baselines.md +5 -5
  54. package/templates/ai-tools/skills/Python/dwy-eapi/SKILL.md +2 -2
  55. package/templates/ai-tools/skills/Python/dwy-eapi/v0/breaking.md +3 -0
  56. package/templates/ai-tools/skills/Python/dwy-eapi/v0/email-canonical.md +28 -3
  57. package/templates/ai-tools/skills/Python/dwy-eapi/v0/index.md +2 -2
  58. package/templates/ai-tools/skills/Python/dwy-eapi/v0/providers-email.md +12 -2
  59. package/templates/ai-tools/skills/Vue/dwy-eui/references/eui-design-guide.md +1 -1
  60. package/templates/ai-tools/skills//344/272/247/345/223/2010/345/210/2601/dwy-architecture/SKILL.md +11 -14
  61. package/templates/ai-tools/skills//344/272/247/345/223/2010/345/210/2601/dwy-product-launcher/references/state-and-contract.md +1 -1
  62. package/templates/ai-tools/skills//344/272/247/345/223/2010/345/210/2601/dwy-prototype/SKILL.md +1 -1
  63. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-github-action-publish/SKILL.md +32 -15
  64. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-github-action-publish/references/electron-release-workflow-template.yml +3 -1
  65. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-github-action-publish/references/release-workflow-template.yml +8 -5
  66. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/SKILL.md +1 -1
  67. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/assets/appstore-submission.yaml +1 -1
  68. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/aso.md +2 -0
  69. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/in-app-purchase-review.md +1 -1
  70. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/SKILL.md +4 -3
  71. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/android.md +1 -1
  72. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/backend-deploy.md +1 -1
  73. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/changelog.md +45 -27
  74. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/frontend-deploy.md +1 -1
  75. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/generic-release.md +1 -1
  76. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/git-tag.md +1 -1
  77. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/harmony.md +1 -1
  78. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/ios.md +1 -1
  79. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-semver/SKILL.md +8 -0
  80. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/SKILL.md +7 -7
  81. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/references/checks-runtime.md +63 -59
  82. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_base.sh +10 -1
  83. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_capacity.sh +21 -23
  84. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_db.sh +9 -1
  85. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_docker.sh +20 -24
  86. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_logs.sh +3 -3
  87. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/SKILL.md +4 -2
  88. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/references/api.md +1 -1
  89. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/synthesize.py +1 -0
  90. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/SKILL.md +7 -5
  91. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/references/platform-copy-examples.md +5 -3
  92. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-dependency-choice/SKILL.md +140 -0
  93. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-git-commit/SKILL.md +113 -0
  94. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-shared/SKILL.md +16 -13
  95. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-whiteboard-prototype/SKILL.md +1 -1
  96. package/src/sync-packs.js +0 -223
  97. package/src/sync-scene.js +0 -178
  98. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-tdd-development.md +0 -115
@@ -1,25 +1,41 @@
1
- # CHANGELOG 按平台子目录各写一份
1
+ # 发版时按项目写 CHANGELOG
2
2
 
3
- monorepo 下一个仓库可能同时含 android / ios / harmony / frontend / backend 多平台。**每个平台维护自己的 CHANGELOG,不写全局单份**。发哪个平台,只写哪个平台那份。
3
+ 只在发版写。不发版不写、不升版本。
4
4
 
5
- ## 各平台 CHANGELOG 位置
5
+ 工厂是这次发版的 git 仓库根。工厂下可以有多个项目。每个项目可以各自有前端和后端。changelog 写在那一端自己的目录里。
6
6
 
7
- - `android/CHANGELOG.md`
8
- - `ios/CHANGELOG.md`
9
- - `harmony/CHANGELOG.md`
10
- - `frontend/CHANGELOG.md`
11
- - `backend/CHANGELOG.md`
7
+ ## 先列出要写的端
12
8
 
13
- 子目录名按仓库实际结构定(先在第 0 步识别平台目录)。单包仓库可在根目录一份;monorepo 按包目录(如 `dwy-cli/CHANGELOG.md`、`frontend/eui/CHANGELOG.md`)。
9
+ 1. 找出项目。一个项目是含有可独立发版的前端和/或后端的目录。常见是 `<项目>/frontend` 与 `<项目>/backend`。仓库根下直接就是这两端时,根就是这一个项目。目录名按仓库实际结构认,不套死 `frontend` / `backend` 这两个词。
10
+ 2. 一端算存在:该目录有自己的版本来源(前端看 `package.json` 的 `version`,后端看 `pyproject.toml` 的 `version`),或有该端的应用入口。没有这一端就不写。
11
+ 3. 决定哪些端要写:
12
+ - 用户点名了项目或端:只写点名的。
13
+ - 没点名:该端目录自上次 release tag 以来有提交才写。没有上次 tag 时,看这次准备发布的提交是否改过该目录。
14
+
15
+ ```bash
16
+ git log <该端上次 tag>..HEAD --oneline -- <项目>/<端>/
17
+ ```
18
+
19
+ 4. 没有提交的端不写、不升版本、不打 tag。
20
+ 5. 写之前先列出清单:项目、端、changelog 路径、有没有变更。清单里该写的还没写完,不进入 tag。
21
+
22
+ 该项目下若还有 android / ios / harmony,同样各算一端,不写进前后端的 changelog。
23
+
24
+ ## 落点
25
+
26
+ - `<项目>/frontend/CHANGELOG.md`
27
+ - `<项目>/backend/CHANGELOG.md`
28
+
29
+ 只有一端的项目只写存在的那一端。不要在工厂根再写一份总表。
14
30
 
15
31
  ## 版本标题格式(与 git tag 对齐)
16
32
 
17
- 新版本必须用二级标题,版本串单独成标题,供第 6 步打 tag 原样取用:
33
+ 新版本必须用二级标题,版本串单独成标题,供打 tag 原样取用:
18
34
 
19
35
  ```markdown
20
- # <包标识> ← monorepo 建议有 H1,作为 tag 的包前缀(如 create-dwy、@dwydev/eui)
36
+ # <包标识> ← 作为 tag 的包前缀(如 shop-frontend、@acme/api)
21
37
 
22
- ## 0.16.1 ← 新版本标题;tag 版本串必须与此完全一致
38
+ ## 0.16.1 ← 新版本标题;这一份 changelog 的 tag 版本串必须与此完全一致
23
39
 
24
40
  ### Patch Changes
25
41
 
@@ -28,30 +44,32 @@ monorepo 下一个仓库可能同时含 android / ios / harmony / frontend / bac
28
44
 
29
45
  约束:
30
46
 
31
- - 标题里只写 SemVer 版本串(可含预发布,如 `1.0.0-rc.1`),不要写 `v0.16.1`、日期或其它后缀
32
- - 该版本串 = 版本来源文件里的 version = 即将打的 tag 中的版本部分(见 `git-tag.md`)
47
+ - 标题里只写 SemVer 版本串,不要写 `v0.16.1`、日期或其它后缀
48
+ - 从 `develop` 发:标题是 `x.y.z-beta.N` 或 `x.y.z-rc.N`。从 `preview` 发正式版:标题是 `x.y.z`,不带预发布
49
+ - 该版本串 = 这一端版本来源文件里的 version = 这一份 changelog 即将打的 tag 中的版本部分(见 `git-tag.md`)
50
+ - 各端版本号各自维护。前端升了,不表示后端也要升
33
51
 
34
52
  ## 写法
35
53
 
36
- 1. 找该平台上一个 release tag
37
- 2. 按平台子目录过滤 commit:
38
-
39
- ```bash
40
- git log <last-tag>..HEAD --oneline -- <平台子目录>/
41
- ```
42
-
54
+ 1. 找这一端的上一个 release tag
55
+ 2. 只取这一端目录里的 commit(命令见上)
43
56
  3. 按 `feat` / `fix` / `refactor` / `chore` 分组
44
- 4. 写入该平台 `CHANGELOG.md`,用 `## <新版本号>` 标注(格式见上)
57
+ 4. 写入这一端的 `CHANGELOG.md`,用 `## <新版本号>` 标注
58
+
59
+ 仓库已有自动生成命令(changelogen 等)时优先使用。仍然只覆盖这一端的目录,版本标题仍要满足上面的格式。
45
60
 
46
- 如果仓库已有自动生成命令(changelogen 等),优先使用,但仍按平台目录过滤范围,且产出的版本标题须满足上述格式。
61
+ 写了几份 changelog,就按 `git-tag.md` 各打一个 tag。不要合成一个工厂级 tag。
47
62
 
48
63
  ## 自动执行
49
64
 
50
- changelog 由 AI 自动生成并写入,不强制逐步确认。仅当 commit 历史无法清晰归类、或平台目录边界不明时才停下问用户。
65
+ changelog 由 AI 生成并写入,不逐步确认。只有 commit 无法归类,或分不清项目边界时才问用户。
51
66
 
52
67
  ## 禁止
53
68
 
54
- - 禁止写一份全局 CHANGELOG 混入多平台变更
69
+ - 禁止在工厂根写一份总 CHANGELOG,把多个项目或前端后端混在一起
70
+ - 禁止只写了其中一个项目就进入 tag
71
+ - 禁止把 A 项目的 commit 写进 B 项目
72
+ - 禁止把前端的 commit 写进后端,或反过来
73
+ - 禁止给没有变更的端写一份空版本
55
74
  - 禁止 changelog 未写完就进入 tag / 部署
56
- - 禁止把其他平台的 commit 写进当前平台 CHANGELOG(必须按目录过滤)
57
- - 禁止版本标题写成与即将打的 tag 版本串不一致的形式
75
+ - 禁止版本标题与这一份即将打的 tag 版本串不一致
@@ -19,6 +19,6 @@
19
19
 
20
20
  ## changelog / tag / 监控
21
21
 
22
- - changelog → `changelog.md`(写 `frontend/CHANGELOG.md`)
22
+ - changelog → `changelog.md`(写该项目的 `frontend/CHANGELOG.md`;工厂里多个项目时每个项目各一份)
23
23
  - tag → `git-tag.md`(每次 bump 必打;版本串与 changelog `##` 标题一致)
24
24
  - 监控 + verify → `monitor-notify.md`(前端信号:页面访问 / 版本接口 / 产物 hash / CDN 刷新)
@@ -22,7 +22,7 @@
22
22
 
23
23
  ## changelog / tag / 安全检查 / 监控
24
24
 
25
- - changelog → `changelog.md`(单包仓库根目录一份;monorepo 按包目录过滤)
25
+ - changelog → `changelog.md`(单包仓库根目录一份;应用工厂按每个项目的前端/后端分写)
26
26
  - tag → `git-tag.md`(每次 bump 必打;版本串与 changelog `##` 标题一致;monorepo 例:`@dwydev/eui@2.2.3`、`create-dwy@0.16.1`)
27
27
  - 安全检查 → `../dwy-sdk-spec`(对外包必查泄露/产物)
28
28
  - 监控 + verify → `monitor-notify.md`(包仓库版本查询 / GitHub Release)
@@ -19,7 +19,7 @@ git push origin <tag>
19
19
 
20
20
  ## tag 与 changelog 版本对齐(硬规则)
21
21
 
22
- tag 中的**版本串**必须与本次 CHANGELOG **新版本标题**完全一致,禁止改写。
22
+ tag 中的**版本串**必须与这一份 CHANGELOG **新版本标题**完全一致,禁止改写。第 4 步写了几份,就各打一个 tag,版本串对应该份标题。
23
23
 
24
24
  | CHANGELOG 写法 | 取出的版本串 |
25
25
  |----------------|-------------|
@@ -20,7 +20,7 @@
20
20
 
21
21
  ## changelog / tag / 安全检查 / 监控
22
22
 
23
- - changelog → `changelog.md`(写 `harmony/CHANGELOG.md`)
23
+ - changelog → `changelog.md`(写该项目的 `harmony/CHANGELOG.md`;工厂里多个项目时每个项目各一份)
24
24
  - tag → `git-tag.md`(每次 bump 必打;版本串与 changelog `##` 标题一致)
25
25
  - 安全检查 → `../dwy-sdk-spec`
26
26
  - 监控 + 结果 → `monitor-notify.md`
@@ -27,7 +27,7 @@
27
27
 
28
28
  ## changelog / tag / 安全检查 / 监控
29
29
 
30
- - changelog → `changelog.md`(写 `ios/CHANGELOG.md`)
30
+ - changelog → `changelog.md`(写该项目的 `ios/CHANGELOG.md`;工厂里多个项目时每个项目各一份)
31
31
  - tag → `git-tag.md`(每次 bump 必打;版本串与 changelog `##` 标题一致)
32
32
  - 安全检查 → `../dwy-sdk-spec`(SDK 发布尤其要查泄露)
33
33
  - 监控 + 结果 → `monitor-notify.md`
@@ -87,6 +87,14 @@ description: "语义化版本号(SemVer 2.0.0)决策助手。涉及以下任
87
87
 
88
88
  预发布优先级排序、版本比较 11 条规则等细节见 [references/semver-spec.md](references/semver-spec.md)。
89
89
 
90
+ ## 分支上用哪个号
91
+
92
+ 只认两条长期分支,和 `rules/开发流程/dwy-prod-branch.md` 同一条。不在发版时不要为了这条去改版本号。
93
+
94
+ - 在 `develop` 发:必须带 `-beta` 或 `-rc`。还在改用 `beta`,准备进 `preview` 用 `rc`。
95
+ - 在 `preview` 发正式版:不带预发布。`rc` 收成正式号时用 `bump.py` 转到正式版。
96
+ - 仓库没有这两条分支:先告诉用户,不要改用 `main` 充当正式分支。
97
+
90
98
  ## 算出具体版本号
91
99
 
92
100
  `scripts/bump.py` 按 SemVer 归零规则与 node-semver 预发布语义计算,避免手算出错:
@@ -278,9 +278,9 @@ bash {scripts}/check_db.sh <target> [ssh_opts...]
278
278
 
279
279
  ### 4.10 硬件识别与资源推荐 — `{scripts}/check_capacity.sh`
280
280
 
281
- 输出宿主硬件规格 + 当前容器 mem_limit + Postgres/Redis 启动参数 + compose 资源声明;主 Claude 对照分级表生成"推荐 vs 当前"对比报告。
281
+ 输出宿主硬件、容器硬限、`docker stats` 单帧、Postgres/Redis 参数、compose 声明。报告写「本次实测 vs 当前硬限」。冷启动先验表只在没有占用和日志增量时使用。
282
282
 
283
- → 容器资源推荐分级表、配比原则、对比报告格式、严重等级标记与日志大小推荐分级表见 `references/checks-runtime.md` §「4.10 硬件识别与资源推荐」
283
+ → 判定见 `references/checks-runtime.md` §「4.10 硬件识别与资源」
284
284
 
285
285
  ### 4.11 凭证强度审计 — `{scripts}/check_secrets.sh`
286
286
 
@@ -392,8 +392,8 @@ bash {scripts}/check_db.sh <target> [ssh_opts...]
392
392
  ### 4.9 日志大小与防爆检查 (7/9 ✅)
393
393
  [...]
394
394
 
395
- ### 4.10 硬件识别与资源推荐 (容器资源 5/7 + 日志推荐 4/5)
396
- **包含"推荐 vs 当前"对比表(见 references/checks-runtime.md §4.10),保留原对比格式**
395
+ ### 4.10 硬件识别与资源 (容器资源 + 日志轮转)
396
+ **写「本次实测 vs 当前硬限」。没有实测才注明用了冷启动先验。不要因为没贴近先验表判失败。**
397
397
 
398
398
  ### 4.11 凭证强度审计 (12/15 ✅)
399
399
 
@@ -464,9 +464,9 @@ bash {scripts}/check_db.sh <target> [ssh_opts...]
464
464
 
465
465
  根据本次失败项归纳的可执行后续动作:
466
466
 
467
- - 镜像版本不固定 (4.6) → 跑 `/dwy-docker` 选 N-1 minor
468
- - daemon 未配 registry-mirrors (4.6) → 跑 `/dwy-mirror-source` 写国内源
469
- - 容器资源偏离推荐 (4.10) → 改 `docker-compose.prod.yml` 的 mem_limit/maxmemory
467
+ - 镜像版本不固定 (4.6) → 跑 `/dwy-docker`,按当次 tag 列表固定;N-1 只是偏好
468
+ - daemon 未配 registry-mirrors,或只是名单里有某个国内域名 (4.6) → 跑 `/dwy-mirror-source`。名单里有源不算通过。当次测延迟和内容。私有库不参加公网竞速
469
+ - 容器无内存硬限,或硬限低于实测占用 (4.10) → 按这次的 `docker stats` 和日志增速改 `mem_limit` / `maxmemory` / `log-opts`,不套用先验表数字
470
470
  - ...
471
471
 
472
472
  ---
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **何时读这份:** 当 AI 即将运行 4.6 / 4.8 / 4.9 / 4.10 类检查或解读其输出时读取本文件。
4
4
 
5
- 本文件聚焦"运行时与韧性"维度的检查规则、严重度判定与输出格式。涵盖 Docker 安全、自愈与资源耗尽防护、日志大小与防爆、硬件识别与资源推荐。
5
+ 本文件聚焦"运行时与韧性"维度的检查规则、严重度判定与输出格式。涵盖 Docker 安全、自愈与资源耗尽防护、日志大小与防爆、硬件与容器资源。内存和日志的具体数字是冷启动先验,有实测就不用表。
6
6
 
7
7
  脚本目录简称 `{scripts}` = `../scripts/`。
8
8
 
@@ -11,8 +11,8 @@
11
11
  ## 4.6 Docker 安全 — `{scripts}/check_docker.sh`
12
12
 
13
13
  > **跨 skill 联动**:本节发现的镜像版本/镜像源问题,只**报告**不修复。具体修复路径:
14
- > - 镜像 tag 不固定 / `:latest` / 浮动 tag → 引导用户跑 `/dwy-docker`(走 query_dockerhub.py 选 N-1 minor)
15
- > - daemon 未配 registry-mirrors / 容器用境外 registry → 引导用户跑 `/dwy-mirror-source`(写阿里云/中科大/daocloud)
14
+ > - 镜像 tag 不固定 / `:latest` / 浮动 tag → 引导用户跑 `/dwy-docker`(当次列出 tag 再固定,N-1 只是偏好)
15
+ > - daemon 未配 registry-mirrors / 容器用境外 registry → 引导用户跑 `/dwy-mirror-source`(当次探测后取延迟最低的源)
16
16
 
17
17
  | 检查项 | 期望值 | 严重级 |
18
18
  |--------|--------|--------|
@@ -30,9 +30,9 @@
30
30
  | 容器 `RestartPolicy` | `always` 或 `unless-stopped`(**服务器重启后自动起来**) | **critical** |
31
31
  | 容器 `RestartPolicy=no` 但正在 running | 不允许(重启会丢) | **critical** |
32
32
  | 容器 `RestartPolicy=on-failure` | 不推荐(手动 stop / OOM 后不会重启) | high |
33
- | daemon 日志驱动 `log-opts.max-size` | 已配置(≤ 100m,防容器日志写满磁盘) | high |
34
- | **daemon `registry-mirrors`**(时区在 PRC 时) | 至少 1 个国内源(daocloud / aliyun / ustc / tsinghua) | high(PRC 无配置)/ info(境外) |
35
- | **运行容器使用境外 registry**(`gcr.io` `ghcr.io` `k8s.gcr.io` `quay.io` `mcr.microsoft.com` `nvcr.io` `docker.elastic.co`)且时区在 PRC | 改用 `<registry>.m.daocloud.io` 前缀(`registry-mirrors` **不**对它们生效) | high |
33
+ | daemon 日志驱动 `log-opts.max-size` | 已配置上限。数字按实测日志增速,不要求 ≤ 100m | high(未配置) |
34
+ | **daemon `registry-mirrors`** | 名单里有 daocloud / aliyun / ustc 不算通过。合格看当次对 Registry API 的延迟和内容。未配置时提示去探测,不因为没写某个国内源判失败。私有库或用户指定源不参加公网竞速 | info |
35
+ | **运行容器使用境外 registry**(`gcr.io` `ghcr.io` `k8s.gcr.io` `quay.io` `mcr.microsoft.com` `nvcr.io` `docker.elastic.co`)且时区在 PRC | 改用当次探测选出的国内前缀(`registry-mirrors` **不**对它们生效)。DaoCloud 前缀只是当前候选。私有库不改前缀 | high |
36
36
 
37
37
  **Docker 版本与暴露面判定补充:**
38
38
 
@@ -93,23 +93,40 @@
93
93
  |--------|--------|--------|
94
94
  | Docker 单容器 `*-json.log` 大小 | < 500 MB(daemon 配 log-opts max-size 时自动控) | high(>500 MB) / critical(>1 GB 且 daemon 无 log-opts) |
95
95
  | 容器自身 `LogConfig.Config` 覆盖 | 至少有 `max-size`,否则继承 daemon | high(容器 + daemon 都没配) |
96
- | Docker daemon `log-opts.max-size` | 已配置 ≤ 100m | high(同 check_docker.sh,本节关联展开) |
96
+ | Docker daemon `log-opts.max-size` | 已配置上限。数字按本节实测增速,不要求 ≤ 100m | high(未配置) |
97
97
  | Nginx access.log / error.log 单文件 | < 500 MB | high |
98
98
  | `/etc/logrotate.d/nginx` | 存在 | high |
99
99
  | `journalctl --disk-usage` | < 2 GB | medium / high(≥ 2 GB 且 SystemMaxUse 未配) |
100
100
  | `/etc/systemd/journald.conf` `SystemMaxUse` | 已显式配置 | low |
101
101
  | 应用日志目录(`/var/log/<svc>` / `/opt/*/logs` / `/home/*/logs` / `/srv/*/logs`) | 列出 Top 10 供人工核对 | info |
102
- | 日志按当前 docker 容器存活时长粗估的撑天数 | > 90 天 | high(<90) / critical(<30) |
102
+ | 日志按当前 docker 容器存活时长粗估的撑天数 | 按实测增速,写满根盘前有人处理。30 / 90 天是告警线,不是要配成的保留天数 | high(<90) / critical(<30) |
103
103
 
104
104
  **输出规约:** 脚本会汇总 `Docker json-log + Nginx + journal + 应用日志` 总占用,对照根盘可用空间,给出"按 docker 当前增速预计可撑 N 天"的粗估。粗估只算 docker json-log 增量,不含数据库/应用日志业务增量,因此**结论偏乐观**,作为下限警示使用。
105
105
 
106
106
  ---
107
107
 
108
- ## 4.10 硬件识别与资源推荐 — `{scripts}/check_capacity.sh`
108
+ ## 4.10 硬件识别与资源 — `{scripts}/check_capacity.sh`
109
109
 
110
- > 脚本只输出 raw(硬件规格 + 当前容器 mem_limit + Postgres/Redis 启动参数 + compose 资源声明);主 Claude 用下表生成 "推荐 vs 当前" 对比报告。详细推荐规则与配比公式参考 `dwy-docker` skill 第二部分。
110
+ 脚本输出宿主规格、容器硬限、`docker stats` 单帧占用、Postgres/Redis 参数、compose 声明、日志日增量能对上的根盘剩余。报告写「本次实测 vs 当前硬限」。**禁止**把下面的数字写成应改成的配额。
111
111
 
112
- **容器资源推荐分级表(按宿主总内存)**
112
+ 必须成立的只有这些:
113
+
114
+ - 每个容器有内存硬限。关键服务(redis / postgres / mysql / mongo / clickhouse / elasticsearch)没有就是 high
115
+ - Redis 设了 `maxmemory`,且容器 `mem_limit` 大于它。未设或为 0 是 **critical**
116
+ - Postgres `shared_buffers` 不超过宿主总内存的 50%。这是 OOM 天花板,不是目标比例
117
+ - 容器硬限合计不超过宿主总内存的 75%。超过则 OS 没有余量,是 high。不要求贴近 65%
118
+ - 日志有 `max-size` 和 `max-file`。两边都没有是 **critical**
119
+ - 按 `check_logs.sh` 的实测日增量,根盘会在短时间内写满,才收紧轮转。30 天 critical,90 天 high。这是告警线
120
+
121
+ 有 `docker stats` 或日志日增量时,用实测:
122
+
123
+ - 内存硬限低于这一帧占用(或已有的监控峰值)才要加。单帧不是峰值,报告里写明
124
+ - 硬限远高于占用,不是问题,不要为了贴近下表去改小
125
+ - 日志配额按日增量和根盘剩余算。`max-size × max-file × 容器数` 本身就能占掉根盘约 5% 以上,说明天花板太高,是 high。5% 是安全天花板,不是目标占用
126
+
127
+ 没有占用、也没有日志增量(服务刚起)时,才用下面的冷启动先验。服务跑起来之后以实测替换,不把先验写回本文件。
128
+
129
+ **冷启动先验:内存(没有实测时才用)**
113
130
 
114
131
  | 宿主总内存 | Backend mem_limit | Postgres mem_limit / shm_size / shared_buffers / effective_cache_size | Redis mem_limit / maxmemory |
115
132
  |-----------|-------------------|--------------------------------------------------------------------|----------------------------|
@@ -118,83 +135,70 @@
118
135
  | 8 GB | 2g | 2g / 512m / 512MB / 1536MB | 768m / 512mb |
119
136
  | 16 GB | 4g | 4g / 1g / 1GB / 3GB | 1g / 700mb |
120
137
 
121
- **配比原则**
138
+ 比例只解释这张先验怎么来的:硬限合计大约留出 OS 余量;Postgres `shared_buffers` 约容器硬限的 25%,`effective_cache_size` 约 75%;Redis `maxmemory` 约容器硬限的 70%,其余给 fork 时的写时复制。实测对不上就丢掉整行。
122
139
 
123
- - 容器 `mem_limit` 合计 ≤ 宿主总内存的 **65%**(预留 OS / 全局 nginx / 监控 agent / frpc 等)
124
- - Postgres `shared_buffers` = 容器 `mem_limit` 的 **25%**
125
- - Postgres `effective_cache_size` = 容器 `mem_limit` 的 **75%**
126
- - Redis `maxmemory` = 容器 `mem_limit` 的 **70%**(剩 30% 给 RDB/AOF fork 时 COW 留 buffer)
127
- - Redis `mem_limit` = `maxmemory ÷ 0.7` 向上取整
128
-
129
- **对比报告格式(主 Claude 在报告里生成)**
140
+ **对比报告格式**
130
141
 
131
142
  ```
132
- | 服务 | 配置项 | 推荐(基于 X GB 宿主) | 当前 | 状态 |
133
- |------|--------|--------------------|------|------|
134
- | backend | mem_limit | 1g | 无 | ❌ 缺失 |
135
- | db | mem_limit | 1g | 1g | ✅ |
136
- | db | shared_buffers | 256MB | 128MB(默认) | ⚠️ 偏低 |
137
- | db | shm_size | 256m | 64m(默认) | ⚠️ 偏低 |
138
- | redis | maxmemory | 256mb | 256mb | ✅ |
139
- | redis | mem_limit | 384m | 384m | ✅ |
140
- | redis | appendonly | yes | no | ⚠️ 重启丢数据 |
143
+ | 服务 | 配置项 | 本次实测 | 当前硬限 | 状态 |
144
+ |------|--------|----------|----------|------|
145
+ | backend | mem | stats 420MiB(单帧) | 无 | 缺上限 |
146
+ | db | mem | stats 300MiB(单帧) | 1g | 硬限高于实测 |
147
+ | db | shared_buffers | — | 超过宿主 50% | 撞上天花板 |
148
+ | redis | maxmemory | 当前占用 | 0 | 未设 |
141
149
  ```
142
150
 
143
- **严重等级标记规则**
151
+ 没有实测的新机器,在「本次实测」列写「无,用冷启动先验 &lt;数字&gt;」,并注明服务跑起来后要重测。
152
+
153
+ **严重等级**
144
154
 
145
155
  | 检查项 | 期望值 | 严重级 |
146
156
  |--------|--------|--------|
147
- | 关键服务(redis / postgres / mysql / mongo / clickhouse / elasticsearch)容器无 `mem_limit` | 已设置 | high |
148
- | Redis `--maxmemory` 未设置或 `0` | 已设置 | **critical** |
149
- | Postgres `shared_buffers` > 宿主总内存 50% | ≤ 宿主总内存 50% | high |
150
- | Postgres `shm_size` < 128m | ≥ 256m | medium |
151
- | Redis 未启用 AOF(`--appendonly yes`) | yes | medium |
152
- | 容器 `mem_limit` 合计 > 宿主总内存 75% | ≤ 65% | high |
153
- | `mem_limit` 偏离推荐表 ±50% 以上(主 Claude 判定) | 在分级表区间内 | medium |
157
+ | 关键服务容器无 `mem_limit` | 已设置 | high |
158
+ | 硬限低于本次 `docker stats` 占用 | 硬限高于实测 | high |
159
+ | Redis `--maxmemory` 未设置或 `0` | 已设置,且小于容器 `mem_limit` | **critical** |
160
+ | Postgres `shared_buffers` > 宿主总内存 50% | 不超过 | high |
161
+ | Redis 未启用 AOF(`--appendonly yes`) | 按持久化需求,不是配额 | medium |
162
+ | 容器 `mem_limit` 合计 > 宿主总内存 75% | 不超过。低于 75% 不要求再贴近某个比例 | high |
163
+
164
+ 偏离冷启动先验表 **不是** 违规。
154
165
 
155
166
  ---
156
167
 
157
- ### 日志大小推荐分级表(防容器日志无限增长撑爆磁盘)
168
+ ### 日志轮转
158
169
 
159
- 依据是 `<根盘容量>` × `<容器规模>`,**单容器最大日志占用 = `max-size` × `max-file`**;所有容器日志合计应 ≤ 根盘可用空间的 **5%**(留磁盘给数据/swap/OS)。
170
+ 有日增量时用增速和根盘剩余决定 `max-size` / `max-file`。没有增量时才看冷启动先验。
160
171
 
161
- **daemon 兜底配置(`/etc/docker/daemon.json` `log-opts`)**
172
+ **冷启动先验:daemon `log-opts`(没有日志增量时才用)**
162
173
 
163
174
  | 宿主规格 | 根盘 | 容器数(估) | `max-size` | `max-file` | 单容器 quota | 备注 |
164
175
  |---------|------|-----------|------------|-----------|-------------|------|
165
- | 入门 | < 50 GB | 任意 | `10m` | `3` | ~30 MB | 2-4 GB VM 入门款,日志少留磁盘 |
166
- | 标准 | 50-150 GB | ≤ 5 | `50m` | `5` | ~250 MB | 4-8 GB VM 通用 |
167
- | 标准 | 50-150 GB | > 5 | `20m` | `5` | ~100 MB | 容器多则降单容器 quota |
168
- | 大型 | > 150 GB | 任意 | `100m` | `5` | ~500 MB | 16+ GB 服务器,空间充裕 |
169
-
170
- **容器级覆盖(compose `logging.options`,优先于 daemon)**
176
+ | 入门 | < 50 GB | 任意 | `10m` | `3` | ~30 MB | 盘小,先验从紧 |
177
+ | 标准 | 50-150 GB | ≤ 5 | `50m` | `5` | ~250 MB | 无增速时的起点 |
178
+ | 标准 | 50-150 GB | > 5 | `20m` | `5` | ~100 MB | 容器多,先验收紧 |
179
+ | 大型 | > 150 GB | 任意 | `100m` | `5` | ~500 MB | 无增速时的起点 |
171
180
 
172
- | 容器类型 | `max-size` | `max-file` | 理由 |
173
- |---------|-----------|-----------|------|
174
- | 数据库 (postgres / mysql / mongo) | `20m` | `10` | 慢查询日志价值高,保留更多滚动 |
175
- | Web 反代 (nginx access log 走 stdout) | `50m` | `5` | 写入量大,单文件可放宽 |
176
- | 应用后端 (FastAPI / Node 等) | `10m` | `5` | 通用 |
177
- | Redis / 缓存类 | `10m` | `3` | 写入少,保留少 |
181
+ 容器级 `logging.options` 盖过 daemon。库、反代、应用的保留条数不一样,同样只在没有该容器增速时参考,不作为合格线。
178
182
 
179
- **daemon.json 模板**
183
+ 字段写法示例(数字不是目标配额):
180
184
 
181
185
  ```json
182
186
  {
183
187
  "log-driver": "json-file",
184
188
  "log-opts": {
185
- "max-size": "50m",
186
- "max-file": "5",
189
+ "max-size": "<当次算出的大小>",
190
+ "max-file": "<当次算出的个数>",
187
191
  "compress": "true"
188
192
  }
189
193
  }
190
194
  ```
191
195
 
192
- **严重等级标记(脚本侧 + 主 Claude 对照表)**
196
+ **严重等级**
193
197
 
194
198
  | 判定 | 严重级 |
195
199
  |------|--------|
196
200
  | daemon 无 `log-opts.max-size` 且容器也无 `LogConfig.Config` | **critical** |
197
- | daemon `max-size` > 推荐档 50% 以上(如根盘 < 50 GB 用 100m) | high |
198
- | 容器无 `LogConfig.Config` 但 daemon 有兜底 | OK(走 daemon) |
199
- | 容器 `LogConfig.Config` 设了但 max-size 偏离推荐档 ±50% | medium |
200
- | 估算所有容器日志合计 > 根盘可用 5% | high |
201
+ | 容器无单独 `LogConfig.Config`,daemon 已有上限 | 通过(走 daemon) |
202
+ | `max-size × max-file × 容器数` > 根盘约 5% | high(配额天花板太高) |
203
+ | 按实测日增量,不足 90 天写满根盘 | high;不足 30 天为 **critical** |
204
+ | 当前 `max-size` 与冷启动先验不同 | 不是问题 |
@@ -30,7 +30,16 @@ for cmd in nginx postgres psql redis-cli docker openssl ufw firewall-cmd iptable
30
30
  done
31
31
 
32
32
  echo "--- PUBLIC IP (best effort) ---"
33
- curl -fsS --max-time 5 https://api.ipify.org 2>/dev/null || hostname -I | awk '{print $1}'
33
+ # 回显地址是先验。一个失败换下一个。全部失败印 unknown。禁止用 hostname -I 的内网地址冒充公网 IP。
34
+ PUB_IP=""
35
+ for url in https://api.ipify.org https://ifconfig.me/ip https://icanhazip.com; do
36
+ PUB_IP=$(curl -fsS --max-time 5 "$url" 2>/dev/null | tr -d '[:space:]')
37
+ if printf '%s' "$PUB_IP" | grep -Eq '^[0-9]{1,3}(\.[0-9]{1,3}){3}$'; then
38
+ break
39
+ fi
40
+ PUB_IP=""
41
+ done
42
+ echo "${PUB_IP:-unknown}"
34
43
  echo
35
44
 
36
45
  echo "--- USER & SUDO ---"
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env bash
2
2
  # 硬件规格识别 + 当前服务资源配置盘点 (只读)
3
3
  #
4
- # 输出 raw data, 由主 Claude 对照 SKILL.md 4.10 的推荐分级表生成
5
- # "推荐 vs 当前" 对比报告。
4
+ # 输出实测:硬件、硬限、docker stats 单帧、日志配额。
5
+ # 分级数字只是没有实测时的冷启动先验,见 checks-runtime.md 4.10。
6
+ # 不要因为当前值没贴近先验就判失败。
6
7
  #
7
8
  # 检查范围:
8
9
  # - 宿主硬件: CPU 核数 / 总内存 / 根盘容量 / swap
@@ -26,7 +27,7 @@ MEM_TOTAL_MB=$(( ${MEM_TOTAL_KB:-0} / 1024 ))
26
27
  MEM_AVAIL_MB=$(( ${MEM_AVAIL_KB:-0} / 1024 ))
27
28
  SWAP_TOTAL_MB=$(( ${SWAP_TOTAL_KB:-0} / 1024 ))
28
29
 
29
- # 推荐分档(对齐 SKILL.md 4.10 的 2/4/8/16 GB 表)
30
+ # 冷启动分档。有 docker stats 时不用这档决定 mem_limit。
30
31
  if [[ $MEM_TOTAL_MB -ge 14000 ]]; then TIER="16GB"
31
32
  elif [[ $MEM_TOTAL_MB -ge 7000 ]]; then TIER="8GB"
32
33
  elif [[ $MEM_TOTAL_MB -ge 3500 ]]; then TIER="4GB"
@@ -39,7 +40,7 @@ echo "CPU 型号: ${CPU_MODEL:-unknown}"
39
40
  echo "总内存: ${MEM_TOTAL_MB} MB"
40
41
  echo "可用内存: ${MEM_AVAIL_MB} MB"
41
42
  echo "Swap: ${SWAP_TOTAL_MB} MB"
42
- echo "推荐分档: ${TIER} (主 Claude 据此查推荐表)"
43
+ echo "冷启动分档: ${TIER} (没有占用数据时才参考先验表)"
43
44
 
44
45
  echo ""
45
46
  echo "--- 根盘容量 ---"
@@ -90,6 +91,8 @@ echo "--- 容器实际内存占用 (docker stats 单帧) ---"
90
91
  timeout 8 docker stats --no-stream --format \
91
92
  'table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.CPUPerc}}' 2>/dev/null \
92
93
  || echo "[i] docker stats 超时或不可用"
94
+ # 单帧不是峰值。硬限低于这一帧才算不够;远高于这一帧不必改到先验表。
95
+ echo "[i] 单帧采样不是峰值。有监控历史用峰值。没有数据时才用冷启动先验,不要为贴近先验表改硬限。"
93
96
 
94
97
  echo ""
95
98
  echo "--- Postgres 启动参数 (从 docker inspect Args 提取) ---"
@@ -116,10 +119,10 @@ for c in $(docker ps -q 2>/dev/null); do
116
119
  # 从 docker inspect 取 shm_size (Postgres 关键)
117
120
  shm=$(docker inspect -f '{{.HostConfig.ShmSize}}' "$c" 2>/dev/null)
118
121
  shm_mb=$(( shm / 1024 / 1024 ))
119
- if [[ "$shm_mb" -lt 128 ]]; then
120
- echo " [!] MEDIUM: shm_size=${shm_mb}m 偏低 (大查询可能 'no space left on /dev/shm', 推荐 >=256m)"
121
- else
122
- echo " [OK] shm_size=${shm_mb}m"
122
+ # 64m 是 Docker 默认。没有 /dev/shm 写满的证据时,不把 256m 当合格线。
123
+ echo " shm_size=${shm_mb}m"
124
+ if [[ "$shm_mb" -lt 64 ]]; then
125
+ echo " [i] shm_size 低于 Docker 默认 64m。仅当日志出现 no space left on /dev/shm 时再加大,不预设 256m"
123
126
  fi
124
127
 
125
128
  # 校验 shared_buffers 是否过大
@@ -200,14 +203,14 @@ for f in $COMPOSE_FILES; do
200
203
  done
201
204
 
202
205
  echo ""
203
- echo "--- 日志兜底推荐档 (基于根盘 + 容器规模, 对照 SKILL.md 4.10) ---"
206
+ echo "--- 日志上限 (冷启动先验,不是目标配额) ---"
204
207
  ROOT_TOTAL_MB=$(df -BM --output=size / 2>/dev/null | tail -1 | tr -d ' M')
205
208
  ROOT_TOTAL_GB=$(( ${ROOT_TOTAL_MB:-0} / 1024 ))
206
209
  RUNNING_COUNT=$(docker ps -q 2>/dev/null | wc -l | tr -d ' ')
207
210
  echo "根盘容量: ${ROOT_TOTAL_GB} GB"
208
211
  echo "运行容器数: ${RUNNING_COUNT}"
209
212
 
210
- # 推荐档分级
213
+ # 没有日志日增量时的起点。有 check_logs 的增速就用增速,不要改成跟这里一致。
211
214
  if [[ $ROOT_TOTAL_GB -lt 50 ]]; then REC_TIER="入门"; REC_SIZE="10m"; REC_FILE="3"
212
215
  elif [[ $ROOT_TOTAL_GB -lt 150 ]]; then
213
216
  REC_TIER="标准"
@@ -215,8 +218,7 @@ elif [[ $ROOT_TOTAL_GB -lt 150 ]]; then
215
218
  else REC_SIZE="50m"; REC_FILE="5"; fi
216
219
  else REC_TIER="大型"; REC_SIZE="100m"; REC_FILE="5"
217
220
  fi
218
- echo "推荐档: ${REC_TIER}"
219
- echo "推荐 daemon log-opts: max-size=${REC_SIZE}, max-file=${REC_FILE}, compress=true"
221
+ echo "冷启动先验档: ${REC_TIER} (无日志增量时才参考 max-size=${REC_SIZE}, max-file=${REC_FILE})"
220
222
 
221
223
  # 拿当前 daemon.json log-opts (复用 check_docker.sh 的逻辑)
222
224
  DAEMON_JSON=$(sudo -n cat /etc/docker/daemon.json 2>/dev/null \
@@ -227,13 +229,11 @@ CUR_FILE=$(echo "$DAEMON_JSON" | grep -oE '"max-file"[[:space:]]*:[[:space:]]*"[
227
229
  | head -1 | grep -oE '"[^"]+"$' | tr -d '"')
228
230
  echo "当前 daemon.json: max-size=${CUR_SIZE:-(未配置)}, max-file=${CUR_FILE:-(未配置)}"
229
231
 
230
- # 简单对比标记
232
+ # 缺上限才是问题。和先验档相同或不同都不表示配额正确。
231
233
  if [[ -z "$CUR_SIZE" ]]; then
232
234
  echo "[!!!] CRITICAL: daemon 无 log-opts.max-size, 长跑容器日志会无限增长"
233
- elif [[ "$CUR_SIZE" == "$REC_SIZE" ]]; then
234
- echo "[OK] max-size 与推荐档一致"
235
235
  else
236
- echo "[i] 当前 max-size=${CUR_SIZE} 与推荐档 ${REC_SIZE} 不同 (主 Claude 据 SKILL.md 4.10 判定是否偏离 50%)"
236
+ echo "[i] 已有 max-size=${CUR_SIZE} max-file=${CUR_FILE:-(未配置)}。与冷启动先验不同不是问题,按日志增速判断。"
237
237
  fi
238
238
 
239
239
  # 估算所有容器日志合计 quota = max-size × max-file × 容器数, 看占根盘比
@@ -250,15 +250,15 @@ if [[ -n "$CUR_SIZE" ]]; then
250
250
  total_quota_mb=$(( ${size_mb:-0} * file_n * RUNNING_COUNT ))
251
251
  if [[ "$ROOT_TOTAL_MB" -gt 0 ]]; then
252
252
  pct=$(( total_quota_mb * 100 / ROOT_TOTAL_MB ))
253
- echo "所有容器最大日志 quota 合计: ${total_quota_mb} MB (占根盘 ${pct}%, 期望 < 5%)"
253
+ echo "所有容器最大日志 quota 合计: ${total_quota_mb} MB (占根盘 ${pct}%)"
254
254
  if [[ "$pct" -gt 5 ]]; then
255
- echo "[!!] HIGH: 日志 quota 合计 ${pct}% 已超根盘 5% 上限"
255
+ echo "[!!] HIGH: 配额天花板占根盘 ${pct}%。5% 是安全上限,超过说明 max-size/max-file 过大,不是叫你改成先验档的 10m/50m"
256
256
  fi
257
257
  fi
258
258
  fi
259
259
 
260
260
  echo ""
261
- echo "--- 资源占比汇总 (供 Claude 校验 65% 上限规则) ---"
261
+ echo "--- 内存硬限占宿主比 (75% 是安全天花板,不是目标利用率) ---"
262
262
  echo "宿主总内存: ${MEM_TOTAL_MB} MB"
263
263
  TOTAL_LIMIT_MB=$(docker ps -q 2>/dev/null \
264
264
  | xargs -I{} docker inspect -f '{{.HostConfig.Memory}}' {} 2>/dev/null \
@@ -268,11 +268,9 @@ if [[ "$MEM_TOTAL_MB" -gt 0 ]]; then
268
268
  pct=$(( TOTAL_LIMIT_MB * 100 / MEM_TOTAL_MB ))
269
269
  echo "占宿主总内存: ${pct}%"
270
270
  if [[ "$pct" -gt 75 ]]; then
271
- echo "[!!] HIGH: 容器硬限合计 > 75% 宿主内存, OS/nginx/监控 留 buffer 不足"
272
- elif [[ "$pct" -lt 30 ]]; then
273
- echo "[i] INFO: 容器硬限合计 < 30%, 可能资源利用不足"
271
+ echo "[!!] HIGH: 容器硬限合计 > 75% 宿主内存, OS 没有余量"
274
272
  else
275
- echo "[OK] 容器硬限合计在 30%-75% 区间"
273
+ echo "[i] 硬限合计 ${pct}%。不要求贴近 65%。硬限低于上面的 docker stats 才要加"
276
274
  fi
277
275
  fi
278
276
  REMOTE
@@ -139,7 +139,15 @@ fi
139
139
 
140
140
  echo ""
141
141
  echo "########## 公网可达性自测 ##########"
142
- PUB_IP=$(curl -fsS --max-time 5 https://api.ipify.org 2>/dev/null)
142
+ # 与 check_base.sh 同一原则:回显地址是先验,失败换下一个,禁止用内网地址顶上。
143
+ PUB_IP=""
144
+ for url in https://api.ipify.org https://ifconfig.me/ip https://icanhazip.com; do
145
+ PUB_IP=$(curl -fsS --max-time 5 "$url" 2>/dev/null | tr -d '[:space:]')
146
+ if printf '%s' "$PUB_IP" | grep -Eq '^[0-9]{1,3}(\.[0-9]{1,3}){3}$'; then
147
+ break
148
+ fi
149
+ PUB_IP=""
150
+ done
143
151
  echo "公网 IP (best effort): ${PUB_IP:-unknown}"
144
152
  if [[ -n "$PUB_IP" ]]; then
145
153
  echo "[i] 注意: 真实公网可达性需从外网测试,此处仅本机视角"