llm-cli-gateway 2.11.0 → 2.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 (36) hide show
  1. package/.agents/skills/async-job-orchestration/SKILL.md +288 -0
  2. package/.agents/skills/implement-review-fix/SKILL.md +154 -0
  3. package/.agents/skills/multi-llm-review/SKILL.md +174 -0
  4. package/.agents/skills/public-demo-session/SKILL.md +100 -0
  5. package/.agents/skills/secure-orchestration/SKILL.md +227 -0
  6. package/.agents/skills/session-workflow/SKILL.md +271 -0
  7. package/CHANGELOG.md +63 -1
  8. package/README.md +86 -27
  9. package/dist/acp/provider-registry.js +6 -6
  10. package/dist/api-provider.d.ts +7 -0
  11. package/dist/api-provider.js +7 -0
  12. package/dist/api-request.js +1 -0
  13. package/dist/async-job-manager.d.ts +11 -1
  14. package/dist/async-job-manager.js +44 -3
  15. package/dist/config.d.ts +2 -0
  16. package/dist/config.js +3 -0
  17. package/dist/index.d.ts +40 -4
  18. package/dist/index.js +611 -158
  19. package/dist/job-store.d.ts +48 -1
  20. package/dist/job-store.js +184 -0
  21. package/dist/provider-codegen.js +3 -0
  22. package/dist/provider-tool-capabilities.d.ts +4 -0
  23. package/dist/provider-tool-capabilities.js +16 -13
  24. package/dist/upstream-contracts.d.ts +1 -0
  25. package/dist/upstream-contracts.js +202 -45
  26. package/dist/validation-orchestrator.d.ts +5 -2
  27. package/dist/validation-orchestrator.js +71 -5
  28. package/dist/validation-receipt.d.ts +68 -0
  29. package/dist/validation-receipt.js +245 -0
  30. package/dist/validation-report.d.ts +4 -2
  31. package/dist/validation-report.js +18 -1
  32. package/dist/validation-tools.js +58 -9
  33. package/npm-shrinkwrap.json +5 -5
  34. package/package.json +10 -4
  35. package/dist/xai-api-provider.d.ts +0 -43
  36. package/dist/xai-api-provider.js +0 -191
@@ -8,7 +8,7 @@ export const ACP_ENTRYPOINT_CONTRACTS = {
8
8
  status: "native",
9
9
  executable: "vibe-acp",
10
10
  entrypointArgs: [],
11
- targetVersion: "vibe 2.14.1",
11
+ targetVersion: "vibe 2.17.1",
12
12
  probeArgs: [["--version"], ["--help"]],
13
13
  evidence: "Native ACP executable vibe-acp; manual initialize + session/new smoke passed. First runtime pilot.",
14
14
  docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.mistral",
@@ -19,9 +19,9 @@ export const ACP_ENTRYPOINT_CONTRACTS = {
19
19
  status: "native",
20
20
  executable: "grok",
21
21
  entrypointArgs: ["agent", "stdio"],
22
- targetVersion: "grok 0.2.50 (cadf94855)",
22
+ targetVersion: "grok 0.2.73 (9ff14c43bb)",
23
23
  probeArgs: [["agent", "stdio", "--help"]],
24
- evidence: "Native ACP via `grok agent stdio`; initialize + session/new smoke passed with isolated leader socket. Second runtime pilot.",
24
+ evidence: "Native ACP via `grok agent stdio`; initialize + session/new smoke passed with isolated leader socket. Second runtime pilot. Entrypoint re-probed clean at 0.2.73.",
25
25
  docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.grok",
26
26
  },
27
27
  codex: {
@@ -30,10 +30,10 @@ export const ACP_ENTRYPOINT_CONTRACTS = {
30
30
  status: "adapter_mediated_deferred",
31
31
  executable: "codex",
32
32
  entrypointArgs: [],
33
- targetVersion: "codex-cli 0.139.0",
33
+ targetVersion: "codex-cli 0.142.4",
34
34
  probeArgs: [],
35
35
  adapterCandidates: ["zed-industries/codex-acp", "agentclientprotocol/codex-acp"],
36
- evidence: "No native ACP entrypoint at codex-cli 0.139.0. Adapter evidence tracked as documentation only; not native gateway ACP support.",
36
+ evidence: "No native ACP entrypoint at codex-cli 0.142.4. Adapter evidence tracked as documentation only; not native gateway ACP support.",
37
37
  docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.codex",
38
38
  },
39
39
  claude: {
@@ -42,10 +42,10 @@ export const ACP_ENTRYPOINT_CONTRACTS = {
42
42
  status: "adapter_mediated_deferred",
43
43
  executable: "claude",
44
44
  entrypointArgs: [],
45
- targetVersion: "claude 2.1.175",
45
+ targetVersion: "claude 2.1.195",
46
46
  probeArgs: [],
47
47
  adapterCandidates: ["Claude Agent SDK ACP adapter"],
48
- evidence: "No native Claude Code CLI ACP entrypoint at claude 2.1.175. Adapter ownership/permission bridging unresolved; deferred.",
48
+ evidence: "No native Claude Code CLI ACP entrypoint at claude 2.1.195. Adapter ownership/permission bridging unresolved; deferred.",
49
49
  docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.claude",
50
50
  },
51
51
  gemini: {
@@ -54,9 +54,9 @@ export const ACP_ENTRYPOINT_CONTRACTS = {
54
54
  status: "absent_watchlist",
55
55
  executable: "agy",
56
56
  entrypointArgs: [],
57
- targetVersion: "agy 1.0.7",
57
+ targetVersion: "agy 1.0.13",
58
58
  probeArgs: [],
59
- evidence: "agy 1.0.7 has no ACP flag or subcommand. Legacy Gemini CLI ACP evidence does not transfer. Watchlist item.",
59
+ evidence: "agy 1.0.13 has no ACP flag or subcommand. Legacy Gemini CLI ACP evidence does not transfer. Watchlist item.",
60
60
  docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.gemini",
61
61
  },
62
62
  devin: {
@@ -65,10 +65,10 @@ export const ACP_ENTRYPOINT_CONTRACTS = {
65
65
  status: "native",
66
66
  executable: "devin",
67
67
  entrypointArgs: ["acp"],
68
- targetVersion: "devin 2026.5.26-8 (1a388fa9)",
68
+ targetVersion: "devin 2026.8.18 (16737566)",
69
69
  probeArgs: [["--version"]],
70
70
  evidence: 'Native ACP entrypoint `devin acp` (stdio JSON-RPC). Slice D1 manual initialize + session/new smoke passed (protocolVersion 1, agent "Affogato", session created). Third native runtime pilot; routing stays config-gated.',
71
- docsRef: "docs/plans/devin-integration-scoping.md",
71
+ docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.devin",
72
72
  },
73
73
  };
74
74
  const PERMISSION_MODES = [
@@ -107,6 +107,7 @@ function subcommand(commandPath, summary, risk, flags = [], options = {}) {
107
107
  summary,
108
108
  conformanceFixtures: options.fixtures ?? [],
109
109
  acknowledgedUpstreamFlags: options.acknowledgedUpstreamFlags ?? [],
110
+ ...(options.helpProbeExitTolerant ? { helpProbeExitTolerant: true } : {}),
110
111
  };
111
112
  }
112
113
  function acknowledgeSubcommandFlags(subcommands, flags) {
@@ -147,6 +148,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
147
148
  agents: subcommand(["agents"], "Inspect and manage Claude agent definitions.", "writes_local_config", [
148
149
  "--add-dir",
149
150
  "--agent",
151
+ "--all",
150
152
  "--allow-dangerously-skip-permissions",
151
153
  "--cwd",
152
154
  "--dangerously-skip-permissions",
@@ -305,8 +307,11 @@ export const UPSTREAM_CLI_CONTRACTS = {
305
307
  acknowledgedUpstreamFlags: [
306
308
  "--allow-dangerously-skip-permissions",
307
309
  "--allowed",
310
+ "--ax-screen-reader",
311
+ "--background",
308
312
  "--bare",
309
313
  "--betas",
314
+ "--bg",
310
315
  "--brief",
311
316
  "--chrome",
312
317
  "--dangerously-skip-permissions",
@@ -318,7 +323,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
318
323
  "--from-pr",
319
324
  "--ide",
320
325
  "--include-hook-events",
321
- "--mcp-debug",
322
326
  "--name",
323
327
  "--no-chrome",
324
328
  "--plugin-dir",
@@ -329,6 +333,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
329
333
  "--remote-control-session-name-prefix",
330
334
  "--replay-user-messages",
331
335
  "--resume",
336
+ "--safe-mode",
332
337
  "--tmux",
333
338
  "--version",
334
339
  "--worktree",
@@ -416,6 +421,12 @@ export const UPSTREAM_CLI_CONTRACTS = {
416
421
  ],
417
422
  expect: "pass",
418
423
  },
424
+ {
425
+ id: "claude-background-acknowledged-not-emitted",
426
+ description: "Claude 2.1.195 advertises --bg/--background (background agent), but the gateway acknowledges them without emitting; caller argv is rejected",
427
+ args: ["-p", "hello", "--background"],
428
+ expect: "fail",
429
+ },
419
430
  ],
420
431
  },
421
432
  codex: {
@@ -471,33 +482,40 @@ export const UPSTREAM_CLI_CONTRACTS = {
471
482
  ], {
472
483
  children: {
473
484
  resume: subcommand(["exec", "resume"], "Resume Codex sessions from the interactive CLI.", "executes_agent", [
474
- "--add-dir",
475
485
  "--all",
476
- "--cd",
477
486
  "--config",
478
487
  "--dangerously-bypass-approvals-and-sandbox",
479
488
  "--dangerously-bypass-hook-trust",
480
489
  "--disable",
481
490
  "--enable",
491
+ "--ephemeral",
492
+ "--ignore-rules",
493
+ "--ignore-user-config",
482
494
  "--image",
483
- "--include-non-interactive",
495
+ "--json",
484
496
  "--last",
485
- "--local-provider",
486
497
  "--model",
487
- "--no-alt-screen",
488
- "--oss",
489
- "--profile",
490
- "--remote",
491
- "--remote-auth-token-env",
492
- "--sandbox",
498
+ "--output-last-message",
499
+ "--output-schema",
500
+ "--skip-git-repo-check",
493
501
  "--strict-config",
494
502
  ]),
495
503
  review: subcommand(["exec", "review"], "Run Codex code review workflows.", "executes_agent", [
496
504
  "--base",
497
505
  "--commit",
498
506
  "--config",
507
+ "--dangerously-bypass-approvals-and-sandbox",
508
+ "--dangerously-bypass-hook-trust",
499
509
  "--disable",
500
510
  "--enable",
511
+ "--ephemeral",
512
+ "--ignore-rules",
513
+ "--ignore-user-config",
514
+ "--json",
515
+ "--model",
516
+ "--output-last-message",
517
+ "--output-schema",
518
+ "--skip-git-repo-check",
501
519
  "--strict-config",
502
520
  "--title",
503
521
  "--uncommitted",
@@ -889,7 +907,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
889
907
  plugins: subcommand(["plugins"], "Alias for Antigravity plugin management.", "writes_local_config", [], {
890
908
  aliases: ["plugin"],
891
909
  }),
892
- update: subcommand(["update"], "Update Antigravity CLI to the current release.", "writes_local_config", [], { tokenCost: "small" }),
910
+ update: subcommand(["update"], "Update Antigravity CLI to the current release.", "writes_local_config", [], { tokenCost: "small", helpProbeExitTolerant: true }),
893
911
  },
894
912
  maxPositionals: 1,
895
913
  mcpTools: ["gemini_request", "gemini_request_async"],
@@ -911,6 +929,8 @@ export const UPSTREAM_CLI_CONTRACTS = {
911
929
  "attachments",
912
930
  "skipTrust",
913
931
  "yolo",
932
+ "project",
933
+ "newProject",
914
934
  ],
915
935
  flags: {
916
936
  "--print": { arity: "none", description: "Run a single prompt non-interactively" },
@@ -926,14 +946,13 @@ export const UPSTREAM_CLI_CONTRACTS = {
926
946
  "--conversation": { arity: "one", description: "Resume a previous conversation by ID" },
927
947
  "--continue": { arity: "none", description: "Continue the most recent conversation" },
928
948
  "-c": { arity: "none", description: "Short alias for --continue" },
949
+ "--project": { arity: "one", description: "Antigravity project ID for this session" },
950
+ "--new-project": {
951
+ arity: "none",
952
+ description: "Create a new Antigravity project for this session",
953
+ },
929
954
  },
930
- acknowledgedUpstreamFlags: [
931
- "--prompt-interactive",
932
- "-i",
933
- "--print-timeout",
934
- "--log-file",
935
- "--version",
936
- ],
955
+ acknowledgedUpstreamFlags: ["--log-file", "--print-timeout", "--prompt-interactive"],
937
956
  env: {},
938
957
  conformanceFixtures: [
939
958
  {
@@ -972,6 +991,18 @@ export const UPSTREAM_CLI_CONTRACTS = {
972
991
  args: ["--print", "hello", "-o", "json"],
973
992
  expect: "fail",
974
993
  },
994
+ {
995
+ id: "gemini-project-wired",
996
+ description: "Antigravity 1.0.13: --project <ID> is wired",
997
+ args: ["--print", "hello", "--project", "proj-123"],
998
+ expect: "pass",
999
+ },
1000
+ {
1001
+ id: "gemini-new-project-wired",
1002
+ description: "Antigravity 1.0.13: --new-project is wired",
1003
+ args: ["--print", "hello", "--new-project"],
1004
+ expect: "pass",
1005
+ },
975
1006
  ],
976
1007
  },
977
1008
  grok: {
@@ -1022,6 +1053,17 @@ export const UPSTREAM_CLI_CONTRACTS = {
1022
1053
  },
1023
1054
  }),
1024
1055
  completions: subcommand(["completions"], "Generate Grok shell completions.", "read_only", ["--leader-socket"], { tier: "inspect" }),
1056
+ dashboard: subcommand(["dashboard"], "Open the Agent Dashboard view at startup.", "read_only", ["--leader-socket"], {
1057
+ tier: "inspect",
1058
+ fixtures: [
1059
+ {
1060
+ id: "grok-dashboard",
1061
+ description: "grok dashboard subcommand (leader socket passthrough)",
1062
+ args: ["--leader-socket", "/tmp/dash.sock"],
1063
+ expect: "pass",
1064
+ },
1065
+ ],
1066
+ }),
1025
1067
  export: subcommand(["export"], "Export Grok session data.", "read_only", ["--clipboard", "--leader-socket"], { tier: "inspect" }),
1026
1068
  import: subcommand(["import"], "Import Grok session data.", "writes_local_config", [
1027
1069
  "--json",
@@ -1052,7 +1094,49 @@ export const UPSTREAM_CLI_CONTRACTS = {
1052
1094
  tier: "inspect",
1053
1095
  }),
1054
1096
  setup: subcommand(["setup"], "Configure Grok CLI local setup.", "writes_local_config", ["--leader-socket"], { exposure: "not_exposed" }),
1055
- ssh: subcommand(["ssh"], "Manage Grok SSH integration.", "network", ["--leader-socket"]),
1097
+ ssh: subcommand(["ssh"], "Manage Grok SSH integration.", "network", ["--leader-socket"], {
1098
+ acknowledgedUpstreamFlags: [
1099
+ "--agent",
1100
+ "--agents",
1101
+ "--allow",
1102
+ "--always-approve",
1103
+ "--best-of-n",
1104
+ "--check",
1105
+ "--continue",
1106
+ "--cwd",
1107
+ "--deny",
1108
+ "--disable-web-search",
1109
+ "--disallowed-tools",
1110
+ "--effort",
1111
+ "--experimental-memory",
1112
+ "--fork-session",
1113
+ "--json-schema",
1114
+ "--max-turns",
1115
+ "--model",
1116
+ "--no-alt-screen",
1117
+ "--no-memory",
1118
+ "--no-plan",
1119
+ "--no-subagents",
1120
+ "--oauth",
1121
+ "--output-format",
1122
+ "--permission-mode",
1123
+ "--prompt-file",
1124
+ "--prompt-json",
1125
+ "--reasoning-effort",
1126
+ "--restore-code",
1127
+ "--resume",
1128
+ "--rules",
1129
+ "--sandbox",
1130
+ "--session-id",
1131
+ "--single",
1132
+ "--system-prompt-override",
1133
+ "--tools",
1134
+ "--verbatim",
1135
+ "--version",
1136
+ "--worktree",
1137
+ "--worktree-ref",
1138
+ ],
1139
+ }),
1056
1140
  trace: subcommand(["trace"], "Inspect Grok trace data.", "read_only", ["--json", "--leader-socket", "--local", "--output"], { tier: "diagnostic" }),
1057
1141
  update: subcommand(["update"], "Update the Grok CLI binary.", "updates_binary", [
1058
1142
  "--alpha",
@@ -1067,7 +1151,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
1067
1151
  worktree: subcommand(["worktree"], "Manage Grok worktree sessions.", "writes_local_config", ["--leader-socket"]),
1068
1152
  }, GROK_DEBUG_HELP_FLAGS),
1069
1153
  maxPositionals: 0,
1070
- acknowledgedUpstreamFlags: GROK_DEBUG_HELP_FLAGS,
1154
+ acknowledgedUpstreamFlags: [...GROK_DEBUG_HELP_FLAGS, "--session-id"],
1071
1155
  mcpTools: ["grok_request", "grok_request_async"],
1072
1156
  mcpParameters: [
1073
1157
  "prompt",
@@ -1112,6 +1196,9 @@ export const UPSTREAM_CLI_CONTRACTS = {
1112
1196
  "restoreCode",
1113
1197
  "leaderSocket",
1114
1198
  "nativeWorktree",
1199
+ "worktreeRef",
1200
+ "forkSession",
1201
+ "jsonSchema",
1115
1202
  ],
1116
1203
  flags: {
1117
1204
  "-p": { arity: "one", description: "Prompt text" },
@@ -1197,22 +1284,40 @@ export const UPSTREAM_CLI_CONTRACTS = {
1197
1284
  description: "Custom leader socket path (isolated leader, Grok 0.2.32+)",
1198
1285
  },
1199
1286
  "--single": { arity: "one", description: "Single-turn prompt" },
1200
- "--todo-gate": { arity: "none", description: "Enable runtime turn-end TodoGate" },
1287
+ "--todo-gate": {
1288
+ arity: "none",
1289
+ description: "Enable runtime turn-end TodoGate (accepted at 0.2.60+ but hidden from --help)",
1290
+ hiddenFromHelp: true,
1291
+ },
1201
1292
  "--verbatim": { arity: "none", description: "Send prompt exactly as given" },
1202
1293
  "--version": { arity: "none", description: "Print version" },
1203
1294
  "--worktree": {
1204
1295
  arity: "optional",
1205
1296
  description: "Start the session in a new git worktree, optionally named",
1206
1297
  },
1298
+ "--worktree-ref": {
1299
+ arity: "one",
1300
+ description: "Git ref to base the worktree on (requires --worktree)",
1301
+ },
1302
+ "--fork-session": {
1303
+ arity: "none",
1304
+ description: "Fork the resumed session into a new session ID",
1305
+ },
1306
+ "--json-schema": {
1307
+ arity: "one",
1308
+ description: "JSON Schema literal constraining structured output (implies json output)",
1309
+ },
1207
1310
  "--compaction-mode": {
1208
1311
  arity: "one",
1209
1312
  values: ["summary", "transcript", "segments"],
1210
1313
  description: "Compaction mode (default summary; sets GROK_COMPACTION_MODE). `segments` persists per-segment markdown.",
1314
+ hiddenFromHelp: true,
1211
1315
  },
1212
1316
  "--compaction-detail": {
1213
1317
  arity: "one",
1214
1318
  values: ["none", "minimal", "balanced", "verbose"],
1215
1319
  description: "Segment verbatim detail (default verbose; sets GROK_COMPACTION_DETAIL). Only affects `--compaction-mode segments`.",
1320
+ hiddenFromHelp: true,
1216
1321
  },
1217
1322
  },
1218
1323
  env: {},
@@ -1370,6 +1475,35 @@ export const UPSTREAM_CLI_CONTRACTS = {
1370
1475
  args: ["-p", "hello", "--agent", "reviewer", "--leader-socket", "/tmp/leader.sock"],
1371
1476
  expect: "pass",
1372
1477
  },
1478
+ {
1479
+ id: "grok-json-schema-wired",
1480
+ description: "Grok 0.2.73: --json-schema <SCHEMA> is wired (structured output, implies json)",
1481
+ args: [
1482
+ "-p",
1483
+ "hello",
1484
+ "--json-schema",
1485
+ '{"type":"object","properties":{"name":{"type":"string"}}}',
1486
+ ],
1487
+ expect: "pass",
1488
+ },
1489
+ {
1490
+ id: "grok-fork-session-wired",
1491
+ description: "Grok 0.2.73: --fork-session is wired (fork resumed session into a new ID)",
1492
+ args: ["-p", "hello", "--resume", "sess-1", "--fork-session"],
1493
+ expect: "pass",
1494
+ },
1495
+ {
1496
+ id: "grok-worktree-ref-wired",
1497
+ description: "Grok 0.2.73: --worktree-ref <REF> is wired (with --worktree)",
1498
+ args: ["-p", "hello", "--worktree", "--worktree-ref", "main"],
1499
+ expect: "pass",
1500
+ },
1501
+ {
1502
+ id: "grok-session-id-acknowledged-not-emitted",
1503
+ description: "Grok 0.2.73 advertises --session-id, but the gateway owns session-id lifecycle and does not emit it; caller argv is rejected",
1504
+ args: ["-p", "hello", "--session-id", "11111111-1111-1111-1111-111111111111"],
1505
+ expect: "fail",
1506
+ },
1373
1507
  ],
1374
1508
  },
1375
1509
  mistral: {
@@ -1377,7 +1511,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
1377
1511
  executable: "vibe",
1378
1512
  upstream: "Mistral Vibe CLI",
1379
1513
  upstreamMetadata: {
1380
- sourceUrls: ["https://github.com/mistralai/mistral-vibe/releases"],
1514
+ sourceUrls: ["https://api.github.com/repos/mistralai/mistral-vibe/releases/latest"],
1381
1515
  packageName: "mistral-vibe",
1382
1516
  repo: "https://github.com/mistralai/mistral-vibe",
1383
1517
  installDocsUrl: "https://github.com/mistralai/mistral-vibe#installation",
@@ -1459,7 +1593,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
1459
1593
  description: "Additional writable workspace directory (Phase 4 slice ζ; repeat once per directory)",
1460
1594
  },
1461
1595
  },
1462
- acknowledgedUpstreamFlags: ["--auto-approve"],
1596
+ acknowledgedUpstreamFlags: ["--auto-approve", "--check-upgrade", "--yolo"],
1463
1597
  env: {
1464
1598
  VIBE_ACTIVE_MODEL: {
1465
1599
  arity: "one",
@@ -1558,11 +1692,25 @@ export const UPSTREAM_CLI_CONTRACTS = {
1558
1692
  },
1559
1693
  {
1560
1694
  id: "mistral-current-help-surface",
1561
- description: "Vibe 2.12.x help surface: --prompt, -v, --version, --setup accepted",
1695
+ description: "Vibe 2.17.1 request-time help surface: --prompt, -v, --version, --setup accepted",
1562
1696
  args: ["--prompt", "hello", "--agent", "auto-approve", "-v", "--version", "--setup"],
1563
1697
  env: { VIBE_ACTIVE_MODEL: "mistral-medium-3.5" },
1564
1698
  expect: "pass",
1565
1699
  },
1700
+ {
1701
+ id: "mistral-yolo-shortcut-rejected",
1702
+ description: "Vibe 2.17.1 advertises --yolo as a shortcut, but the gateway keeps using explicit --agent auto-approve",
1703
+ args: ["-p", "hello", "--yolo"],
1704
+ env: { VIBE_ACTIVE_MODEL: "mistral-medium-3.5" },
1705
+ expect: "fail",
1706
+ },
1707
+ {
1708
+ id: "mistral-check-upgrade-rejected",
1709
+ description: "Vibe 2.17.1 advertises --check-upgrade, but gateway request validation rejects update-prompt flags",
1710
+ args: ["--check-upgrade"],
1711
+ env: { VIBE_ACTIVE_MODEL: "mistral-medium-3.5" },
1712
+ expect: "fail",
1713
+ },
1566
1714
  {
1567
1715
  id: "mistral-resume-bare",
1568
1716
  description: "Vibe --resume without session ID is accepted (optional arity)",
@@ -1604,13 +1752,22 @@ export const UPSTREAM_CLI_CONTRACTS = {
1604
1752
  "--model": { arity: "one", description: "AI model for this session" },
1605
1753
  "--permission-mode": {
1606
1754
  arity: "one",
1607
- values: ["normal", "auto", "dangerous", "yolo", "bypass"],
1608
- description: "Permission mode (normal/auto = read-only auto-approve; dangerous/yolo/bypass = approve all)",
1755
+ values: ["auto", "smart", "dangerous"],
1756
+ description: "Permission mode (auto = read-only auto-approve; smart = additionally auto-runs safe actions per fast model; dangerous = approve all)",
1609
1757
  },
1610
1758
  "--prompt-file": { arity: "one", description: "Load the initial prompt from a file" },
1611
1759
  "--resume": { arity: "one", description: "Resume a specific session by ID" },
1612
1760
  "--continue": { arity: "none", description: "Resume the most recent session in cwd" },
1613
1761
  },
1762
+ acknowledgedUpstreamFlags: [
1763
+ "--agent-config",
1764
+ "--config",
1765
+ "--export",
1766
+ "--print",
1767
+ "--respect-workspace-trust",
1768
+ "--sandbox",
1769
+ "--version",
1770
+ ],
1614
1771
  env: {},
1615
1772
  conformanceFixtures: [
1616
1773
  {
@@ -1633,20 +1790,20 @@ export const UPSTREAM_CLI_CONTRACTS = {
1633
1790
  },
1634
1791
  {
1635
1792
  id: "devin-permission-mode",
1636
- description: "Valid --permission-mode accepted (dangerous alias bypass)",
1637
- args: ["-p", "hello", "--permission-mode", "bypass"],
1793
+ description: "Valid --permission-mode 'dangerous' accepted",
1794
+ args: ["-p", "hello", "--permission-mode", "dangerous"],
1638
1795
  expect: "pass",
1639
1796
  },
1640
1797
  {
1641
1798
  id: "devin-permission-mode-auto",
1642
- description: "Valid --permission-mode alias 'auto' (= normal) accepted",
1799
+ description: "Valid --permission-mode 'auto' accepted",
1643
1800
  args: ["-p", "hello", "--permission-mode", "auto"],
1644
1801
  expect: "pass",
1645
1802
  },
1646
1803
  {
1647
- id: "devin-permission-mode-yolo",
1648
- description: "Valid --permission-mode alias 'yolo' (= dangerous) accepted",
1649
- args: ["-p", "hello", "--permission-mode", "yolo"],
1804
+ id: "devin-permission-mode-smart",
1805
+ description: "Valid --permission-mode 'smart' accepted",
1806
+ args: ["-p", "hello", "--permission-mode", "smart"],
1650
1807
  expect: "pass",
1651
1808
  },
1652
1809
  {
@@ -2224,7 +2381,7 @@ function probeInstalledCliSubcommands(cli, timeoutMs) {
2224
2381
  break;
2225
2382
  }
2226
2383
  outputs.push(`${result.stdout ?? ""}\n${result.stderr ?? ""}`);
2227
- if (result.status !== 0) {
2384
+ if (result.status !== 0 && !sub.helpProbeExitTolerant) {
2228
2385
  warnings.push(`${contract.executable} ${args.join(" ")} exited with status ${result.status}`);
2229
2386
  }
2230
2387
  }
@@ -3,11 +3,13 @@ import { type ProviderRuntimeStatus } from "./provider-status.js";
3
3
  import type { ApiProviderRuntime } from "./config.js";
4
4
  import { type NormalizedValidationResult, type ValidationProvider } from "./validation-normalizer.js";
5
5
  import { type ValidationReport } from "./validation-report.js";
6
+ import type { ValidationRunStore } from "./job-store.js";
6
7
  import { type ValidationIntent } from "./validation-prompts.js";
7
8
  export interface ValidationOrchestratorDeps {
8
9
  asyncJobManager: AsyncJobManager;
9
10
  getProviderRuntimeStatus?: (provider: ValidationProvider) => ProviderRuntimeStatus;
10
11
  apiProviders?: ApiProviderRuntime[];
12
+ validationRunStore?: ValidationRunStore | null;
11
13
  }
12
14
  export interface StartValidationInput {
13
15
  intent: ValidationIntent;
@@ -21,7 +23,7 @@ export interface StartValidationInput {
21
23
  export interface ValidationRunReport {
22
24
  success: boolean;
23
25
  validationId: string;
24
- status: "running" | "partial" | "not_started";
26
+ status: "running" | "partial" | "not_started" | "completed";
25
27
  startedAt: string;
26
28
  intent: ValidationIntent;
27
29
  originalRequest: {
@@ -32,7 +34,7 @@ export interface ValidationRunReport {
32
34
  modelList: ValidationProvider[];
33
35
  results: NormalizedValidationResult[];
34
36
  synthesis: {
35
- status: "not_requested" | "waiting_for_provider_results" | "running" | "skipped";
37
+ status: "not_requested" | "waiting_for_provider_results" | "running" | "skipped" | "completed";
36
38
  judgeModel: ValidationProvider | null;
37
39
  rawJobReference: NormalizedValidationResult["rawJobReference"];
38
40
  note: string;
@@ -45,5 +47,6 @@ export declare function startJudgeSynthesis(deps: ValidationOrchestratorDeps, in
45
47
  question: string;
46
48
  providerResults: NormalizedValidationResult[];
47
49
  judgeProvider: ValidationProvider;
50
+ validationId?: string;
48
51
  }): ValidationRunReport["synthesis"];
49
52
  export declare function collectValidationJobResult(deps: ValidationOrchestratorDeps, provider: ValidationProvider, jobId: string, model: string | null, maxChars?: number): NormalizedValidationResult | null;
@@ -3,7 +3,8 @@ import { getProviderRuntimeStatus } from "./provider-status.js";
3
3
  import { createApiProvider } from "./api-provider.js";
4
4
  import { prepareApiRequest } from "./api-request.js";
5
5
  import { normalizeJobResult, normalizeSkippedProvider, normalizeStartedJob, } from "./validation-normalizer.js";
6
- import { buildValidationReport } from "./validation-report.js";
6
+ import { buildValidationReport, deriveValidationRunStatus, } from "./validation-report.js";
7
+ import { getRequestContext, principalCanAccess, resolveOwnerPrincipal } from "./request-context.js";
7
8
  import { buildJudgePrompt, buildValidationPrompt, } from "./validation-prompts.js";
8
9
  function findApiReviewer(deps, provider) {
9
10
  return deps.apiProviders?.find(p => p.name === provider) ?? null;
@@ -21,8 +22,13 @@ function dispatchProviderJob(deps, provider, prompt, correlationId) {
21
22
  if (api) {
22
23
  const apiProvider = createApiProvider(api.name, api.kind);
23
24
  const apiRequest = prepareApiRequest(api, { prompt });
24
- return deps.asyncJobManager.startHttpJob({ provider: apiProvider, apiRequest, correlationId })
25
- .snapshot;
25
+ return deps.asyncJobManager.startHttpJob({
26
+ provider: apiProvider,
27
+ apiRequest,
28
+ correlationId,
29
+ writeFlightStart: true,
30
+ flightRecorderEntry: { model: apiRequest.model, prompt },
31
+ }).snapshot;
26
32
  }
27
33
  return deps.asyncJobManager.startJob(provider, buildProviderArgs(provider, prompt), correlationId);
28
34
  }
@@ -39,9 +45,16 @@ export function startValidationRun(deps, input) {
39
45
  const providers = uniqueProviders(input.providers);
40
46
  const results = providers.map(provider => startProviderJob(deps, provider, prompt, validationId));
41
47
  const runningCount = results.filter(result => result.status === "running").length;
42
- const skippedCount = results.filter(result => result.status === "skipped").length;
43
48
  const synthesis = plannedJudgeSynthesis(input);
44
- const status = runningCount === 0 ? "not_started" : skippedCount > 0 ? "partial" : "running";
49
+ const status = deriveValidationRunStatus(results, synthesis.status);
50
+ persistValidationRun(deps, {
51
+ validationId,
52
+ startedAt,
53
+ intent: input.intent,
54
+ input,
55
+ providers,
56
+ results,
57
+ });
45
58
  const reportInput = {
46
59
  validationId,
47
60
  status,
@@ -103,6 +116,7 @@ export function startJudgeSynthesis(deps, input) {
103
116
  question: input.question,
104
117
  providerResults: completedResults,
105
118
  }), `validation-judge-${randomUUID()}-${input.judgeProvider}`);
119
+ linkJudgeJob(deps, input.validationId, input.judgeProvider, snapshot);
106
120
  return {
107
121
  status: "running",
108
122
  judgeModel: input.judgeProvider,
@@ -150,6 +164,58 @@ function plannedJudgeSynthesis(input) {
150
164
  note: "Collect provider results first, then call synthesize_validation with those results.",
151
165
  };
152
166
  }
167
+ function linkJudgeJob(deps, validationId, provider, snapshot) {
168
+ const store = deps.validationRunStore;
169
+ if (!store || !validationId)
170
+ return;
171
+ try {
172
+ const run = store.getValidationRun(validationId);
173
+ if (!run)
174
+ return;
175
+ if (!principalCanAccess(run.ownerPrincipal, resolveOwnerPrincipal(getRequestContext())))
176
+ return;
177
+ store.setValidationJudgeLink(validationId, {
178
+ provider: String(provider),
179
+ jobId: snapshot.id,
180
+ correlationId: snapshot.correlationId,
181
+ });
182
+ }
183
+ catch {
184
+ }
185
+ }
186
+ function persistValidationRun(deps, args) {
187
+ const store = deps.validationRunStore;
188
+ if (!store)
189
+ return;
190
+ try {
191
+ const providerLinks = args.results
192
+ .filter(result => result.rawJobReference !== null)
193
+ .map(result => ({
194
+ provider: String(result.provider),
195
+ jobId: result.rawJobReference.jobId,
196
+ correlationId: result.rawJobReference.correlationId,
197
+ }));
198
+ store.recordValidationRun({
199
+ validationId: args.validationId,
200
+ ownerPrincipal: resolveOwnerPrincipal(getRequestContext()),
201
+ intent: args.intent,
202
+ createdAt: args.startedAt,
203
+ requestJson: JSON.stringify({
204
+ question: args.input.question,
205
+ content: args.input.content,
206
+ focus: args.input.focus,
207
+ riskLevel: args.input.riskLevel,
208
+ modelList: args.providers,
209
+ judgeProvider: args.input.judgeProvider ?? null,
210
+ }),
211
+ providerLinks,
212
+ judgeLink: null,
213
+ status: "running",
214
+ });
215
+ }
216
+ catch {
217
+ }
218
+ }
153
219
  function buildProviderArgs(provider, prompt) {
154
220
  if (provider === "claude" || provider === "grok" || provider === "mistral") {
155
221
  return ["-p", prompt];