@hamp10/agentforge 0.2.41 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hamp10/agentforge",
3
- "version": "0.2.41",
3
+ "version": "0.2.42",
4
4
  "description": "AgentForge worker — connect your machine to agentforge.ai",
5
5
  "type": "module",
6
6
  "bin": {
@@ -504,6 +504,16 @@ try {
504
504
  /Requested scoped UI targets: alpha, beta/i,
505
505
  'multi-target UI quality retries should preserve the full scoped target set'
506
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
+ );
507
517
  assert.match(
508
518
  worker._buildScopedUiTargetSetNudge(baseline, message),
509
519
  /one delivery set/i,
@@ -1119,11 +1129,31 @@ assert.match(
1119
1129
  /UI_QUALITY_NUDGE_LIMIT\s*=\s*isVisualUiTask\s*\?\s*Math\.min\(MAX_NUDGES,\s*3\)/,
1120
1130
  'visual UI quality repair loops should use the UI repair budget, not the smaller generic nudge limit'
1121
1131
  );
1122
- assert.match(
1123
- workerSource,
1124
- /UI_REPAIR_NUDGE_LIMIT[\s\S]*consumeUiRepairNudge[\s\S]*reached \$\{UI_REPAIR_NUDGE_LIMIT\} total repair retries/i,
1132
+ assert.match(
1133
+ workerSource,
1134
+ /UI_REPAIR_NUDGE_LIMIT[\s\S]*consumeUiRepairNudge[\s\S]*reached \$\{UI_REPAIR_NUDGE_LIMIT\} total repair retries/i,
1125
1135
  'visual UI retries need a global repair budget across rejection types'
1126
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
+ );
1127
1157
  assert.match(
1128
1158
  workerSource,
1129
1159
  /AGENTFORGE_UI_REPAIR_BUDGET \|\| '12'/,
package/src/worker.js CHANGED
@@ -1453,10 +1453,30 @@ export class AgentForgeWorker extends EventEmitter {
1453
1453
  return [
1454
1454
  'AgentForge removed the rejected generated target file(s) before this retry.',
1455
1455
  ...lines,
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, then verify the rebuilt pages visually.',
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.',
1457
1458
  ].join('\n');
1458
1459
  }
1459
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
+
1460
1480
  _findUiImplementationArtifactChanges(repoBaselines, userMessage) {
1461
1481
  if (!this._isBroadUiQualityTask(userMessage)) return [];
1462
1482
  if (!Array.isArray(repoBaselines) || repoBaselines.length === 0) return [];
@@ -4253,9 +4273,8 @@ export class AgentForgeWorker extends EventEmitter {
4253
4273
  const interimIncompleteScopedUiTargetsNudge = this._buildIncompleteScopedUiTargetsNudge(repoBaselines, scopeAwareUserMessage);
4254
4274
  if (interimIncompleteScopedUiTargetsNudge) {
4255
4275
  nudgeCount++;
4256
- const repairBudget = consumeUiRepairNudge('missed scoped UI target', interimIncompleteScopedUiTargetsNudge);
4257
4276
  if (nudgeCount < MAX_NUDGES) {
4258
- console.log(`[${taskId}] Iteration missed scoped UI target(s) — continuing (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${repairBudget})`);
4277
+ console.log(`[${taskId}] Iteration missed scoped UI target(s) — continuing (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${uiRepairNudgeCount}/${UI_REPAIR_NUDGE_LIMIT})`);
4259
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.`);
4260
4279
  continue;
4261
4280
  }
@@ -4374,9 +4393,15 @@ export class AgentForgeWorker extends EventEmitter {
4374
4393
  if (uiVerificationFailureNudge) {
4375
4394
  nudgeCount++;
4376
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);
4377
4399
  if (nudgeCount < MAX_NUDGES) {
4378
4400
  console.log(`[${taskId}] UI completion still had visual verification warnings — nudging (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${repairBudget})`);
4379
- iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${uiVerificationFailureNudge}\n\nFix the visible UI issues, verify again with the browser, and only then end with ✓ TASK_COMPLETE.`);
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.`);
4380
4405
  continue;
4381
4406
  }
4382
4407
  throw new Error('UI task claimed completion while visual verification still reported issues');
@@ -4415,9 +4440,8 @@ export class AgentForgeWorker extends EventEmitter {
4415
4440
  const incompleteScopedUiTargetsNudge = this._buildIncompleteScopedUiTargetsNudge(repoBaselines, scopeAwareUserMessage);
4416
4441
  if (incompleteScopedUiTargetsNudge) {
4417
4442
  nudgeCount++;
4418
- const repairBudget = consumeUiRepairNudge('completion missed scoped UI target', incompleteScopedUiTargetsNudge);
4419
4443
  if (nudgeCount < MAX_NUDGES) {
4420
- console.log(`[${taskId}] UI completion missed scoped target(s) — nudging (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${repairBudget})`);
4444
+ console.log(`[${taskId}] UI completion missed scoped target(s) — nudging (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${uiRepairNudgeCount}/${UI_REPAIR_NUDGE_LIMIT})`);
4421
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.`);
4422
4446
  continue;
4423
4447
  }
@@ -4641,9 +4665,15 @@ export class AgentForgeWorker extends EventEmitter {
4641
4665
  if (uiVerificationFailureNudge) {
4642
4666
  nudgeCount++;
4643
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);
4644
4671
  if (nudgeCount < MAX_NUDGES) {
4645
4672
  console.log(`[${taskId}] Publish evidence still had visual verification warnings — continuing (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${repairBudget})`);
4646
- iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${uiVerificationFailureNudge}\n\nContinue from the current repo state, fix the visible UI issues, verify again, then commit/push any additional changes before reporting delivery complete.`);
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.`);
4647
4677
  continue;
4648
4678
  }
4649
4679
  throw new Error('Publish task still had visual verification issues after repeated retries');
@@ -4682,9 +4712,8 @@ export class AgentForgeWorker extends EventEmitter {
4682
4712
  const incompleteScopedUiTargetsNudge = this._buildIncompleteScopedUiTargetsNudge(repoBaselines, scopeAwareUserMessage);
4683
4713
  if (incompleteScopedUiTargetsNudge) {
4684
4714
  nudgeCount++;
4685
- const repairBudget = consumeUiRepairNudge('publish missed scoped UI target', incompleteScopedUiTargetsNudge);
4686
4715
  if (nudgeCount < MAX_NUDGES) {
4687
- console.log(`[${taskId}] Publish evidence missed scoped target(s) — continuing (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${repairBudget})`);
4716
+ console.log(`[${taskId}] Publish evidence missed scoped target(s) — continuing (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${uiRepairNudgeCount}/${UI_REPAIR_NUDGE_LIMIT})`);
4688
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.`);
4689
4718
  continue;
4690
4719
  }
@@ -4780,12 +4809,18 @@ export class AgentForgeWorker extends EventEmitter {
4780
4809
  ? this._restoreGeneratedScopedUiTargets(repoBaselines, scopeAwareUserMessage, { onlySlugs: visualFailureSlugs })
4781
4810
  : []
4782
4811
  );
4812
+ const scopedTargetSetNudge = this._formatScopedUiTargetSetReminder(scopeAwareUserMessage);
4813
+ const repeatedVisualRepairNudge = this._formatRepeatedVisualRepairNudge(uiVerificationRetryCount);
4814
+ const visualFailureSummary = this._formatUiVerificationFailureLogSummary(visualVerificationFailureNudge);
4783
4815
  nudgeCount = 0;
4784
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
+ }
4785
4820
  const retryInstruction = generatedResetNudge
4786
- ? '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. 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.'
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.'
4787
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.';
4788
- 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}`);
4789
4824
  } else if (hasMissingLocalUiVerification) {
4790
4825
  uiVerificationRetryCount++;
4791
4826
  const uiVerificationFailureDetails = this._extractUiVerificationFailureDetails(output);
@@ -4800,12 +4835,14 @@ export class AgentForgeWorker extends EventEmitter {
4800
4835
  ? this._restoreGeneratedScopedUiTargets(repoBaselines, scopeAwareUserMessage, { onlySlugs: visualFailureSlugs })
4801
4836
  : []
4802
4837
  );
4838
+ const scopedTargetSetNudge = this._formatScopedUiTargetSetReminder(scopeAwareUserMessage);
4839
+ const repeatedVisualRepairNudge = this._formatRepeatedVisualRepairNudge(uiVerificationRetryCount);
4803
4840
  nudgeCount = 0;
4804
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})`);
4805
4842
  const retryInstruction = generatedResetNudge
4806
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.'
4807
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.';
4808
- 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 ? `\n\n${generatedResetNudge}` : ''}\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.`);
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.`);
4809
4846
  } else if (hasIncompleteTurn) {
4810
4847
  // openclaw reported an incomplete turn (payloads=0) after the agent used a tool.
4811
4848
  // This is a tool timeout, not a narration. Reset nudgeCount and give a targeted retry hint.