@hamp10/agentforge 0.2.40 → 0.2.42
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/package.json +1 -1
- package/scripts/check-task-semantics.js +76 -3
- package/src/worker.js +91 -16
package/package.json
CHANGED
|
@@ -340,6 +340,49 @@ try {
|
|
|
340
340
|
/removed 1 rejected generated scoped file/i,
|
|
341
341
|
'retry feedback should tell the agent that generated scoped pages were removed as failed output'
|
|
342
342
|
);
|
|
343
|
+
const generatedDeltaRel = 'public_html/domains/delta.html';
|
|
344
|
+
const generatedEpsilonRel = 'public_html/domains/epsilon.html';
|
|
345
|
+
writeFileSync(
|
|
346
|
+
path.join(fixture.repo, generatedDeltaRel),
|
|
347
|
+
'<!doctype html><html><body><main><section><h1>Delta</h1><p>New scoped page.</p></section></main></body></html>'
|
|
348
|
+
);
|
|
349
|
+
writeFileSync(
|
|
350
|
+
path.join(fixture.repo, generatedEpsilonRel),
|
|
351
|
+
'<!doctype html><html><body><main><section><h1>Epsilon</h1><p>New scoped page.</p></section></main></body></html>'
|
|
352
|
+
);
|
|
353
|
+
const multiGeneratedQualityMessage = 'Work on the Example.com listing pages for Delta.ai and Epsilon.ai. Make both pages visually polished.';
|
|
354
|
+
assert.deepEqual(
|
|
355
|
+
worker._extractUiVerificationFailureSlugs(
|
|
356
|
+
'delta.html: Visual warning: hero text fails local contrast verification.',
|
|
357
|
+
multiGeneratedQualityMessage
|
|
358
|
+
),
|
|
359
|
+
['delta-ai'],
|
|
360
|
+
'visual verification parsing should identify the scoped page named by a page-prefixed warning'
|
|
361
|
+
);
|
|
362
|
+
assert.deepEqual(
|
|
363
|
+
worker._extractUiVerificationFailureSlugs(
|
|
364
|
+
'Visual warning: hero text fails local contrast verification.',
|
|
365
|
+
multiGeneratedQualityMessage
|
|
366
|
+
),
|
|
367
|
+
[],
|
|
368
|
+
'generic visual warnings should not be treated as evidence to reset every generated scoped page'
|
|
369
|
+
);
|
|
370
|
+
worker._restoreGeneratedScopedUiTargets(
|
|
371
|
+
[{ root: fixture.repo, head: fixture.head, initialDirtyPaths: [] }],
|
|
372
|
+
multiGeneratedQualityMessage,
|
|
373
|
+
{ onlySlugs: ['delta-ai'] }
|
|
374
|
+
);
|
|
375
|
+
assert.equal(
|
|
376
|
+
existsSync(path.join(fixture.repo, generatedDeltaRel)),
|
|
377
|
+
false,
|
|
378
|
+
'page-aware generated resets should remove the rejected generated page'
|
|
379
|
+
);
|
|
380
|
+
assert.equal(
|
|
381
|
+
existsSync(path.join(fixture.repo, generatedEpsilonRel)),
|
|
382
|
+
true,
|
|
383
|
+
'page-aware generated resets should preserve unrelated generated scoped pages'
|
|
384
|
+
);
|
|
385
|
+
rmSync(path.join(fixture.repo, generatedEpsilonRel), { force: true });
|
|
343
386
|
const projectsRoot = mkdtempSync(path.join(tmpdir(), 'agentforge-project-list-'));
|
|
344
387
|
let agentWorkspace = null;
|
|
345
388
|
try {
|
|
@@ -461,6 +504,16 @@ try {
|
|
|
461
504
|
/Requested scoped UI targets: alpha, beta/i,
|
|
462
505
|
'multi-target UI quality retries should preserve the full scoped target set'
|
|
463
506
|
);
|
|
507
|
+
assert.equal(
|
|
508
|
+
worker._formatRepeatedVisualRepairNudge(2),
|
|
509
|
+
'',
|
|
510
|
+
'early visual repair retries should stay concise before escalation'
|
|
511
|
+
);
|
|
512
|
+
assert.match(
|
|
513
|
+
worker._formatRepeatedVisualRepairNudge(3),
|
|
514
|
+
/current repair strategy is not converging/i,
|
|
515
|
+
'repeated visual failures should force a strategy change instead of another micro-edit loop'
|
|
516
|
+
);
|
|
464
517
|
assert.match(
|
|
465
518
|
worker._buildScopedUiTargetSetNudge(baseline, message),
|
|
466
519
|
/one delivery set/i,
|
|
@@ -1076,11 +1129,31 @@ assert.match(
|
|
|
1076
1129
|
/UI_QUALITY_NUDGE_LIMIT\s*=\s*isVisualUiTask\s*\?\s*Math\.min\(MAX_NUDGES,\s*3\)/,
|
|
1077
1130
|
'visual UI quality repair loops should use the UI repair budget, not the smaller generic nudge limit'
|
|
1078
1131
|
);
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1132
|
+
assert.match(
|
|
1133
|
+
workerSource,
|
|
1134
|
+
/UI_REPAIR_NUDGE_LIMIT[\s\S]*consumeUiRepairNudge[\s\S]*reached \$\{UI_REPAIR_NUDGE_LIMIT\} total repair retries/i,
|
|
1082
1135
|
'visual UI retries need a global repair budget across rejection types'
|
|
1083
1136
|
);
|
|
1137
|
+
assert.doesNotMatch(
|
|
1138
|
+
workerSource,
|
|
1139
|
+
/consumeUiRepairNudge\('(?:completion |publish )?missed scoped UI target'/,
|
|
1140
|
+
'missing scoped target recovery should not spend the visual QA budget that may have been consumed by prior screenshot failures'
|
|
1141
|
+
);
|
|
1142
|
+
assert.match(
|
|
1143
|
+
workerSource,
|
|
1144
|
+
/_formatRepeatedVisualRepairNudge[\s\S]*current repair strategy is not converging/i,
|
|
1145
|
+
'repeated visual failures should inject a generic strategy-change nudge'
|
|
1146
|
+
);
|
|
1147
|
+
assert.match(
|
|
1148
|
+
workerSource,
|
|
1149
|
+
/_formatUiVerificationFailureLogSummary[\s\S]*UI visual verification issue\(s\)/i,
|
|
1150
|
+
'worker logs should expose concise visual verification issues for operators'
|
|
1151
|
+
);
|
|
1152
|
+
assert.match(
|
|
1153
|
+
workerSource,
|
|
1154
|
+
/Address every requested target that is currently missing or changed in one coherent pass/i,
|
|
1155
|
+
'generated-page visual retries should preserve the full delivery set after selective resets'
|
|
1156
|
+
);
|
|
1084
1157
|
assert.match(
|
|
1085
1158
|
workerSource,
|
|
1086
1159
|
/AGENTFORGE_UI_REPAIR_BUDGET \|\| '12'/,
|
package/src/worker.js
CHANGED
|
@@ -945,11 +945,19 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
945
945
|
return restored;
|
|
946
946
|
}
|
|
947
947
|
|
|
948
|
-
|
|
948
|
+
_scopedUiPathMatchesAnySlug(relativePath, slugs) {
|
|
949
|
+
const matches = this._scopeSlugsMatchingText(relativePath, slugs);
|
|
950
|
+
return matches.length > 0;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
_restoreGeneratedScopedUiTargets(repoBaselines, userMessage, options = {}) {
|
|
949
954
|
if (!this._isBroadUiQualityTask(userMessage)) return [];
|
|
950
955
|
if (!Array.isArray(repoBaselines) || repoBaselines.length === 0) return [];
|
|
951
956
|
const { slugs: allowedSlugs, pageOnly } = this._extractExplicitScope(userMessage);
|
|
952
957
|
if (allowedSlugs.length === 0 || !pageOnly) return [];
|
|
958
|
+
const onlySlugs = Array.isArray(options.onlySlugs)
|
|
959
|
+
? [...new Set(options.onlySlugs.map(slug => this._scopeSlug(slug)).filter(Boolean))]
|
|
960
|
+
: [];
|
|
953
961
|
|
|
954
962
|
const restored = [];
|
|
955
963
|
for (const baseline of repoBaselines) {
|
|
@@ -970,6 +978,7 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
970
978
|
const files = [...names]
|
|
971
979
|
.filter(rel => !initialDirty.has(rel))
|
|
972
980
|
.filter(rel => this._scopeAllowsChangedPath(baseline, rel, allowedSlugs, pageOnly, userMessage))
|
|
981
|
+
.filter(rel => onlySlugs.length === 0 || this._scopedUiPathMatchesAnySlug(rel, onlySlugs))
|
|
973
982
|
.filter(rel => !this._gitPathExistsAtRef(baseline.root, baseline.head || 'HEAD', rel))
|
|
974
983
|
.sort();
|
|
975
984
|
if (files.length === 0) continue;
|
|
@@ -1444,10 +1453,30 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
1444
1453
|
return [
|
|
1445
1454
|
'AgentForge removed the rejected generated target file(s) before this retry.',
|
|
1446
1455
|
...lines,
|
|
1447
|
-
'Treat those removed files as failed output, not source material. Rebuild the requested target page-owned file(s) from inspected project context and comparable existing pages
|
|
1456
|
+
'Treat those removed files as failed output, not source material. Rebuild the requested target page-owned file(s) from inspected project context and comparable existing pages before optional refinements to other targets.',
|
|
1457
|
+
'If the task names multiple target pages, keep them as one delivery set: every named target must exist, be materially addressed, and be visually verified before completion.',
|
|
1448
1458
|
].join('\n');
|
|
1449
1459
|
}
|
|
1450
1460
|
|
|
1461
|
+
_formatRepeatedVisualRepairNudge(attempt = 1) {
|
|
1462
|
+
if (Number(attempt || 1) < 3) return '';
|
|
1463
|
+
return [
|
|
1464
|
+
'Repeated visual verification is still failing, so the current repair strategy is not converging.',
|
|
1465
|
+
'Switch strategy before the next verification pass: make a coherent page-owned structural pass instead of isolated warning fixes, stale-string edits, color tweaks, or hero-only adjustments.',
|
|
1466
|
+
'Inspect the screenshots as whole screens across top, middle, and lower viewports. Resolve the underlying composition, readability, spacing, section balance, and content-depth problems in the target-owned files, then verify every requested target page again.',
|
|
1467
|
+
].join('\n');
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
_formatUiVerificationFailureLogSummary(nudge) {
|
|
1471
|
+
const lines = String(nudge || '')
|
|
1472
|
+
.split('\n')
|
|
1473
|
+
.map(line => line.trim())
|
|
1474
|
+
.filter(line => /(?:^|[\s:])(Visual warning|Style warning):/i.test(line))
|
|
1475
|
+
.slice(0, 3)
|
|
1476
|
+
.map(line => line.replace(/\s+/g, ' ').slice(0, 240));
|
|
1477
|
+
return lines.join(' | ');
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1451
1480
|
_findUiImplementationArtifactChanges(repoBaselines, userMessage) {
|
|
1452
1481
|
if (!this._isBroadUiQualityTask(userMessage)) return [];
|
|
1453
1482
|
if (!Array.isArray(repoBaselines) || repoBaselines.length === 0) return [];
|
|
@@ -4244,9 +4273,8 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
4244
4273
|
const interimIncompleteScopedUiTargetsNudge = this._buildIncompleteScopedUiTargetsNudge(repoBaselines, scopeAwareUserMessage);
|
|
4245
4274
|
if (interimIncompleteScopedUiTargetsNudge) {
|
|
4246
4275
|
nudgeCount++;
|
|
4247
|
-
const repairBudget = consumeUiRepairNudge('missed scoped UI target', interimIncompleteScopedUiTargetsNudge);
|
|
4248
4276
|
if (nudgeCount < MAX_NUDGES) {
|
|
4249
|
-
console.log(`[${taskId}] Iteration missed scoped UI target(s) — continuing (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${
|
|
4277
|
+
console.log(`[${taskId}] Iteration missed scoped UI target(s) — continuing (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${uiRepairNudgeCount}/${UI_REPAIR_NUDGE_LIMIT})`);
|
|
4250
4278
|
iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${interimIncompleteScopedUiTargetsNudge}\n\nContinue from the current changed files. Do not restart from scratch; address the missing target page(s), then verify each edited target screen after the final edit.`);
|
|
4251
4279
|
continue;
|
|
4252
4280
|
}
|
|
@@ -4365,9 +4393,15 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
4365
4393
|
if (uiVerificationFailureNudge) {
|
|
4366
4394
|
nudgeCount++;
|
|
4367
4395
|
const repairBudget = consumeUiRepairNudge('visual verification warnings', uiVerificationFailureNudge);
|
|
4396
|
+
const scopedTargetSetNudge = this._formatScopedUiTargetSetReminder(scopeAwareUserMessage);
|
|
4397
|
+
const repeatedVisualRepairNudge = this._formatRepeatedVisualRepairNudge(uiRepairNudgeCount);
|
|
4398
|
+
const visualFailureSummary = this._formatUiVerificationFailureLogSummary(uiVerificationFailureNudge);
|
|
4368
4399
|
if (nudgeCount < MAX_NUDGES) {
|
|
4369
4400
|
console.log(`[${taskId}] UI completion still had visual verification warnings — nudging (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${repairBudget})`);
|
|
4370
|
-
|
|
4401
|
+
if (visualFailureSummary) {
|
|
4402
|
+
console.log(`[${taskId}] UI visual verification issue(s): ${visualFailureSummary}`);
|
|
4403
|
+
}
|
|
4404
|
+
iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${[uiVerificationFailureNudge, scopedTargetSetNudge, repeatedVisualRepairNudge].filter(Boolean).join('\n\n')}\n\nFix the visible UI issues, verify again with the browser, and only then end with ✓ TASK_COMPLETE.`);
|
|
4371
4405
|
continue;
|
|
4372
4406
|
}
|
|
4373
4407
|
throw new Error('UI task claimed completion while visual verification still reported issues');
|
|
@@ -4406,9 +4440,8 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
4406
4440
|
const incompleteScopedUiTargetsNudge = this._buildIncompleteScopedUiTargetsNudge(repoBaselines, scopeAwareUserMessage);
|
|
4407
4441
|
if (incompleteScopedUiTargetsNudge) {
|
|
4408
4442
|
nudgeCount++;
|
|
4409
|
-
const repairBudget = consumeUiRepairNudge('completion missed scoped UI target', incompleteScopedUiTargetsNudge);
|
|
4410
4443
|
if (nudgeCount < MAX_NUDGES) {
|
|
4411
|
-
console.log(`[${taskId}] UI completion missed scoped target(s) — nudging (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${
|
|
4444
|
+
console.log(`[${taskId}] UI completion missed scoped target(s) — nudging (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${uiRepairNudgeCount}/${UI_REPAIR_NUDGE_LIMIT})`);
|
|
4412
4445
|
iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${incompleteScopedUiTargetsNudge}\n\nDo not mark complete until every named target page has been addressed directly and visually verified.`);
|
|
4413
4446
|
continue;
|
|
4414
4447
|
}
|
|
@@ -4632,9 +4665,15 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
4632
4665
|
if (uiVerificationFailureNudge) {
|
|
4633
4666
|
nudgeCount++;
|
|
4634
4667
|
const repairBudget = consumeUiRepairNudge('publish visual verification warnings', uiVerificationFailureNudge);
|
|
4668
|
+
const scopedTargetSetNudge = this._formatScopedUiTargetSetReminder(scopeAwareUserMessage);
|
|
4669
|
+
const repeatedVisualRepairNudge = this._formatRepeatedVisualRepairNudge(uiRepairNudgeCount);
|
|
4670
|
+
const visualFailureSummary = this._formatUiVerificationFailureLogSummary(uiVerificationFailureNudge);
|
|
4635
4671
|
if (nudgeCount < MAX_NUDGES) {
|
|
4636
4672
|
console.log(`[${taskId}] Publish evidence still had visual verification warnings — continuing (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${repairBudget})`);
|
|
4637
|
-
|
|
4673
|
+
if (visualFailureSummary) {
|
|
4674
|
+
console.log(`[${taskId}] UI visual verification issue(s): ${visualFailureSummary}`);
|
|
4675
|
+
}
|
|
4676
|
+
iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${[uiVerificationFailureNudge, scopedTargetSetNudge, repeatedVisualRepairNudge].filter(Boolean).join('\n\n')}\n\nContinue from the current repo state, fix the visible UI issues, verify again, then commit/push any additional changes before reporting delivery complete.`);
|
|
4638
4677
|
continue;
|
|
4639
4678
|
}
|
|
4640
4679
|
throw new Error('Publish task still had visual verification issues after repeated retries');
|
|
@@ -4673,9 +4712,8 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
4673
4712
|
const incompleteScopedUiTargetsNudge = this._buildIncompleteScopedUiTargetsNudge(repoBaselines, scopeAwareUserMessage);
|
|
4674
4713
|
if (incompleteScopedUiTargetsNudge) {
|
|
4675
4714
|
nudgeCount++;
|
|
4676
|
-
const repairBudget = consumeUiRepairNudge('publish missed scoped UI target', incompleteScopedUiTargetsNudge);
|
|
4677
4715
|
if (nudgeCount < MAX_NUDGES) {
|
|
4678
|
-
console.log(`[${taskId}] Publish evidence missed scoped target(s) — continuing (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${
|
|
4716
|
+
console.log(`[${taskId}] Publish evidence missed scoped target(s) — continuing (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${uiRepairNudgeCount}/${UI_REPAIR_NUDGE_LIMIT})`);
|
|
4679
4717
|
iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${incompleteScopedUiTargetsNudge}\n\nContinue from the current repo state, address the missing target page(s), verify all edited target screens, then commit/push any additional changes before reporting delivery complete.`);
|
|
4680
4718
|
continue;
|
|
4681
4719
|
}
|
|
@@ -4765,15 +4803,24 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
4765
4803
|
throw new Error('UI task failed visual verification after repeated repair attempts');
|
|
4766
4804
|
}
|
|
4767
4805
|
const repairBudget = consumeUiRepairNudge('visual verification warnings', visualVerificationFailureNudge);
|
|
4806
|
+
const visualFailureSlugs = this._extractUiVerificationFailureSlugs(output, scopeAwareUserMessage);
|
|
4768
4807
|
const generatedResetNudge = this._formatGeneratedScopedUiResetNudge(
|
|
4769
|
-
|
|
4808
|
+
visualFailureSlugs.length > 0
|
|
4809
|
+
? this._restoreGeneratedScopedUiTargets(repoBaselines, scopeAwareUserMessage, { onlySlugs: visualFailureSlugs })
|
|
4810
|
+
: []
|
|
4770
4811
|
);
|
|
4812
|
+
const scopedTargetSetNudge = this._formatScopedUiTargetSetReminder(scopeAwareUserMessage);
|
|
4813
|
+
const repeatedVisualRepairNudge = this._formatRepeatedVisualRepairNudge(uiVerificationRetryCount);
|
|
4814
|
+
const visualFailureSummary = this._formatUiVerificationFailureLogSummary(visualVerificationFailureNudge);
|
|
4771
4815
|
nudgeCount = 0;
|
|
4772
4816
|
console.log(`[${taskId}] UI task visual verification still reported visible issues — retrying (${uiVerificationRetryCount}/${UI_REPAIR_NUDGE_LIMIT}, total UI repairs ${repairBudget})`);
|
|
4817
|
+
if (visualFailureSummary) {
|
|
4818
|
+
console.log(`[${taskId}] UI visual verification issue(s): ${visualFailureSummary}`);
|
|
4819
|
+
}
|
|
4773
4820
|
const retryInstruction = generatedResetNudge
|
|
4774
|
-
? 'Rebuild the removed target page file(s) from already-inspected project context and comparable existing pages. Do not reuse the rejected generated page as the basis for the next attempt.
|
|
4821
|
+
? 'Rebuild the removed target page file(s) from already-inspected project context and comparable existing pages. Do not reuse the rejected generated page as the basis for the next attempt. Address every requested target that is currently missing or changed in one coherent pass, fix the visible issues reported by local browser verification, reopen each edited target screen locally after the final edit, and only then end with ✓ TASK_COMPLETE.'
|
|
4775
4822
|
: 'Continue from the current changed files and latest browser evidence. Fix the visible issues reported by the local browser verification, reopen each edited target screen locally after the final edit, and only then end with ✓ TASK_COMPLETE.';
|
|
4776
|
-
iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${[visualVerificationFailureNudge, generatedResetNudge].filter(Boolean).join('\n\n')}\n\n${retryInstruction}`);
|
|
4823
|
+
iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${[visualVerificationFailureNudge, generatedResetNudge, scopedTargetSetNudge, repeatedVisualRepairNudge].filter(Boolean).join('\n\n')}\n\n${retryInstruction}`);
|
|
4777
4824
|
} else if (hasMissingLocalUiVerification) {
|
|
4778
4825
|
uiVerificationRetryCount++;
|
|
4779
4826
|
const uiVerificationFailureDetails = this._extractUiVerificationFailureDetails(output);
|
|
@@ -4782,15 +4829,20 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
4782
4829
|
throw new Error('UI task failed visual verification after repeated repair attempts');
|
|
4783
4830
|
}
|
|
4784
4831
|
const repairBudget = consumeUiRepairNudge('missing local visual verification', uiVerificationFailureDetails);
|
|
4832
|
+
const visualFailureSlugs = this._extractUiVerificationFailureSlugs(output, scopeAwareUserMessage);
|
|
4785
4833
|
const generatedResetNudge = this._formatGeneratedScopedUiResetNudge(
|
|
4786
|
-
|
|
4834
|
+
visualFailureSlugs.length > 0
|
|
4835
|
+
? this._restoreGeneratedScopedUiTargets(repoBaselines, scopeAwareUserMessage, { onlySlugs: visualFailureSlugs })
|
|
4836
|
+
: []
|
|
4787
4837
|
);
|
|
4838
|
+
const scopedTargetSetNudge = this._formatScopedUiTargetSetReminder(scopeAwareUserMessage);
|
|
4839
|
+
const repeatedVisualRepairNudge = this._formatRepeatedVisualRepairNudge(uiVerificationRetryCount);
|
|
4788
4840
|
nudgeCount = 0;
|
|
4789
4841
|
console.log(`[${taskId}] UI task missing local visual verification — retrying with local-app repair instruction (${uiVerificationRetryCount}/${UI_REPAIR_NUDGE_LIMIT}, total UI repairs ${repairBudget})`);
|
|
4790
4842
|
const retryInstruction = generatedResetNudge
|
|
4791
4843
|
? 'Rebuild the removed target page file(s) from already-inspected project context and comparable existing pages. Do not reuse the rejected generated page as the basis for the next attempt.'
|
|
4792
4844
|
: 'Continue from the current changed files and already-inspected project context. Do not restart from scratch, repeat initial delete/reset/setup steps, discard existing progress, or reread site indexes, shared/global CSS, header/footer partials, or unrelated reference pages unless a specific verification issue requires it.';
|
|
4793
|
-
iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\nYour edits are not complete because the changed UI was not successfully loaded and inspected cleanly in its actual local app URL.${uiVerificationFailureDetails ? `\n\nSpecific verification issue(s):\n${uiVerificationFailureDetails}` : ''}${generatedResetNudge
|
|
4845
|
+
iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\nYour edits are not complete because the changed UI was not successfully loaded and inspected cleanly in its actual local app URL.${uiVerificationFailureDetails ? `\n\nSpecific verification issue(s):\n${uiVerificationFailureDetails}` : ''}${[generatedResetNudge, scopedTargetSetNudge, repeatedVisualRepairNudge].filter(Boolean).map(text => `\n\n${text}`).join('')}\n\n${retryInstruction} Do not use external sites, site indexes, listing indexes, shared style files, or reference pages as final verification for scoped UI edits. Start or repair the project's local dev/static server if needed, use the port the project actually declares, open the real localhost/127.0.0.1 URL for each edited target screen, inspect the changed screen, fix visible issues, and only then end with ✓ TASK_COMPLETE.`);
|
|
4794
4846
|
} else if (hasIncompleteTurn) {
|
|
4795
4847
|
// openclaw reported an incomplete turn (payloads=0) after the agent used a tool.
|
|
4796
4848
|
// This is a tool timeout, not a narration. Reset nudgeCount and give a targeted retry hint.
|
|
@@ -5876,7 +5928,7 @@ end tell`.trim().replace(/\n/g, '\n');
|
|
|
5876
5928
|
.split('\n')
|
|
5877
5929
|
.map(line => line.trim())
|
|
5878
5930
|
.filter(line =>
|
|
5879
|
-
|
|
5931
|
+
/(?:^|[\s:])(?:Style|Visual) warning:/i.test(line) ||
|
|
5880
5932
|
/Browser failed to load/i.test(line) ||
|
|
5881
5933
|
/changed UI was not successfully loaded and inspected/i.test(line) ||
|
|
5882
5934
|
/latest visual verification still reported/i.test(line) ||
|
|
@@ -5886,6 +5938,29 @@ end tell`.trim().replace(/\n/g, '\n');
|
|
|
5886
5938
|
return unique.join('\n').slice(0, 1800);
|
|
5887
5939
|
}
|
|
5888
5940
|
|
|
5941
|
+
_extractUiVerificationFailureSlugs(output, userMessage) {
|
|
5942
|
+
const { slugs: allowedSlugs } = this._extractExplicitScope(userMessage);
|
|
5943
|
+
if (allowedSlugs.length === 0) return [];
|
|
5944
|
+
const lines = String(output || '')
|
|
5945
|
+
.split('\n')
|
|
5946
|
+
.map(line => line.trim())
|
|
5947
|
+
.filter(line =>
|
|
5948
|
+
/(?:^|[\s:])(?:Style|Visual) warning:/i.test(line) ||
|
|
5949
|
+
/Browser failed to load/i.test(line) ||
|
|
5950
|
+
/changed UI was not successfully loaded and inspected/i.test(line) ||
|
|
5951
|
+
/latest visual verification still reported/i.test(line) ||
|
|
5952
|
+
/This is not complete/i.test(line)
|
|
5953
|
+
);
|
|
5954
|
+
if (lines.length === 0) return [];
|
|
5955
|
+
const matched = new Set();
|
|
5956
|
+
for (const line of lines) {
|
|
5957
|
+
for (const slug of this._scopeSlugsMatchingText(line, allowedSlugs)) {
|
|
5958
|
+
matched.add(slug);
|
|
5959
|
+
}
|
|
5960
|
+
}
|
|
5961
|
+
return [...matched];
|
|
5962
|
+
}
|
|
5963
|
+
|
|
5889
5964
|
_buildUiVerificationFailureNudge(output) {
|
|
5890
5965
|
const details = this._extractUiVerificationFailureDetails(output);
|
|
5891
5966
|
const genericFailure =
|