@pellux/goodvibes-sdk 0.33.24 → 0.33.25
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/dist/contracts/artifacts/operator-contract.json +1 -1
- package/dist/events/agents.d.ts +3 -3
- package/dist/events/agents.d.ts.map +1 -1
- package/dist/events/orchestration.d.ts +1 -1
- package/dist/events/orchestration.d.ts.map +1 -1
- package/dist/events/workflows.d.ts +1 -1
- package/dist/events/workflows.d.ts.map +1 -1
- package/dist/platform/agents/archetypes.d.ts.map +1 -1
- package/dist/platform/agents/archetypes.js +14 -0
- package/dist/platform/agents/communication-policy.d.ts.map +1 -1
- package/dist/platform/agents/communication-policy.js +4 -0
- package/dist/platform/agents/orchestrator-prompts.d.ts.map +1 -1
- package/dist/platform/agents/orchestrator-prompts.js +2 -0
- package/dist/platform/agents/wrfc-controller.d.ts +13 -0
- package/dist/platform/agents/wrfc-controller.d.ts.map +1 -1
- package/dist/platform/agents/wrfc-controller.js +425 -7
- package/dist/platform/agents/wrfc-runtime-events.d.ts +1 -1
- package/dist/platform/agents/wrfc-runtime-events.d.ts.map +1 -1
- package/dist/platform/agents/wrfc-types.d.ts +29 -4
- package/dist/platform/agents/wrfc-types.d.ts.map +1 -1
- package/dist/platform/agents/wrfc-workmap.d.ts +2 -1
- package/dist/platform/agents/wrfc-workmap.d.ts.map +1 -1
- package/dist/platform/runtime/emitters/agents.d.ts +3 -3
- package/dist/platform/runtime/emitters/agents.d.ts.map +1 -1
- package/dist/platform/runtime/emitters/orchestration.d.ts +1 -1
- package/dist/platform/runtime/emitters/orchestration.d.ts.map +1 -1
- package/dist/platform/runtime/store/domains/agents.d.ts +2 -2
- package/dist/platform/runtime/store/domains/agents.d.ts.map +1 -1
- package/dist/platform/runtime/store/domains/orchestration.d.ts +1 -1
- package/dist/platform/runtime/store/domains/orchestration.d.ts.map +1 -1
- package/dist/platform/tools/agent/index.d.ts.map +1 -1
- package/dist/platform/tools/agent/index.js +2 -0
- package/dist/platform/tools/agent/manager.d.ts +2 -0
- package/dist/platform/tools/agent/manager.d.ts.map +1 -1
- package/dist/platform/tools/agent/manager.js +22 -3
- package/dist/platform/tools/agent/schema.d.ts +2 -0
- package/dist/platform/tools/agent/schema.d.ts.map +1 -1
- package/dist/platform/tools/agent/schema.js +4 -4
- package/dist/platform/tools/agent/wrfc-batch-policy.d.ts +1 -0
- package/dist/platform/tools/agent/wrfc-batch-policy.d.ts.map +1 -1
- package/dist/platform/tools/agent/wrfc-batch-policy.js +95 -1
- package/dist/platform/version.js +1 -1
- package/package.json +9 -9
|
@@ -16,7 +16,8 @@ import { runWrfcGateChecks } from './wrfc-gate-runtime.js';
|
|
|
16
16
|
export { extractScoreFromText, extractPassedFromText, extractIssuesFromText } from './wrfc-reporting.js';
|
|
17
17
|
const VALID_TRANSITIONS = {
|
|
18
18
|
pending: ['engineering'],
|
|
19
|
-
engineering: ['reviewing', 'failed'],
|
|
19
|
+
engineering: ['integrating', 'reviewing', 'failed'],
|
|
20
|
+
integrating: ['reviewing', 'failed'],
|
|
20
21
|
reviewing: ['fixing', 'awaiting_gates', 'failed'],
|
|
21
22
|
fixing: ['reviewing', 'failed'],
|
|
22
23
|
awaiting_gates: ['gating', 'failed'],
|
|
@@ -149,10 +150,13 @@ export class WrfcController {
|
|
|
149
150
|
emitWrfcStateChanged(this.runtimeBus, this.sessionId, chain.id, from, to);
|
|
150
151
|
logger.debug('WrfcController.transition', { chainId: chain.id, from, to });
|
|
151
152
|
}
|
|
152
|
-
applyWrfcAgentMetadata(chain, record, role) {
|
|
153
|
+
applyWrfcAgentMetadata(chain, record, role, subtaskId) {
|
|
153
154
|
record.wrfcId = chain.id;
|
|
154
155
|
record.wrfcRole = role;
|
|
155
156
|
record.wrfcPhaseOrder = this.wrfcPhaseOrder(role);
|
|
157
|
+
if (subtaskId) {
|
|
158
|
+
record.wrfcSubtaskId = subtaskId;
|
|
159
|
+
}
|
|
156
160
|
if (role === 'owner') {
|
|
157
161
|
record.progress = this.ownerProgress(chain);
|
|
158
162
|
}
|
|
@@ -207,20 +211,28 @@ export class WrfcController {
|
|
|
207
211
|
});
|
|
208
212
|
}
|
|
209
213
|
ownerProgress(chain) {
|
|
214
|
+
if (chain.subtasks && chain.subtasks.length > 0) {
|
|
215
|
+
const passed = chain.subtasks.filter((subtask) => subtask.state === 'passed').length;
|
|
216
|
+
return `WRFC owner supervising compound chain (${chain.state}, ${passed}/${chain.subtasks.length} deliverables passed)`;
|
|
217
|
+
}
|
|
210
218
|
return `WRFC owner supervising child agents (${chain.state})`;
|
|
211
219
|
}
|
|
212
220
|
wrfcPhaseOrder(role) {
|
|
213
221
|
switch (role) {
|
|
214
222
|
case 'owner':
|
|
215
223
|
return 0;
|
|
224
|
+
case 'orchestrator':
|
|
225
|
+
return 0;
|
|
216
226
|
case 'engineer':
|
|
217
227
|
return 1;
|
|
218
228
|
case 'reviewer':
|
|
219
229
|
return 2;
|
|
220
230
|
case 'fixer':
|
|
221
231
|
return 3;
|
|
222
|
-
case '
|
|
232
|
+
case 'integrator':
|
|
223
233
|
return 4;
|
|
234
|
+
case 'verifier':
|
|
235
|
+
return 5;
|
|
224
236
|
}
|
|
225
237
|
}
|
|
226
238
|
setupListeners() {
|
|
@@ -264,6 +276,23 @@ export class WrfcController {
|
|
|
264
276
|
state: chain.state,
|
|
265
277
|
outputLength: rawOutput.length,
|
|
266
278
|
});
|
|
279
|
+
const subtask = this.findSubtaskByAgentId(chain, agentId);
|
|
280
|
+
if (subtask) {
|
|
281
|
+
await this.onCompoundSubtaskAgentComplete(chain, subtask, agentId, rawOutput, record ?? undefined);
|
|
282
|
+
if (this.planManager) {
|
|
283
|
+
completePlanItemsForAgent(agentId, this.planManager);
|
|
284
|
+
}
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
if (agentId === chain.integratorAgentId) {
|
|
288
|
+
const report = parseEngineerCompletionReport(rawOutput, record?.template);
|
|
289
|
+
this.setWrfcWorkPlanTaskStatus(chain, agentId, 'done');
|
|
290
|
+
this.handleIntegratorCompletion(chain, agentId, report);
|
|
291
|
+
if (this.planManager) {
|
|
292
|
+
completePlanItemsForAgent(agentId, this.planManager);
|
|
293
|
+
}
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
267
296
|
if (chain.state === 'pending') {
|
|
268
297
|
chain.bufferedCompletion = { agentId, fullOutput: rawOutput };
|
|
269
298
|
logger.debug('WrfcController.onAgentComplete: chain pending, buffering completion', {
|
|
@@ -541,6 +570,47 @@ export class WrfcController {
|
|
|
541
570
|
constraintFailure: unsatisfiedConstraintIds.length > 0,
|
|
542
571
|
};
|
|
543
572
|
}
|
|
573
|
+
evaluateSubtaskConstraints(subtask, review) {
|
|
574
|
+
if (subtask.constraints.length === 0) {
|
|
575
|
+
return {
|
|
576
|
+
constraintsSatisfied: 0,
|
|
577
|
+
constraintsTotal: 0,
|
|
578
|
+
unsatisfiedConstraintIds: [],
|
|
579
|
+
ignoredConstraintFindingIds: [],
|
|
580
|
+
constraintFailure: false,
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
const expectedIds = new Set(subtask.constraints.map((constraint) => constraint.id));
|
|
584
|
+
const findingMap = new Map();
|
|
585
|
+
const ignoredConstraintFindingIds = [];
|
|
586
|
+
for (const finding of review.constraintFindings ?? []) {
|
|
587
|
+
if (!expectedIds.has(finding.constraintId)) {
|
|
588
|
+
ignoredConstraintFindingIds.push(finding.constraintId);
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
if (!findingMap.has(finding.constraintId)) {
|
|
592
|
+
findingMap.set(finding.constraintId, finding);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
let constraintsSatisfied = 0;
|
|
596
|
+
const unsatisfiedConstraintIds = [];
|
|
597
|
+
for (const constraint of subtask.constraints) {
|
|
598
|
+
const finding = findingMap.get(constraint.id);
|
|
599
|
+
if (finding?.satisfied === true) {
|
|
600
|
+
constraintsSatisfied += 1;
|
|
601
|
+
}
|
|
602
|
+
else {
|
|
603
|
+
unsatisfiedConstraintIds.push(constraint.id);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
return {
|
|
607
|
+
constraintsSatisfied,
|
|
608
|
+
constraintsTotal: subtask.constraints.length,
|
|
609
|
+
unsatisfiedConstraintIds,
|
|
610
|
+
ignoredConstraintFindingIds,
|
|
611
|
+
constraintFailure: unsatisfiedConstraintIds.length > 0,
|
|
612
|
+
};
|
|
613
|
+
}
|
|
544
614
|
async processGateResults(chain, results) {
|
|
545
615
|
if (!chain.currentNodeId?.includes(':gate:')) {
|
|
546
616
|
chain.currentNodeId = startWrfcOrchestrationNode(this.runtimeBus, this.sessionId, chain.id, `gate:${chain.reviewCycles}:${chain.fixAttempts}`, 'verifier', 'Quality gates');
|
|
@@ -635,6 +705,7 @@ export class WrfcController {
|
|
|
635
705
|
const allChains = Array.from(this.chains.values()).filter((chain) => chain.state !== 'passed' && chain.state !== 'failed');
|
|
636
706
|
const activeWorkChains = allChains.filter((chain) => (chain.state === 'pending'
|
|
637
707
|
|| chain.state === 'engineering'
|
|
708
|
+
|| chain.state === 'integrating'
|
|
638
709
|
|| chain.state === 'reviewing'
|
|
639
710
|
|| chain.state === 'fixing'));
|
|
640
711
|
if (activeWorkChains.length > 0) {
|
|
@@ -703,6 +774,12 @@ export class WrfcController {
|
|
|
703
774
|
}
|
|
704
775
|
const wasActive = chain.state !== 'passed' && chain.state !== 'failed' && chain.state !== 'pending';
|
|
705
776
|
this.failCurrentNode(chain, reason);
|
|
777
|
+
for (const subtask of chain.subtasks ?? []) {
|
|
778
|
+
if (subtask.currentNodeId) {
|
|
779
|
+
failWrfcOrchestrationNode(this.runtimeBus, this.sessionId, chain.id, subtask.currentNodeId, reason);
|
|
780
|
+
subtask.currentNodeId = undefined;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
706
783
|
try {
|
|
707
784
|
this.transition(chain, 'failed');
|
|
708
785
|
}
|
|
@@ -854,7 +931,26 @@ export class WrfcController {
|
|
|
854
931
|
failWrfcOrchestrationNode(this.runtimeBus, this.sessionId, chain.id, chain.currentNodeId, error);
|
|
855
932
|
chain.currentNodeId = undefined;
|
|
856
933
|
}
|
|
934
|
+
completeSubtaskNode(chain, subtask, summary) {
|
|
935
|
+
if (!subtask.currentNodeId)
|
|
936
|
+
return;
|
|
937
|
+
completeWrfcOrchestrationNode(this.runtimeBus, this.sessionId, chain.id, subtask.currentNodeId, summary);
|
|
938
|
+
subtask.currentNodeId = undefined;
|
|
939
|
+
}
|
|
857
940
|
createBaseChain(ownerRecord) {
|
|
941
|
+
const subtasks = (ownerRecord.wrfcSubtasks ?? [])
|
|
942
|
+
.filter((task) => typeof task.task === 'string' && task.task.trim().length > 0)
|
|
943
|
+
.map((task, index) => ({
|
|
944
|
+
id: `deliverable-${index + 1}`,
|
|
945
|
+
title: task.task.trim().slice(0, 80),
|
|
946
|
+
task: task.task.trim(),
|
|
947
|
+
state: 'pending',
|
|
948
|
+
fixAttempts: 0,
|
|
949
|
+
reviewCycles: 0,
|
|
950
|
+
reviewScores: [],
|
|
951
|
+
constraints: [],
|
|
952
|
+
constraintsEnumerated: false,
|
|
953
|
+
}));
|
|
858
954
|
const chain = {
|
|
859
955
|
id: this.generateWrfcId(),
|
|
860
956
|
state: 'pending',
|
|
@@ -869,6 +965,7 @@ export class WrfcController {
|
|
|
869
965
|
constraints: [],
|
|
870
966
|
constraintsEnumerated: false,
|
|
871
967
|
createdAt: Date.now(),
|
|
968
|
+
...(subtasks.length > 1 ? { subtasks } : {}),
|
|
872
969
|
};
|
|
873
970
|
this.chains.set(chain.id, chain);
|
|
874
971
|
emitWrfcGraphCreated(this.runtimeBus, this.sessionId, chain.id, `WRFC: ${ownerRecord.task}`);
|
|
@@ -886,6 +983,10 @@ export class WrfcController {
|
|
|
886
983
|
return chain;
|
|
887
984
|
}
|
|
888
985
|
startEngineeringChain(chain, emitCreated) {
|
|
986
|
+
if (chain.subtasks && chain.subtasks.length > 1) {
|
|
987
|
+
this.startCompoundEngineeringChain(chain, emitCreated);
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
889
990
|
this.activeChainCount += 1;
|
|
890
991
|
this.transition(chain, 'engineering');
|
|
891
992
|
this.setWrfcWorkPlanTaskStatus(chain, chain.ownerAgentId, 'in_progress');
|
|
@@ -909,6 +1010,34 @@ export class WrfcController {
|
|
|
909
1010
|
});
|
|
910
1011
|
this.upsertWrfcWorkPlanTask(chain, 'engineer', engineerRecord, 'in_progress');
|
|
911
1012
|
}
|
|
1013
|
+
startCompoundEngineeringChain(chain, emitCreated) {
|
|
1014
|
+
this.activeChainCount += 1;
|
|
1015
|
+
this.transition(chain, 'engineering');
|
|
1016
|
+
this.setWrfcWorkPlanTaskStatus(chain, chain.ownerAgentId, 'in_progress');
|
|
1017
|
+
if (emitCreated) {
|
|
1018
|
+
emitWrfcChainCreated(this.runtimeBus, this.sessionId, chain.id, chain.task);
|
|
1019
|
+
}
|
|
1020
|
+
this.appendOwnerDecision(chain, 'compound_started', `Compound WRFC owner supervising ${chain.subtasks?.length ?? 0} deliverables under one chain`, { agentId: chain.ownerAgentId });
|
|
1021
|
+
for (const subtask of chain.subtasks ?? []) {
|
|
1022
|
+
subtask.state = 'engineering';
|
|
1023
|
+
const engineerRecord = this.spawnWrfcAgent(chain, 'engineer', 'engineer', this.buildSubtaskEngineerTask(chain, subtask), true, subtask.id);
|
|
1024
|
+
this.applyWrfcAgentMetadata(chain, engineerRecord, 'engineer', subtask.id);
|
|
1025
|
+
subtask.engineerAgentId = engineerRecord.id;
|
|
1026
|
+
chain.allAgentIds.push(engineerRecord.id);
|
|
1027
|
+
this.messageBus.registerAgent({
|
|
1028
|
+
agentId: engineerRecord.id,
|
|
1029
|
+
role: 'engineer',
|
|
1030
|
+
wrfcId: chain.id,
|
|
1031
|
+
});
|
|
1032
|
+
subtask.currentNodeId = startWrfcOrchestrationNode(this.runtimeBus, this.sessionId, chain.id, `subtask:${subtask.id}:engineer:0`, 'engineer', `Engineer ${subtask.title}`, engineerRecord.id);
|
|
1033
|
+
this.appendOwnerDecision(chain, 'spawn_engineer', this.withRouteReason(`Start compound WRFC engineer child for ${subtask.id}`, engineerRecord), {
|
|
1034
|
+
agentId: engineerRecord.id,
|
|
1035
|
+
role: 'engineer',
|
|
1036
|
+
record: engineerRecord,
|
|
1037
|
+
});
|
|
1038
|
+
this.upsertWrfcWorkPlanTask(chain, 'engineer', engineerRecord, 'in_progress', subtask.id);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
912
1041
|
handleEngineerCompletion(chain, agentId, report) {
|
|
913
1042
|
let reportForReview = report;
|
|
914
1043
|
this.completeCurrentNode(chain, report.summary);
|
|
@@ -981,6 +1110,278 @@ export class WrfcController {
|
|
|
981
1110
|
}
|
|
982
1111
|
this.startReview(chain, reportForReview);
|
|
983
1112
|
}
|
|
1113
|
+
buildSubtaskEngineerTask(chain, subtask) {
|
|
1114
|
+
return [
|
|
1115
|
+
`Compound WRFC engineer task`,
|
|
1116
|
+
`Parent WRFC ask (authoritative whole):`,
|
|
1117
|
+
chain.task,
|
|
1118
|
+
``,
|
|
1119
|
+
`Sub-deliverable ${subtask.id}:`,
|
|
1120
|
+
subtask.task,
|
|
1121
|
+
``,
|
|
1122
|
+
`Instructions:`,
|
|
1123
|
+
`1. Implement only this sub-deliverable, but keep the parent ask in mind for compatibility.`,
|
|
1124
|
+
`2. Do not review or verify sibling deliverables. The WRFC owner controls review/fix phases after your output exists.`,
|
|
1125
|
+
`3. Return a structured EngineerReport JSON block.`,
|
|
1126
|
+
].join('\n');
|
|
1127
|
+
}
|
|
1128
|
+
buildCompoundIntegrationTask(chain) {
|
|
1129
|
+
const subtaskSummaries = (chain.subtasks ?? []).map((subtask) => [
|
|
1130
|
+
`## ${subtask.id}: ${subtask.title}`,
|
|
1131
|
+
`Task: ${subtask.task}`,
|
|
1132
|
+
`Review cycles: ${subtask.reviewCycles}`,
|
|
1133
|
+
`Last score: ${subtask.reviewScores.at(-1) ?? 'n/a'}`,
|
|
1134
|
+
`Engineer summary: ${subtask.engineerReport?.summary ?? '(no summary)'}`,
|
|
1135
|
+
`Reviewer summary: ${subtask.reviewerReport?.summary ?? '(no review)'}`,
|
|
1136
|
+
].join('\n')).join('\n\n');
|
|
1137
|
+
return [
|
|
1138
|
+
`Compound WRFC integration task`,
|
|
1139
|
+
`Parent WRFC ask (authoritative full scope):`,
|
|
1140
|
+
chain.task,
|
|
1141
|
+
``,
|
|
1142
|
+
`All sub-deliverables have individually passed review. Integrate them into one coherent final result.`,
|
|
1143
|
+
``,
|
|
1144
|
+
subtaskSummaries,
|
|
1145
|
+
``,
|
|
1146
|
+
`Instructions:`,
|
|
1147
|
+
`1. Inspect the current workspace and the sub-deliverable outputs before editing.`,
|
|
1148
|
+
`2. Resolve cross-deliverable API, export, documentation, and test consistency issues.`,
|
|
1149
|
+
`3. Preserve all accepted sub-deliverable behavior; do not start unrelated new work.`,
|
|
1150
|
+
`4. Return a structured EngineerReport JSON block so the final reviewer can inspect integration changes.`,
|
|
1151
|
+
].join('\n');
|
|
1152
|
+
}
|
|
1153
|
+
findSubtaskByAgentId(chain, agentId) {
|
|
1154
|
+
for (const subtask of chain.subtasks ?? []) {
|
|
1155
|
+
if (subtask.engineerAgentId === agentId
|
|
1156
|
+
|| subtask.reviewerAgentId === agentId
|
|
1157
|
+
|| subtask.fixerAgentId === agentId) {
|
|
1158
|
+
return subtask;
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
return null;
|
|
1162
|
+
}
|
|
1163
|
+
async onCompoundSubtaskAgentComplete(chain, subtask, agentId, rawOutput, record) {
|
|
1164
|
+
if (agentId === subtask.engineerAgentId || agentId === subtask.fixerAgentId) {
|
|
1165
|
+
const report = parseEngineerCompletionReport(rawOutput, record?.template);
|
|
1166
|
+
this.setWrfcWorkPlanTaskStatus(chain, agentId, 'done');
|
|
1167
|
+
this.handleCompoundEngineerCompletion(chain, subtask, agentId, report);
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
if (agentId === subtask.reviewerAgentId) {
|
|
1171
|
+
const review = parseReviewerCompletionReport(chain.id, rawOutput, getWrfcScoreThreshold(this.configManager));
|
|
1172
|
+
subtask.reviewerReport = review;
|
|
1173
|
+
subtask.reviewCycles += 1;
|
|
1174
|
+
this.setWrfcWorkPlanTaskStatus(chain, agentId, 'done');
|
|
1175
|
+
await this.processCompoundSubtaskReview(chain, subtask, review);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
handleCompoundEngineerCompletion(chain, subtask, agentId, report) {
|
|
1179
|
+
let reportForReview = report;
|
|
1180
|
+
this.completeSubtaskNode(chain, subtask, report.summary);
|
|
1181
|
+
if (subtask.state === 'engineering') {
|
|
1182
|
+
subtask.engineerReport = report;
|
|
1183
|
+
this.workmap.append({
|
|
1184
|
+
ts: new Date().toISOString(),
|
|
1185
|
+
wrfcId: chain.id,
|
|
1186
|
+
event: 'engineer_complete',
|
|
1187
|
+
agentId,
|
|
1188
|
+
task: subtask.task,
|
|
1189
|
+
subtaskId: subtask.id,
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
const isEngineerReportShape = (r) => r.archetype === 'engineer';
|
|
1193
|
+
if (!subtask.constraintsEnumerated) {
|
|
1194
|
+
subtask.constraints = isEngineerReportShape(report) ? (report.constraints ?? []) : [];
|
|
1195
|
+
subtask.constraintsEnumerated = true;
|
|
1196
|
+
}
|
|
1197
|
+
else if (isEngineerReportShape(report)) {
|
|
1198
|
+
const fixerConstraints = report.constraints ?? [];
|
|
1199
|
+
reportForReview = this.canonicalizeFixerReportConstraints(report, subtask.constraints);
|
|
1200
|
+
if (subtask.constraints.length === 0) {
|
|
1201
|
+
if (fixerConstraints.length > 0) {
|
|
1202
|
+
logger.warn('WrfcController: ignored compound fixer-invented constraints for unconstrained subtask', {
|
|
1203
|
+
chainId: chain.id,
|
|
1204
|
+
subtaskId: subtask.id,
|
|
1205
|
+
extra: fixerConstraints.map((constraint) => constraint.id),
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
else {
|
|
1210
|
+
const expectedIds = new Set(subtask.constraints.map((constraint) => constraint.id));
|
|
1211
|
+
const actualIds = new Set(fixerConstraints.map((constraint) => constraint.id));
|
|
1212
|
+
const missing = [...expectedIds].filter((id) => !actualIds.has(id));
|
|
1213
|
+
const extra = [...actualIds].filter((id) => !expectedIds.has(id));
|
|
1214
|
+
if (missing.length > 0 || extra.length > 0) {
|
|
1215
|
+
const description = `Fixer regressed constraint continuity for ${subtask.id}: missing=[${missing.join(',')}] extra=[${extra.join(',')}]`;
|
|
1216
|
+
logger.warn('WrfcController: compound fixer constraint-continuity violation', {
|
|
1217
|
+
chainId: chain.id,
|
|
1218
|
+
subtaskId: subtask.id,
|
|
1219
|
+
missing,
|
|
1220
|
+
extra,
|
|
1221
|
+
});
|
|
1222
|
+
subtask.syntheticIssues ??= [];
|
|
1223
|
+
subtask.syntheticIssues.push({ severity: 'critical', description });
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
else if (subtask.constraints.length > 0) {
|
|
1228
|
+
const description = `Fixer regressed constraint continuity for ${subtask.id}: missing=[${subtask.constraints.map((constraint) => constraint.id).join(',')}] extra=[]`;
|
|
1229
|
+
logger.warn('WrfcController: compound fixer constraint-continuity violation', {
|
|
1230
|
+
chainId: chain.id,
|
|
1231
|
+
subtaskId: subtask.id,
|
|
1232
|
+
missing: subtask.constraints.map((constraint) => constraint.id),
|
|
1233
|
+
extra: [],
|
|
1234
|
+
});
|
|
1235
|
+
subtask.syntheticIssues ??= [];
|
|
1236
|
+
subtask.syntheticIssues.push({ severity: 'critical', description });
|
|
1237
|
+
}
|
|
1238
|
+
subtask.engineerReport = reportForReview;
|
|
1239
|
+
this.startCompoundSubtaskReview(chain, subtask, reportForReview);
|
|
1240
|
+
}
|
|
1241
|
+
startCompoundSubtaskReview(chain, subtask, report) {
|
|
1242
|
+
subtask.state = 'reviewing';
|
|
1243
|
+
let reviewTask = buildReviewTask(chain.id, `Parent WRFC ask:\n${chain.task}\n\nSub-deliverable ${subtask.id}:\n${subtask.task}`, report, getWrfcScoreThreshold(this.configManager), subtask.constraints);
|
|
1244
|
+
if (subtask.syntheticIssues && subtask.syntheticIssues.length > 0) {
|
|
1245
|
+
const syntheticBlock = [
|
|
1246
|
+
`## Synthetic issues from controller`,
|
|
1247
|
+
``,
|
|
1248
|
+
...subtask.syntheticIssues.map((issue) => `- [${issue.severity.toUpperCase()}] ${issue.description}`),
|
|
1249
|
+
].join('\n');
|
|
1250
|
+
reviewTask = syntheticBlock + '\n\n---\n\n' + reviewTask;
|
|
1251
|
+
subtask.syntheticIssues = [];
|
|
1252
|
+
}
|
|
1253
|
+
const reviewerRecord = this.spawnWrfcAgent(chain, 'reviewer', 'reviewer', reviewTask, true, subtask.id);
|
|
1254
|
+
subtask.reviewerAgentId = reviewerRecord.id;
|
|
1255
|
+
this.applyWrfcAgentMetadata(chain, reviewerRecord, 'reviewer', subtask.id);
|
|
1256
|
+
chain.allAgentIds.push(reviewerRecord.id);
|
|
1257
|
+
this.messageBus.registerAgent({
|
|
1258
|
+
agentId: reviewerRecord.id,
|
|
1259
|
+
role: 'reviewer',
|
|
1260
|
+
wrfcId: chain.id,
|
|
1261
|
+
});
|
|
1262
|
+
subtask.currentNodeId = startWrfcOrchestrationNode(this.runtimeBus, this.sessionId, chain.id, `subtask:${subtask.id}:review:${subtask.reviewCycles + 1}`, 'reviewer', `Review ${subtask.title}`, reviewerRecord.id);
|
|
1263
|
+
this.appendOwnerDecision(chain, 'spawn_reviewer', this.withRouteReason(`Review compound sub-deliverable ${subtask.id} after engineer output exists`, reviewerRecord), {
|
|
1264
|
+
agentId: reviewerRecord.id,
|
|
1265
|
+
role: 'reviewer',
|
|
1266
|
+
record: reviewerRecord,
|
|
1267
|
+
});
|
|
1268
|
+
this.upsertWrfcWorkPlanTask(chain, 'reviewer', reviewerRecord, 'in_progress', subtask.id);
|
|
1269
|
+
}
|
|
1270
|
+
async processCompoundSubtaskReview(chain, subtask, review) {
|
|
1271
|
+
const threshold = getWrfcScoreThreshold(this.configManager);
|
|
1272
|
+
const constraintEvaluation = this.evaluateSubtaskConstraints(subtask, review);
|
|
1273
|
+
const passed = review.score >= threshold && !constraintEvaluation.constraintFailure;
|
|
1274
|
+
this.completeSubtaskNode(chain, subtask, `Score ${review.score}/10${passed ? ' passed' : ' needs fixes'}`);
|
|
1275
|
+
emitWorkflowReviewCompleted(this.runtimeBus, createWrfcWorkflowContext(this.sessionId, chain.id), {
|
|
1276
|
+
chainId: chain.id,
|
|
1277
|
+
score: review.score,
|
|
1278
|
+
passed,
|
|
1279
|
+
...(subtask.constraints.length > 0
|
|
1280
|
+
? {
|
|
1281
|
+
constraintsSatisfied: constraintEvaluation.constraintsSatisfied,
|
|
1282
|
+
constraintsTotal: constraintEvaluation.constraintsTotal,
|
|
1283
|
+
unsatisfiedConstraintIds: constraintEvaluation.unsatisfiedConstraintIds,
|
|
1284
|
+
}
|
|
1285
|
+
: {}),
|
|
1286
|
+
});
|
|
1287
|
+
this.workmap.append({
|
|
1288
|
+
ts: new Date().toISOString(),
|
|
1289
|
+
wrfcId: chain.id,
|
|
1290
|
+
event: 'review_complete',
|
|
1291
|
+
agentId: subtask.reviewerAgentId,
|
|
1292
|
+
score: review.score,
|
|
1293
|
+
passed,
|
|
1294
|
+
subtaskId: subtask.id,
|
|
1295
|
+
issues: review.issues?.slice(0, 10).map((issue) => ({
|
|
1296
|
+
severity: issue.severity,
|
|
1297
|
+
description: issue.description,
|
|
1298
|
+
file: issue.file,
|
|
1299
|
+
})),
|
|
1300
|
+
});
|
|
1301
|
+
subtask.reviewScores.push(review.score);
|
|
1302
|
+
if (passed) {
|
|
1303
|
+
subtask.state = 'passed';
|
|
1304
|
+
this.appendOwnerDecision(chain, 'subtask_review_passed', `Sub-deliverable ${subtask.id} passed review with ${review.score}/10`, {
|
|
1305
|
+
agentId: subtask.reviewerAgentId,
|
|
1306
|
+
role: 'reviewer',
|
|
1307
|
+
reviewScore: review.score,
|
|
1308
|
+
});
|
|
1309
|
+
if ((chain.subtasks ?? []).every((candidate) => candidate.state === 'passed')) {
|
|
1310
|
+
this.startIntegration(chain);
|
|
1311
|
+
}
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1314
|
+
const maxFixAttempts = getWrfcMaxFixAttempts(this.configManager);
|
|
1315
|
+
if (subtask.fixAttempts >= maxFixAttempts) {
|
|
1316
|
+
subtask.state = 'failed';
|
|
1317
|
+
this.failChain(chain, `Sub-deliverable ${subtask.id} review score ${review.score}/10 below threshold ${threshold}/10 after ${subtask.fixAttempts} fix attempt${subtask.fixAttempts !== 1 ? 's' : ''}`);
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1320
|
+
this.appendOwnerDecision(chain, 'subtask_review_failed', `Sub-deliverable ${subtask.id} review did not pass`, {
|
|
1321
|
+
agentId: subtask.reviewerAgentId,
|
|
1322
|
+
role: 'reviewer',
|
|
1323
|
+
reviewScore: review.score,
|
|
1324
|
+
});
|
|
1325
|
+
this.startCompoundSubtaskFix(chain, subtask, review);
|
|
1326
|
+
}
|
|
1327
|
+
startCompoundSubtaskFix(chain, subtask, review) {
|
|
1328
|
+
subtask.fixAttempts += 1;
|
|
1329
|
+
subtask.state = 'fixing';
|
|
1330
|
+
const targetConstraintIds = this.evaluateSubtaskConstraints(subtask, review).unsatisfiedConstraintIds;
|
|
1331
|
+
emitWorkflowFixAttempted(this.runtimeBus, createWrfcWorkflowContext(this.sessionId, chain.id), {
|
|
1332
|
+
chainId: chain.id,
|
|
1333
|
+
attempt: subtask.fixAttempts,
|
|
1334
|
+
maxAttempts: getWrfcMaxFixAttempts(this.configManager),
|
|
1335
|
+
...(targetConstraintIds.length > 0 ? { targetConstraintIds } : {}),
|
|
1336
|
+
});
|
|
1337
|
+
const fixerRecord = this.spawnWrfcAgent(chain, 'fixer', 'engineer', buildFixTask(chain.id, `Parent WRFC ask:\n${chain.task}\n\nSub-deliverable ${subtask.id}:\n${subtask.task}`, review, getWrfcScoreThreshold(this.configManager), subtask.fixAttempts, subtask.constraints, review.constraintFindings ?? []), true, subtask.id);
|
|
1338
|
+
subtask.fixerAgentId = fixerRecord.id;
|
|
1339
|
+
this.applyWrfcAgentMetadata(chain, fixerRecord, 'fixer', subtask.id);
|
|
1340
|
+
chain.allAgentIds.push(fixerRecord.id);
|
|
1341
|
+
this.messageBus.registerAgent({
|
|
1342
|
+
agentId: fixerRecord.id,
|
|
1343
|
+
role: 'fixer',
|
|
1344
|
+
wrfcId: chain.id,
|
|
1345
|
+
});
|
|
1346
|
+
subtask.currentNodeId = startWrfcOrchestrationNode(this.runtimeBus, this.sessionId, chain.id, `subtask:${subtask.id}:fix:${subtask.fixAttempts}`, 'fixer', `Fix ${subtask.title}`, fixerRecord.id);
|
|
1347
|
+
this.appendOwnerDecision(chain, 'spawn_fixer', this.withRouteReason(`Fix compound sub-deliverable ${subtask.id}`, fixerRecord), {
|
|
1348
|
+
agentId: fixerRecord.id,
|
|
1349
|
+
role: 'fixer',
|
|
1350
|
+
record: fixerRecord,
|
|
1351
|
+
});
|
|
1352
|
+
this.upsertWrfcWorkPlanTask(chain, 'fixer', fixerRecord, 'in_progress', subtask.id);
|
|
1353
|
+
}
|
|
1354
|
+
startIntegration(chain) {
|
|
1355
|
+
this.transition(chain, 'integrating');
|
|
1356
|
+
const integratorRecord = this.spawnWrfcAgent(chain, 'integrator', 'integrator', this.buildCompoundIntegrationTask(chain), true);
|
|
1357
|
+
chain.integratorAgentId = integratorRecord.id;
|
|
1358
|
+
this.applyWrfcAgentMetadata(chain, integratorRecord, 'integrator');
|
|
1359
|
+
chain.allAgentIds.push(integratorRecord.id);
|
|
1360
|
+
this.messageBus.registerAgent({
|
|
1361
|
+
agentId: integratorRecord.id,
|
|
1362
|
+
role: 'integrator',
|
|
1363
|
+
wrfcId: chain.id,
|
|
1364
|
+
});
|
|
1365
|
+
chain.currentNodeId = startWrfcOrchestrationNode(this.runtimeBus, this.sessionId, chain.id, `integrator:${Date.now()}`, 'integrator', 'Integrate passed deliverables', integratorRecord.id);
|
|
1366
|
+
this.appendOwnerDecision(chain, 'spawn_integrator', this.withRouteReason('Integrate all passed compound WRFC deliverables before final full-scope review', integratorRecord), {
|
|
1367
|
+
agentId: integratorRecord.id,
|
|
1368
|
+
role: 'integrator',
|
|
1369
|
+
record: integratorRecord,
|
|
1370
|
+
});
|
|
1371
|
+
this.upsertWrfcWorkPlanTask(chain, 'integrator', integratorRecord, 'in_progress');
|
|
1372
|
+
}
|
|
1373
|
+
handleIntegratorCompletion(chain, agentId, report) {
|
|
1374
|
+
chain.integratorReport = report;
|
|
1375
|
+
this.completeCurrentNode(chain, report.summary);
|
|
1376
|
+
this.workmap.append({
|
|
1377
|
+
ts: new Date().toISOString(),
|
|
1378
|
+
wrfcId: chain.id,
|
|
1379
|
+
event: 'integrator_complete',
|
|
1380
|
+
agentId,
|
|
1381
|
+
task: chain.task,
|
|
1382
|
+
});
|
|
1383
|
+
this.startReview(chain, report);
|
|
1384
|
+
}
|
|
984
1385
|
canonicalizeFixerReportConstraints(report, constraints) {
|
|
985
1386
|
const canonical = {
|
|
986
1387
|
...report,
|
|
@@ -997,7 +1398,7 @@ export class WrfcController {
|
|
|
997
1398
|
].join('\n');
|
|
998
1399
|
return canonical;
|
|
999
1400
|
}
|
|
1000
|
-
spawnWrfcAgent(chain, role, template, task, dangerouslyDisableWrfc) {
|
|
1401
|
+
spawnWrfcAgent(chain, role, template, task, dangerouslyDisableWrfc, subtaskId) {
|
|
1001
1402
|
const owner = this.agentManager.getStatus(chain.ownerAgentId);
|
|
1002
1403
|
const selectedRoute = this.selectChildRoute?.({ chain, role, task, ownerAgent: owner }) ?? null;
|
|
1003
1404
|
const model = selectedRoute?.model ?? owner?.model;
|
|
@@ -1016,9 +1417,13 @@ export class WrfcController {
|
|
|
1016
1417
|
...(routing ? { routing } : {}),
|
|
1017
1418
|
...(reasoningEffort ? { reasoningEffort } : {}),
|
|
1018
1419
|
...(template === 'engineer' ? { systemPromptAddendum: '\n\n---\n\n' + buildEngineerConstraintAddendum() } : {}),
|
|
1420
|
+
...(template === 'integrator' ? { systemPromptAddendum: '\n\n---\n\n' + buildEngineerConstraintAddendum() } : {}),
|
|
1019
1421
|
...(dangerouslyDisableWrfc ? { dangerously_disable_wrfc: true } : {}),
|
|
1020
1422
|
});
|
|
1021
1423
|
record.wrfcId = chain.id;
|
|
1424
|
+
if (subtaskId) {
|
|
1425
|
+
record.wrfcSubtaskId = subtaskId;
|
|
1426
|
+
}
|
|
1022
1427
|
if (selectedRoute?.reason) {
|
|
1023
1428
|
record.wrfcRouteReason = selectedRoute.reason;
|
|
1024
1429
|
}
|
|
@@ -1075,16 +1480,18 @@ export class WrfcController {
|
|
|
1075
1480
|
});
|
|
1076
1481
|
}
|
|
1077
1482
|
}
|
|
1078
|
-
upsertWrfcWorkPlanTask(chain, role, record, status) {
|
|
1483
|
+
upsertWrfcWorkPlanTask(chain, role, record, status, subtaskId) {
|
|
1079
1484
|
if (!this.workPlanService)
|
|
1080
1485
|
return;
|
|
1081
1486
|
const taskId = this.workPlanTaskIdForAgent(chain, record.id, role);
|
|
1082
1487
|
const task = {
|
|
1083
1488
|
taskId,
|
|
1084
|
-
title: this.workPlanTaskTitle(role, chain.task),
|
|
1489
|
+
title: this.workPlanTaskTitle(role, role === 'owner' ? chain.task : record.task),
|
|
1085
1490
|
notes: role === 'owner'
|
|
1086
1491
|
? 'WRFC owner chain supervising lifecycle child agents.'
|
|
1087
|
-
:
|
|
1492
|
+
: subtaskId
|
|
1493
|
+
? `WRFC ${role} phase for compound deliverable ${subtaskId}.`
|
|
1494
|
+
: `WRFC ${role} phase for the owner chain.`,
|
|
1088
1495
|
owner: role,
|
|
1089
1496
|
status,
|
|
1090
1497
|
source: 'wrfc',
|
|
@@ -1097,6 +1504,7 @@ export class WrfcController {
|
|
|
1097
1504
|
metadata: {
|
|
1098
1505
|
wrfcState: chain.state,
|
|
1099
1506
|
agentTemplate: record.template,
|
|
1507
|
+
...(subtaskId ? { wrfcSubtaskId: subtaskId } : {}),
|
|
1100
1508
|
},
|
|
1101
1509
|
};
|
|
1102
1510
|
this.enqueueWrfcWorkPlanTaskOperation(taskId, async () => {
|
|
@@ -1177,6 +1585,16 @@ export class WrfcController {
|
|
|
1177
1585
|
return 'reviewer';
|
|
1178
1586
|
if (agentId === chain.fixerAgentId)
|
|
1179
1587
|
return 'fixer';
|
|
1588
|
+
if (agentId === chain.integratorAgentId)
|
|
1589
|
+
return 'integrator';
|
|
1590
|
+
for (const subtask of chain.subtasks ?? []) {
|
|
1591
|
+
if (agentId === subtask.engineerAgentId)
|
|
1592
|
+
return 'engineer';
|
|
1593
|
+
if (agentId === subtask.reviewerAgentId)
|
|
1594
|
+
return 'reviewer';
|
|
1595
|
+
if (agentId === subtask.fixerAgentId)
|
|
1596
|
+
return 'fixer';
|
|
1597
|
+
}
|
|
1180
1598
|
return null;
|
|
1181
1599
|
}
|
|
1182
1600
|
workPlanTaskIdForAgent(chain, agentId, role) {
|
|
@@ -6,7 +6,7 @@ export type WorkflowContext = {
|
|
|
6
6
|
traceId: string;
|
|
7
7
|
source: string;
|
|
8
8
|
};
|
|
9
|
-
export type WrfcNodeRole = 'engineer' | 'reviewer' | 'fixer' | 'verifier';
|
|
9
|
+
export type WrfcNodeRole = 'orchestrator' | 'engineer' | 'reviewer' | 'fixer' | 'integrator' | 'verifier';
|
|
10
10
|
export declare function createWrfcWorkflowContext(sessionId: string, chainId: string): WorkflowContext;
|
|
11
11
|
export declare function createWrfcOrchestrationGraphId(chainId: string): string;
|
|
12
12
|
export declare function emitWrfcStateChanged(runtimeBus: RuntimeEventBus, sessionId: string, chainId: string, from: WrfcState, to: WrfcState): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrfc-runtime-events.d.ts","sourceRoot":"","sources":["../../../src/platform/agents/wrfc-runtime-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAgBjD,MAAM,MAAM,eAAe,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACrF,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"wrfc-runtime-events.d.ts","sourceRoot":"","sources":["../../../src/platform/agents/wrfc-runtime-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAgBjD,MAAM,MAAM,eAAe,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACrF,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,YAAY,GAAG,UAAU,CAAC;AAE1G,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,CAM7F;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,SAAS,GACZ,IAAI,CAEN;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAExH;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAEvI;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAEzG;AAED,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAC9B,IAAI,CAEN;AAED,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,IAAI,CAEN;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,UAAU,EAAE,GACxB,IAAI,CAEN;AAED,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,IAAI,CAMN;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAqBR;AAED,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAUN;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,IAAI,CAUN"}
|
|
@@ -6,10 +6,11 @@ export interface QueuedChain {
|
|
|
6
6
|
queuedAt: number;
|
|
7
7
|
}
|
|
8
8
|
/** WRFC chain lifecycle states. */
|
|
9
|
-
export type WrfcState = 'pending' | 'engineering' | 'reviewing' | 'fixing' | 'awaiting_gates' | 'gating' | 'passed' | 'failed' | 'committing';
|
|
9
|
+
export type WrfcState = 'pending' | 'engineering' | 'integrating' | 'reviewing' | 'fixing' | 'awaiting_gates' | 'gating' | 'passed' | 'failed' | 'committing';
|
|
10
10
|
/** Agent role within a WRFC chain. The owner is the durable chain orchestrator. */
|
|
11
|
-
export type WrfcAgentRole = 'owner' | 'engineer' | 'reviewer' | 'fixer' | 'verifier';
|
|
12
|
-
export type
|
|
11
|
+
export type WrfcAgentRole = 'owner' | 'orchestrator' | 'engineer' | 'reviewer' | 'fixer' | 'integrator' | 'verifier';
|
|
12
|
+
export type WrfcSubtaskState = 'pending' | 'engineering' | 'reviewing' | 'fixing' | 'passed' | 'failed';
|
|
13
|
+
export type WrfcOwnerDecisionAction = 'chain_created' | 'compound_started' | 'spawn_engineer' | 'spawn_reviewer' | 'spawn_fixer' | 'spawn_integrator' | 'spawn_gate_fixer' | 'subtask_review_passed' | 'subtask_review_failed' | 'review_passed' | 'review_failed' | 'gate_passed' | 'gate_failed' | 'chain_passed' | 'chain_failed' | 'chain_cancelled' | 'owner_completion_ignored' | 'owner_failure_ignored' | 'resume_skipped' | 'resume_started';
|
|
13
14
|
export interface WrfcOwnerDecision {
|
|
14
15
|
id: string;
|
|
15
16
|
ts: string;
|
|
@@ -33,10 +34,31 @@ export interface WrfcChildRouteSelection {
|
|
|
33
34
|
}
|
|
34
35
|
export type WrfcChildRouteSelector = (context: {
|
|
35
36
|
readonly chain: WrfcChain;
|
|
36
|
-
readonly role: Exclude<WrfcAgentRole, 'owner' | 'verifier'>;
|
|
37
|
+
readonly role: Exclude<WrfcAgentRole, 'owner' | 'orchestrator' | 'verifier'>;
|
|
37
38
|
readonly task: string;
|
|
38
39
|
readonly ownerAgent: AgentRecord | null;
|
|
39
40
|
}) => WrfcChildRouteSelection | null | undefined;
|
|
41
|
+
export interface WrfcSubtask {
|
|
42
|
+
id: string;
|
|
43
|
+
title: string;
|
|
44
|
+
task: string;
|
|
45
|
+
state: WrfcSubtaskState;
|
|
46
|
+
currentNodeId?: string | undefined;
|
|
47
|
+
engineerAgentId?: string | undefined;
|
|
48
|
+
reviewerAgentId?: string | undefined;
|
|
49
|
+
fixerAgentId?: string | undefined;
|
|
50
|
+
engineerReport?: CompletionReport | undefined;
|
|
51
|
+
reviewerReport?: ReviewerReport | undefined;
|
|
52
|
+
fixAttempts: number;
|
|
53
|
+
reviewCycles: number;
|
|
54
|
+
reviewScores: number[];
|
|
55
|
+
constraints: Constraint[];
|
|
56
|
+
constraintsEnumerated: boolean;
|
|
57
|
+
syntheticIssues?: Array<{
|
|
58
|
+
severity: 'critical';
|
|
59
|
+
description: string;
|
|
60
|
+
}> | undefined;
|
|
61
|
+
}
|
|
40
62
|
/** A single WRFC chain instance. */
|
|
41
63
|
export interface WrfcChain {
|
|
42
64
|
id: string;
|
|
@@ -47,10 +69,13 @@ export interface WrfcChain {
|
|
|
47
69
|
engineerAgentId?: string | undefined;
|
|
48
70
|
reviewerAgentId?: string | undefined;
|
|
49
71
|
fixerAgentId?: string | undefined;
|
|
72
|
+
integratorAgentId?: string | undefined;
|
|
50
73
|
/** All agent IDs involved in this chain (for worktree cleanup). */
|
|
51
74
|
allAgentIds: string[];
|
|
52
75
|
engineerReport?: CompletionReport | undefined;
|
|
53
76
|
reviewerReport?: ReviewerReport | undefined;
|
|
77
|
+
integratorReport?: CompletionReport | undefined;
|
|
78
|
+
subtasks?: WrfcSubtask[] | undefined;
|
|
54
79
|
fixAttempts: number;
|
|
55
80
|
reviewCycles: number;
|
|
56
81
|
gateResults?: QualityGateResult[] | undefined;
|