@hamp10/agentforge 0.2.44 → 0.2.46

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.44",
3
+ "version": "0.2.46",
4
4
  "description": "AgentForge worker — connect your machine to agentforge.ai",
5
5
  "type": "module",
6
6
  "bin": {
@@ -303,6 +303,16 @@ try {
303
303
  '',
304
304
  'new untracked scoped page files should count as touched UI targets'
305
305
  );
306
+ git(fixture.repo, ['add', untrackedGammaRel]);
307
+ assert.equal(
308
+ worker._buildIncompleteScopedUiTargetsNudge(
309
+ [{ root: fixture.repo, head: fixture.head, initialDirtyPaths: [] }],
310
+ 'Work on the Example.com listing pages for Alpha.ai, Beta.ai, and Gamma.ai. Make all three pages visually polished.'
311
+ ),
312
+ '',
313
+ 'new staged scoped page files should count as touched UI targets'
314
+ );
315
+ git(fixture.repo, ['restore', '--staged', untrackedGammaRel]);
306
316
  rmSync(path.join(fixture.repo, untrackedGammaRel), { force: true });
307
317
  const untrackedShallowGammaHtml = [
308
318
  '<!doctype html>',
@@ -522,6 +532,14 @@ try {
522
532
  /current repair strategy is not converging/i,
523
533
  'repeated visual failures should force a strategy change instead of another micro-edit loop'
524
534
  );
535
+ assert.match(
536
+ worker._formatVisualFailureFocusNudge(
537
+ 'gamma-ai: Visual warning: target hero text is clipped.',
538
+ 'Work on the Example.com listing pages for Alpha.ai, Beta.ai, and Gamma.ai. Delete and rebuild Alpha.ai and Beta.ai from a clean start, and fix Gamma.ai so all three are visually polished.'
539
+ ),
540
+ /Keep other requested target page\(s\) intact[\s\S]*alpha-ai, beta-ai/i,
541
+ 'visual-warning retries should focus on the failing target instead of recreating unrelated completed targets'
542
+ );
525
543
  assert.match(
526
544
  worker._buildScopedUiTargetSetNudge(baseline, message),
527
545
  /one delivery set/i,
@@ -1167,6 +1185,11 @@ assert.match(
1167
1185
  /_formatRepeatedVisualRepairNudge[\s\S]*current repair strategy is not converging/i,
1168
1186
  'repeated visual failures should inject a generic strategy-change nudge'
1169
1187
  );
1188
+ assert.match(
1189
+ workerSource,
1190
+ /_formatVisualFailureFocusNudge[\s\S]*Do not delete or recreate already-built target pages during a visual-warning repair/i,
1191
+ 'visual-warning retries should preserve completed targets outside the failing page'
1192
+ );
1170
1193
  assert.match(
1171
1194
  workerSource,
1172
1195
  /_formatUiVerificationFailureLogSummary[\s\S]*UI visual verification issue\(s\)/i,
@@ -1327,6 +1350,16 @@ assert.match(
1327
1350
  /const visualWarnings = \[\];[\s\S]*visualWarnings\.push\(`\$\{slug\}: \$\{visualWarning\}`\);[\s\S]*continue;[\s\S]*lastDirectVisualWarning = visualWarnings\.join\('\\n'\);/i,
1328
1351
  'multi-target scoped verification should inspect every missing target before returning visual warnings'
1329
1352
  );
1353
+ assert.match(
1354
+ workerSource,
1355
+ /diff', '--cached', '--numstat'/,
1356
+ 'scoped UI target checks should count staged changes as touched targets'
1357
+ );
1358
+ assert.match(
1359
+ workerSource,
1360
+ /diff', '--cached', '--unified=0'/,
1361
+ 'UI quality artifact checks should inspect staged source diffs before commit'
1362
+ );
1330
1363
  assert.match(
1331
1364
  openClawSource,
1332
1365
  /Network\.setCacheDisabled[\s\S]*waitForRequestedDocument/i,
package/src/worker.js CHANGED
@@ -562,8 +562,12 @@ export class AgentForgeWorker extends EventEmitter {
562
562
  this._gitOutput(baseline.root, ['diff', '--numstat'], 10000),
563
563
  'working tree'
564
564
  );
565
+ const staged = this._parseNumstat(
566
+ this._gitOutput(baseline.root, ['diff', '--cached', '--numstat'], 10000),
567
+ 'staged'
568
+ );
565
569
  const byPath = new Map();
566
- for (const stat of [...committed, ...working]) {
570
+ for (const stat of [...committed, ...staged, ...working]) {
567
571
  const key = stat.path;
568
572
  const current = byPath.get(key) || { additions: 0, deletions: 0, path: key, sources: new Set() };
569
573
  current.additions += stat.additions;
@@ -1185,6 +1189,10 @@ export class AgentForgeWorker extends EventEmitter {
1185
1189
  this._gitOutput(baseline.root, ['diff', '--numstat'], 10000),
1186
1190
  'working tree'
1187
1191
  );
1192
+ const staged = this._parseNumstat(
1193
+ this._gitOutput(baseline.root, ['diff', '--cached', '--numstat'], 10000),
1194
+ 'staged'
1195
+ );
1188
1196
  const untracked = this._listUntrackedUiFiles(baseline, userMessage, { scopedOnly: true })
1189
1197
  .map(rel => {
1190
1198
  let additions = 0;
@@ -1198,7 +1206,7 @@ export class AgentForgeWorker extends EventEmitter {
1198
1206
  }
1199
1207
  return { additions, deletions: 0, path: rel, source: 'untracked' };
1200
1208
  });
1201
- const combined = [...committed, ...working, ...untracked]
1209
+ const combined = [...committed, ...staged, ...working, ...untracked]
1202
1210
  .filter(stat => /\.(html?|css|s[ac]ss|jsx?|tsx?|vue|svelte|astro|mdx?)$/i.test(stat.path));
1203
1211
  if (combined.length === 0) continue;
1204
1212
 
@@ -1349,6 +1357,7 @@ export class AgentForgeWorker extends EventEmitter {
1349
1357
  for (const baseline of repoBaselines) {
1350
1358
  const byPath = new Map();
1351
1359
  scanDiff(baseline, ['diff', '--unified=0', `${baseline.head}..HEAD`], 'committed', byPath);
1360
+ scanDiff(baseline, ['diff', '--cached', '--unified=0'], 'staged', byPath);
1352
1361
  scanDiff(baseline, ['diff', '--unified=0'], 'working tree', byPath);
1353
1362
  scanUntracked(baseline, byPath);
1354
1363
  const changedFiles = [...byPath.values()];
@@ -1467,6 +1476,21 @@ export class AgentForgeWorker extends EventEmitter {
1467
1476
  ].join('\n');
1468
1477
  }
1469
1478
 
1479
+ _formatVisualFailureFocusNudge(output, userMessage) {
1480
+ const { slugs: allSlugs } = this._extractExplicitScope(userMessage);
1481
+ const failedSlugs = this._extractUiVerificationFailureSlugs(output, userMessage);
1482
+ if (allSlugs.length < 2 || failedSlugs.length === 0 || failedSlugs.length >= allSlugs.length) return '';
1483
+ const untouched = allSlugs.filter(slug => !failedSlugs.includes(slug));
1484
+ return [
1485
+ `Current visual verification warnings identify target page(s): ${failedSlugs.join(', ')}.`,
1486
+ untouched.length > 0
1487
+ ? `Keep other requested target page(s) intact unless their own verification reports a concrete issue: ${untouched.join(', ')}.`
1488
+ : '',
1489
+ 'If the original task included delete/rebuild or clean-start language, treat that as already satisfied for target files that now exist. Do not delete or recreate already-built target pages during a visual-warning repair unless the warning is for that same page.',
1490
+ 'After fixing the failing target-owned structure, re-verify every requested target page locally before commit or completion.',
1491
+ ].filter(Boolean).join('\n');
1492
+ }
1493
+
1470
1494
  _formatUiVerificationFailureLogSummary(nudge) {
1471
1495
  const lines = String(nudge || '')
1472
1496
  .split('\n')
@@ -1584,6 +1608,7 @@ export class AgentForgeWorker extends EventEmitter {
1584
1608
 
1585
1609
  for (const baseline of repoBaselines) {
1586
1610
  scanDiff(baseline, ['diff', '--unified=0', `${baseline.head}..HEAD`], 'committed');
1611
+ scanDiff(baseline, ['diff', '--cached', '--unified=0'], 'staged');
1587
1612
  scanDiff(baseline, ['diff', '--unified=0'], 'working tree');
1588
1613
  }
1589
1614
 
@@ -1635,6 +1660,10 @@ export class AgentForgeWorker extends EventEmitter {
1635
1660
  this._gitOutput(baseline.root, ['diff', '--numstat'], 10000),
1636
1661
  'working tree'
1637
1662
  );
1663
+ const staged = this._parseNumstat(
1664
+ this._gitOutput(baseline.root, ['diff', '--cached', '--numstat'], 10000),
1665
+ 'staged'
1666
+ );
1638
1667
  const initialDirty = new Set(baseline.initialDirtyPaths || []);
1639
1668
  const untracked = String(this._gitOutput(baseline.root, ['ls-files', '--others', '--exclude-standard'], 10000) || '')
1640
1669
  .split('\n')
@@ -1643,7 +1672,7 @@ export class AgentForgeWorker extends EventEmitter {
1643
1672
  .filter(rel => uiFileRe.test(rel))
1644
1673
  .filter(rel => !initialDirty.has(rel))
1645
1674
  .filter(rel => !this._isNestedProjectCopyRel(baseline.root, rel, baseline.head || 'HEAD'));
1646
- const changedFiles = [...committed, ...working]
1675
+ const changedFiles = [...committed, ...staged, ...working]
1647
1676
  .filter(stat => uiFileRe.test(stat.path))
1648
1677
  .map(stat => stat.path)
1649
1678
  .concat(untracked);
@@ -4395,13 +4424,14 @@ export class AgentForgeWorker extends EventEmitter {
4395
4424
  const repairBudget = consumeUiRepairNudge('visual verification warnings', uiVerificationFailureNudge);
4396
4425
  const scopedTargetSetNudge = this._formatScopedUiTargetSetReminder(scopeAwareUserMessage);
4397
4426
  const repeatedVisualRepairNudge = this._formatRepeatedVisualRepairNudge(uiRepairNudgeCount);
4427
+ const visualFailureFocusNudge = this._formatVisualFailureFocusNudge(output, scopeAwareUserMessage);
4398
4428
  const visualFailureSummary = this._formatUiVerificationFailureLogSummary(uiVerificationFailureNudge);
4399
4429
  if (nudgeCount < MAX_NUDGES) {
4400
4430
  console.log(`[${taskId}] UI completion still had visual verification warnings — nudging (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${repairBudget})`);
4401
4431
  if (visualFailureSummary) {
4402
4432
  console.log(`[${taskId}] UI visual verification issue(s): ${visualFailureSummary}`);
4403
4433
  }
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.`);
4434
+ iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${[uiVerificationFailureNudge, visualFailureFocusNudge, 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.`);
4405
4435
  continue;
4406
4436
  }
4407
4437
  throw new Error('UI task claimed completion while visual verification still reported issues');
@@ -4667,13 +4697,14 @@ export class AgentForgeWorker extends EventEmitter {
4667
4697
  const repairBudget = consumeUiRepairNudge('publish visual verification warnings', uiVerificationFailureNudge);
4668
4698
  const scopedTargetSetNudge = this._formatScopedUiTargetSetReminder(scopeAwareUserMessage);
4669
4699
  const repeatedVisualRepairNudge = this._formatRepeatedVisualRepairNudge(uiRepairNudgeCount);
4700
+ const visualFailureFocusNudge = this._formatVisualFailureFocusNudge(output, scopeAwareUserMessage);
4670
4701
  const visualFailureSummary = this._formatUiVerificationFailureLogSummary(uiVerificationFailureNudge);
4671
4702
  if (nudgeCount < MAX_NUDGES) {
4672
4703
  console.log(`[${taskId}] Publish evidence still had visual verification warnings — continuing (${nudgeCount}/${MAX_NUDGES}, total UI repairs ${repairBudget})`);
4673
4704
  if (visualFailureSummary) {
4674
4705
  console.log(`[${taskId}] UI visual verification issue(s): ${visualFailureSummary}`);
4675
4706
  }
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.`);
4707
+ iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${[uiVerificationFailureNudge, visualFailureFocusNudge, 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.`);
4677
4708
  continue;
4678
4709
  }
4679
4710
  throw new Error('Publish task still had visual verification issues after repeated retries');
@@ -4811,6 +4842,7 @@ export class AgentForgeWorker extends EventEmitter {
4811
4842
  );
4812
4843
  const scopedTargetSetNudge = this._formatScopedUiTargetSetReminder(scopeAwareUserMessage);
4813
4844
  const repeatedVisualRepairNudge = this._formatRepeatedVisualRepairNudge(uiVerificationRetryCount);
4845
+ const visualFailureFocusNudge = this._formatVisualFailureFocusNudge(output, scopeAwareUserMessage);
4814
4846
  const visualFailureSummary = this._formatUiVerificationFailureLogSummary(visualVerificationFailureNudge);
4815
4847
  nudgeCount = 0;
4816
4848
  console.log(`[${taskId}] UI task visual verification still reported visible issues — retrying (${uiVerificationRetryCount}/${UI_REPAIR_NUDGE_LIMIT}, total UI repairs ${repairBudget})`);
@@ -4820,7 +4852,7 @@ export class AgentForgeWorker extends EventEmitter {
4820
4852
  const retryInstruction = generatedResetNudge
4821
4853
  ? '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.'
4822
4854
  : '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.';
4823
- iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${[visualVerificationFailureNudge, generatedResetNudge, scopedTargetSetNudge, repeatedVisualRepairNudge].filter(Boolean).join('\n\n')}\n\n${retryInstruction}`);
4855
+ iterationMessage = withTaskContext(`The task is: "${userMessage}"\n\n${[visualVerificationFailureNudge, visualFailureFocusNudge, generatedResetNudge, scopedTargetSetNudge, repeatedVisualRepairNudge].filter(Boolean).join('\n\n')}\n\n${retryInstruction}`);
4824
4856
  } else if (hasMissingLocalUiVerification) {
4825
4857
  uiVerificationRetryCount++;
4826
4858
  const uiVerificationFailureDetails = this._extractUiVerificationFailureDetails(output);