@withgauge/cli 0.2.0 → 0.4.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 (3) hide show
  1. package/README.md +11 -2
  2. package/dist/index.js +1373 -352
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -141,10 +141,10 @@ var batterySpecSchema = z2.object({
141
141
  prompts: z2.array(batteryPromptSpecSchema).min(1)
142
142
  });
143
143
  var batteryPlanScheduleSchema = z2.object({
144
- action: z2.enum(["create", "update"]),
144
+ action: z2.enum(["create", "update", "none"]),
145
145
  repoUrl: z2.string().nullable(),
146
146
  repoRef: z2.string().nullable(),
147
- /** Runs this schedule would enqueue (agents × samples; 0 unless `expand`). */
147
+ /** Runs this target would enqueue (agents × samples; 0 unless `expand`). */
148
148
  runs: z2.number().int()
149
149
  });
150
150
  var batteryPlanPromptSchema = z2.object({
@@ -342,6 +342,54 @@ var listBrandsQuerySchema = listQuerySchema.extend({
342
342
  });
343
343
  var brandListResponseSchema = listResponseSchema(brandSchema);
344
344
 
345
+ // ../packages/api-schemas/src/device.ts
346
+ import { z as z5 } from "zod";
347
+ var deviceAuthorizeRequestSchema = z5.object({
348
+ /** Device label (the CLI's hostname) for display + token naming. */
349
+ deviceName: z5.string().trim().max(64).optional(),
350
+ /** Optional: email a magic-link that lands on the approval page pre-scoped
351
+ * to this device (best-effort — the printed URL always works regardless). */
352
+ email: z5.string().trim().email().max(320).optional()
353
+ });
354
+ var deviceAuthorizeResponseSchema = z5.object({
355
+ /** The one-time secret the CLI polls with (never shown again). */
356
+ deviceCode: z5.string(),
357
+ /** Short human-typed code the user confirms in the browser (e.g. WXYZ-1234). */
358
+ userCode: z5.string(),
359
+ /** Where the user approves (e.g. https://…/cli/authorize). */
360
+ verificationUri: z5.string(),
361
+ /** verificationUri with the code pre-filled, for one-click / QR. */
362
+ verificationUriComplete: z5.string(),
363
+ /** Minimum seconds between polls. */
364
+ interval: z5.number().int().positive(),
365
+ /** Seconds until the device code expires. */
366
+ expiresIn: z5.number().int().positive(),
367
+ /** Whether a magic-link email was dispatched (best-effort). */
368
+ emailSent: z5.boolean()
369
+ });
370
+ var deviceTokenRequestSchema = z5.object({
371
+ deviceCode: z5.string().min(1)
372
+ });
373
+ var deviceTokenApprovedSchema = z5.object({
374
+ status: z5.literal("approved"),
375
+ /** The `gauge_…` bearer secret. Store it now — never returned again. */
376
+ accessToken: z5.string(),
377
+ tokenType: z5.literal("bearer"),
378
+ /** ISO-8601 expiry, or null for no expiry. */
379
+ expiresAt: z5.string().nullable()
380
+ });
381
+ var deviceTokenResultSchema = z5.discriminatedUnion("status", [
382
+ // Not yet approved — keep polling at `interval`.
383
+ z5.object({ status: z5.literal("pending") }),
384
+ // Polled faster than `interval` — back off by `interval` seconds.
385
+ z5.object({ status: z5.literal("slow_down"), interval: z5.number().int() }),
386
+ // The user explicitly denied the request. Stop.
387
+ z5.object({ status: z5.literal("denied") }),
388
+ // The device code expired or is unknown/already-redeemed. Stop and restart.
389
+ z5.object({ status: z5.literal("expired") }),
390
+ deviceTokenApprovedSchema
391
+ ]);
392
+
345
393
  // ../packages/api-schemas/src/keys.ts
346
394
  var keys_exports = {};
347
395
  __export(keys_exports, {
@@ -352,54 +400,69 @@ __export(keys_exports, {
352
400
  setProviderKeyBodySchema: () => setProviderKeyBodySchema,
353
401
  setProviderKeyResponseSchema: () => setProviderKeyResponseSchema
354
402
  });
355
- import { z as z5 } from "zod";
403
+ import { z as z6 } from "zod";
356
404
  var PROVIDER_TYPES = ["anthropic", "openai"];
357
- var providerTypeSchema = z5.enum(PROVIDER_TYPES);
358
- var setProviderKeyBodySchema = z5.object({
405
+ var providerTypeSchema = z6.enum(PROVIDER_TYPES);
406
+ var setProviderKeyBodySchema = z6.object({
359
407
  /** The raw provider API key. Verified + stored server-side (AWS Secrets
360
408
  * Manager); never persisted in the app DB and never echoed back. */
361
- key: z5.string().min(1)
409
+ key: z6.string().min(1)
362
410
  });
363
- var setProviderKeyResponseSchema = z5.object({
411
+ var setProviderKeyResponseSchema = z6.object({
364
412
  providerType: providerTypeSchema,
365
- last4: z5.string()
413
+ last4: z6.string()
366
414
  });
367
- var providerKeySchema = z5.object({
415
+ var providerKeySchema = z6.object({
368
416
  providerType: providerTypeSchema,
369
- last4: z5.string(),
370
- createdAt: z5.string(),
417
+ last4: z6.string(),
418
+ createdAt: z6.string(),
371
419
  /** When the key was last saved/rotated. */
372
- updatedAt: z5.string()
420
+ updatedAt: z6.string()
373
421
  });
374
422
  var providerKeyListResponseSchema = listResponseSchema(providerKeySchema);
375
423
 
376
424
  // ../packages/api-schemas/src/me.ts
377
- import { z as z6 } from "zod";
378
- var meUserSchema = z6.object({
379
- id: z6.string(),
380
- email: z6.string().nullable(),
381
- isSuperuser: z6.boolean()
425
+ import { z as z7 } from "zod";
426
+ var meUserSchema = z7.object({
427
+ id: z7.string(),
428
+ email: z7.string().nullable(),
429
+ isSuperuser: z7.boolean()
382
430
  });
383
- var meOrgSchema = z6.object({
384
- slug: z6.string(),
431
+ var meOrgSchema = z7.object({
432
+ slug: z7.string(),
385
433
  // Gauge's immutable Organization.public_id; null for LOCAL orgs.
386
- publicId: z6.string().nullable(),
387
- name: z6.string()
434
+ publicId: z7.string().nullable(),
435
+ name: z7.string()
388
436
  });
389
- var meResponseSchema = z6.object({
437
+ var meResponseSchema = z7.object({
390
438
  user: meUserSchema,
391
439
  // Membership-scoped for normal users; superusers see every org (mirrors the
392
440
  // web tier's userOrgs).
393
- orgs: z6.array(meOrgSchema)
441
+ orgs: z7.array(meOrgSchema)
442
+ });
443
+
444
+ // ../packages/api-schemas/src/orgs.ts
445
+ import { z as z8 } from "zod";
446
+ var createOrgRequestSchema = z8.object({
447
+ /** Workspace display name; the slug is derived server-side. */
448
+ name: z8.string().trim().min(1).max(200),
449
+ /** Optional company site (logo source; stamped onto the org). */
450
+ website: z8.string().trim().max(300).optional()
451
+ });
452
+ var createOrgResponseSchema = z8.object({
453
+ slug: z8.string(),
454
+ name: z8.string(),
455
+ // LOCAL orgs never have a Gauge publicId.
456
+ publicId: z8.string().nullable()
394
457
  });
395
458
 
396
459
  // ../packages/api-schemas/src/prompts.ts
397
- import { z as z10 } from "zod";
460
+ import { z as z13 } from "zod";
398
461
 
399
462
  // ../packages/api-schemas/src/schedules.ts
400
- import { z as z7 } from "zod";
463
+ import { z as z9 } from "zod";
401
464
  var AGENTS = ["CLAUDE_CODE", "CODEX_CLI", "CURSOR"];
402
- var agentSchema = z7.enum(AGENTS);
465
+ var agentSchema = z9.enum(AGENTS);
403
466
  var CADENCES = [
404
467
  "NONE",
405
468
  "DAILY",
@@ -407,184 +470,455 @@ var CADENCES = [
407
470
  "MONTHLY",
408
471
  "DAYS_PER_WEEK"
409
472
  ];
410
- var cadenceSchema = z7.enum(CADENCES);
411
- var daysPerWeekSchema = z7.number().int().min(1).max(7);
412
- var scheduleSchema = z7.object({
413
- id: z7.string(),
414
- promptId: z7.string(),
415
- /** Base repo to run against; null = the default scaffold. */
416
- repoUrl: z7.string().nullable(),
473
+ var cadenceSchema = z9.enum(CADENCES);
474
+ var daysPerWeekSchema = z9.number().int().min(1).max(7);
475
+ var scheduleRepoSchema = z9.object({
476
+ repoUrl: z9.string(),
417
477
  /** Branch/ref; null = the repo's default branch. */
418
- repoRef: z7.string().nullable(),
478
+ repoRef: z9.string().nullable()
479
+ });
480
+ var scheduleSchema = z9.object({
481
+ id: z9.string(),
482
+ name: z9.string(),
419
483
  cadence: cadenceSchema,
420
484
  /** Only set when cadence is DAYS_PER_WEEK (1–7). */
421
- daysPerWeek: z7.number().int().nullable(),
422
- samplesPerCycle: z7.number().int(),
423
- agents: z7.array(agentSchema),
485
+ daysPerWeek: z9.number().int().nullable(),
486
+ samplesPerCycle: z9.number().int(),
487
+ agents: z9.array(agentSchema),
424
488
  /** Pinned model id; null = the agent's default. */
425
- model: z7.string().nullable(),
426
- /** Cohort label for experiment analysis; null for ad-hoc schedules. */
427
- experiment: z7.string().nullable(),
428
- createdAt: z7.string(),
429
- updatedAt: z7.string()
489
+ model: z9.string().nullable(),
490
+ /** Repo targets in stable expansion order; empty = the default scaffold. */
491
+ repos: z9.array(scheduleRepoSchema),
492
+ /** Cohort label for experiment analysis; null outside labeled experiments. */
493
+ experiment: z9.string().nullable(),
494
+ enabled: z9.boolean(),
495
+ lastExpandedAt: z9.string().nullable(),
496
+ /** Member prompt ids, in stable expansion order. */
497
+ promptIds: z9.array(z9.string()),
498
+ promptCount: z9.number().int(),
499
+ createdAt: z9.string(),
500
+ updatedAt: z9.string()
430
501
  });
431
502
  var scheduleListResponseSchema = listResponseSchema(scheduleSchema);
432
- var createScheduleBodySchema = z7.object({
433
- repoUrl: z7.string().min(1).nullish(),
434
- repoRef: z7.string().min(1).nullish(),
503
+ var scheduleRepoInputSchema = z9.object({
504
+ repoUrl: z9.string().min(1),
505
+ repoRef: z9.string().min(1).nullish()
506
+ });
507
+ var createScheduleBodySchema = z9.object({
508
+ name: z9.string().min(1, "name is required"),
435
509
  cadence: cadenceSchema.default("NONE"),
436
510
  daysPerWeek: daysPerWeekSchema.optional(),
437
- agents: z7.array(agentSchema).min(1, "Select at least one agent")
438
- });
439
- var updateScheduleBodySchema = z7.object({
440
- repoUrl: z7.string().min(1).nullish(),
441
- repoRef: z7.string().min(1).nullish(),
511
+ samplesPerCycle: z9.number().int().min(1).default(1),
512
+ agents: z9.array(agentSchema).min(1, "Select at least one agent"),
513
+ model: z9.string().min(1).nullish(),
514
+ /** Repo targets; empty = the default scaffold (greenfield). */
515
+ repos: z9.array(scheduleRepoInputSchema).default([]),
516
+ /** Member prompt ids (resolved by the caller — tag→prompt resolution is a
517
+ * UI-side authoring convenience, never stored). */
518
+ promptIds: z9.array(z9.string().min(1)).default([]),
519
+ enabled: z9.boolean().default(true)
520
+ });
521
+ var updateScheduleBodySchema = z9.object({
522
+ name: z9.string().min(1).optional(),
442
523
  cadence: cadenceSchema.optional(),
443
524
  daysPerWeek: daysPerWeekSchema.optional(),
444
- agents: z7.array(agentSchema).min(1, "Select at least one agent").optional()
525
+ samplesPerCycle: z9.number().int().min(1).optional(),
526
+ agents: z9.array(agentSchema).min(1, "Select at least one agent").optional(),
527
+ model: z9.string().min(1).nullish(),
528
+ repos: z9.array(scheduleRepoInputSchema).optional(),
529
+ promptIds: z9.array(z9.string().min(1)).optional(),
530
+ enabled: z9.boolean().optional()
531
+ });
532
+ var runScheduleResponseSchema = z9.object({
533
+ batchIds: z9.array(z9.string()),
534
+ runIds: z9.array(z9.string()),
535
+ blocked: z9.enum(["insufficient_credits", "needs_provider_key"]).optional(),
536
+ notReady: z9.array(
537
+ z9.object({
538
+ repoUrl: z9.string(),
539
+ status: z9.enum(["building", "failed", "none"])
540
+ })
541
+ ).optional()
445
542
  });
446
543
 
447
544
  // ../packages/api-schemas/src/tags.ts
448
- import { z as z8 } from "zod";
449
- var tagSchema = z8.object({
450
- id: z8.string(),
451
- name: z8.string(),
545
+ import { z as z10 } from "zod";
546
+ var tagSchema = z10.object({
547
+ id: z10.string(),
548
+ name: z10.string(),
452
549
  /** A Mantine palette name (e.g. "blue", "grape"); unknown values are
453
550
  * normalized server-side to the default ("gray"). */
454
- color: z8.string()
551
+ color: z10.string()
455
552
  });
456
- var createTagBodySchema = z8.object({
457
- name: z8.string().min(1),
458
- color: z8.string().optional()
553
+ var createTagBodySchema = z10.object({
554
+ name: z10.string().min(1),
555
+ color: z10.string().optional()
459
556
  });
460
- var updateTagBodySchema = z8.object({
461
- name: z8.string().min(1).optional(),
462
- color: z8.string().optional()
557
+ var updateTagBodySchema = z10.object({
558
+ name: z10.string().min(1).optional(),
559
+ color: z10.string().optional()
463
560
  });
464
561
  var tagListResponseSchema = listResponseSchema(tagSchema);
465
562
 
466
563
  // ../packages/api-schemas/src/topics.ts
467
- import { z as z9 } from "zod";
468
- var topicSchema = z9.object({
469
- id: z9.string(),
470
- name: z9.string()
564
+ import { z as z11 } from "zod";
565
+ var topicSchema = z11.object({
566
+ id: z11.string(),
567
+ name: z11.string()
471
568
  });
472
- var createTopicBodySchema = z9.object({
473
- name: z9.string().min(1, "name is required")
569
+ var createTopicBodySchema = z11.object({
570
+ name: z11.string().min(1, "name is required")
474
571
  });
475
572
  var topicListResponseSchema = listResponseSchema(topicSchema);
476
573
 
574
+ // ../packages/api-schemas/src/web-fixtures.ts
575
+ var web_fixtures_exports = {};
576
+ __export(web_fixtures_exports, {
577
+ MAX_WEB_FIXTURE_BYTES: () => MAX_WEB_FIXTURE_BYTES,
578
+ webFixtureSchema: () => webFixtureSchema
579
+ });
580
+ import { z as z12 } from "zod";
581
+ var MAX_WEB_FIXTURE_BYTES = 1e6;
582
+ function withoutFragment(raw) {
583
+ const fragment = raw.indexOf("#");
584
+ return fragment === -1 ? raw : raw.slice(0, fragment);
585
+ }
586
+ var searchResultSchema = z12.object({
587
+ title: z12.string().min(1),
588
+ url: z12.url().transform(withoutFragment),
589
+ snippet: z12.string()
590
+ });
591
+ var searchFixtureSchema = z12.object({
592
+ query: z12.string().trim().min(1),
593
+ results: z12.array(searchResultSchema)
594
+ });
595
+ var pageFixtureSchema = z12.object({
596
+ url: z12.url().transform(withoutFragment),
597
+ status: z12.int().min(100).max(599).default(200),
598
+ contentType: z12.string().trim().min(1).default("text/html"),
599
+ body: z12.string()
600
+ });
601
+ var webFixtureSchema = z12.object({
602
+ version: z12.literal(1),
603
+ searches: z12.array(searchFixtureSchema).default([]),
604
+ pages: z12.array(pageFixtureSchema).default([])
605
+ }).superRefine((fixture, ctx) => {
606
+ const queries = /* @__PURE__ */ new Set();
607
+ fixture.searches.forEach((entry, index) => {
608
+ if (queries.has(entry.query)) {
609
+ ctx.addIssue({
610
+ code: "custom",
611
+ path: ["searches", index, "query"],
612
+ message: `duplicate normalized query: ${entry.query}`
613
+ });
614
+ }
615
+ queries.add(entry.query);
616
+ });
617
+ const urls = /* @__PURE__ */ new Set();
618
+ fixture.pages.forEach((entry, index) => {
619
+ if (urls.has(entry.url)) {
620
+ ctx.addIssue({
621
+ code: "custom",
622
+ path: ["pages", index, "url"],
623
+ message: `duplicate normalized URL: ${entry.url}`
624
+ });
625
+ }
626
+ urls.add(entry.url);
627
+ });
628
+ const bytes = new TextEncoder().encode(JSON.stringify(fixture)).byteLength;
629
+ if (bytes > MAX_WEB_FIXTURE_BYTES) {
630
+ ctx.addIssue({
631
+ code: "custom",
632
+ message: `serialized fixture is ${bytes} bytes; maximum is ${MAX_WEB_FIXTURE_BYTES}`
633
+ });
634
+ }
635
+ });
636
+
477
637
  // ../packages/api-schemas/src/prompts.ts
478
638
  var SCENARIOS = ["GREENFIELD", "MIGRATION"];
479
- var scenarioSchema = z10.enum(SCENARIOS);
480
- var promptSummarySchema = z10.object({
481
- id: z10.string(),
482
- text: z10.string(),
639
+ var scenarioSchema = z13.enum(SCENARIOS);
640
+ var promptSummarySchema = z13.object({
641
+ id: z13.string(),
642
+ text: z13.string(),
483
643
  scenario: scenarioSchema,
484
- isBranded: z10.boolean(),
644
+ isBranded: z13.boolean(),
485
645
  /** Battery-spec identity (idempotent applies); null for UI/CLI-created prompts. */
486
- externalKey: z10.string().nullable(),
646
+ externalKey: z13.string().nullable(),
487
647
  topic: topicSchema.nullable(),
488
- tags: z10.array(tagSchema),
489
- scheduleCount: z10.number().int(),
490
- createdAt: z10.string()
648
+ tags: z13.array(tagSchema),
649
+ scheduleCount: z13.number().int(),
650
+ createdAt: z13.string()
651
+ });
652
+ var promptScheduleRefSchema = z13.object({
653
+ id: z13.string(),
654
+ name: z13.string(),
655
+ cadence: cadenceSchema,
656
+ daysPerWeek: z13.number().int().nullable(),
657
+ enabled: z13.boolean()
491
658
  });
492
659
  var promptDetailSchema = promptSummarySchema.extend({
493
- schedules: z10.array(scheduleSchema)
660
+ schedules: z13.array(promptScheduleRefSchema)
494
661
  });
495
662
  var promptListResponseSchema = listResponseSchema(promptSummarySchema);
496
663
  var listPromptsQuerySchema = listQuerySchema.extend({
497
- topic: z10.string().min(1).optional(),
498
- tag: z10.string().min(1).optional(),
499
- q: z10.string().min(1).optional()
664
+ topic: z13.string().min(1).optional(),
665
+ tag: z13.string().min(1).optional(),
666
+ q: z13.string().min(1).optional()
500
667
  });
501
- var createPromptBodySchema = z10.object({
502
- text: z10.string().min(1, "text is required"),
668
+ var createPromptBodySchema = z13.object({
669
+ text: z13.string().min(1, "text is required"),
503
670
  scenario: scenarioSchema.default("GREENFIELD"),
504
- isBranded: z10.boolean().default(false),
505
- topic: z10.string().min(1).optional(),
506
- tags: z10.array(z10.string().min(1)).default([]),
507
- schedules: z10.array(createScheduleBodySchema).default([])
508
- });
509
- var createPromptResponseSchema = promptDetailSchema.extend({
510
- firstRunBlocked: z10.enum(["insufficient_credits", "needs_provider_key"]).optional()
511
- });
512
- var updatePromptBodySchema = z10.object({
513
- text: z10.string().min(1).optional(),
514
- isBranded: z10.boolean().optional(),
515
- topicId: z10.string().min(1).nullish(),
516
- tags: z10.array(z10.string().min(1)).optional()
517
- });
518
- var runPromptBodySchema = z10.object({
519
- agents: z10.array(agentSchema).min(1).optional(),
520
- scheduleIds: z10.array(z10.string().min(1)).min(1).optional()
521
- });
522
- var runPromptResponseSchema = z10.object({
523
- batchIds: z10.array(z10.string()),
524
- runIds: z10.array(z10.string()),
525
- /** Present when SOME schedules hit a billing gate but at least one run was
526
- * enqueued (mirrors the battery apply response; an all-blocked run is a
527
- * 402 error instead). */
528
- blocked: z10.enum(["insufficient_credits", "needs_provider_key"]).optional()
671
+ isBranded: z13.boolean().default(false),
672
+ topic: z13.string().min(1).optional(),
673
+ tags: z13.array(z13.string().min(1)).default([])
674
+ });
675
+ var updatePromptBodySchema = z13.object({
676
+ text: z13.string().min(1).optional(),
677
+ isBranded: z13.boolean().optional(),
678
+ topicId: z13.string().min(1).nullish(),
679
+ tags: z13.array(z13.string().min(1)).optional()
680
+ });
681
+ var runPromptBodySchema = z13.object({
682
+ agents: z13.array(agentSchema).min(1, "Select at least one agent").default(["CLAUDE_CODE", "CODEX_CLI"]),
683
+ repoUrl: z13.string().min(1).nullish(),
684
+ repoRef: z13.string().min(1).nullish(),
685
+ samplesPerCycle: z13.number().int().min(1).max(10).default(1),
686
+ webFixture: webFixtureSchema.optional()
687
+ });
688
+ var runPromptResponseSchema = z13.object({
689
+ batchIds: z13.array(z13.string()),
690
+ runIds: z13.array(z13.string())
691
+ });
692
+
693
+ // ../packages/api-schemas/src/query.ts
694
+ import { z as z15 } from "zod";
695
+
696
+ // ../packages/api-schemas/src/stats.ts
697
+ import { z as z14 } from "zod";
698
+ var BRAND_KINDS2 = ["OWNED", "COMPETITOR", "OTHER"];
699
+ var brandKindSchema2 = z14.enum(BRAND_KINDS2);
700
+ var brandRankingSchema = z14.object({
701
+ rank: z14.number().int(),
702
+ brandId: z14.string(),
703
+ brandName: z14.string(),
704
+ kind: brandKindSchema2,
705
+ installs: z14.number().int(),
706
+ installRate: z14.number(),
707
+ mentionRate: z14.number(),
708
+ /** Movement between the two most recent batch windows; null if not ranked in both. */
709
+ deltaRank: z14.number().int().nullable()
710
+ });
711
+ var packageRateSchema = z14.object({
712
+ ecosystem: z14.string(),
713
+ name: z14.string(),
714
+ brandName: z14.string().optional(),
715
+ kind: brandKindSchema2.optional(),
716
+ installs: z14.number().int(),
717
+ rate: z14.number()
718
+ });
719
+ var brandRateSchema = z14.object({
720
+ brandId: z14.string(),
721
+ brandName: z14.string(),
722
+ kind: brandKindSchema2,
723
+ installs: z14.number().int(),
724
+ rate: z14.number()
725
+ });
726
+ var brandFunnelRowSchema = z14.object({
727
+ brandId: z14.string(),
728
+ brandName: z14.string(),
729
+ kind: brandKindSchema2,
730
+ mentionRate: z14.number(),
731
+ installRate: z14.number()
732
+ });
733
+ var domainRateSchema = z14.object({
734
+ domain: z14.string(),
735
+ runs: z14.number().int(),
736
+ rate: z14.number(),
737
+ requests: z14.number().int(),
738
+ brandName: z14.string().optional(),
739
+ owned: z14.boolean().optional()
740
+ });
741
+ var statsFreshnessSchema = z14.object({
742
+ /** Newest run-ingest time across the org (ISO), or null if nothing ingested. */
743
+ watermark: z14.string().nullable(),
744
+ /** Runs that succeeded recently but haven't landed in the warehouse yet. */
745
+ pending: z14.number().int(),
746
+ /** False when the freshness read itself failed (distinguish from genuine zero). */
747
+ available: z14.boolean()
748
+ });
749
+ var statsResponseSchema = (item) => z14.object({ items: z14.array(item), freshness: statsFreshnessSchema });
750
+ var rankingsResponseSchema = statsResponseSchema(brandRankingSchema);
751
+ var installsResponseSchema = statsResponseSchema(packageRateSchema);
752
+ var brandsResponseSchema = statsResponseSchema(brandRateSchema);
753
+ var funnelResponseSchema = statsResponseSchema(brandFunnelRowSchema);
754
+ var domainsResponseSchema = statsResponseSchema(domainRateSchema);
755
+
756
+ // ../packages/api-schemas/src/query.ts
757
+ var DATASETS = [
758
+ "runs",
759
+ "installs",
760
+ "mentions",
761
+ "web",
762
+ "network",
763
+ "files",
764
+ "tokens"
765
+ ];
766
+ var datasetSchema = z15.enum(DATASETS);
767
+ var WHERE_OPS = [
768
+ "eq",
769
+ "neq",
770
+ "in",
771
+ "notIn",
772
+ "contains",
773
+ "gt",
774
+ "gte",
775
+ "lt",
776
+ "lte"
777
+ ];
778
+ var whereOpSchema = z15.enum(WHERE_OPS);
779
+ var GRANULARITIES = ["day", "week", "month"];
780
+ var granularitySchema = z15.enum(GRANULARITIES);
781
+ var DEFAULT_QUERY_LIMIT = 50;
782
+ var MAX_QUERY_LIMIT = 1e3;
783
+ var scalar = z15.union([z15.string(), z15.number(), z15.boolean()]);
784
+ var whereClauseSchema = z15.object({
785
+ dimension: z15.string().min(1),
786
+ op: whereOpSchema,
787
+ value: z15.union([scalar, z15.array(scalar)])
788
+ });
789
+ var queryFiltersSchema = z15.object({
790
+ prompt: z15.string(),
791
+ topic: z15.array(z15.string()),
792
+ tag: z15.array(z15.string()),
793
+ repo: z15.array(z15.string()),
794
+ language: z15.array(z15.string()),
795
+ framework: z15.array(z15.string()),
796
+ size: z15.array(z15.string()),
797
+ agent: z15.array(z15.string()),
798
+ model: z15.array(z15.string()),
799
+ scenario: z15.array(z15.string()),
800
+ experiment: z15.array(z15.string()),
801
+ branded: z15.boolean()
802
+ }).partial();
803
+ var dateRangeSchema = z15.object({
804
+ since: z15.string(),
805
+ until: z15.string(),
806
+ lastDays: z15.number().int().positive()
807
+ }).partial();
808
+ var orderBySchema = z15.object({
809
+ /** A selected dimension or metric name. */
810
+ key: z15.string().min(1),
811
+ dir: z15.enum(["asc", "desc"]).default("desc")
812
+ });
813
+ var querySpecSchema = z15.object({
814
+ dataset: datasetSchema.default("runs"),
815
+ dimensions: z15.array(z15.string()).default([]),
816
+ metrics: z15.array(z15.string()).min(1, "at least one metric is required"),
817
+ filters: queryFiltersSchema.default({}),
818
+ where: z15.array(whereClauseSchema).default([]),
819
+ dateRange: dateRangeSchema.optional(),
820
+ orderBy: z15.array(orderBySchema).default([]),
821
+ limit: z15.number().int().min(1).max(MAX_QUERY_LIMIT).default(DEFAULT_QUERY_LIMIT),
822
+ granularity: granularitySchema.default("day"),
823
+ /** When true, the response echoes the compiled SQL (params bound, not inlined). */
824
+ explain: z15.boolean().default(false)
825
+ });
826
+ var columnKindSchema = z15.enum(["dimension", "metric"]);
827
+ var queryColumnSchema = z15.object({
828
+ key: z15.string(),
829
+ kind: columnKindSchema
830
+ });
831
+ var queryRowSchema = z15.record(
832
+ z15.string(),
833
+ z15.union([z15.string(), z15.number(), z15.boolean(), z15.null()])
834
+ );
835
+ var queryResponseSchema = z15.object({
836
+ columns: z15.array(queryColumnSchema),
837
+ rows: z15.array(queryRowSchema),
838
+ /** Present only when the request set explain=true. */
839
+ sql: z15.string().optional(),
840
+ freshness: statsFreshnessSchema
841
+ });
842
+ var fieldTypeSchema = z15.enum([
843
+ "string",
844
+ "number",
845
+ "rate",
846
+ "date",
847
+ "boolean"
848
+ ]);
849
+ var fieldSchema = z15.object({
850
+ name: z15.string(),
851
+ type: fieldTypeSchema,
852
+ /** One-line human/agent hint. */
853
+ description: z15.string().optional()
854
+ });
855
+ var datasetMetaSchema = z15.object({
856
+ name: datasetSchema,
857
+ grain: z15.string(),
858
+ dimensions: z15.array(fieldSchema),
859
+ metrics: z15.array(fieldSchema)
860
+ });
861
+ var metadataResponseSchema = z15.object({
862
+ datasets: z15.array(datasetMetaSchema)
529
863
  });
530
864
 
531
865
  // ../packages/api-schemas/src/repos.ts
532
- import { z as z11 } from "zod";
866
+ import { z as z16 } from "zod";
533
867
  var REPO_SIZE_BUCKETS = [
534
868
  "small",
535
869
  "medium",
536
870
  "large",
537
871
  "xlarge"
538
872
  ];
539
- var repoSizeBucketSchema = z11.enum(REPO_SIZE_BUCKETS);
540
- var repoSchema = z11.object({
541
- url: z11.string(),
542
- name: z11.string(),
543
- isSystem: z11.boolean(),
544
- languages: z11.array(z11.string()),
545
- frameworks: z11.array(z11.string()),
873
+ var repoSizeBucketSchema = z16.enum(REPO_SIZE_BUCKETS);
874
+ var repoSchema = z16.object({
875
+ url: z16.string(),
876
+ name: z16.string(),
877
+ isSystem: z16.boolean(),
878
+ languages: z16.array(z16.string()),
879
+ frameworks: z16.array(z16.string()),
546
880
  /** Faceted labels (complexity:L2, buildable:yes, stack:nextjs, …). */
547
- tags: z11.array(z11.string()),
548
- primaryLanguage: z11.string(),
549
- sizeKb: z11.number(),
881
+ tags: z16.array(z16.string()),
882
+ primaryLanguage: z16.string(),
883
+ sizeKb: z16.number(),
550
884
  sizeBucket: repoSizeBucketSchema.nullable(),
551
- stars: z11.number()
885
+ stars: z16.number()
552
886
  });
553
887
  var repoListResponseSchema = listResponseSchema(repoSchema);
554
- var addRepoBodySchema = z11.object({
555
- url: z11.string().min(1, "url is required"),
888
+ var addRepoBodySchema = z16.object({
889
+ url: z16.string().min(1, "url is required"),
556
890
  /**
557
891
  * Reserved (accepted, not yet persisted): the catalog keys repos by URL only
558
892
  * — `fact_repo` has no ref column and metadata sync always reads the default
559
893
  * branch. Kept in the wire format so `gauge repos add --ref` is stable once
560
894
  * the catalog learns refs.
561
895
  */
562
- ref: z11.string().min(1).optional(),
896
+ ref: z16.string().min(1).optional(),
563
897
  /** Display name; defaults to the `owner/repo` label of the URL. */
564
- name: z11.string().min(1).optional(),
898
+ name: z16.string().min(1).optional(),
565
899
  /** Manual override; defaults to frameworks detected from the repo's manifests. */
566
- frameworks: z11.array(z11.string()).optional(),
567
- tags: z11.array(z11.string()).optional()
900
+ frameworks: z16.array(z16.string()).optional(),
901
+ tags: z16.array(z16.string()).optional()
568
902
  });
569
- var updateRepoBodySchema = z11.object({
570
- url: z11.string().min(1, "url is required"),
571
- name: z11.string().min(1).optional(),
572
- frameworks: z11.array(z11.string()).optional(),
573
- tags: z11.array(z11.string()).optional()
903
+ var updateRepoBodySchema = z16.object({
904
+ url: z16.string().min(1, "url is required"),
905
+ name: z16.string().min(1).optional(),
906
+ frameworks: z16.array(z16.string()).optional(),
907
+ tags: z16.array(z16.string()).optional()
574
908
  });
575
- var resyncRepoBodySchema = z11.object({
576
- url: z11.string().min(1, "url is required")
909
+ var resyncRepoBodySchema = z16.object({
910
+ url: z16.string().min(1, "url is required")
577
911
  });
578
- var deleteRepoQuerySchema = z11.object({
579
- url: z11.string().min(1, "url is required")
912
+ var deleteRepoQuerySchema = z16.object({
913
+ url: z16.string().min(1, "url is required")
580
914
  });
581
- var repoSyncResultSchema = z11.object({
915
+ var repoSyncResultSchema = z16.object({
582
916
  repo: repoSchema,
583
- synced: z11.boolean()
917
+ synced: z16.boolean()
584
918
  });
585
919
 
586
920
  // ../packages/api-schemas/src/runs.ts
587
- import { z as z12 } from "zod";
921
+ import { z as z17 } from "zod";
588
922
  var RUN_STATUSES = [
589
923
  "QUEUED",
590
924
  "CLAIMED",
@@ -595,152 +929,143 @@ var RUN_STATUSES = [
595
929
  "TIMED_OUT",
596
930
  "CANCELED"
597
931
  ];
598
- var runStatusSchema = z12.enum(RUN_STATUSES);
932
+ var runStatusSchema = z17.enum(RUN_STATUSES);
599
933
  var AGENTS2 = ["CLAUDE_CODE", "CODEX_CLI", "CURSOR"];
600
- var agentSchema2 = z12.enum(AGENTS2);
601
- var runStatusFilterSchema = z12.string().transform(
934
+ var agentSchema2 = z17.enum(AGENTS2);
935
+ var runStatusFilterSchema = z17.string().transform(
602
936
  (raw) => raw.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean)
603
- ).pipe(z12.array(runStatusSchema).min(1));
937
+ ).pipe(z17.array(runStatusSchema).min(1));
604
938
  var runListQuerySchema = listQuerySchema.extend({
605
939
  status: runStatusFilterSchema.optional(),
606
- batch: z12.string().optional(),
607
- prompt: z12.string().optional(),
608
- experiment: z12.string().optional(),
609
- since: z12.string().optional()
940
+ batch: z17.string().optional(),
941
+ prompt: z17.string().optional(),
942
+ experiment: z17.string().optional(),
943
+ since: z17.string().optional()
610
944
  });
611
- var runListItemSchema = z12.object({
612
- id: z12.string(),
945
+ var runListItemSchema = z17.object({
946
+ id: z17.string(),
613
947
  status: runStatusSchema,
614
948
  agent: agentSchema2,
615
- model: z12.string(),
616
- promptId: z12.string(),
949
+ model: z17.string(),
950
+ promptId: z17.string(),
617
951
  /** First ~80 chars of the batch's prompt snapshot, whitespace-collapsed. */
618
- promptSnippet: z12.string(),
619
- batchId: z12.string(),
620
- experiment: z12.string().nullable(),
621
- turns: z12.number().int().nullable(),
622
- usdCost: z12.number().nullable(),
623
- durationMs: z12.number().int().nullable(),
624
- exitReason: z12.string().nullable(),
625
- createdAt: z12.string(),
626
- startedAt: z12.string().nullable(),
627
- finishedAt: z12.string().nullable()
952
+ promptSnippet: z17.string(),
953
+ batchId: z17.string(),
954
+ experiment: z17.string().nullable(),
955
+ turns: z17.number().int().nullable(),
956
+ usdCost: z17.number().nullable(),
957
+ durationMs: z17.number().int().nullable(),
958
+ exitReason: z17.string().nullable(),
959
+ createdAt: z17.string(),
960
+ startedAt: z17.string().nullable(),
961
+ finishedAt: z17.string().nullable()
628
962
  });
629
963
  var runListResponseSchema = listResponseSchema(runListItemSchema);
630
964
  var runDetailSchema = runListItemSchema.omit({ promptSnippet: true }).extend({
631
- promptText: z12.string(),
632
- attempt: z12.number().int(),
633
- cancelRequested: z12.boolean(),
634
- failureReason: z12.string().nullable(),
635
- repoUrl: z12.string().nullable(),
636
- repoRef: z12.string().nullable(),
637
- scenario: z12.string(),
638
- funding: z12.string(),
965
+ promptText: z17.string(),
966
+ attempt: z17.number().int(),
967
+ cancelRequested: z17.boolean(),
968
+ failureReason: z17.string().nullable(),
969
+ repoUrl: z17.string().nullable(),
970
+ repoRef: z17.string().nullable(),
971
+ scenario: z17.string(),
972
+ funding: z17.string(),
639
973
  /** Raw harness usage write-back (token counts etc.); shape may evolve. */
640
- usage: z12.unknown().nullable(),
974
+ usage: z17.unknown().nullable(),
641
975
  /** Artifact pointer: a working-tree diff exists at GET /runs/{id}/diff. */
642
- hasDiff: z12.boolean(),
643
- claimedAt: z12.string().nullable()
976
+ hasDiff: z17.boolean(),
977
+ claimedAt: z17.string().nullable()
644
978
  });
645
- var cancelRunResponseSchema = z12.object({
646
- id: z12.string(),
979
+ var cancelRunResponseSchema = z17.object({
980
+ id: z17.string(),
647
981
  status: runStatusSchema,
648
- cancelRequested: z12.boolean(),
649
- note: z12.string().optional()
650
- });
651
- var runEventSchema = z12.looseObject({
652
- run_id: z12.string(),
653
- seq: z12.number(),
654
- turn: z12.number(),
655
- ts: z12.string(),
656
- type: z12.string()
982
+ cancelRequested: z17.boolean(),
983
+ note: z17.string().optional()
984
+ });
985
+ var forkRunBodySchema = z17.object({
986
+ prompt: z17.string().trim().min(1).max(2e4),
987
+ turn: z17.number().int().min(0).optional()
988
+ });
989
+ var forkRunResponseSchema = z17.object({
990
+ runId: z17.string(),
991
+ batchId: z17.string(),
992
+ parentRunId: z17.string(),
993
+ checkpointId: z17.string(),
994
+ turn: z17.number().int().min(0)
995
+ });
996
+ var RUN_INSIGHT_STATUSES = [
997
+ "PENDING",
998
+ "RUNNING",
999
+ "COMPLETE",
1000
+ "FAILED",
1001
+ "SKIPPED"
1002
+ ];
1003
+ var runInsightStatusSchema = z17.enum(RUN_INSIGHT_STATUSES);
1004
+ var insightPassSchema = z17.object({
1005
+ status: runInsightStatusSchema,
1006
+ model: z17.string().nullable(),
1007
+ inputTokens: z17.number().int().nullable(),
1008
+ outputTokens: z17.number().int().nullable(),
1009
+ usdCost: z17.number().nullable(),
1010
+ error: z17.string().nullable()
1011
+ });
1012
+ var runDecisionSchema = z17.object({
1013
+ index: z17.number().int(),
1014
+ category: z17.string(),
1015
+ categoryRaw: z17.string().nullable(),
1016
+ chosenName: z17.string(),
1017
+ chosenEcosystem: z17.string().nullable(),
1018
+ chosenPackage: z17.string().nullable(),
1019
+ reversed: z17.boolean(),
1020
+ detail: z17.unknown()
1021
+ });
1022
+ var runImplementationSchema = z17.object({
1023
+ brandName: z17.string(),
1024
+ ecosystem: z17.string().nullable(),
1025
+ package: z17.string().nullable(),
1026
+ verdict: z17.string(),
1027
+ docConsulted: z17.boolean(),
1028
+ detail: z17.unknown()
1029
+ });
1030
+ var runInsightResponseSchema = z17.object({
1031
+ runId: z17.string(),
1032
+ decision: insightPassSchema,
1033
+ implementation: insightPassSchema,
1034
+ decisions: z17.array(runDecisionSchema),
1035
+ implementations: z17.array(runImplementationSchema)
1036
+ });
1037
+ var runEventSchema = z17.looseObject({
1038
+ run_id: z17.string(),
1039
+ seq: z17.number(),
1040
+ turn: z17.number(),
1041
+ ts: z17.string(),
1042
+ type: z17.string()
657
1043
  });
658
1044
 
659
- // ../packages/api-schemas/src/stats.ts
660
- import { z as z13 } from "zod";
661
- var BRAND_KINDS2 = ["OWNED", "COMPETITOR", "OTHER"];
662
- var brandKindSchema2 = z13.enum(BRAND_KINDS2);
663
- var brandRankingSchema = z13.object({
664
- rank: z13.number().int(),
665
- brandId: z13.string(),
666
- brandName: z13.string(),
667
- kind: brandKindSchema2,
668
- installs: z13.number().int(),
669
- installRate: z13.number(),
670
- mentionRate: z13.number(),
671
- /** Movement between the two most recent batch windows; null if not ranked in both. */
672
- deltaRank: z13.number().int().nullable()
673
- });
674
- var packageRateSchema = z13.object({
675
- ecosystem: z13.string(),
676
- name: z13.string(),
677
- brandName: z13.string().optional(),
678
- kind: brandKindSchema2.optional(),
679
- installs: z13.number().int(),
680
- rate: z13.number()
681
- });
682
- var brandRateSchema = z13.object({
683
- brandId: z13.string(),
684
- brandName: z13.string(),
685
- kind: brandKindSchema2,
686
- installs: z13.number().int(),
687
- rate: z13.number()
688
- });
689
- var brandFunnelRowSchema = z13.object({
690
- brandId: z13.string(),
691
- brandName: z13.string(),
692
- kind: brandKindSchema2,
693
- mentionRate: z13.number(),
694
- installRate: z13.number()
695
- });
696
- var domainRateSchema = z13.object({
697
- domain: z13.string(),
698
- runs: z13.number().int(),
699
- rate: z13.number(),
700
- requests: z13.number().int(),
701
- deniedRequests: z13.number().int(),
702
- brandName: z13.string().optional(),
703
- owned: z13.boolean().optional()
704
- });
705
- var statsFreshnessSchema = z13.object({
706
- /** Newest run-ingest time across the org (ISO), or null if nothing ingested. */
707
- watermark: z13.string().nullable(),
708
- /** Runs that succeeded recently but haven't landed in the warehouse yet. */
709
- pending: z13.number().int(),
710
- /** False when the freshness read itself failed (distinguish from genuine zero). */
711
- available: z13.boolean()
712
- });
713
- var statsResponseSchema = (item) => z13.object({ items: z13.array(item), freshness: statsFreshnessSchema });
714
- var rankingsResponseSchema = statsResponseSchema(brandRankingSchema);
715
- var installsResponseSchema = statsResponseSchema(packageRateSchema);
716
- var brandsResponseSchema = statsResponseSchema(brandRateSchema);
717
- var funnelResponseSchema = statsResponseSchema(brandFunnelRowSchema);
718
- var domainsResponseSchema = statsResponseSchema(domainRateSchema);
719
-
720
1045
  // ../packages/api-schemas/src/tokens.ts
721
- import { z as z14 } from "zod";
722
- var apiTokenSchema = z14.object({
723
- id: z14.string(),
724
- name: z14.string(),
1046
+ import { z as z18 } from "zod";
1047
+ var apiTokenSchema = z18.object({
1048
+ id: z18.string(),
1049
+ name: z18.string(),
725
1050
  /** Last 4 chars of the plaintext, for recognizability (non-secret). */
726
- last4: z14.string(),
727
- expiresAt: z14.iso.datetime().nullable(),
728
- lastUsedAt: z14.iso.datetime().nullable(),
729
- createdAt: z14.iso.datetime(),
730
- revokedAt: z14.iso.datetime().nullable()
731
- });
732
- var createTokenRequestSchema = z14.object({
733
- name: z14.string().min(1).max(100),
1051
+ last4: z18.string(),
1052
+ expiresAt: z18.iso.datetime().nullable(),
1053
+ lastUsedAt: z18.iso.datetime().nullable(),
1054
+ createdAt: z18.iso.datetime(),
1055
+ revokedAt: z18.iso.datetime().nullable()
1056
+ });
1057
+ var createTokenRequestSchema = z18.object({
1058
+ name: z18.string().min(1).max(100),
734
1059
  /** ISO-8601 datetime; omit for no expiry. */
735
- expiresAt: z14.iso.datetime({ offset: true }).optional()
1060
+ expiresAt: z18.iso.datetime({ offset: true }).optional()
736
1061
  });
737
1062
  var createTokenResponseSchema = apiTokenSchema.extend({
738
- token: z14.string()
1063
+ token: z18.string()
739
1064
  });
740
1065
  var listTokensResponseSchema = listResponseSchema(apiTokenSchema);
741
1066
 
742
1067
  // src/commands/apply.ts
743
- import { z as z15 } from "zod";
1068
+ import { z as z19 } from "zod";
744
1069
 
745
1070
  // src/version.ts
746
1071
  import { createRequire } from "module";
@@ -1082,7 +1407,16 @@ var EXAMPLE_SPEC = {
1082
1407
  key: "migrate-to-vitest",
1083
1408
  text: "Migrate the test suite from Jest to Vitest.",
1084
1409
  scenario: "MIGRATION",
1085
- schedules: [{ repoUrl: "https://github.com/acme/api", repoRef: "main" }]
1410
+ schedules: [
1411
+ {
1412
+ repoUrl: "https://github.com/acme/api",
1413
+ repoRef: "main",
1414
+ // Optional: pin a specific model id. Must be one the schedule's
1415
+ // agent(s) can actually serve, or the run falls back to the agent
1416
+ // default. Omit (or use null) to always use the agent default.
1417
+ model: "claude-opus-4-8"
1418
+ }
1419
+ ]
1086
1420
  }
1087
1421
  ]
1088
1422
  };
@@ -1181,7 +1515,7 @@ function register(program2) {
1181
1515
  ).option("-f, --file <path>", "battery spec JSON file").option("--dry-run", "print the plan without applying").option("--schema", "print the battery spec JSON Schema and exit").option("--example", "print a minimal example battery spec and exit").action(
1182
1516
  async (opts, command) => {
1183
1517
  if (opts.schema) {
1184
- printJson(z15.toJSONSchema(batteries_exports.batterySpecSchema));
1518
+ printJson(z19.toJSONSchema(batteries_exports.batterySpecSchema));
1185
1519
  return;
1186
1520
  }
1187
1521
  if (opts.example) {
@@ -1218,12 +1552,14 @@ function register(program2) {
1218
1552
  // src/commands/auth.ts
1219
1553
  var auth_exports = {};
1220
1554
  __export(auth_exports, {
1555
+ deviceLogin: () => deviceLogin,
1221
1556
  register: () => register2
1222
1557
  });
1223
1558
  import { spawn } from "child_process";
1224
1559
  import { randomBytes } from "crypto";
1225
1560
  import { createServer } from "http";
1226
1561
  import { hostname } from "os";
1562
+ import { setTimeout as sleep } from "timers/promises";
1227
1563
 
1228
1564
  // src/lib/paginate.ts
1229
1565
  async function fetchAllPages(client, path, query = {}) {
@@ -1380,6 +1716,125 @@ async function browserLogin() {
1380
1716
  server.closeAllConnections();
1381
1717
  }
1382
1718
  }
1719
+ var DEVICE_ENDPOINT = "/api/v1/device";
1720
+ async function devicePost(path, body) {
1721
+ const base = resolveBaseUrl().replace(/\/+$/, "");
1722
+ let res;
1723
+ try {
1724
+ res = await fetch(`${base}${path}`, {
1725
+ method: "POST",
1726
+ headers: {
1727
+ "Content-Type": "application/json",
1728
+ Accept: "application/json",
1729
+ "User-Agent": USER_AGENT
1730
+ },
1731
+ body: JSON.stringify(body)
1732
+ });
1733
+ } catch (e) {
1734
+ throw new CliError(
1735
+ "network",
1736
+ `Request to ${base} failed: ${e instanceof Error ? e.message : String(e)}`
1737
+ );
1738
+ }
1739
+ const text = await res.text();
1740
+ if (!res.ok) {
1741
+ try {
1742
+ const parsed = errorEnvelopeSchema.safeParse(JSON.parse(text));
1743
+ if (parsed.success) {
1744
+ throw new CliError(parsed.data.error.code, parsed.data.error.message);
1745
+ }
1746
+ } catch (e) {
1747
+ if (e instanceof CliError) throw e;
1748
+ }
1749
+ throw new CliError(
1750
+ "internal",
1751
+ `Device request failed: HTTP ${res.status} ${res.statusText}`.trim()
1752
+ );
1753
+ }
1754
+ return JSON.parse(text);
1755
+ }
1756
+ async function deviceLogin(opts) {
1757
+ const start = await devicePost(
1758
+ `${DEVICE_ENDPOINT}/authorize`,
1759
+ { deviceName: hostname() || "this device", email: opts.email }
1760
+ );
1761
+ console.log("To sign in, open this URL in a browser:\n");
1762
+ console.log(` ${start.verificationUriComplete}
1763
+ `);
1764
+ console.log(`and confirm this code: ${start.userCode}
1765
+ `);
1766
+ if (start.emailSent && opts.email) {
1767
+ console.log(`We also emailed a sign-in link to ${opts.email}.`);
1768
+ }
1769
+ console.log("Waiting for you to approve in the browser\u2026");
1770
+ openBrowser(start.verificationUriComplete);
1771
+ const deadline = Date.now() + start.expiresIn * 1e3;
1772
+ const MAX_TRANSIENT = 5;
1773
+ let interval = start.interval;
1774
+ let transient = 0;
1775
+ while (Date.now() < deadline) {
1776
+ await sleep(interval * 1e3);
1777
+ let raw;
1778
+ try {
1779
+ raw = await devicePost(`${DEVICE_ENDPOINT}/token`, {
1780
+ deviceCode: start.deviceCode
1781
+ });
1782
+ } catch (e) {
1783
+ if (e instanceof CliError && (e.code === "network" || e.code === "internal") && ++transient <= MAX_TRANSIENT) {
1784
+ continue;
1785
+ }
1786
+ throw e;
1787
+ }
1788
+ transient = 0;
1789
+ const parsed = deviceTokenResultSchema.safeParse(raw);
1790
+ if (!parsed.success) {
1791
+ throw new CliError(
1792
+ "internal",
1793
+ "Unexpected response from the device token endpoint."
1794
+ );
1795
+ }
1796
+ const result = parsed.data;
1797
+ switch (result.status) {
1798
+ case "pending":
1799
+ continue;
1800
+ case "slow_down":
1801
+ interval = result.interval;
1802
+ continue;
1803
+ case "denied":
1804
+ throw new CliError(
1805
+ "unauthorized",
1806
+ "Authorization was denied in the browser."
1807
+ );
1808
+ case "expired":
1809
+ throw new CliError(
1810
+ "unauthorized",
1811
+ "The sign-in request expired before it was approved. Re-run it to try again."
1812
+ );
1813
+ case "approved": {
1814
+ const token = result.accessToken;
1815
+ saveToken(token);
1816
+ try {
1817
+ const me = await fetchMe(new ApiClient({ token }));
1818
+ return { token, me };
1819
+ } catch (e) {
1820
+ throw new CliError(
1821
+ "network",
1822
+ `Signed in and token saved to ${credentialsPath()}, but couldn't load your profile (${e instanceof Error ? e.message : String(e)}). Run \`gauge whoami\` to retry.`
1823
+ );
1824
+ }
1825
+ }
1826
+ default:
1827
+ throw new CliError(
1828
+ "internal",
1829
+ `Unexpected device authorization status: ${result.status}`
1830
+ );
1831
+ }
1832
+ }
1833
+ throw new CliError(
1834
+ "network",
1835
+ "Timed out waiting for browser approval. Re-run to try again."
1836
+ );
1837
+ }
1383
1838
  async function readStdin() {
1384
1839
  let data = "";
1385
1840
  for await (const chunk of process.stdin) data += chunk;
@@ -1447,10 +1902,26 @@ async function whoami(output) {
1447
1902
  }
1448
1903
  function register2(program2) {
1449
1904
  const auth = program2.command("auth").description("Authenticate the CLI (personal access tokens)");
1450
- auth.command("login").description("Log in via the browser (localhost callback flow)").option("--with-token", "read a token from stdin (headless machines)").action(async (opts) => {
1451
- if (opts.withToken) await withTokenLogin();
1452
- else await browserLogin();
1453
- });
1905
+ auth.command("login").description("Log in via the browser (localhost callback flow)").option("--with-token", "read a token from stdin (headless machines)").option(
1906
+ "--device",
1907
+ "device-authorization flow: print a URL + code to approve elsewhere (no loopback listener; agent/remote-friendly)"
1908
+ ).option(
1909
+ "--email <email>",
1910
+ "with --device: also email a sign-in link to this address"
1911
+ ).action(
1912
+ async (opts) => {
1913
+ if (opts.device) {
1914
+ const { token, me } = await deviceLogin({ email: opts.email });
1915
+ saveToken(token);
1916
+ console.log(`Token saved to ${credentialsPath()}`);
1917
+ printIdentity(me);
1918
+ } else if (opts.withToken) {
1919
+ await withTokenLogin();
1920
+ } else {
1921
+ await browserLogin();
1922
+ }
1923
+ }
1924
+ );
1454
1925
  auth.command("logout").description("Remove the stored token").action(() => {
1455
1926
  clearToken();
1456
1927
  console.log(`Removed ${credentialsPath()}`);
@@ -1926,15 +2397,95 @@ function register7(program2) {
1926
2397
  });
1927
2398
  }
1928
2399
 
1929
- // src/commands/orgs.ts
1930
- var orgs_exports = {};
1931
- __export(orgs_exports, {
2400
+ // src/commands/onboard.ts
2401
+ var onboard_exports = {};
2402
+ __export(onboard_exports, {
1932
2403
  register: () => register8
1933
2404
  });
2405
+ function orgNameFromEmail(email) {
2406
+ const domain = email?.split("@")[1] ?? "";
2407
+ const base = domain.split(".")[0] ?? "";
2408
+ if (!base) return "My Workspace";
2409
+ return base.charAt(0).toUpperCase() + base.slice(1);
2410
+ }
2411
+ function register8(program2) {
2412
+ program2.command("onboard").description(
2413
+ "Self-serve onboarding: sign in (device flow) and create your first workspace"
2414
+ ).option("--email <email>", "email a sign-in link (device-flow convenience)").option("--org-name <name>", "workspace name (default: from your email)").option("--website <url>", "company site (logo source)").option("--new", "create a new workspace even if you already belong to one").action(
2415
+ async (opts, command) => {
2416
+ const output = resolveOutput(command);
2417
+ let client;
2418
+ let me;
2419
+ if (resolveToken()) {
2420
+ client = new ApiClient();
2421
+ me = await client.get("/api/v1/me");
2422
+ if (output !== "json") {
2423
+ console.log(`Already signed in as ${me.user.email ?? me.user.id}.`);
2424
+ }
2425
+ } else {
2426
+ const login = await deviceLogin({ email: opts.email });
2427
+ saveToken(login.token);
2428
+ me = login.me;
2429
+ client = new ApiClient({ token: login.token });
2430
+ if (output !== "json") {
2431
+ console.log(
2432
+ `
2433
+ Signed in as ${me.user.email ?? me.user.id} \u2014 token saved to ${credentialsPath()}.`
2434
+ );
2435
+ }
2436
+ }
2437
+ const wantNewOrg = opts.new === true || opts.orgName !== void 0 || me.orgs.length === 0;
2438
+ let orgSlug;
2439
+ let createdOrg = null;
2440
+ if (wantNewOrg) {
2441
+ const name = opts.orgName?.trim() || orgNameFromEmail(me.user.email);
2442
+ createdOrg = await client.post("/api/v1/orgs", {
2443
+ name,
2444
+ website: opts.website
2445
+ });
2446
+ orgSlug = createdOrg.slug;
2447
+ } else {
2448
+ orgSlug = readConfig().defaultOrg ?? me.orgs[0]?.slug ?? "";
2449
+ if (!orgSlug) {
2450
+ throw new CliError(
2451
+ "internal",
2452
+ "No workspace available; re-run with --org-name to create one."
2453
+ );
2454
+ }
2455
+ }
2456
+ updateConfig({ defaultOrg: orgSlug });
2457
+ if (output === "json") {
2458
+ printJson({
2459
+ user: me.user,
2460
+ org: createdOrg ?? { slug: orgSlug },
2461
+ defaultOrg: orgSlug
2462
+ });
2463
+ return;
2464
+ }
2465
+ console.log(
2466
+ createdOrg ? `
2467
+ Created workspace ${createdOrg.name} (${orgSlug}).` : `
2468
+ Using workspace ${orgSlug}.`
2469
+ );
2470
+ console.log(`Default org set to ${orgSlug}. You're ready:`);
2471
+ console.log(
2472
+ " gauge apply --example > battery.json # scaffold a run"
2473
+ );
2474
+ console.log(" gauge apply -f battery.json # launch it");
2475
+ console.log(" gauge runs list # watch results");
2476
+ }
2477
+ );
2478
+ }
2479
+
2480
+ // src/commands/orgs.ts
2481
+ var orgs_exports2 = {};
2482
+ __export(orgs_exports2, {
2483
+ register: () => register9
2484
+ });
1934
2485
  function isDefault(org, defaultOrg) {
1935
2486
  return defaultOrg !== void 0 && (org.slug === defaultOrg || org.publicId === defaultOrg);
1936
2487
  }
1937
- function register8(program2) {
2488
+ function register9(program2) {
1938
2489
  const orgs = program2.command("orgs").description("Organizations");
1939
2490
  orgs.command("list").description("List orgs you belong to").action(async (_opts, command) => {
1940
2491
  const output = resolveOutput(command);
@@ -1959,6 +2510,23 @@ function register8(program2) {
1959
2510
  "table"
1960
2511
  );
1961
2512
  });
2513
+ orgs.command("create <name>").description("Create a new LOCAL workspace and set it as the default org").option("--website <url>", "company site (used as the logo source)").option("--no-use", "don't set the new org as the default").action(
2514
+ async (name, opts, command) => {
2515
+ const created = await createClient().post(
2516
+ "/api/v1/orgs",
2517
+ { name, website: opts.website }
2518
+ );
2519
+ if (opts.use !== false) updateConfig({ defaultOrg: created.slug });
2520
+ if (resolveOutput(command) === "json") {
2521
+ printJson(created);
2522
+ return;
2523
+ }
2524
+ console.log(`Created workspace ${created.name} (${created.slug})`);
2525
+ if (opts.use !== false) {
2526
+ console.log(`Default org set to ${created.slug}`);
2527
+ }
2528
+ }
2529
+ );
1962
2530
  orgs.command("use <org>").description("Set the default org (slug or public id) in local config").action(async (org, _opts, command) => {
1963
2531
  const me = await createClient().get("/api/v1/me");
1964
2532
  const match = me.orgs.find((o) => o.slug === org || o.publicId === org);
@@ -1989,9 +2557,11 @@ function register8(program2) {
1989
2557
  var prompts_exports2 = {};
1990
2558
  __export(prompts_exports2, {
1991
2559
  parseAgents: () => parseAgents,
2560
+ parseSamples: () => parseSamples,
1992
2561
  promptsPath: () => promptsPath,
1993
2562
  readPromptText: () => readPromptText,
1994
- register: () => register9,
2563
+ readWebFixture: () => readWebFixture,
2564
+ register: () => register10,
1995
2565
  resolveOrCreateTopicId: () => resolveOrCreateTopicId
1996
2566
  });
1997
2567
  import { readFileSync as readFileSync4 } from "fs";
@@ -2036,6 +2606,38 @@ function readPromptText(opts) {
2036
2606
  if (!text) throw new CliError("usage", "prompt file is empty");
2037
2607
  return text;
2038
2608
  }
2609
+ function readWebFixture(path) {
2610
+ let raw;
2611
+ try {
2612
+ raw = readFileSync4(path, "utf8");
2613
+ } catch (error) {
2614
+ throw new CliError(
2615
+ "usage",
2616
+ "cannot read web fixture " + path + ": " + (error instanceof Error ? error.message : String(error))
2617
+ );
2618
+ }
2619
+ let parsed;
2620
+ try {
2621
+ parsed = JSON.parse(raw);
2622
+ } catch (error) {
2623
+ throw new CliError(
2624
+ "invalid_request",
2625
+ "web fixture is not valid JSON: " + (error instanceof Error ? error.message : String(error))
2626
+ );
2627
+ }
2628
+ const result = web_fixtures_exports.webFixtureSchema.safeParse(parsed);
2629
+ if (!result.success) {
2630
+ const details = result.error.issues.map(
2631
+ (issue) => ` ${issue.path.join(".") || "(fixture)"}: ${issue.message}`
2632
+ ).join("\n");
2633
+ throw new CliError(
2634
+ "invalid_request",
2635
+ `not a valid web fixture:
2636
+ ${details}`
2637
+ );
2638
+ }
2639
+ return result.data;
2640
+ }
2039
2641
  async function resolveOrCreateTopicId(client, org, name) {
2040
2642
  const path = `/api/v1/orgs/${encodeURIComponent(org)}/topics`;
2041
2643
  let cursor;
@@ -2070,15 +2672,17 @@ function toRow2(p) {
2070
2672
  scenario: p.scenario
2071
2673
  };
2072
2674
  }
2073
- var BLOCK_WARNINGS = {
2074
- insufficient_credits: "warning: prompt created, but the first run was blocked: out of credits",
2075
- needs_provider_key: "warning: prompt created, but the first run was blocked: no provider key for the selected agents"
2076
- };
2077
- var RUN_BLOCK_WARNINGS = {
2078
- insufficient_credits: "warning: some schedules were skipped or truncated: out of credits",
2079
- needs_provider_key: "warning: some schedules were skipped: no provider key for the selected agents"
2080
- };
2081
- function register9(program2) {
2675
+ var DEFAULT_RUN_AGENTS = ["CLAUDE_CODE", "CODEX_CLI"];
2676
+ function parseSamples(raw, max) {
2677
+ const n = Number(raw);
2678
+ if (!Number.isInteger(n) || n < 1 || max !== void 0 && n > max)
2679
+ throw new CliError(
2680
+ "usage",
2681
+ max === void 0 ? "--samples must be an integer >= 1" : `--samples must be an integer 1-${max}`
2682
+ );
2683
+ return n;
2684
+ }
2685
+ function register10(program2) {
2082
2686
  const group = program2.command("prompts").description("Manage prompts");
2083
2687
  group.command("list").description("List prompts").option("--topic <topic>", "filter by topic (id or name)").option("--tag <tag>", "filter by tag (id or name)").option("-q, --query <text>", "text search").action(
2084
2688
  async (opts, cmd) => {
@@ -2092,7 +2696,7 @@ function register9(program2) {
2092
2696
  else printItems(items.map(toRow2), "table");
2093
2697
  }
2094
2698
  );
2095
- group.command("get <id>").description("Show a prompt (schedules, topic, tags)").action(async (id, _opts, cmd) => {
2699
+ group.command("get <id>").description("Show a prompt (scheduled-via, topic, tags)").action(async (id, _opts, cmd) => {
2096
2700
  const org = resolveOrg(cmd);
2097
2701
  const prompt = await createClient().get(
2098
2702
  `${promptsPath(org)}/${encodeURIComponent(id)}`
@@ -2111,20 +2715,19 @@ function register9(program2) {
2111
2715
  console.log(`created: ${prompt.createdAt}`);
2112
2716
  console.log(`text: ${prompt.text}`);
2113
2717
  if (prompt.schedules.length) {
2114
- console.log("schedules:");
2718
+ console.log("scheduled via:");
2115
2719
  printItems(
2116
2720
  prompt.schedules.map((s) => ({
2117
2721
  id: s.id,
2118
- repo: s.repoUrl ?? "(default scaffold)",
2119
- ref: s.repoRef ?? "",
2722
+ name: s.name,
2120
2723
  cadence: s.cadence,
2121
2724
  days: s.daysPerWeek ?? "",
2122
- agents: s.agents.join(", ")
2725
+ enabled: s.enabled ? "yes" : "no"
2123
2726
  })),
2124
2727
  "table"
2125
2728
  );
2126
2729
  } else {
2127
- console.log("schedules: (none)");
2730
+ console.log("scheduled via: (none)");
2128
2731
  }
2129
2732
  });
2130
2733
  group.command("create").description("Create a prompt").option("--text <text>", "prompt text").option("--file <path>", 'read prompt text from a file ("-" for stdin)').option("--scenario <scenario>", "greenfield | migration", "greenfield").option("--branded", "mark as a branded prompt").option("--topic <name>", "topic (created if new)").option(
@@ -2156,11 +2759,9 @@ function register9(program2) {
2156
2759
  else {
2157
2760
  console.log(`Created prompt ${created.id}`);
2158
2761
  console.log(
2159
- `No schedules yet \u2014 add one with \`gauge schedules add --prompt ${created.id} --agent claude-code\``
2762
+ `Run it now with \`gauge prompts run ${created.id}\`, or add it to a schedule set with \`gauge schedules create --name <name> --prompt ${created.id} --agent claude-code\``
2160
2763
  );
2161
2764
  }
2162
- if (created.firstRunBlocked)
2163
- console.error(BLOCK_WARNINGS[created.firstRunBlocked]);
2164
2765
  }
2165
2766
  );
2166
2767
  group.command("edit <id>").description("Update a prompt").option("--text <text>", "new prompt text").option("--file <path>", 'read new text from a file ("-" for stdin)').option("--branded <bool>", "true | false").option("--topic <name>", "set the topic (created if new)").option("--clear-topic", "clear the topic").option(
@@ -2206,19 +2807,27 @@ function register9(program2) {
2206
2807
  );
2207
2808
  if (resolveOutput(cmd) !== "json") console.log(`Deleted prompt ${id}`);
2208
2809
  });
2209
- group.command("run <id>").description("Run a prompt now (ORG funding, credit-gated)").option(
2810
+ group.command("run <id>").description(
2811
+ "Run a prompt now \u2014 an ad-hoc agents x repo x samples spec (ORG funding, credit-gated)"
2812
+ ).option(
2210
2813
  "--agent <agents>",
2211
- "comma-separated agents, e.g. claude-code,codex"
2212
- ).option("--schedule <ids>", "comma-separated schedule ids").action(
2814
+ "comma-separated agents, e.g. claude-code,codex (default: claude-code,codex)"
2815
+ ).option("--repo <url>", "base repo to run against (default: the scaffold)").option("--ref <ref>", "branch, tag, or commit (with --repo)").option("--samples <n>", "samples per agent, 1-10 (default: 1)").option(
2816
+ "--web-fixture <path>",
2817
+ "web fixture JSON; pages are injected transparently into native WebFetch (misses pass through live)"
2818
+ ).action(
2213
2819
  async (id, opts, cmd) => {
2214
2820
  const org = resolveOrg(cmd);
2215
- const body = {};
2216
- if (opts.agent !== void 0) body.agents = parseAgents(opts.agent);
2217
- if (opts.schedule !== void 0) {
2218
- const ids = opts.schedule.split(",").map((s) => s.trim()).filter(Boolean);
2219
- if (ids.length === 0)
2220
- throw new CliError("usage", "no schedule ids given");
2221
- body.scheduleIds = ids;
2821
+ if (opts.ref !== void 0 && opts.repo === void 0)
2822
+ throw new CliError("usage", "--ref requires --repo");
2823
+ const body = {
2824
+ agents: opts.agent !== void 0 ? parseAgents(opts.agent) : DEFAULT_RUN_AGENTS,
2825
+ samplesPerCycle: opts.samples !== void 0 ? parseSamples(opts.samples, 10) : 1
2826
+ };
2827
+ if (opts.repo !== void 0) body.repoUrl = opts.repo;
2828
+ if (opts.ref !== void 0) body.repoRef = opts.ref;
2829
+ if (opts.webFixture !== void 0) {
2830
+ body.webFixture = readWebFixture(opts.webFixture);
2222
2831
  }
2223
2832
  const result = await createClient().post(
2224
2833
  `${promptsPath(org)}/${encodeURIComponent(id)}/run`,
@@ -2229,25 +2838,251 @@ function register9(program2) {
2229
2838
  return;
2230
2839
  }
2231
2840
  if (result.runIds.length === 0) {
2232
- console.log(
2233
- "No runs enqueued (the prompt has no matching schedules)"
2234
- );
2841
+ console.log("No runs enqueued");
2235
2842
  return;
2236
2843
  }
2237
2844
  console.log(
2238
2845
  `Enqueued ${result.runIds.length} run(s) in ${result.batchIds.length} batch(es)`
2239
2846
  );
2240
2847
  for (const runId of result.runIds) console.log(runId);
2241
- if (result.blocked) console.error(RUN_BLOCK_WARNINGS[result.blocked]);
2242
2848
  console.error("Tip: `gauge runs watch <id>` streams a run live");
2243
2849
  }
2244
2850
  );
2245
2851
  }
2246
2852
 
2853
+ // src/commands/query.ts
2854
+ var query_exports2 = {};
2855
+ __export(query_exports2, {
2856
+ register: () => register11
2857
+ });
2858
+ var collect3 = (value, prev = []) => [
2859
+ ...prev,
2860
+ value
2861
+ ];
2862
+ var csv = (raw) => raw.split(",").map((s) => s.trim()).filter(Boolean);
2863
+ function parseWhere(expr) {
2864
+ const inMatch = expr.match(/^\s*(\w+)\s+(in|contains)\s+(.*)$/i);
2865
+ if (inMatch) {
2866
+ const [, dimension2, opRaw, rest2] = inMatch;
2867
+ const op = opRaw.toLowerCase();
2868
+ if (op === "in") {
2869
+ return { dimension: dimension2, op: "in", value: csv(rest2) };
2870
+ }
2871
+ return { dimension: dimension2, op: "contains", value: rest2.trim() };
2872
+ }
2873
+ const opMatch = expr.match(/^\s*(\w+)\s*(!=|>=|<=|=|>|<)\s*(.*)$/);
2874
+ if (!opMatch) {
2875
+ throw new CliError(
2876
+ "usage",
2877
+ `Could not parse --where "${expr}". Use e.g. "action=install", "ecosystem in npm,pypi", or "name contains supa".`
2878
+ );
2879
+ }
2880
+ const [, dimension, sym, rest] = opMatch;
2881
+ const opFor = {
2882
+ "=": "eq",
2883
+ "!=": "neq",
2884
+ ">": "gt",
2885
+ ">=": "gte",
2886
+ "<": "lt",
2887
+ "<=": "lte"
2888
+ };
2889
+ return { dimension, op: opFor[sym], value: rest.trim() };
2890
+ }
2891
+ function parseOrderBy(raw) {
2892
+ const [key, dir] = raw.split(":");
2893
+ return { key: key.trim(), dir: dir?.trim() === "asc" ? "asc" : "desc" };
2894
+ }
2895
+ async function readStdin2() {
2896
+ const chunks = [];
2897
+ for await (const chunk of process.stdin) chunks.push(chunk);
2898
+ return Buffer.concat(chunks).toString("utf8");
2899
+ }
2900
+ async function buildSpec(opts) {
2901
+ let spec = { metrics: [] };
2902
+ if (opts.json) {
2903
+ const raw = opts.json === "-" ? await readStdin2() : opts.json;
2904
+ try {
2905
+ spec = JSON.parse(raw);
2906
+ } catch (e) {
2907
+ throw new CliError(
2908
+ "usage",
2909
+ `--json is not valid JSON: ${e.message}`
2910
+ );
2911
+ }
2912
+ }
2913
+ if (opts.dataset) spec.dataset = opts.dataset;
2914
+ if (opts.dimensions !== void 0) spec.dimensions = csv(opts.dimensions);
2915
+ if (opts.metrics !== void 0) spec.metrics = csv(opts.metrics);
2916
+ if (opts.where?.length) spec.where = opts.where.map(parseWhere);
2917
+ if (opts.orderBy?.length) spec.orderBy = opts.orderBy.map(parseOrderBy);
2918
+ if (opts.limit !== void 0) spec.limit = Number(opts.limit);
2919
+ if (opts.granularity)
2920
+ spec.granularity = opts.granularity;
2921
+ if (opts.explain) spec.explain = true;
2922
+ const date = {
2923
+ ...spec.dateRange ?? {}
2924
+ };
2925
+ if (opts.since) {
2926
+ date.since = opts.since;
2927
+ delete date.lastDays;
2928
+ } else if (opts.lastDays) {
2929
+ date.lastDays = Number(opts.lastDays);
2930
+ delete date.since;
2931
+ }
2932
+ if (opts.until) date.until = opts.until;
2933
+ if (Object.keys(date).length) spec.dateRange = date;
2934
+ if (opts.branded && opts.unbranded) {
2935
+ throw new CliError("usage", "Pass at most one of --branded / --unbranded.");
2936
+ }
2937
+ const filters = {
2938
+ ...spec.filters ?? {}
2939
+ };
2940
+ if (opts.prompt) filters.prompt = opts.prompt;
2941
+ if (opts.topic) filters.topic = csv(opts.topic);
2942
+ if (opts.tag) filters.tag = csv(opts.tag);
2943
+ if (opts.repo) filters.repo = csv(opts.repo);
2944
+ if (opts.language) filters.language = csv(opts.language);
2945
+ if (opts.framework) filters.framework = csv(opts.framework);
2946
+ if (opts.size) filters.size = csv(opts.size);
2947
+ if (opts.agent) filters.agent = csv(opts.agent);
2948
+ if (opts.model) filters.model = csv(opts.model);
2949
+ if (opts.scenario) filters.scenario = csv(opts.scenario);
2950
+ if (opts.experiment) filters.experiment = csv(opts.experiment);
2951
+ if (opts.branded) filters.branded = true;
2952
+ if (opts.unbranded) filters.branded = false;
2953
+ if (Object.keys(filters).length) spec.filters = filters;
2954
+ if (!spec.metrics || spec.metrics.length === 0) {
2955
+ throw new CliError(
2956
+ "usage",
2957
+ "At least one metric is required. Pass --metrics <a,b> (or a `metrics` array in --json). See `gauge query fields --dataset <name>`."
2958
+ );
2959
+ }
2960
+ return spec;
2961
+ }
2962
+ var pct = (n) => `${(n * 100).toFixed(1)}%`;
2963
+ function noteFreshness(f) {
2964
+ if (!f.available) {
2965
+ console.error(
2966
+ "warning: analytics store is temporarily unavailable; results may be incomplete."
2967
+ );
2968
+ } else if (f.pending > 0) {
2969
+ console.error(
2970
+ `note: ${f.pending} recent run(s) still ingesting; results may not reflect them yet.`
2971
+ );
2972
+ }
2973
+ }
2974
+ async function runQuery(command, opts) {
2975
+ const org = resolveOrg(command);
2976
+ const output = resolveOutput(command);
2977
+ const spec = await buildSpec(opts);
2978
+ const res = await createClient().post(
2979
+ `/api/v1/orgs/${encodeURIComponent(org)}/query`,
2980
+ spec
2981
+ );
2982
+ if (output === "json") {
2983
+ printJson(res);
2984
+ return;
2985
+ }
2986
+ if (res.sql) console.error(`
2987
+ ${res.sql}
2988
+ `);
2989
+ const rateKeys = new Set(
2990
+ res.columns.filter((c) => c.kind === "metric" && c.key.endsWith("_rate")).map((c) => c.key)
2991
+ );
2992
+ const rows = res.rows.map((row) => {
2993
+ const out = {};
2994
+ for (const col of res.columns) {
2995
+ const v = row[col.key];
2996
+ out[col.key] = rateKeys.has(col.key) && typeof v === "number" ? pct(v) : v;
2997
+ }
2998
+ return out;
2999
+ });
3000
+ printItems(
3001
+ rows,
3002
+ "table",
3003
+ res.columns.map((c) => ({ key: c.key }))
3004
+ );
3005
+ noteFreshness(res.freshness);
3006
+ }
3007
+ async function showMetadata(command, mode, dataset) {
3008
+ const org = resolveOrg(command);
3009
+ const output = resolveOutput(command);
3010
+ const meta = await createClient().get(
3011
+ `/api/v1/orgs/${encodeURIComponent(org)}/query/metadata`
3012
+ );
3013
+ if (mode === "datasets") {
3014
+ if (output === "json")
3015
+ return printJson(
3016
+ meta.datasets.map((d) => ({ name: d.name, grain: d.grain }))
3017
+ );
3018
+ printItems(
3019
+ meta.datasets.map((d) => ({ dataset: d.name, grain: d.grain })),
3020
+ "table"
3021
+ );
3022
+ return;
3023
+ }
3024
+ const ds = meta.datasets.find((d) => d.name === dataset);
3025
+ if (!ds) {
3026
+ throw new CliError(
3027
+ "usage",
3028
+ `Unknown dataset "${dataset}". Valid: ${meta.datasets.map((d) => d.name).join(", ")}.`
3029
+ );
3030
+ }
3031
+ if (output === "json") return printJson(ds);
3032
+ const rows = [
3033
+ ...ds.dimensions.map((f) => ({
3034
+ field: f.name,
3035
+ kind: "dimension",
3036
+ type: f.type,
3037
+ about: f.description ?? ""
3038
+ })),
3039
+ ...ds.metrics.map((f) => ({
3040
+ field: f.name,
3041
+ kind: "metric",
3042
+ type: f.type,
3043
+ about: f.description ?? ""
3044
+ }))
3045
+ ];
3046
+ console.error(`dataset: ${ds.name} \u2014 ${ds.grain}`);
3047
+ printItems(rows, "table");
3048
+ }
3049
+ function register11(program2) {
3050
+ const group = program2.command("query").description(
3051
+ "Flexible reports over your event warehouse (run a report, or discover the catalog)"
3052
+ );
3053
+ group.command("run", { isDefault: true }).description("Run a report (default command)").option(
3054
+ "--json <spec>",
3055
+ "full query spec as JSON (or '-' to read stdin); flags override its keys"
3056
+ ).option(
3057
+ "--dataset <name>",
3058
+ "runs | installs | mentions | web | network | files | tokens (default runs)"
3059
+ ).option("-d, --dimensions <names>", "comma-separated GROUP BY dimensions").option("-m, --metrics <names>", "comma-separated metrics (at least one)").option(
3060
+ "--where <expr>",
3061
+ 'predicate, e.g. "action=install" (repeatable)',
3062
+ collect3
3063
+ ).option("--since <val>", "date range start \u2014 ISO date or window (30d, 24h)").option("--until <val>", "date range end \u2014 ISO date or window").option("--last-days <n>", "shorthand for --since <n> days ago").option(
3064
+ "--order-by <key:dir>",
3065
+ "sort by a selected key, e.g. installs:desc (repeatable)",
3066
+ collect3
3067
+ ).option("--limit <n>", "max rows (default 50, max 1000)").option(
3068
+ "--granularity <g>",
3069
+ "date bucket: day | week | month (default day)"
3070
+ ).option("--explain", "print the compiled SQL to stderr").option("--prompt <id>", "filter to a single prompt").option("--topic <ids>", "comma-separated topic ids").option("--tag <ids>", "comma-separated tag ids").option("--repo <urls>", "comma-separated base repo urls").option("--language <langs>", "comma-separated repo languages").option("--framework <names>", "comma-separated repo frameworks").option("--size <buckets>", "comma-separated codebase-size buckets").option("--agent <names>", "comma-separated agent names").option("--model <models>", "comma-separated models").option(
3071
+ "--scenario <types>",
3072
+ "comma-separated scenario types (greenfield|migration)"
3073
+ ).option("--experiment <labels>", "comma-separated experiment labels").option("--branded", "only branded prompts").option("--unbranded", "only non-branded prompts").action((opts, command) => runQuery(command, opts));
3074
+ group.command("datasets").description("List the datasets you can query").action(
3075
+ (_opts, command) => showMetadata(command, "datasets")
3076
+ );
3077
+ group.command("fields").description("List the dimensions and metrics for a dataset").requiredOption("--dataset <name>", "dataset to describe").action(
3078
+ (opts, command) => showMetadata(command, "fields", opts.dataset)
3079
+ );
3080
+ }
3081
+
2247
3082
  // src/commands/repos.ts
2248
3083
  var repos_exports2 = {};
2249
3084
  __export(repos_exports2, {
2250
- register: () => register10
3085
+ register: () => register12
2251
3086
  });
2252
3087
  function reposPath(org) {
2253
3088
  return `/api/v1/orgs/${encodeURIComponent(org)}/repos`;
@@ -2270,7 +3105,7 @@ function toRow3(repo) {
2270
3105
  function syncWarning(repo) {
2271
3106
  return `warning: GitHub metadata sync failed; retry with \`gauge repos resync ${repo.url}\``;
2272
3107
  }
2273
- function register10(program2) {
3108
+ function register12(program2) {
2274
3109
  const repos = program2.command("repos").description("Manage repositories");
2275
3110
  repos.command("list").description("List repositories (yours + read-only Gauge-provided ones)").action(async (_opts, command) => {
2276
3111
  const org = resolveOrg(command);
@@ -2334,7 +3169,7 @@ function register10(program2) {
2334
3169
  // src/commands/runs.ts
2335
3170
  var runs_exports2 = {};
2336
3171
  __export(runs_exports2, {
2337
- register: () => register11
3172
+ register: () => register13
2338
3173
  });
2339
3174
  function runPath(id) {
2340
3175
  return `/api/v1/runs/${encodeURIComponent(id)}`;
@@ -2397,6 +3232,64 @@ function detailLines(run) {
2397
3232
  ["Finished", run.finishedAt ?? "\u2014"]
2398
3233
  ];
2399
3234
  }
3235
+ function passLine(label, pass) {
3236
+ const bits = [pass.status];
3237
+ if (pass.model) bits.push(pass.model);
3238
+ const cost = fmtUsd(pass.usdCost);
3239
+ if (cost) bits.push(cost);
3240
+ if (pass.error) bits.push(`error: ${compact(pass.error, 60)}`);
3241
+ return `${label.padEnd(20)} ${bits.join(" ")}`;
3242
+ }
3243
+ function influencesVia(detail) {
3244
+ const raw = detail?.influences;
3245
+ if (!Array.isArray(raw)) return "";
3246
+ const types = [];
3247
+ for (const inf of raw) {
3248
+ const type = inf?.type;
3249
+ if (typeof type === "string" && !types.includes(type)) types.push(type);
3250
+ }
3251
+ return types.join(", ");
3252
+ }
3253
+ function printInsight(insight) {
3254
+ console.log(passLine("Decision pass", insight.decision));
3255
+ console.log(passLine("Implementation pass", insight.implementation));
3256
+ console.log(`
3257
+ Decisions (${insight.decisions.length})`);
3258
+ if (insight.decisions.length === 0) {
3259
+ console.log(insight.decision.status === "SKIPPED" ? "(skipped)" : "(none)");
3260
+ } else {
3261
+ printItems(
3262
+ insight.decisions.map((d) => ({
3263
+ "#": d.index,
3264
+ arena: d.category === "other" && d.categoryRaw ? d.categoryRaw : d.category,
3265
+ chosen: d.chosenPackage ?? d.chosenName,
3266
+ reversed: d.reversed ? "yes" : "",
3267
+ via: influencesVia(d.detail)
3268
+ })),
3269
+ "table"
3270
+ );
3271
+ }
3272
+ console.log(`
3273
+ Implementation quality (${insight.implementations.length})`);
3274
+ if (insight.implementations.length === 0) {
3275
+ console.log(
3276
+ insight.implementation.status === "SKIPPED" ? "(skipped)" : "(none)"
3277
+ );
3278
+ } else {
3279
+ printItems(
3280
+ insight.implementations.map((it) => ({
3281
+ verdict: it.verdict,
3282
+ brand: it.brandName,
3283
+ package: it.package ?? "",
3284
+ docs: it.docConsulted ? "docs consulted" : ""
3285
+ })),
3286
+ "table"
3287
+ );
3288
+ }
3289
+ if (insight.decisions.length > 0 || insight.implementations.length > 0) {
3290
+ console.error("\n(full detail: rerun with -o json)");
3291
+ }
3292
+ }
2400
3293
  function parseEvent(data) {
2401
3294
  try {
2402
3295
  const parsed = runEventSchema.safeParse(JSON.parse(data));
@@ -2512,7 +3405,7 @@ async function streamRun(id, json, opts) {
2512
3405
  if (drainTimer) clearTimeout(drainTimer);
2513
3406
  }
2514
3407
  }
2515
- function register11(program2) {
3408
+ function register13(program2) {
2516
3409
  const runs = program2.command("runs").description("Inspect and manage runs");
2517
3410
  runs.command("list").description("List runs (newest first)").option("--status <status>", "filter by status, e.g. running,queued").option("--batch <id>", "filter by batch").option("--prompt <id>", "filter by prompt").option("--experiment <experiment>", "filter by experiment label").option("--since <window>", "e.g. 24h, 7d, or an ISO date").option("--limit <n>", "page size (1-200)", "50").option("--cursor <cursor>", "resume from a previous page's nextCursor").action(
2518
3411
  async (opts, command) => {
@@ -2554,6 +3447,18 @@ function register11(program2) {
2554
3447
  console.log(`${label.padEnd(width)} ${value}`);
2555
3448
  }
2556
3449
  });
3450
+ runs.command("insight <id>").description(
3451
+ "Show the run's LLM analysis (decisions + implementation quality)"
3452
+ ).action(async (id, _opts, command) => {
3453
+ const insight = await createClient().get(
3454
+ `${runPath(id)}/insight`
3455
+ );
3456
+ if (resolveOutput(command) === "json") {
3457
+ printJson(insight);
3458
+ return;
3459
+ }
3460
+ printInsight(insight);
3461
+ });
2557
3462
  runs.command("watch <id>").description(
2558
3463
  "Stream normalized trace events live (SSE; exits when the run finishes)"
2559
3464
  ).action(async (id, _opts, command) => {
@@ -2572,8 +3477,26 @@ function register11(program2) {
2572
3477
  });
2573
3478
  runs.command("diff <id>").description("Print the run's working-tree diff to stdout").action(async (id) => {
2574
3479
  const diff = await createClient().get(`${runPath(id)}/diff`);
3480
+ if (!diff) {
3481
+ console.error("(no diff)");
3482
+ return;
3483
+ }
2575
3484
  process.stdout.write(diff);
2576
3485
  });
3486
+ runs.command("fork <id>").description("Fork a finished run from its latest conversation checkpoint").requiredOption("--prompt <text>", "continuation prompt for the child run").action(async (id, opts, command) => {
3487
+ const result = await createClient().post(
3488
+ `${runPath(id)}/fork`,
3489
+ { prompt: opts.prompt }
3490
+ );
3491
+ if (resolveOutput(command) === "json") {
3492
+ printJson(result);
3493
+ return;
3494
+ }
3495
+ console.log(
3496
+ `Forked run ${result.runId} from ${result.parentRunId} at turn ${result.turn}`
3497
+ );
3498
+ console.error(`Watch it with: gauge runs watch ${result.runId}`);
3499
+ });
2577
3500
  runs.command("cancel <id>").description("Request cancellation of a run").action(async (id, _opts, command) => {
2578
3501
  const result = await createClient().post(
2579
3502
  `${runPath(id)}/cancel`
@@ -2592,7 +3515,7 @@ function register11(program2) {
2592
3515
  // src/commands/schedules.ts
2593
3516
  var schedules_exports2 = {};
2594
3517
  __export(schedules_exports2, {
2595
- register: () => register12
3518
+ register: () => register14
2596
3519
  });
2597
3520
  var CADENCE_CHOICES = [
2598
3521
  "none",
@@ -2617,67 +3540,138 @@ function parseDays(raw) {
2617
3540
  throw new CliError("usage", "--days-per-week must be an integer 1-7");
2618
3541
  return n;
2619
3542
  }
3543
+ function collect4(value, previous) {
3544
+ return [...previous, value];
3545
+ }
3546
+ function reposLabel(repos) {
3547
+ if (repos.length === 0) return "(default scaffold)";
3548
+ if (repos.length === 1) {
3549
+ const r = repos[0];
3550
+ return r.repoRef ? `${r.repoUrl}@${r.repoRef}` : r.repoUrl;
3551
+ }
3552
+ return `${repos.length} repos`;
3553
+ }
3554
+ function reposFromOpts(repo, ref) {
3555
+ return [{ repoUrl: repo, repoRef: ref ?? null }];
3556
+ }
2620
3557
  function toRow5(s) {
2621
3558
  return {
2622
3559
  id: s.id,
2623
- repo: s.repoUrl ?? "(default scaffold)",
2624
- ref: s.repoRef ?? "",
3560
+ name: s.name,
2625
3561
  cadence: s.cadence,
2626
3562
  days: s.daysPerWeek ?? "",
2627
3563
  agents: s.agents.join(", "),
3564
+ repos: reposLabel(s.repos),
3565
+ prompts: s.promptCount,
3566
+ enabled: s.enabled ? "yes" : "no",
2628
3567
  experiment: s.experiment ?? ""
2629
3568
  };
2630
3569
  }
2631
- function register12(program2) {
2632
- const group = program2.command("schedules").description("Manage prompt schedules");
2633
- group.command("list").description("List schedules for a prompt").requiredOption("--prompt <id>", "prompt id").action(async (opts, cmd) => {
3570
+ function toRefRow(s) {
3571
+ return {
3572
+ id: s.id,
3573
+ name: s.name,
3574
+ cadence: s.cadence,
3575
+ days: s.daysPerWeek ?? "",
3576
+ enabled: s.enabled ? "yes" : "no"
3577
+ };
3578
+ }
3579
+ var RUN_BLOCK_WARNINGS = {
3580
+ insufficient_credits: "warning: some targets were skipped or truncated: out of credits",
3581
+ needs_provider_key: "warning: some targets were skipped: no provider key for the selected agents"
3582
+ };
3583
+ function register14(program2) {
3584
+ const group = program2.command("schedules").description("Manage org schedules (named prompt sets on a cadence)");
3585
+ group.command("list").description(
3586
+ "List schedules for the org, or (with --prompt) the schedules a prompt is in"
3587
+ ).option("--prompt <id>", "only schedules that contain this prompt").action(async (opts, cmd) => {
2634
3588
  const org = resolveOrg(cmd);
2635
- const res = await createClient().get(
2636
- `${promptsPath(org)}/${encodeURIComponent(opts.prompt)}/schedules`
3589
+ const client = createClient();
3590
+ const json = resolveOutput(cmd) === "json";
3591
+ if (opts.prompt !== void 0) {
3592
+ const res2 = await client.get(
3593
+ `${promptsPath(org)}/${encodeURIComponent(opts.prompt)}/schedules`
3594
+ );
3595
+ if (json) printJson(res2.items);
3596
+ else printItems(res2.items.map(toRefRow), "table");
3597
+ return;
3598
+ }
3599
+ const res = await client.get(
3600
+ `/api/v1/orgs/${encodeURIComponent(org)}/schedules`
2637
3601
  );
2638
- if (resolveOutput(cmd) === "json") printJson(res.items);
3602
+ if (json) printJson(res.items);
2639
3603
  else printItems(res.items.map(toRow5), "table");
2640
3604
  });
2641
- group.command("add").description(
2642
- "Add a schedule (a repo target + cadence + agents) to a prompt"
2643
- ).requiredOption("--prompt <id>", "prompt id").requiredOption(
3605
+ group.command("create").description(
3606
+ "Create an org schedule: a named prompt set + agents + cadence + repo"
3607
+ ).requiredOption("--name <name>", "schedule name").requiredOption(
2644
3608
  "--agent <agents>",
2645
3609
  "comma-separated agents, e.g. claude-code,codex"
2646
- ).option("--repo <url>", "repository URL (default: the Gauge scaffold)").option("--ref <ref>", "branch, tag, or commit").option("--cadence <cadence>", CADENCE_CHOICES.join(" | "), "none").option("--days-per-week <n>", "1-7 (with --cadence days-per-week)").action(
3610
+ ).option(
3611
+ "--prompt <id>",
3612
+ "member prompt id (repeatable)",
3613
+ collect4,
3614
+ []
3615
+ ).option("--repo <url>", "repository URL (default: the Gauge scaffold)").option("--ref <ref>", "branch, tag, or commit (with --repo)").option("--cadence <cadence>", CADENCE_CHOICES.join(" | "), "none").option("--days-per-week <n>", "1-7 (with --cadence days-per-week)").option("--samples <n>", "samples per cycle (default: 1)").option("--model <id>", "pin a model id (default: the agent's default)").option("--disabled", "create the schedule disabled").action(
2647
3616
  async (opts, cmd) => {
2648
3617
  const org = resolveOrg(cmd);
3618
+ if (opts.ref !== void 0 && opts.repo === void 0)
3619
+ throw new CliError("usage", "--ref requires --repo");
2649
3620
  const body = {
3621
+ name: opts.name,
2650
3622
  agents: parseAgents(opts.agent),
2651
3623
  cadence: parseCadence(opts.cadence),
2652
- repoUrl: opts.repo,
2653
- repoRef: opts.ref
3624
+ samplesPerCycle: opts.samples !== void 0 ? parseSamples(opts.samples) : 1,
3625
+ repos: opts.repo !== void 0 ? reposFromOpts(opts.repo, opts.ref) : [],
3626
+ promptIds: opts.prompt,
3627
+ enabled: !opts.disabled
2654
3628
  };
2655
3629
  if (opts.daysPerWeek !== void 0)
2656
3630
  body.daysPerWeek = parseDays(opts.daysPerWeek);
3631
+ if (opts.model !== void 0) body.model = opts.model;
2657
3632
  const schedule = await createClient().post(
2658
- `${promptsPath(org)}/${encodeURIComponent(opts.prompt)}/schedules`,
3633
+ `/api/v1/orgs/${encodeURIComponent(org)}/schedules`,
2659
3634
  body
2660
3635
  );
2661
3636
  if (resolveOutput(cmd) === "json") printJson(schedule);
2662
- else console.log(`Added schedule ${schedule.id}`);
3637
+ else console.log(`Created schedule ${schedule.id}`);
2663
3638
  }
2664
3639
  );
2665
- group.command("edit <id>").description("Update a schedule").option("--agent <agents>", "comma-separated agents").option("--repo <url>", "repository URL").option("--clear-repo", "reset to the default scaffold").option("--ref <ref>", "branch, tag, or commit").option("--clear-ref", "reset to the repo's default branch").option("--cadence <cadence>", CADENCE_CHOICES.join(" | ")).option("--days-per-week <n>", "1-7 (with cadence days-per-week)").action(
3640
+ group.command("edit <id>").description("Update a schedule (repos and prompts are full replacements)").option("--name <name>", "rename the schedule").option("--agent <agents>", "comma-separated agents").option(
3641
+ "--prompt <id>",
3642
+ "member prompt id \u2014 replaces the whole set (repeatable)",
3643
+ collect4,
3644
+ []
3645
+ ).option("--clear-prompts", "remove all member prompts").option("--repo <url>", "set a single repo target").option("--ref <ref>", "branch, tag, or commit (with --repo)").option("--clear-repos", "reset to the default scaffold (no repos)").option("--cadence <cadence>", CADENCE_CHOICES.join(" | ")).option("--days-per-week <n>", "1-7 (with cadence days-per-week)").option("--samples <n>", "samples per cycle").option("--model <id>", "pin a model id").option("--clear-model", "use the agent's default model").option("--enable", "enable the schedule").option("--disable", "disable the schedule").action(
2666
3646
  async (id, opts, cmd) => {
2667
3647
  const body = {};
3648
+ if (opts.name !== void 0) body.name = opts.name;
2668
3649
  if (opts.agent !== void 0) body.agents = parseAgents(opts.agent);
2669
- if (opts.repo !== void 0 && opts.clearRepo)
2670
- throw new CliError("usage", "--repo and --clear-repo conflict");
2671
- if (opts.clearRepo) body.repoUrl = null;
2672
- else if (opts.repo !== void 0) body.repoUrl = opts.repo;
2673
- if (opts.ref !== void 0 && opts.clearRef)
2674
- throw new CliError("usage", "--ref and --clear-ref conflict");
2675
- if (opts.clearRef) body.repoRef = null;
2676
- else if (opts.ref !== void 0) body.repoRef = opts.ref;
2677
3650
  if (opts.cadence !== void 0)
2678
3651
  body.cadence = parseCadence(opts.cadence);
2679
3652
  if (opts.daysPerWeek !== void 0)
2680
3653
  body.daysPerWeek = parseDays(opts.daysPerWeek);
3654
+ if (opts.samples !== void 0)
3655
+ body.samplesPerCycle = parseSamples(opts.samples);
3656
+ if (opts.model !== void 0 && opts.clearModel)
3657
+ throw new CliError("usage", "--model and --clear-model conflict");
3658
+ if (opts.clearModel) body.model = null;
3659
+ else if (opts.model !== void 0) body.model = opts.model;
3660
+ if (opts.ref !== void 0 && opts.repo === void 0)
3661
+ throw new CliError("usage", "--ref requires --repo");
3662
+ if (opts.repo !== void 0 && opts.clearRepos)
3663
+ throw new CliError("usage", "--repo and --clear-repos conflict");
3664
+ if (opts.clearRepos) body.repos = [];
3665
+ else if (opts.repo !== void 0)
3666
+ body.repos = reposFromOpts(opts.repo, opts.ref);
3667
+ if (opts.prompt.length > 0 && opts.clearPrompts)
3668
+ throw new CliError("usage", "--prompt and --clear-prompts conflict");
3669
+ if (opts.clearPrompts) body.promptIds = [];
3670
+ else if (opts.prompt.length > 0) body.promptIds = opts.prompt;
3671
+ if (opts.enable && opts.disable)
3672
+ throw new CliError("usage", "--enable and --disable conflict");
3673
+ if (opts.enable) body.enabled = true;
3674
+ else if (opts.disable) body.enabled = false;
2681
3675
  if (Object.keys(body).length === 0)
2682
3676
  throw new CliError("usage", "nothing to change");
2683
3677
  const schedule = await createClient().patch(
@@ -2688,6 +3682,32 @@ function register12(program2) {
2688
3682
  else console.log(`Updated schedule ${schedule.id}`);
2689
3683
  }
2690
3684
  );
3685
+ group.command("run <id>").description(
3686
+ "Run a schedule now \u2014 forced expansion of its whole member set (ORG funding, credit-gated)"
3687
+ ).action(async (id, _opts, cmd) => {
3688
+ const result = await createClient().post(
3689
+ `/api/v1/schedules/${encodeURIComponent(id)}/run`,
3690
+ {}
3691
+ );
3692
+ if (resolveOutput(cmd) === "json") {
3693
+ printJson(result);
3694
+ return;
3695
+ }
3696
+ if (result.runIds.length === 0) {
3697
+ console.log("No runs enqueued (the schedule has no member prompts)");
3698
+ return;
3699
+ }
3700
+ console.log(
3701
+ `Enqueued ${result.runIds.length} run(s) in ${result.batchIds.length} batch(es)`
3702
+ );
3703
+ for (const runId of result.runIds) console.log(runId);
3704
+ if (result.blocked) console.error(RUN_BLOCK_WARNINGS[result.blocked]);
3705
+ for (const nr of result.notReady ?? [])
3706
+ console.error(
3707
+ `warning: skipped ${nr.repoUrl} \u2014 baseline snapshot ${nr.status}`
3708
+ );
3709
+ console.error("Tip: `gauge runs watch <id>` streams a run live");
3710
+ });
2691
3711
  group.command("rm <id>").description("Delete a schedule").action(async (id, _opts, cmd) => {
2692
3712
  await createClient().delete(
2693
3713
  `/api/v1/schedules/${encodeURIComponent(id)}`
@@ -2699,7 +3719,7 @@ function register12(program2) {
2699
3719
  // src/commands/stats.ts
2700
3720
  var stats_exports2 = {};
2701
3721
  __export(stats_exports2, {
2702
- register: () => register13
3722
+ register: () => register15
2703
3723
  });
2704
3724
  function addFilterOptions(cmd) {
2705
3725
  return cmd.option("--prompt <id>", "filter to a single prompt").option("--topic <ids>", "comma-separated topic ids").option("--tag <ids>", "comma-separated tag ids").option("--repo <urls>", "comma-separated base repo urls").option("--language <langs>", "comma-separated repo languages").option("--framework <names>", "comma-separated repo frameworks").option("--size <buckets>", "comma-separated codebase-size buckets").option("--branded", "only branded prompts").option("--unbranded", "only non-branded prompts").option("--limit <n>", "max rows (default 50)").option("--full", "return all rows (up to 1000)");
@@ -2720,9 +3740,9 @@ function filterQuery(opts) {
2720
3740
  limit: opts.full ? "1000" : opts.limit
2721
3741
  };
2722
3742
  }
2723
- var pct = (rate) => `${(rate * 100).toFixed(1)}%`;
3743
+ var pct2 = (rate) => `${(rate * 100).toFixed(1)}%`;
2724
3744
  var delta = (d) => d === null || d === 0 ? "\u2014" : d > 0 ? `+${d}` : String(d);
2725
- function noteFreshness(f) {
3745
+ function noteFreshness2(f) {
2726
3746
  if (!f.available) {
2727
3747
  console.error(
2728
3748
  "warning: analytics store is temporarily unavailable; results may be incomplete."
@@ -2745,15 +3765,15 @@ async function runStats(command, resource, opts, toRow6) {
2745
3765
  return;
2746
3766
  }
2747
3767
  printItems(res.items.map(toRow6), "table");
2748
- noteFreshness(res.freshness);
3768
+ noteFreshness2(res.freshness);
2749
3769
  }
2750
3770
  var rankingRow = (r) => ({
2751
3771
  rank: r.rank,
2752
3772
  brand: r.brandName,
2753
3773
  kind: r.kind,
2754
3774
  installs: r.installs,
2755
- "install%": pct(r.installRate),
2756
- "mention%": pct(r.mentionRate),
3775
+ "install%": pct2(r.installRate),
3776
+ "mention%": pct2(r.mentionRate),
2757
3777
  delta: delta(r.deltaRank)
2758
3778
  });
2759
3779
  var packageRow = (r) => ({
@@ -2762,29 +3782,28 @@ var packageRow = (r) => ({
2762
3782
  brand: r.brandName,
2763
3783
  kind: r.kind,
2764
3784
  installs: r.installs,
2765
- rate: pct(r.rate)
3785
+ rate: pct2(r.rate)
2766
3786
  });
2767
3787
  var brandRow = (r) => ({
2768
3788
  brand: r.brandName,
2769
3789
  kind: r.kind,
2770
3790
  installs: r.installs,
2771
- rate: pct(r.rate)
3791
+ rate: pct2(r.rate)
2772
3792
  });
2773
3793
  var funnelRow = (r) => ({
2774
3794
  brand: r.brandName,
2775
3795
  kind: r.kind,
2776
- "mention%": pct(r.mentionRate),
2777
- "install%": pct(r.installRate)
3796
+ "mention%": pct2(r.mentionRate),
3797
+ "install%": pct2(r.installRate)
2778
3798
  });
2779
3799
  var domainRow = (r) => ({
2780
3800
  domain: r.domain,
2781
3801
  brand: r.brandName,
2782
3802
  runs: r.runs,
2783
- rate: pct(r.rate),
2784
- requests: r.requests,
2785
- denied: r.deniedRequests
3803
+ rate: pct2(r.rate),
3804
+ requests: r.requests
2786
3805
  });
2787
- function register13(program2) {
3806
+ function register15(program2) {
2788
3807
  const group = program2.command("stats").description("Read-only analytics over your runs");
2789
3808
  addFilterOptions(
2790
3809
  group.command("rankings").description("Brands ranked by install rate")
@@ -2816,12 +3835,12 @@ function register13(program2) {
2816
3835
  // src/commands/tags.ts
2817
3836
  var tags_exports2 = {};
2818
3837
  __export(tags_exports2, {
2819
- register: () => register14
3838
+ register: () => register16
2820
3839
  });
2821
3840
  function tagsPath(org) {
2822
3841
  return `/api/v1/orgs/${encodeURIComponent(org)}/tags`;
2823
3842
  }
2824
- function register14(program2) {
3843
+ function register16(program2) {
2825
3844
  const group = program2.command("tags").description("Manage org tags");
2826
3845
  group.command("list").description("List tags").action(async (_opts, cmd) => {
2827
3846
  const org = resolveOrg(cmd);
@@ -2864,12 +3883,12 @@ function register14(program2) {
2864
3883
  // src/commands/topics.ts
2865
3884
  var topics_exports2 = {};
2866
3885
  __export(topics_exports2, {
2867
- register: () => register15
3886
+ register: () => register17
2868
3887
  });
2869
3888
  function topicsPath(org) {
2870
3889
  return `/api/v1/orgs/${encodeURIComponent(org)}/topics`;
2871
3890
  }
2872
- function register15(program2) {
3891
+ function register17(program2) {
2873
3892
  const group = program2.command("topics").description("Manage org topics");
2874
3893
  group.command("list").description("List topics").action(async (_opts, cmd) => {
2875
3894
  const org = resolveOrg(cmd);
@@ -2890,9 +3909,9 @@ function register15(program2) {
2890
3909
  // src/commands/usage.ts
2891
3910
  var usage_exports = {};
2892
3911
  __export(usage_exports, {
2893
- register: () => register16
3912
+ register: () => register18
2894
3913
  });
2895
- function register16(program2) {
3914
+ function register18(program2) {
2896
3915
  program2.command("usage").description("List credit ledger entries").option("--since <window>", 'e.g. "30d", "24h", or an ISO date').option("--limit <n>", "page size (1-200)", parseLimit, 50).option("--cursor <cursor>", "resume from a previous page's nextCursor").action(
2897
3916
  async (opts, cmd) => {
2898
3917
  const org = resolveOrg(cmd);
@@ -2948,7 +3967,8 @@ program.name("gauge").description(
2948
3967
  );
2949
3968
  for (const group of [
2950
3969
  auth_exports,
2951
- orgs_exports,
3970
+ onboard_exports,
3971
+ orgs_exports2,
2952
3972
  prompts_exports2,
2953
3973
  schedules_exports2,
2954
3974
  repos_exports2,
@@ -2962,6 +3982,7 @@ for (const group of [
2962
3982
  billing_exports2,
2963
3983
  usage_exports,
2964
3984
  stats_exports2,
3985
+ query_exports2,
2965
3986
  config_exports
2966
3987
  ]) {
2967
3988
  group.register(program);