@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.
- package/MANIFEST.json +307 -0
- package/engine/VERSION +1 -0
- package/engine/agents/catalog.json +454 -0
- package/engine/configs/_aliases.proposed.json +651 -0
- package/engine/configs/_migration-plan.proposed.json +899 -0
- package/engine/configs/account.json +272 -0
- package/engine/configs/advanced.json +205 -0
- package/engine/configs/host.json +149 -0
- package/engine/configs/hr.json +27 -0
- package/engine/configs/notify.json +264 -0
- package/engine/core/cli/argent.mjs +277 -0
- package/engine/core/contracts/argent.contracts.json +1065 -0
- package/engine/core/contracts/verbs.schema.json +2539 -0
- package/engine/core/lib/argent-datadir.mjs +223 -0
- package/engine/core/lib/audit.mjs +187 -0
- package/engine/core/lib/claim.mjs +258 -0
- package/engine/core/lib/config-catalog.mjs +1172 -0
- package/engine/core/lib/doctor-customer.mjs +577 -0
- package/engine/core/lib/flow-list.mjs +138 -0
- package/engine/core/lib/flow-registry.mjs +48 -0
- package/engine/core/lib/init.mjs +247 -0
- package/engine/core/lib/ledger.mjs +124 -0
- package/engine/core/lib/license-activate.mjs +813 -0
- package/engine/core/lib/license-device.mjs +314 -0
- package/engine/core/lib/license-file.mjs +349 -0
- package/engine/core/lib/license-guard.mjs +123 -0
- package/engine/core/lib/license-ops.mjs +1645 -0
- package/engine/core/lib/license-verdict.mjs +133 -0
- package/engine/core/lib/license.mjs +577 -0
- package/engine/core/lib/notify/dedup.mjs +101 -0
- package/engine/core/lib/notify/feishu.mjs +38 -0
- package/engine/core/lib/notify/index.mjs +95 -0
- package/engine/core/lib/notify/verb.mjs +327 -0
- package/engine/core/lib/notify/webhook.mjs +135 -0
- package/engine/core/lib/notify/wecom.mjs +36 -0
- package/engine/core/lib/python.mjs +145 -0
- package/engine/core/lib/sop.mjs +116 -0
- package/engine/core/lib/versions.mjs +205 -0
- package/engine/core/mcp/client.mjs +67 -0
- package/engine/core/mcp/http.mjs +138 -0
- package/engine/core/mcp/server.mjs +702 -0
- package/engine/scripts/_engine_rules_probe.py +15 -0
- package/engine/scripts/analyze-full-day.py +568 -0
- package/engine/scripts/archive/feishu-bridge.js +246 -0
- package/engine/scripts/argent-agents.mjs +527 -0
- package/engine/scripts/argent-capabilities.mjs +776 -0
- package/engine/scripts/argent-catalog.mjs +186 -0
- package/engine/scripts/argent-datadir.py +62 -0
- package/engine/scripts/argent-doctor.mjs +624 -0
- package/engine/scripts/argent-env-write.mjs +302 -0
- package/engine/scripts/argent-schedule.mjs +620 -0
- package/engine/scripts/argent-setup-check.mjs +369 -0
- package/engine/scripts/argent-upgrade.mjs +1046 -0
- package/engine/scripts/base-bootstrap.sh +575 -0
- package/engine/scripts/billing-mode-daily.sh +12 -0
- package/engine/scripts/build-engine-package.mjs +123 -0
- package/engine/scripts/capability-packs.lock.json +484 -0
- package/engine/scripts/capability_pack.py +1242 -0
- package/engine/scripts/check-1.0-criteria.mjs +355 -0
- package/engine/scripts/check-agent-catalog.mjs +141 -0
- package/engine/scripts/check-billing-mode.sh +377 -0
- package/engine/scripts/check-child-sessions.mjs +83 -0
- package/engine/scripts/check-config-catalog.mjs +677 -0
- package/engine/scripts/check-docs-drift.mjs +522 -0
- package/engine/scripts/check-dsh-web-expose.sh +98 -0
- package/engine/scripts/check-judgment-drift.mjs +403 -0
- package/engine/scripts/check-license.mjs +199 -0
- package/engine/scripts/check-model-auth.py +443 -0
- package/engine/scripts/check-pack-closure.mjs +661 -0
- package/engine/scripts/check-portable-symbols.mjs +116 -0
- package/engine/scripts/check-preset-landing.mjs +124 -0
- package/engine/scripts/check-production-home.mjs +602 -0
- package/engine/scripts/check-role-mapping.mjs +461 -0
- package/engine/scripts/check-sample-redaction.mjs +320 -0
- package/engine/scripts/check-skill-classification.mjs +188 -0
- package/engine/scripts/check-sop-consistency.mjs +431 -0
- package/engine/scripts/check-test-env-safety.mjs +627 -0
- package/engine/scripts/check-version-consistency.mjs +452 -0
- package/engine/scripts/ci-run.sh +558 -0
- package/engine/scripts/config-explain.mjs +278 -0
- package/engine/scripts/configure-provider.rb +29 -0
- package/engine/scripts/customer-config-migrate.mjs +179 -0
- package/engine/scripts/customer-preflight.py +892 -0
- package/engine/scripts/customer-readiness.sh +134 -0
- package/engine/scripts/daily-report-inbox.py +242 -0
- package/engine/scripts/daily-report-reconcile.mjs +312 -0
- package/engine/scripts/daily-report.mjs +1310 -0
- package/engine/scripts/daily-report.sh +46 -0
- package/engine/scripts/data/lip-product-dict.json +306 -0
- package/engine/scripts/deliver-customer.mjs +932 -0
- package/engine/scripts/delivery-faces.txt +31 -0
- package/engine/scripts/desktop-trial.sh +146 -0
- package/engine/scripts/dev-window.sh +260 -0
- package/engine/scripts/drill-clean-machine.sh +315 -0
- package/engine/scripts/dsh-api-client.mjs +215 -0
- package/engine/scripts/dsh-backup-scope.sh +83 -0
- package/engine/scripts/dsh-offline-pack.mjs +77 -0
- package/engine/scripts/dsh-overlay-pin.sh +87 -0
- package/engine/scripts/dsh-plane.mjs +153 -0
- package/engine/scripts/dsh-portforward.py +223 -0
- package/engine/scripts/dsh-preflight.mjs +179 -0
- package/engine/scripts/dsh-release-watch-daily.sh +19 -0
- package/engine/scripts/dsh-release-watch.mjs +458 -0
- package/engine/scripts/dsh-remote-check.sh +99 -0
- package/engine/scripts/dsh-restart.sh +179 -0
- package/engine/scripts/dsh-restore.sh +111 -0
- package/engine/scripts/dsh-scope-rewire.mjs +803 -0
- package/engine/scripts/dsh-snapshot.mjs +116 -0
- package/engine/scripts/dsh-upgrade-readiness.mjs +165 -0
- package/engine/scripts/dsh-upgrade.mjs +612 -0
- package/engine/scripts/dsh-url.sh +86 -0
- package/engine/scripts/dsh-web-launch.mjs +155 -0
- package/engine/scripts/ensure-store-windows.py +509 -0
- package/engine/scripts/entitlements.py +458 -0
- package/engine/scripts/env_probe.py +411 -0
- package/engine/scripts/feishu-card.mjs +252 -0
- package/engine/scripts/fix-skill-frontmatter.py +209 -0
- package/engine/scripts/flow-auto-retry.py +454 -0
- package/engine/scripts/flow-requirements.json +720 -0
- package/engine/scripts/flow-scaffold.py +275 -0
- package/engine/scripts/flow-timers-plist.sh +86 -0
- package/engine/scripts/flow-timers.sh +182 -0
- package/engine/scripts/flow-trigger-wake.mjs +284 -0
- package/engine/scripts/flow-trigger.sh +571 -0
- package/engine/scripts/flow_billing.py +354 -0
- package/engine/scripts/flow_capability_stats.py +314 -0
- package/engine/scripts/flow_case.py +194 -0
- package/engine/scripts/flow_claim.py +497 -0
- package/engine/scripts/flow_config.py +1024 -0
- package/engine/scripts/flow_failure.py +588 -0
- package/engine/scripts/flow_learn.py +105 -0
- package/engine/scripts/flow_ledger.py +235 -0
- package/engine/scripts/flow_policy.py +238 -0
- package/engine/scripts/flow_preflight.py +339 -0
- package/engine/scripts/flow_registry.py +341 -0
- package/engine/scripts/flow_retry.py +304 -0
- package/engine/scripts/flow_return_to_ops.py +191 -0
- package/engine/scripts/flow_source.py +315 -0
- package/engine/scripts/flow_sources/__init__.py +53 -0
- package/engine/scripts/flow_sources/cases_json.py +106 -0
- package/engine/scripts/flow_sources/common.py +428 -0
- package/engine/scripts/flow_sources/feishu_base.py +273 -0
- package/engine/scripts/flow_stale.py +185 -0
- package/engine/scripts/flow_status_reconcile.py +344 -0
- package/engine/scripts/flow_triage.py +849 -0
- package/engine/scripts/flow_write_verify.py +496 -0
- package/engine/scripts/fulfillment.js +586 -0
- package/engine/scripts/gen-agent-bundles.mjs +276 -0
- package/engine/scripts/gen-preset-rows.mjs +259 -0
- package/engine/scripts/init-ml.sh +2275 -0
- package/engine/scripts/install-internal-role.sh +190 -0
- package/engine/scripts/install-license.mjs +641 -0
- package/engine/scripts/install-one-shot.mjs +665 -0
- package/engine/scripts/integration_contract.py +220 -0
- package/engine/scripts/integrations/wenyao/adapter.py +98 -0
- package/engine/scripts/integrations/xzh/adapter.py +75 -0
- package/engine/scripts/invoice-mapping.example.json +40 -0
- package/engine/scripts/invoice-table.sh +194 -0
- package/engine/scripts/invoice_carrier_notice.py +279 -0
- package/engine/scripts/invoice_fail_closeout.py +297 -0
- package/engine/scripts/invoice_lip_runner.py +1508 -0
- package/engine/scripts/invoice_lip_runner.py.bak-20260922-1710-freready +1090 -0
- package/engine/scripts/invoice_ready_audit.py +191 -0
- package/engine/scripts/invoice_runner.py +675 -0
- package/engine/scripts/invoice_stageb.py +516 -0
- package/engine/scripts/launchd/com.whyshu.argent-bridge.plist.example +42 -0
- package/engine/scripts/launchd/com.whyshu.fulfillment-poll.plist.example +29 -0
- package/engine/scripts/lease.py +377 -0
- package/engine/scripts/lib/agent-install.mjs +649 -0
- package/engine/scripts/lib/argent-datadir.mjs +16 -0
- package/engine/scripts/lib/argent_datadir.py +262 -0
- package/engine/scripts/lib/argent_filelock.py +507 -0
- package/engine/scripts/lib/bootcheck-wiring.mjs +510 -0
- package/engine/scripts/lib/cdp_ports.py +197 -0
- package/engine/scripts/lib/customer-env.mjs +102 -0
- package/engine/scripts/lib/daily-report-core.mjs +517 -0
- package/engine/scripts/lib/dep-declaration.mjs +81 -0
- package/engine/scripts/lib/deps-migrate.mjs +310 -0
- package/engine/scripts/lib/dsh-host-resolve.mjs +109 -0
- package/engine/scripts/lib/dsh-scope.mjs +500 -0
- package/engine/scripts/lib/dsh-snapshot-path.mjs +35 -0
- package/engine/scripts/lib/dsh-versions.mjs +96 -0
- package/engine/scripts/lib/dsh-web-probe.mjs +214 -0
- package/engine/scripts/lib/is-direct-run.mjs +61 -0
- package/engine/scripts/lib/patch-compose.mjs +241 -0
- package/engine/scripts/lib/patch-target.mjs +35 -0
- package/engine/scripts/lib/plugin-lifecycle.mjs +128 -0
- package/engine/scripts/lib/plugin-packages.mjs +332 -0
- package/engine/scripts/lib/preset-compat.mjs +127 -0
- package/engine/scripts/lib/preset-install.mjs +575 -0
- package/engine/scripts/lib/preset-mechanism.mjs +56 -0
- package/engine/scripts/lib/preset-sync.mjs +59 -0
- package/engine/scripts/lib/profile-retire.mjs +97 -0
- package/engine/scripts/lib/python-runtime.mjs +190 -0
- package/engine/scripts/lib/registry.mjs +72 -0
- package/engine/scripts/lib/repo-root.sh +56 -0
- package/engine/scripts/lib/schedule-mechanism.mjs +659 -0
- package/engine/scripts/lib/schedule-probe.mjs +835 -0
- package/engine/scripts/lib/scope-pointer.mjs +164 -0
- package/engine/scripts/lib/settings-panels.mjs +816 -0
- package/engine/scripts/lib/stdio_utf8.py +86 -0
- package/engine/scripts/lib/wake-auth.mjs +392 -0
- package/engine/scripts/lib/webdriver_ipc.py +264 -0
- package/engine/scripts/lib/zstd-frames.mjs +104 -0
- package/engine/scripts/license-e2e-drill.mjs +426 -0
- package/engine/scripts/license-gate.mjs +245 -0
- package/engine/scripts/lip_backlog.py +171 -0
- package/engine/scripts/lip_table.py +185 -0
- package/engine/scripts/local-usage.mjs +214 -0
- package/engine/scripts/migrate-providers.mjs +127 -0
- package/engine/scripts/migrate-skills.sh +65 -0
- package/engine/scripts/ml-oauth-setup.mjs +550 -0
- package/engine/scripts/ml-store-ids.json +26 -0
- package/engine/scripts/ml_artifact_attribution.py +333 -0
- package/engine/scripts/ml_capacity_probe.py +1158 -0
- package/engine/scripts/ml_hub_status.py +1556 -0
- package/engine/scripts/ml_schema_check.py +115 -0
- package/engine/scripts/ml_store_ids.py +139 -0
- package/engine/scripts/npm-publish-argent.mjs +499 -0
- package/engine/scripts/npm-publish-argent.sh +20 -0
- package/engine/scripts/orchestrator.py +13811 -0
- package/engine/scripts/pack-plugins.mjs +140 -0
- package/engine/scripts/patches/dsh-llm-deepseek--transport-diagnostics.patch +297 -0
- package/engine/scripts/patches/dsh-session--append-message-shape.patch +15 -0
- package/engine/scripts/patches/dsh-session--tool-result-block-017.patch +28 -0
- package/engine/scripts/patches/dsh-session-format-v0-to-v1--permission-preset-origin.patch +11 -0
- package/engine/scripts/patches/dsh-session-format-v3-to-v4--turn-outside-replace.patch +20 -0
- package/engine/scripts/patches/dsh-session-persistence-jsonl--worker-bundled-migrators.patch +39 -0
- package/engine/scripts/patches/dsh-tools--render-return-shape.patch +50 -0
- package/engine/scripts/patches/verify-bundled-migrators.mjs +79 -0
- package/engine/scripts/patches/verify-hardening.mjs +167 -0
- package/engine/scripts/patches/verify-session-migration.mjs +149 -0
- package/engine/scripts/patches/verify-transport-diagnostics.mjs +227 -0
- package/engine/scripts/plan-role-rename.mjs +125 -0
- package/engine/scripts/plugin-bootcheck.mjs +451 -0
- package/engine/scripts/plugin-composition.json +15 -0
- package/engine/scripts/poc-mcp-host.mjs +455 -0
- package/engine/scripts/poll-fulfillment.sh +293 -0
- package/engine/scripts/poll-invoice.sh +74 -0
- package/engine/scripts/profile-doctor.mjs +686 -0
- package/engine/scripts/provider-select.sh +70 -0
- package/engine/scripts/provider-switch.sh +146 -0
- package/engine/scripts/provider-sync-target.check.mjs +64 -0
- package/engine/scripts/python-runtime.sh +78 -0
- package/engine/scripts/query_runner.py +310 -0
- package/engine/scripts/release-argent.sh +574 -0
- package/engine/scripts/repair-unresolved-tools.mjs +178 -0
- package/engine/scripts/run-tests.sh +256 -0
- package/engine/scripts/self-sign-license.mjs +179 -0
- package/engine/scripts/session-health-scan.mjs +63 -0
- package/engine/scripts/session-repair-tool-result-content.mjs +181 -0
- package/engine/scripts/setup.sh +22 -0
- package/engine/scripts/skill-install.mjs +629 -0
- package/engine/scripts/sku_translate.py +148 -0
- package/engine/scripts/sync-plugins.sh +90 -0
- package/engine/scripts/sync-presets.sh +27 -0
- package/engine/scripts/sync-scripts.sh +445 -0
- package/engine/scripts/telemetry.py +873 -0
- package/engine/scripts/ui-copy-count.mjs +220 -0
- package/engine/scripts/usage-anchor.sh +136 -0
- package/engine/scripts/usage_report.py +531 -0
- package/engine/scripts/validate-preset-schema.mjs +208 -0
- package/engine/scripts/vertical-init.mjs +323 -0
- package/engine/scripts/vertical-lint.mjs +482 -0
- package/engine/scripts/wenyao-browser.sh +73 -0
- package/engine/scripts/wenyao-fixture-export.py +116 -0
- package/engine/scripts/wenyao-invoice-writeback.mjs +540 -0
- package/engine/scripts/wenyao-login.sh +34 -0
- package/engine/scripts/wenyao-template-map.json +292 -0
- package/engine/scripts/wenyao_attach.py +131 -0
- package/engine/scripts/wenyao_download_template.py +144 -0
- package/engine/scripts/wenyao_fill_template.py +568 -0
- package/engine/scripts/wenyao_login.py +145 -0
- package/engine/scripts/wenyao_portal.py +633 -0
- package/engine/scripts/wenyao_recon.py +230 -0
- package/engine/scripts/wenyao_run.py +503 -0
- package/engine/scripts/wenyao_shadow_diff.py +160 -0
- package/engine/scripts/wenyao_skill_contract.py +156 -0
- package/engine/scripts/wenyao_template_fetch.py +175 -0
- package/engine/scripts/win/dsh-web-autostart.ps1 +372 -0
- package/engine/scripts/ziniao-auth-probe.sh +268 -0
- package/engine/scripts/ziniao-keepalive.sh +216 -0
- package/engine/scripts/ziniao-post-upgrade-check.sh +120 -0
- package/engine/scripts/ziniao-windows.sh +153 -0
- package/engine/version.mjs +1 -0
- package/engine/verticals/README.md +103 -0
- package/engine/verticals/_engine-words.baseline.txt +237 -0
- package/engine/verticals/_engine-words.json +19 -0
- package/engine/verticals/mercadolibre/README.md +43 -0
- package/engine/verticals/mercadolibre/config.json +709 -0
- package/engine/verticals/mercadolibre/flows.json +706 -0
- package/engine/verticals/mercadolibre/manifest.json +538 -0
- package/engine/verticals/mercadolibre/migrate-machine-state.mjs +138 -0
- package/engine/verticals/mercadolibre/preflight.py +143 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.failure.md +69 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.md +47 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.scheduled.md +79 -0
- package/engine/verticals/mercadolibre/prompts/full.failure.md +125 -0
- package/engine/verticals/mercadolibre/prompts/full.md +91 -0
- package/engine/verticals/mercadolibre/prompts/wenyao-invoice.failure.md +88 -0
- package/engine/verticals/mercadolibre/prompts/wenyao-invoice.md +64 -0
- package/engine/verticals/mercadolibre/prompts/xzh-invoice.failure.md +91 -0
- package/engine/verticals/mercadolibre/prompts/xzh-invoice.md +46 -0
- package/package.json +21 -4
- package/README.md +0 -3
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_doc": "配置目录 · 通知与投递域(引擎级)。声明格式与四道门禁见 docs/Argent-宿主适配契约.md §7。webhook / 群 ID 这类「拿到就能发消息」的值按 secret 处理(页面只显示已配置/未配置)。",
|
|
3
|
+
"domain": "notify",
|
|
4
|
+
"order": 20,
|
|
5
|
+
"items": [
|
|
6
|
+
{
|
|
7
|
+
"key": "notify.feishu.chat_id",
|
|
8
|
+
"label": "飞书推送群(通用兜底)",
|
|
9
|
+
"category": "通知与投递",
|
|
10
|
+
"type": "string",
|
|
11
|
+
"source": "json",
|
|
12
|
+
"secret": true,
|
|
13
|
+
"required": false,
|
|
14
|
+
"validation": {
|
|
15
|
+
"pattern": "^oc_[A-Za-z0-9]+$|^ou_[A-Za-z0-9]+$"
|
|
16
|
+
},
|
|
17
|
+
"capability": null,
|
|
18
|
+
"vertical": null,
|
|
19
|
+
"editable": true,
|
|
20
|
+
"help": "流程通知/告警的兜底落点(能被 @ 到就能被投递,故按密钥处理)。",
|
|
21
|
+
"binding": {
|
|
22
|
+
"kind": "json",
|
|
23
|
+
"file": "config.json",
|
|
24
|
+
"field": "feishuChatId"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"key": "notify.daily.chat_id",
|
|
29
|
+
"label": "日报推送群",
|
|
30
|
+
"category": "通知与投递",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"source": "json",
|
|
33
|
+
"secret": true,
|
|
34
|
+
"required": false,
|
|
35
|
+
"validation": {
|
|
36
|
+
"pattern": "^oc_[A-Za-z0-9]+$|^ou_[A-Za-z0-9]+$"
|
|
37
|
+
},
|
|
38
|
+
"capability": "daily-report",
|
|
39
|
+
"vertical": "mercadolibre",
|
|
40
|
+
"editable": true,
|
|
41
|
+
"help": "日报专属落点;留空则回落通用群。",
|
|
42
|
+
"binding": {
|
|
43
|
+
"kind": "json",
|
|
44
|
+
"file": "config.json",
|
|
45
|
+
"field": "mlDailyChatId"
|
|
46
|
+
},
|
|
47
|
+
"todayChain": [
|
|
48
|
+
"json",
|
|
49
|
+
"env"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"key": "notify.daily.profile",
|
|
54
|
+
"label": "日报投递身份",
|
|
55
|
+
"category": "通知与投递",
|
|
56
|
+
"type": "string",
|
|
57
|
+
"source": "json",
|
|
58
|
+
"secret": false,
|
|
59
|
+
"required": false,
|
|
60
|
+
"capability": "daily-report",
|
|
61
|
+
"vertical": "mercadolibre",
|
|
62
|
+
"editable": true,
|
|
63
|
+
"help": "用哪个机器人身份发日报(客户端身份名)。",
|
|
64
|
+
"binding": {
|
|
65
|
+
"kind": "json",
|
|
66
|
+
"file": "config.json",
|
|
67
|
+
"field": "mlDailyProfile"
|
|
68
|
+
},
|
|
69
|
+
"todayChain": [
|
|
70
|
+
"json",
|
|
71
|
+
"env"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"key": "notify.daily.webhook",
|
|
76
|
+
"label": "日报自定义 Webhook",
|
|
77
|
+
"category": "通知与投递",
|
|
78
|
+
"type": "string",
|
|
79
|
+
"source": "json",
|
|
80
|
+
"secret": true,
|
|
81
|
+
"required": false,
|
|
82
|
+
"capability": "daily-report",
|
|
83
|
+
"vertical": "mercadolibre",
|
|
84
|
+
"editable": true,
|
|
85
|
+
"help": "非飞书通道的自定义投递地址(URL 本身就是凭据)。",
|
|
86
|
+
"binding": {
|
|
87
|
+
"kind": "json",
|
|
88
|
+
"file": "config.json",
|
|
89
|
+
"field": "mlDailyWebhook"
|
|
90
|
+
},
|
|
91
|
+
"todayChain": [
|
|
92
|
+
"json",
|
|
93
|
+
"env"
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"key": "notify.daily.alert_chat_id",
|
|
98
|
+
"label": "日报告警群",
|
|
99
|
+
"category": "通知与投递",
|
|
100
|
+
"type": "string",
|
|
101
|
+
"source": "json",
|
|
102
|
+
"secret": true,
|
|
103
|
+
"required": false,
|
|
104
|
+
"capability": "daily-report",
|
|
105
|
+
"vertical": "mercadolibre",
|
|
106
|
+
"editable": true,
|
|
107
|
+
"help": "日报失败/异常告警的落点(与日报正文分开,避免刷屏)。",
|
|
108
|
+
"binding": {
|
|
109
|
+
"kind": "json",
|
|
110
|
+
"file": "config.json",
|
|
111
|
+
"field": "mlDailyAlertChatId"
|
|
112
|
+
},
|
|
113
|
+
"todayChain": [
|
|
114
|
+
"env",
|
|
115
|
+
"json"
|
|
116
|
+
],
|
|
117
|
+
"_note": "批 3-1(2026-10-09)声明纠正:原写 [json,env],与代码事实**相反**。读取点为证 —— scripts/daily-report.mjs:1006 逐字是 `env.ML_DAILY_ALERT_CHAT_ID || (cfg && cfg.mlDailyAlertChatId) || ML_DAILY_ALERT_CHAT_ID`(最后一项是内部群常量)⇒ 实际是 env 优先。本批**代码零改动**;链首级纠正为 env 后与规范链首级一致 ⇒ 设置页「旧优先级」提示自然消失。⛔ 这不是删提示,是声明与代码事实一致后才消失的。"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"key": "notify.daily.alert_profile",
|
|
121
|
+
"label": "日报告警身份",
|
|
122
|
+
"category": "通知与投递",
|
|
123
|
+
"type": "string",
|
|
124
|
+
"source": "json",
|
|
125
|
+
"secret": false,
|
|
126
|
+
"required": false,
|
|
127
|
+
"capability": "daily-report",
|
|
128
|
+
"vertical": "mercadolibre",
|
|
129
|
+
"editable": true,
|
|
130
|
+
"help": "用哪个机器人身份发日报告警。",
|
|
131
|
+
"binding": {
|
|
132
|
+
"kind": "json",
|
|
133
|
+
"file": "config.json",
|
|
134
|
+
"field": "mlDailyAlertProfile"
|
|
135
|
+
},
|
|
136
|
+
"todayChain": [
|
|
137
|
+
"env",
|
|
138
|
+
"json"
|
|
139
|
+
],
|
|
140
|
+
"_note": "批 3-1(2026-10-09)声明纠正:同 notify.daily.alert_chat_id —— 原写 [json,env],与代码事实相反。**5 个读取点全部 env 优先**:scripts/daily-report.mjs:1007(`env.ML_DAILY_ALERT_PROFILE || cfg.mlDailyAlertProfile`)、scripts/feishu-card.mjs:174(`dailyEnv.LARK_PROFILE || cfg.mlDailyAlertProfile`)、scripts/feishu-card.mjs:177(`fullEnv.NOTIFY_PROFILE || cfg.mlDailyAlertProfile`)、scripts/flow_preflight.py:277 与 scripts/flow_preflight.py:280(envs/shared 的 *_PROFILE 优先,cfgj.mlDailyAlertProfile 作回落)⇒ 实际是 env 优先。⚠️ feishu-card / flow_preflight 读的 env 名与声明登记的 ML_DAILY_ALERT_PROFILE 并不一致(已知缺陷,调查产物 #13 的 regression 已单列,⛔ 不在本批改)—— 此处只纠正**层级次序**,不涉及 env 名。本批代码零改动;提示因声明与事实一致而消失。"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"key": "notify.flow.profile",
|
|
144
|
+
"label": "流程通知身份",
|
|
145
|
+
"category": "通知与投递",
|
|
146
|
+
"type": "string",
|
|
147
|
+
"source": "envfile",
|
|
148
|
+
"secret": false,
|
|
149
|
+
"required": false,
|
|
150
|
+
"capability": null,
|
|
151
|
+
"vertical": null,
|
|
152
|
+
"editable": false,
|
|
153
|
+
"help": "流程通知默认用哪个身份投递。",
|
|
154
|
+
"binding": {
|
|
155
|
+
"kind": "envfile",
|
|
156
|
+
"file": "fulfillment.env",
|
|
157
|
+
"env": "NOTIFY_PROFILE",
|
|
158
|
+
"vertical": "mercadolibre"
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"key": "notify.flow.lark_profile",
|
|
163
|
+
"label": "流程读表身份",
|
|
164
|
+
"category": "通知与投递",
|
|
165
|
+
"type": "string",
|
|
166
|
+
"source": "envfile",
|
|
167
|
+
"secret": false,
|
|
168
|
+
"required": false,
|
|
169
|
+
"capability": null,
|
|
170
|
+
"vertical": null,
|
|
171
|
+
"editable": false,
|
|
172
|
+
"help": "流程读写飞书表默认用的 CLI 身份。",
|
|
173
|
+
"binding": {
|
|
174
|
+
"kind": "envfile",
|
|
175
|
+
"file": "fulfillment.env",
|
|
176
|
+
"env": "LARK_PROFILE",
|
|
177
|
+
"vertical": "mercadolibre"
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"key": "notify.full.internal_chat_id",
|
|
182
|
+
"label": "货件流程内部群",
|
|
183
|
+
"category": "通知与投递",
|
|
184
|
+
"type": "string",
|
|
185
|
+
"source": "envfile",
|
|
186
|
+
"secret": true,
|
|
187
|
+
"required": false,
|
|
188
|
+
"capability": "full",
|
|
189
|
+
"vertical": "mercadolibre",
|
|
190
|
+
"editable": false,
|
|
191
|
+
"help": "货件流程的过程通知落点(内部群)。",
|
|
192
|
+
"binding": {
|
|
193
|
+
"kind": "envfile",
|
|
194
|
+
"file": "fulfillment.env",
|
|
195
|
+
"env": "FULL_INTERNAL_CHAT_ID",
|
|
196
|
+
"vertical": "mercadolibre"
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"key": "notify.full.done_chat_id",
|
|
201
|
+
"label": "货件完成通知群",
|
|
202
|
+
"category": "通知与投递",
|
|
203
|
+
"type": "string",
|
|
204
|
+
"source": "envfile",
|
|
205
|
+
"secret": true,
|
|
206
|
+
"required": false,
|
|
207
|
+
"capability": "full",
|
|
208
|
+
"vertical": "mercadolibre",
|
|
209
|
+
"editable": false,
|
|
210
|
+
"help": "货件完成后的对外通知落点。",
|
|
211
|
+
"binding": {
|
|
212
|
+
"kind": "envfile",
|
|
213
|
+
"file": "fulfillment.env",
|
|
214
|
+
"env": "FULL_DONE_CHAT_ID",
|
|
215
|
+
"vertical": "mercadolibre"
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"key": "notify.full.done_profile",
|
|
220
|
+
"label": "货件完成通知身份",
|
|
221
|
+
"category": "通知与投递",
|
|
222
|
+
"type": "string",
|
|
223
|
+
"source": "envfile",
|
|
224
|
+
"secret": false,
|
|
225
|
+
"required": false,
|
|
226
|
+
"capability": "full",
|
|
227
|
+
"vertical": "mercadolibre",
|
|
228
|
+
"editable": false,
|
|
229
|
+
"help": "货件完成通知用哪个身份投递。",
|
|
230
|
+
"binding": {
|
|
231
|
+
"kind": "envfile",
|
|
232
|
+
"file": "fulfillment.env",
|
|
233
|
+
"env": "FULL_DONE_PROFILE",
|
|
234
|
+
"vertical": "mercadolibre"
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"key": "notify.full.mode",
|
|
239
|
+
"label": "货件通知模式",
|
|
240
|
+
"category": "通知与投递",
|
|
241
|
+
"type": "enum",
|
|
242
|
+
"source": "envfile",
|
|
243
|
+
"secret": false,
|
|
244
|
+
"required": false,
|
|
245
|
+
"validation": {
|
|
246
|
+
"enum": [
|
|
247
|
+
"final",
|
|
248
|
+
"feishu"
|
|
249
|
+
]
|
|
250
|
+
},
|
|
251
|
+
"capability": "full",
|
|
252
|
+
"vertical": "mercadolibre",
|
|
253
|
+
"editable": false,
|
|
254
|
+
"help": "final = 只在终态通知;feishu = 恢复旧行为(每步都发)。",
|
|
255
|
+
"binding": {
|
|
256
|
+
"kind": "envfile",
|
|
257
|
+
"file": "fulfillment.env",
|
|
258
|
+
"env": "FULL_NOTIFY_MODE",
|
|
259
|
+
"vertical": "mercadolibre"
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
],
|
|
263
|
+
"entries": []
|
|
264
|
+
}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Argent 单入口(0.3 P1)—— `argent <verb> [args…]`
|
|
4
|
+
*
|
|
5
|
+
* 目的:把宿主(dsh / 未来任何 agent / 云端 MCP)对 Argent 的依赖**收敛成一条命令族**,
|
|
6
|
+
* 而不是散落的 `scripts/*.py|mjs` 文件名 —— 这是"抽离基座"的第一步。
|
|
7
|
+
*
|
|
8
|
+
* ⚠️ **薄别名层**:本文件**不复制任何业务逻辑**,只把 verb 映射到既有脚本(或 core/lib 里的共享实现)
|
|
9
|
+
* 并把参数原样透传 ⇒ 行为与今天直接调脚本**完全一致**(P1 的红线:不动现网行为)。
|
|
10
|
+
* 契约见 core/contracts/argent.contracts.json。
|
|
11
|
+
*
|
|
12
|
+
* 2026-10-03 修两处"假绿"缺陷(均有复现原文,见各自模块头注释):
|
|
13
|
+
* · D1 `ledger` 返回假空 ⇒ 走 `core/lib/ledger.mjs`(读全量 → 过滤 → 再取末尾 N 行;回显生效条件)
|
|
14
|
+
* · D3 解释器单候选 + 空 catch 吞异常 ⇒ 走 `core/lib/python.mjs`(多候选 + 响亮失败)
|
|
15
|
+
*
|
|
16
|
+
* 2026-10-03 P1 第二批:
|
|
17
|
+
* · `license` 组落地(status|verify|install|request|renew|explain,§3.5①):判定点唯一在 CLI 进程内、
|
|
18
|
+
* 离线可验;**旧行为**(恒 `ok:true` 只回计费巡检文本)正是 §2.2④ 要修的假绿;
|
|
19
|
+
* · **写类 verb 接许可闸门**(`flow claim --apply` / `writeback --yes`):调既有
|
|
20
|
+
* `scripts/license-gate.mjs`(**不复制判据**),默认 `observe`(只留证据不拦),`enforce` 才拒写;
|
|
21
|
+
* · `--help --json` 改为报**代码里实际存在**的 verb/子命令(此前直接照抄契约 ⇒ 门禁的
|
|
22
|
+
* "契约声明了、CLI 里没有"这一向恒绿,是假绿空间)。
|
|
23
|
+
*
|
|
24
|
+
* 2026-10-03 P1 第三批(M1 外围三件):
|
|
25
|
+
* · `notify`(P2 webhook 一条):端口 + 通道实现落在 `core/lib/notify/`,**判据与投递分离**
|
|
26
|
+
* (去重/审计/dry-run 在 verb 层,通道只负责"送到没送到");默认 dry-run,真发要 `--apply`;
|
|
27
|
+
* · `init`(数据目录画像,默认 dry-run,`--apply` 才建目录;⛔ 不写 settings/credentials)、
|
|
28
|
+
* `versions`(五面对账)、`audit`(4 处审计 JSONL 只读汇总)、`flow list`(注册表只读清单)。
|
|
29
|
+
*
|
|
30
|
+
* 2026-10-03 P1 首批(`flow claim`):
|
|
31
|
+
* · `claim` 从"其实是分诊"改成**真正的原子认领**(包 `scripts/flow_claim.py`,退出码 3 ⇒ 0 + empty:true);
|
|
32
|
+
* 旧行为逐字保留在 `flow triage` / `claim --plan-only`;
|
|
33
|
+
* · 新增 `flow` 组(claim|triage)+ `triage` 别名;适配层在 `core/lib/claim.mjs`(A1/A2/A3 口径);
|
|
34
|
+
* · `--help --json` 输出机器可读的 verb 清单(门禁 `scripts/check-judgment-drift.mjs` 的"代码侧"来源)。
|
|
35
|
+
*
|
|
36
|
+
* 2026-10-03 P4 收尾(M1 判据③):
|
|
37
|
+
* · `doctor --customer` = **客户机一页式自检**(`core/lib/doctor-customer.mjs`):整机、只读、
|
|
38
|
+
* **不要求本机装 dsh**(无宿主 ⇒ 宿主档事实记 `applicable:false`「本档不适用」,**不算 FAIL**);
|
|
39
|
+
* 退出码按 A1:全 ok/warn ⇒ `0`(warn 只在 JSON 标记)、存在 fail ⇒ `1`、用法错误 ⇒ `2`;
|
|
40
|
+
* · `doctor --flow <id> [--online]` 的旧行为**逐字保留**(仍转发 `scripts/flow_preflight.py`,判据不重复);
|
|
41
|
+
* · ⚠️ `doctor --help` 现在打**自检形态**的用法(那份用法里同时写了单流程形态的出口);
|
|
42
|
+
* 单流程的前置检查帮助仍可直接跑 `python3 scripts/flow_preflight.py --help`。
|
|
43
|
+
*/
|
|
44
|
+
import { execFileSync } from 'node:child_process'
|
|
45
|
+
import { readFileSync } from 'node:fs'
|
|
46
|
+
import { dirname, join, resolve } from 'node:path'
|
|
47
|
+
import { fileURLToPath } from 'node:url'
|
|
48
|
+
import { resolveSop } from '../lib/sop.mjs'
|
|
49
|
+
import { queryLedger, resolveLedgerFlow } from '../lib/ledger.mjs'
|
|
50
|
+
import { pickPython } from '../lib/python.mjs'
|
|
51
|
+
import { resolveDataDir } from '../lib/argent-datadir.mjs'
|
|
52
|
+
import { buildInvocation, runFlowVerb } from '../lib/claim.mjs'
|
|
53
|
+
import { runLicenseVerb, LICENSE_SUBCOMMANDS } from '../lib/license.mjs'
|
|
54
|
+
import { applyGate, gateWrite } from '../lib/license-guard.mjs'
|
|
55
|
+
import { loadRegistry, resolveFlow } from '../lib/flow-registry.mjs'
|
|
56
|
+
import { runNotifyVerb } from '../lib/notify/verb.mjs'
|
|
57
|
+
import { runInitVerb } from '../lib/init.mjs'
|
|
58
|
+
import { runVersionsVerb } from '../lib/versions.mjs'
|
|
59
|
+
import { runAuditVerb } from '../lib/audit.mjs'
|
|
60
|
+
import { runFlowListVerb } from '../lib/flow-list.mjs'
|
|
61
|
+
import { runDoctorCustomerVerb } from '../lib/doctor-customer.mjs'
|
|
62
|
+
|
|
63
|
+
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
64
|
+
const REPO = resolve(HERE, '..', '..')
|
|
65
|
+
// 数据目录:内核三级链(唯一判据)
|
|
66
|
+
const DATA_DIR = resolveDataDir({ env: process.env }).dir
|
|
67
|
+
const script = (p) => join(REPO, p)
|
|
68
|
+
|
|
69
|
+
// 解释器(D3):**多候选 + 响亮失败**。惰性解析 —— 不用 Python 的 verb(version/license,
|
|
70
|
+
// 以及不带 --flow 的 ledger)既不付探测开销,也不因缺解释器而失败("无宿主机器上 version 仍可用")。
|
|
71
|
+
let _py = null
|
|
72
|
+
const python = () => (_py ||= pickPython({ env: process.env, dataDir: DATA_DIR, repo: REPO }))
|
|
73
|
+
const pyPath = () => { const p = python(); return p.ok ? p.path : '' }
|
|
74
|
+
const pyFailure = () => { const p = python(); return p.ok ? null : p.diagnostics }
|
|
75
|
+
|
|
76
|
+
/** `flow claim` / `flow triage` / `claim --plan-only`:同一个适配层(退出码翻译 + A2 回显)。 */
|
|
77
|
+
const flowVerb = (args) => runFlowVerb(args, { repo: REPO, py: pyPath(), pyFailure: pyFailure() })
|
|
78
|
+
|
|
79
|
+
// ── 写类 verb 的许可闸门(P1 第二批,§3.6① 第 4 步)──────────────────────────
|
|
80
|
+
// **不复制判据**:调既有 `scripts/license-gate.mjs`(flow-trigger.sh:238 用的同一个;判定↔取证一份),
|
|
81
|
+
// 本层只决定"这次调用是不是真写"以及"被拒时怎么回"。默认 `observe` ⇒ **只留证据、不拦**。
|
|
82
|
+
const CONFIRM = ['--apply', '--confirm', '--yes', '--write']
|
|
83
|
+
const isRealWrite = (args) => CONFIRM.some((f) => args.includes(f)) && !args.includes('--dry-run')
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 闸门上下文:能力 id 与业务线**从注册表解析**(与 flow-trigger.sh 用 `flow_config.py --get capability`
|
|
87
|
+
* 同源)。注册表读不到 ⇒ 退化为"以流程名当能力"并**如实标注**(宁可不拦 / 不可误停,与 flow-trigger.sh
|
|
88
|
+
* 的 `LICENSE_CAP="$CAP"; [ -n "$LICENSE_CAP" ] || LICENSE_CAP="$FLOW"` 逐字同口径)。
|
|
89
|
+
*/
|
|
90
|
+
function gateContext(flow) {
|
|
91
|
+
const py = pyPath()
|
|
92
|
+
if (!py) return { cap: flow, vertical: null, capSource: 'fallback_no_python' }
|
|
93
|
+
const reg = loadRegistry({ repo: REPO, py })
|
|
94
|
+
if (!reg.ok) return { cap: flow, vertical: null, capSource: `fallback_registry:${reg.reason}` }
|
|
95
|
+
const r = resolveFlow({ input: flow, doc: reg.doc })
|
|
96
|
+
const f = (reg.doc.flows || {})[r.canonical] || {}
|
|
97
|
+
const vertical = r.canonical.includes('.') ? r.canonical.split('.')[0] : null
|
|
98
|
+
return { cap: String(f.capability || r.local || flow), vertical, capSource: 'registry' }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const runGate = (flow) => {
|
|
102
|
+
const ctx = gateContext(flow)
|
|
103
|
+
const gate = gateWrite({ repo: REPO, flow, cap: ctx.cap, vertical: ctx.vertical, env: process.env })
|
|
104
|
+
return { ...gate, capSource: ctx.capSource, cap: ctx.cap, vertical: ctx.vertical, flow }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** 被闸门拒绝(只在 `enforce` 下发生):**整体拒绝 + 零副作用**(不认领、不回写、不落台账)。 */
|
|
108
|
+
const deniedEnvelope = (name, flow, gate) => {
|
|
109
|
+
const json = applyGate({ ok: true, empty: false, code: 0, reason: null, verb: name, flow }, gate)
|
|
110
|
+
return {
|
|
111
|
+
json,
|
|
112
|
+
human: `⛔ 许可闸门[enforce]:${gate.human || gate.reason} ⇒ 拒绝 ${name}(零副作用:没有写任何东西)`,
|
|
113
|
+
stderr: '', exit: 1,
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** `claim`(含 `flow claim`):真写前过闸门;dry-run 不查(不打扰只读路径,也不污染证据)。 */
|
|
118
|
+
function gatedClaim(args) {
|
|
119
|
+
const built = buildInvocation(args)
|
|
120
|
+
const flow = built.ok ? built.echo.flow : (argOf(args, '--flow') || '?')
|
|
121
|
+
const gate = built.ok && !built.dryRun ? runGate(flow) : null
|
|
122
|
+
if (gate && gate.blocked) return deniedEnvelope('claim', flow, gate)
|
|
123
|
+
const res = flowVerb(args)
|
|
124
|
+
if (gate) res.json = applyGate(res.json, gate)
|
|
125
|
+
return res
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** `writeback`:真写(`--yes`/`--write`)前过闸门;默认 dry-run 不查。 */
|
|
129
|
+
function gatedWriteback(args) {
|
|
130
|
+
const flow = argOf(args, '--flow') || 'wenyao-invoice' // 该回写器服务的就是文鳐发票流程
|
|
131
|
+
const gate = isRealWrite(args) ? runGate(flow) : null
|
|
132
|
+
if (gate && gate.blocked) return deniedEnvelope('writeback', flow, gate)
|
|
133
|
+
const out = run('node', [script('scripts/wenyao-invoice-writeback.mjs'), ...args])
|
|
134
|
+
return gate ? applyGate(out, gate) : out
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
/** 未知子命令:A1 的"用法错误"(2)+ A2 的 reason(**不是**静默成功)。 */
|
|
139
|
+
const unknownSub = (sub) => ({
|
|
140
|
+
json: { ok: false, empty: false, code: 2, reason: 'unknown_subcommand',
|
|
141
|
+
error: `未知子命令:${sub || '(缺)'}(可用:claim、triage、list)`,
|
|
142
|
+
flow: null, flowPrefix: null, flowKnown: false, dryRun: null, casesFromDir: null },
|
|
143
|
+
human: `❌ unknown_subcommand:未知子命令 ${sub || '(缺)'}(可用:claim、triage、list)`,
|
|
144
|
+
stderr: '', exit: 2,
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
/** `argent flow <claim|triage|list> …` —— 组 verb 只做分派,不另立判据。 */
|
|
148
|
+
const flowGroup = (args) => {
|
|
149
|
+
const [sub, ...rest] = args
|
|
150
|
+
if (sub === 'claim') return gatedClaim(rest)
|
|
151
|
+
if (sub === 'triage') return flowVerb(rest.includes('--plan-only') ? rest : [...rest, '--plan-only'])
|
|
152
|
+
// P1 第三批:`flow list` = 注册表只读清单(薄包 flow_registry.py --json,不实现合并)
|
|
153
|
+
if (sub === 'list') return runFlowListVerb(rest, { repo: REPO, env: process.env })
|
|
154
|
+
if (sub === '--help' || sub === '-h') { // 组帮助不是"用法错误":列出子命令后 exit 0
|
|
155
|
+
const contracts = JSON.parse(readFileSync(join(HERE, '..', 'contracts', 'argent.contracts.json'), 'utf8'))
|
|
156
|
+
return { json: { ok: true, flow: 'flow', subcommands: Object.keys(contracts.verbs.flow.subcommands || {}) },
|
|
157
|
+
human: `argent flow <子命令> —— ${contracts.verbs.flow.desc}\n`
|
|
158
|
+
+ Object.entries(contracts.verbs.flow.subcommands || {}).map(([s, d]) => ` ${s.padEnd(8)} ${d}`).join('\n'),
|
|
159
|
+
stderr: '', exit: 0 }
|
|
160
|
+
}
|
|
161
|
+
return unknownSub(sub)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** verb → 具体实现(薄映射;后续逐步把实现搬进 core/,宿主侧不用改) */
|
|
165
|
+
const VERBS = {
|
|
166
|
+
version: () => {
|
|
167
|
+
const argent = (readFileSync(script('VERSION'), 'utf8') || '').trim()
|
|
168
|
+
let dsh = ''
|
|
169
|
+
try { dsh = execFileSync('dsh', ['--version'], { encoding: 'utf8' }).trim() } catch { /* 不在 PATH */ }
|
|
170
|
+
return { ok: true, argent, dsh }
|
|
171
|
+
},
|
|
172
|
+
sop: (args) => resolveSop(argOf(args, '--flow') || 'full', { repo: REPO, py: pyPath(), pyFailure: pyFailure() }),
|
|
173
|
+
source: (args) => runPy([script('scripts/flow_source.py'), ...args]),
|
|
174
|
+
flow: (args) => flowGroup(args),
|
|
175
|
+
// P1 首批:`claim` = **真认领**(默认 dry-run;`--plan-only` 走旧的分诊行为)
|
|
176
|
+
// P1 第二批:**真写**(--apply/--confirm)前过许可闸门(observe 只留证据;enforce 直接拒绝)
|
|
177
|
+
claim: (args) => gatedClaim(args),
|
|
178
|
+
// 旧 `claim` 的行为(只出计划)——名字还给它,行为逐字保留
|
|
179
|
+
triage: (args) => flowVerb(args.includes('--plan-only') ? args : [...args, '--plan-only']),
|
|
180
|
+
gap: (args) => runPy([script('scripts/flow_preflight.py'), ...args]),
|
|
181
|
+
// 真写(--yes/--write)前过许可闸门;dry-run(默认)不查 —— 写操作的判据一致,读操作不打扰
|
|
182
|
+
writeback: (args) => gatedWriteback(args),
|
|
183
|
+
report: (args) => runPy([script('scripts/flow_failure.py'), ...args]),
|
|
184
|
+
// D1:读全量 → 过滤 → 再取末尾 N 行;`flow` 回显**实际生效**的过滤条件(null = 未过滤)
|
|
185
|
+
ledger: (args) => queryLedger({
|
|
186
|
+
file: join(DATA_DIR, 'flow-ledger.jsonl'),
|
|
187
|
+
flow: argOf(args, '--flow'),
|
|
188
|
+
tailInput: argOf(args, '--tail'),
|
|
189
|
+
resolveFilter: (f) => resolveLedgerFlow(f, { repo: REPO, py: pyPath(), pyFailure: pyFailure() }),
|
|
190
|
+
}),
|
|
191
|
+
// P1 第二批:许可组(status|verify|install|request|renew|explain)——判定点唯一在 CLI 进程内
|
|
192
|
+
license: (args) => runLicenseVerb(args, { repo: REPO, env: process.env }),
|
|
193
|
+
// `doctor`:**两种形态,判据不重复**。
|
|
194
|
+
// · `doctor --customer`(M1 判据③)= 客户机一页式自检:整机、**只读**、**不要求 dsh**
|
|
195
|
+
// (无宿主 ⇒ 宿主档事实记「本档不适用」,不算 FAIL)—— 见 core/lib/doctor-customer.mjs;
|
|
196
|
+
// · `doctor --flow <id> [--online]`(旧行为,逐字保留)= 单流程前置检查:仍转发
|
|
197
|
+
// `scripts/flow_preflight.py`(同一个脚本,`--customer` 之前它要求 `--flow` ⇒ exit 2)。
|
|
198
|
+
doctor: (args) => (args.includes('--customer') || args.includes('--help') || args.includes('-h')
|
|
199
|
+
? runDoctorCustomerVerb(args, { repo: REPO, env: process.env })
|
|
200
|
+
: runPy([script('scripts/flow_preflight.py'), ...args])),
|
|
201
|
+
// ── P1 第三批(2026-10-03):补齐 M1 判据的外围三件 ──────────────────────────
|
|
202
|
+
// notify:通道选择 + 幂等 + dry-run(判断⑩;适配层在 core/lib/notify/,通道实现可替换)
|
|
203
|
+
notify: (args) => runNotifyVerb(args, { repo: REPO, env: process.env }),
|
|
204
|
+
// init:数据目录画像(判断⑧);默认 dry-run,--apply 才建目录(⛔ 不写 settings/credentials)
|
|
205
|
+
init: (args) => runInitVerb(args, { repo: REPO, env: process.env }),
|
|
206
|
+
// versions:CLI/内核/契约/补丁/能力包版本对账(只读)
|
|
207
|
+
versions: (args) => runVersionsVerb(args, { repo: REPO, env: process.env }),
|
|
208
|
+
// audit:审计 JSONL 只读汇总(先全量→过滤→排序→取末尾 N 行,不回退成"先截断")
|
|
209
|
+
audit: (args) => runAuditVerb(args, { repo: REPO, env: process.env }),
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function run(bin, argv) {
|
|
213
|
+
try {
|
|
214
|
+
const out = execFileSync(bin, argv, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] })
|
|
215
|
+
return { ok: true, output: out }
|
|
216
|
+
} catch (e) {
|
|
217
|
+
return { ok: false, code: e.status ?? 1, output: String(e.stdout || ''), error: String(e.stderr || e.message).slice(0, 400) }
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** 需要 Python 的 verb:解释器不可用时**响亮失败**(不 exec 一个不存在的路径当"没结果")。 */
|
|
222
|
+
function runPy(argv) {
|
|
223
|
+
const p = python()
|
|
224
|
+
if (!p.ok) return { ok: false, code: 2, reason: 'python_unavailable', error: p.diagnostics }
|
|
225
|
+
return run(p.path, argv)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const argOf = (args, name) => { const i = args.indexOf(name); return i > -1 ? args[i + 1] : '' }
|
|
229
|
+
|
|
230
|
+
const [verb, ...args] = process.argv.slice(2)
|
|
231
|
+
if (!verb || verb === '--help' || verb === '-h') {
|
|
232
|
+
const contracts = JSON.parse(readFileSync(join(HERE, '..', 'contracts', 'argent.contracts.json'), 'utf8'))
|
|
233
|
+
// ⚠️ **代码侧清单**:列 `VERBS` 里**真的有实现**的(P1 第二批改)——此前直接照抄契约,
|
|
234
|
+
// 于是门禁 `check-judgment-drift` 的 "契约声明了 verb,CLI 里没有"(R1a)**恒绿**(假绿空间)。
|
|
235
|
+
// 子命令同理:只报本进程真的分派得动的那些。
|
|
236
|
+
const SUBCOMMANDS = { flow: ['claim', 'triage', 'list'], license: [...LICENSE_SUBCOMMANDS] }
|
|
237
|
+
const implemented = Object.keys(VERBS)
|
|
238
|
+
const meta = (name) => {
|
|
239
|
+
const c = contracts.verbs[name] || {}
|
|
240
|
+
return { kind: c.kind || 'read', desc: c.desc || '(未在契约声明 —— 门禁会报 R1b 漂移)' }
|
|
241
|
+
}
|
|
242
|
+
// `--help --json`:机器可读的 verb 清单(门禁/宿主用它拿"代码里实际存在什么",不用解析人话)
|
|
243
|
+
if (args.includes('--json')) {
|
|
244
|
+
const verbs = implemented.map((name) => ({
|
|
245
|
+
name, ...meta(name),
|
|
246
|
+
...(SUBCOMMANDS[name] ? { subcommands: SUBCOMMANDS[name] } : {}),
|
|
247
|
+
...((contracts.verbs[name] || {}).aliases ? { aliases: contracts.verbs[name].aliases } : {}),
|
|
248
|
+
}))
|
|
249
|
+
console.log(JSON.stringify({ ok: true, argent: (readFileSync(script('VERSION'), 'utf8') || '').trim(), verbs }, null, 2))
|
|
250
|
+
process.exit(0)
|
|
251
|
+
}
|
|
252
|
+
console.log('argent <verb> [args…] —— Argent 单入口(0.3 P1,薄别名层)\n')
|
|
253
|
+
for (const name of implemented) {
|
|
254
|
+
const c = meta(name)
|
|
255
|
+
console.log(` ${name.padEnd(10)} [${c.kind}] ${c.desc}`)
|
|
256
|
+
for (const s of SUBCOMMANDS[name] || []) console.log(` · ${s.padEnd(8)} ${(contracts.verbs[name]?.subcommands || {})[s] || ''}`)
|
|
257
|
+
}
|
|
258
|
+
process.exit(0)
|
|
259
|
+
}
|
|
260
|
+
const fn = VERBS[verb]
|
|
261
|
+
if (!fn) { console.error(`未知 verb:${verb}(可用:${Object.keys(VERBS).join(', ')})`); process.exit(2) }
|
|
262
|
+
const AS_JSON = args.includes('--json') || ['version', 'ledger'].includes(verb)
|
|
263
|
+
// P1 第三批:`notify` 的投递是异步的(`--json <payload>` 与 A2 开关同名,由 parseNotifyArgs 自己判形态)
|
|
264
|
+
// ⇒ 顶层 await(本文件是 ESM);同步 verb 不受影响(await 一个非 Promise 值是恒等的)。
|
|
265
|
+
const raw = await fn(args)
|
|
266
|
+
// 适配层 verb 返回信封 `{json, human, stderr}`:人类输出与 JSON 载荷分离 ⇒ `--json` 时 stdout 只有合同字段
|
|
267
|
+
const isEnvelope = Boolean(raw && typeof raw === 'object' && raw.json && typeof raw.json === 'object')
|
|
268
|
+
const out = isEnvelope ? raw.json : raw
|
|
269
|
+
const human = isEnvelope ? raw.human : null
|
|
270
|
+
if (isEnvelope && raw.stderr) process.stderr.write(raw.stderr.endsWith('\n') ? raw.stderr : `${raw.stderr}\n`)
|
|
271
|
+
if (AS_JSON) console.log(JSON.stringify(out, null, 2))
|
|
272
|
+
else console.log(human !== null ? human : (typeof out === 'string' ? out : (out.output || JSON.stringify(out, null, 2))))
|
|
273
|
+
// 失败一律**留痕**(D3:诊断必须看得见;退出码沿用既有口径:ok:false ⇒ code 或 1)
|
|
274
|
+
if (out && out.ok === false && out.error) console.error(String(out.error))
|
|
275
|
+
// A1:`3` **只**表示许可宽限放行 —— 写类 verb 在宽限期内照常完成,但必须用 3 让调用方上报
|
|
276
|
+
const exitCode = out && out.ok === false ? (out.code || 1) : (out && out.code === 3 ? 3 : 0)
|
|
277
|
+
process.exit(exitCode)
|