rivet-design 0.27.0 → 0.27.1

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 (65) hide show
  1. package/dist/agent-variants/DirectionRefReservations.d.ts +11 -0
  2. package/dist/agent-variants/DirectionRefReservations.js +47 -0
  3. package/dist/agent-variants/SessionStore.d.ts +10 -1
  4. package/dist/agent-variants/SessionStore.js +25 -2
  5. package/dist/agent-variants/WorkItemRequestTimes.d.ts +6 -0
  6. package/dist/agent-variants/WorkItemRequestTimes.js +21 -0
  7. package/dist/agent-variants/WorktreeOrchestrator.d.ts +2 -1
  8. package/dist/agent-variants/WorktreeOrchestrator.js +92 -78
  9. package/dist/agent-variants/contracts.d.ts +4 -0
  10. package/dist/agent-variants/existingStaticEntry.d.ts +34 -0
  11. package/dist/agent-variants/existingStaticEntry.js +136 -0
  12. package/dist/agent-variants/staticPreviewFiles.js +1 -1
  13. package/dist/agent-variants/variant-project-runtime.d.ts +2 -1
  14. package/dist/agent-variants/variantsTelemetry.d.ts +4 -0
  15. package/dist/agent-variants/variantsTelemetry.js +2 -0
  16. package/dist/agent-variants/workItemInput.d.ts +22 -0
  17. package/dist/agent-variants/workItemInput.js +12 -1
  18. package/dist/cli/commands/directionTarget.d.ts +23 -0
  19. package/dist/cli/commands/directionTarget.js +87 -0
  20. package/dist/cli/commands/open.js +28 -4
  21. package/dist/cli/commands/variants.js +36 -43
  22. package/dist/cli/envelope.d.ts +1 -1
  23. package/dist/cli/envelope.js +1 -0
  24. package/dist/cli/projectRuntimeUpgrade.d.ts +11 -0
  25. package/dist/cli/projectRuntimeUpgrade.js +43 -11
  26. package/dist/config/pluginMetrics.js +2 -0
  27. package/dist/mcp/explorationSchema.js +1 -1
  28. package/dist/mcp/getExploration.js +11 -5
  29. package/dist/proxy-middleware/proxy-config.js +7 -0
  30. package/dist/routes/agentVariants.js +4 -0
  31. package/dist/routes/cli.js +10 -1
  32. package/dist/server.js +12 -6
  33. package/dist/services/ProjectLibrary.d.ts +4 -1
  34. package/dist/services/ProjectLibrary.js +14 -9
  35. package/dist/services/ProjectRuntimeService.d.ts +8 -0
  36. package/dist/services/ProjectRuntimeService.js +15 -2
  37. package/dist/services/TelemetryService.d.ts +5 -0
  38. package/dist/services/TelemetryService.js +19 -0
  39. package/dist/services/VariantHistoryService.d.ts +8 -0
  40. package/dist/services/VariantHistoryService.js +40 -0
  41. package/dist/services/WorktreeManager.d.ts +1 -0
  42. package/dist/services/WorktreeManager.js +12 -0
  43. package/dist/services/createAgentVariantsOrchestrator.js +9 -2
  44. package/dist/services/directionRefs.d.ts +21 -0
  45. package/dist/services/directionRefs.js +148 -0
  46. package/dist/services/projectDirections.d.ts +22 -0
  47. package/dist/services/projectDirections.js +38 -0
  48. package/dist/types/direction-ref.d.ts +36 -0
  49. package/dist/types/direction-ref.js +3 -0
  50. package/dist/types/variant-history.d.ts +3 -1
  51. package/dist/utils/skills/cli-guidance.js +4 -3
  52. package/dist/utils/subprocessEnvironment.d.ts +1 -1
  53. package/dist/utils/subprocessEnvironment.js +0 -1
  54. package/package.json +3 -3
  55. package/src/ui/dist/assets/LibraryEntry-BZ5EdFgA.js +37 -0
  56. package/src/ui/dist/assets/main-MepMmTwb.css +1 -0
  57. package/src/ui/dist/assets/main-RriU35pI.js +497 -0
  58. package/src/ui/dist/index.html +2 -2
  59. package/dist/services/StaticPreviewServer.d.ts +0 -8
  60. package/dist/services/StaticPreviewServer.js +0 -207
  61. package/src/ui/dist/assets/LibraryEntry-RI9Lc7P3.js +0 -37
  62. package/src/ui/dist/assets/main-D0UmAaUe.css +0 -1
  63. package/src/ui/dist/assets/main-DgrLzS5j.js +0 -497
  64. package/src/ui/dist/fonts/Goldman-Bold.woff2 +0 -0
  65. package/src/ui/dist/fonts/Goldman-Regular.woff2 +0 -0
@@ -0,0 +1,11 @@
1
+ import type { VariantHistoryService } from '../services/VariantHistoryService';
2
+ import type { DirectionRef } from '../types/direction-ref';
3
+ export declare class DirectionRefReservations {
4
+ private readonly taken;
5
+ reserve(label: string): DirectionRef;
6
+ load(args: {
7
+ projectPath: string;
8
+ history: VariantHistoryService;
9
+ }): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=DirectionRefReservations.d.ts.map
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DirectionRefReservations = void 0;
4
+ const directionRefs_1 = require("../services/directionRefs");
5
+ const projectDirections_1 = require("../services/projectDirections");
6
+ const logger_1 = require("../utils/logger");
7
+ const log = (0, logger_1.createLogger)('DirectionRefReservations');
8
+ class DirectionRefReservations {
9
+ taken = new Set();
10
+ reserve(label) {
11
+ const directionRef = (0, directionRefs_1.nextDirectionRef)({ label, taken: this.taken });
12
+ this.taken.add(directionRef);
13
+ return directionRef;
14
+ }
15
+ async load(args) {
16
+ let directions;
17
+ try {
18
+ directions = await (0, projectDirections_1.listProjectDirections)({
19
+ kind: 'history',
20
+ history: args.history,
21
+ projectPath: args.projectPath,
22
+ });
23
+ }
24
+ catch (error) {
25
+ log.warn('Direction ref history could not be listed', error);
26
+ return;
27
+ }
28
+ for (const direction of directions) {
29
+ this.taken.add(direction.directionRef);
30
+ if (direction.manifest.directionRef)
31
+ continue;
32
+ try {
33
+ await args.history.assignDirectionRef({
34
+ projectPath: direction.projectPath,
35
+ sessionId: direction.manifest.sessionId,
36
+ variantId: direction.manifest.variantId,
37
+ directionRef: direction.directionRef,
38
+ });
39
+ }
40
+ catch (error) {
41
+ log.warn(`Direction ref backfill failed for ${direction.manifest.sessionId}:${direction.manifest.variantId}`, error);
42
+ }
43
+ }
44
+ }
45
+ }
46
+ exports.DirectionRefReservations = DirectionRefReservations;
47
+ //# sourceMappingURL=DirectionRefReservations.js.map
@@ -2,6 +2,8 @@ import type { GuidanceDocument } from '../types/guidance';
2
2
  import type { WorkerSelection } from '../types/change-request-types';
3
3
  import { type VariantReference } from '../types/variant-reference';
4
4
  import { type Brief, type ActiveVariantSnapshot, type LeasedWorkItemDescriptor, type ProjectContext, type Stage, type StartVariantsBriefContent, type StaticPreviewTargetElement, type Target, type TerminalSummary, type VariantContextBinding, type VariantContextBundle, type VariantQaResult, type VariantWorkItemContext, type WorkItem, type WorkItemKind, type WorkItemStatus, type WorkerFidelity, type WorkerRuntimeInfo } from './contracts';
5
+ import { DirectionRefReservations } from './DirectionRefReservations';
6
+ import type { DirectionRef } from '../types/direction-ref';
5
7
  import { type VariantWorkItemInput, type VariantWorkItemInputByKind, type VariantWorkItemKind } from './workItemInput';
6
8
  export declare const DEFAULT_LEASE_TTL_MS: number;
7
9
  export declare const SCAFFOLD_LEASE_TTL_MS: number;
@@ -60,7 +62,8 @@ export declare const buildImageRefs: (artifacts: ReadonlyArray<{
60
62
  export declare class SessionStore {
61
63
  private readonly sessions;
62
64
  private readonly clock;
63
- constructor(clock?: SessionStoreClock);
65
+ readonly directionRefs: DirectionRefReservations;
66
+ constructor(clock?: SessionStoreClock, directionRefs?: DirectionRefReservations);
64
67
  propose(args: ProposeArgs): ProposeResult;
65
68
  reportBriefs(args: {
66
69
  sessionId: string;
@@ -163,6 +166,7 @@ export declare class SessionStore {
163
166
  references?: VariantReference[];
164
167
  previewRoutes?: string[];
165
168
  runLabel?: string;
169
+ sourceDirectionRef?: DirectionRef;
166
170
  }): {
167
171
  workItemId: string;
168
172
  briefId: string;
@@ -180,12 +184,17 @@ export declare class SessionStore {
180
184
  references?: VariantReference[];
181
185
  previewRoutes?: string[];
182
186
  runLabel?: string;
187
+ sourceDirectionRef?: DirectionRef;
183
188
  projectContext: ProjectContext;
184
189
  }): {
185
190
  sessionId: string;
186
191
  workItemId: string;
187
192
  briefId: string;
188
193
  };
194
+ claimDirectionRef(args: {
195
+ sessionId: string;
196
+ workItemId: string;
197
+ }): DirectionRef;
189
198
  private findAdoptedVariant;
190
199
  assignVariantPreviewRoutes(args: {
191
200
  sessionId: string;
@@ -7,6 +7,7 @@ const crypto_1 = require("crypto");
7
7
  const errors_1 = require("./errors");
8
8
  const contracts_1 = require("./contracts");
9
9
  const briefContent_1 = require("./briefContent");
10
+ const DirectionRefReservations_1 = require("./DirectionRefReservations");
10
11
  const runLabel_1 = require("./runLabel");
11
12
  const runPlan_1 = require("./runPlan");
12
13
  const workItemInput_1 = require("./workItemInput");
@@ -185,8 +186,10 @@ const resolveVariantWorkItemContext = (args) => {
185
186
  class SessionStore {
186
187
  sessions = new Map();
187
188
  clock;
188
- constructor(clock = SYSTEM_CLOCK) {
189
+ directionRefs;
190
+ constructor(clock = SYSTEM_CLOCK, directionRefs = new DirectionRefReservations_1.DirectionRefReservations()) {
189
191
  this.clock = clock;
192
+ this.directionRefs = directionRefs;
190
193
  }
191
194
  propose(args) {
192
195
  const sessionId = args.sessionId ?? (0, crypto_1.randomUUID)();
@@ -345,6 +348,7 @@ class SessionStore {
345
348
  input: {
346
349
  briefId: brief.briefId,
347
350
  briefLabel: brief.label,
351
+ directionRef: this.directionRefs.reserve(brief.label),
348
352
  briefBody: sel.bodyOverride ?? brief.body,
349
353
  instruction: session.prompt,
350
354
  guidance: session.guidance,
@@ -376,6 +380,7 @@ class SessionStore {
376
380
  input: {
377
381
  briefId: brief.briefId,
378
382
  briefLabel: brief.label,
383
+ directionRef: this.directionRefs.reserve(brief.label),
379
384
  briefBody: sel.bodyOverride ?? brief.body,
380
385
  instruction: session.prompt,
381
386
  guidance: session.guidance,
@@ -582,6 +587,7 @@ class SessionStore {
582
587
  guidance: args.guidance ?? [],
583
588
  briefId: targetInput.briefId,
584
589
  briefLabel: targetInput.briefLabel,
590
+ ...(0, workItemInput_1.shownDirectionRef)(targetInput),
585
591
  briefBody: targetInput.briefBody,
586
592
  references: targetInput.references,
587
593
  ...(targetInput.briefNotes
@@ -660,6 +666,7 @@ class SessionStore {
660
666
  },
661
667
  }
662
668
  : sourceInput.context;
669
+ const briefLabel = brief?.label ?? `${labelBase}${suffix}`;
663
670
  const item = {
664
671
  id: (0, crypto_1.randomUUID)(),
665
672
  kind: 'static_preview',
@@ -668,7 +675,8 @@ class SessionStore {
668
675
  dependsOn: [],
669
676
  input: {
670
677
  briefId: `${sourceInput.briefId ?? 'v'}-vary-${(0, crypto_1.randomUUID)().slice(0, 8)}`,
671
- briefLabel: brief?.label ?? `${labelBase}${suffix}`,
678
+ briefLabel,
679
+ directionRef: this.directionRefs.reserve(briefLabel),
672
680
  briefBody: brief?.body ?? prettyInstruction,
673
681
  ...(brief?.notes ? { briefNotes: brief.notes } : {}),
674
682
  ...(previewRoutes.length ? { previewRoutes } : {}),
@@ -757,6 +765,7 @@ class SessionStore {
757
765
  input: {
758
766
  briefId: brief.briefId,
759
767
  briefLabel: brief.label,
768
+ directionRef: this.directionRefs.reserve(brief.label),
760
769
  briefBody: brief.body,
761
770
  references: (0, variant_reference_1.mergeVariantReferences)(sourceInput?.references, context?.references),
762
771
  instruction: args.instruction,
@@ -815,6 +824,9 @@ class SessionStore {
815
824
  input: {
816
825
  briefId,
817
826
  briefLabel: args.label,
827
+ ...(args.sourceDirectionRef
828
+ ? { sourceDirectionRef: args.sourceDirectionRef }
829
+ : {}),
818
830
  ...(args.description ? { briefBody: args.description } : {}),
819
831
  ...(args.runLabel ? { runLabel: args.runLabel } : {}),
820
832
  adoptedFrom: { ...args.source },
@@ -854,6 +866,7 @@ class SessionStore {
854
866
  references: args.references,
855
867
  previewRoutes: args.previewRoutes,
856
868
  runLabel: args.runLabel,
869
+ sourceDirectionRef: args.sourceDirectionRef,
857
870
  });
858
871
  return {
859
872
  sessionId,
@@ -861,6 +874,15 @@ class SessionStore {
861
874
  briefId: adopted.briefId,
862
875
  };
863
876
  }
877
+ claimDirectionRef(args) {
878
+ const item = this.requireWorkItem(this.requireSession(args.sessionId), args.workItemId);
879
+ if (!(0, workItemInput_1.isVariantWorkItem)(item))
880
+ throw new errors_1.AgentVariantsError('WORK_ITEM_NOT_FOUND', `Work item ${item.id} is a ${item.kind} work item, not a direction`);
881
+ const directionRef = item.input.directionRef ??
882
+ this.directionRefs.reserve(item.input.briefLabel ?? '');
883
+ item.input.directionRef = directionRef;
884
+ return directionRef;
885
+ }
864
886
  findAdoptedVariant(session, source) {
865
887
  for (const item of session.workItems.values()) {
866
888
  if (item.removed || !(0, workItemInput_1.isVariantWorkItem)(item))
@@ -1427,6 +1449,7 @@ class SessionStore {
1427
1449
  ? { previewRoutes: [...input.previewRoutes] }
1428
1450
  : {}),
1429
1451
  briefId: input.briefId ?? '',
1452
+ ...(0, workItemInput_1.shownDirectionRef)(input),
1430
1453
  label: input.briefLabel ?? 'Variant',
1431
1454
  references: input.references,
1432
1455
  status: item.status,
@@ -0,0 +1,6 @@
1
+ export declare class WorkItemRequestTimes {
2
+ private readonly requestedAt;
3
+ record(workItemIds: readonly string[], requestedAt: number): void;
4
+ elapsedSinceRequestMs(workItemId: string, at: number | undefined): number | null;
5
+ }
6
+ //# sourceMappingURL=WorkItemRequestTimes.d.ts.map
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkItemRequestTimes = void 0;
4
+ class WorkItemRequestTimes {
5
+ requestedAt = new Map();
6
+ record(workItemIds, requestedAt) {
7
+ for (const workItemId of workItemIds) {
8
+ if (!this.requestedAt.has(workItemId)) {
9
+ this.requestedAt.set(workItemId, requestedAt);
10
+ }
11
+ }
12
+ }
13
+ elapsedSinceRequestMs(workItemId, at) {
14
+ const requestedAt = this.requestedAt.get(workItemId);
15
+ if (requestedAt === undefined || at === undefined)
16
+ return null;
17
+ return at - requestedAt;
18
+ }
19
+ }
20
+ exports.WorkItemRequestTimes = WorkItemRequestTimes;
21
+ //# sourceMappingURL=WorkItemRequestTimes.js.map
@@ -4,7 +4,7 @@ import type { VariantStartRequest, VariantStartResult } from './variant-start-ty
4
4
  import { AgentVariantsError } from './errors';
5
5
  import { SessionStore, type ApprovedBriefSelection, type ApproveResult, type ProposeArgs, type ProposeResult, type ReportCompleteResult, type RequestWorkResult } from './SessionStore';
6
6
  import type { ActiveProjectContext, AdoptPastVariantArgs, BootstrapPastVariantSessionArgs, BootstrapPastVariantSessionResult, ActiveVariantSnapshot, Brief, ProjectContext, Stage, TerminalSummary, VariantContextBinding, HostVariantWorkItemSnapshot, VariantQaResult, WorkItemStatus } from './contracts';
7
- import type { VariantWorkItemInput } from './workItemInput';
7
+ import { type VariantWorkItemInput } from './workItemInput';
8
8
  import { VariantHistoryService } from '../services/VariantHistoryService';
9
9
  import type { MCPVariantsTelemetryMetadata } from '../services/MCPVariantsTelemetry';
10
10
  import type { ProjectEnvironment, WorktreeManagerLike } from './variant-project-runtime';
@@ -249,6 +249,7 @@ export declare class AgentVariantsOrchestrator {
249
249
  private readonly pendingHistoryPersists;
250
250
  private trackHistoryPersist;
251
251
  settleHistoryPersists(): Promise<void>;
252
+ loadDirectionRefs(): Promise<void>;
252
253
  private getSavedVariant;
253
254
  isHistoryDurableForRestart(isForced?: boolean): Promise<boolean>;
254
255
  private persistCompletedExistingVariant;
@@ -8,6 +8,7 @@ const workItemContextFiles_1 = require("./workItemContextFiles");
8
8
  const staticPreviewFiles_1 = require("./staticPreviewFiles");
9
9
  const workItemPreviewRoutes_1 = require("./workItemPreviewRoutes");
10
10
  const staticPreviewRefinements_1 = require("./staticPreviewRefinements");
11
+ const WorkItemRequestTimes_1 = require("./WorkItemRequestTimes");
11
12
  const crypto_1 = require("crypto");
12
13
  const events_1 = require("events");
13
14
  const fs_1 = __importDefault(require("fs"));
@@ -20,6 +21,7 @@ const workItemBriefing_1 = require("./workItemBriefing");
20
21
  const briefContent_1 = require("./briefContent");
21
22
  const runLabel_1 = require("./runLabel");
22
23
  const previewQa_1 = require("./previewQa");
24
+ const workItemInput_1 = require("./workItemInput");
23
25
  const WorkspaceInventory_1 = require("./WorkspaceInventory");
24
26
  const WorkspaceProvisioning_1 = require("./WorkspaceProvisioning");
25
27
  const PreviewRuntime_1 = require("./PreviewRuntime");
@@ -31,6 +33,7 @@ const variantsTelemetry_1 = require("./variantsTelemetry");
31
33
  const variantWorkspaceFiles_1 = require("./variantWorkspaceFiles");
32
34
  const errorMessage_1 = require("../utils/errorMessage");
33
35
  const pathContainment_1 = require("../utils/pathContainment");
36
+ const existingStaticEntry_1 = require("./existingStaticEntry");
34
37
  var variantWorkspaceFiles_2 = require("./variantWorkspaceFiles");
35
38
  Object.defineProperty(exports, "buildStaticPreviewDocument", { enumerable: true, get: function () { return variantWorkspaceFiles_2.buildStaticPreviewDocument; } });
36
39
  const log = (0, logger_1.createLogger)('AgentVariantsOrchestrator');
@@ -426,6 +429,7 @@ class AgentVariantsOrchestrator {
426
429
  leaseExpiresAt: item.leaseExpiresAt,
427
430
  workspace,
428
431
  mode,
432
+ ...(0, workItemInput_1.shownDirectionRef)(input),
429
433
  direction: {
430
434
  label: input.briefLabel ?? 'Variant',
431
435
  brief: input.briefBody ?? input.instruction ?? 'Create this variant',
@@ -487,6 +491,7 @@ class AgentVariantsOrchestrator {
487
491
  resources.currentRoundStartedAt = startedAt;
488
492
  resources.currentRoundMode = args.mode;
489
493
  resources.currentRoundWorkItemIds = workItemIds;
494
+ resources.requestTimes.record(workItemIds ?? [], startedAt);
490
495
  const projectContext = this.store.getProjectContext(args.sessionId);
491
496
  this.telemetry.trackAgentVariantsRoundStarted?.({
492
497
  sessionId: args.sessionId,
@@ -565,6 +570,7 @@ class AgentVariantsOrchestrator {
565
570
  const workItemIds = [...args.workItemIds];
566
571
  round.workItemIds = workItemIds;
567
572
  resources.currentRoundWorkItemIds = workItemIds;
573
+ resources.requestTimes.record(workItemIds, round.startedAt);
568
574
  this.completeTerminalVariantsRounds(args.sessionId);
569
575
  }
570
576
  completeTerminalVariantsRounds(sessionId) {
@@ -646,6 +652,8 @@ class AgentVariantsOrchestrator {
646
652
  };
647
653
  }
648
654
  trackRefinementLeased(args) {
655
+ const requestTimes = this.resources.get(args.sessionId)?.requestTimes;
656
+ const leasedAt = Date.now();
649
657
  for (const item of args.lease.leasedWorkItems) {
650
658
  const telemetry = this.refinementTelemetryForWorkItem({
651
659
  sessionId: args.sessionId,
@@ -657,6 +665,7 @@ class AgentVariantsOrchestrator {
657
665
  this.telemetry.trackAgentVariantsRefinementLeased?.({
658
666
  ...telemetry,
659
667
  leaseDurationMs: args.lease.leaseTtlMs,
668
+ queueWaitMs: requestTimes?.elapsedSinceRequestMs(item.id, leasedAt) ?? undefined,
660
669
  workItemCount: 1,
661
670
  });
662
671
  }
@@ -788,13 +797,16 @@ class AgentVariantsOrchestrator {
788
797
  }
789
798
  }
790
799
  beginStaticPreviewRefinements(args) {
791
- return (0, staticPreviewRefinements_1.createStaticPreviewRefinements)({
800
+ const result = (0, staticPreviewRefinements_1.createStaticPreviewRefinements)({
792
801
  request: args,
793
802
  store: this.store,
794
803
  telemetry: this.telemetry,
795
804
  getStaticPreviewHtml: (sessionId, workItemId) => this.getStaticPreviewHtml(sessionId, workItemId),
796
805
  emitChange: () => this.emitChange(),
797
806
  });
807
+ const requestTimes = this.resources.get(args.sessionId)?.requestTimes;
808
+ requestTimes?.record(result.createdWorkItemIds, Date.now());
809
+ return result;
798
810
  }
799
811
  async adoptPastVariant(args) {
800
812
  const { assetBase, entryPath, hasAssets } = await (0, staticPreviewFiles_1.resolveStaticPreviewFiles)({
@@ -810,6 +822,7 @@ class AgentVariantsOrchestrator {
810
822
  references: args.references,
811
823
  previewRoutes: args.previewRoutes,
812
824
  runLabel: args.runLabel,
825
+ sourceDirectionRef: args.directionRef,
813
826
  });
814
827
  this.telemetry.trackAgentVariantsRequestStarted?.({
815
828
  sessionId: args.sessionId,
@@ -859,6 +872,7 @@ class AgentVariantsOrchestrator {
859
872
  references: args.references,
860
873
  previewRoutes: args.previewRoutes,
861
874
  runLabel: args.runLabel,
875
+ directionRef: args.directionRef,
862
876
  });
863
877
  return {
864
878
  sessionId: usableSessionId,
@@ -880,6 +894,7 @@ class AgentVariantsOrchestrator {
880
894
  references: args.references,
881
895
  previewRoutes: args.previewRoutes,
882
896
  runLabel: args.runLabel,
897
+ sourceDirectionRef: args.directionRef,
883
898
  projectContext: args.projectContext,
884
899
  });
885
900
  this.activeSessionId = created.sessionId;
@@ -1548,6 +1563,8 @@ class AgentVariantsOrchestrator {
1548
1563
  const durationMs = leasedAt !== undefined ? Date.now() - leasedAt : null;
1549
1564
  const approveStartedAt = resources?.approveStartedAt;
1550
1565
  const approveToCompleteMs = approveStartedAt !== undefined ? Date.now() - approveStartedAt : null;
1566
+ const requestTimes = resources?.requestTimes;
1567
+ const elapsedSinceRequestMs = (at) => requestTimes?.elapsedSinceRequestMs(args.workItemId, at) ?? null;
1551
1568
  const outputBytes = (0, variantWorkspaceFiles_1.estimateOutputBytes)(effectiveArgs.output);
1552
1569
  const projectContextKind = this.store.getProjectContext(args.sessionId).kind;
1553
1570
  const mode = workItemKind !== undefined && isImplementationWorkItemKind(workItemKind)
@@ -1563,6 +1580,8 @@ class AgentVariantsOrchestrator {
1563
1580
  attempt: args.attempt,
1564
1581
  durationMs,
1565
1582
  approveToCompleteMs,
1583
+ requestToCompleteMs: elapsedSinceRequestMs(Date.now()),
1584
+ queueWaitMs: elapsedSinceRequestMs(leasedAt),
1566
1585
  kind: workItemKind ?? null,
1567
1586
  mode,
1568
1587
  leaseToReportMs: leasedAt !== undefined ? reportReceivedAt - leasedAt : null,
@@ -2094,12 +2113,24 @@ class AgentVariantsOrchestrator {
2094
2113
  catch (err) {
2095
2114
  log.warn(`getDiff failed for ${record.worktreePath}`, err);
2096
2115
  }
2116
+ const staticEntryResolution = isFresh
2117
+ ? Promise.resolve(undefined)
2118
+ : (0, existingStaticEntry_1.resolveExistingStaticPreviewEntry)({
2119
+ sessionId,
2120
+ record,
2121
+ resolveEnv: this.resolveEnv,
2122
+ worktrees: this.worktrees,
2123
+ telemetry: this.telemetry,
2124
+ });
2097
2125
  if (!isFresh) {
2098
- this.trackHistoryPersist(this.persistCompletedExistingVariant({
2126
+ this.trackHistoryPersist(staticEntryResolution
2127
+ .then((staticEntry) => this.persistCompletedExistingVariant({
2099
2128
  sessionId,
2100
2129
  workItemId,
2101
2130
  diff: record.diff ?? '',
2102
- }).catch((err) => {
2131
+ staticEntry,
2132
+ }))
2133
+ .catch((err) => {
2103
2134
  log.warn(`persistCompletedExistingVariant failed for ${sessionId}/${workItemId}`, err);
2104
2135
  }));
2105
2136
  }
@@ -2111,12 +2142,11 @@ class AgentVariantsOrchestrator {
2111
2142
  log.warn(`persistCompletedArtifactVariant failed for ${sessionId}/${workItemId}`, err);
2112
2143
  }));
2113
2144
  }
2114
- if (!isFresh) {
2115
- const staticPreview = await this.registerExistingStaticPreview(sessionId, workItemId, record);
2116
- if (staticPreview !== 'not_static') {
2117
- this.emitChange();
2118
- return;
2119
- }
2145
+ const staticEntry = await staticEntryResolution;
2146
+ if (staticEntry) {
2147
+ await this.registerExistingStaticPreview(sessionId, workItemId, staticEntry);
2148
+ this.emitChange();
2149
+ return;
2120
2150
  }
2121
2151
  await this.previewRuntime.startVariant({
2122
2152
  sessionId,
@@ -2224,6 +2254,12 @@ class AgentVariantsOrchestrator {
2224
2254
  await Promise.allSettled([...this.pendingHistoryPersists]);
2225
2255
  }
2226
2256
  }
2257
+ loadDirectionRefs() {
2258
+ return this.store.directionRefs.load({
2259
+ projectPath: this.getProjectPath(),
2260
+ history: this.variantHistory,
2261
+ });
2262
+ }
2227
2263
  async getSavedVariant(args) {
2228
2264
  const saved = await this.variantHistory.getVariant(args);
2229
2265
  if (saved)
@@ -2297,16 +2333,9 @@ class AgentVariantsOrchestrator {
2297
2333
  return;
2298
2334
  }
2299
2335
  const record = this.workspaceInventory.getWorktree(args.sessionId, args.workItemId);
2300
- let sourceDir;
2301
- const staticEntryPath = env.framework === 'static' ? env.entryPath : undefined;
2302
- if (env.framework === 'static' && record) {
2303
- try {
2304
- sourceDir = await this.worktrees.getProjectCwdInWorktree(record.worktreePath);
2305
- }
2306
- catch (err) {
2307
- log.warn(`persistCompletedExistingVariant: static snapshot path failed for ${args.sessionId}/${args.workItemId}`, err);
2308
- }
2309
- }
2336
+ const staticSource = args.staticEntry?.kind === 'found' ? args.staticEntry : undefined;
2337
+ const sourceDir = staticSource?.projectDirectory;
2338
+ const staticEntryPath = staticSource?.entryPath;
2310
2339
  const input = this.store.requireVariantWorkItemInput({
2311
2340
  sessionId: args.sessionId,
2312
2341
  workItemId: args.workItemId,
@@ -2333,7 +2362,7 @@ class AgentVariantsOrchestrator {
2333
2362
  recipe: (0, variantWorkspaceFiles_1.buildServeRecipeFromResolved)(record.worktreePath, runningPreview.command, runningPreview.port),
2334
2363
  };
2335
2364
  }
2336
- else if (record) {
2365
+ else if (record && env.framework !== 'static') {
2337
2366
  try {
2338
2367
  const dev = await this.previewRuntime.resolveCommand(args.sessionId, record.worktreePath, RECIPE_PORT_SENTINEL, false);
2339
2368
  serve = {
@@ -2350,6 +2379,7 @@ class AgentVariantsOrchestrator {
2350
2379
  sessionId: args.sessionId,
2351
2380
  variantId: args.workItemId,
2352
2381
  ...(input.requestId ? { requestId: input.requestId } : {}),
2382
+ directionRef: this.store.claimDirectionRef(args),
2353
2383
  label: input.briefLabel,
2354
2384
  brief: input.briefBody,
2355
2385
  references: input.references,
@@ -2380,92 +2410,74 @@ class AgentVariantsOrchestrator {
2380
2410
  : {}),
2381
2411
  });
2382
2412
  }
2383
- async registerExistingStaticPreview(sessionId, workItemId, record) {
2384
- let env;
2385
- try {
2386
- env = await this.resolveEnv(sessionId);
2387
- }
2388
- catch (err) {
2389
- log.warn(`registerExistingStaticPreview: resolveEnv failed for ${sessionId}`, err);
2390
- return 'not_static';
2391
- }
2392
- if (env.framework !== 'static')
2393
- return 'not_static';
2394
- const previewStartedAt = Date.now();
2395
- (0, variantsTelemetry_1.trackPreviewStarted)(this.telemetry, {
2396
- sessionId,
2397
- variantId: workItemId,
2398
- projectContextKind: 'existing',
2399
- previewKind: 'static_artifact',
2400
- });
2413
+ async registerExistingStaticPreview(sessionId, workItemId, entry) {
2401
2414
  const resources = this.resources.get(sessionId);
2402
2415
  if (!resources)
2403
- return 'unavailable';
2416
+ return;
2404
2417
  const input = this.store.getVariantWorkItemInput(sessionId, workItemId);
2405
2418
  if (!input?.briefId)
2406
- return 'unavailable';
2407
- let projectCwd;
2408
- try {
2409
- projectCwd = await this.worktrees.getProjectCwdInWorktree(record.worktreePath);
2410
- }
2411
- catch (err) {
2412
- log.warn(`registerExistingStaticPreview: project cwd failed for ${sessionId}/${workItemId}`, err);
2413
- return 'unavailable';
2414
- }
2415
- const entryFile = path_1.default.join(projectCwd, env.entryPath);
2416
- try {
2417
- await fs_1.default.promises.access(entryFile, fs_1.default.constants.R_OK);
2418
- }
2419
- catch (err) {
2420
- log.warn(`registerExistingStaticPreview: no entry HTML at ${entryFile} for ${sessionId}/${workItemId}; preview unavailable`, err);
2421
- (0, variantsTelemetry_1.trackPreviewFailed)(this.telemetry, {
2422
- sessionId,
2423
- variantId: workItemId,
2424
- projectContextKind: 'existing',
2425
- previewKind: 'static_artifact',
2426
- errorCode: 'STATIC_PREVIEW_ENTRY_MISSING',
2427
- reason: 'missing_static_entry',
2428
- durationMs: Date.now() - previewStartedAt,
2429
- });
2430
- this.previewRuntime.setFailure(sessionId, workItemId, {
2431
- reason: 'missing_static_entry',
2432
- portInUse: false,
2433
- });
2434
- return 'unavailable';
2419
+ return;
2420
+ switch (entry.kind) {
2421
+ case 'unresolved':
2422
+ return;
2423
+ case 'missing':
2424
+ log.warn(`registerExistingStaticPreview: no entry page (${entry.source}) for ${sessionId}/${workItemId}; preview unavailable`);
2425
+ (0, variantsTelemetry_1.trackPreviewFailed)(this.telemetry, {
2426
+ sessionId,
2427
+ variantId: workItemId,
2428
+ projectContextKind: 'existing',
2429
+ previewKind: 'static_artifact',
2430
+ errorCode: 'STATIC_PREVIEW_ENTRY_MISSING',
2431
+ reason: 'missing_static_entry',
2432
+ durationMs: Date.now() - entry.startedAt,
2433
+ staticEntrySource: entry.source,
2434
+ });
2435
+ this.previewRuntime.setFailure(sessionId, workItemId, {
2436
+ reason: 'missing_static_entry',
2437
+ portInUse: false,
2438
+ detail: entry.detail,
2439
+ });
2440
+ return;
2441
+ case 'found':
2442
+ break;
2443
+ default: {
2444
+ const unhandled = entry;
2445
+ throw new Error(`Unhandled static entry ${JSON.stringify(unhandled)}`);
2446
+ }
2435
2447
  }
2436
2448
  let dir;
2437
2449
  try {
2438
- dir = fs_1.default.realpathSync(projectCwd);
2450
+ dir = fs_1.default.realpathSync(entry.projectDirectory);
2439
2451
  }
2440
2452
  catch {
2441
- dir = projectCwd;
2453
+ dir = entry.projectDirectory;
2442
2454
  }
2443
2455
  let siteFallbackBase;
2444
2456
  try {
2445
- const hostRealRoot = fs_1.default.realpathSync(env.projectPath);
2457
+ const hostRealRoot = fs_1.default.realpathSync(entry.hostProjectPath);
2446
2458
  if (hostRealRoot !== dir)
2447
- siteFallbackBase = path_1.default.join(hostRealRoot, path_1.default.dirname(env.entryPath));
2459
+ siteFallbackBase = path_1.default.join(hostRealRoot, path_1.default.dirname(entry.entryPath));
2448
2460
  }
2449
2461
  catch { }
2450
2462
  this.workspaceInventory.setStaticPreview(sessionId, {
2451
2463
  workItemId,
2452
2464
  briefId: input.briefId,
2453
- entryPath: path_1.default.basename(env.entryPath),
2454
- assetBase: path_1.default.dirname(path_1.default.join(dir, env.entryPath)),
2465
+ entryPath: path_1.default.basename(entry.entryPath),
2466
+ assetBase: path_1.default.dirname(path_1.default.join(dir, entry.entryPath)),
2455
2467
  hasAssets: true,
2456
2468
  ...(siteFallbackBase ? { assetFallbackBase: siteFallbackBase } : {}),
2457
2469
  });
2458
2470
  this.previewRuntime.clearFailure(sessionId, workItemId);
2459
- log.info(`Variant ${workItemId} served as a static preview (existing/static, no dev server; root ${projectCwd})`);
2471
+ log.info(`Variant ${workItemId} served as a static preview (existing/static, no dev server; root ${entry.projectDirectory})`);
2460
2472
  (0, variantsTelemetry_1.trackPreviewReady)(this.telemetry, {
2461
2473
  sessionId,
2462
2474
  variantId: workItemId,
2463
2475
  projectContextKind: 'existing',
2464
2476
  previewKind: 'static_artifact',
2465
2477
  hasPort: false,
2466
- durationMs: Date.now() - previewStartedAt,
2478
+ durationMs: Date.now() - entry.startedAt,
2479
+ staticEntrySource: entry.source,
2467
2480
  });
2468
- return 'registered';
2469
2481
  }
2470
2482
  async prepareArtifactBase(sessionId) {
2471
2483
  const { projectPath } = await this.resolveEnv(sessionId);
@@ -2478,7 +2490,7 @@ class AgentVariantsOrchestrator {
2478
2490
  async createArtifactDiff(args) {
2479
2491
  const base = await this.prepareArtifactBase(args.sessionId);
2480
2492
  const env = await this.resolveEnv(args.sessionId);
2481
- const entryPath = env.framework === 'static' ? env.entryPath : 'index.html';
2493
+ const entryPath = (env.framework === 'static' && env.entryPath) || 'index.html';
2482
2494
  const files = (0, staticPreviewFiles_1.prepareStaticPreviewProjectFiles)({
2483
2495
  sourceDir: args.sourceDir,
2484
2496
  entryPath,
@@ -2598,6 +2610,7 @@ class AgentVariantsOrchestrator {
2598
2610
  sessionId: args.sessionId,
2599
2611
  variantId: args.workItemId,
2600
2612
  ...(input.requestId ? { requestId: input.requestId } : {}),
2613
+ directionRef: this.store.claimDirectionRef(args),
2601
2614
  label: input.briefLabel,
2602
2615
  brief: input.briefBody ?? '',
2603
2616
  references: input.references,
@@ -2746,6 +2759,7 @@ class AgentVariantsOrchestrator {
2746
2759
  startedAt: Date.now(),
2747
2760
  nextRoundIndex: 0,
2748
2761
  rounds: new Map(),
2762
+ requestTimes: new WorkItemRequestTimes_1.WorkItemRequestTimes(),
2749
2763
  leasedAt: new Map(),
2750
2764
  qaResults: new Map(),
2751
2765
  qaRegenRetried: new Set(),
@@ -1,5 +1,6 @@
1
1
  import type { GuidanceDocument } from '../types/guidance';
2
2
  import type { WorkerSelection } from '../types/change-request-types';
3
+ import type { DirectionRef } from '../types/direction-ref';
3
4
  import { type VariantReference } from '../types/variant-reference';
4
5
  import { z } from 'zod/v3';
5
6
  import { ERROR_CODES, type ErrorCode } from './errors';
@@ -6343,6 +6344,7 @@ export interface SavedVariantPreview {
6343
6344
  references?: VariantReference[];
6344
6345
  previewRoutes?: string[];
6345
6346
  runLabel?: string;
6347
+ directionRef?: DirectionRef;
6346
6348
  }
6347
6349
  export interface AdoptPastVariantArgs extends SavedVariantPreview {
6348
6350
  sessionId: string;
@@ -6361,6 +6363,7 @@ export interface ActiveVariantSnapshot {
6361
6363
  previewRoutes?: string[];
6362
6364
  workItemId: string;
6363
6365
  briefId: string;
6366
+ directionRef?: DirectionRef;
6364
6367
  label: string;
6365
6368
  status: WorkItemStatus;
6366
6369
  workItemKind?: 'code_gen' | 'static_preview';
@@ -6443,6 +6446,7 @@ export interface HostVariantImplementationWorkItemSnapshot extends HostVariantWo
6443
6446
  kind: 'static_preview' | 'refine_variant' | 'code_gen';
6444
6447
  workspace: VariantAssignedWorkspace;
6445
6448
  mode: VariantExecutionMode;
6449
+ directionRef?: DirectionRef;
6446
6450
  direction: VariantWorkerDirection;
6447
6451
  fidelity?: WorkerFidelity;
6448
6452
  sourceDirection?: VariantWorkerDirection;