import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { join } from "node:path"; import test from "node:test"; const schemaSource = readFileSync( join(process.cwd(), "convex", "schema.ts"), "utf8", ); const domainSource = readFileSync( join(process.cwd(), "convex", "domain.ts"), "utf8", ); function extractTableSection(tableName: string) { const marker = `${tableName}: defineTable({`; const markerIndex = schemaSource.indexOf(marker); assert.notEqual( markerIndex, -1, `Expected schema table definition for ${tableName}.`, ); const objectStart = schemaSource.indexOf("{", markerIndex); let depth = 0; let objectEnd = -1; for (let index = objectStart; index < schemaSource.length; index += 1) { if (schemaSource[index] === "{") { depth += 1; } else if (schemaSource[index] === "}") { depth -= 1; if (depth === 0) { objectEnd = index; break; } } } assert.notEqual(objectEnd, -1, `Could not parse schema object for ${tableName}.`); const remainder = schemaSource.slice(objectEnd + 1); const nextTableMatch = remainder.match( /^\s*[a-zA-Z_][\w]*:\s*defineTable\(/m, ); const sectionEnd = nextTableMatch === null ? schemaSource.length : objectEnd + 1 + nextTableMatch.index!; const section = schemaSource.slice(markerIndex, sectionEnd); const objectBlock = schemaSource.slice(markerIndex, objectEnd + 1); return { section, objectBlock }; } function assertHas(pattern: RegExp, source: string, message: string) { assert.equal(pattern.test(source), true, message); } test("auditGenerations table has contract fields", () => { const { section, objectBlock } = extractTableSection("auditGenerations"); assertHas( /leadId:\s*v\.id\(["']leads["']\)/, objectBlock, "auditGenerations.leadId must be required lead id.", ); assertHas( /auditId:\s*v\.optional\(\s*v\.id\(["']audits["']\)\s*\)/, objectBlock, "auditGenerations.auditId should be optional audit id.", ); assertHas( /runId:\s*v\.id\(["']agentRuns["']\)/, objectBlock, "auditGenerations.runId should be required agent run id.", ); assertHas( /stage:\s*auditGenerationStage/, objectBlock, "auditGenerations.stage should use auditGenerationStage validator.", ); assertHas( /modelProfile:\s*v\.string\(\)/, objectBlock, "auditGenerations.modelProfile should be required string.", ); assertHas( /modelId:\s*v\.string\(\)/, objectBlock, "auditGenerations.modelId should be required string.", ); assertHas( /prompt:\s*v\.string\(\)/, objectBlock, "auditGenerations.prompt should be required string.", ); assertHas( /systemPrompt:\s*v\.optional\(\s*v\.string\(\)\s*\)/, objectBlock, "auditGenerations.systemPrompt should be optional string.", ); assertHas( /rawResponse:\s*v\.optional\(\s*v\.string\(\)\s*\)/, objectBlock, "auditGenerations.rawResponse should be optional string.", ); assertHas( /parsedJson:\s*v\.optional\(\s*auditGenerationParsedJson\s*\)/, objectBlock, "auditGenerations.parsedJson should allow string or structured object.", ); assertHas( /usage:\s*v\.optional\(\s*auditGenerationUsage\s*\)/, objectBlock, "auditGenerations.usage should be optional token usage object.", ); assertHas( /finishReason:\s*v\.optional\(\s*v\.string\(\)\s*\)/, objectBlock, "auditGenerations.finishReason should be optional string.", ); assertHas( /status:\s*auditGenerationStatus/, objectBlock, "auditGenerations.status should use auditGenerationStatus validator.", ); assertHas( /errorSummary:\s*v\.optional\(\s*v\.string\(\)\s*\)/, objectBlock, "auditGenerations.errorSummary should be optional string.", ); assertHas( /createdAt:\s*v\.number\(\)/, objectBlock, "auditGenerations.createdAt should be required number.", ); assertHas( /updatedAt:\s*v\.number\(\)/, objectBlock, "auditGenerations.updatedAt should be required number.", ); assertHas( /index\("by_leadId",\s*\["leadId"\]\)/, section, "auditGenerations should have by_leadId index.", ); assertHas( /index\("by_auditId",\s*\["auditId"\]\)/, section, "auditGenerations should have by_auditId index.", ); assertHas( /index\("by_runId",\s*\["runId"\]\)/, section, "auditGenerations should have by_runId index.", ); assertHas( /index\("by_stage",\s*\["stage"\]\)/, section, "auditGenerations should have by_stage index.", ); assertHas( /index\("by_leadId_and_stage",\s*\["leadId",\s*"stage"\]\)/, section, "auditGenerations should have by_leadId_and_stage index.", ); }); test("audit-generation validators are declared", () => { assertHas( /const\s+auditGenerationStage\s*=\s*v\.union\([\s\S]*\)/, schemaSource, "schema should define auditGenerationStage union.", ); assertHas( /const\s+auditGenerationStatus\s*=\s*v\.union\([\s\S]*\)/, schemaSource, "schema should define auditGenerationStatus union.", ); assertHas( /AUDIT_GENERATION_STAGES\s*=\s*\[[\s\S]*["']classification["'][\s\S]*\]/, domainSource, "auditGenerationStage should include classification.", ); assertHas( /AUDIT_GENERATION_STAGES\s*=\s*\[[\s\S]*["']multimodalAudit["'][\s\S]*\]/, domainSource, "auditGenerationStage should include multimodalAudit.", ); assertHas( /AUDIT_GENERATION_STAGES\s*=\s*\[[\s\S]*["']germanCopy["'][\s\S]*\]/, domainSource, "auditGenerationStage should include germanCopy.", ); assertHas( /AUDIT_GENERATION_STAGES\s*=\s*\[[\s\S]*["']qualityReview["'][\s\S]*\]/, domainSource, "auditGenerationStage should include qualityReview.", ); });