rivet-design 0.11.13 → 0.11.14

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 (76) hide show
  1. package/dist/config/flags.d.ts +1 -1
  2. package/dist/config/flags.js +1 -1
  3. package/dist/config/proxy.d.ts +6 -0
  4. package/dist/config/proxy.d.ts.map +1 -1
  5. package/dist/config/proxy.js +36 -19
  6. package/dist/config/proxy.js.map +1 -1
  7. package/dist/install/harnesses.d.ts.map +1 -1
  8. package/dist/install/harnesses.js +78 -42
  9. package/dist/install/harnesses.js.map +1 -1
  10. package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts +29 -0
  11. package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
  12. package/dist/mcp/agent-variants/WorktreeOrchestrator.js +472 -8
  13. package/dist/mcp/agent-variants/WorktreeOrchestrator.js.map +1 -1
  14. package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts.map +1 -1
  15. package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js +64 -0
  16. package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js.map +1 -1
  17. package/dist/mcp/agent-variants/contracts.d.ts +378 -378
  18. package/dist/mcp/agent-variants/tools.d.ts +29 -1
  19. package/dist/mcp/agent-variants/tools.d.ts.map +1 -1
  20. package/dist/mcp/agent-variants/tools.js +142 -13
  21. package/dist/mcp/agent-variants/tools.js.map +1 -1
  22. package/dist/mcp/auth/tools.d.ts.map +1 -1
  23. package/dist/mcp/auth/tools.js +68 -2
  24. package/dist/mcp/auth/tools.js.map +1 -1
  25. package/dist/mcp/server.d.ts +54 -2
  26. package/dist/mcp/server.d.ts.map +1 -1
  27. package/dist/mcp/server.js +190 -41
  28. package/dist/mcp/server.js.map +1 -1
  29. package/dist/mcp/toolAnalytics.d.ts +15 -0
  30. package/dist/mcp/toolAnalytics.d.ts.map +1 -0
  31. package/dist/mcp/toolAnalytics.js +87 -0
  32. package/dist/mcp/toolAnalytics.js.map +1 -0
  33. package/dist/onboarding/signin.d.ts +10 -0
  34. package/dist/onboarding/signin.d.ts.map +1 -1
  35. package/dist/onboarding/signin.js +41 -3
  36. package/dist/onboarding/signin.js.map +1 -1
  37. package/dist/routes/agentVariants.d.ts +2 -2
  38. package/dist/routes/agentVariants.d.ts.map +1 -1
  39. package/dist/routes/agentVariants.js +12 -7
  40. package/dist/routes/agentVariants.js.map +1 -1
  41. package/dist/routes/mcp.d.ts.map +1 -1
  42. package/dist/routes/mcp.js +153 -2
  43. package/dist/routes/mcp.js.map +1 -1
  44. package/dist/server.d.ts +6 -0
  45. package/dist/server.d.ts.map +1 -1
  46. package/dist/server.js +52 -37
  47. package/dist/server.js.map +1 -1
  48. package/dist/services/BridgeBatchPipeline.d.ts +4 -0
  49. package/dist/services/BridgeBatchPipeline.d.ts.map +1 -1
  50. package/dist/services/BridgeBatchPipeline.js +18 -1
  51. package/dist/services/BridgeBatchPipeline.js.map +1 -1
  52. package/dist/services/MCPOnboardingTelemetry.d.ts +41 -0
  53. package/dist/services/MCPOnboardingTelemetry.d.ts.map +1 -0
  54. package/dist/services/MCPOnboardingTelemetry.js +158 -0
  55. package/dist/services/MCPOnboardingTelemetry.js.map +1 -0
  56. package/dist/services/MCPVariantsTelemetry.d.ts +59 -0
  57. package/dist/services/MCPVariantsTelemetry.d.ts.map +1 -0
  58. package/dist/services/MCPVariantsTelemetry.js +153 -0
  59. package/dist/services/MCPVariantsTelemetry.js.map +1 -0
  60. package/dist/services/SessionBridgeService.d.ts +28 -7
  61. package/dist/services/SessionBridgeService.d.ts.map +1 -1
  62. package/dist/services/SessionBridgeService.js +46 -9
  63. package/dist/services/SessionBridgeService.js.map +1 -1
  64. package/dist/services/TelemetryService.d.ts +108 -0
  65. package/dist/services/TelemetryService.d.ts.map +1 -1
  66. package/dist/services/TelemetryService.js +269 -1
  67. package/dist/services/TelemetryService.js.map +1 -1
  68. package/dist/services/WorktreeManager.d.ts.map +1 -1
  69. package/dist/services/WorktreeManager.js +3 -0
  70. package/dist/services/WorktreeManager.js.map +1 -1
  71. package/package.json +2 -2
  72. package/src/ui/dist/assets/main-CNVy90lr.css +1 -0
  73. package/src/ui/dist/assets/main-tL2Lt1OL.js +655 -0
  74. package/src/ui/dist/index.html +2 -2
  75. package/src/ui/dist/assets/main-DREt3GGU.css +0 -1
  76. package/src/ui/dist/assets/main-Dt7ShmjM.js +0 -655
@@ -402,6 +402,31 @@ class AgentVariantsOrchestrator {
402
402
  const result = this.store.propose(args);
403
403
  this.activeSessionId = result.sessionId;
404
404
  this.ensureResources(result.sessionId);
405
+ const projectContext = args.projectContext ?? { kind: 'existing' };
406
+ const mode = this.getVariantsTelemetryMode(projectContext, args.target);
407
+ this.startVariantsRound({
408
+ sessionId: result.sessionId,
409
+ mode,
410
+ workItemCount: args.count ?? 4,
411
+ });
412
+ if (result.sourcePlanWorkItem) {
413
+ this.telemetry.trackAgentVariantsSourcePlanStarted?.({
414
+ sessionId: result.sessionId,
415
+ workItemId: result.sourcePlanWorkItem.id,
416
+ mode,
417
+ projectContextKind: projectContext.kind,
418
+ requestedCount: args.count ?? 4,
419
+ });
420
+ }
421
+ if (result.briefWorkItem) {
422
+ this.telemetry.trackAgentVariantsBriefsStarted?.({
423
+ sessionId: result.sessionId,
424
+ workItemId: result.briefWorkItem.id,
425
+ mode,
426
+ projectContextKind: projectContext.kind,
427
+ requestedCount: args.count ?? 4,
428
+ });
429
+ }
405
430
  this.telemetry.track('agent_variants.session_started', {
406
431
  source: 'mcp',
407
432
  sessionId: result.sessionId,
@@ -501,6 +526,205 @@ class AgentVariantsOrchestrator {
501
526
  ...(artifacts.length > 0 ? { artifacts } : {}),
502
527
  };
503
528
  }
529
+ getVariantsTelemetryMode(projectContext, _target) {
530
+ if (projectContext.kind === 'fresh' && projectContext.variantContext) {
531
+ return 'source_grounded';
532
+ }
533
+ if (projectContext.kind === 'fresh')
534
+ return 'zero_to_one';
535
+ return 'initial_generation';
536
+ }
537
+ startVariantsRound(args) {
538
+ const resources = this.ensureResources(args.sessionId);
539
+ const roundIndex = resources.nextRoundIndex;
540
+ const startedAt = Date.now();
541
+ const workItemIds = args.workItemIds ? [...args.workItemIds] : undefined;
542
+ resources.nextRoundIndex += 1;
543
+ resources.rounds.set(roundIndex, {
544
+ roundIndex,
545
+ startedAt,
546
+ mode: args.mode,
547
+ workItemIds,
548
+ completed: false,
549
+ });
550
+ resources.currentRoundIndex = roundIndex;
551
+ resources.currentRoundStartedAt = startedAt;
552
+ resources.currentRoundMode = args.mode;
553
+ resources.currentRoundWorkItemIds = workItemIds;
554
+ const projectContext = this.store.getProjectContext(args.sessionId);
555
+ this.telemetry.trackAgentVariantsRoundStarted?.({
556
+ sessionId: args.sessionId,
557
+ roundIndex,
558
+ mode: args.mode,
559
+ projectContextKind: projectContext.kind,
560
+ workItemCount: args.workItemCount,
561
+ });
562
+ }
563
+ completeVariantsRound(args) {
564
+ const resources = this.resources.get(args.sessionId);
565
+ if (!resources)
566
+ return;
567
+ const roundIndex = args.roundIndex ?? resources.currentRoundIndex;
568
+ if (roundIndex === undefined)
569
+ return;
570
+ const round = resources.rounds.get(roundIndex);
571
+ if (round?.completed)
572
+ return;
573
+ const projectContext = this.store.getProjectContext(args.sessionId);
574
+ const summary = round?.workItemIds
575
+ ? this.buildRoundSummary({
576
+ sessionId: args.sessionId,
577
+ workItemIds: round.workItemIds,
578
+ })
579
+ : args.summary;
580
+ this.telemetry.trackAgentVariantsRoundCompleted?.({
581
+ sessionId: args.sessionId,
582
+ roundIndex,
583
+ mode: round?.mode ?? resources.currentRoundMode,
584
+ projectContextKind: projectContext.kind,
585
+ requestStatus: args.requestStatus,
586
+ completedCount: summary.successCount,
587
+ failedCount: summary.failureCount,
588
+ cancelledCount: summary.cancelledCount,
589
+ durationMs: round?.startedAt !== undefined
590
+ ? Date.now() - round.startedAt
591
+ : undefined,
592
+ });
593
+ if (round) {
594
+ round.completed = true;
595
+ }
596
+ if (resources.currentRoundIndex === roundIndex) {
597
+ resources.currentRoundIndex = undefined;
598
+ resources.currentRoundStartedAt = undefined;
599
+ resources.currentRoundMode = undefined;
600
+ resources.currentRoundWorkItemIds = undefined;
601
+ }
602
+ }
603
+ buildRoundSummary(args) {
604
+ const ids = new Set(args.workItemIds);
605
+ const variants = this.store
606
+ .getVariants(args.sessionId)
607
+ .filter((variant) => ids.has(variant.workItemId))
608
+ .map((variant) => ({
609
+ workItemId: variant.workItemId,
610
+ status: variant.status,
611
+ label: variant.label,
612
+ }));
613
+ return {
614
+ successCount: variants.filter((variant) => variant.status === 'succeeded')
615
+ .length,
616
+ failureCount: variants.filter((variant) => variant.status === 'failed')
617
+ .length,
618
+ cancelledCount: variants.filter((variant) => variant.status === 'cancelled').length,
619
+ variants,
620
+ };
621
+ }
622
+ recordCurrentVariantsRoundWorkItems(args) {
623
+ const resources = this.resources.get(args.sessionId);
624
+ if (!resources || resources.currentRoundIndex === undefined)
625
+ return;
626
+ const round = resources.rounds.get(resources.currentRoundIndex);
627
+ if (!round || round.workItemIds)
628
+ return;
629
+ const workItemIds = [...args.workItemIds];
630
+ round.workItemIds = workItemIds;
631
+ resources.currentRoundWorkItemIds = workItemIds;
632
+ this.completeTerminalVariantsRounds(args.sessionId);
633
+ }
634
+ completeTerminalVariantsRounds(sessionId) {
635
+ const resources = this.resources.get(sessionId);
636
+ if (!resources)
637
+ return;
638
+ for (const round of resources.rounds.values()) {
639
+ if (round.completed || !round.workItemIds)
640
+ continue;
641
+ const summary = this.buildRoundSummary({
642
+ sessionId,
643
+ workItemIds: round.workItemIds,
644
+ });
645
+ if (!this.isVariantsRoundTerminal(summary, round.workItemIds))
646
+ continue;
647
+ this.completeVariantsRound({
648
+ sessionId,
649
+ roundIndex: round.roundIndex,
650
+ requestStatus: this.getVariantsRoundRequestStatus(summary),
651
+ summary,
652
+ });
653
+ }
654
+ }
655
+ completePendingVariantsRounds(args) {
656
+ const resources = this.resources.get(args.sessionId);
657
+ if (!resources)
658
+ return;
659
+ for (const round of resources.rounds.values()) {
660
+ if (round.completed)
661
+ continue;
662
+ this.completeVariantsRound({
663
+ ...args,
664
+ roundIndex: round.roundIndex,
665
+ summary: round.workItemIds
666
+ ? this.buildRoundSummary({
667
+ sessionId: args.sessionId,
668
+ workItemIds: round.workItemIds,
669
+ })
670
+ : args.summary,
671
+ });
672
+ }
673
+ }
674
+ isVariantsRoundTerminal(summary, workItemIds) {
675
+ return (summary.variants.length === workItemIds.length &&
676
+ summary.variants.every((variant) => variant.status === 'succeeded' ||
677
+ variant.status === 'failed' ||
678
+ variant.status === 'cancelled'));
679
+ }
680
+ getVariantsRoundRequestStatus(summary) {
681
+ if (summary.cancelledCount > 0 && summary.successCount === 0) {
682
+ return summary.failureCount > 0 ? 'failed' : 'cancelled';
683
+ }
684
+ if (summary.failureCount > 0) {
685
+ return summary.successCount > 0 ? 'degraded' : 'failed';
686
+ }
687
+ if (summary.cancelledCount > 0)
688
+ return 'degraded';
689
+ return 'completed';
690
+ }
691
+ refinementTelemetryForWorkItem(args) {
692
+ const input = this.store.getWorkItemInput(args.sessionId, args.workItemId);
693
+ const targetVariantId = input?.variantId ?? input?.sourceVariantId;
694
+ if (!targetVariantId)
695
+ return null;
696
+ const projectContext = this.store.getProjectContext(args.sessionId);
697
+ return {
698
+ sessionId: args.sessionId,
699
+ requestId: input?.requestId,
700
+ workItemId: args.workItemId,
701
+ leaseId: args.leaseId,
702
+ targetVariantId,
703
+ sourceVariantId: input?.sourceVariantId,
704
+ mode: input?.sourceVariantId ? 'vary' : 'comment_refine',
705
+ projectContextKind: projectContext.kind,
706
+ requestStatus: args.requestStatus,
707
+ instructionLength: input?.instruction?.length,
708
+ durationMs: args.durationMs,
709
+ failureReason: args.failureReason,
710
+ };
711
+ }
712
+ trackRefinementLeased(args) {
713
+ for (const item of args.lease.leasedWorkItems) {
714
+ const telemetry = this.refinementTelemetryForWorkItem({
715
+ sessionId: args.sessionId,
716
+ workItemId: item.id,
717
+ leaseId: args.lease.leaseId,
718
+ });
719
+ if (!telemetry)
720
+ continue;
721
+ this.telemetry.trackAgentVariantsRefinementLeased?.({
722
+ ...telemetry,
723
+ leaseDurationMs: args.lease.leaseTtlMs,
724
+ workItemCount: 1,
725
+ });
726
+ }
727
+ }
504
728
  emitChange() {
505
729
  try {
506
730
  this.events.emit('change', this.buildActiveSnapshot());
@@ -510,7 +734,19 @@ class AgentVariantsOrchestrator {
510
734
  }
511
735
  }
512
736
  reportBriefs(args) {
513
- const result = this.store.reportBriefs(args);
737
+ let result;
738
+ try {
739
+ result = this.store.reportBriefs(args);
740
+ }
741
+ catch (error) {
742
+ this.telemetry.trackAgentVariantsBriefsFailed?.({
743
+ sessionId: args.sessionId,
744
+ workItemId: args.workItemId,
745
+ briefCount: args.briefs.length,
746
+ failureReason: error,
747
+ });
748
+ throw error;
749
+ }
514
750
  const projectContext = this.store.getProjectContext(args.sessionId);
515
751
  if (projectContext.variantContext) {
516
752
  (0, variantContext_1.writeVariantContextBundle)(projectContext.variantContext);
@@ -523,11 +759,33 @@ class AgentVariantsOrchestrator {
523
759
  evidenceBackedCount,
524
760
  shortBriefCount,
525
761
  });
762
+ this.telemetry.trackAgentVariantsBriefsCompleted?.({
763
+ sessionId: args.sessionId,
764
+ workItemId: args.workItemId,
765
+ mode: args.mode,
766
+ projectContextKind: projectContext.kind,
767
+ requestStatus: 'completed',
768
+ briefCount: result.briefs.length,
769
+ briefLabelCount: result.briefs.filter((brief) => brief.label.length > 0)
770
+ .length,
771
+ bindingCount: args.bindings?.length ?? 0,
772
+ });
526
773
  this.emitChange();
527
774
  return result;
528
775
  }
529
776
  reportSourcePlan(args) {
530
- const result = this.store.reportSourcePlan(args);
777
+ let result;
778
+ try {
779
+ result = this.store.reportSourcePlan(args);
780
+ }
781
+ catch (error) {
782
+ this.telemetry.trackAgentVariantsSourcePlanFailed?.({
783
+ sessionId: args.sessionId,
784
+ workItemId: args.workItemId,
785
+ failureReason: error,
786
+ });
787
+ throw error;
788
+ }
531
789
  const projectContext = this.store.getProjectContext(args.sessionId);
532
790
  if (projectContext.variantContext) {
533
791
  (0, variantContext_1.writeVariantContextBundle)(projectContext.variantContext);
@@ -547,6 +805,20 @@ class AgentVariantsOrchestrator {
547
805
  preserveBrand: false,
548
806
  });
549
807
  }
808
+ this.telemetry.trackAgentVariantsSourcePlanCompleted?.({
809
+ sessionId: args.sessionId,
810
+ workItemId: args.workItemId,
811
+ projectContextKind: projectContext.kind,
812
+ requestStatus: 'completed',
813
+ actionCount: args.sourcePlan.actions.length,
814
+ metadataCount: args.sourcePlan.metadata.length,
815
+ bindingCount: args.sourcePlan.bindings?.length ?? 0,
816
+ });
817
+ this.telemetry.trackAgentVariantsBriefsStarted?.({
818
+ sessionId: args.sessionId,
819
+ workItemId: result.briefWorkItem.id,
820
+ projectContextKind: projectContext.kind,
821
+ });
550
822
  this.emitChange();
551
823
  return result;
552
824
  }
@@ -562,6 +834,7 @@ class AgentVariantsOrchestrator {
562
834
  resources.leasedAt.set(item.id, now);
563
835
  }
564
836
  }
837
+ this.trackRefinementLeased({ sessionId: args.sessionId, lease: result });
565
838
  // Decorate each leased item's input with the worktreePath provisioned
566
839
  // by approve(). The skill instructs agents to write files to
567
840
  // `input.worktreePath` — without this decoration that field would be
@@ -598,6 +871,19 @@ class AgentVariantsOrchestrator {
598
871
  if (seenVariantIds.has(target.variantId))
599
872
  continue;
600
873
  seenVariantIds.add(target.variantId);
874
+ const mode = target.count == null ? 'comment_refine' : 'vary';
875
+ this.telemetry.trackAgentVariantsRefinementRequested?.({
876
+ sessionId: args.sessionId,
877
+ requestId: target.requestId,
878
+ entryPoint: 'watch_loop',
879
+ mode,
880
+ projectContextKind: this.store.getProjectContext(args.sessionId).kind,
881
+ targetVariantId: target.variantId,
882
+ sourceVariantId: mode === 'vary' ? target.variantId : undefined,
883
+ requestedCount: target.count,
884
+ commentCount: 1,
885
+ instructionLength: target.instruction.length,
886
+ });
601
887
  const currentHtml = this.getStaticPreviewHtml(args.sessionId, target.variantId);
602
888
  if (target.count == null) {
603
889
  // Plain Apply (no variantRequest) → refine the variant IN PLACE: one
@@ -679,6 +965,17 @@ class AgentVariantsOrchestrator {
679
965
  throw error;
680
966
  }
681
967
  }
968
+ for (const dropped of droppedRefinements) {
969
+ this.telemetry.trackAgentVariantsRefinementFailed?.({
970
+ sessionId: args.sessionId,
971
+ targetVariantId: dropped.variantId,
972
+ mode: args.targets.find((target) => target.variantId === dropped.variantId)
973
+ ?.count == null
974
+ ? 'comment_refine'
975
+ : 'vary',
976
+ failureReason: dropped.reason,
977
+ });
978
+ }
682
979
  this.emitChange();
683
980
  return { droppedRefinements, createdWorkItemIds };
684
981
  }
@@ -709,6 +1006,14 @@ class AgentVariantsOrchestrator {
709
1006
  description: args.description,
710
1007
  runLabel: args.runLabel,
711
1008
  });
1009
+ this.telemetry.trackAgentVariantsRequestStarted?.({
1010
+ sessionId: args.sessionId,
1011
+ entryPoint: 'history',
1012
+ mode: 'history_adoption',
1013
+ projectContextKind: this.store.getProjectContext(args.sessionId).kind,
1014
+ requestedCount: 1,
1015
+ sourceVariantId: args.source.variantId,
1016
+ });
712
1017
  // Register (or re-register, harmlessly) the static-preview record so the
713
1018
  // snapshot surfaces the adopted variant as a static_artifact.
714
1019
  const resources = this.ensureResources(args.sessionId);
@@ -718,6 +1023,16 @@ class AgentVariantsOrchestrator {
718
1023
  assetBase,
719
1024
  hasAssets,
720
1025
  });
1026
+ this.telemetry.trackAgentVariantsRequestAccepted?.({
1027
+ sessionId: args.sessionId,
1028
+ entryPoint: 'history',
1029
+ mode: 'history_adoption',
1030
+ projectContextKind: this.store.getProjectContext(args.sessionId).kind,
1031
+ requestStatus: 'accepted',
1032
+ acceptedCount: append.created ? 1 : 0,
1033
+ sourceVariantId: args.source.variantId,
1034
+ targetVariantId: append.workItemId,
1035
+ });
721
1036
  this.emitChange();
722
1037
  return {
723
1038
  workItemId: append.workItemId,
@@ -800,7 +1115,9 @@ class AgentVariantsOrchestrator {
800
1115
  }
801
1116
  let hasAssets = false;
802
1117
  try {
803
- hasAssets = fs_1.default.readdirSync(assetBase).some((name) => name !== 'index.html');
1118
+ hasAssets = fs_1.default
1119
+ .readdirSync(assetBase)
1120
+ .some((name) => name !== 'index.html');
804
1121
  }
805
1122
  catch {
806
1123
  hasAssets = false;
@@ -815,7 +1132,7 @@ class AgentVariantsOrchestrator {
815
1132
  */
816
1133
  isStaticPreviewVariant(sessionId, workItemId) {
817
1134
  try {
818
- return this.store.getWorkItemKind(sessionId, workItemId) === 'static_preview';
1135
+ return (this.store.getWorkItemKind(sessionId, workItemId) === 'static_preview');
819
1136
  }
820
1137
  catch {
821
1138
  return false;
@@ -825,12 +1142,22 @@ class AgentVariantsOrchestrator {
825
1142
  return this.store.getVariantPick(sessionId);
826
1143
  }
827
1144
  refineVariant(args) {
1145
+ this.telemetry.trackAgentVariantsRefinementRequested?.({
1146
+ sessionId: args.sessionId,
1147
+ entryPoint: 'mcp_tool',
1148
+ mode: 'comment_refine',
1149
+ projectContextKind: this.store.getProjectContext(args.sessionId).kind,
1150
+ targetVariantId: args.variantId,
1151
+ commentCount: 1,
1152
+ instructionLength: args.instruction.length,
1153
+ });
828
1154
  try {
829
1155
  const lease = this.store.leaseRefineItemForVariant({
830
1156
  sessionId: args.sessionId,
831
1157
  variantId: args.variantId,
832
1158
  leaseOwner: args.leaseOwner,
833
1159
  });
1160
+ this.trackRefinementLeased({ sessionId: args.sessionId, lease });
834
1161
  this.emitChange();
835
1162
  return lease;
836
1163
  }
@@ -838,6 +1165,14 @@ class AgentVariantsOrchestrator {
838
1165
  if (!(error instanceof errors_1.AgentVariantsError) ||
839
1166
  error.code !== 'INVALID_STAGE_ACTION' ||
840
1167
  !error.message.includes('No pending refinement exists')) {
1168
+ this.telemetry.trackAgentVariantsRefinementFailed?.({
1169
+ sessionId: args.sessionId,
1170
+ entryPoint: 'mcp_tool',
1171
+ mode: 'comment_refine',
1172
+ projectContextKind: this.store.getProjectContext(args.sessionId).kind,
1173
+ targetVariantId: args.variantId,
1174
+ failureReason: error,
1175
+ });
841
1176
  throw error;
842
1177
  }
843
1178
  }
@@ -848,6 +1183,16 @@ class AgentVariantsOrchestrator {
848
1183
  instruction: args.instruction,
849
1184
  currentHtml,
850
1185
  });
1186
+ this.telemetry.trackAgentVariantsRefinementLeased?.({
1187
+ sessionId: args.sessionId,
1188
+ entryPoint: 'mcp_tool',
1189
+ mode: 'comment_refine',
1190
+ projectContextKind: this.store.getProjectContext(args.sessionId).kind,
1191
+ targetVariantId: args.variantId,
1192
+ workItemId: refineItem.id,
1193
+ workItemCount: 1,
1194
+ instructionLength: args.instruction.length,
1195
+ });
851
1196
  // Lease the just-created refine item by id. A generic
852
1197
  // requestWork({ requestedLeaseCount: 1 }) takes the first leasable item in
853
1198
  // work-item order, which could be an unrelated still-pending static_preview
@@ -1086,12 +1431,20 @@ class AgentVariantsOrchestrator {
1086
1431
  const result = this.store.approve(args);
1087
1432
  const resources = this.ensureResources(args.sessionId);
1088
1433
  resources.approveStartedAt = Date.now();
1434
+ const projectContext = this.store.getProjectContext(args.sessionId);
1089
1435
  this.telemetry.track('agent_variants.approved', {
1090
1436
  source: 'mcp',
1091
1437
  sessionId: args.sessionId,
1092
1438
  approvedCount: result.approvedCount,
1093
1439
  totalBriefs: result.totalCount,
1094
- isFresh: this.store.getProjectContext(args.sessionId).kind === 'fresh',
1440
+ isFresh: projectContext.kind === 'fresh',
1441
+ });
1442
+ const workItemIds = projectContext.kind === 'fresh'
1443
+ ? this.store.getVariants(args.sessionId).map((v) => v.workItemId)
1444
+ : result.codeGenWorkItemIds;
1445
+ this.recordCurrentVariantsRoundWorkItems({
1446
+ sessionId: args.sessionId,
1447
+ workItemIds,
1095
1448
  });
1096
1449
  this.emitChange();
1097
1450
  // Await provisioning before returning so request_work always sees a
@@ -1179,6 +1532,14 @@ class AgentVariantsOrchestrator {
1179
1532
  })
1180
1533
  : this.store.appendExistingCodeGenVariants(forkArgs);
1181
1534
  variantIds = createdWorkItemIds;
1535
+ this.startVariantsRound({
1536
+ sessionId,
1537
+ mode: args.sourceVariantId
1538
+ ? 'vary'
1539
+ : this.getVariantsTelemetryMode(projectContext, args.target),
1540
+ workItemCount: createdWorkItemIds.length,
1541
+ workItemIds: createdWorkItemIds,
1542
+ });
1182
1543
  if (args.sourceVariantId) {
1183
1544
  await this.provisionForkedFromVariantWorktrees(sessionId, args.sourceVariantId, createdWorkItemIds);
1184
1545
  }
@@ -1208,11 +1569,12 @@ class AgentVariantsOrchestrator {
1208
1569
  !proposeResult.briefWorkItem) {
1209
1570
  throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', `start_variants expected awaiting_briefs from propose, got ${proposeResult.stage}`);
1210
1571
  }
1211
- this.store.reportBriefs({
1572
+ this.reportBriefs({
1212
1573
  sessionId: proposeResult.sessionId,
1213
1574
  workItemId: proposeResult.briefWorkItem.id,
1214
1575
  attempt: proposeResult.briefWorkItem.attempt,
1215
1576
  briefs,
1577
+ mode: this.getVariantsTelemetryMode(projectContext, args.target),
1216
1578
  });
1217
1579
  const approveResult = await this.approve({
1218
1580
  sessionId: proposeResult.sessionId,
@@ -1243,12 +1605,29 @@ class AgentVariantsOrchestrator {
1243
1605
  if (args.requestId) {
1244
1606
  this.store.assignVariantRequestId(sessionId, variantIds, args.requestId);
1245
1607
  }
1608
+ if (args.sourceVariantId) {
1609
+ this.telemetry.trackAgentVariantsRefinementRequested?.({
1610
+ sessionId,
1611
+ requestId: args.requestId,
1612
+ entryPoint: 'mcp_tool',
1613
+ mode: 'vary',
1614
+ projectContextKind: projectContext.kind,
1615
+ targetVariantId: args.sourceVariantId,
1616
+ sourceVariantId: args.sourceVariantId,
1617
+ requestedCount: count,
1618
+ instructionLength: args.prompt.length,
1619
+ });
1620
+ }
1246
1621
  const variants = variantIds.map((workItemId, i) => ({
1247
1622
  variantId: workItemId,
1248
1623
  briefId: briefs[i].briefId,
1249
1624
  label: briefs[i].label,
1250
1625
  status: 'pending',
1251
1626
  }));
1627
+ this.recordCurrentVariantsRoundWorkItems({
1628
+ sessionId,
1629
+ workItemIds: variantIds,
1630
+ });
1252
1631
  let leaseId;
1253
1632
  let leaseTtlMs;
1254
1633
  let leasedWorkItems;
@@ -1384,6 +1763,16 @@ class AgentVariantsOrchestrator {
1384
1763
  (workItemKind === 'static_preview' ||
1385
1764
  workItemKind === 'refine_variant') &&
1386
1765
  !parseStaticPreviewOutput(normalizeOutput(args.output))) {
1766
+ const telemetry = this.refinementTelemetryForWorkItem({
1767
+ sessionId: args.sessionId,
1768
+ workItemId: args.workItemId,
1769
+ leaseId: args.leaseId,
1770
+ requestStatus: 'failed',
1771
+ failureReason: 'schema_validation_failed',
1772
+ });
1773
+ if (telemetry) {
1774
+ this.telemetry.trackAgentVariantsRefinementFailed?.(telemetry);
1775
+ }
1387
1776
  throw new errors_1.AgentVariantsError('SCHEMA_VALIDATION_FAILED', `${workItemKind} report_variant_complete requires output.html (string, non-empty). ` +
1388
1777
  'Pass the full HTML inline as output: { html: "<!doctype html>...", css?: "...", js?: "..." }. ' +
1389
1778
  'Do NOT write the HTML to a file and report a file list — Rivet renders the HTML inline; on-disk files are not read.');
@@ -1438,7 +1827,23 @@ class AgentVariantsOrchestrator {
1438
1827
  };
1439
1828
  }
1440
1829
  }
1441
- const result = this.store.reportComplete(effectiveArgs);
1830
+ let result;
1831
+ try {
1832
+ result = this.store.reportComplete(effectiveArgs);
1833
+ }
1834
+ catch (error) {
1835
+ const telemetry = this.refinementTelemetryForWorkItem({
1836
+ sessionId: args.sessionId,
1837
+ workItemId: args.workItemId,
1838
+ leaseId: args.leaseId,
1839
+ requestStatus: 'failed',
1840
+ failureReason: error,
1841
+ });
1842
+ if (telemetry) {
1843
+ this.telemetry.trackAgentVariantsRefinementFailed?.(telemetry);
1844
+ }
1845
+ throw error;
1846
+ }
1442
1847
  this.emitChange();
1443
1848
  // Per-variant telemetry on terminal item statuses (skip 'running'
1444
1849
  // heartbeats and the brief work item — only code_gen / scaffold_base
@@ -1471,16 +1876,45 @@ class AgentVariantsOrchestrator {
1471
1876
  model: args.model ?? null,
1472
1877
  outputBytes,
1473
1878
  });
1879
+ const refinementTelemetry = this.refinementTelemetryForWorkItem({
1880
+ sessionId: args.sessionId,
1881
+ workItemId: args.workItemId,
1882
+ leaseId: args.leaseId,
1883
+ requestStatus: effectiveArgs.status === 'succeeded' ? 'completed' : 'failed',
1884
+ durationMs: durationMs ?? undefined,
1885
+ failureReason: effectiveArgs.error?.code,
1886
+ });
1887
+ if (refinementTelemetry) {
1888
+ const counts = {
1889
+ completedCount: effectiveArgs.status === 'succeeded' ? 1 : 0,
1890
+ failedCount: effectiveArgs.status === 'failed' ? 1 : 0,
1891
+ cancelledCount: effectiveArgs.status === 'cancelled' ? 1 : 0,
1892
+ resultVariantCount: effectiveArgs.status === 'succeeded' ? 1 : 0,
1893
+ };
1894
+ if (effectiveArgs.status === 'succeeded') {
1895
+ this.telemetry.trackAgentVariantsRefinementCompleted?.({
1896
+ ...refinementTelemetry,
1897
+ ...counts,
1898
+ });
1899
+ }
1900
+ else {
1901
+ this.telemetry.trackAgentVariantsRefinementFailed?.({
1902
+ ...refinementTelemetry,
1903
+ ...counts,
1904
+ });
1905
+ }
1906
+ }
1474
1907
  }
1908
+ this.completeTerminalVariantsRounds(args.sessionId);
1475
1909
  if (contracts_1.TERMINAL_STAGES.has(result.stage)) {
1476
1910
  const resources = this.resources.get(args.sessionId);
1911
+ const summary = result.summary ?? this.store.getSummary(args.sessionId);
1477
1912
  if (resources && resources.terminalAt === undefined) {
1478
1913
  resources.terminalAt = Date.now();
1479
1914
  const totalLatencyMs = resources.terminalAt - resources.startedAt;
1480
1915
  const approveToTerminalMs = resources.approveStartedAt !== undefined
1481
1916
  ? resources.terminalAt - resources.approveStartedAt
1482
1917
  : null;
1483
- const summary = result.summary ?? this.store.getSummary(args.sessionId);
1484
1918
  this.telemetry.track('agent_variants.terminal_state', {
1485
1919
  source: 'mcp',
1486
1920
  sessionId: args.sessionId,
@@ -1493,6 +1927,19 @@ class AgentVariantsOrchestrator {
1493
1927
  projectContextKind: this.store.getProjectContext(args.sessionId).kind,
1494
1928
  });
1495
1929
  }
1930
+ if (resources) {
1931
+ this.completePendingVariantsRounds({
1932
+ sessionId: args.sessionId,
1933
+ requestStatus: result.stage === 'cancelled'
1934
+ ? 'cancelled'
1935
+ : result.stage === 'failed'
1936
+ ? 'failed'
1937
+ : result.stage === 'degraded'
1938
+ ? 'degraded'
1939
+ : 'completed',
1940
+ summary,
1941
+ });
1942
+ }
1496
1943
  }
1497
1944
  if (effectiveArgs.status === 'succeeded' &&
1498
1945
  workItemKind !== 'refine_variant') {
@@ -1524,6 +1971,11 @@ class AgentVariantsOrchestrator {
1524
1971
  reason: args.reason ?? null,
1525
1972
  fromStage: stageBefore,
1526
1973
  });
1974
+ this.completePendingVariantsRounds({
1975
+ sessionId: args.sessionId,
1976
+ requestStatus: 'cancelled',
1977
+ summary: this.store.getSummary(args.sessionId),
1978
+ });
1527
1979
  this.emitChange();
1528
1980
  void this.markPersistedVariantsCancelled(args.sessionId).catch((err) => {
1529
1981
  log.warn(`markPersistedVariantsCancelled failed for ${args.sessionId}`, err);
@@ -1657,6 +2109,16 @@ class AgentVariantsOrchestrator {
1657
2109
  try {
1658
2110
  return await run;
1659
2111
  }
2112
+ catch (error) {
2113
+ this.telemetry.trackAgentVariantsCommitFailed?.({
2114
+ sessionId: args.sessionId,
2115
+ targetVariantId: args.variantId,
2116
+ mode: 'commit',
2117
+ requestStatus: 'failed',
2118
+ failureReason: error,
2119
+ });
2120
+ throw error;
2121
+ }
1660
2122
  finally {
1661
2123
  if (this.inflightCommits.get(args.sessionId) === run) {
1662
2124
  this.inflightCommits.delete(args.sessionId);
@@ -4028,6 +4490,8 @@ class AgentVariantsOrchestrator {
4028
4490
  cleanupStarted: false,
4029
4491
  committedVariantIds: new Set(),
4030
4492
  startedAt: Date.now(),
4493
+ nextRoundIndex: 0,
4494
+ rounds: new Map(),
4031
4495
  leasedAt: new Map(),
4032
4496
  qaResults: new Map(),
4033
4497
  qaRegenRetried: new Set(),