@hamp10/agentforge 0.2.40 → 0.2.41
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 +43 -0
- package/src/worker.js +42 -4
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 {
|
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;
|
|
@@ -4765,8 +4774,11 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
4765
4774
|
throw new Error('UI task failed visual verification after repeated repair attempts');
|
|
4766
4775
|
}
|
|
4767
4776
|
const repairBudget = consumeUiRepairNudge('visual verification warnings', visualVerificationFailureNudge);
|
|
4777
|
+
const visualFailureSlugs = this._extractUiVerificationFailureSlugs(output, scopeAwareUserMessage);
|
|
4768
4778
|
const generatedResetNudge = this._formatGeneratedScopedUiResetNudge(
|
|
4769
|
-
|
|
4779
|
+
visualFailureSlugs.length > 0
|
|
4780
|
+
? this._restoreGeneratedScopedUiTargets(repoBaselines, scopeAwareUserMessage, { onlySlugs: visualFailureSlugs })
|
|
4781
|
+
: []
|
|
4770
4782
|
);
|
|
4771
4783
|
nudgeCount = 0;
|
|
4772
4784
|
console.log(`[${taskId}] UI task visual verification still reported visible issues — retrying (${uiVerificationRetryCount}/${UI_REPAIR_NUDGE_LIMIT}, total UI repairs ${repairBudget})`);
|
|
@@ -4782,8 +4794,11 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
4782
4794
|
throw new Error('UI task failed visual verification after repeated repair attempts');
|
|
4783
4795
|
}
|
|
4784
4796
|
const repairBudget = consumeUiRepairNudge('missing local visual verification', uiVerificationFailureDetails);
|
|
4797
|
+
const visualFailureSlugs = this._extractUiVerificationFailureSlugs(output, scopeAwareUserMessage);
|
|
4785
4798
|
const generatedResetNudge = this._formatGeneratedScopedUiResetNudge(
|
|
4786
|
-
|
|
4799
|
+
visualFailureSlugs.length > 0
|
|
4800
|
+
? this._restoreGeneratedScopedUiTargets(repoBaselines, scopeAwareUserMessage, { onlySlugs: visualFailureSlugs })
|
|
4801
|
+
: []
|
|
4787
4802
|
);
|
|
4788
4803
|
nudgeCount = 0;
|
|
4789
4804
|
console.log(`[${taskId}] UI task missing local visual verification — retrying with local-app repair instruction (${uiVerificationRetryCount}/${UI_REPAIR_NUDGE_LIMIT}, total UI repairs ${repairBudget})`);
|
|
@@ -5876,7 +5891,7 @@ end tell`.trim().replace(/\n/g, '\n');
|
|
|
5876
5891
|
.split('\n')
|
|
5877
5892
|
.map(line => line.trim())
|
|
5878
5893
|
.filter(line =>
|
|
5879
|
-
|
|
5894
|
+
/(?:^|[\s:])(?:Style|Visual) warning:/i.test(line) ||
|
|
5880
5895
|
/Browser failed to load/i.test(line) ||
|
|
5881
5896
|
/changed UI was not successfully loaded and inspected/i.test(line) ||
|
|
5882
5897
|
/latest visual verification still reported/i.test(line) ||
|
|
@@ -5886,6 +5901,29 @@ end tell`.trim().replace(/\n/g, '\n');
|
|
|
5886
5901
|
return unique.join('\n').slice(0, 1800);
|
|
5887
5902
|
}
|
|
5888
5903
|
|
|
5904
|
+
_extractUiVerificationFailureSlugs(output, userMessage) {
|
|
5905
|
+
const { slugs: allowedSlugs } = this._extractExplicitScope(userMessage);
|
|
5906
|
+
if (allowedSlugs.length === 0) return [];
|
|
5907
|
+
const lines = String(output || '')
|
|
5908
|
+
.split('\n')
|
|
5909
|
+
.map(line => line.trim())
|
|
5910
|
+
.filter(line =>
|
|
5911
|
+
/(?:^|[\s:])(?:Style|Visual) warning:/i.test(line) ||
|
|
5912
|
+
/Browser failed to load/i.test(line) ||
|
|
5913
|
+
/changed UI was not successfully loaded and inspected/i.test(line) ||
|
|
5914
|
+
/latest visual verification still reported/i.test(line) ||
|
|
5915
|
+
/This is not complete/i.test(line)
|
|
5916
|
+
);
|
|
5917
|
+
if (lines.length === 0) return [];
|
|
5918
|
+
const matched = new Set();
|
|
5919
|
+
for (const line of lines) {
|
|
5920
|
+
for (const slug of this._scopeSlugsMatchingText(line, allowedSlugs)) {
|
|
5921
|
+
matched.add(slug);
|
|
5922
|
+
}
|
|
5923
|
+
}
|
|
5924
|
+
return [...matched];
|
|
5925
|
+
}
|
|
5926
|
+
|
|
5889
5927
|
_buildUiVerificationFailureNudge(output) {
|
|
5890
5928
|
const details = this._extractUiVerificationFailureDetails(output);
|
|
5891
5929
|
const genericFailure =
|