diff --git a/src/semantic-value-visibility/constants.js b/src/image-enrichment/constants.js similarity index 77% rename from src/semantic-value-visibility/constants.js rename to src/image-enrichment/constants.js index afb08d7cb2..1134326e34 100644 --- a/src/semantic-value-visibility/constants.js +++ b/src/image-enrichment/constants.js @@ -10,6 +10,6 @@ * governing permissions and limitations under the License. */ -export const AUDIT_TYPE = 'semantic-value-visibility'; -export const GUIDANCE_TYPE = 'guidance:semantic-value-visibility'; -export const OPPORTUNITY_TYPE = 'semantic-value-visibility'; +export const AUDIT_TYPE = 'image-enrichment'; +export const GUIDANCE_TYPE = 'guidance:image-enrichment'; +export const OPPORTUNITY_TYPE = 'image-enrichment'; diff --git a/src/semantic-value-visibility/guidance-handler.js b/src/image-enrichment/guidance-handler.js similarity index 77% rename from src/semantic-value-visibility/guidance-handler.js rename to src/image-enrichment/guidance-handler.js index de7b2efe0a..030acc7f9d 100644 --- a/src/semantic-value-visibility/guidance-handler.js +++ b/src/image-enrichment/guidance-handler.js @@ -17,7 +17,7 @@ import { createOpportunityData } from './opportunity-data-mapper.js'; import { OPPORTUNITY_TYPE } from './constants.js'; /** - * Guidance handler for semantic value visibility. + * Guidance handler for image enrichment. * * Receives Mystique's response with marketing image suggestions and: * - Creates/updates an opportunity for the site @@ -35,7 +35,7 @@ export default async function handler(message, context) { // Validate siteId const site = await Site.findById(siteId); if (!site) { - log.error(`[semantic-value-visibility] Site not found for siteId: ${siteId}`); + log.error(`[image-enrichment] Site not found for siteId: ${siteId}`); return notFound('Site not found'); } @@ -47,23 +47,23 @@ export default async function handler(message, context) { // Note: semanticHtml contains untrusted LLM-generated content from Mystique. // Downstream consumers must sanitize before rendering. if (!Array.isArray(suggestions)) { - log.error(`[semantic-value-visibility] Invalid suggestions format for siteId: ${siteId}`); + log.error(`[image-enrichment] Invalid suggestions format for siteId: ${siteId}`); return badRequest('Suggestions must be an array'); } const validSuggestions = suggestions.filter((s) => { const hasRequiredFields = s?.data?.imageUrl && s?.data?.semanticHtml; if (!hasRequiredFields) { - log.warn('[semantic-value-visibility] Skipping suggestion with missing imageUrl or semanticHtml'); + log.warn('[image-enrichment] Skipping suggestion with missing imageUrl or semanticHtml'); } return hasRequiredFields; }); - log.info(`[semantic-value-visibility] Guidance handler received ${validSuggestions.length} valid suggestions for siteId: ${siteId}`); + log.info(`[image-enrichment] Guidance handler received ${validSuggestions.length} valid suggestions for siteId: ${siteId}`); // No valid suggestions — handle stale opportunity if (validSuggestions.length === 0) { - log.info(`[semantic-value-visibility] No marketing images found for siteId: ${siteId}`); + log.info(`[image-enrichment] No marketing images found for siteId: ${siteId}`); // Check if there's an existing opportunity to clean up const existing = await Opportunity.allBySiteIdAndStatus(siteId, 'NEW'); @@ -72,7 +72,7 @@ export default async function handler(message, context) { ); if (staleOpportunity) { - log.info(`[semantic-value-visibility] Removing stale opportunity ${staleOpportunity.getId()} for siteId: ${siteId}`); + log.info(`[image-enrichment] Removing stale opportunity ${staleOpportunity.getId()} for siteId: ${siteId}`); staleOpportunity.setStatus('RESOLVED'); staleOpportunity.setUpdatedBy('system'); await staleOpportunity.save(); @@ -94,11 +94,11 @@ export default async function handler(message, context) { ); if (!opportunity) { - log.error(`[semantic-value-visibility] Failed to create opportunity for siteId: ${siteId}`); + log.error(`[image-enrichment] Failed to create opportunity for siteId: ${siteId}`); return badRequest('Failed to create opportunity'); } - log.info(`[semantic-value-visibility] Opportunity ${opportunity.getId()} ready for siteId: ${siteId}`); + log.info(`[image-enrichment] Opportunity ${opportunity.getId()} ready for siteId: ${siteId}`); // Sync suggestions — adds new ones, marks outdated ones await syncSuggestions({ @@ -114,7 +114,7 @@ export default async function handler(message, context) { context, }); - log.info(`[semantic-value-visibility] Synced ${validSuggestions.length} suggestions for opportunity ${opportunity.getId()}`); + log.info(`[image-enrichment] Synced ${validSuggestions.length} suggestions for opportunity ${opportunity.getId()}`); return ok(); } diff --git a/src/semantic-value-visibility/handler.js b/src/image-enrichment/handler.js similarity index 95% rename from src/semantic-value-visibility/handler.js rename to src/image-enrichment/handler.js index e8d29edba3..8bfb1f3b7a 100644 --- a/src/semantic-value-visibility/handler.js +++ b/src/image-enrichment/handler.js @@ -38,7 +38,7 @@ export async function sendToMystique(auditUrl, auditData, context, site) { data: { url: auditUrl }, }); - log.info('[semantic-value-visibility] Request sent to Mystique'); + log.info('[image-enrichment] Request sent to Mystique'); return auditData; } diff --git a/src/semantic-value-visibility/opportunity-data-mapper.js b/src/image-enrichment/opportunity-data-mapper.js similarity index 100% rename from src/semantic-value-visibility/opportunity-data-mapper.js rename to src/image-enrichment/opportunity-data-mapper.js diff --git a/src/index.js b/src/index.js index 2683b282e7..15313e7c55 100644 --- a/src/index.js +++ b/src/index.js @@ -118,8 +118,8 @@ import youtubeAnalysisGuidance from './youtube-analysis/guidance-handler.js'; import citedAnalysis from './cited-analysis/handler.js'; import citedAnalysisGuidance from './cited-analysis/guidance-handler.js'; import frescopaDataGeneration from './frescopa-data-generation/handler.js'; -import semanticValueVisibility from './semantic-value-visibility/handler.js'; -import semanticValueVisibilityGuidance from './semantic-value-visibility/guidance-handler.js'; +import imageEnrichment from './image-enrichment/handler.js'; +import imageEnrichmentGuidance from './image-enrichment/guidance-handler.js'; import drsPromptGeneration from './drs-prompt-generation/handler.js'; import offsiteBrandPresence from './offsite-brand-presence/handler.js'; @@ -223,8 +223,11 @@ const HANDLERS = { 'cited-analysis': citedAnalysis, 'guidance:cited-analysis': citedAnalysisGuidance, 'frescopa-data-generation': frescopaDataGeneration, - 'semantic-value-visibility': semanticValueVisibility, - 'guidance:semantic-value-visibility': semanticValueVisibilityGuidance, + 'image-enrichment': imageEnrichment, + 'guidance:image-enrichment': imageEnrichmentGuidance, + // @deprecated remove after jobs-dispatcher + mystique PR 1704 in prod + 'semantic-value-visibility': imageEnrichment, + 'guidance:semantic-value-visibility': imageEnrichmentGuidance, 'drs:prompt_generation_base_url': drsPromptGeneration, 'offsite-brand-presence': offsiteBrandPresence, dummy: (message) => ok(message), diff --git a/test/audits/semantic-value-visibility/guidance-handler.test.js b/test/audits/image-enrichment/guidance-handler.test.js similarity index 97% rename from test/audits/semantic-value-visibility/guidance-handler.test.js rename to test/audits/image-enrichment/guidance-handler.test.js index 1d395eca60..fd8b953ece 100644 --- a/test/audits/semantic-value-visibility/guidance-handler.test.js +++ b/test/audits/image-enrichment/guidance-handler.test.js @@ -22,12 +22,12 @@ use(sinonChai); const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -const fixturesPath = join(__dirname, '../../fixtures/semantic-value-visibility'); +const fixturesPath = join(__dirname, '../../fixtures/image-enrichment'); // Load Krisshop fixture (new format with top-level guidance) const krisshopFixture = JSON.parse(readFileSync(join(fixturesPath, 'Krisshop.json'), 'utf8')); -describe('Semantic Value Visibility Guidance Handler', () => { +describe('Image Enrichment Guidance Handler', () => { let context; let log; let Opportunity; @@ -46,7 +46,7 @@ describe('Semantic Value Visibility Guidance Handler', () => { // Load handler with mocked dependencies const mockedHandler = await esmock( - '../../../src/semantic-value-visibility/guidance-handler.js', + '../../../src/image-enrichment/guidance-handler.js', { '../../../src/utils/data-access.js': { syncSuggestions: syncSuggestionsStub, @@ -316,7 +316,7 @@ describe('Semantic Value Visibility Guidance Handler', () => { it('should mark stale opportunity as RESOLVED when no new suggestions', async () => { const staleOpportunity = { getId: sinon.stub().returns('stale-oppty-123'), - getType: sinon.stub().returns('semantic-value-visibility'), + getType: sinon.stub().returns('image-enrichment'), setStatus: sinon.stub(), setUpdatedBy: sinon.stub(), save: sinon.stub().resolves(), diff --git a/test/audits/semantic-value-visibility/handler.test.js b/test/audits/image-enrichment/handler.test.js similarity index 92% rename from test/audits/semantic-value-visibility/handler.test.js rename to test/audits/image-enrichment/handler.test.js index b50926fc19..f8e840c4c6 100644 --- a/test/audits/semantic-value-visibility/handler.test.js +++ b/test/audits/image-enrichment/handler.test.js @@ -13,11 +13,11 @@ import { expect, use } from 'chai'; import sinon from 'sinon'; import sinonChai from 'sinon-chai'; -import { auditRunner, sendToMystique } from '../../../src/semantic-value-visibility/handler.js'; +import { auditRunner, sendToMystique } from '../../../src/image-enrichment/handler.js'; use(sinonChai); -describe('Semantic Value Visibility Handler', () => { +describe('Image Enrichment Handler', () => { let sandbox; let site; let context; @@ -83,7 +83,7 @@ describe('Semantic Value Visibility Handler', () => { const message = sqsStub.sendMessage.getCall(0).args[1]; expect(message).to.deep.include({ - type: 'guidance:semantic-value-visibility', + type: 'guidance:image-enrichment', siteId, auditId: 'audit-456', url: auditUrl, @@ -107,7 +107,7 @@ describe('Semantic Value Visibility Handler', () => { await sendToMystique(auditUrl, {}, context, site); expect(logStub.info).to.have.been.calledWith( - '[semantic-value-visibility] Request sent to Mystique', + '[image-enrichment] Request sent to Mystique', ); }); diff --git a/test/audits/semantic-value-visibility/opportunity-data-mapper.test.js b/test/audits/image-enrichment/opportunity-data-mapper.test.js similarity index 93% rename from test/audits/semantic-value-visibility/opportunity-data-mapper.test.js rename to test/audits/image-enrichment/opportunity-data-mapper.test.js index c43e96cf0d..a88e219e5c 100644 --- a/test/audits/semantic-value-visibility/opportunity-data-mapper.test.js +++ b/test/audits/image-enrichment/opportunity-data-mapper.test.js @@ -14,15 +14,15 @@ import { expect } from 'chai'; import { readFileSync } from 'fs'; import { dirname, join } from 'path'; import { fileURLToPath } from 'url'; -import { createOpportunityData } from '../../../src/semantic-value-visibility/opportunity-data-mapper.js'; +import { createOpportunityData } from '../../../src/image-enrichment/opportunity-data-mapper.js'; import { DATA_SOURCES } from '../../../src/common/constants.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -const fixturesPath = join(__dirname, '../../fixtures/semantic-value-visibility'); +const fixturesPath = join(__dirname, '../../fixtures/image-enrichment'); const krisshopFixture = JSON.parse(readFileSync(join(fixturesPath, 'Krisshop.json'), 'utf8')); -describe('Semantic Value Visibility Opportunity Data Mapper', () => { +describe('Image Enrichment Opportunity Data Mapper', () => { describe('createOpportunityData', () => { it('should create opportunity data with all required fields', () => { const result = createOpportunityData({ guidance: krisshopFixture.guidance }); diff --git a/test/fixtures/semantic-value-visibility/Krisshop.json b/test/fixtures/image-enrichment/Krisshop.json similarity index 99% rename from test/fixtures/semantic-value-visibility/Krisshop.json rename to test/fixtures/image-enrichment/Krisshop.json index 55780d9af6..c8fe1b776b 100644 --- a/test/fixtures/semantic-value-visibility/Krisshop.json +++ b/test/fixtures/image-enrichment/Krisshop.json @@ -1,6 +1,6 @@ { "url": "https://www.krisshop.com/", - "opportunityType": "semantic-value-visibility", + "opportunityType": "image-enrichment", "guidance": { "insight": "Marketing images on this page contain promotional text (headlines, offers, CTAs) that is not represented in the page's semantic HTML structure.", "rationale": "Text embedded in images is invisible to LLMs and search engines. Without machine-readable HTML equivalents, key marketing messages cannot be understood, indexed, or surfaced in AI-powered search results.",