@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,1065 @@
1
+ {
2
+ "argentVersion": "0.6.0",
3
+ "principle": "宿主无关:宿主只依赖 `argent <verb>`;确定性逻辑在 CLI/MCP,不在提示词里。",
4
+ "verbs": {
5
+ "version": {
6
+ "kind": "read",
7
+ "desc": "Argent 版本 + dsh 版本 + 计费模式",
8
+ "args": []
9
+ },
10
+ "sop": {
11
+ "kind": "read",
12
+ "desc": "取流程 SOP(提示词/技能目录/踩坑)",
13
+ "args": [
14
+ "--flow"
15
+ ]
16
+ },
17
+ "source": {
18
+ "kind": "read",
19
+ "desc": "按注册表 source.kind 拉源 → cases",
20
+ "args": [
21
+ "--flow",
22
+ "--json"
23
+ ]
24
+ },
25
+ "flow": {
26
+ "kind": "group",
27
+ "desc": "流程族:claim(原子认领,默认 dry-run)|triage(只出计划,旧 claim 行为)|list(注册表只读清单)",
28
+ "args": [
29
+ "claim",
30
+ "triage",
31
+ "list"
32
+ ],
33
+ "subcommands": {
34
+ "claim": "原子认领(planned + 租约);默认 dry-run,真写要 --apply/--confirm",
35
+ "triage": "只出计划不落台账(旧 `claim` 行为,逐字保留)",
36
+ "list": "注册表只读清单(薄包 flow_registry.py --json;不实现合并)"
37
+ }
38
+ },
39
+ "claim": {
40
+ "kind": "write",
41
+ "desc": "原子认领待跑票(台账 planned + 租约);默认 dry-run",
42
+ "args": [
43
+ "--flow",
44
+ "--max",
45
+ "--lease-min",
46
+ "--cases-from-dir",
47
+ "--apply",
48
+ "--plan-only",
49
+ "--json"
50
+ ],
51
+ "guarantees": [
52
+ "idempotent",
53
+ "audited",
54
+ "dry-run-by-default"
55
+ ],
56
+ "legacyPlanOnly": "`claim --plan-only` = 旧的分诊行为(等价 `flow triage`);改名只为把名字还给真正的认领"
57
+ },
58
+ "triage": {
59
+ "kind": "read",
60
+ "desc": "分诊计划(只出计划,不落台账)—— 旧 `claim` 行为,逐字保留",
61
+ "args": [
62
+ "--flow",
63
+ "--cases-from-dir",
64
+ "--json"
65
+ ]
66
+ },
67
+ "gap": {
68
+ "kind": "read",
69
+ "desc": "字段缺口检查",
70
+ "args": [
71
+ "--flow",
72
+ "--ticket"
73
+ ]
74
+ },
75
+ "writeback": {
76
+ "kind": "write",
77
+ "desc": "白名单守卫回写(写前备份/写后读回/审计)",
78
+ "args": [
79
+ "--flow",
80
+ "--record-id",
81
+ "--allow-record"
82
+ ],
83
+ "guarantees": [
84
+ "whitelist",
85
+ "backup",
86
+ "readback",
87
+ "audit"
88
+ ]
89
+ },
90
+ "report": {
91
+ "kind": "net",
92
+ "desc": "失败上报(带 DOM/日志证据)",
93
+ "args": [
94
+ "--flow",
95
+ "--ticket",
96
+ "--step"
97
+ ]
98
+ },
99
+ "ledger": {
100
+ "kind": "read",
101
+ "desc": "台账查询(唯一真相)",
102
+ "args": [
103
+ "--flow",
104
+ "--tail"
105
+ ]
106
+ },
107
+ "license": {
108
+ "kind": "read",
109
+ "desc": "离线许可组:status(三态+能力门+设备)|verify(验签本身)|install --file(默认 dry-run)|request(设备码)|renew --file(默认 dry-run)|explain(缺什么/下一步)|activate --code(一次性激活码兑换:默认 dry-run,真兑换要 --apply)|ops(只读运营巡检 O2:在途码/失败码/事件时间线/席位账目/异常清单,替代 mongosh)",
110
+ "args": [
111
+ "status",
112
+ "verify",
113
+ "install",
114
+ "request",
115
+ "renew",
116
+ "explain",
117
+ "activate",
118
+ "ops"
119
+ ],
120
+ "subcommands": {
121
+ "status": "三态(valid/grace/denied)+ 能力/业务线命中 + 设备绑定态;透传 check-license 退出码 0/3/1/2",
122
+ "verify": "只验一份许可(HMAC-SHA256 + canonicalJson + 判期 + 设备比对),**不落盘**",
123
+ "install": "验签 + 设备比对后落盘(0600 / 临时文件 rename / 覆盖前备份);**默认 dry-run**,真写要 --apply",
124
+ "request": "打印**设备码**(离线激活第一步;指纹只认 IOPlatformUUID,禁止主机名/MAC/IP/安装路径)",
125
+ "renew": "续期:离线 = 换一份新许可文件(默认 dry-run);没有新文件 ⇒ 成功但空(empty:true),**绝不当 denied**",
126
+ "explain": "把三态翻译成「缺什么 / 下一步做什么」(只重组 check-license --json 的既有字段)",
127
+ "activate": "一次性激活码兑换(方案 §9):用网页/手机端**登录后**生成的一次性码,换一份**绑定本机设备码**的许可。**默认 dry-run**(零网络请求 + 零落盘,连审计都不落),真兑换要 `--apply`。两步:先 `argent license request` 拿设备码 → 再 `activate --code <码>`。落盘复用 `scripts/install-license.mjs` 的既有判据(验签/设备比对/0600/备份/读回/幂等/拒绝倒退);**明文码绝不出现在任何输出里**(只回显 codePrefix)。",
128
+ "ops": "只读运营巡检(O2:替代 `mongosh`):在途码(state∈issued|redeeming + TTL 剩余/failCount)|失败码(failCount>0 或 revoked + code_redeem_denied/code_revoke_denied 计数)|近 N 天事件时间线(只 action/result/codePrefix)|席位账目(seats + deviceLimit(缺省跟随 seats)+ used=releasedAt 为空的设备码去重数)|异常清单(在途码超 TTL 未终态 / 同设备挂多账号且均未释放 / audit 里 device_release/rejected 探针痕迹 / …)。**只读且零副作用**:不写任何集合/文件/审计,HTTP 只发 GET(⛔ 绝不调 POST /release-device)。数据源三选一:`--from <快照>`|`--server <base>`(管理员 JWT,只从 600 的 `*.env` 读)|缺省=本机只读产物。答不了的节**如实标 available:false + needs**,⛔ 不用 0 充数;两个已知陷阱(`state` 不是 `status`、席位是算出来的)一律 `field_missing`(exit 2)响亮失败。"
129
+ }
130
+ },
131
+ "doctor": {
132
+ "kind": "read",
133
+ "desc": "环境自检:`--customer` = 客户机一页式自检(整机/只读/**不要求 dsh**);`--flow <id>` = 单流程前置检查(转发 flow_preflight.py)",
134
+ "args": [
135
+ "--customer",
136
+ "--flow",
137
+ "--online",
138
+ "--json"
139
+ ],
140
+ "subforms": {
141
+ "customer": {
142
+ "form": "--customer [--json]",
143
+ "exitCodes": [
144
+ 0,
145
+ 1,
146
+ 2
147
+ ],
148
+ "desc": "客户机一页式自检(M1 判据③):数据目录 / 解释器 / 外发技能 / 许可 / 通知通道 / 数据源可达性 / 宿主档事实",
149
+ "sevenChecks": [
150
+ "data_dir",
151
+ "interpreter",
152
+ "skills",
153
+ "license",
154
+ "channels",
155
+ "source",
156
+ "host"
157
+ ],
158
+ "levels": {
159
+ "ok": "通过",
160
+ "warn": "需看一眼(**不改变退出码**)",
161
+ "fail": "硬失败(exit 1 + reason=check_failed)"
162
+ },
163
+ "notFail": [
164
+ "无 dsh(宿主档事实记 applicable:false「本档不适用」)",
165
+ "缺许可(reason=missing ⇒ warn)",
166
+ "缺技能/只装一半(warn + 安装命令)",
167
+ "数据目录不存在但可建(warn + init --apply)"
168
+ ],
169
+ "judgmentsFrom": [
170
+ "J7-license-three-state",
171
+ "J9-data-dir-audit-backup",
172
+ "core/lib/python.mjs(D3)",
173
+ "core/lib/notify/index.mjs(P2 端口)",
174
+ "scripts/flow_registry.py(注册表唯一真源)"
175
+ ],
176
+ "noNewJudgment": "本子形态**不新增判断**:每条检查都调既有唯一入口,只把事实分成 ok/warn/fail 三档并给处置建议",
177
+ "sideEffects": {
178
+ "writes": "none",
179
+ "settings": false,
180
+ "credentials": false,
181
+ "notifications": false,
182
+ "note": "JSON 的 sideEffects 是机器可读自证;回归用「夹具目录逐文件 sha 前后一致」验(scripts/tests/doctor-customer.test.mjs)"
183
+ },
184
+ "impl": "core/lib/doctor-customer.mjs"
185
+ },
186
+ "flow": {
187
+ "form": "--flow <id> [--online] [--json]",
188
+ "desc": "单流程前置检查(逐字保留旧行为,转发 scripts/flow_preflight.py;缺 --flow ⇒ 2)",
189
+ "impl": "scripts/flow_preflight.py"
190
+ }
191
+ }
192
+ },
193
+ "notify": {
194
+ "kind": "net",
195
+ "desc": "通知投递(P2):通道选择 + 幂等去重 + dry-run;默认 dry-run,真发要 --apply",
196
+ "args": [
197
+ "--channel",
198
+ "--url",
199
+ "--target",
200
+ "--text",
201
+ "--file",
202
+ "--body-json",
203
+ "--kind",
204
+ "--summary",
205
+ "--header",
206
+ "--idempotency-key",
207
+ "--timeout-ms",
208
+ "--apply",
209
+ "--send",
210
+ "--dry-run",
211
+ "--json"
212
+ ]
213
+ },
214
+ "init": {
215
+ "kind": "read",
216
+ "desc": "数据目录画像(判断⑧):数据目录/解释器候选/已装技能/许可/通道/宿主档事实;默认 dry-run,--apply 才建目录",
217
+ "args": [
218
+ "--apply",
219
+ "--dry-run",
220
+ "--json"
221
+ ]
222
+ },
223
+ "versions": {
224
+ "kind": "read",
225
+ "desc": "版本对账(只读):CLI/契约/内核整树 sha/能力包版本/宿主补丁清单/宿主版本",
226
+ "args": [
227
+ "--only",
228
+ "--json"
229
+ ]
230
+ },
231
+ "audit": {
232
+ "kind": "read",
233
+ "desc": "审计 JSONL 只读汇总:先全量→按 --since 过滤→合并排序→取末尾 N 行",
234
+ "args": [
235
+ "--source",
236
+ "--since",
237
+ "--tail",
238
+ "--json"
239
+ ]
240
+ }
241
+ },
242
+ "judgmentMeta": {
243
+ "purpose": "判断面清单(P0 0.1):把「哪些判断必须由 L1 做」从默契变成清单 + 可判形式。宿主只做「选 verb → 读 $? 与 JSON → 按 reason 处置」,不得复述本段任何常量。",
244
+ "ownerForm": "<仓库相对路径>:<行号>(1-based)。owner = 主实现位置;implementations = 全部已声明实现位置(含 owner,逐条带 anchor)。",
245
+ "ownerSlackLines": 25,
246
+ "anchorRule": "anchor 是逐字字面量,必须出现在该实现文件的 [行号−slack, 行号+slack] 内;同一 anchor 出现在扫描面里的**未声明**文件 ⇒ 报漂移(代码有契约没有)。",
247
+ "scan": {
248
+ "globs": [
249
+ "core/**/*.mjs",
250
+ "core/**/*.js",
251
+ "scripts/**/*.mjs",
252
+ "scripts/**/*.py"
253
+ ],
254
+ "excludeGlobs": [
255
+ "scripts/tests/**",
256
+ "scripts/archive/**",
257
+ "scripts/patches/**"
258
+ ],
259
+ "note": "扫描面 = L1 代码文件(契约 §1:core/ + scripts/ 引擎);测试/归档/补丁不算实现位。glob 与 anchor 全部来自本文件,门禁不另写第二份清单。"
260
+ },
261
+ "restateRule": "复述判据(P0 0.4 / §P0-A V1):skills/**/SKILL.md、verticals/**/prompts/*.md 与 presets/**/*.yml(2026-10-04 扩展,A5)里,同一行命中 ≥2 个 restateTokens 且**无引用点**(judgmentMeta.restateCitationTokens)⇒ 记一条告警(默认只 warn,--strict 才红)。token 同样从本清单读。",
262
+ "restateScan": {
263
+ "globs": [
264
+ "skills/**/SKILL.md",
265
+ "verticals/**/prompts/*.md",
266
+ "presets/**/*.yml"
267
+ ],
268
+ "excludeGlobs": [],
269
+ "citationTokens": [
270
+ "argent ",
271
+ "scripts/flow_",
272
+ "flows.json",
273
+ "flow-requirements.json",
274
+ "core/contracts/"
275
+ ],
276
+ "baselineNote": "首日允许非零(§2.3 D5 基线:白名单枚举 4 处、终态枚举 6 处);先 warn + 基线清单、后收紧,否则就是恒红陷阱。|**2026-10-04 扩展扫描面到 `presets/**/*.yml`**(角色 preset 的 persona 也是提示词,此前不在扫描面 ⇒ 盘点文档 §4-③ 的 2 处 J2 白名单复述「门禁看不见」):扩展后**首测 +2**(`presets/argent-ml-invoice-{wy,xzh}/agent.cordis.yml` 的同一行逐字枚举四字段)——同批已改成**引用**(写手姿态 `argent writeback --print-posture` 的 `allowedFields`,声明在 `flow-requirements.json#capabilities.invoice.writeFields`)⇒ **presets 命中 0**;同一处「在飞上限 2」也改成不写数字(该常量 CLI/契约里根本没有)。**扩展后基线 = skills/ 20 条不变(终态/状态机/历史证据类,下一批收口),presets/ 0 条**;口径仍是先 warn(`--strict` 才红),不一次全红。",
277
+ "minTokens": 2
278
+ },
279
+ "exitCodes": "见 core/contracts/verbs.schema.json#exitCodes(唯一口径,A1);本文件的每条 onReject.code 必须落在该表内。",
280
+ "onRejectForm": "{ code, reason, effect }:code 见 verbs.schema.json#exitCodes;reason 见本文件 reasonCodes;effect = 处置(谁该做什么)。",
281
+ "reasonScanGlobs": [
282
+ "core/lib/claim.mjs",
283
+ "core/lib/ledger.mjs",
284
+ "core/lib/license.mjs",
285
+ "core/lib/license-device.mjs",
286
+ "core/lib/license-verdict.mjs",
287
+ "core/lib/license-guard.mjs",
288
+ "core/lib/notify/verb.mjs",
289
+ "core/lib/notify/index.mjs",
290
+ "core/lib/notify/webhook.mjs",
291
+ "core/lib/notify/feishu.mjs",
292
+ "core/lib/notify/wecom.mjs",
293
+ "core/lib/doctor-customer.mjs",
294
+ "core/lib/license-activate.mjs",
295
+ "core/lib/license-ops.mjs"
296
+ ],
297
+ "reasonScanNote": "A2 适配层里发出的 reason 短码必须在 reasonCodes 里(P1 第二批起覆盖 `core/lib/license*.mjs`;P1 第三批起覆盖 P2 通知端口 `core/lib/notify/*.mjs`)。P4 起覆盖客户机自检 `core/lib/doctor-customer.mjs`(fail 短码 = check_failed)。其余 verb 的 a2.compliant=false 已如实登记,待后续批次收口。一次性激活码兑换(`core/lib/license-activate.mjs`)同批纳入扫描面:它发出的每个短码都必须在 reasonCodes 里。 只读运营巡检(`core/lib/license-ops.mjs`,O2)同批纳入扫描面:它发出的每个短码都必须在 reasonCodes 里(`field_missing` 为它新增 —— 两个已知陷阱的响亮失败码)。"
298
+ },
299
+ "judgments": {
300
+ "J1-source-pick-gate": {
301
+ "id": "J1",
302
+ "title": "数据源门禁与必需字段(候选收窄 · 缺口归桶)",
303
+ "owner": "scripts/flow_sources/common.py:264",
304
+ "implementations": [
305
+ {
306
+ "at": "scripts/flow_sources/common.py:264",
307
+ "anchor": "def apply_pick"
308
+ },
309
+ {
310
+ "at": "scripts/flow_sources/common.py:407",
311
+ "anchor": "def required_projection"
312
+ },
313
+ {
314
+ "at": "scripts/flow_sources/common.py:231",
315
+ "anchor": "def wanted_pick_columns"
316
+ }
317
+ ],
318
+ "declaredIn": [
319
+ "verticals/*/flows.json#flows.*.source.pick",
320
+ "verticals/*/flows.json#flows.*.required"
321
+ ],
322
+ "inputs": [
323
+ "源行 fields",
324
+ "流程声明的 source.pick(equals / excludeEquals / excludeAllPresent)",
325
+ "流程声明的 required[].role(input/state 才拉,output/derived 不拉)"
326
+ ],
327
+ "outputs": [
328
+ "候选行集合(收窄后)",
329
+ "必需字段投影列名",
330
+ "缺口按 owner 归桶:need_fields(运营补数据,落卡等人)/ 仍可派发(系统字段)"
331
+ ],
332
+ "onReject": {
333
+ "code": 0,
334
+ "reason": "no_ticket",
335
+ "effect": "收窄后为空是**合法结论**(本轮无事可做),不是错误;必须带 notes 说明为何为空(已推送/未到点/窗口已过/等人补字段)"
336
+ }
337
+ },
338
+ "J2-writeback-whitelist": {
339
+ "id": "J2",
340
+ "title": "回写白名单(字段级 + 记录级 + 单向释放字段)",
341
+ "owner": "scripts/wenyao-invoice-writeback.mjs:79",
342
+ "implementations": [
343
+ {
344
+ "at": "scripts/wenyao-invoice-writeback.mjs:79",
345
+ "anchor": "export const ALLOWED_FIELDS"
346
+ },
347
+ {
348
+ "at": "scripts/wenyao-invoice-writeback.mjs:93",
349
+ "anchor": "export const ONEWAY_FALSE_FIELDS"
350
+ },
351
+ {
352
+ "at": "scripts/wenyao-invoice-writeback.mjs:152",
353
+ "anchor": "export function guardRecord"
354
+ }
355
+ ],
356
+ "declaredIn": [
357
+ "scripts/flow-requirements.json#capabilities.invoice.writeFields"
358
+ ],
359
+ "inputs": [
360
+ "目标字段名 + 值",
361
+ "--allow-record <recordId>(记录白名单必填)",
362
+ "附件字段标记(附件只能走上传通道,不能当普通值写)"
363
+ ],
364
+ "outputs": [
365
+ "guardPatch 结论:{ok:true} 或 {ok:false, error}",
366
+ "被拒原因串(field-not-whitelisted / attachment-field-needs-upload / missing-allow-record / record-not-whitelisted)"
367
+ ],
368
+ "onReject": {
369
+ "code": 1,
370
+ "reason": "guard_rejected",
371
+ "effect": "拒绝且**零副作用**(不许先写后撤回);调用方按 error 串改参数或请人,不得当成功继续"
372
+ },
373
+ "restateTokens": [
374
+ "发票状态",
375
+ "发票文件",
376
+ "大货标签",
377
+ "发票错误信息"
378
+ ]
379
+ },
380
+ "J3-terminal-state": {
381
+ "id": "J3",
382
+ "title": "状态机与终态(终态需 --force;同一个值 = noop)",
383
+ "owner": "scripts/wenyao-invoice-writeback.mjs:160",
384
+ "implementations": [
385
+ {
386
+ "at": "scripts/wenyao-invoice-writeback.mjs:160",
387
+ "anchor": "export function guardStatusTransition"
388
+ },
389
+ {
390
+ "at": "scripts/wenyao-invoice-writeback.mjs:94",
391
+ "anchor": "export const STATUS_OPTIONS"
392
+ },
393
+ {
394
+ "at": "scripts/wenyao-invoice-writeback.mjs:100",
395
+ "anchor": "export const STATUS_TERMINAL"
396
+ }
397
+ ],
398
+ "declaredIn": [
399
+ "verticals/*/flows.json#flows.*.guards"
400
+ ],
401
+ "inputs": [
402
+ "当前状态(规范化后)",
403
+ "目标状态",
404
+ "--force(显式确权)"
405
+ ],
406
+ "outputs": [
407
+ "{ok:true, action:'write'|'noop', from, to} 或 {ok:false, error}",
408
+ "终态判定:from ∈ STATUS_TERMINAL ⇒ 无 --force 即拒"
409
+ ],
410
+ "onReject": {
411
+ "code": 1,
412
+ "reason": "guard_rejected",
413
+ "effect": "拒绝写(terminal-status-needs-force / unknown-status);重跑终态行必须由人显式加 --force"
414
+ },
415
+ "restateTokens": [
416
+ "已上传",
417
+ "标签已下载",
418
+ "已完成"
419
+ ]
420
+ },
421
+ "J4-failure-classification": {
422
+ "id": "J4",
423
+ "title": "失败分类阈值(retryable / needs_human / needs_agent)",
424
+ "owner": "scripts/flow_failure.py:118",
425
+ "implementations": [
426
+ {
427
+ "at": "scripts/flow_failure.py:118",
428
+ "anchor": "GROUPS = (('capacityFull', 'needs_human')"
429
+ },
430
+ {
431
+ "at": "scripts/flow_failure.py:121",
432
+ "anchor": "DEFAULT_KIND ="
433
+ }
434
+ ],
435
+ "declaredIn": [
436
+ "scripts/flow-requirements.json#failureClasses"
437
+ ],
438
+ "inputs": [
439
+ "错误文本(stdout/stderr/DOM 证据)",
440
+ "尝试次数 attempt"
441
+ ],
442
+ "outputs": [
443
+ "kind ∈ {retryable, needs_human, needs_agent}(未知一律 needs_agent)",
444
+ "命中的**组**名(capacityFull / pageFlaky / …)进 reason,便于区分是哪条链",
445
+ "是否唤醒掌舵者:只有 needs_agent 叫醒"
446
+ ],
447
+ "onReject": {
448
+ "code": 0,
449
+ "reason": "no_ticket",
450
+ "effect": "分类本身不失败;阈值改变 = 契约级改动(规则唯一权威是 flow-requirements.json#failureClasses,禁止在 SKILL/提示词里另写一套)"
451
+ },
452
+ "restateTokens": [
453
+ "retryable",
454
+ "needs_human",
455
+ "needs_agent"
456
+ ]
457
+ },
458
+ "J5-idempotency-key": {
459
+ "id": "J5",
460
+ "title": "幂等键(caseId = flowId__ticketKey;台账是唯一真相)",
461
+ "owner": "scripts/flow_sources/common.py:387",
462
+ "implementations": [
463
+ {
464
+ "at": "scripts/flow_sources/common.py:387",
465
+ "anchor": "def ticket_key"
466
+ },
467
+ {
468
+ "at": "scripts/flow_case.py:66",
469
+ "anchor": "def case_id"
470
+ }
471
+ ],
472
+ "declaredIn": [
473
+ "verticals/*/flows.json#flows.*.source.ticketKey",
474
+ "core/lib/ledger.mjs#queryLedger"
475
+ ],
476
+ "inputs": [
477
+ "源行 record_id",
478
+ "票号列的值",
479
+ "流程声明的 source.ticketKey(record_id | ticketField,缺省=票号列优先)"
480
+ ],
481
+ "outputs": [
482
+ "ticketKey(行身份)",
483
+ "caseId(幂等键:同流程同票 = 同 case ⇒ 不重复建案/不重复派发)"
484
+ ],
485
+ "onReject": {
486
+ "code": 0,
487
+ "reason": "no_ticket",
488
+ "effect": "身份取不到 ⇒ 该行不进候选(不是错误);⛔ 不许用「目录里最新的文件」之类的兜底冒充身份"
489
+ }
490
+ },
491
+ "J6-lease-and-concurrency": {
492
+ "id": "J6",
493
+ "title": "租约与并发(planned + leaseUntil;按店/按 IP 限并发)",
494
+ "owner": "scripts/flow_claim.py:92",
495
+ "implementations": [
496
+ {
497
+ "at": "scripts/flow_claim.py:92",
498
+ "anchor": "def live_leases"
499
+ },
500
+ {
501
+ "at": "scripts/flow_claim.py:128",
502
+ "anchor": "def select_candidates"
503
+ },
504
+ {
505
+ "at": "scripts/flow_claim.py:180",
506
+ "anchor": "def planned_record"
507
+ }
508
+ ],
509
+ "declaredIn": [
510
+ "verticals/*/flows.json#flows.*.concurrency",
511
+ "scripts/flow-requirements.json#lease"
512
+ ],
513
+ "inputs": [
514
+ "台账里的最新事件(planned / done / failed / blocked)",
515
+ "leaseUntil 与 now",
516
+ "流程配置 concurrency(max / leaseMin / perStore / batchPerStore / perIp)"
517
+ ],
518
+ "outputs": [
519
+ "本轮可认领的票(atomic:锁内 读 triage → 选票 → 写 planned)",
520
+ "每店/每 IP 的在飞计数"
521
+ ],
522
+ "onReject": {
523
+ "code": 0,
524
+ "reason": "no_ticket",
525
+ "effect": "无票可认领 = 正常态(exit 0 + empty:true;脚本内部的 3 由 verb 适配层翻译,禁止把 3 用作第二语义)"
526
+ }
527
+ },
528
+ "J7-license-three-state": {
529
+ "id": "J7",
530
+ "title": "许可三态与能力门(0 允许 / 3 宽限放行 / 1 拒绝)+ 离线设备绑定(unbound 放行 / mismatch 宽限或拒绝)",
531
+ "owner": "scripts/check-license.mjs:88",
532
+ "implementations": [
533
+ {
534
+ "at": "scripts/check-license.mjs:88",
535
+ "anchor": "const exitCode = allowed"
536
+ },
537
+ {
538
+ "at": "scripts/license-gate.mjs:55",
539
+ "anchor": "export function normalizeMode"
540
+ },
541
+ {
542
+ "at": "core/lib/license-verdict.mjs:49",
543
+ "anchor": "export function licenseVerdict"
544
+ },
545
+ {
546
+ "at": "core/lib/license-device.mjs:168",
547
+ "anchor": "export function bindingOf"
548
+ },
549
+ {
550
+ "at": "core/lib/license-device.mjs:46",
551
+ "anchor": "export function readFingerprint"
552
+ },
553
+ {
554
+ "at": "core/lib/license-guard.mjs:48",
555
+ "anchor": "export function gateWrite"
556
+ },
557
+ {
558
+ "at": "core/lib/license.mjs:472",
559
+ "anchor": "export function runLicenseVerb"
560
+ }
561
+ ],
562
+ "declaredIn": [
563
+ "scripts/flow-requirements.json#lease",
564
+ "core/lib/license-file.mjs",
565
+ "core/lib/license-verdict.mjs",
566
+ "core/lib/license-device.mjs",
567
+ "core/contracts/verbs.schema.json#verbs.*.licenseGate"
568
+ ],
569
+ "inputs": [
570
+ "许可文件(离线验签 + 有效期 + capabilities)",
571
+ "--cap / --vertical(能力门)",
572
+ "闸门模式(off / observe / enforce;默认 observe)",
573
+ "载荷里**可选**的 `device` 声明 + 本机设备码(指纹**只认 IOPlatformUUID**,D3)",
574
+ "自助重绑计数($ARGENT_DATA_DIR/license-rebind.json:3 次 + 7 天宽限)"
575
+ ],
576
+ "outputs": [
577
+ "state ∈ {valid, grace, denied}(**不新增第四态**:设备不匹配在宽限内复用 grace)",
578
+ "退出码 0 / 3 / 1(3 = 宽限放行,必须上报)",
579
+ "设备绑定态:unbound / match / rebound / mismatch / unsupported(± reason:unbound、device_mismatch、rebind_exhausted…)",
580
+ "证据 JSONL(observe 模式只留痕不停派);写类 verb 在 enforce 下拒绝时**零副作用**"
581
+ ],
582
+ "onReject": {
583
+ "code": 1,
584
+ "reason": "guard_rejected",
585
+ "effect": "denied ⇒ 停派/拒写(不带 3);grace ⇒ 继续跑业务但必须上报。⛔ `device` **未进签名**(v1 只签 9 项)⇒ 只能当“服务端声明 + 客户端比对”,不得当已验签字段引用"
586
+ }
587
+ },
588
+ "J8-readiness-gate": {
589
+ "id": "J8",
590
+ "title": "就绪判据(店铺逐字归属 + 运营放行位;Bridge 就绪属宿主档事实)",
591
+ "owner": "scripts/flow_claim.py:26",
592
+ "implementations": [
593
+ {
594
+ "at": "scripts/flow_claim.py:26",
595
+ "anchor": "def _ziniao_stores"
596
+ },
597
+ {
598
+ "at": "scripts/flow_claim.py:50",
599
+ "anchor": "def _ziniao_store_ips"
600
+ },
601
+ {
602
+ "at": "scripts/flow_triage.py:387",
603
+ "anchor": "def release_gate"
604
+ }
605
+ ],
606
+ "declaredIn": [
607
+ "verticals/*/flows.json#flows.*.source.fields.store",
608
+ "verticals/*/flows.json#flows.*.pick.releaseReDispatch"
609
+ ],
610
+ "inputs": [
611
+ "票上的店铺名(逐字,不归一化)",
612
+ "紫鸟店铺清单(ziniao-cli store list,带 TTL 缓存;取不到 ⇒ 跳过校验,宁可不拦)",
613
+ "运营勾的放行位(就绪=true)"
614
+ ],
615
+ "outputs": [
616
+ "店铺不在清单 ⇒ 拒该票 + 写 blocked(不猜账号,绝不回退默认账号)",
617
+ "放行位为真且上游 failed/blocked ⇒ 允许重新派发(受每票上限 + 冷却约束)"
618
+ ],
619
+ "onReject": {
620
+ "code": 0,
621
+ "reason": "no_ticket",
622
+ "effect": "被拒的票不进本轮候选(不是失败);Bridge/客户端就绪属宿主档事实,只在壳体探测并如实上报(契约 §3 矩阵),不得为它改内核"
623
+ }
624
+ },
625
+ "J9-data-dir-audit-backup": {
626
+ "id": "J9",
627
+ "title": "数据目录唯一判据 + 审计/备份落点",
628
+ "owner": "core/lib/argent-datadir.mjs:128",
629
+ "implementations": [
630
+ {
631
+ "at": "core/lib/argent-datadir.mjs:128",
632
+ "anchor": "export function resolveDataDir"
633
+ },
634
+ {
635
+ "at": "scripts/lib/argent_datadir.py:156",
636
+ "anchor": "def resolve_data_dir"
637
+ },
638
+ {
639
+ "at": "scripts/wenyao-invoice-writeback.mjs:201",
640
+ "anchor": "const AUDIT = join("
641
+ },
642
+ {
643
+ "at": "scripts/wenyao-invoice-writeback.mjs:251",
644
+ "anchor": "function backup(recordId, fieldIds, tag)"
645
+ }
646
+ ],
647
+ "declaredIn": [
648
+ "core/lib/argent-datadir.mjs",
649
+ "scripts/lib/argent_datadir.py"
650
+ ],
651
+ "inputs": [
652
+ "环境变量 ARGENT_DATA_DIR / DSH_HOME / HOME"
653
+ ],
654
+ "outputs": [
655
+ "数据目录 dir(三级链:ARGENT_DATA_DIR → $DSH_HOME/argent → ~/.dsh/argent)",
656
+ "isolated 判据(dir ≠ 默认目录 ⇒ 失败回路安全阀生效)",
657
+ "写前整行备份(backup/<tag>-<recordId>-<ts>.json)+ 审计 JSONL(audit.jsonl)"
658
+ ],
659
+ "onReject": {
660
+ "code": 1,
661
+ "reason": "internal_error",
662
+ "effect": "拿不到数据目录 / 备份写不下 ⇒ 拒绝真写(fail-closed);⛔ 禁止在别处复制这条链"
663
+ }
664
+ },
665
+ "J10-sideeffect-boundary": {
666
+ "id": "J10",
667
+ "title": "副作用边界:--dry-run 零副作用清单 + 通知去重(同一事实不重发)",
668
+ "owner": "scripts/flow_claim.py:302",
669
+ "implementations": [
670
+ {
671
+ "at": "scripts/flow_claim.py:302",
672
+ "anchor": "ap.add_argument('--dry-run'"
673
+ },
674
+ {
675
+ "at": "scripts/wenyao-invoice-writeback.mjs:452",
676
+ "anchor": "if (o['dry-run'])"
677
+ },
678
+ {
679
+ "at": "scripts/daily-report.mjs:691",
680
+ "anchor": "const markerFile = "
681
+ },
682
+ {
683
+ "at": "core/lib/notify/verb.mjs:149",
684
+ "anchor": "const dryRun = bools.has('--dry-run')"
685
+ },
686
+ {
687
+ "at": "core/lib/notify/dedup.mjs:57",
688
+ "anchor": "export function dedupMarkerPath"
689
+ }
690
+ ],
691
+ "declaredIn": [
692
+ "core/contracts/verbs.schema.json#dryRunContract",
693
+ "scripts/flow-requirements.json#capabilities.invoice.gate"
694
+ ],
695
+ "inputs": [
696
+ "调用方是否给了确权参数(--apply / --confirm / --yes)",
697
+ "同一事实的幂等键(.pushed-<date>-<storeKey> 标记)"
698
+ ],
699
+ "outputs": [
700
+ "dry-run:只打印「将要做什么」(目标记录/字段/命令)+ dryRun:true",
701
+ "真写:落台账/备份/审计,并打幂等标记;重复通知 ⇒ skipped:true"
702
+ ],
703
+ "dryRunZeroSideEffectsRef": "core/contracts/verbs.schema.json#dryRunContract.zeroSideEffects",
704
+ "dryRunZeroSideEffectsNote": "零副作用清单**只有一份**(引用的那份);本条目不复制它 —— 复述即第二份判据。判据 = 跑两次 dry-run 后数据目录逐字节不变。",
705
+ "onReject": {
706
+ "code": 1,
707
+ "reason": "internal_error",
708
+ "effect": "dry-run 落了任何一条 ⇒ 违规(判据 = 跑两次 dry-run 后数据目录逐字节不变);调用方说了算(能靠参数绕过判据)= 红"
709
+ }
710
+ }
711
+ },
712
+ "reasonCodes": {
713
+ "_doc": "机器可判的短码(A2):ok:false 与 empty:true 时必须给;禁止拿中文句子当判据(人话放 error/note)。exit = 该 reason 对应的进程退出码(必须与 verbs.schema.json#exitCodes 一致)。",
714
+ "no_ticket": {
715
+ "exit": 0,
716
+ "meaning": "成功但无事可做(无票可认领 / 收窄后为空)"
717
+ },
718
+ "no_match": {
719
+ "exit": 0,
720
+ "meaning": "查询类 verb 成功但无匹配行(含被过滤/被截断,须回显生效条件)"
721
+ },
722
+ "license_grace": {
723
+ "exit": 3,
724
+ "meaning": "许可宽限期内:业务放行,但必须上报"
725
+ },
726
+ "guard_rejected": {
727
+ "exit": 1,
728
+ "meaning": "写守卫/许可拒绝(白名单、终态、记录授权、超宽限)"
729
+ },
730
+ "source_failed": {
731
+ "exit": 1,
732
+ "meaning": "数据源读取失败/超时(网络、飞书半开连接)"
733
+ },
734
+ "internal_error": {
735
+ "exit": 1,
736
+ "meaning": "内部错误(不含用法问题)"
737
+ },
738
+ "check_failed": {
739
+ "exit": 1,
740
+ "meaning": "`argent doctor --customer` 自检发现 fail 项(数据目录不可写 / 解释器全不可用 / 技能与仓库漂移 / 许可被拒 / 数据面未实现 / 无可用通知通道)",
741
+ "note": "warn **不**产生该码,也不改变退出码(A1:2 不得再被用作「有告警」);fail 项在 JSON 的 checks[].id/level 里点名"
742
+ },
743
+ "bad_output": {
744
+ "exit": 1,
745
+ "meaning": "被包脚本输出不可解析(不是 JSON)"
746
+ },
747
+ "missing_declaration": {
748
+ "exit": 2,
749
+ "meaning": "注册表里没有这条流程/这个能力(缺声明)"
750
+ },
751
+ "usage_error": {
752
+ "exit": 2,
753
+ "meaning": "参数/环境错误(缺必填参数、配置引用的 env 缺失)"
754
+ },
755
+ "field_missing": {
756
+ "exit": 2,
757
+ "meaning": "数据源缺**域必需字段**(或查询用了本域不存在的字段)—— 必须响亮失败,⛔ **不得**降级成\"0 条\"/\"空结果\"",
758
+ "note": "判据落点 `core/lib/license-ops.mjs#checkOpsFields`/`parseOpsArgs`(O2 的两个已知陷阱):① 码状态字段是 `state` **不是** `status`(按 `status` 查恒空 ⇒ 会把\"有在途码\"误读成\"没有\");② 席位**不是**存储字段 `used`(= `seats` + `deviceLimit`(缺省跟随 seats)+ `releasedAt` 为空的设备码去重数)。⇒ 用错字段名一律 exit 2 + 本码 + `missingFields` 回显,绝不静默返回 0。"
759
+ },
760
+ "endpoint_missing": {
761
+ "exit": 0,
762
+ "meaning": "**节级**短码(唯一真源 = `core/lib/license-ops.mjs#OPS_SECTION_REASONS`):服务端**没有**这个只读接口(静态登记 `exists:false`,或**本轮实测 404 路由不在** = 接口已就绪但**还没部署**)⇒ 那一节 `available:false` + `needs`,⛔ **绝不当成「0 条」**;顶层仍 exit 0(「答不了」≠「读失败」)",
763
+ "note": "宿主在 `json.<section>.reason` 上分支。本轮(2026-10-04)的实测形态:4 个只读接口已在 `whyshu-svr` 就绪但**未部署** ⇒ `argent license ops --server <base>` 会把它标成本码 + `missingEndpoints[].runtime:true`,`--probe` 同时报 `missing` 且 `agrees:false`。"
764
+ },
765
+ "needs_server": {
766
+ "exit": 0,
767
+ "meaning": "**节级**短码:本机只读产物答不了这一节,要服务端只读接口(`--server <base>`)—— 不是\"没有\"",
768
+ "note": "唯一真源 = `core/lib/license-ops.mjs#OPS_SECTION_REASONS`。"
769
+ },
770
+ "no_prefix": {
771
+ "exit": 0,
772
+ "meaning": "**节级**短码:没有可查的码前缀(既没 `--prefix`,本机审计里也没有)—— ⛔ 不是\"没有在途码\"",
773
+ "note": "唯一真源 = `core/lib/license-ops.mjs#OPS_SECTION_REASONS`。"
774
+ },
775
+ "no_data": {
776
+ "exit": 0,
777
+ "meaning": "**节级**短码:快照里**没有这个集合**(缺席 ≠ 为空)—— ⛔ 不报 0",
778
+ "note": "唯一真源 = `core/lib/license-ops.mjs#OPS_SECTION_REASONS`。"
779
+ },
780
+ "field_unknown": {
781
+ "exit": 2,
782
+ "meaning": "服务端**不认识**这个参数名(典型 = `?status=`;服务端对未知参数一律 400 `field_unknown` 并点名「请用 `state`」)—— 必须响亮失败,⛔ **不得**降级成\"筛出 0 条\"/空集",
783
+ "note": "判据落点 `core/lib/license-ops.mjs#opsServerGet`(O2 只读运营视图接服务端 4 个只读接口)。服务端契约 §0:`?status=` ⇒ **400 `field_unknown`** + 文案点名\"字段是 `state`\";客户端把 400/200 上挂的 `ok:false` **按 reason 判定**(⛔ 不看状态码),并原样带上服务端原文与陷阱提示。"
784
+ },
785
+ "rate_limited": {
786
+ "exit": 1,
787
+ "meaning": "兑换:触发限流 ⇒ 退避重试(**同一个码**重试是安全的:同码同机走幂等复用)"
788
+ },
789
+ "method_not_allowed": {
790
+ "exit": 2,
791
+ "meaning": "只读接口**只接受 GET**(服务端契约 §0:其它动词 ⇒ 405 + `Allow: GET`)—— 客户端只发 GET,见到 405 即链路/网关不对,⛔ 不是\"没有数据\"",
792
+ "note": "判据落点 `core/lib/license-ops.mjs#opsServerGet`。同族的 `admin_required`(401/403,`adminAuth` 口径)与 `bad_request`(400 `bad_limit`/`bad_state`/`bad_since`/`bad_device`)也在同一处判定。"
793
+ },
794
+ "admin_required": {
795
+ "exit": 2,
796
+ "meaning": "只读接口要求**管理员**身份(服务端 `adminAuth`:无令牌 401、非管理员 403)—— 换管理员 JWT,⛔ 不绕过鉴权、⛔ 不降级成空集",
797
+ "note": "判据落点 `core/lib/license-ops.mjs#opsServerGet`(401/403 同口径)。"
798
+ },
799
+ "bad_request": {
800
+ "exit": 1,
801
+ "meaning": "兑换:服务端认为请求不合法(字段缺失/类型错)⇒ 客户端与服务端**契约版本不一致**,先核对版本(不反复重试)"
802
+ },
803
+ "python_unavailable": {
804
+ "exit": 2,
805
+ "meaning": "解释器不可用(多候选全部探测失败)"
806
+ },
807
+ "no_ledger": {
808
+ "exit": 1,
809
+ "meaning": "台账文件不存在(数据目录不对 / 这台机器从未跑过流程)—— **不得**降级成 empty"
810
+ },
811
+ "ok": {
812
+ "exit": 0,
813
+ "meaning": "判定通过(许可/设备正常态)—— 只在需要显式回执的 verb 里出现;ok:true 且无事可报时宁可写 null"
814
+ },
815
+ "unbound": {
816
+ "exit": 0,
817
+ "meaning": "许可未声明设备(无 device 字段)⇒ **不做比对、放行**(存量许可继续有效,D1-兼容)"
818
+ },
819
+ "device_match": {
820
+ "exit": 0,
821
+ "meaning": "许可声明的设备码与本机一致 ⇒ 放行"
822
+ },
823
+ "device_rebound": {
824
+ "exit": 0,
825
+ "meaning": "本机自助重绑过这份许可的设备码 ⇒ 放行(计数见 $ARGENT_DATA_DIR/license-rebind.json)"
826
+ },
827
+ "device_unsupported": {
828
+ "exit": 2,
829
+ "meaning": "本机不支持设备绑定(非 Darwin / 读不到 IOPlatformUUID)⇒ **不 fail-closed**:按 unbound 放行并如实标注"
830
+ },
831
+ "device_read_failed": {
832
+ "exit": 2,
833
+ "meaning": "读本机指纹失败(ioreg 失败/无该字段)⇒ 同上,放行 + 明确标注(`license request` 以此为结论码)"
834
+ },
835
+ "device_algo_unknown": {
836
+ "exit": 0,
837
+ "meaning": "许可声明的指纹算法本客户端不认识 ⇒ 无法比对,按 unbound 放行(换算法不破坏老文件)"
838
+ },
839
+ "device_mismatch": {
840
+ "exit": 1,
841
+ "meaning": "设备码不匹配:`install` 拒绝落盘;运行期在 7 天宽限内 state=grace(放行+上报),超宽限 ⇒ denied"
842
+ },
843
+ "rebind_exhausted": {
844
+ "exit": 1,
845
+ "meaning": "设备码不匹配且自助重绑 3 次已用尽 ⇒ 拒绝 + 人工指引(服务端按 `license request` 的设备码重签)"
846
+ },
847
+ "regression_refused": {
848
+ "exit": 1,
849
+ "meaning": "`install`/`renew` 拒绝**倒退**安装:新文件比现役更早到期(stale)或能力/业务线/席位被收窄(narrowed)⇒ 原许可未改动;显式 `--allow-regression` 才放行(换绑不由该码表达:它走 device_mismatch/rebind_exhausted)"
850
+ },
851
+ "license_denied": {
852
+ "exit": 1,
853
+ "meaning": "**写类 verb** 在 enforce 模式下被许可闸门拒绝(零副作用:没写台账/没落盘/没回写)"
854
+ },
855
+ "enforce_off": {
856
+ "exit": 0,
857
+ "meaning": "许可闸门逃生阀(`ARGENT_LICENSE_ENFORCE=off`):**没有做判定**(不读许可、不留证据)⇒ 照常写"
858
+ },
859
+ "gate_error": {
860
+ "exit": 0,
861
+ "meaning": "闸门自己跑不起来(缺 `scripts/license-gate.mjs` / 输出不可解析 / 超时)⇒ **放行 + 响亮告警**(宁可不拦,不可误停;与 flow-trigger.sh 同口径)"
862
+ },
863
+ "missing": {
864
+ "exit": 1,
865
+ "meaning": "许可文件不存在(未授权:装上许可前写操作会被拒)—— **不得**降级成 empty(§3.5③ 验收行)"
866
+ },
867
+ "bad_signature": {
868
+ "exit": 1,
869
+ "meaning": "许可验签失败(文件被改过 / 不是本机这把密钥签的)⇒ 拒绝"
870
+ },
871
+ "expired": {
872
+ "exit": 1,
873
+ "meaning": "许可已过期且超出宽限期 ⇒ 拒绝(宽限期内是 license_grace)"
874
+ },
875
+ "malformed": {
876
+ "exit": 1,
877
+ "meaning": "许可文件不是合法许可 JSON(字段缺失 / 时间不可解析)⇒ 拒绝(绝不宽容成永不过期)"
878
+ },
879
+ "bad_version": {
880
+ "exit": 1,
881
+ "meaning": "许可版本本客户端不认识(当前只认 v1)⇒ 拒绝"
882
+ },
883
+ "no_secret": {
884
+ "exit": 1,
885
+ "meaning": "本机没有验签密钥(ARGENT_LICENSE_SECRET / license.secret 都没有)⇒ 拒绝,不是“当通过”"
886
+ },
887
+ "unreadable": {
888
+ "exit": 1,
889
+ "meaning": "许可文件读不出来(权限/IO)⇒ 拒绝"
890
+ },
891
+ "cap_not_allowed": {
892
+ "exit": 1,
893
+ "meaning": "许可里没有这次要用的能力(capabilities 是白名单:空数组 = 什么都不许)"
894
+ },
895
+ "vertical_not_allowed": {
896
+ "exit": 1,
897
+ "meaning": "许可不含这条业务线(verticals 空 = 不限,非空则必须显式包含)"
898
+ },
899
+ "no_refresh_source": {
900
+ "exit": 0,
901
+ "meaning": "`license renew` 没有可用的续期来源(没有新许可文件、也没有在线端点)⇒ **成功但空**,维持原状态"
902
+ },
903
+ "duplicate_suppressed": {
904
+ "exit": 0,
905
+ "meaning": "通知幂等:同一事实已投递过 ⇒ 成功但**不重发**(empty:true)"
906
+ },
907
+ "delivery_failed": {
908
+ "exit": 1,
909
+ "meaning": "投递失败(非 2xx / 超时 / 连接失败;不跟随重定向,3xx 也算失败)"
910
+ },
911
+ "unknown_channel": {
912
+ "exit": 2,
913
+ "meaning": "通知通道名未登记(缺声明)"
914
+ },
915
+ "channel_not_implemented": {
916
+ "exit": 2,
917
+ "meaning": "通道是**预留位**:端口契约已定、投递实现未落地(绝不假装已发)"
918
+ },
919
+ "target_required": {
920
+ "exit": 2,
921
+ "meaning": "通道缺目标(webhook 的 --url 等)"
922
+ },
923
+ "bad_target": {
924
+ "exit": 2,
925
+ "meaning": "目标不是该通道接受的形态(如 webhook 非 http(s))"
926
+ },
927
+ "missing_body": {
928
+ "exit": 2,
929
+ "meaning": "通知缺正文(--text/--file/--body-json 三选一都没给,或 --text 是空串)"
930
+ },
931
+ "body_unreadable": {
932
+ "exit": 2,
933
+ "meaning": "正文文件读不到(路径/权限)"
934
+ },
935
+ "bad_body_json": {
936
+ "exit": 2,
937
+ "meaning": "--body-json 不是合法 JSON"
938
+ },
939
+ "datadir_unwritable": {
940
+ "exit": 2,
941
+ "meaning": "数据目录建不出来(`init --apply`;环境问题 ⇒ 补环境而非重试)"
942
+ },
943
+ "_activationNote": "一次性激活码兑换(方案《许可自助签发与续期》§9)的短码:服务端错误码在客户端**同名映射**(code_*/no_*/seat_*/device_bound_*/rebind_window_*/payment_required/rate_limited/bad_device 与服务端 §9.3 逐字相同),客户端自己产生的码一律 `activation_` 前缀。映射表唯一实现在 `core/lib/license-activate.mjs#SERVER_ERROR_MAP`/`CLIENT_ERROR_MAP`,由 `scripts/tests/license-activate.test.mjs` 与契约逐条对账(R1e 同一条纪律)。",
944
+ "code_unknown": {
945
+ "exit": 1,
946
+ "meaning": "兑换:激活码不存在(抄错,或不是这台服务器的码)⇒ 在网页/手机端重新生成"
947
+ },
948
+ "code_expired": {
949
+ "exit": 1,
950
+ "meaning": "兑换:激活码已过期(TTL ≤15 分钟)⇒ 重新生成并**尽快**兑换"
951
+ },
952
+ "code_already_redeemed": {
953
+ "exit": 1,
954
+ "meaning": "兑换:激活码已被用掉且超出\"同码同机幂等复用窗口\"(24h)⇒ 重新生成;窗口内的同机重放是**幂等复用**,不会给该码"
955
+ },
956
+ "code_device_locked": {
957
+ "exit": 1,
958
+ "meaning": "兑换:激活码已绑定到**另一台机器**(码被转发/双花)⇒ 在那台机器上兑换,或重新生成"
959
+ },
960
+ "code_revoked": {
961
+ "exit": 1,
962
+ "meaning": "兑换:激活码被运营撤销"
963
+ },
964
+ "code_locked": {
965
+ "exit": 1,
966
+ "meaning": "兑换:该码失败尝试超限已锁定 ⇒ 重新生成(并核对该机器的设备码)"
967
+ },
968
+ "no_entitlement": {
969
+ "exit": 1,
970
+ "meaning": "兑换:账号没有任何有效许可(服务端 §2.2-D 同名)⇒ 先购买/开通"
971
+ },
972
+ "no_license": {
973
+ "exit": 1,
974
+ "meaning": "兑换:账号没有许可记录 ⇒ 开通"
975
+ },
976
+ "license_revoked": {
977
+ "exit": 1,
978
+ "meaning": "兑换:账号的许可已被吊销 ⇒ 联系运营"
979
+ },
980
+ "capability_not_owned": {
981
+ "exit": 1,
982
+ "meaning": "兑换:请求的能力超出账号权益(**签发不扩权**)⇒ 以账号权益为准"
983
+ },
984
+ "seat_limit_reached": {
985
+ "exit": 1,
986
+ "meaning": "兑换:新设备会超席位上限 ⇒ 解绑旧设备或加席位"
987
+ },
988
+ "device_bound_elsewhere": {
989
+ "exit": 1,
990
+ "meaning": "兑换:同账号同席位已被另一台设备占用 ⇒ 走重绑或人工解绑"
991
+ },
992
+ "rebind_window_expired": {
993
+ "exit": 1,
994
+ "meaning": "兑换:首次发现设备不匹配已超过 7 天宽限 ⇒ 人工重绑"
995
+ },
996
+ "payment_required": {
997
+ "exit": 1,
998
+ "meaning": "兑换:未核账不放行(姿态 A)⇒ 走人工核账"
999
+ },
1000
+ "bad_device": {
1001
+ "exit": 1,
1002
+ "meaning": "兑换:服务端拒绝了设备码(形状/算法不认识)⇒ 重跑 `argent license request`,别手抄"
1003
+ },
1004
+ "activation_server_unconfigured": {
1005
+ "exit": 2,
1006
+ "meaning": "兑换:没有配置端点(`--server` / `ARGENT_LICENSE_SERVER` / `WHYSHU_API_URL` 都没有)⇒ **无默认地址**,补配置再跑(环境问题,不重试)"
1007
+ },
1008
+ "activation_unauthorized": {
1009
+ "exit": 1,
1010
+ "meaning": "兑换:端点返回 401 —— 兑换端点**不应要求账号令牌**(客户机不登录)⇒ 服务端路由/部署配错了"
1011
+ },
1012
+ "activation_server_error": {
1013
+ "exit": 1,
1014
+ "meaning": "兑换:服务端 5xx(含 `signing_secret_missing`)⇒ 运营处置;稍后可用**同一个码**重试"
1015
+ },
1016
+ "activation_bad_response": {
1017
+ "exit": 1,
1018
+ "meaning": "兑换:服务端响应不可解析,或缺 `licenseFile`/`secret` ⇒ **不得**当成功(先核对服务端版本/契约)"
1019
+ },
1020
+ "activation_server_unreachable": {
1021
+ "exit": 1,
1022
+ "meaning": "兑换:连不上端点(DNS/连接失败)⇒ 查网络与 `--server`;同一个码重试安全"
1023
+ },
1024
+ "activation_timeout": {
1025
+ "exit": 1,
1026
+ "meaning": "兑换:请求超时。**码可能已被消费** ⇒ 用**同一个码**重试(同机幂等复用);仍不行 ⇒ 运营用 `GET /license/activation-code/:prefix` 查状态"
1027
+ },
1028
+ "activation_denied": {
1029
+ "exit": 1,
1030
+ "meaning": "兑换:服务端拒绝但 reason 不在本词表 ⇒ 原串只进 `serverReason`(**不当判据**)"
1031
+ },
1032
+ "activation_disabled": {
1033
+ "exit": 1,
1034
+ "meaning": "兑换:服务端灰度未开启/已回滚(`ACTIVATION_ENABLED=0`)⇒ **改走人工签发入口**(运营按设备码签一份,再 `license install --file`),不要反复重试"
1035
+ },
1036
+ "signing_secret_missing": {
1037
+ "exit": 1,
1038
+ "meaning": "兑换:服务端未配置 `LICENSE_SIGNING_SECRET`(⛔ 不回退默认串)⇒ 运营处置后重试(同一个码重试安全)"
1039
+ }
1040
+ },
1041
+ "invariants": [
1042
+ "凭证永不过网:跨平面只下发工具名 + 业务参数",
1043
+ "所有写操作有审计;幂等键来自台账",
1044
+ "离线可用:许可宽限期内业务不停摆"
1045
+ ],
1046
+ "mcpShadow": {
1047
+ "purpose": "写类能力的入场券:先在隔离沙箱跑真实 CLI 路径,真台账零改动,逐字段比对一致后才允许真写",
1048
+ "writtenTools": [
1049
+ "argent_claim_shadow",
1050
+ "argent_claim(门禁=影子 verified;confirm=true 才真写)",
1051
+ "argent_writeback(默认 dry-run;守卫在脚本内)"
1052
+ ],
1053
+ "pendingRealWrites": [
1054
+ "report(待接入 flow_failure.py)"
1055
+ ],
1056
+ "isolation": "ARGENT_DATA_DIR → mkdtemp 沙箱(台账/案件/开关都在沙箱内)",
1057
+ "proof": "realUnchanged=true(真台账事件数前后一致)",
1058
+ "comparator": {
1059
+ "tool": "argent_shadow_compare",
1060
+ "method": "同输入两次独立影子跑 → 事件序列逐字段比对(归一化 ts/createdAt/leaseUntil/sessionId 等)",
1061
+ "gate": "diffCount == 0 且两次退出码为 0 ⇒ 放行对应流程的 MCP 真写路径"
1062
+ },
1063
+ "gate": "compareShadow(flow, fixture=true).verified == true ⇒ 才允许真写;否则 gated 拒绝"
1064
+ }
1065
+ }