rivet-design 0.13.2 → 0.13.4
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.
- package/README.md +5 -1
- package/README.npm.md +5 -1
- package/dist/agent-variants/SessionStore.d.ts +22 -2
- package/dist/agent-variants/SessionStore.d.ts.map +1 -1
- package/dist/agent-variants/SessionStore.js +31 -0
- package/dist/agent-variants/SessionStore.js.map +1 -1
- package/dist/agent-variants/VariantWorkspaceManager.d.ts +43 -0
- package/dist/agent-variants/VariantWorkspaceManager.d.ts.map +1 -0
- package/dist/agent-variants/VariantWorkspaceManager.js +216 -0
- package/dist/agent-variants/VariantWorkspaceManager.js.map +1 -0
- package/dist/agent-variants/WorktreeOrchestrator.d.ts +27 -2
- package/dist/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
- package/dist/agent-variants/WorktreeOrchestrator.js +370 -60
- package/dist/agent-variants/WorktreeOrchestrator.js.map +1 -1
- package/dist/agent-variants/contracts.d.ts +62 -1
- package/dist/agent-variants/contracts.d.ts.map +1 -1
- package/dist/agent-variants/contracts.js +10 -1
- package/dist/agent-variants/contracts.js.map +1 -1
- package/dist/agent-variants/workItemBriefing.d.ts +26 -0
- package/dist/agent-variants/workItemBriefing.d.ts.map +1 -0
- package/dist/agent-variants/workItemBriefing.js +110 -0
- package/dist/agent-variants/workItemBriefing.js.map +1 -0
- package/dist/cli/client.d.ts +2 -0
- package/dist/cli/client.d.ts.map +1 -1
- package/dist/cli/client.js +1 -1
- package/dist/cli/client.js.map +1 -1
- package/dist/cli/commands/mcpServe.d.ts.map +1 -1
- package/dist/cli/commands/mcpServe.js +36 -8
- package/dist/cli/commands/mcpServe.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +3 -1
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/variants.d.ts.map +1 -1
- package/dist/cli/commands/variants.js +45 -8
- package/dist/cli/commands/variants.js.map +1 -1
- package/dist/cli/hostWorkNextAction.d.ts +33 -26
- package/dist/cli/hostWorkNextAction.d.ts.map +1 -1
- package/dist/cli/hostWorkNextAction.js +47 -24
- package/dist/cli/hostWorkNextAction.js.map +1 -1
- package/dist/hosts/workerDefaults.d.ts +62 -0
- package/dist/hosts/workerDefaults.d.ts.map +1 -0
- package/dist/hosts/workerDefaults.js +77 -0
- package/dist/hosts/workerDefaults.js.map +1 -0
- package/dist/install/codexGuidance.d.ts.map +1 -1
- package/dist/install/codexGuidance.js +5 -4
- package/dist/install/codexGuidance.js.map +1 -1
- package/dist/install/harnesses.d.ts.map +1 -1
- package/dist/install/harnesses.js +44 -16
- package/dist/install/harnesses.js.map +1 -1
- package/dist/install/mcpRegistration.d.ts +1 -1
- package/dist/install/mcpRegistration.d.ts.map +1 -1
- package/dist/install/mcpRegistration.js +23 -10
- package/dist/install/mcpRegistration.js.map +1 -1
- package/dist/routes/agentVariants.js +2 -2
- package/dist/routes/agentVariants.js.map +1 -1
- package/dist/services/TelemetryService.d.ts +8 -0
- package/dist/services/TelemetryService.d.ts.map +1 -1
- package/dist/services/TelemetryService.js +24 -0
- package/dist/services/TelemetryService.js.map +1 -1
- package/dist/services/VariantGenerationService.d.ts.map +1 -1
- package/dist/services/VariantGenerationService.js +8 -0
- package/dist/services/VariantGenerationService.js.map +1 -1
- package/dist/services/VariantRunService.d.ts +5 -2
- package/dist/services/VariantRunService.d.ts.map +1 -1
- package/dist/services/VariantRunService.js +39 -14
- package/dist/services/VariantRunService.js.map +1 -1
- package/dist/services/WorktreeManager.d.ts.map +1 -1
- package/dist/services/WorktreeManager.js +7 -2
- package/dist/services/WorktreeManager.js.map +1 -1
- package/dist/types/change-request-types.d.ts +3 -0
- package/dist/types/change-request-types.d.ts.map +1 -1
- package/dist/utils/cloneOrCopyDirSync.d.ts +14 -0
- package/dist/utils/cloneOrCopyDirSync.d.ts.map +1 -0
- package/dist/utils/cloneOrCopyDirSync.js +72 -0
- package/dist/utils/cloneOrCopyDirSync.js.map +1 -0
- package/dist/utils/skillWriter.d.ts +8 -0
- package/dist/utils/skillWriter.d.ts.map +1 -1
- package/dist/utils/skillWriter.js +35 -0
- package/dist/utils/skillWriter.js.map +1 -1
- package/dist/utils/skills/claude-skill.d.ts +2 -2
- package/dist/utils/skills/claude-skill.d.ts.map +1 -1
- package/dist/utils/skills/claude-skill.js +1 -1
- package/dist/utils/skills/cli-guidance.d.ts +2 -2
- package/dist/utils/skills/cli-guidance.d.ts.map +1 -1
- package/dist/utils/skills/cli-guidance.js +8 -8
- package/dist/utils/skills/cursor-rules.d.ts +1 -1
- package/dist/utils/skills/cursor-rules.d.ts.map +1 -1
- package/package.json +12 -9
- package/scripts/verify-node-version.cjs +52 -0
- package/src/ui/dist/assets/main-T3U4Gt16.js +419 -0
- package/src/ui/dist/index.html +1 -1
- package/src/ui/dist/assets/main-BBHg643G.js +0 -419
|
@@ -17,6 +17,7 @@ const devServerError_1 = require("../utils/devServerError");
|
|
|
17
17
|
const errors_1 = require("./errors");
|
|
18
18
|
const createProjectArtifacts_1 = require("./createProjectArtifacts");
|
|
19
19
|
const contracts_1 = require("./contracts");
|
|
20
|
+
const workItemBriefing_1 = require("./workItemBriefing");
|
|
20
21
|
const briefContent_1 = require("./briefContent");
|
|
21
22
|
const runLabel_1 = require("./runLabel");
|
|
22
23
|
const runPlan_1 = require("./runPlan");
|
|
@@ -24,6 +25,7 @@ const viteReactTs_1 = require("../services/templates/viteReactTs");
|
|
|
24
25
|
const StaticPreviewServer_1 = require("../services/StaticPreviewServer");
|
|
25
26
|
const designCatalog_1 = require("../services/templates/designCatalog");
|
|
26
27
|
const previewQa_1 = require("./previewQa");
|
|
28
|
+
const VariantWorkspaceManager_1 = require("./VariantWorkspaceManager");
|
|
27
29
|
const diffQa_1 = require("./diffQa");
|
|
28
30
|
const VariantHistoryService_1 = require("../services/VariantHistoryService");
|
|
29
31
|
const variantContext_1 = require("./variantContext");
|
|
@@ -60,6 +62,16 @@ const BRIEF_LABEL_ALTERNATIVES = [
|
|
|
60
62
|
'Density',
|
|
61
63
|
'Color',
|
|
62
64
|
];
|
|
65
|
+
const FALLBACK_DIRECTION_FOCI = [
|
|
66
|
+
'Emphasize hierarchy and one unmistakable primary action.',
|
|
67
|
+
'Use stronger contrast, scale shifts, and a more expressive visual system.',
|
|
68
|
+
'Favor a quieter, spacious composition with restrained supporting detail.',
|
|
69
|
+
'Make information density and fast scanning the organizing principle.',
|
|
70
|
+
'Lead with imagery and let content frame the visual story.',
|
|
71
|
+
'Use modular cards and clear grouping to expose the product structure.',
|
|
72
|
+
'Explore tactile depth, layering, and purposeful interaction cues.',
|
|
73
|
+
'Reduce the concept to its most essential typography and geometry.',
|
|
74
|
+
];
|
|
63
75
|
// Upper bound on waiting for in-flight history persists during session
|
|
64
76
|
// teardown. Generous enough for a full-repo snapshot on a large project;
|
|
65
77
|
// small enough that a wedged git subprocess (which has its own 120s block
|
|
@@ -350,6 +362,12 @@ const buildViewDisabledReason = (args) => {
|
|
|
350
362
|
return 'Variant is still running';
|
|
351
363
|
};
|
|
352
364
|
const NOOP_TELEMETRY = { track: () => undefined };
|
|
365
|
+
const isImplementationWorkItemKind = (kind) => kind === 'static_preview' || kind === 'refine_variant' || kind === 'code_gen';
|
|
366
|
+
const DEFAULT_EXECUTION_MODE_BY_KIND = {
|
|
367
|
+
static_preview: 'create',
|
|
368
|
+
refine_variant: 'refine',
|
|
369
|
+
code_gen: 'create',
|
|
370
|
+
};
|
|
353
371
|
const DESIGN_CREATION_ACTION_RE = /\b(create|build|design|make|redesign|refresh|update)\b/i;
|
|
354
372
|
const DESIGN_CREATION_SURFACE_RE = /\b(home\s?page|landing page|dashboard|screen|site|website|app|page|ui|interface|component|hero)\b/i;
|
|
355
373
|
const NON_VISUAL_CHANGE_RE = /\b(api|backend|database|event|lint|query|server|test|tracking|typecheck)\b/i;
|
|
@@ -658,16 +676,71 @@ class AgentVariantsOrchestrator {
|
|
|
658
676
|
}
|
|
659
677
|
getHostWork(sessionId) {
|
|
660
678
|
return this.store.getHostWork(sessionId).map((item) => {
|
|
661
|
-
const
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
679
|
+
const kind = item.kind;
|
|
680
|
+
if (!isImplementationWorkItemKind(kind)) {
|
|
681
|
+
const planningItem = {
|
|
682
|
+
...item,
|
|
683
|
+
kind,
|
|
684
|
+
};
|
|
685
|
+
return planningItem;
|
|
686
|
+
}
|
|
687
|
+
const input = (item.input ?? {});
|
|
688
|
+
const workspace = this.getAssignedWorkspace({
|
|
689
|
+
sessionId,
|
|
690
|
+
workItemId: item.workId,
|
|
691
|
+
kind,
|
|
692
|
+
});
|
|
693
|
+
const mode = input.sourceVariantId
|
|
694
|
+
? 'vary'
|
|
695
|
+
: DEFAULT_EXECUTION_MODE_BY_KIND[kind];
|
|
696
|
+
const sourceLabel = input.sourceLabel ?? (mode === 'refine' ? input.briefLabel : undefined);
|
|
697
|
+
const sourceBody = input.sourceBody ??
|
|
698
|
+
(mode === 'refine' ? input.briefBody : undefined) ??
|
|
699
|
+
sourceLabel;
|
|
700
|
+
const implementationItem = {
|
|
701
|
+
workId: item.workId,
|
|
702
|
+
variantId: item.variantId,
|
|
703
|
+
kind,
|
|
704
|
+
status: item.status,
|
|
705
|
+
leaseId: item.leaseId,
|
|
706
|
+
attempt: item.attempt,
|
|
707
|
+
leaseExpiresAt: item.leaseExpiresAt,
|
|
708
|
+
workspace,
|
|
709
|
+
mode,
|
|
710
|
+
direction: {
|
|
711
|
+
label: input.briefLabel ?? 'Variant',
|
|
712
|
+
brief: input.briefBody ?? input.instruction ?? 'Create this variant',
|
|
713
|
+
...(input.briefNotes ? { notes: input.briefNotes } : {}),
|
|
714
|
+
},
|
|
715
|
+
...(sourceLabel && sourceBody
|
|
716
|
+
? { sourceDirection: { label: sourceLabel, brief: sourceBody } }
|
|
717
|
+
: {}),
|
|
718
|
+
...(input.relevantFiles?.length
|
|
719
|
+
? { relevantFiles: input.relevantFiles }
|
|
720
|
+
: {}),
|
|
721
|
+
...(input.instruction ? { instruction: input.instruction } : {}),
|
|
722
|
+
...(input.target ? { target: input.target } : {}),
|
|
723
|
+
...(input.targetElement ? { targetElement: input.targetElement } : {}),
|
|
724
|
+
...(input.context?.contextBundlePath
|
|
725
|
+
? { contextBundlePath: input.context.contextBundlePath }
|
|
726
|
+
: {}),
|
|
727
|
+
completion: kind === 'code_gen'
|
|
728
|
+
? { kind: 'worktree_diff' }
|
|
729
|
+
: { kind: 'static_artifact' },
|
|
668
730
|
};
|
|
731
|
+
return implementationItem;
|
|
669
732
|
});
|
|
670
733
|
}
|
|
734
|
+
getAssignedWorkspace(args) {
|
|
735
|
+
const workspace = this.resources
|
|
736
|
+
.get(args.sessionId)
|
|
737
|
+
?.workspaceManager.getAssignedWorkspace(args.workItemId);
|
|
738
|
+
const expectedKind = args.kind === 'code_gen' ? 'git_worktree' : 'artifact_directory';
|
|
739
|
+
if (!workspace || workspace.kind !== expectedKind) {
|
|
740
|
+
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `Variant ${args.workItemId} has no assigned ${expectedKind} workspace`);
|
|
741
|
+
}
|
|
742
|
+
return workspace;
|
|
743
|
+
}
|
|
671
744
|
getVariantsTelemetryMode(projectContext, _target) {
|
|
672
745
|
if (projectContext.kind === 'fresh' && projectContext.variantContext) {
|
|
673
746
|
return 'source_grounded';
|
|
@@ -967,6 +1040,35 @@ class AgentVariantsOrchestrator {
|
|
|
967
1040
|
}
|
|
968
1041
|
requestWork(args) {
|
|
969
1042
|
const result = this.store.requestWork(args);
|
|
1043
|
+
try {
|
|
1044
|
+
this.ensureStaticWorkspaces(args.sessionId, result.leasedWorkItems);
|
|
1045
|
+
}
|
|
1046
|
+
catch (error) {
|
|
1047
|
+
for (const item of result.leasedWorkItems) {
|
|
1048
|
+
if (item.kind !== 'static_preview' && item.kind !== 'refine_variant') {
|
|
1049
|
+
continue;
|
|
1050
|
+
}
|
|
1051
|
+
try {
|
|
1052
|
+
this.store.reportComplete({
|
|
1053
|
+
sessionId: args.sessionId,
|
|
1054
|
+
workItemId: item.id,
|
|
1055
|
+
leaseId: result.leaseId,
|
|
1056
|
+
attempt: item.attempt,
|
|
1057
|
+
status: 'failed',
|
|
1058
|
+
error: {
|
|
1059
|
+
code: 'RUNTIME_VALIDATION_FAILED',
|
|
1060
|
+
message: error instanceof Error
|
|
1061
|
+
? error.message
|
|
1062
|
+
: 'Failed to assign static variant workspace',
|
|
1063
|
+
},
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
catch (reportError) {
|
|
1067
|
+
log.warn(`Failed to record static workspace provisioning failure for ${item.id}`, reportError);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
throw error;
|
|
1071
|
+
}
|
|
970
1072
|
// Record lease times so variant_completed can report lease→report
|
|
971
1073
|
// duration. (We don't fire a separate code_gen_leased event — the
|
|
972
1074
|
// funnel signal we care about is per-variant completion duration.)
|
|
@@ -977,6 +1079,7 @@ class AgentVariantsOrchestrator {
|
|
|
977
1079
|
resources.leasedAt.set(item.id, now);
|
|
978
1080
|
}
|
|
979
1081
|
}
|
|
1082
|
+
this.writeLeasedWorkItemBriefings(args.sessionId, result.leasedWorkItems.map((item) => item.id));
|
|
980
1083
|
this.trackRefinementLeased({ sessionId: args.sessionId, lease: result });
|
|
981
1084
|
// Decorate each leased item's input with the worktreePath provisioned
|
|
982
1085
|
// by approve(). The skill instructs agents to write files to
|
|
@@ -998,6 +1101,94 @@ class AgentVariantsOrchestrator {
|
|
|
998
1101
|
this.emitChange();
|
|
999
1102
|
return decorated;
|
|
1000
1103
|
}
|
|
1104
|
+
/**
|
|
1105
|
+
* @effect Writes each leased implementation item's server-authored briefing
|
|
1106
|
+
* BESIDE its workspace so the coordinating host dispatches workers with a
|
|
1107
|
+
* short pointer prompt instead of composing prose per worker. Best-effort:
|
|
1108
|
+
* a briefing write failure never blocks the lease (the host guidance's
|
|
1109
|
+
* packet fields still carry the same data).
|
|
1110
|
+
*/
|
|
1111
|
+
writeLeasedWorkItemBriefings(sessionId, leasedWorkItemIds) {
|
|
1112
|
+
if (leasedWorkItemIds.length === 0)
|
|
1113
|
+
return;
|
|
1114
|
+
const leased = new Set(leasedWorkItemIds);
|
|
1115
|
+
for (const item of this.getHostWork(sessionId)) {
|
|
1116
|
+
if (!leased.has(item.workId))
|
|
1117
|
+
continue;
|
|
1118
|
+
if (!isImplementationWorkItemKind(item.kind))
|
|
1119
|
+
continue;
|
|
1120
|
+
const implementation = item;
|
|
1121
|
+
try {
|
|
1122
|
+
const briefingPath = (0, workItemBriefing_1.workItemBriefingPath)(sessionId, item.workId);
|
|
1123
|
+
fs_1.default.mkdirSync(path_1.default.dirname(briefingPath), { recursive: true });
|
|
1124
|
+
fs_1.default.writeFileSync(briefingPath, (0, workItemBriefing_1.renderWorkItemBriefing)(implementation), 'utf8');
|
|
1125
|
+
}
|
|
1126
|
+
catch (error) {
|
|
1127
|
+
log.warn(`Failed to write work-item briefing for ${item.workId}`, error);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
/** @effect Assigns isolated, server-owned artifact workspaces to leased static work. */
|
|
1132
|
+
ensureStaticWorkspaces(sessionId, items) {
|
|
1133
|
+
const resources = this.ensureResources(sessionId);
|
|
1134
|
+
const projectContext = this.store.getProjectContext(sessionId);
|
|
1135
|
+
// This lane provisions by copying the source artifact tree (vary forks) or
|
|
1136
|
+
// seeding an entry file — it bypasses provisionWorktrees, so it gets its
|
|
1137
|
+
// own provisioning telemetry here.
|
|
1138
|
+
const provisionStartedAt = Date.now();
|
|
1139
|
+
let assignedCount = 0;
|
|
1140
|
+
for (const item of items) {
|
|
1141
|
+
if (item.kind !== 'static_preview' && item.kind !== 'refine_variant') {
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
if (resources.workspaceManager.getAssignedWorkspace(item.id))
|
|
1145
|
+
continue;
|
|
1146
|
+
assignedCount += 1;
|
|
1147
|
+
const input = (item.input ?? {});
|
|
1148
|
+
const existingProjectPath = projectContext.kind === 'existing'
|
|
1149
|
+
? projectContext.projectPath
|
|
1150
|
+
: undefined;
|
|
1151
|
+
const existingParent = existingProjectPath && fs_1.default.existsSync(existingProjectPath)
|
|
1152
|
+
? path_1.default.join(existingProjectPath, '.rivet', 'variant-work', sessionId)
|
|
1153
|
+
: path_1.default.join(os_1.default.tmpdir(), 'rivet-variant-work', sessionId);
|
|
1154
|
+
const parent = projectContext.kind === 'fresh'
|
|
1155
|
+
? projectContext.workspacePath
|
|
1156
|
+
: existingParent;
|
|
1157
|
+
fs_1.default.mkdirSync(parent, { recursive: true });
|
|
1158
|
+
const rootPath = projectContext.kind === 'fresh'
|
|
1159
|
+
? path_1.default.join(parent, `.rivet-preview-${item.id}`)
|
|
1160
|
+
: path_1.default.join(parent, item.id);
|
|
1161
|
+
const sourceVariantId = input.sourceVariantId ?? input.variantId;
|
|
1162
|
+
const sourceDirectory = sourceVariantId
|
|
1163
|
+
? resources.staticPreviews.get(sourceVariantId)?.assetBase
|
|
1164
|
+
: undefined;
|
|
1165
|
+
resources.workspaceManager.assignArtifactWorkspace({
|
|
1166
|
+
workItemId: item.id,
|
|
1167
|
+
rootPath,
|
|
1168
|
+
allowedRoot: parent,
|
|
1169
|
+
entryPath: 'index.html',
|
|
1170
|
+
sourceDirectory,
|
|
1171
|
+
seedHtml: input.currentHtml,
|
|
1172
|
+
});
|
|
1173
|
+
}
|
|
1174
|
+
if (assignedCount > 0) {
|
|
1175
|
+
this.telemetry.track('agent_variants.provisioning_completed', {
|
|
1176
|
+
source: 'mcp',
|
|
1177
|
+
sessionId,
|
|
1178
|
+
kind: 'artifact_directory',
|
|
1179
|
+
variantCount: assignedCount,
|
|
1180
|
+
durationMs: Date.now() - provisionStartedAt,
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
/** Reads a completed static artifact while enforcing its assigned directory boundary. */
|
|
1185
|
+
readAssignedStaticArtifact(sessionId, workItemId) {
|
|
1186
|
+
const workspaceManager = this.resources.get(sessionId)?.workspaceManager;
|
|
1187
|
+
if (!workspaceManager) {
|
|
1188
|
+
throw new errors_1.AgentVariantsError('SESSION_NOT_FOUND', `No live resources for session ${sessionId}`);
|
|
1189
|
+
}
|
|
1190
|
+
return workspaceManager.readArtifact(workItemId);
|
|
1191
|
+
}
|
|
1001
1192
|
beginStaticPreviewRefinements(args) {
|
|
1002
1193
|
const seenVariantIds = new Set();
|
|
1003
1194
|
// Targets whose in-place refinement could neither be created nor folded
|
|
@@ -1039,6 +1230,7 @@ class AgentVariantsOrchestrator {
|
|
|
1039
1230
|
instruction: target.instruction,
|
|
1040
1231
|
currentHtml,
|
|
1041
1232
|
targetElement: target.element,
|
|
1233
|
+
relevantFiles: target.relevantFiles,
|
|
1042
1234
|
requestId: target.requestId,
|
|
1043
1235
|
});
|
|
1044
1236
|
createdWorkItemIds.push(refineItem.id);
|
|
@@ -1087,6 +1279,7 @@ class AgentVariantsOrchestrator {
|
|
|
1087
1279
|
...(target.briefs ? { briefs: target.briefs } : {}),
|
|
1088
1280
|
currentHtml,
|
|
1089
1281
|
targetElement: target.element,
|
|
1282
|
+
relevantFiles: target.relevantFiles,
|
|
1090
1283
|
requestId: target.requestId,
|
|
1091
1284
|
});
|
|
1092
1285
|
createdWorkItemIds.push(...forks.map((item) => item.id));
|
|
@@ -1369,6 +1562,10 @@ class AgentVariantsOrchestrator {
|
|
|
1369
1562
|
getWorkItemInput(sessionId, workItemId) {
|
|
1370
1563
|
return this.store.getWorkItemInput(sessionId, workItemId);
|
|
1371
1564
|
}
|
|
1565
|
+
/** Returns status after orchestration QA and refinement post-processing. */
|
|
1566
|
+
getWorkItemStatus(sessionId, workItemId) {
|
|
1567
|
+
return this.store.getWorkItemStatus(sessionId, workItemId);
|
|
1568
|
+
}
|
|
1372
1569
|
getBriefs(sessionId) {
|
|
1373
1570
|
return this.store.getBriefs(sessionId);
|
|
1374
1571
|
}
|
|
@@ -1713,6 +1910,9 @@ class AgentVariantsOrchestrator {
|
|
|
1713
1910
|
sessionId,
|
|
1714
1911
|
briefs,
|
|
1715
1912
|
runLabel: args.runLabel?.trim() || (0, runLabel_1.deriveRunLabel)(args.prompt),
|
|
1913
|
+
...(args.relevantFiles?.length
|
|
1914
|
+
? { relevantFiles: args.relevantFiles }
|
|
1915
|
+
: {}),
|
|
1716
1916
|
...(projectContext.kind === 'existing' && projectContext.variantContext
|
|
1717
1917
|
? { variantContext: projectContext.variantContext }
|
|
1718
1918
|
: {}),
|
|
@@ -1755,6 +1955,7 @@ class AgentVariantsOrchestrator {
|
|
|
1755
1955
|
prompt: args.prompt,
|
|
1756
1956
|
count,
|
|
1757
1957
|
target: args.target,
|
|
1958
|
+
relevantFiles: args.relevantFiles,
|
|
1758
1959
|
projectContext,
|
|
1759
1960
|
runLabel: args.runLabel,
|
|
1760
1961
|
...(args.sessionId ? { sessionId: args.sessionId } : {}),
|
|
@@ -1905,20 +2106,79 @@ class AgentVariantsOrchestrator {
|
|
|
1905
2106
|
return null;
|
|
1906
2107
|
return sessionId;
|
|
1907
2108
|
}
|
|
2109
|
+
/** @effect Registers a provisioned git worktree with runtime and workspace state. */
|
|
2110
|
+
async registerWorktreeWorkspace(resources, record) {
|
|
2111
|
+
let projectPath = record.worktreePath;
|
|
2112
|
+
try {
|
|
2113
|
+
projectPath = await this.worktrees.getProjectCwdInWorktree(record.worktreePath);
|
|
2114
|
+
}
|
|
2115
|
+
catch (err) {
|
|
2116
|
+
log.warn(`Failed to resolve project path in worktree ${record.worktreePath}; using its root`, err);
|
|
2117
|
+
}
|
|
2118
|
+
resources.worktrees.set(record.workItemId, record);
|
|
2119
|
+
resources.workspaceManager.registerGitWorkspace({
|
|
2120
|
+
workItemId: record.workItemId,
|
|
2121
|
+
rootPath: record.worktreePath,
|
|
2122
|
+
projectPath,
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
1908
2125
|
/**
|
|
1909
2126
|
* Provision a worktree for each appended existing-project variant. Mirrors
|
|
1910
2127
|
* {@link provisionExistingWorktrees} but only for the newly appended ids, and
|
|
1911
2128
|
* passes a per-batch `instanceKeyPrefix` so the new worktree dirs do not
|
|
1912
2129
|
* collide with the first batch's `${sessionId}-${i}` paths.
|
|
1913
2130
|
*/
|
|
2131
|
+
/** Emits provisioning started/completed/failed telemetry around `run` for
|
|
2132
|
+
* the vary-fork/append lanes that bypass provisionWorktrees (and its
|
|
2133
|
+
* telemetry). Rethrows failures untouched. */
|
|
2134
|
+
async withProvisioningTelemetry(args, run) {
|
|
2135
|
+
const startedAt = Date.now();
|
|
2136
|
+
this.telemetry.track('agent_variants.provisioning_started', {
|
|
2137
|
+
source: 'mcp',
|
|
2138
|
+
sessionId: args.sessionId,
|
|
2139
|
+
kind: args.kind,
|
|
2140
|
+
variantCount: args.variantCount,
|
|
2141
|
+
});
|
|
2142
|
+
try {
|
|
2143
|
+
const result = await run();
|
|
2144
|
+
this.telemetry.track('agent_variants.provisioning_completed', {
|
|
2145
|
+
source: 'mcp',
|
|
2146
|
+
sessionId: args.sessionId,
|
|
2147
|
+
kind: args.kind,
|
|
2148
|
+
variantCount: args.variantCount,
|
|
2149
|
+
durationMs: Date.now() - startedAt,
|
|
2150
|
+
});
|
|
2151
|
+
return result;
|
|
2152
|
+
}
|
|
2153
|
+
catch (err) {
|
|
2154
|
+
const timedOut = err instanceof ProvisionTimeoutError;
|
|
2155
|
+
this.telemetry.track('agent_variants.provisioning_failed', {
|
|
2156
|
+
source: 'mcp',
|
|
2157
|
+
sessionId: args.sessionId,
|
|
2158
|
+
kind: args.kind,
|
|
2159
|
+
variantCount: args.variantCount,
|
|
2160
|
+
durationMs: Date.now() - startedAt,
|
|
2161
|
+
timedOut,
|
|
2162
|
+
errorCode: timedOut
|
|
2163
|
+
? 'PROVISION_TIMEOUT'
|
|
2164
|
+
: err instanceof errors_1.AgentVariantsError
|
|
2165
|
+
? err.code
|
|
2166
|
+
: 'PROVISION_FAILED',
|
|
2167
|
+
});
|
|
2168
|
+
throw err;
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
1914
2171
|
async provisionAppendedExistingWorktrees(sessionId, workItemIds) {
|
|
1915
2172
|
if (workItemIds.length === 0)
|
|
1916
2173
|
return;
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
2174
|
+
await this.withProvisioningTelemetry({ sessionId, kind: 'appended_existing', variantCount: workItemIds.length }, async () => {
|
|
2175
|
+
const resources = this.ensureResources(sessionId);
|
|
2176
|
+
const instanceKeyPrefix = `a${(0, crypto_1.randomUUID)().slice(0, 8)}-`;
|
|
2177
|
+
const paths = await withProvisionTimeout(this.worktrees.createWorktrees(sessionId, workItemIds.length, instanceKeyPrefix), this.provisionTimeoutMs);
|
|
2178
|
+
await Promise.all(workItemIds.map((id, index) => this.registerWorktreeWorkspace(resources, {
|
|
2179
|
+
workItemId: id,
|
|
2180
|
+
worktreePath: paths[index],
|
|
2181
|
+
})));
|
|
1922
2182
|
});
|
|
1923
2183
|
}
|
|
1924
2184
|
/**
|
|
@@ -1936,14 +2196,21 @@ class AgentVariantsOrchestrator {
|
|
|
1936
2196
|
if (!this.worktrees.forkWorktreesFrom) {
|
|
1937
2197
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', 'worktreeManager does not implement forkWorktreesFrom');
|
|
1938
2198
|
}
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
2199
|
+
await this.withProvisioningTelemetry({ sessionId, kind: 'forked_variant', variantCount: workItemIds.length }, async () => {
|
|
2200
|
+
const resources = this.ensureResources(sessionId);
|
|
2201
|
+
const instanceKeyPrefix = `f${(0, crypto_1.randomUUID)().slice(0, 8)}-`;
|
|
2202
|
+
const paths = await withProvisionTimeout(this.worktrees.forkWorktreesFrom(sourcePath, sessionId, workItemIds.length, instanceKeyPrefix), this.provisionTimeoutMs);
|
|
2203
|
+
await Promise.all(workItemIds.map((id, index) => this.registerWorktreeWorkspace(resources, {
|
|
2204
|
+
workItemId: id,
|
|
2205
|
+
worktreePath: paths[index],
|
|
2206
|
+
})));
|
|
1944
2207
|
});
|
|
1945
2208
|
}
|
|
1946
2209
|
async reportComplete(args) {
|
|
2210
|
+
// Phase-timing anchor: lease→report (agent work) vs report→recorded
|
|
2211
|
+
// (QA gate + post-processing) are attributed separately on
|
|
2212
|
+
// `variant_completed` so latency work can tell them apart.
|
|
2213
|
+
const reportReceivedAt = Date.now();
|
|
1947
2214
|
// Cooperative abort short-circuit: if the work item was removed/cancelled
|
|
1948
2215
|
// while in flight (delete-while-loading, cancel_variant, session cancel),
|
|
1949
2216
|
// skip the schema and QA gates entirely — there is no point validating or
|
|
@@ -1956,18 +2223,23 @@ class AgentVariantsOrchestrator {
|
|
|
1956
2223
|
const workItemKind = this.store.hasSession(args.sessionId)
|
|
1957
2224
|
? this.store.getWorkItemKind(args.sessionId, args.workItemId)
|
|
1958
2225
|
: undefined;
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
2226
|
+
const resolvedArgs = args.status === 'succeeded' &&
|
|
2227
|
+
(workItemKind === 'static_preview' ||
|
|
2228
|
+
workItemKind === 'refine_variant') &&
|
|
2229
|
+
args.output === undefined
|
|
2230
|
+
? {
|
|
2231
|
+
...args,
|
|
2232
|
+
output: this.readAssignedStaticArtifact(args.sessionId, args.workItemId),
|
|
2233
|
+
}
|
|
2234
|
+
: args;
|
|
2235
|
+
// Contract validation keeps internal callers that provide an explicit
|
|
2236
|
+
// static output honest. Host workers complete assigned artifacts without
|
|
2237
|
+
// transporting the HTML through this report.
|
|
2238
|
+
if (resolvedArgs.status === 'succeeded' &&
|
|
1967
2239
|
this.store.hasSession(args.sessionId) &&
|
|
1968
2240
|
(workItemKind === 'static_preview' ||
|
|
1969
2241
|
workItemKind === 'refine_variant') &&
|
|
1970
|
-
!parseStaticPreviewOutput(normalizeOutput(
|
|
2242
|
+
!parseStaticPreviewOutput(normalizeOutput(resolvedArgs.output))) {
|
|
1971
2243
|
const telemetry = this.refinementTelemetryForWorkItem({
|
|
1972
2244
|
sessionId: args.sessionId,
|
|
1973
2245
|
workItemId: args.workItemId,
|
|
@@ -1978,25 +2250,25 @@ class AgentVariantsOrchestrator {
|
|
|
1978
2250
|
if (telemetry) {
|
|
1979
2251
|
this.telemetry.trackAgentVariantsRefinementFailed?.(telemetry);
|
|
1980
2252
|
}
|
|
1981
|
-
throw new errors_1.AgentVariantsError('SCHEMA_VALIDATION_FAILED', `${workItemKind}
|
|
1982
|
-
'Pass the full HTML inline as output: { html: "<!doctype html>...", css?: "...", js?: "..." }. ' +
|
|
1983
|
-
'Do NOT write the HTML to a file and report a file list — Rivet renders the HTML inline; on-disk files are not read.');
|
|
2253
|
+
throw new errors_1.AgentVariantsError('SCHEMA_VALIDATION_FAILED', `${workItemKind} output.html must be a string and non-empty when explicit output is provided. Host workers should write the assigned index.html instead.`);
|
|
1984
2254
|
}
|
|
1985
2255
|
// QA gate: for `succeeded` static_preview reports, run preview QA
|
|
1986
2256
|
// synchronously before recording success in the store. A failed QA
|
|
1987
2257
|
// verdict converts the report to `failed` with code `VARIANT_QA_FAILED`
|
|
1988
2258
|
// so the variant never reaches `ready` and `getVariants` can disable
|
|
1989
2259
|
// its commit action.
|
|
2260
|
+
const qaStartedAt = Date.now();
|
|
1990
2261
|
const qaEval = workItemKind === 'refine_variant'
|
|
1991
2262
|
? null
|
|
1992
|
-
: await this.evaluateQaForReport(
|
|
2263
|
+
: await this.evaluateQaForReport(resolvedArgs);
|
|
2264
|
+
const qaMs = qaEval === null ? null : Date.now() - qaStartedAt;
|
|
1993
2265
|
// A `retry` verdict re-leases the variant for one regeneration (the
|
|
1994
2266
|
// existing-project diff task-fit gate) instead of recording success —
|
|
1995
2267
|
// short-circuit the normal record path.
|
|
1996
2268
|
if (qaEval?.decision === 'retry') {
|
|
1997
|
-
return this.handleQaRegenRetry(
|
|
2269
|
+
return this.handleQaRegenRetry(resolvedArgs, qaEval.qa);
|
|
1998
2270
|
}
|
|
1999
|
-
let effectiveArgs = qaEval?.decision === 'fail_terminal' ? qaEval.overrideArgs :
|
|
2271
|
+
let effectiveArgs = qaEval?.decision === 'fail_terminal' ? qaEval.overrideArgs : resolvedArgs;
|
|
2000
2272
|
// For a successful refine_variant, swap the refined static preview into
|
|
2001
2273
|
// place and persist history BEFORE recording success in the store. This
|
|
2002
2274
|
// keeps the user-visible `refinement.status: succeeded` (and the snapshot
|
|
@@ -2016,7 +2288,7 @@ class AgentVariantsOrchestrator {
|
|
|
2016
2288
|
await this.handleStaticPreviewRefinement({
|
|
2017
2289
|
sessionId: args.sessionId,
|
|
2018
2290
|
workItemId: args.workItemId,
|
|
2019
|
-
output:
|
|
2291
|
+
output: effectiveArgs.output,
|
|
2020
2292
|
});
|
|
2021
2293
|
}
|
|
2022
2294
|
catch (err) {
|
|
@@ -2062,8 +2334,15 @@ class AgentVariantsOrchestrator {
|
|
|
2062
2334
|
const approveStartedAt = resources?.approveStartedAt;
|
|
2063
2335
|
const approveToCompleteMs = approveStartedAt !== undefined ? Date.now() - approveStartedAt : null;
|
|
2064
2336
|
// Byte size of generated output for HTML vs full-stack comparison.
|
|
2065
|
-
const outputBytes = estimateOutputBytes(
|
|
2337
|
+
const outputBytes = estimateOutputBytes(effectiveArgs.output);
|
|
2066
2338
|
const projectContextKind = this.store.getProjectContext(args.sessionId).kind;
|
|
2339
|
+
// Execution mode mirrors the host work-item snapshot derivation so
|
|
2340
|
+
// prod latency can finally segment vary vs create vs refine.
|
|
2341
|
+
const mode = workItemKind !== undefined && isImplementationWorkItemKind(workItemKind)
|
|
2342
|
+
? this.store.isVaryForkWorkItem(args.sessionId, args.workItemId)
|
|
2343
|
+
? 'vary'
|
|
2344
|
+
: DEFAULT_EXECUTION_MODE_BY_KIND[workItemKind]
|
|
2345
|
+
: null;
|
|
2067
2346
|
this.telemetry.track('agent_variants.variant_completed', {
|
|
2068
2347
|
source: 'mcp',
|
|
2069
2348
|
sessionId: args.sessionId,
|
|
@@ -2072,6 +2351,12 @@ class AgentVariantsOrchestrator {
|
|
|
2072
2351
|
attempt: args.attempt,
|
|
2073
2352
|
durationMs,
|
|
2074
2353
|
approveToCompleteMs,
|
|
2354
|
+
kind: workItemKind ?? null,
|
|
2355
|
+
mode,
|
|
2356
|
+
// Phase split of `durationMs`: agent work vs server-side gating.
|
|
2357
|
+
leaseToReportMs: leasedAt !== undefined ? reportReceivedAt - leasedAt : null,
|
|
2358
|
+
reportProcessingMs: Date.now() - reportReceivedAt,
|
|
2359
|
+
qaMs,
|
|
2075
2360
|
hasError: Boolean(effectiveArgs.error),
|
|
2076
2361
|
errorCode: effectiveArgs.error?.code ?? null,
|
|
2077
2362
|
isScaffold: resources?.scaffoldBaseWorkItemId === args.workItemId,
|
|
@@ -2151,7 +2436,7 @@ class AgentVariantsOrchestrator {
|
|
|
2151
2436
|
void this.handleSucceededReport({
|
|
2152
2437
|
sessionId: args.sessionId,
|
|
2153
2438
|
workItemId: args.workItemId,
|
|
2154
|
-
output:
|
|
2439
|
+
output: effectiveArgs.output,
|
|
2155
2440
|
}).catch((err) => {
|
|
2156
2441
|
log.error(`handleSucceededReport failed for ${args.sessionId}/${args.workItemId}`, err);
|
|
2157
2442
|
});
|
|
@@ -2947,7 +3232,7 @@ class AgentVariantsOrchestrator {
|
|
|
2947
3232
|
let cursor = 0;
|
|
2948
3233
|
if (approveResult.scaffoldBaseWorkItemId) {
|
|
2949
3234
|
resources.scaffoldBaseWorkItemId = approveResult.scaffoldBaseWorkItemId;
|
|
2950
|
-
|
|
3235
|
+
await this.registerWorktreeWorkspace(resources, {
|
|
2951
3236
|
workItemId: approveResult.scaffoldBaseWorkItemId,
|
|
2952
3237
|
worktreePath: paths[cursor],
|
|
2953
3238
|
});
|
|
@@ -2956,7 +3241,10 @@ class AgentVariantsOrchestrator {
|
|
|
2956
3241
|
for (const id of approveResult.codeGenWorkItemIds) {
|
|
2957
3242
|
const p = paths[cursor];
|
|
2958
3243
|
cursor += 1;
|
|
2959
|
-
|
|
3244
|
+
await this.registerWorktreeWorkspace(resources, {
|
|
3245
|
+
workItemId: id,
|
|
3246
|
+
worktreePath: p,
|
|
3247
|
+
});
|
|
2960
3248
|
}
|
|
2961
3249
|
}
|
|
2962
3250
|
/**
|
|
@@ -3013,12 +3301,10 @@ class AgentVariantsOrchestrator {
|
|
|
3013
3301
|
resources.freshDestinationParent = destinationParent;
|
|
3014
3302
|
// Each code_gen item maps 1:1 to a fresh worktree. The scaffold_base
|
|
3015
3303
|
// work item is internal — no dedicated worktree.
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
});
|
|
3021
|
-
}
|
|
3304
|
+
await Promise.all(codeGenIds.map((workItemId, index) => this.registerWorktreeWorkspace(resources, {
|
|
3305
|
+
workItemId,
|
|
3306
|
+
worktreePath: paths[index],
|
|
3307
|
+
})));
|
|
3022
3308
|
// Copy agent-planned assets (e.g. avatar.glb) into each worktree so
|
|
3023
3309
|
// generated code can reference them via plan.referenceAs. Done before
|
|
3024
3310
|
// the background install so the assets are on disk by the time the
|
|
@@ -3565,6 +3851,11 @@ class AgentVariantsOrchestrator {
|
|
|
3565
3851
|
hasAssets: Boolean(resolvedAssetBase),
|
|
3566
3852
|
};
|
|
3567
3853
|
resources.staticPreviews.set(workItemId, record);
|
|
3854
|
+
const assignedWorkspace = resources.workspaceManager.getAssignedWorkspace(workItemId);
|
|
3855
|
+
if (assignedWorkspace?.kind === 'artifact_directory' &&
|
|
3856
|
+
assignedWorkspace.rootPath !== record.assetBase) {
|
|
3857
|
+
resources.workspaceManager.removeArtifactWorkspace(workItemId);
|
|
3858
|
+
}
|
|
3568
3859
|
if (this.store.getProjectContext(sessionId).kind === 'fresh') {
|
|
3569
3860
|
// History at `<workspacePath>/.rivet/variants/<sessionId>/<variantId>/`
|
|
3570
3861
|
// is the on-disk record for this generated project.
|
|
@@ -3721,6 +4012,14 @@ class AgentVariantsOrchestrator {
|
|
|
3721
4012
|
hasAssets: Boolean(resolvedAssetBase) || Boolean(previousRecord?.hasAssets),
|
|
3722
4013
|
});
|
|
3723
4014
|
}
|
|
4015
|
+
const refinementWorkspace = resources.workspaceManager.getAssignedWorkspace(args.workItemId);
|
|
4016
|
+
if (refinementWorkspace?.kind === 'artifact_directory' &&
|
|
4017
|
+
dir === refinementWorkspace.rootPath) {
|
|
4018
|
+
resources.workspaceManager.promoteArtifactWorkspace({
|
|
4019
|
+
sourceWorkItemId: args.workItemId,
|
|
4020
|
+
targetWorkItemId: input.variantId,
|
|
4021
|
+
});
|
|
4022
|
+
}
|
|
3724
4023
|
// History persistence is best-effort, mirroring handleSucceededReport's
|
|
3725
4024
|
// fire-and-forget persistence for freshly completed variants. A failure
|
|
3726
4025
|
// here (e.g. a transient filesystem race) must not fail the refinement or
|
|
@@ -4848,12 +5147,13 @@ class AgentVariantsOrchestrator {
|
|
|
4848
5147
|
log.warn(`cleanupSession (worktree removal) failed for ${sessionId}`, err);
|
|
4849
5148
|
}
|
|
4850
5149
|
}
|
|
4851
|
-
//
|
|
4852
|
-
//
|
|
4853
|
-
//
|
|
4854
|
-
//
|
|
4855
|
-
|
|
4856
|
-
|
|
5150
|
+
// Assigned static workspaces are always Rivet-owned, including existing-
|
|
5151
|
+
// project refinement work staged under `.rivet/variant-work` or /tmp.
|
|
5152
|
+
// Fresh staticPreviews are also Rivet staging unless commit already moved
|
|
5153
|
+
// the selected directory into the destination.
|
|
5154
|
+
const ownedArtifactRoots = new Set(resources.workspaceManager.getOwnedArtifactRoots());
|
|
5155
|
+
resources.workspaceManager.removeOwnedArtifactWorkspaces();
|
|
5156
|
+
const staticDirectories = new Set();
|
|
4857
5157
|
if (reason !== 'committed') {
|
|
4858
5158
|
let isFresh = false;
|
|
4859
5159
|
try {
|
|
@@ -4863,16 +5163,21 @@ class AgentVariantsOrchestrator {
|
|
|
4863
5163
|
isFresh = false;
|
|
4864
5164
|
}
|
|
4865
5165
|
if (isFresh) {
|
|
4866
|
-
for (const
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
}
|
|
4870
|
-
catch (err) {
|
|
4871
|
-
log.warn(`failed to remove static preview dir ${sp.assetBase} for ${sessionId}`, err);
|
|
5166
|
+
for (const preview of resources.staticPreviews.values()) {
|
|
5167
|
+
if (!ownedArtifactRoots.has(preview.assetBase)) {
|
|
5168
|
+
staticDirectories.add(preview.assetBase);
|
|
4872
5169
|
}
|
|
4873
5170
|
}
|
|
4874
5171
|
}
|
|
4875
5172
|
}
|
|
5173
|
+
for (const staticDirectory of staticDirectories) {
|
|
5174
|
+
try {
|
|
5175
|
+
fs_1.default.rmSync(staticDirectory, { recursive: true, force: true });
|
|
5176
|
+
}
|
|
5177
|
+
catch (err) {
|
|
5178
|
+
log.warn(`failed to remove static preview dir ${staticDirectory} for ${sessionId}`, err);
|
|
5179
|
+
}
|
|
5180
|
+
}
|
|
4876
5181
|
this.resources.delete(sessionId);
|
|
4877
5182
|
}
|
|
4878
5183
|
ensureResources(sessionId) {
|
|
@@ -4882,6 +5187,7 @@ class AgentVariantsOrchestrator {
|
|
|
4882
5187
|
sessionId,
|
|
4883
5188
|
worktrees: new Map(),
|
|
4884
5189
|
staticPreviews: new Map(),
|
|
5190
|
+
workspaceManager: new VariantWorkspaceManager_1.VariantWorkspaceManager(),
|
|
4885
5191
|
cleanupStarted: false,
|
|
4886
5192
|
committedVariantIds: new Set(),
|
|
4887
5193
|
startedAt: Date.now(),
|
|
@@ -6023,12 +6329,16 @@ const defaultMaterializeProject = async (sourceWorktreePath, destinationPath) =>
|
|
|
6023
6329
|
};
|
|
6024
6330
|
/**
|
|
6025
6331
|
* Synthesize a fallback brief body for a human-direct unified start slot.
|
|
6026
|
-
* Agent callers provide structured briefs before starting.
|
|
6027
|
-
*
|
|
6028
|
-
*
|
|
6332
|
+
* Agent callers provide structured briefs before starting. Human-direct
|
|
6333
|
+
* batches get stable, slot-specific focus statements without another model
|
|
6334
|
+
* call so workers do not independently invent overlapping directions.
|
|
6029
6335
|
*/
|
|
6030
|
-
function synthesizeUnifiedBriefBody(prompt,
|
|
6336
|
+
function synthesizeUnifiedBriefBody(prompt, index, total) {
|
|
6031
6337
|
const trimmed = prompt.trim().replace(/\s+/g, ' ').slice(0, 200);
|
|
6032
|
-
|
|
6338
|
+
const intent = trimmed.length > 0 ? trimmed : 'Create this variant';
|
|
6339
|
+
if (total <= 1)
|
|
6340
|
+
return intent;
|
|
6341
|
+
const focus = FALLBACK_DIRECTION_FOCI[(Math.max(index, 1) - 1) % FALLBACK_DIRECTION_FOCI.length];
|
|
6342
|
+
return `${intent} Direction ${index} of ${total}: ${focus}`;
|
|
6033
6343
|
}
|
|
6034
6344
|
//# sourceMappingURL=WorktreeOrchestrator.js.map
|