@whyshu/argent-engine 0.0.0-stage → 0.6.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 (305) hide show
  1. package/MANIFEST.json +307 -0
  2. package/engine/VERSION +1 -0
  3. package/engine/agents/catalog.json +454 -0
  4. package/engine/configs/_aliases.proposed.json +651 -0
  5. package/engine/configs/_migration-plan.proposed.json +899 -0
  6. package/engine/configs/account.json +272 -0
  7. package/engine/configs/advanced.json +205 -0
  8. package/engine/configs/host.json +149 -0
  9. package/engine/configs/hr.json +27 -0
  10. package/engine/configs/notify.json +264 -0
  11. package/engine/core/cli/argent.mjs +277 -0
  12. package/engine/core/contracts/argent.contracts.json +1065 -0
  13. package/engine/core/contracts/verbs.schema.json +2539 -0
  14. package/engine/core/lib/argent-datadir.mjs +223 -0
  15. package/engine/core/lib/audit.mjs +187 -0
  16. package/engine/core/lib/claim.mjs +258 -0
  17. package/engine/core/lib/config-catalog.mjs +1172 -0
  18. package/engine/core/lib/doctor-customer.mjs +577 -0
  19. package/engine/core/lib/flow-list.mjs +138 -0
  20. package/engine/core/lib/flow-registry.mjs +48 -0
  21. package/engine/core/lib/init.mjs +247 -0
  22. package/engine/core/lib/ledger.mjs +124 -0
  23. package/engine/core/lib/license-activate.mjs +813 -0
  24. package/engine/core/lib/license-device.mjs +314 -0
  25. package/engine/core/lib/license-file.mjs +349 -0
  26. package/engine/core/lib/license-guard.mjs +123 -0
  27. package/engine/core/lib/license-ops.mjs +1645 -0
  28. package/engine/core/lib/license-verdict.mjs +133 -0
  29. package/engine/core/lib/license.mjs +577 -0
  30. package/engine/core/lib/notify/dedup.mjs +101 -0
  31. package/engine/core/lib/notify/feishu.mjs +38 -0
  32. package/engine/core/lib/notify/index.mjs +95 -0
  33. package/engine/core/lib/notify/verb.mjs +327 -0
  34. package/engine/core/lib/notify/webhook.mjs +135 -0
  35. package/engine/core/lib/notify/wecom.mjs +36 -0
  36. package/engine/core/lib/python.mjs +145 -0
  37. package/engine/core/lib/sop.mjs +116 -0
  38. package/engine/core/lib/versions.mjs +205 -0
  39. package/engine/core/mcp/client.mjs +67 -0
  40. package/engine/core/mcp/http.mjs +138 -0
  41. package/engine/core/mcp/server.mjs +702 -0
  42. package/engine/scripts/_engine_rules_probe.py +15 -0
  43. package/engine/scripts/analyze-full-day.py +568 -0
  44. package/engine/scripts/archive/feishu-bridge.js +246 -0
  45. package/engine/scripts/argent-agents.mjs +527 -0
  46. package/engine/scripts/argent-capabilities.mjs +776 -0
  47. package/engine/scripts/argent-catalog.mjs +186 -0
  48. package/engine/scripts/argent-datadir.py +62 -0
  49. package/engine/scripts/argent-doctor.mjs +624 -0
  50. package/engine/scripts/argent-env-write.mjs +302 -0
  51. package/engine/scripts/argent-schedule.mjs +620 -0
  52. package/engine/scripts/argent-setup-check.mjs +369 -0
  53. package/engine/scripts/argent-upgrade.mjs +1046 -0
  54. package/engine/scripts/base-bootstrap.sh +575 -0
  55. package/engine/scripts/billing-mode-daily.sh +12 -0
  56. package/engine/scripts/build-engine-package.mjs +123 -0
  57. package/engine/scripts/capability-packs.lock.json +484 -0
  58. package/engine/scripts/capability_pack.py +1242 -0
  59. package/engine/scripts/check-1.0-criteria.mjs +355 -0
  60. package/engine/scripts/check-agent-catalog.mjs +141 -0
  61. package/engine/scripts/check-billing-mode.sh +377 -0
  62. package/engine/scripts/check-child-sessions.mjs +83 -0
  63. package/engine/scripts/check-config-catalog.mjs +677 -0
  64. package/engine/scripts/check-docs-drift.mjs +522 -0
  65. package/engine/scripts/check-dsh-web-expose.sh +98 -0
  66. package/engine/scripts/check-judgment-drift.mjs +403 -0
  67. package/engine/scripts/check-license.mjs +199 -0
  68. package/engine/scripts/check-model-auth.py +443 -0
  69. package/engine/scripts/check-pack-closure.mjs +661 -0
  70. package/engine/scripts/check-portable-symbols.mjs +116 -0
  71. package/engine/scripts/check-preset-landing.mjs +124 -0
  72. package/engine/scripts/check-production-home.mjs +602 -0
  73. package/engine/scripts/check-role-mapping.mjs +461 -0
  74. package/engine/scripts/check-sample-redaction.mjs +320 -0
  75. package/engine/scripts/check-skill-classification.mjs +188 -0
  76. package/engine/scripts/check-sop-consistency.mjs +431 -0
  77. package/engine/scripts/check-test-env-safety.mjs +627 -0
  78. package/engine/scripts/check-version-consistency.mjs +452 -0
  79. package/engine/scripts/ci-run.sh +558 -0
  80. package/engine/scripts/config-explain.mjs +278 -0
  81. package/engine/scripts/configure-provider.rb +29 -0
  82. package/engine/scripts/customer-config-migrate.mjs +179 -0
  83. package/engine/scripts/customer-preflight.py +892 -0
  84. package/engine/scripts/customer-readiness.sh +134 -0
  85. package/engine/scripts/daily-report-inbox.py +242 -0
  86. package/engine/scripts/daily-report-reconcile.mjs +312 -0
  87. package/engine/scripts/daily-report.mjs +1310 -0
  88. package/engine/scripts/daily-report.sh +46 -0
  89. package/engine/scripts/data/lip-product-dict.json +306 -0
  90. package/engine/scripts/deliver-customer.mjs +932 -0
  91. package/engine/scripts/delivery-faces.txt +31 -0
  92. package/engine/scripts/desktop-trial.sh +146 -0
  93. package/engine/scripts/dev-window.sh +260 -0
  94. package/engine/scripts/drill-clean-machine.sh +315 -0
  95. package/engine/scripts/dsh-api-client.mjs +215 -0
  96. package/engine/scripts/dsh-backup-scope.sh +83 -0
  97. package/engine/scripts/dsh-offline-pack.mjs +77 -0
  98. package/engine/scripts/dsh-overlay-pin.sh +87 -0
  99. package/engine/scripts/dsh-plane.mjs +153 -0
  100. package/engine/scripts/dsh-portforward.py +223 -0
  101. package/engine/scripts/dsh-preflight.mjs +179 -0
  102. package/engine/scripts/dsh-release-watch-daily.sh +19 -0
  103. package/engine/scripts/dsh-release-watch.mjs +458 -0
  104. package/engine/scripts/dsh-remote-check.sh +99 -0
  105. package/engine/scripts/dsh-restart.sh +179 -0
  106. package/engine/scripts/dsh-restore.sh +111 -0
  107. package/engine/scripts/dsh-scope-rewire.mjs +803 -0
  108. package/engine/scripts/dsh-snapshot.mjs +116 -0
  109. package/engine/scripts/dsh-upgrade-readiness.mjs +165 -0
  110. package/engine/scripts/dsh-upgrade.mjs +612 -0
  111. package/engine/scripts/dsh-url.sh +86 -0
  112. package/engine/scripts/dsh-web-launch.mjs +155 -0
  113. package/engine/scripts/ensure-store-windows.py +509 -0
  114. package/engine/scripts/entitlements.py +458 -0
  115. package/engine/scripts/env_probe.py +411 -0
  116. package/engine/scripts/feishu-card.mjs +252 -0
  117. package/engine/scripts/fix-skill-frontmatter.py +209 -0
  118. package/engine/scripts/flow-auto-retry.py +454 -0
  119. package/engine/scripts/flow-requirements.json +720 -0
  120. package/engine/scripts/flow-scaffold.py +275 -0
  121. package/engine/scripts/flow-timers-plist.sh +86 -0
  122. package/engine/scripts/flow-timers.sh +182 -0
  123. package/engine/scripts/flow-trigger-wake.mjs +284 -0
  124. package/engine/scripts/flow-trigger.sh +571 -0
  125. package/engine/scripts/flow_billing.py +354 -0
  126. package/engine/scripts/flow_capability_stats.py +314 -0
  127. package/engine/scripts/flow_case.py +194 -0
  128. package/engine/scripts/flow_claim.py +497 -0
  129. package/engine/scripts/flow_config.py +1024 -0
  130. package/engine/scripts/flow_failure.py +588 -0
  131. package/engine/scripts/flow_learn.py +105 -0
  132. package/engine/scripts/flow_ledger.py +235 -0
  133. package/engine/scripts/flow_policy.py +238 -0
  134. package/engine/scripts/flow_preflight.py +339 -0
  135. package/engine/scripts/flow_registry.py +341 -0
  136. package/engine/scripts/flow_retry.py +304 -0
  137. package/engine/scripts/flow_return_to_ops.py +191 -0
  138. package/engine/scripts/flow_source.py +315 -0
  139. package/engine/scripts/flow_sources/__init__.py +53 -0
  140. package/engine/scripts/flow_sources/cases_json.py +106 -0
  141. package/engine/scripts/flow_sources/common.py +428 -0
  142. package/engine/scripts/flow_sources/feishu_base.py +273 -0
  143. package/engine/scripts/flow_stale.py +185 -0
  144. package/engine/scripts/flow_status_reconcile.py +344 -0
  145. package/engine/scripts/flow_triage.py +849 -0
  146. package/engine/scripts/flow_write_verify.py +496 -0
  147. package/engine/scripts/fulfillment.js +586 -0
  148. package/engine/scripts/gen-agent-bundles.mjs +276 -0
  149. package/engine/scripts/gen-preset-rows.mjs +259 -0
  150. package/engine/scripts/init-ml.sh +2275 -0
  151. package/engine/scripts/install-internal-role.sh +190 -0
  152. package/engine/scripts/install-license.mjs +641 -0
  153. package/engine/scripts/install-one-shot.mjs +665 -0
  154. package/engine/scripts/integration_contract.py +220 -0
  155. package/engine/scripts/integrations/wenyao/adapter.py +98 -0
  156. package/engine/scripts/integrations/xzh/adapter.py +75 -0
  157. package/engine/scripts/invoice-mapping.example.json +40 -0
  158. package/engine/scripts/invoice-table.sh +194 -0
  159. package/engine/scripts/invoice_carrier_notice.py +279 -0
  160. package/engine/scripts/invoice_fail_closeout.py +297 -0
  161. package/engine/scripts/invoice_lip_runner.py +1508 -0
  162. package/engine/scripts/invoice_lip_runner.py.bak-20260922-1710-freready +1090 -0
  163. package/engine/scripts/invoice_ready_audit.py +191 -0
  164. package/engine/scripts/invoice_runner.py +675 -0
  165. package/engine/scripts/invoice_stageb.py +516 -0
  166. package/engine/scripts/launchd/com.whyshu.argent-bridge.plist.example +42 -0
  167. package/engine/scripts/launchd/com.whyshu.fulfillment-poll.plist.example +29 -0
  168. package/engine/scripts/lease.py +377 -0
  169. package/engine/scripts/lib/agent-install.mjs +649 -0
  170. package/engine/scripts/lib/argent-datadir.mjs +16 -0
  171. package/engine/scripts/lib/argent_datadir.py +262 -0
  172. package/engine/scripts/lib/argent_filelock.py +507 -0
  173. package/engine/scripts/lib/bootcheck-wiring.mjs +510 -0
  174. package/engine/scripts/lib/cdp_ports.py +197 -0
  175. package/engine/scripts/lib/customer-env.mjs +102 -0
  176. package/engine/scripts/lib/daily-report-core.mjs +517 -0
  177. package/engine/scripts/lib/dep-declaration.mjs +81 -0
  178. package/engine/scripts/lib/deps-migrate.mjs +310 -0
  179. package/engine/scripts/lib/dsh-host-resolve.mjs +109 -0
  180. package/engine/scripts/lib/dsh-scope.mjs +500 -0
  181. package/engine/scripts/lib/dsh-snapshot-path.mjs +35 -0
  182. package/engine/scripts/lib/dsh-versions.mjs +96 -0
  183. package/engine/scripts/lib/dsh-web-probe.mjs +214 -0
  184. package/engine/scripts/lib/is-direct-run.mjs +61 -0
  185. package/engine/scripts/lib/patch-compose.mjs +241 -0
  186. package/engine/scripts/lib/patch-target.mjs +35 -0
  187. package/engine/scripts/lib/plugin-lifecycle.mjs +128 -0
  188. package/engine/scripts/lib/plugin-packages.mjs +332 -0
  189. package/engine/scripts/lib/preset-compat.mjs +127 -0
  190. package/engine/scripts/lib/preset-install.mjs +575 -0
  191. package/engine/scripts/lib/preset-mechanism.mjs +56 -0
  192. package/engine/scripts/lib/preset-sync.mjs +59 -0
  193. package/engine/scripts/lib/profile-retire.mjs +97 -0
  194. package/engine/scripts/lib/python-runtime.mjs +190 -0
  195. package/engine/scripts/lib/registry.mjs +72 -0
  196. package/engine/scripts/lib/repo-root.sh +56 -0
  197. package/engine/scripts/lib/schedule-mechanism.mjs +659 -0
  198. package/engine/scripts/lib/schedule-probe.mjs +835 -0
  199. package/engine/scripts/lib/scope-pointer.mjs +164 -0
  200. package/engine/scripts/lib/settings-panels.mjs +816 -0
  201. package/engine/scripts/lib/stdio_utf8.py +86 -0
  202. package/engine/scripts/lib/wake-auth.mjs +392 -0
  203. package/engine/scripts/lib/webdriver_ipc.py +264 -0
  204. package/engine/scripts/lib/zstd-frames.mjs +104 -0
  205. package/engine/scripts/license-e2e-drill.mjs +426 -0
  206. package/engine/scripts/license-gate.mjs +245 -0
  207. package/engine/scripts/lip_backlog.py +171 -0
  208. package/engine/scripts/lip_table.py +185 -0
  209. package/engine/scripts/local-usage.mjs +214 -0
  210. package/engine/scripts/migrate-providers.mjs +127 -0
  211. package/engine/scripts/migrate-skills.sh +65 -0
  212. package/engine/scripts/ml-oauth-setup.mjs +550 -0
  213. package/engine/scripts/ml-store-ids.json +26 -0
  214. package/engine/scripts/ml_artifact_attribution.py +333 -0
  215. package/engine/scripts/ml_capacity_probe.py +1158 -0
  216. package/engine/scripts/ml_hub_status.py +1556 -0
  217. package/engine/scripts/ml_schema_check.py +115 -0
  218. package/engine/scripts/ml_store_ids.py +139 -0
  219. package/engine/scripts/npm-publish-argent.mjs +499 -0
  220. package/engine/scripts/npm-publish-argent.sh +20 -0
  221. package/engine/scripts/orchestrator.py +13811 -0
  222. package/engine/scripts/pack-plugins.mjs +140 -0
  223. package/engine/scripts/patches/dsh-llm-deepseek--transport-diagnostics.patch +297 -0
  224. package/engine/scripts/patches/dsh-session--append-message-shape.patch +15 -0
  225. package/engine/scripts/patches/dsh-session--tool-result-block-017.patch +28 -0
  226. package/engine/scripts/patches/dsh-session-format-v0-to-v1--permission-preset-origin.patch +11 -0
  227. package/engine/scripts/patches/dsh-session-format-v3-to-v4--turn-outside-replace.patch +20 -0
  228. package/engine/scripts/patches/dsh-session-persistence-jsonl--worker-bundled-migrators.patch +39 -0
  229. package/engine/scripts/patches/dsh-tools--render-return-shape.patch +50 -0
  230. package/engine/scripts/patches/verify-bundled-migrators.mjs +79 -0
  231. package/engine/scripts/patches/verify-hardening.mjs +167 -0
  232. package/engine/scripts/patches/verify-session-migration.mjs +149 -0
  233. package/engine/scripts/patches/verify-transport-diagnostics.mjs +227 -0
  234. package/engine/scripts/plan-role-rename.mjs +125 -0
  235. package/engine/scripts/plugin-bootcheck.mjs +451 -0
  236. package/engine/scripts/plugin-composition.json +15 -0
  237. package/engine/scripts/poc-mcp-host.mjs +455 -0
  238. package/engine/scripts/poll-fulfillment.sh +293 -0
  239. package/engine/scripts/poll-invoice.sh +74 -0
  240. package/engine/scripts/profile-doctor.mjs +686 -0
  241. package/engine/scripts/provider-select.sh +70 -0
  242. package/engine/scripts/provider-switch.sh +146 -0
  243. package/engine/scripts/provider-sync-target.check.mjs +64 -0
  244. package/engine/scripts/python-runtime.sh +78 -0
  245. package/engine/scripts/query_runner.py +310 -0
  246. package/engine/scripts/release-argent.sh +574 -0
  247. package/engine/scripts/repair-unresolved-tools.mjs +178 -0
  248. package/engine/scripts/run-tests.sh +256 -0
  249. package/engine/scripts/self-sign-license.mjs +179 -0
  250. package/engine/scripts/session-health-scan.mjs +63 -0
  251. package/engine/scripts/session-repair-tool-result-content.mjs +181 -0
  252. package/engine/scripts/setup.sh +22 -0
  253. package/engine/scripts/skill-install.mjs +629 -0
  254. package/engine/scripts/sku_translate.py +148 -0
  255. package/engine/scripts/sync-plugins.sh +90 -0
  256. package/engine/scripts/sync-presets.sh +27 -0
  257. package/engine/scripts/sync-scripts.sh +445 -0
  258. package/engine/scripts/telemetry.py +873 -0
  259. package/engine/scripts/ui-copy-count.mjs +220 -0
  260. package/engine/scripts/usage-anchor.sh +136 -0
  261. package/engine/scripts/usage_report.py +531 -0
  262. package/engine/scripts/validate-preset-schema.mjs +208 -0
  263. package/engine/scripts/vertical-init.mjs +323 -0
  264. package/engine/scripts/vertical-lint.mjs +482 -0
  265. package/engine/scripts/wenyao-browser.sh +73 -0
  266. package/engine/scripts/wenyao-fixture-export.py +116 -0
  267. package/engine/scripts/wenyao-invoice-writeback.mjs +540 -0
  268. package/engine/scripts/wenyao-login.sh +34 -0
  269. package/engine/scripts/wenyao-template-map.json +292 -0
  270. package/engine/scripts/wenyao_attach.py +131 -0
  271. package/engine/scripts/wenyao_download_template.py +144 -0
  272. package/engine/scripts/wenyao_fill_template.py +568 -0
  273. package/engine/scripts/wenyao_login.py +145 -0
  274. package/engine/scripts/wenyao_portal.py +633 -0
  275. package/engine/scripts/wenyao_recon.py +230 -0
  276. package/engine/scripts/wenyao_run.py +503 -0
  277. package/engine/scripts/wenyao_shadow_diff.py +160 -0
  278. package/engine/scripts/wenyao_skill_contract.py +156 -0
  279. package/engine/scripts/wenyao_template_fetch.py +175 -0
  280. package/engine/scripts/win/dsh-web-autostart.ps1 +372 -0
  281. package/engine/scripts/ziniao-auth-probe.sh +268 -0
  282. package/engine/scripts/ziniao-keepalive.sh +216 -0
  283. package/engine/scripts/ziniao-post-upgrade-check.sh +120 -0
  284. package/engine/scripts/ziniao-windows.sh +153 -0
  285. package/engine/version.mjs +1 -0
  286. package/engine/verticals/README.md +103 -0
  287. package/engine/verticals/_engine-words.baseline.txt +237 -0
  288. package/engine/verticals/_engine-words.json +19 -0
  289. package/engine/verticals/mercadolibre/README.md +43 -0
  290. package/engine/verticals/mercadolibre/config.json +709 -0
  291. package/engine/verticals/mercadolibre/flows.json +706 -0
  292. package/engine/verticals/mercadolibre/manifest.json +538 -0
  293. package/engine/verticals/mercadolibre/migrate-machine-state.mjs +138 -0
  294. package/engine/verticals/mercadolibre/preflight.py +143 -0
  295. package/engine/verticals/mercadolibre/prompts/daily-report.failure.md +69 -0
  296. package/engine/verticals/mercadolibre/prompts/daily-report.md +47 -0
  297. package/engine/verticals/mercadolibre/prompts/daily-report.scheduled.md +79 -0
  298. package/engine/verticals/mercadolibre/prompts/full.failure.md +125 -0
  299. package/engine/verticals/mercadolibre/prompts/full.md +91 -0
  300. package/engine/verticals/mercadolibre/prompts/wenyao-invoice.failure.md +88 -0
  301. package/engine/verticals/mercadolibre/prompts/wenyao-invoice.md +64 -0
  302. package/engine/verticals/mercadolibre/prompts/xzh-invoice.failure.md +91 -0
  303. package/engine/verticals/mercadolibre/prompts/xzh-invoice.md +46 -0
  304. package/package.json +21 -4
  305. package/README.md +0 -3
@@ -0,0 +1,899 @@
1
+ {
2
+ "_doc": "18 项迁移计划(未生效)。批 3 只读前置的机读产物 —— 由 docs/配置-18项迁移计划-2026-10-09.md 逐项对应的结构化副本。⛔ 本文件不改任何读取行为;它只是给批 3 实现消费的计划。取值口径:todayChain = configs/*.json 里的声明('旧优先级');readers = 真读点(不含白名单/注释/日志/校验名单);envInProduction = 客户机 huangwei@10.126.126.1 的只读实测结果(只记存在性/长度,⛔ 不含任何值)。",
3
+ "_survey": {
4
+ "date": "2026-10-09",
5
+ "gitHead": "2e02ba5",
6
+ "readerSha256_16": "core/lib/config-catalog.mjs=26fe694a466b8980",
7
+ "catalogSha256_16": {
8
+ "configs/account.json": "3e80bf3bedec835e",
9
+ "configs/notify.json": "1dc3588bc991f3e3",
10
+ "configs/host.json": "8288b112b3221135",
11
+ "configs/advanced.json": "b6cef3120fe33bee",
12
+ "configs/hr.json": "48357e567dad8036",
13
+ "verticals/mercadolibre/config.json": "85e592d700383b9b"
14
+ },
15
+ "readPointSha256_16": {
16
+ "scripts/daily-report.mjs": "c90bf74666a14f1b",
17
+ "scripts/telemetry.py": "c0362ae50638f63b",
18
+ "plugins/argent-core/src/index.js": "f7c885db527793b2"
19
+ },
20
+ "customer": {
21
+ "host": "huangwei@10.126.126.1",
22
+ "hostname": "huangweideMac-mini.local",
23
+ "dataDir": "/Users/huangwei/.dsh/argent",
24
+ "access": "read-only (no writes, no restarts, no remote files created)",
25
+ "envFilesPresent": ["daily-report.env", "fulfillment.env", "wenyao.env", "ziniao-webdriver.env"],
26
+ "canonicalEnvDirPresent": false,
27
+ "note": "~/.dsh/argent/verticals/mercadolibre/ 存在但**无 env/ 子目录** ⇒ 规范 env 路径尚不存在,4 个 env 文件全在旧平铺位",
28
+ "launchdEnvKeys": ["ARGENT_LICENSE_ENFORCE", "ARGENT_LICENSE_GATE_FORCE", "ARGENT_PY", "PATH"],
29
+ "configJsonKeysPresent": ["feishuAppId", "feishuAppSecret", "apiKey", "feishuBaseUrl", "feishuChatId", "fflUser", "fflPass", "xhInvoiceUser", "xhInvoicePass", "telemetryOptIn", "telemetryConsent", "mlDailyAlertChatId", "mlDailyAlertProfile", "mlDailyTime"],
30
+ "configJsonKeysAbsent": ["updateChannel", "mlDailyChatId", "mlDailyProfile", "mlDailyWebhook", "mlDailyTopN", "mlRestockLeadDays", "mlRestockBufferDays", "mlDailyStoreCount", "role"],
31
+ "instanceTokenFile": { "present": true, "size": 897 },
32
+ "rolesJson": { "present": true, "presets": 13, "has_hr_office": true }
33
+ }
34
+ },
35
+ "_blockers": [
36
+ {
37
+ "id": "B1-envfile-layer-unreachable",
38
+ "severity": "high",
39
+ "what": "读取器 resolveOne() 的 ② 层(env 文件)带门:只在 binding.kind==='envfile' 或 item.source==='envfile' 时才查(core/lib/config-catalog.mjs:575)。",
40
+ "consequence": "source:json 的项**永远读不到 env 文件**;18 项里 13 项是 json 源,其中 9 项(notify.daily.* 5 + ml.daily.* 4)今天的 env 回落正落在 daily-report.env。直接做 A ⇒ 这 9 项静默丢掉 env 文件回落。",
41
+ "evidence": "夹具实测:notify.daily.chat_id → missing;notify.daily.profile → missing(客户机今天分别取到 daily-report.env 的 ML_DAILY_CHAT_ID / LARK_PROFILE)",
42
+ "neededBefore": ["notify.daily.chat_id", "notify.daily.profile", "notify.daily.webhook", "ml.daily.hour", "ml.daily.top_n", "ml.daily.restock_lead_days", "ml.daily.restock_buffer_days"]
43
+ },
44
+ {
45
+ "id": "B2-env-name-mismatch",
46
+ "severity": "high",
47
+ "what": "多项的规范 env 名(envNameOf(key))与今天代码实际读的 env 名**完全不同**,且 13 项都没声明 binding.env。",
48
+ "pairs": [
49
+ ["notify.daily.chat_id", "ML_DAILY_CHAT_ID", "NOTIFY_DAILY_CHAT_ID"],
50
+ ["notify.daily.profile", "LARK_PROFILE", "NOTIFY_DAILY_PROFILE"],
51
+ ["notify.daily.webhook", "FEISHU_WEBHOOK_URL", "NOTIFY_DAILY_WEBHOOK"],
52
+ ["notify.daily.alert_chat_id", "ML_DAILY_ALERT_CHAT_ID", "NOTIFY_DAILY_ALERT_CHAT_ID"],
53
+ ["notify.daily.alert_profile", "ML_DAILY_ALERT_PROFILE", "NOTIFY_DAILY_ALERT_PROFILE"],
54
+ ["ml.daily.hour", "REPORT_TIME", "ML_DAILY_HOUR"],
55
+ ["ml.daily.top_n", "TOP_N", "ML_DAILY_TOP_N"],
56
+ ["ml.daily.restock_lead_days", "RESTOCK_LEAD_DAYS", "ML_RESTOCK_LEAD_DAYS"],
57
+ ["ml.daily.restock_buffer_days", "RESTOCK_BUFFER_DAYS", "ML_RESTOCK_BUFFER_DAYS"],
58
+ ["account.feishu.app_id", "(无 env 读取)", "ACCOUNT_FEISHU_APP_ID"],
59
+ ["account.feishu.app_secret", "(无 env 读取)", "ACCOUNT_FEISHU_APP_SECRET"],
60
+ ["account.carrier.user", "(无 env 读取)", "ACCOUNT_CARRIER_USER"],
61
+ ["account.carrier.password", "(无 env 读取)", "ACCOUNT_CARRIER_PASSWORD"],
62
+ ["host.telemetry.instance_token", "ARGENT_INSTANCE_TOKEN", "HOST_TELEMETRY_INSTANCE_TOKEN"]
63
+ ],
64
+ "consequence": "直接 A 会静默丢弃既有 env 键('配了等于没配')。每一项都必须**显式声明 binding.env**(取今天的名字)或一次性改名并同步 init-ml.sh 模板 + 客户机 env 文件(生产变更,需单独批准)。",
65
+ "format": ["key", "todayEnvName", "canonicalEnvName"]
66
+ },
67
+ {
68
+ "id": "B3-declaration-factually-wrong",
69
+ "severity": "medium",
70
+ "what": "三项的 todayChain/声明与代码事实不符(不是'要迁移',是'登记要改正')。",
71
+ "cases": [
72
+ {
73
+ "key": "notify.daily.alert_chat_id",
74
+ "declared": ["json", "env"],
75
+ "actual": ["env", "json"],
76
+ "proof": ["scripts/daily-report.mjs:1006"],
77
+ "fix": "改 todayChain 为 [env,json](代码零改动,提示自然消失 —— 不是'删提示')"
78
+ },
79
+ {
80
+ "key": "notify.daily.alert_profile",
81
+ "declared": ["json", "env"],
82
+ "actual": ["env", "json"],
83
+ "proof": ["scripts/daily-report.mjs:1007", "scripts/feishu-card.mjs:174", "scripts/feishu-card.mjs:177", "scripts/flow_preflight.py:277", "scripts/flow_preflight.py:280"],
84
+ "fix": "改 todayChain 为 [env,json]"
85
+ },
86
+ {
87
+ "key": "host.telemetry.instance_token",
88
+ "declared": ["machine", "env"],
89
+ "actual": ["env", "machine"],
90
+ "proof": ["scripts/telemetry.py:206-212"],
91
+ "fix": "改 todayChain 为 [env,machine] + 修 binding(加 field:'token')"
92
+ }
93
+ ]
94
+ },
95
+ {
96
+ "id": "B4-binding-defects",
97
+ "severity": "high",
98
+ "what": "两条声明的 binding 本身读不出正确的值。",
99
+ "cases": [
100
+ {
101
+ "key": "host.telemetry.instance_token",
102
+ "defect": "binding 缺 field ⇒ 规范读取器把整个 JSON 信封当标量,实测报「期望标量,实际拿到 object(binding 的 field 写错了?)」⇒ 落在 missing",
103
+ "impact": "客户机有 instance-token.json(897 B)却显示「未配置」",
104
+ "fix": "binding.field = 'token'",
105
+ "acceptance": "修后 describe().configured 由 false → true"
106
+ },
107
+ {
108
+ "key": "account.ziniao.api_key",
109
+ "defect": "binding 指向 config.json#apiKey,但该字段在代码里是**问述账号令牌**(7 处 config.apiKey || process.env.WHYSHU_API_KEY);真正的紫鸟 Key 读在 plugins/argent-core/src/index.js:1405-1413(~/.ziniao-cli/config.json#profiles.<cur>.apiKey),面板 hint 明写「不入 config.json」",
110
+ "impact": "设置页「紫鸟 API Key」与目录项指向两个不同文件;按现状 A 会把问述令牌误当紫鸟 Key",
111
+ "fix": "改 binding 指向 ~/.ziniao-cli/config.json(需扩展 schema 支持数据目录外文件),或把本项降级为只读存在性",
112
+ "doNot": "⛔ 不要按现状做 A"
113
+ }
114
+ ]
115
+ },
116
+ {
117
+ "id": "B5-reader-order-conflicts",
118
+ "severity": "medium",
119
+ "what": "同一 key 的多个读取点顺序相反(todayChain 是一项一条,无法表达)。",
120
+ "cases": [
121
+ { "key": "notify.daily.chat_id", "jsonFirst": ["scripts/daily-report.mjs:985"], "envFirst": ["scripts/feishu-card.mjs:173", "scripts/flow_preflight.py:274"] },
122
+ { "key": "notify.daily.profile", "jsonFirst": ["scripts/daily-report.mjs:986"], "envFirst": ["scripts/flow_preflight.py:273", "scripts/feishu-card.mjs:174"], "quirk": "scripts/feishu-card.mjs:174 的 config 回落读的是 **alert** profile(疑似缺陷,建议单独记 issue,⛔ 不在本批改)" }
123
+ ],
124
+ "consequence": "迁移必须**逐读取点**确认,不能只按声明改一处。"
125
+ }
126
+ ],
127
+ "_decisionPoints": [
128
+ { "id": "D1-schema-fallbacks", "question": "json 源项要不要支持 env 文件回落?(阻塞 9 项)", "options": ["① 声明加 binding.fallbacks(推荐:显式、可门禁)", "② 放开读取器 ② 层的门(改动小、语义变宽)", "③ 另立 envfile 声明项(不动 schema,但一个语义两行声明)"], "blocks": ["B1-envfile-layer-unreachable"] },
129
+ { "id": "D2-env-name-strategy", "question": "env 名取今天的名字(显式声明 binding.env)还是一次性改成规范名?", "recommend": "先取今天的名字(保住既有覆盖),规范名只作文档别名", "blocks": ["B2-env-name-mismatch"] },
130
+ { "id": "D3-push-target", "question": "notify.daily.chat_id / profile 翻转会改生产推送目标与身份,是否接受?", "recommend": "先双写(config.json 与 env 同时有值)再切换读取方", "requiresUserApproval": true },
131
+ { "id": "D4-ziniao-binding", "question": "account.ziniao.api_key 的 binding 怎么修?", "requiresUserApproval": true },
132
+ { "id": "D5-telemetry-semantics", "question": "advanced.telemetry.opt_in 是否确认选 B(隐私同意 + TELEMETRY_DISABLE 反向硬关,不要 env 覆盖)?", "recommend": "B", "requiresUserApproval": true },
133
+ { "id": "D6-instance-token", "question": "host.telemetry.instance_token 是否确认 B + 修 field:'token'?ARGENT_INSTANCE_TOKEN 是否登记为运维/测试逃生阀?", "recommend": "B + 修 field + 登记逃生阀", "requiresUserApproval": true },
134
+ { "id": "D7-update-channel", "question": "advanced.update.channel 补读者(--check-update 读通道)还是如实标注'暂不生效'?", "requiresUserApproval": true },
135
+ { "id": "D8-hr-retired", "question": "hr.office.role(hr-office 角色 2026-10-04 已退役、preset 是墓碑)是否保留该目录项?", "requiresUserApproval": true }
136
+ ],
137
+ "_unlistedHazards": [
138
+ {
139
+ "id": "H1-notify.feishu.chat_id",
140
+ "severity": "medium",
141
+ "what": "唯一「source:json 且无 todayChain」的项(configs/notify.json 首项,绑定 config.json#feishuChatId),代码实际 env 优先且 env 名是 FULL_INTERNAL_CHAT_ID(规范名应为 NOTIFY_FEISHU_CHAT_ID)",
142
+ "proof": ["scripts/feishu-card.mjs:176"],
143
+ "why": "与 18 项同一形态,却因未写 todayChain 而在设置页**一句提示都没有** ⇒ 静默隐患",
144
+ "suggest": "补 todayChain:[env,json](与代码一致、不产生提示)或与 18 项同批盘查"
145
+ },
146
+ {
147
+ "id": "H2-evidence-tokens-blind",
148
+ "severity": "medium",
149
+ "what": "门禁 evidenceTokens() 只用 binding.env/file/field 作'被读证据'候选(scripts/check-config-catalog.mjs:172-185),看不见'今日 env 名'",
150
+ "consequence": "迁移后 ML_DAILY_CHAT_ID / TOP_N / REPORT_TIME / LARK_PROFILE / ARGENT_INSTANCE_TOKEN 等读取点对门禁不可见",
151
+ "suggest": "在 todayChain 旁登记 todayEnvName,供门禁消费"
152
+ },
153
+ {
154
+ "id": "H3-canonical-env-path-absent",
155
+ "severity": "medium",
156
+ "what": "客户机 ~/.dsh/argent/verticals/mercadolibre/ 无 env/ 子目录,4 个 env 文件全在旧平铺位",
157
+ "consequence": "现状能读到(读取器 ② 层规范路径优先、旧平铺兜底);但任何'搬到规范路径'的动作必须同时确认所有读取者都走同一条兜底",
158
+ "suggest": "搬文件前先查 scripts/invoice_lip_runner.py、scripts/orchestrator.py 的 _profile_from_deploy 等非读取器调用方"
159
+ },
160
+ {
161
+ "id": "H4-apikey-second-slot",
162
+ "severity": "medium",
163
+ "what": "config.json#apiKey 是问述令牌的**第二个存储槽**(与 whyshu.env#WHYSHU_API_KEY 并存),被 7+ 处读取;目录里**没有**任何项把它声明为问述令牌(唯一命中的项却声称它是紫鸟 Key)",
164
+ "proof": ["plugins/argent-core/src/index.js:339", "plugins/argent-core/src/index.js:573", "plugins/argent-core/src/index.js:600", "plugins/argent-core/src/index.js:869", "plugins/argent-core/src/index.js:895", "plugins/argent-core/src/index.js:2632", "plugins/argent-core/src/index.js:3056", "scripts/telemetry.py:137-144", "scripts/invoice_lip_runner.py:618-625", "scripts/check-model-auth.py:177-182"],
165
+ "suggest": "或补一条 account.whyshu.api_key_json 之类的声明,或把该槽登记为 account.whyshu.api_key 的 envfile→json 回落"
166
+ }
167
+ ],
168
+ "items": [
169
+ {
170
+ "key": "account.feishu.app_id",
171
+ "todayChain": ["json"],
172
+ "group": "json",
173
+ "category": "账号",
174
+ "readers": [
175
+ "plugins/argent-core/src/index.js:1428",
176
+ "plugins/argent-core/src/index.js:2829",
177
+ "plugins/argent-gateway/src/index.js:213",
178
+ "plugins/argent-gateway/src/index.js:223"
179
+ ],
180
+ "readersExcluded": ["plugins/argent-core/src/index.js:1477", "plugins/argent-core/src/index.js:1486", "plugins/argent-core/src/index.js:1487"],
181
+ "readersExcludedWhy": "只读刚提交的 patch,非存量配置",
182
+ "todayEnvName": null,
183
+ "canonicalEnvName": "ACCOUNT_FEISHU_APP_ID",
184
+ "envInProduction": false,
185
+ "envFileInProduction": false,
186
+ "jsonInProduction": true,
187
+ "activeValueSourceToday": "json",
188
+ "recommend": "A",
189
+ "behaviorChange": "none",
190
+ "behaviorChangeDetail": "客户机 env 无值 ⇒ 两链同取 config.json#feishuAppId。仅当有人设了同名 env 才改变。",
191
+ "writerAtDeclaredLevel": true,
192
+ "writerAtEnvLevel": false,
193
+ "writerNote": "设置页 POST /api/argent-state/config(白名单 argent-core:81/:150;面板 verticals/mercadolibre/manifest.json:80-92)",
194
+ "regression": [
195
+ "设置页「飞书应用 App ID」保存→读回",
196
+ "POST /api/argent-state/feishu-test",
197
+ "gateway 启动日志的 Bot 配置行"
198
+ ],
199
+ "needsUserDecision": true,
200
+ "decisionWhy": "env 名策略(D2):规范名 ACCOUNT_FEISHU_APP_ID 今天无人读;若要兼容 lark-cli 的 LARK_APP_ID 需另行决定",
201
+ "priority": 2,
202
+ "risk": "low"
203
+ },
204
+ {
205
+ "key": "account.feishu.app_secret",
206
+ "todayChain": ["json"],
207
+ "group": "json",
208
+ "category": "账号",
209
+ "readers": [
210
+ "plugins/argent-core/src/index.js:1436",
211
+ "plugins/argent-core/src/index.js:1438",
212
+ "plugins/argent-core/src/index.js:2830",
213
+ "plugins/argent-gateway/src/index.js:214",
214
+ "plugins/argent-gateway/src/index.js:233"
215
+ ],
216
+ "todayEnvName": null,
217
+ "canonicalEnvName": "ACCOUNT_FEISHU_APP_SECRET",
218
+ "envInProduction": false,
219
+ "envFileInProduction": false,
220
+ "jsonInProduction": true,
221
+ "activeValueSourceToday": "json",
222
+ "recommend": "A",
223
+ "behaviorChange": "none",
224
+ "behaviorChangeDetail": "客户机 env 无值 ⇒ 不变。密钥项经 env 优先注入后可不再明文落 config.json。",
225
+ "writerAtDeclaredLevel": true,
226
+ "writerAtEnvLevel": false,
227
+ "writerNote": "设置页同上(secret;SECRET_KEYS 名单 argent-core:249)",
228
+ "regression": [
229
+ "掩码回显(describe() 永不回值)",
230
+ "feishu-test 仍能取到",
231
+ "重启后 gateway 仍能起 Bot"
232
+ ],
233
+ "needsUserDecision": true,
234
+ "decisionWhy": "env 名策略(D2)",
235
+ "priority": 2,
236
+ "risk": "low"
237
+ },
238
+ {
239
+ "key": "account.ziniao.api_key",
240
+ "todayChain": ["json"],
241
+ "group": "json",
242
+ "category": "账号",
243
+ "readers": [
244
+ "plugins/argent-core/src/index.js:339",
245
+ "plugins/argent-core/src/index.js:573",
246
+ "plugins/argent-core/src/index.js:600",
247
+ "plugins/argent-core/src/index.js:869",
248
+ "plugins/argent-core/src/index.js:895",
249
+ "plugins/argent-core/src/index.js:2632",
250
+ "plugins/argent-core/src/index.js:3056",
251
+ "scripts/telemetry.py:137-144",
252
+ "scripts/invoice_lip_runner.py:618-625",
253
+ "scripts/check-model-auth.py:177-182"
254
+ ],
255
+ "readersNote": "以上读取点读的 config.json#apiKey 在代码里是**问述账号令牌**(config.apiKey || process.env.WHYSHU_API_KEY),不是紫鸟 Key。真正的紫鸟 Key 读在 plugins/argent-core/src/index.js:1405-1413(~/.ziniao-cli/config.json#profiles.<cur>.apiKey),写入在 scripts/init-ml.sh:256/:266,探测在 :134/:137/:141。",
256
+ "todayEnvName": "WHYSHU_API_KEY",
257
+ "canonicalEnvName": "ACCOUNT_ZINIAO_API_KEY",
258
+ "envInProduction": false,
259
+ "envFileInProduction": false,
260
+ "jsonInProduction": true,
261
+ "jsonNote": "config.json#apiKey 存在(❰已设置❱,len=191)—— 但那是问述令牌",
262
+ "activeValueSourceToday": "json",
263
+ "recommend": "B",
264
+ "recommendNote": "⛔ 不是普通 B:先修**绑定**。建议改 binding 指向 ~/.ziniao-cli/config.json(需扩展 schema 支持数据目录外文件),或把本项降级为只读存在性。⛔ 不要按现状做 A。",
265
+ "behaviorChange": "changes-if-env-set",
266
+ "behaviorChangeDetail": "按现状 A:configured 会随**问述令牌**有无而变,与设置页「紫鸟 API Key」显示(读 ~/.ziniao-cli)互相矛盾。",
267
+ "writerAtDeclaredLevel": true,
268
+ "writerAtEnvLevel": false,
269
+ "writerNote": "设置页「紫鸟 API Key」实际走 POST /api/argent-state/ziniao-key → ~/.ziniao-cli/config.json(manifest.json:154-158,hint 明写「不入 config.json」)——写的是错的那个键",
270
+ "regression": [
271
+ "设置页「紫鸟 API Key:已配置」与 ziniao-cli config show 一致",
272
+ "构造「有 config.json#apiKey 但无 ziniao 配置」夹具 ⇒ 必须报未配置",
273
+ "问述令牌相关读取点零改动(git diff 断言)"
274
+ ],
275
+ "needsUserDecision": true,
276
+ "decisionWhy": "D4:绑定改法需用户拍板(涉及数据目录外文件的 schema 扩展)",
277
+ "priority": 6,
278
+ "risk": "high"
279
+ },
280
+ {
281
+ "key": "account.carrier.user",
282
+ "todayChain": ["json"],
283
+ "group": "json",
284
+ "category": "账号",
285
+ "readers": ["scripts/invoice_runner.py:93"],
286
+ "todayEnvName": null,
287
+ "canonicalEnvName": "ACCOUNT_CARRIER_USER",
288
+ "envInProduction": false,
289
+ "envFileInProduction": false,
290
+ "jsonInProduction": true,
291
+ "activeValueSourceToday": "json",
292
+ "recommend": "A",
293
+ "behaviorChange": "none",
294
+ "behaviorChangeDetail": "客户机 env 无值 ⇒ 不变。A 后可部署期注入门户账号。",
295
+ "writerAtDeclaredLevel": true,
296
+ "writerAtEnvLevel": false,
297
+ "writerNote": "设置页(白名单 argent-core:81;面板 manifest.json:351-362)",
298
+ "regression": [
299
+ "xzh 发票 load_creds() 取到非空",
300
+ "invoice_stageb.login_xinhang() 不因凭据缺失早退"
301
+ ],
302
+ "needsUserDecision": true,
303
+ "decisionWhy": "env 名策略(D2)",
304
+ "priority": 2,
305
+ "risk": "low"
306
+ },
307
+ {
308
+ "key": "account.carrier.password",
309
+ "todayChain": ["json"],
310
+ "group": "json",
311
+ "category": "账号",
312
+ "readers": ["scripts/invoice_runner.py:93", "scripts/invoice_stageb.py:45"],
313
+ "todayEnvName": null,
314
+ "canonicalEnvName": "ACCOUNT_CARRIER_PASSWORD",
315
+ "envInProduction": false,
316
+ "envFileInProduction": false,
317
+ "jsonInProduction": true,
318
+ "activeValueSourceToday": "json",
319
+ "recommend": "A",
320
+ "behaviorChange": "none",
321
+ "behaviorChangeDetail": "客户机 env 无值 ⇒ 不变。A 后门户密码可只住 env/credentials。",
322
+ "writerAtDeclaredLevel": true,
323
+ "writerAtEnvLevel": false,
324
+ "writerNote": "设置页(secret;SECRET_KEYS:249)",
325
+ "regression": [
326
+ "掩码不回显",
327
+ "invoice_stageb 登录路径",
328
+ "写前备份/写后读回的既有守卫"
329
+ ],
330
+ "needsUserDecision": true,
331
+ "decisionWhy": "env 名策略(D2)",
332
+ "priority": 2,
333
+ "risk": "low"
334
+ },
335
+ {
336
+ "key": "advanced.telemetry.opt_in",
337
+ "todayChain": ["json"],
338
+ "group": "json",
339
+ "category": "高级与诊断",
340
+ "readers": [
341
+ "scripts/telemetry.py:276-295",
342
+ "scripts/orchestrator.py:520-548",
343
+ "plugins/argent-core/src/index.js:457",
344
+ "plugins/argent-core/src/index.js:484",
345
+ "plugins/argent-core/src/index.js:1467"
346
+ ],
347
+ "readersNote": "telemetry.enabled() 是**唯一判定来源**;orchestrator._telemetry_opt_in() 委托它;consumers scripts/telemetry.py:604/:675/:764-766",
348
+ "todayEnvName": "TELEMETRY_DISABLE",
349
+ "todayEnvSemantics": "反向硬关(压过一切,含显式同意;没有任何 env 能'打开'上报)",
350
+ "canonicalEnvName": "ADVANCED_TELEMETRY_OPT_IN",
351
+ "envInProduction": false,
352
+ "envFileInProduction": false,
353
+ "jsonInProduction": true,
354
+ "activeValueSourceToday": "json",
355
+ "recommend": "B",
356
+ "recommendRationale": "隐私同意项:必须由单一显式落点(config.json,用户可见开关)独占;TELEMETRY_DISABLE 是反向硬关,不能映射成普通 env 覆盖层。A 会把硬关降级为可覆盖 ⇒ 隐私语义倒退。",
357
+ "behaviorChange": "none",
358
+ "behaviorChangeDetail": "不变;且'不变'正是要点。附带:todayChain 漏登记了 TELEMETRY_DISABLE 这个 env 层(登记不全,非优先级错)。",
359
+ "writerAtDeclaredLevel": true,
360
+ "writerAtEnvLevel": true,
361
+ "writerNote": "设置页(advanced.json editable:true)+ 安装器同意步 install-argent.mjs:1116-1129 + argent-core saveConfig;env 层仅 TELEMETRY_DISABLE(硬关)",
362
+ "regression": [
363
+ "scripts/tests/telemetry-consent.test.mjs",
364
+ "scripts/tests/telemetry-instance-token.test.mjs 的「令牌 ≠ 同意」",
365
+ "orchestrator._telemetry_opt_in() 与 telemetry_enabled() 夹具对拍同判",
366
+ "关闭后队列清空(config-set-off / settings-off)"
367
+ ],
368
+ "needsUserDecision": true,
369
+ "decisionWhy": "D5:确认选 B 并登记 TELEMETRY_DISABLE 硬关",
370
+ "priority": 5,
371
+ "risk": "medium"
372
+ },
373
+ {
374
+ "key": "advanced.update.channel",
375
+ "todayChain": ["json"],
376
+ "group": "json",
377
+ "category": "高级与诊断",
378
+ "readers": [],
379
+ "readersNote": "⛔ 全仓 0 个读取点。唯一出现处 = 白名单 plugins/argent-core/src/index.js:81 + 声明 configs/advanced.json:50。",
380
+ "todayEnvName": null,
381
+ "canonicalEnvName": "ADVANCED_UPDATE_CHANNEL",
382
+ "envInProduction": false,
383
+ "envFileInProduction": false,
384
+ "jsonInProduction": false,
385
+ "activeValueSourceToday": "default",
386
+ "recommend": "B",
387
+ "recommendRationale": "无读者 ⇒ 翻转无意义。要么补读者(--check-update 读通道),要么如实标注'暂不生效'。",
388
+ "behaviorChange": "none",
389
+ "behaviorChangeDetail": "今天就没有任何代码读它。",
390
+ "writerAtDeclaredLevel": true,
391
+ "writerAtEnvLevel": false,
392
+ "writerNote": "设置页可写(advanced.json editable:true + kind:json ⇒ writeTargetOf 返回 config.json#updateChannel)—— 典型的'可写没人读'",
393
+ "regression": [
394
+ "若补读者:install-argent.mjs --check-update 的通道选择 + --json 输出",
395
+ "若只读展示:设置页不得声称'影响检查更新'"
396
+ ],
397
+ "needsUserDecision": true,
398
+ "decisionWhy": "D7:补读者 vs 如实标注",
399
+ "priority": 1,
400
+ "risk": "low"
401
+ },
402
+ {
403
+ "key": "hr.office.role",
404
+ "todayChain": ["json"],
405
+ "group": "json",
406
+ "category": "人事(HR)",
407
+ "bindingNote": "binding = {kind:json, file:roles.json, field:'presets.hr-office'}(configs/hr.json:20-21)",
408
+ "readers": [
409
+ "plugins/argent-gateway/src/index.js:395-399",
410
+ "plugins/argent-gateway/src/index.js:383",
411
+ "scripts/flow_preflight.py:293",
412
+ "scripts/check-role-mapping.mjs:276",
413
+ "scripts/check-role-mapping.mjs:325",
414
+ "scripts/check-role-mapping.mjs:363",
415
+ "scripts/customer-readiness.sh:61"
416
+ ],
417
+ "todayEnvName": null,
418
+ "canonicalEnvName": "HR_OFFICE_ROLE",
419
+ "envInProduction": false,
420
+ "envFileInProduction": false,
421
+ "jsonInProduction": true,
422
+ "jsonNote": "客户机 roles.json 存在,presets=13,含 hr-office",
423
+ "activeValueSourceToday": "json",
424
+ "recommend": "B",
425
+ "recommendRationale": "机器事实:角色→preset 映射由 check-role-mapping.mjs --write 生成的 roles.json 独占,本就无 env 层 ⇒ 两链同值,提示属误报。",
426
+ "behaviorChange": "none",
427
+ "behaviorChangeDetail": "无 env 层 ⇒ 翻转不改变任何取值。",
428
+ "writerAtDeclaredLevel": true,
429
+ "writerAtEnvLevel": false,
430
+ "writerNote": "node scripts/check-role-mapping.mjs --write(roles.json 唯一生成器)+ scripts/customer-config-migrate.mjs",
431
+ "regression": [
432
+ "node scripts/check-role-mapping.mjs(roles.json 与角色集一致)",
433
+ "gateway 重启后日志出现「roles.json 已应用 N 个角色映射」",
434
+ "⚠️ hr-office 2026-10-04 已退役(gateway.json 无该行,preset 是墓碑)"
435
+ ],
436
+ "needsUserDecision": true,
437
+ "decisionWhy": "D8:退役角色的目录项是否保留",
438
+ "priority": 1,
439
+ "risk": "medium"
440
+ },
441
+ {
442
+ "key": "notify.daily.chat_id",
443
+ "todayChain": ["json", "env"],
444
+ "group": "json→env",
445
+ "category": "通知与投递",
446
+ "readers": [
447
+ "scripts/daily-report.mjs:985",
448
+ "scripts/feishu-card.mjs:173",
449
+ "scripts/flow_preflight.py:274"
450
+ ],
451
+ "readerOrders": {
452
+ "scripts/daily-report.mjs:985": "json-first(pick() 定义在 scripts/daily-report.mjs:902;env = {...daily-report.env, ...process.env},:1291)",
453
+ "scripts/feishu-card.mjs:173": "env-first",
454
+ "scripts/flow_preflight.py:274": "env-first"
455
+ },
456
+ "todayEnvName": "ML_DAILY_CHAT_ID",
457
+ "canonicalEnvName": "NOTIFY_DAILY_CHAT_ID",
458
+ "envInProduction": false,
459
+ "envInProcessEnv": false,
460
+ "envFileInProduction": true,
461
+ "envFileWhere": "daily-report.env",
462
+ "jsonInProduction": false,
463
+ "activeValueSourceToday": "envfile",
464
+ "activeValueSourceTodayDetail": "daily-report.env#ML_DAILY_CHAT_ID(客户机 config.json#mlDailyChatId 不存在)",
465
+ "recommend": "A",
466
+ "recommendRationale": "部署期最常改的落点;客户机现状正是'env 文件有值 / json 无值',与声明相反。",
467
+ "behaviorChange": "changes-if-env-set",
468
+ "behaviorChangeDetail": "⛔ 客户机上**会变**:A 后规范读取器取到 **missing**(夹具实测)⇒ 日报失去推送目标(scripts/daily-report.mjs:989 抛「未配置推送通道」)。必须先落地 D1(env 文件回落)与 D2(显式声明 binding.env: ML_DAILY_CHAT_ID)。",
469
+ "writerAtDeclaredLevel": true,
470
+ "writerAtEnvLevel": false,
471
+ "writerNote": "设置页(CONFIG_KEYS:81、校验:131;面板 manifest.json:412-424);env 层无写入器(argent-env-write.mjs 只收 binding.kind=envfile 的项与面板 env 字段),env 文件由 init-ml.sh:1360 起的一次性模板生成",
472
+ "regression": [
473
+ "客户机 node scripts/daily-report.mjs --dry-run --force(不推送)确认 chat_id 来源与值同改前",
474
+ "python3 scripts/flow_preflight.py --flow daily-report 的 push 项须 ok 且群 id 前缀一致",
475
+ "回滚演练:清掉 config.json 的值 ⇒ 必须仍能取到 env 文件的值"
476
+ ],
477
+ "needsUserDecision": true,
478
+ "decisionWhy": "D1 + D2 + D3:直接 A 会让客户机日报丢推送目标",
479
+ "priority": 4,
480
+ "risk": "high"
481
+ },
482
+ {
483
+ "key": "notify.daily.profile",
484
+ "todayChain": ["json", "env"],
485
+ "group": "json→env",
486
+ "category": "通知与投递",
487
+ "readers": [
488
+ "scripts/daily-report.mjs:986",
489
+ "scripts/flow_preflight.py:273",
490
+ "scripts/feishu-card.mjs:174"
491
+ ],
492
+ "readerOrders": {
493
+ "scripts/daily-report.mjs:986": "json-first(默认常量 scripts/daily-report.mjs:922)",
494
+ "scripts/flow_preflight.py:273": "env-first",
495
+ "scripts/feishu-card.mjs:174": "env-first;且 config 回落读的是 mlDailyAlertProfile(疑似缺陷)"
496
+ },
497
+ "todayEnvName": "LARK_PROFILE",
498
+ "canonicalEnvName": "NOTIFY_DAILY_PROFILE",
499
+ "envInProduction": false,
500
+ "envInProcessEnv": false,
501
+ "envFileInProduction": true,
502
+ "envFileWhere": "daily-report.env, fulfillment.env",
503
+ "jsonInProduction": false,
504
+ "activeValueSourceToday": "envfile",
505
+ "recommend": "A",
506
+ "behaviorChange": "changes-if-env-set",
507
+ "behaviorChangeDetail": "⛔ 客户机上**会变**:A 后 **missing**(夹具实测)⇒ 回落到代码默认 ml-daily,而客户机实际用 LARK_PROFILE 指定的 Bot 身份 ⇒ 可能换身份发或发不出。",
508
+ "nameConflict": "LARK_PROFILE 已被 notify.flow.lark_profile 声明为 fulfillment.env#LARK_PROFILE(configs/notify.json:160-177)—— 同一 env 名两个项 + 两种语义",
509
+ "writerAtDeclaredLevel": true,
510
+ "writerAtEnvLevel": false,
511
+ "writerNote": "设置页(日报面板);env 层无写入器",
512
+ "regression": [
513
+ "同 notify.daily.chat_id",
514
+ "推送日志里 lark-cli --profile <X> 必须是客户机实际在群内的那个",
515
+ "flow_preflight 的「推送身份可用」须 ok"
516
+ ],
517
+ "needsUserDecision": true,
518
+ "decisionWhy": "D1 + D2 + D3 + LARK_PROFILE 同名冲突归属",
519
+ "priority": 4,
520
+ "risk": "high"
521
+ },
522
+ {
523
+ "key": "notify.daily.webhook",
524
+ "todayChain": ["json", "env"],
525
+ "group": "json→env",
526
+ "category": "通知与投递",
527
+ "readers": [
528
+ "scripts/daily-report.mjs:988",
529
+ "plugins/argent-core/src/index.js:2793",
530
+ "plugins/argent-core/src/index.js:2798"
531
+ ],
532
+ "readerOrders": {
533
+ "scripts/daily-report.mjs:988": "json-first(降级通道)",
534
+ "plugins/argent-core/src/index.js:2793": "json-first",
535
+ "plugins/argent-core/src/index.js:2798": "再正则扫 daily-report.env 文本取 FEISHU_WEBHOOK_URL ⇒ json→envfile"
536
+ },
537
+ "todayEnvName": "FEISHU_WEBHOOK_URL",
538
+ "canonicalEnvName": "NOTIFY_DAILY_WEBHOOK",
539
+ "envInProduction": false,
540
+ "envFileInProduction": false,
541
+ "jsonInProduction": false,
542
+ "activeValueSourceToday": "missing",
543
+ "recommend": "B",
544
+ "recommendRationale": "已弃用项(docs/daily-report.md:14/:100 明写 KB-057 后设置页不再暴露);不宜再给它 env 覆盖能力把弃用通道'复活'。",
545
+ "behaviorChange": "changes-if-env-set",
546
+ "behaviorChangeDetail": "客户机无变化(两链都空)。若他机 env 文件里有 FEISHU_WEBHOOK_URL,A 会忽略它 ⇒ 降级通道失效。",
547
+ "writerAtDeclaredLevel": true,
548
+ "writerAtEnvLevel": false,
549
+ "writerNote": "设置页(CONFIG_KEYS:81;SECRET_KEYS:249);init-ml.sh:1360 模板留空",
550
+ "regression": [
551
+ "POST /api/argent-state/daily-webhook-test 未配置时回可执行错误串",
552
+ "daily-report.mjs --dry-run 仅在无 chatId 时走 webhook 分支"
553
+ ],
554
+ "needsUserDecision": false,
555
+ "priority": 4,
556
+ "risk": "low"
557
+ },
558
+ {
559
+ "key": "notify.daily.alert_chat_id",
560
+ "todayChain": ["json", "env"],
561
+ "todayChainActual": ["env", "json"],
562
+ "group": "json→env",
563
+ "category": "通知与投递",
564
+ "readers": ["scripts/daily-report.mjs:1006"],
565
+ "readerOrders": { "scripts/daily-report.mjs:1006": "env-first(env.ML_DAILY_ALERT_CHAT_ID || cfg.mlDailyAlertChatId || 内部群常量 oc_8ce5…)" },
566
+ "todayEnvName": "ML_DAILY_ALERT_CHAT_ID",
567
+ "canonicalEnvName": "NOTIFY_DAILY_ALERT_CHAT_ID",
568
+ "envInProduction": false,
569
+ "envFileInProduction": false,
570
+ "jsonInProduction": true,
571
+ "jsonNote": "config.json#mlDailyAlertChatId = ❰已设置❱(len=35)",
572
+ "activeValueSourceToday": "json",
573
+ "recommend": "B",
574
+ "recommendRationale": "声明写反(§B3):所有读取点都是 env 优先 ⇒ 真相是 [env,json],与规范链首级一致。改声明后提示自然消失,**代码零改动** —— 不是'删提示'(有 1 个读取点为证)。",
575
+ "behaviorChange": "none",
576
+ "behaviorChangeDetail": "客户机 env 无值 ⇒ 两链都取 config 值(env 优先链的回落就是 config)。",
577
+ "writerAtDeclaredLevel": true,
578
+ "writerAtEnvLevel": false,
579
+ "writerNote": "设置页(面板 manifest.json:491-503)",
580
+ "regression": [
581
+ "用夹具构造推送失败路径(⛔ 不在生产上制造失败)验证告警仍发到 mlDailyAlertChatId 指定的群",
582
+ "describe() 的 chainNote 变 null"
583
+ ],
584
+ "needsUserDecision": true,
585
+ "decisionWhy": "承认声明写错(改声明)vs 反向改代码 —— 需用户拍板",
586
+ "priority": 1,
587
+ "risk": "low"
588
+ },
589
+ {
590
+ "key": "notify.daily.alert_profile",
591
+ "todayChain": ["json", "env"],
592
+ "todayChainActual": ["env", "json"],
593
+ "group": "json→env",
594
+ "category": "通知与投递",
595
+ "readers": [
596
+ "scripts/daily-report.mjs:1007",
597
+ "scripts/feishu-card.mjs:174",
598
+ "scripts/feishu-card.mjs:177",
599
+ "scripts/flow_preflight.py:277",
600
+ "scripts/flow_preflight.py:280"
601
+ ],
602
+ "readerOrders": {
603
+ "scripts/daily-report.mjs:1007": "env-first(默认常量 :930)",
604
+ "scripts/feishu-card.mjs:174": "env-first(config 作回落)",
605
+ "scripts/feishu-card.mjs:177": "env-first(config 作回落)",
606
+ "scripts/flow_preflight.py:277": "env-first(config 作回落)",
607
+ "scripts/flow_preflight.py:280": "config 作回落"
608
+ },
609
+ "todayEnvName": "ML_DAILY_ALERT_PROFILE",
610
+ "canonicalEnvName": "NOTIFY_DAILY_ALERT_PROFILE",
611
+ "envInProduction": false,
612
+ "envFileInProduction": false,
613
+ "jsonInProduction": true,
614
+ "jsonNote": "config.json#mlDailyAlertProfile = ❰已设置❱(len=20)",
615
+ "activeValueSourceToday": "json",
616
+ "recommend": "B",
617
+ "recommendRationale": "同 notify.daily.alert_chat_id:声明写反,5 个读取点为证。",
618
+ "behaviorChange": "none",
619
+ "behaviorChangeDetail": "客户机 env 无值 ⇒ 不变。",
620
+ "writerAtDeclaredLevel": true,
621
+ "writerAtEnvLevel": false,
622
+ "writerNote": "设置页(面板 manifest.json:508-519)",
623
+ "regression": [
624
+ "同 notify.daily.alert_chat_id",
625
+ "feishu-card.mjs 的 internal/daily 两种 sink 的 profile 来源比对(:174 回落读 alert profile 疑似缺陷,建议单独记 issue,⛔ 不在本批改)"
626
+ ],
627
+ "needsUserDecision": true,
628
+ "decisionWhy": "同 alert_chat_id",
629
+ "priority": 1,
630
+ "risk": "low"
631
+ },
632
+ {
633
+ "key": "ml.daily.hour",
634
+ "todayChain": ["json", "env", "default"],
635
+ "group": "json→env→default",
636
+ "category": "美客多·只读",
637
+ "readers": [
638
+ "scripts/daily-report.mjs:1308",
639
+ "scripts/daily-report.mjs:154",
640
+ "scripts/daily-report-inbox.py:88-108",
641
+ "scripts/customer-preflight.py:327-334"
642
+ ],
643
+ "readerOrders": {
644
+ "scripts/daily-report.mjs:1308": "json-first(pick(cfg,env,'mlDailyTime','REPORT_TIME','08:00'))",
645
+ "scripts/daily-report-inbox.py:88-108": "json → daily-report.env#REPORT_TIME → 进程 env REPORT_TIME → '08:00'(json-first)"
646
+ },
647
+ "todayEnvName": "REPORT_TIME",
648
+ "canonicalEnvName": "ML_DAILY_HOUR",
649
+ "envInProduction": false,
650
+ "envFileInProduction": false,
651
+ "jsonInProduction": true,
652
+ "jsonNote": "config.json#mlDailyTime = 已设置(len=5)",
653
+ "activeValueSourceToday": "json",
654
+ "recommend": "A",
655
+ "behaviorChange": "changes-if-env-set",
656
+ "behaviorChangeDetail": "客户机不变(config 有值、env 无值 ⇒ 两链同取 00:05)。若他机 daily-report.env#REPORT_TIME 有值 ⇒ A 后会被忽略。",
657
+ "writerAtDeclaredLevel": true,
658
+ "writerAtEnvLevel": false,
659
+ "writerNote": "设置页(日报面板);init-ml.sh:1365 模板 REPORT_TIME=08:00",
660
+ "regression": [
661
+ "node scripts/daily-report.mjs --dry-run --force 打印的推送时刻仍 00:05",
662
+ "python3 scripts/daily-report-inbox.py 的 gate 结论与改前逐字一致",
663
+ "python3 scripts/customer-preflight.py 的 env.daily_time 项仍 ok"
664
+ ],
665
+ "needsUserDecision": true,
666
+ "decisionWhy": "D2 env 名策略(REPORT_TIME vs ML_DAILY_HOUR)",
667
+ "priority": 3,
668
+ "risk": "medium"
669
+ },
670
+ {
671
+ "key": "ml.daily.top_n",
672
+ "todayChain": ["json", "env", "default"],
673
+ "group": "json→env→default",
674
+ "category": "美客多·只读",
675
+ "readers": [
676
+ "scripts/daily-report.mjs:1228",
677
+ "scripts/daily-report.mjs:1265",
678
+ "scripts/daily-report.mjs:1314",
679
+ "scripts/daily-report.mjs:1386"
680
+ ],
681
+ "todayEnvName": "TOP_N",
682
+ "canonicalEnvName": "ML_DAILY_TOP_N",
683
+ "envInProduction": false,
684
+ "envFileInProduction": false,
685
+ "jsonInProduction": false,
686
+ "activeValueSourceToday": "default",
687
+ "activeValueSourceTodayDetail": "default 5(两侧都空)",
688
+ "recommend": "A",
689
+ "behaviorChange": "changes-if-env-set",
690
+ "behaviorChangeDetail": "客户机不变(默认 5)。若他机 TOP_N 有值 ⇒ A 后忽略。",
691
+ "writerAtDeclaredLevel": true,
692
+ "writerAtEnvLevel": false,
693
+ "writerNote": "设置页(INT_KEYS 1–20 校验 argent-core:109);init-ml.sh:1373 模板 TOP_N=5",
694
+ "regression": [
695
+ "--dry-run 的畅销榜条数仍 5",
696
+ "--mock <夹具> 渲染行数一致",
697
+ "INT_KEYS 越界仍被拒"
698
+ ],
699
+ "needsUserDecision": true,
700
+ "decisionWhy": "D2 env 名策略",
701
+ "priority": 3,
702
+ "risk": "low"
703
+ },
704
+ {
705
+ "key": "ml.daily.restock_lead_days",
706
+ "todayChain": ["json", "env", "default"],
707
+ "group": "json→env→default",
708
+ "category": "美客多·只读",
709
+ "readers": [
710
+ "scripts/daily-report.mjs:1229",
711
+ "scripts/daily-report.mjs:1266",
712
+ "scripts/daily-report.mjs:264",
713
+ "scripts/daily-report.mjs:545"
714
+ ],
715
+ "todayEnvName": "RESTOCK_LEAD_DAYS",
716
+ "canonicalEnvName": "ML_RESTOCK_LEAD_DAYS",
717
+ "envInProduction": false,
718
+ "envFileInProduction": false,
719
+ "jsonInProduction": false,
720
+ "activeValueSourceToday": "default",
721
+ "activeValueSourceTodayDetail": "default 15(阈值 = lead + buffer = 22)",
722
+ "recommend": "A",
723
+ "behaviorChange": "changes-if-env-set",
724
+ "behaviorChangeDetail": "客户机不变。若他机 RESTOCK_LEAD_DAYS 有值 ⇒ A 后忽略。",
725
+ "writerAtDeclaredLevel": true,
726
+ "writerAtEnvLevel": false,
727
+ "writerNote": "设置页(INT_KEYS 0–90);init-ml.sh:1368 模板 RESTOCK_LEAD_DAYS=15",
728
+ "regression": [
729
+ "--dry-run 的补货预警阈值仍 22 天",
730
+ "⛔ 必须与 ml.daily.restock_buffer_days 同批(阈值 = lead + buffer)",
731
+ "computeAlerts 字面量断言"
732
+ ],
733
+ "needsUserDecision": true,
734
+ "decisionWhy": "D2 env 名策略",
735
+ "priority": 3,
736
+ "risk": "low"
737
+ },
738
+ {
739
+ "key": "ml.daily.restock_buffer_days",
740
+ "todayChain": ["json", "env", "default"],
741
+ "group": "json→env→default",
742
+ "category": "美客多·只读",
743
+ "readers": ["scripts/daily-report.mjs:1230", "scripts/daily-report.mjs:1267"],
744
+ "todayEnvName": "RESTOCK_BUFFER_DAYS",
745
+ "canonicalEnvName": "ML_RESTOCK_BUFFER_DAYS",
746
+ "envInProduction": false,
747
+ "envFileInProduction": false,
748
+ "jsonInProduction": false,
749
+ "activeValueSourceToday": "default",
750
+ "activeValueSourceTodayDetail": "default 7(阈值 = lead + buffer = 22)",
751
+ "recommend": "A",
752
+ "behaviorChange": "changes-if-env-set",
753
+ "behaviorChangeDetail": "客户机不变。若他机 RESTOCK_BUFFER_DAYS 有值 ⇒ A 后忽略。",
754
+ "writerAtDeclaredLevel": true,
755
+ "writerAtEnvLevel": false,
756
+ "writerNote": "设置页(INT_KEYS 0–90);init-ml.sh:1369 模板 RESTOCK_BUFFER_DAYS=7",
757
+ "regression": [
758
+ "同 ml.daily.restock_lead_days(同一条阈值断言)"
759
+ ],
760
+ "needsUserDecision": true,
761
+ "decisionWhy": "D2 env 名策略",
762
+ "priority": 3,
763
+ "risk": "low"
764
+ },
765
+ {
766
+ "key": "host.telemetry.instance_token",
767
+ "todayChain": ["machine", "env"],
768
+ "todayChainActual": ["env", "machine"],
769
+ "group": "machine→env",
770
+ "category": "宿主与机器",
771
+ "readers": [
772
+ "scripts/telemetry.py:206-208",
773
+ "scripts/telemetry.py:209-212",
774
+ "scripts/telemetry.py:252",
775
+ "scripts/telemetry.py:754"
776
+ ],
777
+ "readerOrders": { "scripts/telemetry.py:206-212": "env-first(ARGENT_INSTANCE_TOKEN → <数据目录>/instance-token.json),与声明相反" },
778
+ "todayEnvName": "ARGENT_INSTANCE_TOKEN",
779
+ "canonicalEnvName": "HOST_TELEMETRY_INSTANCE_TOKEN",
780
+ "envInProduction": false,
781
+ "envFileInProduction": false,
782
+ "machineInProduction": true,
783
+ "machineNote": "instance-token.json 存在(897 B)",
784
+ "activeValueSourceToday": "machine",
785
+ "recommend": "B",
786
+ "recommendRationale": "机器事实:令牌随机器走,由许可离线下发链路写入 scripts/install-license.mjs:412;ARGENT_INSTANCE_TOKEN 是运维/测试逃生阀,不是产品语义的'env 优先'。",
787
+ "behaviorChange": "changes-if-env-set",
788
+ "behaviorChangeDetail": "⛔ 会变 —— 而且现在就已经是错的:binding 缺 field ⇒ 规范读取器把整个 JSON 信封当标量,实测报「期望标量,实际拿到 object(binding 的 field 写错了?)」⇒ 落在 missing;客户机明明有令牌却显示「未配置」。",
789
+ "bindingFix": { "field": "token" },
790
+ "bindingFixAcceptance": "修后 describe().configured 由 false → true",
791
+ "writerAtDeclaredLevel": true,
792
+ "writerAtEnvLevel": false,
793
+ "writerNote": "node scripts/install-license.mjs --instance-token-file <f>(0600 + 写前判归属/设备码/期限 + 幂等)",
794
+ "regression": [
795
+ "node scripts/tests/telemetry-instance-token.test.mjs(62 例)",
796
+ "python3 scripts/telemetry.py --status 的 credential.source=instance-token、header=x-instance-token",
797
+ "describe().configured 由 false → true"
798
+ ],
799
+ "needsUserDecision": true,
800
+ "decisionWhy": "D6:确认 B + 修 field;ARGENT_INSTANCE_TOKEN 是否登记为逃生阀",
801
+ "priority": 5,
802
+ "risk": "medium"
803
+ }
804
+ ],
805
+ "batches": [
806
+ {
807
+ "id": "3-1",
808
+ "title": "零行为变化·只改声明",
809
+ "items": ["notify.daily.alert_chat_id", "notify.daily.alert_profile", "advanced.update.channel", "hr.office.role"],
810
+ "why": "4 项都没有任何 env 值,翻转后取值逐字不变;其中 2 项是'改正写反的声明'(有读取点为证)",
811
+ "regression": [
812
+ "node scripts/check-config-catalog.mjs --strict 四道门禁全绿",
813
+ "node scripts/tests/config-gates.test.mjs",
814
+ "chainNote 项数由 18 → 14",
815
+ "这 4 项在客户机的取值与改前一致(只读 --list 输出逐字比对)"
816
+ ],
817
+ "risk": "low"
818
+ },
819
+ {
820
+ "id": "3-2",
821
+ "title": "账号面(无 env 值)",
822
+ "items": ["account.feishu.app_id", "account.feishu.app_secret", "account.carrier.user", "account.carrier.password"],
823
+ "why": "客户机这 4 项只有 config.json 有值、env 全空 ⇒ 翻转不改值;先用低风险项验证'显式声明 binding.env'的机制",
824
+ "regression": [
825
+ "设置页 4 个字段保存→读回(掩码不回明文)",
826
+ "POST /api/argent-state/feishu-test(桩化)",
827
+ "plugins/argent-gateway 启动日志仍打印 Bot 配置",
828
+ "xzh 发票 load_creds() 取到非空(不联网路径)"
829
+ ],
830
+ "risk": "low"
831
+ },
832
+ {
833
+ "id": "3-3",
834
+ "title": "日报数值旋钮(有 default)",
835
+ "items": ["ml.daily.hour", "ml.daily.top_n", "ml.daily.restock_lead_days", "ml.daily.restock_buffer_days"],
836
+ "why": "有 default ⇒ 最坏退到默认;客户机三项空、mlDailyTime 有值 ⇒ 预期零变化;restock 两项必须同批(阈值 = lead + buffer)",
837
+ "regression": [
838
+ "node scripts/daily-report.mjs --dry-run --force:推送时刻仍 00:05、畅销榜仍 5 条、补货阈值仍 22 天(逐字比对)",
839
+ "python3 scripts/daily-report-inbox.py 的 gate 同结论",
840
+ "python3 scripts/customer-preflight.py 的 env.daily_time 仍 ok",
841
+ "--mock <夹具> 渲染不回归"
842
+ ],
843
+ "risk": "medium"
844
+ },
845
+ {
846
+ "id": "3-4",
847
+ "title": "日报投递面(生产推送目标)",
848
+ "items": ["notify.daily.webhook", "notify.daily.chat_id", "notify.daily.profile"],
849
+ "why": "⛔ 本批会改变生效值;必须等 3-1~3-3 验证完迁移机制、D1/D2/D3 决策落地、且双写窗口开启后再做;弃用项 webhook 放最前(零风险)",
850
+ "regression": [
851
+ "客户机 node scripts/daily-report.mjs --dry-run --force(只打印不推送)确认 chat_id/profile 来源与值同改前",
852
+ "python3 scripts/flow_preflight.py --flow daily-report 的 push 项 ok、群 id 前缀一致",
853
+ "一次真实投递到测试群(需用户单独批准,⛔ 不直发客户群)",
854
+ "回滚演练:清掉 config.json 的值 ⇒ 必须仍能取到 env 文件的值"
855
+ ],
856
+ "risk": "high",
857
+ "requiresUserApproval": true
858
+ },
859
+ {
860
+ "id": "3-5",
861
+ "title": "隐私与机器事实",
862
+ "items": ["advanced.telemetry.opt_in", "host.telemetry.instance_token"],
863
+ "why": "语义最敏感(同意/凭证),且 instance_token 的 binding 当前读不出值 ⇒ 修复本身要单独验证;不涉及生产业务流,可与 3-4 解耦",
864
+ "regression": [
865
+ "node scripts/tests/telemetry-consent.test.mjs",
866
+ "node scripts/tests/telemetry-instance-token.test.mjs(62 例)",
867
+ "python3 scripts/telemetry.py --status 的 credential.source=instance-token、header=x-instance-token",
868
+ "instance_token 修 field 后 describe().configured 由 false→true",
869
+ "orchestrator._telemetry_opt_in() 与 telemetry_enabled() 夹具对拍同判"
870
+ ],
871
+ "risk": "medium"
872
+ },
873
+ {
874
+ "id": "3-6",
875
+ "title": "语义错绑(最后)",
876
+ "items": ["account.ziniao.api_key"],
877
+ "why": "唯一'改声明本身就要动 schema'的项,且影响设置页「紫鸟 API Key」的真假判断 ⇒ 放最后,前面各批的经验(schema 扩展、binding.field、证据闭合)都用得上",
878
+ "regression": [
879
+ "设置页「紫鸟 API Key:已配置/未配置」与 ziniao-cli config show、~/.ziniao-cli/config.json 存在性三处一致",
880
+ "目录项取值不得再受问述令牌影响(夹具:有 config.json#apiKey 但无 ziniao 配置 ⇒ 必须报未配置)",
881
+ "问述令牌相关 7 处读取点零改动(git diff 断言)"
882
+ ],
883
+ "risk": "high",
884
+ "requiresUserApproval": true
885
+ }
886
+ ],
887
+ "_commonRegression": [
888
+ "node scripts/check-config-catalog.mjs --strict",
889
+ "node scripts/tests/config-gates.test.mjs",
890
+ "node -e 'import(\"./core/lib/config-catalog.mjs\").then(m=>{const i=m.loadCatalog().items.filter(x=>m.chainNoteOf(x));console.log(i.length,i.map(x=>x.key).join(\",\"))})'"
891
+ ],
892
+ "_discipline": {
893
+ "readOnly": true,
894
+ "changedExistingFiles": false,
895
+ "customerMachineWrites": false,
896
+ "secretsInThisFile": false,
897
+ "note": "客户机只跑只读命令(ls/awk/python3 读取 + ps/plutil/launchctl print),未写未改未重启,未落任何远程文件(脚本经 stdin 管道执行)。"
898
+ }
899
+ }