@mnemom/mnemom 0.10.0 → 0.12.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 (40) hide show
  1. package/README.md +25 -25
  2. package/dist/commands/agents.js +2 -7
  3. package/dist/commands/api-key.d.ts +37 -0
  4. package/dist/commands/api-key.js +179 -0
  5. package/dist/commands/auth.js +1 -2
  6. package/dist/commands/card.js +33 -22
  7. package/dist/commands/governance.d.ts +85 -0
  8. package/dist/commands/governance.js +329 -0
  9. package/dist/commands/integrity.js +1 -2
  10. package/dist/commands/license.js +13 -4
  11. package/dist/commands/listen.d.ts +29 -0
  12. package/dist/commands/listen.js +201 -0
  13. package/dist/commands/logs.js +1 -3
  14. package/dist/commands/org.js +4 -6
  15. package/dist/commands/protection.js +70 -23
  16. package/dist/commands/recipes.d.ts +34 -0
  17. package/dist/commands/recipes.js +80 -0
  18. package/dist/commands/status.js +6 -169
  19. package/dist/commands/team.js +5 -10
  20. package/dist/commands/validate.js +7 -4
  21. package/dist/commands/webhooks.d.ts +61 -0
  22. package/dist/commands/webhooks.js +328 -0
  23. package/dist/index.js +489 -1
  24. package/dist/lib/api.d.ts +199 -2
  25. package/dist/lib/api.js +207 -0
  26. package/dist/lib/auth.js +1 -5
  27. package/dist/lib/format.d.ts +4 -0
  28. package/dist/lib/format.js +6 -0
  29. package/dist/lib/listen-stream.d.ts +40 -0
  30. package/dist/lib/listen-stream.js +101 -0
  31. package/dist/lib/webhooks-api.d.ts +80 -0
  32. package/dist/lib/webhooks-api.js +172 -0
  33. package/dist/smoltbot-shim.js +3 -3
  34. package/package.json +1 -1
  35. package/dist/lib/model-cache.d.ts +0 -16
  36. package/dist/lib/model-cache.js +0 -137
  37. package/dist/lib/models.d.ts +0 -41
  38. package/dist/lib/models.js +0 -357
  39. package/dist/lib/openclaw.d.ts +0 -221
  40. package/dist/lib/openclaw.js +0 -474
package/dist/index.js CHANGED
@@ -10,10 +10,13 @@ import { protectionShowCommand, protectionPublishCommand, protectionValidateComm
10
10
  import { agentsListCommand } from "./commands/agents.js";
11
11
  import { orgListCommand, orgShowCommand } from "./commands/org.js";
12
12
  import { teamListCommand, teamShowCommand, teamTemplateCommand, teamPreviewComposeCommand, teamAdminGrantCommand, teamAdminRevokeCommand, teamAdminListCommand, teamCoverageCommand, } from "./commands/team.js";
13
- import { advisoriesListCommand, advisoriesShowCommand, } from "./commands/advisories.js";
13
+ import { advisoriesListCommand, advisoriesShowCommand } from "./commands/advisories.js";
14
14
  import { postureListCommand, postureShowCommand, postureCreateCommand, postureUpdateCommand, postureCloneCommand, postureRevisionsCommand, postureDiffCommand, postureAssignCommand, postureUnassignCommand, posturePreviewComposeCommand, postureDeleteCommand, } from "./commands/posture.js";
15
15
  import { loginCommand, logoutCommand, whoamiCommand } from "./commands/auth.js";
16
16
  import { validateSafeHouseCommand } from "./commands/validate.js";
17
+ import { apiKeyListCommand, apiKeyCreateCommand, apiKeyRotateCommand, apiKeyRevokeCommand, } from "./commands/api-key.js";
18
+ import { webhooksListCommand, webhooksGetCommand, webhooksCreateCommand, webhooksUpdateCommand, webhooksDeleteCommand, webhooksRotateSecretCommand, webhooksTriggerCommand, webhooksListDeliveriesCommand, webhooksRedeliverCommand, webhooksReplayCommand, } from "./commands/webhooks.js";
19
+ import { listenCommand } from "./commands/listen.js";
17
20
  program
18
21
  .name("mnemom")
19
22
  .description("Transparent AI agent tracing")
@@ -521,6 +524,212 @@ advisoriesCmd
521
524
  }
522
525
  });
523
526
  // ============================================================================
527
+ // Governance signals (ADR-048) — operator-actionable observation surface
528
+ //
529
+ // Distinct from `mnemom advisories list` (which now narrows to runtime.* /
530
+ // manual.* per ADR-048 §1). Surfaces sideband.* + future protection.* /
531
+ // posture.* signals from governance_signals: ack/resolve/dismiss workflow,
532
+ // notification destinations (slack/email/pagerduty/webhook), escalation
533
+ // rules.
534
+ // ============================================================================
535
+ import { governanceSignalsListCommand, governanceSignalsShowCommand, governanceSignalsAckCommand, governanceSignalsResolveCommand, governanceSignalsDismissCommand, governanceDestinationsListCommand, governanceDestinationsAddCommand, governanceDestinationsRemoveCommand, governanceDestinationsTestCommand, governanceRulesListCommand, governanceRulesAddCommand, governanceRulesRemoveCommand, } from "./commands/governance.js";
536
+ const governanceCmd = program
537
+ .command("governance")
538
+ .description("Operator workflow for governance_signals (ADR-048)");
539
+ const govSignalsCmd = governanceCmd
540
+ .command("signals")
541
+ .description("List, inspect, and transition governance_signals");
542
+ govSignalsCmd
543
+ .command("list")
544
+ .description("List governance signals at platform/org/team/agent scope")
545
+ .option("--org <id>", "Org scope")
546
+ .option("--team <id>", "Team scope")
547
+ .option("--agent <id>", "Per-agent slice (signals affecting this agent)")
548
+ .option("--source <s>", "Filter by source (sideband.{drift,coherence,fault_line,fleet})")
549
+ .option("--severity <s>", "Filter by severity (info|warn|high|critical)")
550
+ .option("--status <s>", "Filter by status (open|acknowledged|resolved|dismissed|expired)")
551
+ .option("--scope <s>", "Filter by scope (platform|org|team|agent)")
552
+ .option("--pattern-type <s>", "Filter by pattern_type")
553
+ .option("--since <iso>", "Detected since (ISO timestamp)")
554
+ .option("--limit <n>", "Max rows (default 100, max 500)")
555
+ .option("--json", "Output JSON")
556
+ .action(async (options) => {
557
+ try {
558
+ await governanceSignalsListCommand(options);
559
+ }
560
+ catch (error) {
561
+ console.error("Error:", error instanceof Error ? error.message : error);
562
+ process.exit(1);
563
+ }
564
+ });
565
+ govSignalsCmd
566
+ .command("show <signal_id>")
567
+ .description("Show one signal in detail")
568
+ .option("--json", "Output JSON")
569
+ .action(async (signalId, options) => {
570
+ try {
571
+ await governanceSignalsShowCommand(signalId, options);
572
+ }
573
+ catch (error) {
574
+ console.error("Error:", error instanceof Error ? error.message : error);
575
+ process.exit(1);
576
+ }
577
+ });
578
+ govSignalsCmd
579
+ .command("ack <signal_id>")
580
+ .description("Acknowledge an open signal (org_admin / org_owner)")
581
+ .option("--action <text>", "Operator-authored action note")
582
+ .option("--json", "Output JSON")
583
+ .action(async (signalId, options) => {
584
+ try {
585
+ await governanceSignalsAckCommand(signalId, options);
586
+ }
587
+ catch (error) {
588
+ console.error("Error:", error instanceof Error ? error.message : error);
589
+ process.exit(1);
590
+ }
591
+ });
592
+ govSignalsCmd
593
+ .command("resolve <signal_id>")
594
+ .description("Resolve a signal with a resolution status")
595
+ .requiredOption("--status <s>", "Resolution status (action_taken|wont_fix|duplicate|false_positive|self_resolved)")
596
+ .option("--action <text>", "Operator-authored action note")
597
+ .option("--json", "Output JSON")
598
+ .action(async (signalId, options) => {
599
+ try {
600
+ await governanceSignalsResolveCommand(signalId, options);
601
+ }
602
+ catch (error) {
603
+ console.error("Error:", error instanceof Error ? error.message : error);
604
+ process.exit(1);
605
+ }
606
+ });
607
+ govSignalsCmd
608
+ .command("dismiss <signal_id>")
609
+ .description("Dismiss a signal as not actionable")
610
+ .option("--reason <text>", "Operator-authored dismissal reason")
611
+ .option("--json", "Output JSON")
612
+ .action(async (signalId, options) => {
613
+ try {
614
+ await governanceSignalsDismissCommand(signalId, options);
615
+ }
616
+ catch (error) {
617
+ console.error("Error:", error instanceof Error ? error.message : error);
618
+ process.exit(1);
619
+ }
620
+ });
621
+ const govDestCmd = governanceCmd
622
+ .command("destinations")
623
+ .description("Manage notification destinations (slack/email/pagerduty/webhook)");
624
+ govDestCmd
625
+ .command("list")
626
+ .description("List destinations for an org")
627
+ .requiredOption("--org <id>", "Org ID")
628
+ .option("--json", "Output JSON")
629
+ .action(async (options) => {
630
+ try {
631
+ await governanceDestinationsListCommand(options);
632
+ }
633
+ catch (error) {
634
+ console.error("Error:", error instanceof Error ? error.message : error);
635
+ process.exit(1);
636
+ }
637
+ });
638
+ govDestCmd
639
+ .command("add")
640
+ .description("Add a destination (channel + JSON config)")
641
+ .requiredOption("--org <id>", "Org ID")
642
+ .requiredOption("--channel <c>", "webhook|slack|email|pagerduty")
643
+ .requiredOption("--config <json>", 'Channel config (e.g., \'{"url":"...","signing_secret":"..."}\')')
644
+ .option("--name <n>", "Display name")
645
+ .option("--filter <json>", "Filter narrowing (sources/severities/etc)")
646
+ .option("--json", "Output JSON")
647
+ .action(async (options) => {
648
+ try {
649
+ await governanceDestinationsAddCommand(options);
650
+ }
651
+ catch (error) {
652
+ console.error("Error:", error instanceof Error ? error.message : error);
653
+ process.exit(1);
654
+ }
655
+ });
656
+ govDestCmd
657
+ .command("remove <destination_id>")
658
+ .description("Remove a destination")
659
+ .requiredOption("--org <id>", "Org ID")
660
+ .option("--json", "Output JSON")
661
+ .action(async (id, options) => {
662
+ try {
663
+ await governanceDestinationsRemoveCommand(id, options);
664
+ }
665
+ catch (error) {
666
+ console.error("Error:", error instanceof Error ? error.message : error);
667
+ process.exit(1);
668
+ }
669
+ });
670
+ govDestCmd
671
+ .command("test <destination_id>")
672
+ .description("Send a synthetic test signal through this destination")
673
+ .requiredOption("--org <id>", "Org ID")
674
+ .option("--json", "Output JSON")
675
+ .action(async (id, options) => {
676
+ try {
677
+ await governanceDestinationsTestCommand(id, options);
678
+ }
679
+ catch (error) {
680
+ console.error("Error:", error instanceof Error ? error.message : error);
681
+ process.exit(1);
682
+ }
683
+ });
684
+ const govRulesCmd = governanceCmd
685
+ .command("rules")
686
+ .description("Manage escalation rules (predicate → destinations)");
687
+ govRulesCmd
688
+ .command("list")
689
+ .description("List escalation rules for an org")
690
+ .requiredOption("--org <id>", "Org ID")
691
+ .option("--json", "Output JSON")
692
+ .action(async (options) => {
693
+ try {
694
+ await governanceRulesListCommand(options);
695
+ }
696
+ catch (error) {
697
+ console.error("Error:", error instanceof Error ? error.message : error);
698
+ process.exit(1);
699
+ }
700
+ });
701
+ govRulesCmd
702
+ .command("add")
703
+ .description("Add an escalation rule (predicate JSON + destination IDs)")
704
+ .requiredOption("--org <id>", "Org ID")
705
+ .requiredOption("--name <n>", "Rule name")
706
+ .requiredOption("--predicate <json>", 'Predicate JSON (e.g., \'{"source":"sideband.fleet","severity_min":"high"}\')')
707
+ .requiredOption("--destinations <ids>", "Comma-separated destination IDs")
708
+ .option("--json", "Output JSON")
709
+ .action(async (options) => {
710
+ try {
711
+ await governanceRulesAddCommand(options);
712
+ }
713
+ catch (error) {
714
+ console.error("Error:", error instanceof Error ? error.message : error);
715
+ process.exit(1);
716
+ }
717
+ });
718
+ govRulesCmd
719
+ .command("remove <rule_id>")
720
+ .description("Remove an escalation rule")
721
+ .requiredOption("--org <id>", "Org ID")
722
+ .option("--json", "Output JSON")
723
+ .action(async (id, options) => {
724
+ try {
725
+ await governanceRulesRemoveCommand(id, options);
726
+ }
727
+ catch (error) {
728
+ console.error("Error:", error instanceof Error ? error.message : error);
729
+ process.exit(1);
730
+ }
731
+ });
732
+ // ============================================================================
524
733
  // Trust Posture (Piece 3 of T1-3.1, ADR-045)
525
734
  //
526
735
  // Postures are team-scoped policy input that drives the observer's sideband
@@ -764,4 +973,283 @@ validateCmd
764
973
  process.exit(1);
765
974
  }
766
975
  });
976
+ // ── api-key (ADR-049 capability-based scopes) ────────────────────────────
977
+ const apiKeyCmd = program
978
+ .command("api-key")
979
+ .description("Manage personal API keys (capability-based scopes — ADR-049)");
980
+ apiKeyCmd
981
+ .command("list")
982
+ .description("List your active personal API keys with their scope sets")
983
+ .option("--json", "Emit raw JSON instead of rendered output")
984
+ .action(async (options) => {
985
+ try {
986
+ await apiKeyListCommand({ json: options.json });
987
+ }
988
+ catch (error) {
989
+ console.error("Error:", error instanceof Error ? error.message : error);
990
+ process.exit(1);
991
+ }
992
+ });
993
+ apiKeyCmd
994
+ .command("create")
995
+ .description("Mint a new personal API key. Default scopes: gateway, api:read, api:write. " +
996
+ "Admin scopes (admin:org, admin:platform) are role-gated at mint time.")
997
+ .requiredOption("--name <name>", "Friendly name for the key (e.g. 'ci-prod')")
998
+ .option("--scopes <list>", "Comma-separated capability scopes. Valid: " +
999
+ "gateway, api:read, api:write, admin:org, admin:platform. " +
1000
+ "Default: gateway,api:read,api:write")
1001
+ .option("--json", "Emit raw JSON instead of rendered output")
1002
+ .action(async (options) => {
1003
+ try {
1004
+ await apiKeyCreateCommand({
1005
+ name: options.name,
1006
+ scopes: options.scopes,
1007
+ json: options.json,
1008
+ });
1009
+ }
1010
+ catch (error) {
1011
+ console.error("Error:", error instanceof Error ? error.message : error);
1012
+ process.exit(1);
1013
+ }
1014
+ });
1015
+ apiKeyCmd
1016
+ .command("rotate <key_id>")
1017
+ .description("Atomic mint-new + revoke-old. Returns the new cleartext once.")
1018
+ .option("--json", "Emit raw JSON instead of rendered output")
1019
+ .action(async (keyId, options) => {
1020
+ try {
1021
+ await apiKeyRotateCommand(keyId, { json: options.json });
1022
+ }
1023
+ catch (error) {
1024
+ console.error("Error:", error instanceof Error ? error.message : error);
1025
+ process.exit(1);
1026
+ }
1027
+ });
1028
+ apiKeyCmd
1029
+ .command("revoke <key_id>")
1030
+ .description("Soft-revoke an active key. Action is immediate and irreversible.")
1031
+ .action(async (keyId) => {
1032
+ try {
1033
+ await apiKeyRevokeCommand(keyId);
1034
+ }
1035
+ catch (error) {
1036
+ console.error("Error:", error instanceof Error ? error.message : error);
1037
+ process.exit(1);
1038
+ }
1039
+ });
1040
+ // ============================================================================
1041
+ // Webhook lifecycle commands (Track 2 W3.5)
1042
+ // ============================================================================
1043
+ const webhooksCmd = program
1044
+ .command("webhooks")
1045
+ .description("Manage webhook endpoints, deliveries, and event replay");
1046
+ webhooksCmd
1047
+ .command("list <org_id>")
1048
+ .description("List webhook endpoints for an org")
1049
+ .option("--json", "Emit raw JSON instead of rendered output")
1050
+ .action(async (orgId, options) => {
1051
+ try {
1052
+ await webhooksListCommand(orgId, options);
1053
+ }
1054
+ catch (error) {
1055
+ console.error("Error:", error instanceof Error ? error.message : error);
1056
+ process.exit(1);
1057
+ }
1058
+ });
1059
+ webhooksCmd
1060
+ .command("get <org_id> <endpoint_id>")
1061
+ .description("Show details for a single webhook endpoint")
1062
+ .option("--json", "Emit raw JSON instead of rendered output")
1063
+ .action(async (orgId, endpointId, options) => {
1064
+ try {
1065
+ await webhooksGetCommand(orgId, endpointId, options);
1066
+ }
1067
+ catch (error) {
1068
+ console.error("Error:", error instanceof Error ? error.message : error);
1069
+ process.exit(1);
1070
+ }
1071
+ });
1072
+ webhooksCmd
1073
+ .command("create <org_id>")
1074
+ .description("Create a new webhook endpoint (signing secret returned ONCE)")
1075
+ .requiredOption("--url <url>", "HTTPS URL to deliver events to (private/internal IPs blocked)")
1076
+ .option("--events <list>", "Comma-separated list of event types to subscribe to (default: none — explicit per-event opt-in)")
1077
+ .option("--description <text>", "Human-readable description")
1078
+ .option("--json", "Emit raw JSON instead of rendered output")
1079
+ .action(async (orgId, options) => {
1080
+ try {
1081
+ await webhooksCreateCommand(orgId, options);
1082
+ }
1083
+ catch (error) {
1084
+ console.error("Error:", error instanceof Error ? error.message : error);
1085
+ process.exit(1);
1086
+ }
1087
+ });
1088
+ webhooksCmd
1089
+ .command("update <org_id> <endpoint_id>")
1090
+ .description("Update fields on an existing webhook endpoint")
1091
+ .option("--url <url>", "Replace the delivery URL")
1092
+ .option("--events <list>", "Replace the event-type subscription list (comma-separated)")
1093
+ .option("--description <text>", "Replace the description")
1094
+ .option("--active <bool>", "Set is_active to 'true' or 'false' (re-enabling resets failure counter)")
1095
+ .option("--json", "Emit raw JSON instead of rendered output")
1096
+ .action(async (orgId, endpointId, options) => {
1097
+ try {
1098
+ await webhooksUpdateCommand(orgId, endpointId, options);
1099
+ }
1100
+ catch (error) {
1101
+ console.error("Error:", error instanceof Error ? error.message : error);
1102
+ process.exit(1);
1103
+ }
1104
+ });
1105
+ webhooksCmd
1106
+ .command("delete <org_id> <endpoint_id>")
1107
+ .description("Permanently delete a webhook endpoint")
1108
+ .action(async (orgId, endpointId) => {
1109
+ try {
1110
+ await webhooksDeleteCommand(orgId, endpointId);
1111
+ }
1112
+ catch (error) {
1113
+ console.error("Error:", error instanceof Error ? error.message : error);
1114
+ process.exit(1);
1115
+ }
1116
+ });
1117
+ webhooksCmd
1118
+ .command("rotate-secret <org_id> <endpoint_id>")
1119
+ .description("Mint a new signing secret (shown ONCE; immediately invalidates the previous secret)")
1120
+ .option("--json", "Emit raw JSON instead of rendered output")
1121
+ .action(async (orgId, endpointId, options) => {
1122
+ try {
1123
+ await webhooksRotateSecretCommand(orgId, endpointId, options);
1124
+ }
1125
+ catch (error) {
1126
+ console.error("Error:", error instanceof Error ? error.message : error);
1127
+ process.exit(1);
1128
+ }
1129
+ });
1130
+ webhooksCmd
1131
+ .command("trigger <org_id> <endpoint_id>")
1132
+ .description("Fire a synthetic test event through the full delivery pipeline (Stripe-equivalent ergonomics)")
1133
+ .option("--json", "Emit raw JSON instead of rendered output")
1134
+ .action(async (orgId, endpointId, options) => {
1135
+ try {
1136
+ await webhooksTriggerCommand(orgId, endpointId, options);
1137
+ }
1138
+ catch (error) {
1139
+ console.error("Error:", error instanceof Error ? error.message : error);
1140
+ process.exit(1);
1141
+ }
1142
+ });
1143
+ webhooksCmd
1144
+ .command("list-deliveries <org_id>")
1145
+ .description("List recent webhook deliveries (optionally scoped to one endpoint)")
1146
+ .option("--endpoint <endpoint_id>", "Scope to a single endpoint")
1147
+ .option("--limit <n>", "Maximum entries to return (default 50, max 100)")
1148
+ .option("--offset <n>", "Skip the first N entries (pagination)")
1149
+ .option("--json", "Emit raw JSON instead of rendered output")
1150
+ .action(async (orgId, options) => {
1151
+ try {
1152
+ await webhooksListDeliveriesCommand(orgId, options);
1153
+ }
1154
+ catch (error) {
1155
+ console.error("Error:", error instanceof Error ? error.message : error);
1156
+ process.exit(1);
1157
+ }
1158
+ });
1159
+ webhooksCmd
1160
+ .command("redeliver <org_id> <delivery_id>")
1161
+ .description("Retry a single previous delivery (re-fires that one delivery row)")
1162
+ .option("--json", "Emit raw JSON instead of rendered output")
1163
+ .action(async (orgId, deliveryId, options) => {
1164
+ try {
1165
+ await webhooksRedeliverCommand(orgId, deliveryId, options);
1166
+ }
1167
+ catch (error) {
1168
+ console.error("Error:", error instanceof Error ? error.message : error);
1169
+ process.exit(1);
1170
+ }
1171
+ });
1172
+ webhooksCmd
1173
+ .command("replay <org_id> <event_id>")
1174
+ .description("Re-fan-out a historical event to all currently-subscribed endpoints (or to a specified subset)")
1175
+ .option("--endpoint <endpoint_id>", "Only replay to the specified endpoint (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
1176
+ .option("--json", "Emit raw JSON instead of rendered output")
1177
+ .action(async (orgId, eventId, options) => {
1178
+ try {
1179
+ await webhooksReplayCommand(orgId, eventId, options);
1180
+ }
1181
+ catch (error) {
1182
+ console.error("Error:", error instanceof Error ? error.message : error);
1183
+ process.exit(1);
1184
+ }
1185
+ });
1186
+ // ============================================================================
1187
+ // mnemom listen — live webhook event stream (Track 2 W3.4)
1188
+ // ============================================================================
1189
+ program
1190
+ .command("listen <org_id>")
1191
+ .description("Stream live webhook events for an org (Stripe-equivalent ergonomics)")
1192
+ .option("--forward-to <url>", "POST each event to this local URL (requires --secret for HMAC re-signing)")
1193
+ .option("--secret <hex>", "Local signing secret used to re-sign forwarded deliveries")
1194
+ .option("--filter <list>", "Comma-separated event types to surface (default: all)")
1195
+ .option("--since <event_id>", "Resume from this cursor on first connect")
1196
+ .option("--json", "Emit raw JSON lines instead of a formatted summary")
1197
+ .action(async (orgId, options) => {
1198
+ try {
1199
+ await listenCommand(orgId, options);
1200
+ }
1201
+ catch (error) {
1202
+ console.error("Error:", error instanceof Error ? error.message : error);
1203
+ process.exit(1);
1204
+ }
1205
+ });
1206
+ // ============================================================================
1207
+ // AEGIS-6b — Customer FN/FP recipe report commands.
1208
+ //
1209
+ // `mnemom recipes report-fn <recipe-id>` / `mnemom recipes report-fp <id>`
1210
+ // POST to /v1/recipes/:id/report (AEGIS-6a; mnemom-api#508). The endpoint
1211
+ // requires customer-session auth (JWT cookie/bearer or API key) and a
1212
+ // non-empty summary; the CLI accepts the summary as `--summary` or via
1213
+ // stdin. Idempotency-Key is generated per call by postApi(); the body
1214
+ // fingerprint is folded server-side so a retry with corrected text returns
1215
+ // 422 rather than silently replaying.
1216
+ // ============================================================================
1217
+ import { recipesReportFnCommand, recipesReportFpCommand, } from "./commands/recipes.js";
1218
+ const recipesCmd = program
1219
+ .command("recipes")
1220
+ .description("Customer-side recipe reporting (false-negatives, false-positives)");
1221
+ recipesCmd
1222
+ .command("report-fn <recipe-id>")
1223
+ .description("File a false-negative report against an existing recipe (something got through that the recipe should have caught)")
1224
+ .option("--summary <text>", "Human-readable description of what happened (required; pipe via stdin alternatively)")
1225
+ .option("--evidence <text>", "Optional raw payload / log excerpt")
1226
+ .option("--agent <id>", "Optional. Your agent id when the report concerns a specific agent")
1227
+ .option("--checkpoint <id>", "Optional. Related integrity_checkpoints id (helps the reviewer correlate)")
1228
+ .option("--json", "Output JSON")
1229
+ .action(async (recipeId, options) => {
1230
+ try {
1231
+ await recipesReportFnCommand(recipeId, options);
1232
+ }
1233
+ catch (error) {
1234
+ console.error("Error:", error instanceof Error ? error.message : error);
1235
+ process.exit(1);
1236
+ }
1237
+ });
1238
+ recipesCmd
1239
+ .command("report-fp <recipe-id>")
1240
+ .description("File a false-positive report against an existing recipe (the recipe fired on legitimate behaviour)")
1241
+ .option("--summary <text>", "Human-readable description of what happened (required; pipe via stdin alternatively)")
1242
+ .option("--evidence <text>", "Optional raw payload / log excerpt")
1243
+ .option("--agent <id>", "Optional. Your agent id when the report concerns a specific agent")
1244
+ .option("--checkpoint <id>", "Optional. Related integrity_checkpoints id (helps the reviewer correlate)")
1245
+ .option("--json", "Output JSON")
1246
+ .action(async (recipeId, options) => {
1247
+ try {
1248
+ await recipesReportFpCommand(recipeId, options);
1249
+ }
1250
+ catch (error) {
1251
+ console.error("Error:", error instanceof Error ? error.message : error);
1252
+ process.exit(1);
1253
+ }
1254
+ });
767
1255
  program.parse();