Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@
## 2026-07-16 - [O(N*M) Nested Loop Lookups in Grading Engines]
**Learning:** In interactive scenarios (such as Bid Elevator and STR Triage), grading engines frequently iterate over user decisions and match them against scenario properties (like keywords or search terms). Performing `array.find()` inside loop bodies or filter predicates results in costly O(N*M) lookups.
**Action:** Convert arrays to `Map` lookups before entering loops/nested scans. Mapping keys once in O(M) time enables O(1) lookups during execution, transforming the time complexity of the grading logic to O(N + M).

## 2026-07-17 - [O(N*M) Nested Loop Lookups in Listing Audit grading]
**Learning:** In the Listing Audit grading engine, both findingsAccuracy and severityCalibration iterated over student findings and performed an `array.find()` lookup against reference findings, leading to O(N*M) operations.
**Action:** Convert the reference findings array into a Map, matching keys once in O(M) time, to enable O(1) lookups inside the loop, achieving O(N+M) time complexity.
97 changes: 97 additions & 0 deletions src/engine/listing-audit/engine.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { describe, it, expect } from 'vitest';
import { gradeListingAudit, generateAutoFindings } from './engine';
import type { ListingAuditScenario, ListingAuditFinding } from './types';

describe('listing-audit engine', () => {
const mockScenario: ListingAuditScenario = {
id: 'la-test-001',
slug: 'test-cutting-board',
category: 'kitchen',
product: {
asin: 'B09KCB001',
name: 'Bamboo Cutting Board',
category: 'Kitchen',
aov: 1200,
targetAcos: 0.30,
},
currentListing: {
title: 'Bamboo Cutting Board',
bullets: ['Bamboo material', 'Durable'],
description: 'A cutting board.',
imageCount: 3,
hasAplusContent: false,
pricePhp: 1200,
reviewCount: 18,
averageRating: 4.3,
},
referenceListing: {
title: 'Bamboo Cutting Board with Deep Juice Groove β€” Eco-Friendly Kitchen Chopping Board for Vegetables, Meat, Cheese | Large 16x12 inch with Non-Slip Feet | Durable, Dishwasher Safe',
bullets: [
'DEEP JUICE GROOVE β€” Catches liquids from meat, fruit, and vegetables. No more countertop spills.',
'ECO-FRIENDLY BAMBOO β€” Sustainably sourced, naturally antibacterial. Lasts longer than plastic.',
'LARGE 16x12 INCH β€” Fits a whole meal prep. Reversible design doubles your workspace.',
'NON-SLIP FEET β€” Stays put on the counter. No more chasing the board while chopping.',
'DISHWASHER SAFE β€” Easy cleanup. Oil monthly with food-grade mineral oil for best results.',
],
description: 'A premium cutting board made of 100% natural organic bamboo. Perfect for any kitchen task.',
imageCount: 9,
hasAplusContent: true,
pricePhp: 1200,
reviewCount: 200,
averageRating: 4.6,
},
referenceFindings: [
{ field: 'title', severity: 'critical', message: 'Title is too short.' },
{ field: 'bullets', severity: 'critical', message: 'Only 2 bullets.' },
{ field: 'images', severity: 'critical', message: 'Only 3 images.' },
{ field: 'aplus', severity: 'warning', message: 'No A+ content.' },
],
explanation: 'Test explanation',
};

it('correctly grades ideal student findings matching reference findings', () => {
const studentFindings: ListingAuditFinding[] = [
{ field: 'title', severity: 'critical', message: 'Title is too short.' },
{ field: 'bullets', severity: 'critical', message: 'Only 2 bullets.' },
{ field: 'images', severity: 'critical', message: 'Only 3 images.' },
{ field: 'aplus', severity: 'warning', message: 'No A+ content.' },
];

const studentRevision = {
title: 'Bamboo Cutting Board with Deep Juice Groove β€” Eco-Friendly Kitchen Chopping Board for Vegetables, Meat, Cheese | Large 16x12 inch with Non-Slip Feet | Durable, Dishwasher Safe',
bullets: [
'DEEP JUICE GROOVE β€” Catches liquids from meat, fruit, and vegetables. No more countertop spills.',
'ECO-FRIENDLY BAMBOO β€” Sustainably sourced, naturally antibacterial. Lasts longer than plastic.',
'LARGE 16x12 INCH β€” Fits a whole meal prep. Reversible design doubles your workspace.',
'NON-SLIP FEET β€” Stays put on the counter. No more chasing the board while chopping.',
'DISHWASHER SAFE β€” Easy cleanup. Oil monthly with food-grade mineral oil for best results.',
],
imageCount: 9,
hasAplusContent: true,
};

const grade = gradeListingAudit(mockScenario, studentFindings, studentRevision);
expect(grade.passed).toBe(true);
expect(grade.totalScore).toBeGreaterThanOrEqual(70);
});

it('correctly grades poor or missing student findings', () => {
const studentFindings: ListingAuditFinding[] = []; // No findings submitted

const grade = gradeListingAudit(mockScenario, studentFindings);
expect(grade.passed).toBe(false);
expect(grade.totalScore).toBeLessThan(70);
});

it('generates auto findings correctly based on guidelines', () => {
const current = mockScenario.currentListing;
const reference = mockScenario.referenceListing;
const autoFindings = generateAutoFindings(current, reference);

expect(autoFindings.length).toBeGreaterThan(0);
expect(autoFindings.some(f => f.field === 'title' && f.severity === 'critical')).toBe(true);
expect(autoFindings.some(f => f.field === 'bullets' && f.severity === 'critical')).toBe(true);
expect(autoFindings.some(f => f.field === 'images' && f.severity === 'critical')).toBe(true);
expect(autoFindings.some(f => f.field === 'aplus' && f.severity === 'warning')).toBe(true);
});
});
21 changes: 19 additions & 2 deletions src/engine/listing-audit/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,18 @@ function findingsAccuracy(
if (student.length === 0) {
return binaryCriterion('findings_accuracy', false, PASS, 'No findings submitted.');
}

// Bolt optimization: Map reference findings by field to replace O(N*M) nested lookups with O(1) lookups
const refMap = new Map<string, ListingAuditFinding>();
for (const rf of ref) {
if (!refMap.has(rf.field)) {
refMap.set(rf.field, rf);
}
}

let truePositives = 0;
for (const sf of student) {
const match = ref.find((rf) => rf.field === sf.field);
const match = refMap.get(sf.field);
if (!match) continue;
// Severity at least matches
if (severityAtLeast(sf.severity, match.severity)) truePositives++;
Expand All @@ -104,10 +113,18 @@ function severityCalibration(
student: ListingAuditFinding[],
ref: ListingAuditFinding[]
): CriterionResult {
// Bolt optimization: Map reference findings by field to replace O(N*M) nested lookups with O(1) lookups
const refMap = new Map<string, ListingAuditFinding>();
for (const rf of ref) {
if (!refMap.has(rf.field)) {
refMap.set(rf.field, rf);
}
}

let correct = 0;
let total = 0;
for (const sf of student) {
const match = ref.find((rf) => rf.field === sf.field);
const match = refMap.get(sf.field);
if (!match) continue;
total++;
if (sf.severity === match.severity) correct++;
Expand Down