@vibecheckai/cli 3.9.0 → 4.0.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 (88) hide show
  1. package/README.md +1 -1
  2. package/bin/runners/context/generators/cursor-enhanced.js +99 -13
  3. package/bin/runners/lib/unified-cli-output.js +16 -0
  4. package/bin/runners/runCI.js +353 -0
  5. package/bin/runners/runCheckpoint.js +2 -2
  6. package/mcp-server/.eslintrc.json +24 -0
  7. package/mcp-server/README.md +425 -135
  8. package/mcp-server/SPEC.md +583 -0
  9. package/mcp-server/configs/README.md +172 -0
  10. package/mcp-server/configs/claude-desktop-pro.json +31 -0
  11. package/mcp-server/configs/claude-desktop-with-workspace.json +25 -0
  12. package/mcp-server/configs/claude-desktop.json +19 -0
  13. package/mcp-server/configs/cursor-mcp.json +21 -0
  14. package/mcp-server/configs/windsurf-mcp.json +17 -0
  15. package/mcp-server/mcp-config.example.json +9 -0
  16. package/mcp-server/package.json +49 -34
  17. package/mcp-server/src/cli.ts +185 -0
  18. package/mcp-server/src/index.ts +85 -0
  19. package/mcp-server/src/server.ts +1933 -0
  20. package/mcp-server/src/services/cache-service.ts +466 -0
  21. package/mcp-server/src/services/cli-service.ts +345 -0
  22. package/mcp-server/src/services/context-manager.ts +717 -0
  23. package/mcp-server/src/services/firewall-service.ts +662 -0
  24. package/mcp-server/src/services/git-service.ts +671 -0
  25. package/mcp-server/src/services/index.ts +52 -0
  26. package/mcp-server/src/services/prompt-builder-service.ts +1031 -0
  27. package/mcp-server/src/services/session-service.ts +550 -0
  28. package/mcp-server/src/services/tier-service.ts +470 -0
  29. package/mcp-server/src/types.ts +351 -0
  30. package/mcp-server/tsconfig.json +16 -27
  31. package/package.json +6 -6
  32. package/mcp-server/.guardrail/audit/audit.log.jsonl +0 -2
  33. package/mcp-server/.specs/architecture.mdc +0 -90
  34. package/mcp-server/.specs/security.mdc +0 -30
  35. package/mcp-server/HARDENING_SUMMARY.md +0 -299
  36. package/mcp-server/agent-checkpoint.js +0 -364
  37. package/mcp-server/agent-firewall-interceptor.js +0 -500
  38. package/mcp-server/architect-tools.js +0 -707
  39. package/mcp-server/audit-mcp.js +0 -206
  40. package/mcp-server/authority-tools.js +0 -569
  41. package/mcp-server/codebase-architect-tools.js +0 -838
  42. package/mcp-server/conductor/conflict-resolver.js +0 -588
  43. package/mcp-server/conductor/execution-planner.js +0 -544
  44. package/mcp-server/conductor/index.js +0 -377
  45. package/mcp-server/conductor/lock-manager.js +0 -615
  46. package/mcp-server/conductor/request-queue.js +0 -550
  47. package/mcp-server/conductor/session-manager.js +0 -500
  48. package/mcp-server/conductor/tools.js +0 -510
  49. package/mcp-server/consolidated-tools.js +0 -1170
  50. package/mcp-server/deprecation-middleware.js +0 -282
  51. package/mcp-server/handlers/index.ts +0 -15
  52. package/mcp-server/handlers/tool-handler.ts +0 -593
  53. package/mcp-server/hygiene-tools.js +0 -428
  54. package/mcp-server/index-v1.js +0 -698
  55. package/mcp-server/index.js +0 -2940
  56. package/mcp-server/intelligence-tools.js +0 -664
  57. package/mcp-server/intent-drift-tools.js +0 -873
  58. package/mcp-server/intent-firewall-interceptor.js +0 -529
  59. package/mcp-server/lib/api-client.cjs +0 -13
  60. package/mcp-server/lib/cache-wrapper.cjs +0 -383
  61. package/mcp-server/lib/error-envelope.js +0 -138
  62. package/mcp-server/lib/executor.ts +0 -499
  63. package/mcp-server/lib/index.ts +0 -29
  64. package/mcp-server/lib/logger.cjs +0 -30
  65. package/mcp-server/lib/rate-limiter.js +0 -166
  66. package/mcp-server/lib/sandbox.test.ts +0 -519
  67. package/mcp-server/lib/sandbox.ts +0 -395
  68. package/mcp-server/lib/types.ts +0 -267
  69. package/mcp-server/logger.js +0 -173
  70. package/mcp-server/manifest.json +0 -473
  71. package/mcp-server/mdc-generator.js +0 -298
  72. package/mcp-server/premium-tools.js +0 -1275
  73. package/mcp-server/proof-tools.js +0 -571
  74. package/mcp-server/registry/tool-registry.js +0 -586
  75. package/mcp-server/registry/tools.json +0 -619
  76. package/mcp-server/registry.test.ts +0 -340
  77. package/mcp-server/test-mcp.js +0 -108
  78. package/mcp-server/test-tools.js +0 -36
  79. package/mcp-server/tests/tier-gating.test.js +0 -297
  80. package/mcp-server/tier-auth.js +0 -767
  81. package/mcp-server/tools/index.js +0 -72
  82. package/mcp-server/tools-reorganized.ts +0 -244
  83. package/mcp-server/tools-v3.js +0 -1004
  84. package/mcp-server/truth-context.js +0 -622
  85. package/mcp-server/truth-firewall-tools.js +0 -2183
  86. package/mcp-server/vibecheck-2.0-tools.js +0 -761
  87. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
  88. package/mcp-server/vibecheck-tools.js +0 -1075
@@ -1,529 +0,0 @@
1
- /**
2
- * Intent-Aware Firewall Interceptor - MCP Tool v3.0
3
- *
4
- * ═══════════════════════════════════════════════════════════════════════════════
5
- * AGENT FIREWALL™ v3.0 - UNIFIED ENFORCEMENT GATEWAY
6
- * ═══════════════════════════════════════════════════════════════════════════════
7
- *
8
- * SEAMLESS UX: When no intent is declared, changes are OBSERVED (not blocked).
9
- * Changes are logged to the session collector for later approval.
10
- *
11
- * Now uses the unified EnforcementGateway for all operations:
12
- * - Real-time interception with explainable blocks
13
- * - Signed verdicts for audit trail
14
- * - Fix guidance for each violation
15
- *
16
- * Modes:
17
- * - No intent → OBSERVE: Log changes, allow to proceed, prompt for intent
18
- * - Intent exists → ENFORCE: Check alignment, block if not aligned
19
- *
20
- * @module intent-firewall-interceptor
21
- * @version 3.0.0
22
- */
23
-
24
- import path from "path";
25
- import fs from "fs";
26
- import { createRequire } from "module";
27
-
28
- // Import tier auth for secure tier validation
29
- import { getMcpToolAccess } from "./tier-auth.js";
30
-
31
- const require = createRequire(import.meta.url);
32
-
33
- // Import v3 unified enforcement gateway
34
- let createGateway, IntentStore, checkAlignment, MODE, VERDICT, SessionCollector;
35
- let createOrchestrator, ModeConfig; // Legacy compatibility
36
- try {
37
- const agentFirewall = require("../bin/runners/lib/agent-firewall");
38
- createGateway = agentFirewall.createGateway;
39
- IntentStore = agentFirewall.IntentStore;
40
- checkAlignment = agentFirewall.checkAlignment;
41
- MODE = agentFirewall.MODE;
42
- VERDICT = agentFirewall.VERDICT;
43
- SessionCollector = agentFirewall.SessionCollector;
44
-
45
- // Legacy compatibility
46
- createOrchestrator = agentFirewall.createOrchestrator;
47
- ModeConfig = agentFirewall.ModeConfig;
48
- } catch (err) {
49
- console.warn(`[Intent Firewall] v3 modules not available: ${err.message}`);
50
-
51
- // Fallback to v2 imports
52
- try {
53
- const enforcement = require("../bin/runners/lib/agent-firewall/enforcement");
54
- createOrchestrator = enforcement.createOrchestrator;
55
- createGateway = enforcement.createGateway;
56
- MODE = enforcement.MODE;
57
- VERDICT = enforcement.VERDICT;
58
- ModeConfig = enforcement.ModeConfig;
59
-
60
- const intent = require("../bin/runners/lib/agent-firewall/intent");
61
- IntentStore = intent.IntentStore;
62
- checkAlignment = intent.checkAlignment;
63
-
64
- const session = require("../bin/runners/lib/agent-firewall/session");
65
- SessionCollector = session.SessionCollector;
66
- } catch (err2) {
67
- console.warn(`[Intent Firewall] Fallback failed: ${err2.message}`);
68
- }
69
- }
70
-
71
- /**
72
- * MCP Tool Definition for Intent-Aware Interception
73
- */
74
- const INTENT_FIREWALL_TOOL = {
75
- name: "vibecheck_intent_firewall_intercept",
76
- description: `🛡️ Intent-Aware Agent Firewall v2.1 - SEAMLESS enforcement.
77
-
78
- Intercepts AI code changes with seamless UX:
79
- - No intent declared? → OBSERVE mode (changes logged, allowed to proceed)
80
- - Intent declared? → ENFORCE mode (check alignment, block if not aligned)
81
-
82
- After a vibe session, run: vibecheck approve
83
- This reviews logged changes and creates intent retroactively.
84
-
85
- Returns: { mode, decision, logged, intent_prompt }`,
86
- inputSchema: {
87
- type: "object",
88
- required: ["agentId", "filePath", "content"],
89
- properties: {
90
- agentId: {
91
- type: "string",
92
- description: "Agent identifier (e.g., 'cursor', 'windsurf', 'copilot')"
93
- },
94
- filePath: {
95
- type: "string",
96
- description: "File path relative to project root"
97
- },
98
- content: {
99
- type: "string",
100
- description: "New file content"
101
- },
102
- oldContent: {
103
- type: "string",
104
- description: "Old file content (optional, for diff generation)"
105
- },
106
- intent: {
107
- type: "string",
108
- description: "Agent's stated intent for this change (NOT user intent - user intent must be declared via CLI)"
109
- },
110
- projectRoot: {
111
- type: "string",
112
- default: ".",
113
- description: "Project root directory"
114
- },
115
- apiKey: {
116
- type: "string",
117
- description: "API key for authentication"
118
- }
119
- }
120
- }
121
- };
122
-
123
- /**
124
- * Handle MCP tool call for intent-aware interception
125
- * Uses the unified EnforcementGateway for all operations
126
- *
127
- * @param {string} name - Tool name (unused)
128
- * @param {object} args - Tool arguments
129
- * @returns {object} MCP tool response
130
- */
131
- async function handleIntentFirewallIntercept(name, args) {
132
- const projectRoot = path.resolve(args.projectRoot || ".");
133
- const agentId = args.agentId || "unknown";
134
- const filePath = args.filePath;
135
- const content = args.content;
136
- const oldContent = args.oldContent || null;
137
- const agentIntent = args.intent || "No intent provided";
138
-
139
- // Validate modules are available
140
- if (!createGateway && !IntentStore) {
141
- return {
142
- content: [{
143
- type: "text",
144
- text: `⚠️ Intent Firewall modules not available. Change allowed but not tracked.`
145
- }]
146
- };
147
- }
148
-
149
- // Validate file path is within project root
150
- const fileAbs = path.resolve(projectRoot, filePath);
151
- if (!fileAbs.startsWith(projectRoot + path.sep) && fileAbs !== projectRoot) {
152
- return {
153
- content: [{
154
- type: "text",
155
- text: `❌ BLOCKED: File path outside project root: ${filePath}`
156
- }],
157
- isError: true
158
- };
159
- }
160
-
161
- try {
162
- // Create enforcement gateway
163
- const gateway = createGateway ? createGateway(projectRoot) : null;
164
-
165
- // Build raw change for gateway
166
- const rawChange = {
167
- type: oldContent ? "file_write" : "file_create",
168
- path: filePath,
169
- content,
170
- diff: oldContent ? {
171
- before: oldContent,
172
- after: content,
173
- } : null,
174
- };
175
-
176
- // Use gateway if available
177
- if (gateway) {
178
- const verdict = await gateway.intercept(rawChange, {
179
- agentId,
180
- interceptionPoint: "mcp_tool",
181
- toolName: "vibecheck_intent_firewall_intercept",
182
- });
183
-
184
- // Handle OBSERVE mode (WOULD_PASS/WOULD_BLOCK)
185
- if (verdict.decision === "WOULD_PASS" || verdict.decision === "WOULD_BLOCK") {
186
- const wouldBlock = verdict.decision === "WOULD_BLOCK";
187
-
188
- return {
189
- content: [{
190
- type: "text",
191
- text: `📋 OBSERVE MODE - Change ${wouldBlock ? "would be blocked" : "logged"}
192
-
193
- File: ${filePath}
194
- Agent: ${agentId}
195
- ✓ Logged to session for later review
196
- ${wouldBlock ? `\n⚠️ Would block: ${verdict.summary}` : ""}
197
-
198
- ═══════════════════════════════════════════════════════════════
199
- No intent declared - running in OBSERVE mode.
200
- Changes are allowed but logged for review.
201
-
202
- After your vibe session, run:
203
- vibecheck approve
204
-
205
- Or declare intent now for enforcement:
206
- vibecheck i "${agentIntent || "your intent"}"
207
- ═══════════════════════════════════════════════════════════════
208
-
209
- 💡 TIP: Quick intent declaration:
210
- vibecheck i "fix login bug"
211
-
212
- This auto-infers constraints from your git context.`
213
- }]
214
- };
215
- }
216
-
217
- // Handle BLOCK
218
- if (verdict.decision === "BLOCK") {
219
- // Format violations with fix guidance
220
- const violationLines = verdict.violations.map(v => {
221
- let line = `❌ [${v.code}] ${v.message}`;
222
- if (v.evidence?.file) line += `\n File: ${v.evidence.file}:${v.evidence.line || ''}`;
223
- if (v.evidence?.snippet) line += `\n Snippet: ${v.evidence.snippet.substring(0, 60)}...`;
224
- if (v.fix_hint) line += `\n Fix: ${v.fix_hint}`;
225
- return line;
226
- }).join("\n\n");
227
-
228
- // Format fix guidance
229
- const fixCommands = (verdict.fix_guidance || [])
230
- .filter(f => f.command)
231
- .map(f => ` ${f.command}`)
232
- .join("\n");
233
-
234
- return {
235
- content: [{
236
- type: "text",
237
- text: `═══════════════════════════════════════════════════════════════════════════════
238
- BLOCKED BY AGENT FIREWALL
239
- ═══════════════════════════════════════════════════════════════════════════════
240
-
241
- ${violationLines}
242
-
243
- ═══════════════════════════════════════════════════════════════════════════════
244
- Verdict: ${verdict.decision}
245
- Violations: ${verdict.violations.length}
246
- Intent Hash: ${verdict.intent_hash?.slice(0, 16) || "NONE"}...
247
- Verdict Hash: ${verdict.verdict_hash?.slice(0, 16)}...
248
-
249
- To proceed:
250
- ${fixCommands || " Review and fix the violations above"}
251
- ═══════════════════════════════════════════════════════════════════════════════`
252
- }],
253
- isError: true
254
- };
255
- }
256
-
257
- // Handle PASS
258
- const intentStore = new IntentStore(projectRoot);
259
- const userIntent = intentStore.getCurrent({ allowMissing: true });
260
-
261
- return {
262
- content: [{
263
- type: "text",
264
- text: `✅ ALLOWED BY AGENT FIREWALL
265
-
266
- Verdict: ${verdict.decision}
267
- File: ${filePath}
268
-
269
- Intent Aligned:
270
- "${userIntent?.summary || "No intent"}"
271
-
272
- ═══════════════════════════════════════════════════════════════════════════════
273
- Intent Hash: ${verdict.intent_hash?.slice(0, 16) || "NONE"}...
274
- Verdict Hash: ${verdict.verdict_hash?.slice(0, 16)}...
275
- Proofs: ${verdict.proofs?.length || 0} verified
276
- ═══════════════════════════════════════════════════════════════════════════════
277
-
278
- Change may proceed.`
279
- }]
280
- };
281
- }
282
-
283
- // Fallback to legacy orchestrator if gateway not available
284
- const intentStore = new IntentStore(projectRoot);
285
- const userIntent = intentStore.getCurrent({ allowMissing: true });
286
- const hasUserIntent = intentStore.hasIntent();
287
- const isBlockingIntent = userIntent?.summary?.includes("NO INTENT DECLARED");
288
-
289
- // OBSERVE mode fallback
290
- if (!hasUserIntent || isBlockingIntent) {
291
- if (SessionCollector) {
292
- try {
293
- const collector = new SessionCollector(projectRoot);
294
- collector.record({
295
- type: oldContent ? "file_modify" : "file_create",
296
- path: filePath,
297
- agent_id: agentId,
298
- });
299
- } catch {}
300
- }
301
-
302
- return {
303
- content: [{
304
- type: "text",
305
- text: `📋 OBSERVE MODE - Change logged
306
-
307
- File: ${filePath}
308
- Agent: ${agentId}
309
-
310
- ═══════════════════════════════════════════════════════════════
311
- No intent declared. Run: vibecheck approve after session.
312
- ═══════════════════════════════════════════════════════════════`
313
- }]
314
- };
315
- }
316
-
317
- // Legacy alignment check
318
- const changeEvent = {
319
- type: oldContent ? "file_write" : "file_create",
320
- location: filePath,
321
- diff: oldContent ? { before: oldContent, after: content } : null,
322
- content,
323
- domain: classifyDomain(filePath),
324
- claims: [],
325
- timestamp: new Date().toISOString(),
326
- };
327
-
328
- const alignmentResult = checkAlignment(userIntent, changeEvent);
329
-
330
- if (!alignmentResult.aligned) {
331
- const violations = alignmentResult.violations.map(v =>
332
- `- [${v.code}] ${v.message}\n Resource: ${v.resource}`
333
- ).join("\n\n");
334
-
335
- return {
336
- content: [{
337
- type: "text",
338
- text: `❌ BLOCKED BY AGENT FIREWALL
339
-
340
- ${violations}
341
-
342
- Intent: "${userIntent.summary}"
343
- Intent Hash: ${userIntent.hash?.slice(0, 16)}...`
344
- }],
345
- isError: true
346
- };
347
- }
348
-
349
- return {
350
- content: [{
351
- type: "text",
352
- text: `✅ ALLOWED - Intent aligned: "${userIntent.summary}"`
353
- }]
354
- };
355
-
356
- } catch (error) {
357
- return {
358
- content: [{
359
- type: "text",
360
- text: `❌ BLOCKED: Enforcement error: ${error.message}\n\n${error.stack}`
361
- }],
362
- isError: true
363
- };
364
- }
365
- }
366
-
367
- /**
368
- * Classify file domain
369
- * @param {string} filePath - File path
370
- * @returns {string} Domain
371
- */
372
- function classifyDomain(filePath) {
373
- if (!filePath) return "general";
374
- const s = filePath.toLowerCase();
375
- if (s.includes("auth")) return "auth";
376
- if (s.includes("stripe") || s.includes("payment")) return "payments";
377
- if (s.includes("routes") || s.includes("router") || s.includes("api")) return "routes";
378
- if (s.includes("schema") || s.includes("contract")) return "contracts";
379
- if (s.includes("ui") || s.includes("components") || s.includes("pages")) return "ui";
380
- if (s.includes("database") || s.includes("prisma") || s.includes("migration")) return "database";
381
- return "general";
382
- }
383
-
384
- /**
385
- * MCP Tool for getting current intent status
386
- */
387
- const INTENT_STATUS_TOOL = {
388
- name: "vibecheck_intent_status",
389
- description: `📋 Get current firewall status and pending changes.
390
-
391
- Shows:
392
- - Current mode (OBSERVE/ENFORCE)
393
- - Intent status (if declared)
394
- - Pending session changes (if in OBSERVE mode)
395
-
396
- Returns: { mode, hasIntent, pendingChanges, summary }`,
397
- inputSchema: {
398
- type: "object",
399
- properties: {
400
- projectRoot: {
401
- type: "string",
402
- default: ".",
403
- description: "Project root directory"
404
- }
405
- }
406
- }
407
- };
408
-
409
- /**
410
- * Handle intent status tool call
411
- */
412
- async function handleIntentStatus(name, args) {
413
- const projectRoot = path.resolve(args.projectRoot || ".");
414
-
415
- if (!IntentStore) {
416
- return {
417
- content: [{
418
- type: "text",
419
- text: `⚠️ Intent system not available`
420
- }]
421
- };
422
- }
423
-
424
- try {
425
- const intentStore = new IntentStore(projectRoot);
426
- const intent = intentStore.getCurrent({ allowMissing: true });
427
- const hasIntent = intentStore.hasIntent();
428
- const isBlocking = intent?.summary?.includes("NO INTENT DECLARED");
429
-
430
- // Get session info if available
431
- let sessionInfo = null;
432
- if (SessionCollector) {
433
- try {
434
- const collector = new SessionCollector(projectRoot);
435
- if (collector.hasPending()) {
436
- sessionInfo = collector.getSummary();
437
- }
438
- } catch {
439
- // Ignore session errors
440
- }
441
- }
442
-
443
- if (!hasIntent || isBlocking) {
444
- // OBSERVE MODE - show session info
445
- let response = `📋 OBSERVE MODE (no intent declared)\n\n`;
446
- response += `Changes are allowed and logged for later review.\n\n`;
447
-
448
- if (sessionInfo) {
449
- response += `═══════════════════════════════════════════════════════════════\n`;
450
- response += `SESSION CHANGES\n`;
451
- response += ` Files touched: ${sessionInfo.files_touched}\n`;
452
- response += ` Total changes: ${sessionInfo.total_changes}\n`;
453
- response += ` Duration: ${sessionInfo.duration_minutes} minutes\n`;
454
- response += ` Domains: ${sessionInfo.domains.join(", ") || "(none)"}\n`;
455
- response += `═══════════════════════════════════════════════════════════════\n\n`;
456
- response += `When done, run: vibecheck approve\n`;
457
- } else {
458
- response += `No changes logged yet in this session.\n`;
459
- }
460
-
461
- response += `\n💡 Quick intent: vibecheck i "your intent"\n`;
462
-
463
- return {
464
- content: [{
465
- type: "text",
466
- text: response
467
- }]
468
- };
469
- }
470
-
471
- // ENFORCE MODE - show intent
472
- let response = `✅ ENFORCE MODE (intent active)\n\n`;
473
- response += `Summary: ${intent.summary}\n\n`;
474
-
475
- if (intent.constraints && intent.constraints.length > 0) {
476
- response += `Constraints:\n`;
477
- for (const c of intent.constraints) {
478
- response += ` - ${c}\n`;
479
- }
480
- response += "\n";
481
- }
482
-
483
- if (intent.allowed_changes && intent.allowed_changes.length > 0) {
484
- response += `Allowed Changes:\n`;
485
- for (const ac of intent.allowed_changes) {
486
- response += ` - [${ac.type}] ${ac.target || ac.pattern}\n`;
487
- }
488
- response += "\n";
489
- }
490
-
491
- if (intent.scope) {
492
- response += `Scope:\n`;
493
- if (intent.scope.directories) {
494
- response += ` Directories: ${intent.scope.directories.join(", ")}\n`;
495
- }
496
- if (intent.scope.domains) {
497
- response += ` Domains: ${intent.scope.domains.join(", ")}\n`;
498
- }
499
- response += "\n";
500
- }
501
-
502
- response += `Hash: ${intent.hash?.slice(0, 16)}...\n`;
503
- response += `Version: ${intent.version || 1}\n`;
504
- response += `Created: ${intent.created_at}`;
505
-
506
- return {
507
- content: [{
508
- type: "text",
509
- text: response
510
- }]
511
- };
512
-
513
- } catch (error) {
514
- return {
515
- content: [{
516
- type: "text",
517
- text: `❌ Error: ${error.message}`
518
- }],
519
- isError: true
520
- };
521
- }
522
- }
523
-
524
- export {
525
- INTENT_FIREWALL_TOOL,
526
- handleIntentFirewallIntercept,
527
- INTENT_STATUS_TOOL,
528
- handleIntentStatus
529
- };
@@ -1,13 +0,0 @@
1
- /**
2
- * API Client - MCP Server Re-export
3
- *
4
- * This module re-exports from the canonical bin/runners/lib/api-client.js
5
- * DO NOT add implementation here.
6
- *
7
- * @see ../../../bin/runners/lib/api-client.js for the canonical implementation
8
- */
9
-
10
- "use strict";
11
-
12
- // Re-export everything from the canonical api-client
13
- module.exports = require('../../bin/runners/lib/api-client.js');