@claritylabs/cl-sdk 0.16.2 → 0.17.0

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/dist/index.js CHANGED
@@ -79,6 +79,7 @@ __export(index_exports, {
79
79
  CoverageSchema: () => CoverageSchema,
80
80
  CoverageTriggerSchema: () => CoverageTriggerSchema,
81
81
  CoverageValueTypeSchema: () => CoverageValueTypeSchema,
82
+ CoveredReasonSchema: () => CoveredReasonSchema,
82
83
  CrimeDeclarationsSchema: () => CrimeDeclarationsSchema,
83
84
  CyberDeclarationsSchema: () => CyberDeclarationsSchema,
84
85
  DEDUCTIBLE_TYPES: () => DEDUCTIBLE_TYPES,
@@ -91,6 +92,7 @@ __export(index_exports, {
91
92
  DeductibleScheduleSchema: () => DeductibleScheduleSchema,
92
93
  DeductibleTypeSchema: () => DeductibleTypeSchema,
93
94
  DefenseCostTreatmentSchema: () => DefenseCostTreatmentSchema,
95
+ DefinitionSchema: () => DefinitionSchema,
94
96
  DocumentTypeSchema: () => DocumentTypeSchema,
95
97
  DriverRecordSchema: () => DriverRecordSchema,
96
98
  DwellingDetailsSchema: () => DwellingDetailsSchema,
@@ -1493,6 +1495,29 @@ var AuxiliaryFactSchema = import_zod16.z.object({
1493
1495
  subject: import_zod16.z.string().optional(),
1494
1496
  context: import_zod16.z.string().optional()
1495
1497
  });
1498
+ var DefinitionSchema = import_zod16.z.object({
1499
+ term: import_zod16.z.string(),
1500
+ definition: import_zod16.z.string(),
1501
+ pageNumber: import_zod16.z.number().optional(),
1502
+ formNumber: import_zod16.z.string().optional(),
1503
+ formTitle: import_zod16.z.string().optional(),
1504
+ sectionRef: import_zod16.z.string().optional(),
1505
+ originalContent: import_zod16.z.string().optional()
1506
+ });
1507
+ var CoveredReasonSchema = import_zod16.z.object({
1508
+ coverageName: import_zod16.z.string(),
1509
+ reasonNumber: import_zod16.z.string().optional(),
1510
+ title: import_zod16.z.string().optional(),
1511
+ content: import_zod16.z.string(),
1512
+ conditions: import_zod16.z.array(import_zod16.z.string()).optional(),
1513
+ exceptions: import_zod16.z.array(import_zod16.z.string()).optional(),
1514
+ appliesTo: import_zod16.z.array(import_zod16.z.string()).optional(),
1515
+ pageNumber: import_zod16.z.number().optional(),
1516
+ formNumber: import_zod16.z.string().optional(),
1517
+ formTitle: import_zod16.z.string().optional(),
1518
+ sectionRef: import_zod16.z.string().optional(),
1519
+ originalContent: import_zod16.z.string().optional()
1520
+ });
1496
1521
  var BaseDocumentFields = {
1497
1522
  id: import_zod16.z.string(),
1498
1523
  carrier: import_zod16.z.string(),
@@ -1503,6 +1528,8 @@ var BaseDocumentFields = {
1503
1528
  policyTypes: import_zod16.z.array(import_zod16.z.string()).optional(),
1504
1529
  coverages: import_zod16.z.array(CoverageSchema),
1505
1530
  sections: import_zod16.z.array(SectionSchema).optional(),
1531
+ definitions: import_zod16.z.array(DefinitionSchema).optional(),
1532
+ coveredReasons: import_zod16.z.array(CoveredReasonSchema).optional(),
1506
1533
  // Enriched fields (v1.2+)
1507
1534
  carrierLegalName: import_zod16.z.string().optional(),
1508
1535
  carrierNaicNumber: import_zod16.z.string().optional(),
@@ -1948,13 +1975,26 @@ function getDeclarationFields(doc) {
1948
1975
  return Array.isArray(decl?.fields) ? decl.fields : [];
1949
1976
  }
1950
1977
  function fieldMatches(fieldName, patterns) {
1951
- const lower = fieldName.toLowerCase().replace(/[\s_-]/g, "");
1952
- return patterns.some((p) => lower === p.toLowerCase().replace(/[\s_-]/g, ""));
1978
+ const lower = normalizeFieldName(fieldName);
1979
+ return patterns.some((p) => lower === normalizeFieldName(p));
1980
+ }
1981
+ function normalizeFieldName(fieldName) {
1982
+ return fieldName.toLowerCase().replace(/[^a-z0-9]/g, "");
1953
1983
  }
1954
- function findFieldValue(fields, patterns) {
1955
- const match = fields.find((f) => fieldMatches(f.field, patterns));
1984
+ function findFieldValue(fields, patterns, reject) {
1985
+ const match = fields.find((f) => fieldMatches(f.field, patterns) && !reject?.(f));
1956
1986
  return match?.value;
1957
1987
  }
1988
+ function stringValue(value) {
1989
+ return typeof value === "string" && value.trim() ? value : void 0;
1990
+ }
1991
+ function findRawString(raw, keys) {
1992
+ for (const key of keys) {
1993
+ const value = stringValue(raw[key]);
1994
+ if (value) return value;
1995
+ }
1996
+ return void 0;
1997
+ }
1958
1998
  function promoteCarrierFields(doc) {
1959
1999
  const raw = doc;
1960
2000
  if (!raw.carrierNaicNumber && raw.naicNumber) {
@@ -2270,8 +2310,126 @@ function synthesizeDeductibles(doc) {
2270
2310
  raw.deductibles = deductibles;
2271
2311
  }
2272
2312
  }
2273
- var PREMIUM_PATTERNS = ["premium", "totalPremium", "annualPremium", "policyPremium", "basePremium"];
2274
- var TOTAL_COST_PATTERNS = ["totalCost", "totalDue", "totalAmount", "totalPolicyPremium"];
2313
+ var PREMIUM_PATTERNS = [
2314
+ "premium",
2315
+ "premiumAmount",
2316
+ "premium amount",
2317
+ "totalPremium",
2318
+ "total premium",
2319
+ "totalPolicyPremium",
2320
+ "total policy premium",
2321
+ "annualPremium",
2322
+ "annual premium",
2323
+ "estimatedAnnualPremium",
2324
+ "estimated annual premium",
2325
+ "policyPremium",
2326
+ "policy premium",
2327
+ "basePremium",
2328
+ "base premium",
2329
+ "planCost",
2330
+ "plan cost",
2331
+ "policyCost",
2332
+ "policy cost",
2333
+ "premiumSubtotal",
2334
+ "premium subtotal",
2335
+ "subtotalPremium",
2336
+ "subtotal premium",
2337
+ "quotedPremium",
2338
+ "quoted premium"
2339
+ ];
2340
+ var TOTAL_COST_PATTERNS = [
2341
+ "totalCost",
2342
+ "total cost",
2343
+ "total",
2344
+ "totalDue",
2345
+ "total due",
2346
+ "amountPaid",
2347
+ "amount paid",
2348
+ "totalPaid",
2349
+ "total paid",
2350
+ "totalPrice",
2351
+ "total price",
2352
+ "totalTripCost",
2353
+ "total trip cost",
2354
+ "amountCharged",
2355
+ "amount charged",
2356
+ "amountDue",
2357
+ "amount due",
2358
+ "totalAmountDue",
2359
+ "total amount due",
2360
+ "totalAmount",
2361
+ "total amount",
2362
+ "grandTotal",
2363
+ "grand total",
2364
+ "totalPayable",
2365
+ "total payable",
2366
+ "totalCharges",
2367
+ "total charges",
2368
+ "totalPolicyCost",
2369
+ "total policy cost"
2370
+ ];
2371
+ var PREMIUM_RAW_KEYS = [
2372
+ "premium",
2373
+ "premiumAmount",
2374
+ "premium_amount",
2375
+ "totalPremium",
2376
+ "totalPolicyPremium",
2377
+ "annualPremium",
2378
+ "estimatedAnnualPremium",
2379
+ "policyPremium",
2380
+ "basePremium",
2381
+ "planCost",
2382
+ "policyCost",
2383
+ "premiumSubtotal",
2384
+ "subtotalPremium",
2385
+ "quotedPremium"
2386
+ ];
2387
+ var TOTAL_COST_RAW_KEYS = [
2388
+ "totalCost",
2389
+ "total_cost",
2390
+ "total",
2391
+ "totalDue",
2392
+ "amountPaid",
2393
+ "amount_paid",
2394
+ "totalPaid",
2395
+ "total_paid",
2396
+ "totalPrice",
2397
+ "totalTripCost",
2398
+ "amountCharged",
2399
+ "amountDue",
2400
+ "totalAmountDue",
2401
+ "totalAmount",
2402
+ "grandTotal",
2403
+ "totalPayable",
2404
+ "totalCharges",
2405
+ "totalPolicyCost"
2406
+ ];
2407
+ function isTaxOrFeeField(fieldName) {
2408
+ const normalized = normalizeFieldName(fieldName);
2409
+ return /tax|gst|hst|pst|qst|fee|surcharge|assessment|stamp|filing|inspection/.test(normalized);
2410
+ }
2411
+ function isTotalCostField(fieldName) {
2412
+ return fieldMatches(fieldName, TOTAL_COST_PATTERNS);
2413
+ }
2414
+ function taxFeeType(fieldName) {
2415
+ const normalized = normalizeFieldName(fieldName);
2416
+ if (normalized.includes("tax") || ["gst", "hst", "pst", "qst"].some((token) => normalized.includes(token))) return "tax";
2417
+ if (normalized.includes("surcharge")) return "surcharge";
2418
+ if (normalized.includes("assessment")) return "assessment";
2419
+ if (normalized.includes("fee") || normalized.includes("stamp") || normalized.includes("filing")) return "fee";
2420
+ return void 0;
2421
+ }
2422
+ function titleizeFieldName(fieldName) {
2423
+ const spaced = fieldName.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
2424
+ return spaced.replace(/\b\w/g, (letter) => letter.toUpperCase());
2425
+ }
2426
+ function taxFeeKey(item) {
2427
+ return [
2428
+ normalizeFieldName(item.name),
2429
+ normalizeFieldName(item.amount),
2430
+ item.type ?? ""
2431
+ ].join("|");
2432
+ }
2275
2433
  function absorbNegative(value) {
2276
2434
  return value.replace(/^-\s*/, "").replace(/^\(\s*(.*?)\s*\)$/, "$1");
2277
2435
  }
@@ -2279,16 +2437,41 @@ function promotePremium(doc) {
2279
2437
  const raw = doc;
2280
2438
  const fields = getDeclarationFields(doc);
2281
2439
  if (!raw.premium) {
2282
- const premium = findFieldValue(fields, PREMIUM_PATTERNS);
2440
+ const premium = findRawString(raw, PREMIUM_RAW_KEYS) ?? findFieldValue(fields, PREMIUM_PATTERNS, (field) => isTaxOrFeeField(field.field));
2283
2441
  if (premium) raw.premium = premium;
2284
2442
  }
2285
2443
  if (!raw.totalCost) {
2286
- const totalCost = findFieldValue(fields, TOTAL_COST_PATTERNS);
2444
+ const totalCost = findRawString(raw, TOTAL_COST_RAW_KEYS) ?? findFieldValue(fields, TOTAL_COST_PATTERNS);
2287
2445
  if (totalCost) raw.totalCost = totalCost;
2288
2446
  }
2289
2447
  if (typeof raw.premium === "string") raw.premium = absorbNegative(raw.premium);
2290
2448
  if (typeof raw.totalCost === "string") raw.totalCost = absorbNegative(raw.totalCost);
2291
2449
  }
2450
+ function synthesizeTaxesAndFees(doc) {
2451
+ const raw = doc;
2452
+ const fields = getDeclarationFields(doc);
2453
+ if (fields.length === 0) return;
2454
+ const existing = Array.isArray(raw.taxesAndFees) ? raw.taxesAndFees : [];
2455
+ const byKey = /* @__PURE__ */ new Map();
2456
+ for (const item of existing) {
2457
+ if (!item?.name || !item?.amount) continue;
2458
+ byKey.set(taxFeeKey(item), item);
2459
+ }
2460
+ for (const field of fields) {
2461
+ if (!field.value?.trim()) continue;
2462
+ if (!isTaxOrFeeField(field.field)) continue;
2463
+ if (isTotalCostField(field.field)) continue;
2464
+ const item = {
2465
+ name: titleizeFieldName(field.field),
2466
+ amount: absorbNegative(field.value),
2467
+ ...taxFeeType(field.field) ? { type: taxFeeType(field.field) } : {}
2468
+ };
2469
+ byKey.set(taxFeeKey(item), item);
2470
+ }
2471
+ if (byKey.size > 0) {
2472
+ raw.taxesAndFees = [...byKey.values()];
2473
+ }
2474
+ }
2292
2475
  function promoteExtractedFields(doc) {
2293
2476
  promoteCarrierFields(doc);
2294
2477
  promoteBroker(doc);
@@ -2296,6 +2479,7 @@ function promoteExtractedFields(doc) {
2296
2479
  promoteLocations(doc);
2297
2480
  synthesizeLimits(doc);
2298
2481
  synthesizeDeductibles(doc);
2482
+ synthesizeTaxesAndFees(doc);
2299
2483
  promotePremium(doc);
2300
2484
  }
2301
2485
 
@@ -2313,6 +2497,8 @@ function assembleDocument(documentId, documentType, memory) {
2313
2497
  const sections = memory.get("sections");
2314
2498
  const supplementary = memory.get("supplementary");
2315
2499
  const formInventory = memory.get("form_inventory");
2500
+ const definitions = memory.get("definitions");
2501
+ const coveredReasons = memory.get("covered_reasons");
2316
2502
  const classify = memory.get("classify");
2317
2503
  const base = {
2318
2504
  id: documentId,
@@ -2334,6 +2520,8 @@ function assembleDocument(documentId, documentType, memory) {
2334
2520
  conditions: conditions?.conditions,
2335
2521
  sections: sections?.sections,
2336
2522
  formInventory: formInventory?.forms,
2523
+ definitions: definitions?.definitions,
2524
+ coveredReasons: coveredReasons?.coveredReasons ?? coveredReasons?.covered_reasons,
2337
2525
  declarations: declarations ? sanitizeNulls(declarations) : void 0,
2338
2526
  ...sanitizeNulls(lossHistory ?? {})
2339
2527
  };
@@ -2493,6 +2681,21 @@ function collectContentFields(doc) {
2493
2681
  add(`conditions[${i}].content`, doc.conditions[i].content);
2494
2682
  }
2495
2683
  }
2684
+ const extendedDoc = doc;
2685
+ if (extendedDoc.definitions) {
2686
+ for (let i = 0; i < extendedDoc.definitions.length; i++) {
2687
+ add(`definitions[${i}].definition`, extendedDoc.definitions[i].definition);
2688
+ }
2689
+ }
2690
+ const coveredReasons = extendedDoc.coveredReasons ?? extendedDoc.covered_reasons;
2691
+ if (coveredReasons) {
2692
+ for (let i = 0; i < coveredReasons.length; i++) {
2693
+ add(`coveredReasons[${i}].content`, coveredReasons[i].content);
2694
+ coveredReasons[i].conditions?.forEach((condition, j) => {
2695
+ add(`coveredReasons[${i}].conditions[${j}]`, condition);
2696
+ });
2697
+ }
2698
+ }
2496
2699
  return entries;
2497
2700
  }
2498
2701
  function parseFormatResponse(response) {
@@ -2508,6 +2711,10 @@ function parseFormatResponse(response) {
2508
2711
  return results;
2509
2712
  }
2510
2713
  function applyFormattedContent(doc, entries, formatted) {
2714
+ const docRecord = doc;
2715
+ if (!docRecord.coveredReasons && docRecord.covered_reasons) {
2716
+ docRecord.coveredReasons = docRecord.covered_reasons;
2717
+ }
2511
2718
  for (const entry of entries) {
2512
2719
  const cleaned = formatted.get(entry.id);
2513
2720
  if (!cleaned) continue;
@@ -2516,6 +2723,14 @@ function applyFormattedContent(doc, entries, formatted) {
2516
2723
  const [, field, idx1, sub1, idx2, sub2] = segments;
2517
2724
  if (!sub1) {
2518
2725
  doc[field] = cleaned;
2726
+ } else if (idx2 && !sub2) {
2727
+ const arr = doc[field];
2728
+ if (arr && arr[Number(idx1)]) {
2729
+ const nested = arr[Number(idx1)][sub1];
2730
+ if (Array.isArray(nested)) {
2731
+ nested[Number(idx2)] = cleaned;
2732
+ }
2733
+ }
2519
2734
  } else if (!sub2) {
2520
2735
  const arr = doc[field];
2521
2736
  if (arr && arr[Number(idx1)]) {
@@ -2580,6 +2795,16 @@ function formatAddress(addr) {
2580
2795
  const parts = [addr.street1, addr.street2, addr.city, addr.state, addr.zip, addr.country].filter(Boolean);
2581
2796
  return parts.join(", ");
2582
2797
  }
2798
+ function asRecordArray(value) {
2799
+ return Array.isArray(value) ? value.filter((item) => Boolean(item) && typeof item === "object" && !Array.isArray(item)) : [];
2800
+ }
2801
+ function firstString(item, keys) {
2802
+ for (const key of keys) {
2803
+ const value = item[key];
2804
+ if (typeof value === "string" && value.trim()) return value;
2805
+ }
2806
+ return void 0;
2807
+ }
2583
2808
  function chunkDocument(doc) {
2584
2809
  const ensureArray = (v) => Array.isArray(v) ? v : [];
2585
2810
  doc = {
@@ -2593,6 +2818,7 @@ function chunkDocument(doc) {
2593
2818
  const chunks = [];
2594
2819
  const docId = doc.id;
2595
2820
  const policyTypesStr = doc.policyTypes?.length ? doc.policyTypes.join(",") : void 0;
2821
+ const extendedDoc = doc;
2596
2822
  function stringMetadata(entries) {
2597
2823
  const base = Object.fromEntries(
2598
2824
  Object.entries(entries).filter(([, value]) => value !== void 0 && value !== null && String(value).length > 0).map(([key, value]) => [key, String(value)])
@@ -2950,6 +3176,82 @@ ${exc.content}`.trim(),
2950
3176
  })
2951
3177
  });
2952
3178
  });
3179
+ asRecordArray(extendedDoc.definitions).forEach((definition, i) => {
3180
+ const term = firstString(definition, ["term", "name", "title"]) ?? `Definition ${i + 1}`;
3181
+ const body = firstString(definition, ["definition", "content", "text", "meaning"]);
3182
+ chunks.push({
3183
+ id: `${docId}:definition:${i}`,
3184
+ documentId: docId,
3185
+ type: "definition",
3186
+ text: [
3187
+ `Definition: ${term}`,
3188
+ body,
3189
+ firstString(definition, ["originalContent", "source"]) ? `Source: ${firstString(definition, ["originalContent", "source"])}` : null
3190
+ ].filter(Boolean).join("\n"),
3191
+ metadata: stringMetadata({
3192
+ term,
3193
+ formNumber: firstString(definition, ["formNumber"]),
3194
+ formTitle: firstString(definition, ["formTitle"]),
3195
+ pageNumber: typeof definition.pageNumber === "number" ? definition.pageNumber : void 0,
3196
+ sectionRef: firstString(definition, ["sectionRef", "sectionTitle"]),
3197
+ documentType: doc.type
3198
+ })
3199
+ });
3200
+ });
3201
+ const coveredReasons = asRecordArray(extendedDoc.coveredReasons ?? extendedDoc.covered_reasons);
3202
+ coveredReasons.forEach((coveredReason, i) => {
3203
+ const title = firstString(coveredReason, ["title", "name", "reason", "peril", "cause"]) ?? `Covered Reason ${i + 1}`;
3204
+ const coverageName = firstString(coveredReason, ["coverageName", "coverage", "coveragePart"]);
3205
+ const reasonNumber = firstString(coveredReason, ["reasonNumber", "number"]);
3206
+ const body = firstString(coveredReason, ["content", "description", "text", "coverageGrant"]);
3207
+ chunks.push({
3208
+ id: `${docId}:covered_reason:${i}`,
3209
+ documentId: docId,
3210
+ type: "covered_reason",
3211
+ text: [
3212
+ coverageName ? `Coverage: ${coverageName}` : null,
3213
+ reasonNumber ? `Reason Number: ${reasonNumber}` : null,
3214
+ `Covered Reason: ${title}`,
3215
+ body,
3216
+ firstString(coveredReason, ["originalContent", "source"]) ? `Source: ${firstString(coveredReason, ["originalContent", "source"])}` : null
3217
+ ].filter(Boolean).join("\n"),
3218
+ metadata: stringMetadata({
3219
+ coverageName,
3220
+ reasonNumber,
3221
+ title,
3222
+ formNumber: firstString(coveredReason, ["formNumber"]),
3223
+ formTitle: firstString(coveredReason, ["formTitle"]),
3224
+ pageNumber: typeof coveredReason.pageNumber === "number" ? coveredReason.pageNumber : void 0,
3225
+ sectionRef: firstString(coveredReason, ["sectionRef", "sectionTitle"]),
3226
+ documentType: doc.type
3227
+ })
3228
+ });
3229
+ const conditions = Array.isArray(coveredReason.conditions) ? coveredReason.conditions.filter((condition) => typeof condition === "string" && condition.trim().length > 0) : [];
3230
+ conditions.forEach((condition, conditionIndex) => {
3231
+ chunks.push({
3232
+ id: `${docId}:covered_reason:${i}:condition:${conditionIndex}`,
3233
+ documentId: docId,
3234
+ type: "covered_reason",
3235
+ text: [
3236
+ coverageName ? `Coverage: ${coverageName}` : null,
3237
+ reasonNumber ? `Reason Number: ${reasonNumber}` : null,
3238
+ `Covered Reason Condition: ${title}`,
3239
+ condition
3240
+ ].filter(Boolean).join("\n"),
3241
+ metadata: stringMetadata({
3242
+ coverageName,
3243
+ reasonNumber,
3244
+ title,
3245
+ conditionIndex,
3246
+ formNumber: firstString(coveredReason, ["formNumber"]),
3247
+ formTitle: firstString(coveredReason, ["formTitle"]),
3248
+ pageNumber: typeof coveredReason.pageNumber === "number" ? coveredReason.pageNumber : void 0,
3249
+ sectionRef: firstString(coveredReason, ["sectionRef", "sectionTitle"]),
3250
+ documentType: doc.type
3251
+ })
3252
+ });
3253
+ });
3254
+ });
2953
3255
  if (doc.declarations) {
2954
3256
  const decl = doc.declarations;
2955
3257
  const declLines = [];
@@ -3495,6 +3797,13 @@ function dedupeByKey(items, keyFn) {
3495
3797
  }
3496
3798
  return merged;
3497
3799
  }
3800
+ function normalizeKeyPart(value) {
3801
+ if (value === void 0 || value === null) return "";
3802
+ return String(value).toLowerCase().replace(/&/g, "and").replace(/[^a-z0-9]+/g, "");
3803
+ }
3804
+ function keyFromParts(...parts) {
3805
+ return parts.map(normalizeKeyPart).join("|");
3806
+ }
3498
3807
  function mergeUniqueObjects(existing, incoming, keyFn) {
3499
3808
  return dedupeByKey([...existing, ...incoming], keyFn);
3500
3809
  }
@@ -3523,13 +3832,13 @@ function mergeCoverageLimits(existing, incoming) {
3523
3832
  const merged = mergeShallowPreferPresent(existing, incoming);
3524
3833
  const existingCoverages = Array.isArray(existing.coverages) ? existing.coverages : [];
3525
3834
  const incomingCoverages = Array.isArray(incoming.coverages) ? incoming.coverages : [];
3526
- const coverageKey = (coverage) => [
3527
- String(coverage.name ?? "").toLowerCase(),
3528
- String(coverage.limitType ?? "").toLowerCase(),
3529
- String(coverage.limit ?? "").toLowerCase(),
3530
- String(coverage.deductible ?? "").toLowerCase(),
3531
- String(coverage.formNumber ?? "").toLowerCase()
3532
- ].join("|");
3835
+ const coverageKey = (coverage) => keyFromParts(
3836
+ coverage.name,
3837
+ coverage.limitType,
3838
+ coverage.limit,
3839
+ coverage.deductible,
3840
+ coverage.formNumber
3841
+ );
3533
3842
  const byKey = /* @__PURE__ */ new Map();
3534
3843
  for (const coverage of [...existingCoverages, ...incomingCoverages]) {
3535
3844
  const key = coverageKey(coverage);
@@ -3543,11 +3852,11 @@ function mergeDeclarations(existing, incoming) {
3543
3852
  const merged = mergeShallowPreferPresent(existing, incoming);
3544
3853
  const existingFields = Array.isArray(existing.fields) ? existing.fields : [];
3545
3854
  const incomingFields = Array.isArray(incoming.fields) ? incoming.fields : [];
3546
- merged.fields = mergeUniqueObjects(existingFields, incomingFields, (field) => [
3547
- String(field.field ?? "").toLowerCase(),
3548
- String(field.value ?? "").toLowerCase(),
3549
- String(field.section ?? "").toLowerCase()
3550
- ].join("|"));
3855
+ merged.fields = mergeUniqueObjects(existingFields, incomingFields, (field) => keyFromParts(
3856
+ field.field,
3857
+ field.value,
3858
+ field.section
3859
+ ));
3551
3860
  return merged;
3552
3861
  }
3553
3862
  function mergeArrayPayload(existing, incoming, arrayKey, keyFn) {
@@ -3557,30 +3866,53 @@ function mergeArrayPayload(existing, incoming, arrayKey, keyFn) {
3557
3866
  merged[arrayKey] = mergeUniqueObjects(existingItems, incomingItems, keyFn);
3558
3867
  return merged;
3559
3868
  }
3869
+ function readArray(record, ...keys) {
3870
+ for (const key of keys) {
3871
+ if (Array.isArray(record[key])) return record[key];
3872
+ }
3873
+ return [];
3874
+ }
3875
+ function mergeAliasedArrayPayload(existing, incoming, outputKey, inputKeys, keyFn) {
3876
+ const merged = mergeShallowPreferPresent(existing, incoming);
3877
+ const byKey = /* @__PURE__ */ new Map();
3878
+ for (const item of [
3879
+ ...readArray(existing, outputKey, ...inputKeys),
3880
+ ...readArray(incoming, outputKey, ...inputKeys)
3881
+ ]) {
3882
+ const key = keyFn(item);
3883
+ const current = byKey.get(key);
3884
+ byKey.set(key, current ? mergeShallowPreferPresent(current, item) : item);
3885
+ }
3886
+ merged[outputKey] = [...byKey.values()];
3887
+ for (const key of inputKeys) {
3888
+ if (key !== outputKey) delete merged[key];
3889
+ }
3890
+ return merged;
3891
+ }
3560
3892
  function mergeSupplementary(existing, incoming) {
3561
3893
  const merged = mergeShallowPreferPresent(existing, incoming);
3562
3894
  const mergeContactArray = (arrayKey) => {
3563
3895
  const existingItems = Array.isArray(existing[arrayKey]) ? existing[arrayKey] : [];
3564
3896
  const incomingItems = Array.isArray(incoming[arrayKey]) ? incoming[arrayKey] : [];
3565
- merged[arrayKey] = mergeUniqueObjects(existingItems, incomingItems, (item) => [
3566
- String(item.name ?? "").toLowerCase(),
3567
- String(item.phone ?? "").toLowerCase(),
3568
- String(item.email ?? "").toLowerCase(),
3569
- String(item.address ?? "").toLowerCase(),
3570
- String(item.type ?? "").toLowerCase()
3571
- ].join("|"));
3897
+ merged[arrayKey] = mergeUniqueObjects(existingItems, incomingItems, (item) => keyFromParts(
3898
+ item.name,
3899
+ item.phone,
3900
+ item.email,
3901
+ item.address,
3902
+ item.type
3903
+ ));
3572
3904
  };
3573
3905
  mergeContactArray("regulatoryContacts");
3574
3906
  mergeContactArray("claimsContacts");
3575
3907
  mergeContactArray("thirdPartyAdministrators");
3576
3908
  const existingFacts = Array.isArray(existing.auxiliaryFacts) ? existing.auxiliaryFacts : [];
3577
3909
  const incomingFacts = Array.isArray(incoming.auxiliaryFacts) ? incoming.auxiliaryFacts : [];
3578
- merged.auxiliaryFacts = mergeUniqueObjects(existingFacts, incomingFacts, (item) => [
3579
- String(item.key ?? "").toLowerCase(),
3580
- String(item.value ?? "").toLowerCase(),
3581
- String(item.subject ?? "").toLowerCase(),
3582
- String(item.context ?? "").toLowerCase()
3583
- ].join("|"));
3910
+ merged.auxiliaryFacts = mergeUniqueObjects(existingFacts, incomingFacts, (item) => keyFromParts(
3911
+ item.key,
3912
+ item.value,
3913
+ item.subject,
3914
+ item.context
3915
+ ));
3584
3916
  return merged;
3585
3917
  }
3586
3918
  function mergeExtractorResult(extractorName, existing, incoming) {
@@ -3601,31 +3933,43 @@ function mergeExtractorResult(extractorName, existing, incoming) {
3601
3933
  return mergeCoverageLimits(current, next);
3602
3934
  case "declarations":
3603
3935
  return mergeDeclarations(current, next);
3936
+ case "definitions":
3937
+ return mergeArrayPayload(current, next, "definitions", (item) => keyFromParts(
3938
+ item.term ?? item.name ?? item.key,
3939
+ item.pageNumber ?? item.pageStart
3940
+ ));
3941
+ case "covered_reasons":
3942
+ return mergeAliasedArrayPayload(current, next, "coveredReasons", ["covered_reasons"], (item) => keyFromParts(
3943
+ item.coverageName ?? item.coverage,
3944
+ item.reasonNumber ?? item.number,
3945
+ item.title ?? item.reason ?? item.name ?? item.cause,
3946
+ item.pageNumber ?? item.pageStart
3947
+ ));
3604
3948
  case "endorsements":
3605
- return mergeArrayPayload(current, next, "endorsements", (item) => [
3606
- String(item.formNumber ?? "").toLowerCase(),
3607
- String(item.title ?? "").toLowerCase(),
3608
- String(item.pageStart ?? "")
3609
- ].join("|"));
3949
+ return mergeArrayPayload(current, next, "endorsements", (item) => keyFromParts(
3950
+ item.formNumber,
3951
+ item.title,
3952
+ item.pageStart
3953
+ ));
3610
3954
  case "exclusions":
3611
- return mergeArrayPayload(current, next, "exclusions", (item) => [
3612
- String(item.name ?? "").toLowerCase(),
3613
- String(item.formNumber ?? "").toLowerCase(),
3614
- String(item.pageNumber ?? "")
3615
- ].join("|"));
3955
+ return mergeArrayPayload(current, next, "exclusions", (item) => keyFromParts(
3956
+ item.name,
3957
+ item.formNumber,
3958
+ item.pageNumber
3959
+ ));
3616
3960
  case "conditions":
3617
- return mergeArrayPayload(current, next, "conditions", (item) => [
3618
- String(item.name ?? "").toLowerCase(),
3619
- String(item.conditionType ?? "").toLowerCase(),
3620
- String(item.pageNumber ?? "")
3621
- ].join("|"));
3961
+ return mergeArrayPayload(current, next, "conditions", (item) => keyFromParts(
3962
+ item.name,
3963
+ item.conditionType,
3964
+ item.pageNumber
3965
+ ));
3622
3966
  case "sections":
3623
- return mergeArrayPayload(current, next, "sections", (item) => [
3624
- String(item.title ?? "").toLowerCase(),
3625
- String(item.type ?? "").toLowerCase(),
3626
- String(item.pageStart ?? ""),
3627
- String(item.pageEnd ?? "")
3628
- ].join("|"));
3967
+ return mergeArrayPayload(current, next, "sections", (item) => keyFromParts(
3968
+ item.title,
3969
+ item.type,
3970
+ item.pageStart,
3971
+ item.pageEnd
3972
+ ));
3629
3973
  default:
3630
3974
  return mergeShallowPreferPresent(current, next);
3631
3975
  }
@@ -4484,6 +4828,8 @@ var PageExtractorSchema = import_zod20.z.enum([
4484
4828
  "carrier_info",
4485
4829
  "named_insured",
4486
4830
  "coverage_limits",
4831
+ "covered_reasons",
4832
+ "definitions",
4487
4833
  "endorsements",
4488
4834
  "exclusions",
4489
4835
  "conditions",
@@ -4530,6 +4876,8 @@ Available extractors:
4530
4876
  - carrier_info
4531
4877
  - named_insured
4532
4878
  - coverage_limits
4879
+ - covered_reasons
4880
+ - definitions
4533
4881
  - endorsements
4534
4882
  - exclusions
4535
4883
  - conditions
@@ -4543,6 +4891,8 @@ Rules:
4543
4891
  - Identify the broad section or form context first, then assign focused extractors within that context.
4544
4892
  - Use specific extractors for declarations, schedules, endorsements, exclusions, conditions, premium pages, and loss runs.
4545
4893
  - Use "sections" for pages that contain substantive policy text or mixed content that should still be preserved as raw sections.
4894
+ - Use "definitions" for policy-form pages containing defined terms, definitions sections, or term meaning clauses.
4895
+ - Use "covered_reasons" for pages listing covered causes of loss, covered reasons, covered perils, named perils, covered events, or covered loss triggers.
4546
4896
  - Avoid assigning broad ranges mentally; decide page by page.
4547
4897
  - A page may map to multiple extractors if it legitimately contains multiple relevant sections.
4548
4898
  - Prefer declarations and schedules for numeric limits/deductibles over later generic form wording.
@@ -4550,6 +4900,7 @@ Rules:
4550
4900
  - Do NOT assign "coverage_limits" for generic policy-form or endorsement text that merely explains how limits, deductibles, waiting periods, or coinsurance work, or that says values are "shown in the declarations", "shown in the schedule", "as stated", or "if applicable".
4551
4901
  - Headings like "Limits of Insurance", "Deductible", "Coinsurance", "Loss Conditions", or "Definitions" inside a policy form usually indicate form language, not declarations or schedules.
4552
4902
  - Continuation pages near the end of a form should stay mapped to "sections" plus "conditions"/"exclusions" when applicable, even if they mention limits or deductibles.
4903
+ - Covered causes/reasons and definitions often span a whole form section; tag every substantive page in that section, not just the heading page.
4553
4904
  - When a form inventory entry identifies a page range as a specific form type (e.g., endorsement, coverage, application), use that classification to guide your extractor choice. Do not assign "coverage_limits" to pages the inventory identifies as endorsement or condition/exclusion forms unless the page contains actual schedule values.
4554
4905
  - Do not tag a page with "exclusions" or "conditions" if it only contains a table of contents, page-number reference, running header/footer, or a heading that points to another page without substantive wording.
4555
4906
  - If a page appears to be part of a larger exclusion, conditions, or endorsement section within the same form, keep the assignment consistent across nearby pages in that section rather than isolating a single page fragment.
@@ -4618,9 +4969,13 @@ Mark the extraction as NOT complete if any of these are true:
4618
4969
  - required fields are missing
4619
4970
  - extracted values are generic placeholders like "shown in declarations", "per schedule", "if applicable", "as stated"
4620
4971
  - coverage limits or deductibles appear to come from generic form language instead of declaration/schedule-specific values
4972
+ - definitions pages were mapped but no definition records or definition-type sections were extracted
4973
+ - covered causes/reasons pages were mapped but no covered reason, covered peril, covered cause, or matching section records were extracted
4621
4974
  - page assignments suggest declaration, schedule, endorsement, exclusion, or condition pages were not actually extracted with the matching focused extractor
4622
4975
  - a focused extractor exists but returned too little substance for the relevant pages
4623
4976
 
4977
+ When reviewing CURRENT EXTRACTION SUMMARY, compare the page-map counts to extracted counts. For definitions and covered_reasons, missing extraction should produce a quality issue and a narrow follow-up task over the mapped page range.
4978
+
4624
4979
  Return JSON:
4625
4980
  {
4626
4981
  "complete": boolean,
@@ -5264,6 +5619,107 @@ For auxiliaryFacts:
5264
5619
  Return JSON only.`;
5265
5620
  }
5266
5621
 
5622
+ // src/prompts/extractors/definitions.ts
5623
+ var import_zod34 = require("zod");
5624
+ var DefinitionsSchema = import_zod34.z.object({
5625
+ definitions: import_zod34.z.array(
5626
+ import_zod34.z.object({
5627
+ term: import_zod34.z.string().describe("Defined term exactly as shown in the document"),
5628
+ definition: import_zod34.z.string().describe("Full verbatim definition text, preserving original wording"),
5629
+ pageNumber: import_zod34.z.number().optional().describe("Original document page number"),
5630
+ formNumber: import_zod34.z.string().optional().describe("Form number where this definition appears"),
5631
+ formTitle: import_zod34.z.string().optional().describe("Form title where this definition appears"),
5632
+ sectionRef: import_zod34.z.string().optional().describe("Definition section heading or subsection reference"),
5633
+ originalContent: import_zod34.z.string().optional().describe("Short verbatim source snippet containing the term and definition")
5634
+ })
5635
+ ).describe("All substantive insurance definitions found in the document")
5636
+ });
5637
+ function buildDefinitionsPrompt() {
5638
+ return `You are an expert insurance document analyst. Extract ALL substantive defined terms from this document. Preserve original wording verbatim.
5639
+
5640
+ For EACH definition, extract:
5641
+ - term: defined term exactly as shown \u2014 REQUIRED
5642
+ - definition: full verbatim definition text including all included subparts \u2014 REQUIRED
5643
+ - pageNumber: original document page number where the definition appears
5644
+ - formNumber: form number where the definition appears, if shown
5645
+ - formTitle: form title where the definition appears, if shown
5646
+ - sectionRef: heading such as "Definitions", "Words and Phrases Defined", or coverage-specific definition section
5647
+ - originalContent: short verbatim source snippet containing the term and definition
5648
+
5649
+ Focus on:
5650
+ - Terms in sections titled Definitions, Words and Phrases Defined, Glossary, or similar
5651
+ - Coverage-specific defined terms embedded in insuring agreements, endorsements, exclusions, or conditions
5652
+ - Multi-part definitions with numbered, lettered, or bulleted clauses
5653
+ - Definitions that affect coverage triggers, covered property, insured status, exclusions, limits, or duties
5654
+
5655
+ Critical rules:
5656
+ - Preserve the original content. Do not paraphrase content.
5657
+ - Keep all subparts of a definition together in one item when they define the same term.
5658
+ - Ignore table-of-contents entries, running headers/footers, indexes, and cross-references that do not include substantive definition text.
5659
+ - Do not emit generic headings like "Definitions" as a term unless the page defines an actual term.
5660
+ - Always include pageNumber when the definition appears on a specific page in the supplied document chunk.
5661
+ - Use definition as the canonical full text. Do not return a separate content field.
5662
+
5663
+ Return JSON only.`;
5664
+ }
5665
+
5666
+ // src/prompts/extractors/covered-reasons.ts
5667
+ var import_zod35 = require("zod");
5668
+ var CoveredReasonsSchema = import_zod35.z.object({
5669
+ coveredReasons: import_zod35.z.array(
5670
+ import_zod35.z.object({
5671
+ coverageName: import_zod35.z.string().describe("Coverage, coverage part, or form this covered reason belongs to"),
5672
+ reasonNumber: import_zod35.z.string().optional().describe("Source number or letter for the covered reason, if shown"),
5673
+ title: import_zod35.z.string().optional().describe("Covered reason title, peril, cause of loss, trigger, or short name"),
5674
+ content: import_zod35.z.string().describe("Full verbatim covered-reason or insuring-agreement text"),
5675
+ conditions: import_zod35.z.array(import_zod35.z.string()).optional().describe("Conditions, timing rules, documentation requirements, or prerequisites attached to this covered reason"),
5676
+ exceptions: import_zod35.z.array(import_zod35.z.string()).optional().describe("Exceptions or limitations attached to this covered reason"),
5677
+ appliesTo: import_zod35.z.array(import_zod35.z.string()).optional().describe("Covered property, persons, autos, locations, operations, or coverage parts this reason applies to"),
5678
+ pageNumber: import_zod35.z.number().optional().describe("Original document page number"),
5679
+ formNumber: import_zod35.z.string().optional().describe("Form number where this covered reason appears"),
5680
+ formTitle: import_zod35.z.string().optional().describe("Form title where this covered reason appears"),
5681
+ sectionRef: import_zod35.z.string().optional().describe("Section heading where this covered reason appears"),
5682
+ originalContent: import_zod35.z.string().optional().describe("Short verbatim source snippet used for this covered reason")
5683
+ })
5684
+ ).describe("Covered causes, perils, triggers, or reasons that affirmatively grant coverage")
5685
+ });
5686
+ function buildCoveredReasonsPrompt() {
5687
+ return `You are an expert insurance document analyst. Extract ALL covered reasons from this document. Preserve original wording verbatim.
5688
+
5689
+ A covered reason is affirmative coverage language explaining why, when, or for what cause the insurer will pay. This may be called a covered peril, covered cause of loss, accident, occurrence, loss trigger, additional coverage, expense, or insuring agreement grant.
5690
+
5691
+ For EACH covered reason, extract:
5692
+ - coverageName: coverage, coverage part, or form this covered reason belongs to \u2014 REQUIRED
5693
+ - reasonNumber: source number or letter for the covered reason, if shown
5694
+ - title: covered peril, cause of loss, trigger, or short name
5695
+ - content: full verbatim covered-reason or insuring-agreement text \u2014 REQUIRED
5696
+ - conditions: conditions, timing rules, documentation requirements, or prerequisites attached to this covered reason
5697
+ - exceptions: exceptions or limitations attached to this covered reason
5698
+ - appliesTo: covered property, persons, autos, locations, operations, or coverage parts this reason applies to
5699
+ - pageNumber: original document page number where this covered reason appears
5700
+ - formNumber: form number where this covered reason appears, if shown
5701
+ - formTitle: form title where this covered reason appears, if shown
5702
+ - sectionRef: heading where this covered reason appears
5703
+ - originalContent: short verbatim source snippet used for this covered reason
5704
+
5705
+ Focus on:
5706
+ - Named perils and covered causes of loss
5707
+ - Insuring agreement grants and coverage triggers
5708
+ - Additional coverages and coverage extensions that state when payment applies
5709
+ - Personal lines phrases such as fire, lightning, windstorm, hail, theft, collision, comprehensive, or accidental direct physical loss
5710
+ - Commercial lines phrases such as bodily injury, property damage, personal and advertising injury, employee dishonesty, computer fraud, equipment breakdown, or professional services acts
5711
+
5712
+ Critical rules:
5713
+ - Preserve the original content. Do not paraphrase content.
5714
+ - Extract affirmative coverage grants, not exclusions, conditions, or declarations-only limit rows.
5715
+ - Do not emit a covered reason from a table-of-contents entry, running header/footer, or reference that only points elsewhere.
5716
+ - If a covered reason includes exceptions or limitations in the same clause, keep them in content and also list them in exceptions when they can be separated cleanly.
5717
+ - Always include pageNumber when the covered reason appears on a specific page in the supplied document chunk.
5718
+ - Preserve coverage grouping. Do not merge separate coverage parts into one generic list.
5719
+
5720
+ Return JSON only.`;
5721
+ }
5722
+
5267
5723
  // src/prompts/extractors/index.ts
5268
5724
  var EXTRACTORS = {
5269
5725
  carrier_info: { buildPrompt: buildCarrierInfoPrompt, schema: CarrierInfoSchema, maxTokens: 2048 },
@@ -5276,28 +5732,30 @@ var EXTRACTORS = {
5276
5732
  declarations: { buildPrompt: buildDeclarationsPrompt, schema: DeclarationsExtractSchema, maxTokens: 8192 },
5277
5733
  loss_history: { buildPrompt: buildLossHistoryPrompt, schema: LossHistorySchema, maxTokens: 4096 },
5278
5734
  sections: { buildPrompt: buildSectionsPrompt, schema: SectionsSchema, maxTokens: 8192 },
5279
- supplementary: { buildPrompt: buildSupplementaryPrompt, schema: SupplementarySchema, maxTokens: 2048 }
5735
+ supplementary: { buildPrompt: buildSupplementaryPrompt, schema: SupplementarySchema, maxTokens: 2048 },
5736
+ definitions: { buildPrompt: buildDefinitionsPrompt, schema: DefinitionsSchema, maxTokens: 8192 },
5737
+ covered_reasons: { buildPrompt: buildCoveredReasonsPrompt, schema: CoveredReasonsSchema, maxTokens: 8192 }
5280
5738
  };
5281
5739
  function getExtractor(name) {
5282
5740
  return EXTRACTORS[name];
5283
5741
  }
5284
5742
 
5285
5743
  // src/extraction/resolve-referential.ts
5286
- var import_zod35 = require("zod");
5744
+ var import_zod37 = require("zod");
5287
5745
 
5288
5746
  // src/prompts/extractors/referential-lookup.ts
5289
- var import_zod34 = require("zod");
5290
- var ReferentialLookupSchema = import_zod34.z.object({
5291
- resolvedCoverages: import_zod34.z.array(
5292
- import_zod34.z.object({
5293
- coverageName: import_zod34.z.string().describe("The coverage name that was referenced"),
5294
- resolvedLimit: import_zod34.z.string().optional().describe("The concrete limit value found, if any"),
5747
+ var import_zod36 = require("zod");
5748
+ var ReferentialLookupSchema = import_zod36.z.object({
5749
+ resolvedCoverages: import_zod36.z.array(
5750
+ import_zod36.z.object({
5751
+ coverageName: import_zod36.z.string().describe("The coverage name that was referenced"),
5752
+ resolvedLimit: import_zod36.z.string().optional().describe("The concrete limit value found, if any"),
5295
5753
  resolvedLimitValueType: CoverageValueTypeSchema.optional(),
5296
- resolvedDeductible: import_zod34.z.string().optional().describe("The concrete deductible value found, if any"),
5754
+ resolvedDeductible: import_zod36.z.string().optional().describe("The concrete deductible value found, if any"),
5297
5755
  resolvedDeductibleValueType: CoverageValueTypeSchema.optional(),
5298
- pageNumber: import_zod34.z.number().optional().describe("Page where the resolved value was found"),
5299
- originalContent: import_zod34.z.string().optional().describe("Verbatim source text for the resolved value"),
5300
- confidence: import_zod34.z.enum(["high", "medium", "low"]).describe("Confidence in the resolution")
5756
+ pageNumber: import_zod36.z.number().optional().describe("Page where the resolved value was found"),
5757
+ originalContent: import_zod36.z.string().optional().describe("Verbatim source text for the resolved value"),
5758
+ confidence: import_zod36.z.enum(["high", "medium", "low"]).describe("Confidence in the resolution")
5301
5759
  })
5302
5760
  )
5303
5761
  });
@@ -5356,9 +5814,9 @@ function parseReferenceTarget(text) {
5356
5814
  if (/if applicable/i.test(normalized)) return void 0;
5357
5815
  return void 0;
5358
5816
  }
5359
- var PageLocationSchema = import_zod35.z.object({
5360
- startPage: import_zod35.z.number(),
5361
- endPage: import_zod35.z.number()
5817
+ var PageLocationSchema = import_zod37.z.object({
5818
+ startPage: import_zod37.z.number(),
5819
+ endPage: import_zod37.z.number()
5362
5820
  });
5363
5821
  async function findReferencedPages(params) {
5364
5822
  const {
@@ -5678,6 +6136,32 @@ function buildExtractionReviewReport(params) {
5678
6136
  const exclusions = memory.get("exclusions")?.exclusions ?? [];
5679
6137
  const conditions = memory.get("conditions")?.conditions ?? [];
5680
6138
  const sections = memory.get("sections")?.sections ?? [];
6139
+ const definitionsResult = memory.get("definitions");
6140
+ const coveredReasonsResult = memory.get("covered_reasons");
6141
+ const definitions = Array.isArray(definitionsResult?.definitions) ? definitionsResult.definitions : sections.filter((section) => section.type === "definition");
6142
+ const coveredReasons = Array.isArray(coveredReasonsResult?.coveredReasons) ? coveredReasonsResult.coveredReasons : Array.isArray(coveredReasonsResult?.covered_reasons) ? coveredReasonsResult.covered_reasons : sections.filter((section) => {
6143
+ const title = String(section.title ?? "").toLowerCase();
6144
+ const type = String(section.type ?? "").toLowerCase();
6145
+ return type === "covered_reason" || title.includes("covered cause") || title.includes("covered reason") || title.includes("covered peril");
6146
+ });
6147
+ const mappedDefinitions = params.pageAssignments.some((assignment) => assignment.extractorNames.includes("definitions"));
6148
+ const mappedCoveredReasons = params.pageAssignments.some((assignment) => assignment.extractorNames.includes("covered_reasons"));
6149
+ if (mappedDefinitions && definitions.length === 0) {
6150
+ deterministicIssues.push({
6151
+ code: "definitions_mapped_but_empty",
6152
+ severity: "warning",
6153
+ message: "Page map assigned definitions extraction, but no definition records were extracted.",
6154
+ extractorName: "definitions"
6155
+ });
6156
+ }
6157
+ if (mappedCoveredReasons && coveredReasons.length === 0) {
6158
+ deterministicIssues.push({
6159
+ code: "covered_reasons_mapped_but_empty",
6160
+ severity: "warning",
6161
+ message: "Page map assigned covered reasons extraction, but no covered reason records were extracted.",
6162
+ extractorName: "covered_reasons"
6163
+ });
6164
+ }
5681
6165
  for (const form of extractedFormInventory) {
5682
6166
  addFormEntry(
5683
6167
  inventory,
@@ -5875,6 +6359,67 @@ function buildExtractionReviewReport(params) {
5875
6359
  });
5876
6360
  }
5877
6361
  }
6362
+ for (const definition of definitions) {
6363
+ const term = typeof definition.term === "string" ? definition.term : typeof definition.title === "string" ? definition.title : "unknown";
6364
+ const content = typeof definition.definition === "string" ? definition.definition : typeof definition.content === "string" ? definition.content : "";
6365
+ if (!content.trim()) {
6366
+ deterministicIssues.push({
6367
+ code: "definition_missing_content",
6368
+ severity: "warning",
6369
+ message: `Definition "${term}" is missing definition text.`,
6370
+ extractorName: "definitions",
6371
+ formNumber: normalizeFormNumber(definition.formNumber),
6372
+ pageNumber: typeof definition.pageNumber === "number" ? definition.pageNumber : typeof definition.pageStart === "number" ? definition.pageStart : void 0,
6373
+ itemName: term
6374
+ });
6375
+ }
6376
+ if (typeof definition.pageNumber !== "number" && typeof definition.pageStart !== "number") {
6377
+ deterministicIssues.push({
6378
+ code: "definition_missing_page_number",
6379
+ severity: "warning",
6380
+ message: `Definition "${term}" is missing page provenance.`,
6381
+ extractorName: "definitions",
6382
+ formNumber: normalizeFormNumber(definition.formNumber),
6383
+ itemName: term
6384
+ });
6385
+ }
6386
+ }
6387
+ for (const coveredReason of coveredReasons) {
6388
+ const itemName = typeof coveredReason.name === "string" ? coveredReason.name : typeof coveredReason.reason === "string" ? coveredReason.reason : typeof coveredReason.title === "string" ? coveredReason.title : "unknown";
6389
+ const content = typeof coveredReason.content === "string" ? coveredReason.content : typeof coveredReason.description === "string" ? coveredReason.description : "";
6390
+ if (!content.trim()) {
6391
+ deterministicIssues.push({
6392
+ code: "covered_reason_missing_content",
6393
+ severity: "warning",
6394
+ message: `Covered reason "${itemName}" is missing substantive text.`,
6395
+ extractorName: "covered_reasons",
6396
+ formNumber: normalizeFormNumber(coveredReason.formNumber),
6397
+ pageNumber: typeof coveredReason.pageNumber === "number" ? coveredReason.pageNumber : typeof coveredReason.pageStart === "number" ? coveredReason.pageStart : void 0,
6398
+ itemName
6399
+ });
6400
+ }
6401
+ if (typeof coveredReason.pageNumber !== "number" && typeof coveredReason.pageStart !== "number") {
6402
+ deterministicIssues.push({
6403
+ code: "covered_reason_missing_page_number",
6404
+ severity: "warning",
6405
+ message: `Covered reason "${itemName}" is missing page provenance.`,
6406
+ extractorName: "covered_reasons",
6407
+ formNumber: normalizeFormNumber(coveredReason.formNumber),
6408
+ itemName
6409
+ });
6410
+ }
6411
+ if (looksReferential2(content) || looksReferential2(coveredReason.reason)) {
6412
+ deterministicIssues.push({
6413
+ code: "covered_reason_referential_value",
6414
+ severity: "warning",
6415
+ message: `Covered reason "${itemName}" contains referential language instead of the extracted covered cause wording.`,
6416
+ extractorName: "covered_reasons",
6417
+ formNumber: normalizeFormNumber(coveredReason.formNumber),
6418
+ pageNumber: typeof coveredReason.pageNumber === "number" ? coveredReason.pageNumber : typeof coveredReason.pageStart === "number" ? coveredReason.pageStart : void 0,
6419
+ itemName
6420
+ });
6421
+ }
6422
+ }
5878
6423
  for (const section of sections) {
5879
6424
  if (typeof section.content === "string" && section.content.trim().length < 120 && typeof section.pageStart === "number" && (!("pageEnd" in section) || section.pageEnd === section.pageStart || section.pageEnd === void 0)) {
5880
6425
  deterministicIssues.push({
@@ -5897,6 +6442,8 @@ function buildExtractionReviewReport(params) {
5897
6442
  const artifacts = [
5898
6443
  { kind: "form_inventory", label: "Form Inventory", itemCount: formInventory.length },
5899
6444
  { kind: "page_map", label: "Page Map", itemCount: params.pageAssignments.length },
6445
+ { kind: "definitions", label: "Definitions", itemCount: definitions.length },
6446
+ { kind: "covered_reasons", label: "Covered Reasons", itemCount: coveredReasons.length },
5900
6447
  { kind: "referential_resolution", label: "Referential Resolution", itemCount: coverages.filter((c) => c.limitValueType === "referential" || c.limitValueType === "as_stated" || c.deductibleValueType === "referential" || c.deductibleValueType === "as_stated").length }
5901
6448
  ];
5902
6449
  const qualityGateStatus = evaluateQualityGate({
@@ -5964,6 +6511,15 @@ function createExtractor(config) {
5964
6511
  const exclusionResult = memory.get("exclusions");
5965
6512
  const conditionResult = memory.get("conditions");
5966
6513
  const sectionResult = memory.get("sections");
6514
+ const definitionsResult = memory.get("definitions");
6515
+ const coveredReasonsResult = memory.get("covered_reasons");
6516
+ const sections = Array.isArray(sectionResult?.sections) ? sectionResult.sections : [];
6517
+ const definitionCount = Array.isArray(definitionsResult?.definitions) ? definitionsResult.definitions.length : sections.filter((section) => section.type === "definition").length;
6518
+ const coveredReasonCount = Array.isArray(coveredReasonsResult?.coveredReasons) ? coveredReasonsResult.coveredReasons.length : Array.isArray(coveredReasonsResult?.covered_reasons) ? coveredReasonsResult.covered_reasons.length : sections.filter((section) => {
6519
+ const title = String(section.title ?? "").toLowerCase();
6520
+ const type = String(section.type ?? "").toLowerCase();
6521
+ return type === "covered_reason" || title.includes("covered cause") || title.includes("covered reason") || title.includes("covered peril");
6522
+ }).length;
5967
6523
  const coverageSummary = Array.isArray(coverageResult?.coverages) ? coverageResult.coverages.slice(0, 12).map((coverage) => ({
5968
6524
  name: coverage.name,
5969
6525
  limit: coverage.limit,
@@ -5978,7 +6534,9 @@ function createExtractor(config) {
5978
6534
  endorsementCount: Array.isArray(endorsementResult?.endorsements) ? endorsementResult.endorsements.length : 0,
5979
6535
  exclusionCount: Array.isArray(exclusionResult?.exclusions) ? exclusionResult.exclusions.length : 0,
5980
6536
  conditionCount: Array.isArray(conditionResult?.conditions) ? conditionResult.conditions.length : 0,
5981
- sectionCount: Array.isArray(sectionResult?.sections) ? sectionResult.sections.length : 0
6537
+ definitionCount,
6538
+ coveredReasonCount,
6539
+ sectionCount: sections.length
5982
6540
  }, null, 2);
5983
6541
  }
5984
6542
  function buildAlreadyExtractedSummary(memory) {
@@ -6021,7 +6579,7 @@ function createExtractor(config) {
6021
6579
  }
6022
6580
  }
6023
6581
  if (extractorPages.size === 0) return "No page assignments available.";
6024
- return [...extractorPages.entries()].map(([extractorName, pages]) => `${extractorName}: pages ${pages.join(", ")}`).join("\n");
6582
+ return [...extractorPages.entries()].map(([extractorName, pages]) => `${extractorName}: ${pages.length} page(s), pages ${pages.join(", ")}`).join("\n");
6025
6583
  }
6026
6584
  function normalizePageAssignments(pageAssignments, formInventory) {
6027
6585
  const pageFormTypes = /* @__PURE__ */ new Map();
@@ -6111,7 +6669,7 @@ function createExtractor(config) {
6111
6669
  extractorPages.set("sections", [...extractorPages.get("sections") ?? [], page]);
6112
6670
  }
6113
6671
  }
6114
- const contextualExtractors = /* @__PURE__ */ new Set(["conditions", "exclusions", "endorsements"]);
6672
+ const contextualExtractors = /* @__PURE__ */ new Set(["conditions", "covered_reasons", "definitions", "exclusions", "endorsements"]);
6115
6673
  const contextualForms = (formInventory?.forms ?? []).filter(
6116
6674
  (form) => form.pageStart != null && (form.pageEnd ?? form.pageStart) != null
6117
6675
  );
@@ -6327,7 +6885,7 @@ function createExtractor(config) {
6327
6885
  const extractorResults = await Promise.all(
6328
6886
  tasks.map(
6329
6887
  (task) => limit(async () => {
6330
- const ext = getExtractor(task.extractorName);
6888
+ const ext = getExtractor(task.extractorName) ?? (task.extractorName === "definitions" || task.extractorName === "covered_reasons" ? getExtractor("sections") : void 0);
6331
6889
  if (!ext) {
6332
6890
  await log?.(`Unknown extractor: ${task.extractorName}, skipping`);
6333
6891
  return null;
@@ -6458,7 +7016,7 @@ function createExtractor(config) {
6458
7016
  const followUpResults = await Promise.all(
6459
7017
  reviewResponse.object.additionalTasks.map(
6460
7018
  (task) => limit(async () => {
6461
- const ext = getExtractor(task.extractorName);
7019
+ const ext = getExtractor(task.extractorName) ?? (task.extractorName === "definitions" || task.extractorName === "covered_reasons" ? getExtractor("sections") : void 0);
6462
7020
  if (!ext) return null;
6463
7021
  try {
6464
7022
  const result = await runExtractor({
@@ -6798,8 +7356,8 @@ Respond with JSON only:
6798
7356
  }`;
6799
7357
 
6800
7358
  // src/schemas/application.ts
6801
- var import_zod36 = require("zod");
6802
- var FieldTypeSchema = import_zod36.z.enum([
7359
+ var import_zod38 = require("zod");
7360
+ var FieldTypeSchema = import_zod38.z.enum([
6803
7361
  "text",
6804
7362
  "numeric",
6805
7363
  "currency",
@@ -6808,131 +7366,131 @@ var FieldTypeSchema = import_zod36.z.enum([
6808
7366
  "table",
6809
7367
  "declaration"
6810
7368
  ]);
6811
- var ApplicationFieldSchema = import_zod36.z.object({
6812
- id: import_zod36.z.string(),
6813
- label: import_zod36.z.string(),
6814
- section: import_zod36.z.string(),
7369
+ var ApplicationFieldSchema = import_zod38.z.object({
7370
+ id: import_zod38.z.string(),
7371
+ label: import_zod38.z.string(),
7372
+ section: import_zod38.z.string(),
6815
7373
  fieldType: FieldTypeSchema,
6816
- required: import_zod36.z.boolean(),
6817
- options: import_zod36.z.array(import_zod36.z.string()).optional(),
6818
- columns: import_zod36.z.array(import_zod36.z.string()).optional(),
6819
- requiresExplanationIfYes: import_zod36.z.boolean().optional(),
6820
- condition: import_zod36.z.object({
6821
- dependsOn: import_zod36.z.string(),
6822
- whenValue: import_zod36.z.string()
7374
+ required: import_zod38.z.boolean(),
7375
+ options: import_zod38.z.array(import_zod38.z.string()).optional(),
7376
+ columns: import_zod38.z.array(import_zod38.z.string()).optional(),
7377
+ requiresExplanationIfYes: import_zod38.z.boolean().optional(),
7378
+ condition: import_zod38.z.object({
7379
+ dependsOn: import_zod38.z.string(),
7380
+ whenValue: import_zod38.z.string()
6823
7381
  }).optional(),
6824
- value: import_zod36.z.string().optional(),
6825
- source: import_zod36.z.string().optional().describe("Where the value came from: auto-fill, user, lookup"),
6826
- confidence: import_zod36.z.enum(["confirmed", "high", "medium", "low"]).optional()
6827
- });
6828
- var ApplicationClassifyResultSchema = import_zod36.z.object({
6829
- isApplication: import_zod36.z.boolean(),
6830
- confidence: import_zod36.z.number().min(0).max(1),
6831
- applicationType: import_zod36.z.string().nullable()
6832
- });
6833
- var FieldExtractionResultSchema = import_zod36.z.object({
6834
- fields: import_zod36.z.array(ApplicationFieldSchema)
6835
- });
6836
- var AutoFillMatchSchema = import_zod36.z.object({
6837
- fieldId: import_zod36.z.string(),
6838
- value: import_zod36.z.string(),
6839
- confidence: import_zod36.z.enum(["confirmed"]),
6840
- contextKey: import_zod36.z.string()
6841
- });
6842
- var AutoFillResultSchema = import_zod36.z.object({
6843
- matches: import_zod36.z.array(AutoFillMatchSchema)
6844
- });
6845
- var QuestionBatchResultSchema = import_zod36.z.object({
6846
- batches: import_zod36.z.array(import_zod36.z.array(import_zod36.z.string()).describe("Array of field IDs in this batch"))
6847
- });
6848
- var LookupRequestSchema = import_zod36.z.object({
6849
- type: import_zod36.z.string().describe("Type of lookup: 'records', 'website', 'policy'"),
6850
- description: import_zod36.z.string(),
6851
- url: import_zod36.z.string().optional(),
6852
- targetFieldIds: import_zod36.z.array(import_zod36.z.string())
6853
- });
6854
- var ReplyIntentSchema = import_zod36.z.object({
6855
- primaryIntent: import_zod36.z.enum(["answers_only", "question", "lookup_request", "mixed"]),
6856
- hasAnswers: import_zod36.z.boolean(),
6857
- questionText: import_zod36.z.string().optional(),
6858
- questionFieldIds: import_zod36.z.array(import_zod36.z.string()).optional(),
6859
- lookupRequests: import_zod36.z.array(LookupRequestSchema).optional()
6860
- });
6861
- var ParsedAnswerSchema = import_zod36.z.object({
6862
- fieldId: import_zod36.z.string(),
6863
- value: import_zod36.z.string(),
6864
- explanation: import_zod36.z.string().optional()
6865
- });
6866
- var AnswerParsingResultSchema = import_zod36.z.object({
6867
- answers: import_zod36.z.array(ParsedAnswerSchema),
6868
- unanswered: import_zod36.z.array(import_zod36.z.string()).describe("Field IDs that were not answered")
6869
- });
6870
- var LookupFillSchema = import_zod36.z.object({
6871
- fieldId: import_zod36.z.string(),
6872
- value: import_zod36.z.string(),
6873
- source: import_zod36.z.string().describe("Specific citable reference, e.g. 'GL Policy #POL-12345 (Hartford)'")
6874
- });
6875
- var LookupFillResultSchema = import_zod36.z.object({
6876
- fills: import_zod36.z.array(LookupFillSchema),
6877
- unfillable: import_zod36.z.array(import_zod36.z.string()),
6878
- explanation: import_zod36.z.string().optional()
6879
- });
6880
- var FlatPdfPlacementSchema = import_zod36.z.object({
6881
- fieldId: import_zod36.z.string(),
6882
- page: import_zod36.z.number(),
6883
- x: import_zod36.z.number().describe("Percentage from left edge (0-100)"),
6884
- y: import_zod36.z.number().describe("Percentage from top edge (0-100)"),
6885
- text: import_zod36.z.string(),
6886
- fontSize: import_zod36.z.number().optional(),
6887
- isCheckmark: import_zod36.z.boolean().optional()
6888
- });
6889
- var AcroFormMappingSchema = import_zod36.z.object({
6890
- fieldId: import_zod36.z.string(),
6891
- acroFormName: import_zod36.z.string(),
6892
- value: import_zod36.z.string()
6893
- });
6894
- var QualityGateStatusSchema = import_zod36.z.enum(["passed", "warning", "failed"]);
6895
- var QualitySeveritySchema = import_zod36.z.enum(["info", "warning", "blocking"]);
6896
- var ApplicationQualityIssueSchema = import_zod36.z.object({
6897
- code: import_zod36.z.string(),
7382
+ value: import_zod38.z.string().optional(),
7383
+ source: import_zod38.z.string().optional().describe("Where the value came from: auto-fill, user, lookup"),
7384
+ confidence: import_zod38.z.enum(["confirmed", "high", "medium", "low"]).optional()
7385
+ });
7386
+ var ApplicationClassifyResultSchema = import_zod38.z.object({
7387
+ isApplication: import_zod38.z.boolean(),
7388
+ confidence: import_zod38.z.number().min(0).max(1),
7389
+ applicationType: import_zod38.z.string().nullable()
7390
+ });
7391
+ var FieldExtractionResultSchema = import_zod38.z.object({
7392
+ fields: import_zod38.z.array(ApplicationFieldSchema)
7393
+ });
7394
+ var AutoFillMatchSchema = import_zod38.z.object({
7395
+ fieldId: import_zod38.z.string(),
7396
+ value: import_zod38.z.string(),
7397
+ confidence: import_zod38.z.enum(["confirmed"]),
7398
+ contextKey: import_zod38.z.string()
7399
+ });
7400
+ var AutoFillResultSchema = import_zod38.z.object({
7401
+ matches: import_zod38.z.array(AutoFillMatchSchema)
7402
+ });
7403
+ var QuestionBatchResultSchema = import_zod38.z.object({
7404
+ batches: import_zod38.z.array(import_zod38.z.array(import_zod38.z.string()).describe("Array of field IDs in this batch"))
7405
+ });
7406
+ var LookupRequestSchema = import_zod38.z.object({
7407
+ type: import_zod38.z.string().describe("Type of lookup: 'records', 'website', 'policy'"),
7408
+ description: import_zod38.z.string(),
7409
+ url: import_zod38.z.string().optional(),
7410
+ targetFieldIds: import_zod38.z.array(import_zod38.z.string())
7411
+ });
7412
+ var ReplyIntentSchema = import_zod38.z.object({
7413
+ primaryIntent: import_zod38.z.enum(["answers_only", "question", "lookup_request", "mixed"]),
7414
+ hasAnswers: import_zod38.z.boolean(),
7415
+ questionText: import_zod38.z.string().optional(),
7416
+ questionFieldIds: import_zod38.z.array(import_zod38.z.string()).optional(),
7417
+ lookupRequests: import_zod38.z.array(LookupRequestSchema).optional()
7418
+ });
7419
+ var ParsedAnswerSchema = import_zod38.z.object({
7420
+ fieldId: import_zod38.z.string(),
7421
+ value: import_zod38.z.string(),
7422
+ explanation: import_zod38.z.string().optional()
7423
+ });
7424
+ var AnswerParsingResultSchema = import_zod38.z.object({
7425
+ answers: import_zod38.z.array(ParsedAnswerSchema),
7426
+ unanswered: import_zod38.z.array(import_zod38.z.string()).describe("Field IDs that were not answered")
7427
+ });
7428
+ var LookupFillSchema = import_zod38.z.object({
7429
+ fieldId: import_zod38.z.string(),
7430
+ value: import_zod38.z.string(),
7431
+ source: import_zod38.z.string().describe("Specific citable reference, e.g. 'GL Policy #POL-12345 (Hartford)'")
7432
+ });
7433
+ var LookupFillResultSchema = import_zod38.z.object({
7434
+ fills: import_zod38.z.array(LookupFillSchema),
7435
+ unfillable: import_zod38.z.array(import_zod38.z.string()),
7436
+ explanation: import_zod38.z.string().optional()
7437
+ });
7438
+ var FlatPdfPlacementSchema = import_zod38.z.object({
7439
+ fieldId: import_zod38.z.string(),
7440
+ page: import_zod38.z.number(),
7441
+ x: import_zod38.z.number().describe("Percentage from left edge (0-100)"),
7442
+ y: import_zod38.z.number().describe("Percentage from top edge (0-100)"),
7443
+ text: import_zod38.z.string(),
7444
+ fontSize: import_zod38.z.number().optional(),
7445
+ isCheckmark: import_zod38.z.boolean().optional()
7446
+ });
7447
+ var AcroFormMappingSchema = import_zod38.z.object({
7448
+ fieldId: import_zod38.z.string(),
7449
+ acroFormName: import_zod38.z.string(),
7450
+ value: import_zod38.z.string()
7451
+ });
7452
+ var QualityGateStatusSchema = import_zod38.z.enum(["passed", "warning", "failed"]);
7453
+ var QualitySeveritySchema = import_zod38.z.enum(["info", "warning", "blocking"]);
7454
+ var ApplicationQualityIssueSchema = import_zod38.z.object({
7455
+ code: import_zod38.z.string(),
6898
7456
  severity: QualitySeveritySchema,
6899
- message: import_zod36.z.string(),
6900
- fieldId: import_zod36.z.string().optional()
7457
+ message: import_zod38.z.string(),
7458
+ fieldId: import_zod38.z.string().optional()
6901
7459
  });
6902
- var ApplicationQualityRoundSchema = import_zod36.z.object({
6903
- round: import_zod36.z.number(),
6904
- kind: import_zod36.z.string(),
7460
+ var ApplicationQualityRoundSchema = import_zod38.z.object({
7461
+ round: import_zod38.z.number(),
7462
+ kind: import_zod38.z.string(),
6905
7463
  status: QualityGateStatusSchema,
6906
- summary: import_zod36.z.string().optional()
7464
+ summary: import_zod38.z.string().optional()
6907
7465
  });
6908
- var ApplicationQualityArtifactSchema = import_zod36.z.object({
6909
- kind: import_zod36.z.string(),
6910
- label: import_zod36.z.string().optional(),
6911
- itemCount: import_zod36.z.number().optional()
7466
+ var ApplicationQualityArtifactSchema = import_zod38.z.object({
7467
+ kind: import_zod38.z.string(),
7468
+ label: import_zod38.z.string().optional(),
7469
+ itemCount: import_zod38.z.number().optional()
6912
7470
  });
6913
- var ApplicationEmailReviewSchema = import_zod36.z.object({
6914
- issues: import_zod36.z.array(ApplicationQualityIssueSchema),
7471
+ var ApplicationEmailReviewSchema = import_zod38.z.object({
7472
+ issues: import_zod38.z.array(ApplicationQualityIssueSchema),
6915
7473
  qualityGateStatus: QualityGateStatusSchema
6916
7474
  });
6917
- var ApplicationQualityReportSchema = import_zod36.z.object({
6918
- issues: import_zod36.z.array(ApplicationQualityIssueSchema),
6919
- rounds: import_zod36.z.array(ApplicationQualityRoundSchema).optional(),
6920
- artifacts: import_zod36.z.array(ApplicationQualityArtifactSchema).optional(),
7475
+ var ApplicationQualityReportSchema = import_zod38.z.object({
7476
+ issues: import_zod38.z.array(ApplicationQualityIssueSchema),
7477
+ rounds: import_zod38.z.array(ApplicationQualityRoundSchema).optional(),
7478
+ artifacts: import_zod38.z.array(ApplicationQualityArtifactSchema).optional(),
6921
7479
  emailReview: ApplicationEmailReviewSchema.optional(),
6922
7480
  qualityGateStatus: QualityGateStatusSchema
6923
7481
  });
6924
- var ApplicationStateSchema = import_zod36.z.object({
6925
- id: import_zod36.z.string(),
6926
- pdfBase64: import_zod36.z.string().optional().describe("Original PDF, omitted after extraction"),
6927
- title: import_zod36.z.string().optional(),
6928
- applicationType: import_zod36.z.string().nullable().optional(),
6929
- fields: import_zod36.z.array(ApplicationFieldSchema),
6930
- batches: import_zod36.z.array(import_zod36.z.array(import_zod36.z.string())).optional(),
6931
- currentBatchIndex: import_zod36.z.number().default(0),
7482
+ var ApplicationStateSchema = import_zod38.z.object({
7483
+ id: import_zod38.z.string(),
7484
+ pdfBase64: import_zod38.z.string().optional().describe("Original PDF, omitted after extraction"),
7485
+ title: import_zod38.z.string().optional(),
7486
+ applicationType: import_zod38.z.string().nullable().optional(),
7487
+ fields: import_zod38.z.array(ApplicationFieldSchema),
7488
+ batches: import_zod38.z.array(import_zod38.z.array(import_zod38.z.string())).optional(),
7489
+ currentBatchIndex: import_zod38.z.number().default(0),
6932
7490
  qualityReport: ApplicationQualityReportSchema.optional(),
6933
- status: import_zod36.z.enum(["classifying", "extracting", "auto_filling", "batching", "collecting", "confirming", "mapping", "complete"]),
6934
- createdAt: import_zod36.z.number(),
6935
- updatedAt: import_zod36.z.number()
7491
+ status: import_zod38.z.enum(["classifying", "extracting", "auto_filling", "batching", "collecting", "confirming", "mapping", "complete"]),
7492
+ createdAt: import_zod38.z.number(),
7493
+ updatedAt: import_zod38.z.number()
6936
7494
  });
6937
7495
 
6938
7496
  // src/application/agents/classifier.ts
@@ -8038,7 +8596,7 @@ INSTRUCTIONS:
8038
8596
  - If the user's attachment already contains critical facts, still request chunk/document lookup when policy or quote details should be cross-checked against stored records
8039
8597
 
8040
8598
  CHUNK TYPES (for chunkTypes filter):
8041
- carrier_info, named_insured, coverage, endorsement, exclusion, condition, section, declaration, loss_history, premium, supplementary
8599
+ carrier_info, named_insured, coverage, covered_reason, definition, endorsement, exclusion, condition, section, declaration, loss_history, premium, supplementary
8042
8600
 
8043
8601
  Respond with the structured classification.`;
8044
8602
  }
@@ -8069,91 +8627,91 @@ Respond with the final answer, deduplicated citations array, overall confidence
8069
8627
  }
8070
8628
 
8071
8629
  // src/schemas/query.ts
8072
- var import_zod37 = require("zod");
8073
- var QueryIntentSchema = import_zod37.z.enum([
8630
+ var import_zod39 = require("zod");
8631
+ var QueryIntentSchema = import_zod39.z.enum([
8074
8632
  "policy_question",
8075
8633
  "coverage_comparison",
8076
8634
  "document_search",
8077
8635
  "claims_inquiry",
8078
8636
  "general_knowledge"
8079
8637
  ]);
8080
- var QueryAttachmentKindSchema = import_zod37.z.enum(["image", "pdf", "text"]);
8081
- var QueryAttachmentSchema = import_zod37.z.object({
8082
- id: import_zod37.z.string().optional().describe("Optional stable attachment ID from the caller"),
8638
+ var QueryAttachmentKindSchema = import_zod39.z.enum(["image", "pdf", "text"]);
8639
+ var QueryAttachmentSchema = import_zod39.z.object({
8640
+ id: import_zod39.z.string().optional().describe("Optional stable attachment ID from the caller"),
8083
8641
  kind: QueryAttachmentKindSchema,
8084
- name: import_zod37.z.string().optional().describe("Original filename or user-facing label"),
8085
- mimeType: import_zod37.z.string().optional().describe("MIME type such as image/jpeg or application/pdf"),
8086
- base64: import_zod37.z.string().optional().describe("Base64-encoded file content for image/pdf attachments"),
8087
- text: import_zod37.z.string().optional().describe("Plain-text attachment content when available"),
8088
- description: import_zod37.z.string().optional().describe("Caller-provided description of the attachment")
8089
- });
8090
- var SubQuestionSchema = import_zod37.z.object({
8091
- question: import_zod37.z.string().describe("Atomic sub-question to retrieve and answer independently"),
8642
+ name: import_zod39.z.string().optional().describe("Original filename or user-facing label"),
8643
+ mimeType: import_zod39.z.string().optional().describe("MIME type such as image/jpeg or application/pdf"),
8644
+ base64: import_zod39.z.string().optional().describe("Base64-encoded file content for image/pdf attachments"),
8645
+ text: import_zod39.z.string().optional().describe("Plain-text attachment content when available"),
8646
+ description: import_zod39.z.string().optional().describe("Caller-provided description of the attachment")
8647
+ });
8648
+ var SubQuestionSchema = import_zod39.z.object({
8649
+ question: import_zod39.z.string().describe("Atomic sub-question to retrieve and answer independently"),
8092
8650
  intent: QueryIntentSchema,
8093
- chunkTypes: import_zod37.z.array(import_zod37.z.string()).optional().describe("Chunk types to filter retrieval (e.g. coverage, endorsement, declaration)"),
8094
- documentFilters: import_zod37.z.object({
8095
- type: import_zod37.z.enum(["policy", "quote"]).optional(),
8096
- carrier: import_zod37.z.string().optional(),
8097
- insuredName: import_zod37.z.string().optional(),
8098
- policyNumber: import_zod37.z.string().optional(),
8099
- quoteNumber: import_zod37.z.string().optional(),
8100
- policyTypes: import_zod37.z.array(PolicyTypeSchema).optional().describe("Filter by policy type (e.g. homeowners_ho3, renters_ho4, pet) to avoid mixing up similar policies")
8651
+ chunkTypes: import_zod39.z.array(import_zod39.z.string()).optional().describe("Chunk types to filter retrieval (e.g. coverage, endorsement, declaration)"),
8652
+ documentFilters: import_zod39.z.object({
8653
+ type: import_zod39.z.enum(["policy", "quote"]).optional(),
8654
+ carrier: import_zod39.z.string().optional(),
8655
+ insuredName: import_zod39.z.string().optional(),
8656
+ policyNumber: import_zod39.z.string().optional(),
8657
+ quoteNumber: import_zod39.z.string().optional(),
8658
+ policyTypes: import_zod39.z.array(PolicyTypeSchema).optional().describe("Filter by policy type (e.g. homeowners_ho3, renters_ho4, pet) to avoid mixing up similar policies")
8101
8659
  }).optional().describe("Structured filters to narrow document lookup")
8102
8660
  });
8103
- var QueryClassifyResultSchema = import_zod37.z.object({
8661
+ var QueryClassifyResultSchema = import_zod39.z.object({
8104
8662
  intent: QueryIntentSchema,
8105
- subQuestions: import_zod37.z.array(SubQuestionSchema).min(1).describe("Decomposed atomic sub-questions"),
8106
- requiresDocumentLookup: import_zod37.z.boolean().describe("Whether structured document lookup is needed"),
8107
- requiresChunkSearch: import_zod37.z.boolean().describe("Whether semantic chunk search is needed"),
8108
- requiresConversationHistory: import_zod37.z.boolean().describe("Whether conversation history is relevant")
8109
- });
8110
- var EvidenceItemSchema = import_zod37.z.object({
8111
- source: import_zod37.z.enum(["chunk", "document", "conversation", "attachment"]),
8112
- chunkId: import_zod37.z.string().optional(),
8113
- documentId: import_zod37.z.string().optional(),
8114
- turnId: import_zod37.z.string().optional(),
8115
- attachmentId: import_zod37.z.string().optional(),
8116
- text: import_zod37.z.string().describe("Text excerpt from the source"),
8117
- relevance: import_zod37.z.number().min(0).max(1),
8118
- metadata: import_zod37.z.array(import_zod37.z.object({ key: import_zod37.z.string(), value: import_zod37.z.string() })).optional()
8119
- });
8120
- var AttachmentInterpretationSchema = import_zod37.z.object({
8121
- summary: import_zod37.z.string().describe("Concise summary of what the attachment shows or contains"),
8122
- extractedFacts: import_zod37.z.array(import_zod37.z.string()).describe("Specific observable or document facts grounded in the attachment"),
8123
- recommendedFocus: import_zod37.z.array(import_zod37.z.string()).describe("Important details to incorporate when answering follow-up questions"),
8124
- confidence: import_zod37.z.number().min(0).max(1)
8125
- });
8126
- var RetrievalResultSchema = import_zod37.z.object({
8127
- subQuestion: import_zod37.z.string(),
8128
- evidence: import_zod37.z.array(EvidenceItemSchema)
8129
- });
8130
- var CitationSchema = import_zod37.z.object({
8131
- index: import_zod37.z.number().describe("Citation number [1], [2], etc."),
8132
- chunkId: import_zod37.z.string().describe("Source chunk ID, e.g. doc-123:coverage:2"),
8133
- documentId: import_zod37.z.string(),
8134
- documentType: import_zod37.z.enum(["policy", "quote"]).optional(),
8135
- field: import_zod37.z.string().optional().describe("Specific field path, e.g. coverages[0].deductible"),
8136
- quote: import_zod37.z.string().describe("Exact text from source that supports the claim"),
8137
- relevance: import_zod37.z.number().min(0).max(1)
8138
- });
8139
- var SubAnswerSchema = import_zod37.z.object({
8140
- subQuestion: import_zod37.z.string(),
8141
- answer: import_zod37.z.string(),
8142
- citations: import_zod37.z.array(CitationSchema),
8143
- confidence: import_zod37.z.number().min(0).max(1),
8144
- needsMoreContext: import_zod37.z.boolean().describe("True if evidence was insufficient to answer fully")
8145
- });
8146
- var VerifyResultSchema = import_zod37.z.object({
8147
- approved: import_zod37.z.boolean().describe("Whether all sub-answers are adequately grounded"),
8148
- issues: import_zod37.z.array(import_zod37.z.string()).describe("Specific grounding or consistency issues found"),
8149
- retrySubQuestions: import_zod37.z.array(import_zod37.z.string()).optional().describe("Sub-questions that need additional retrieval or re-reasoning")
8150
- });
8151
- var QueryResultSchema = import_zod37.z.object({
8152
- answer: import_zod37.z.string(),
8153
- citations: import_zod37.z.array(CitationSchema),
8663
+ subQuestions: import_zod39.z.array(SubQuestionSchema).min(1).describe("Decomposed atomic sub-questions"),
8664
+ requiresDocumentLookup: import_zod39.z.boolean().describe("Whether structured document lookup is needed"),
8665
+ requiresChunkSearch: import_zod39.z.boolean().describe("Whether semantic chunk search is needed"),
8666
+ requiresConversationHistory: import_zod39.z.boolean().describe("Whether conversation history is relevant")
8667
+ });
8668
+ var EvidenceItemSchema = import_zod39.z.object({
8669
+ source: import_zod39.z.enum(["chunk", "document", "conversation", "attachment"]),
8670
+ chunkId: import_zod39.z.string().optional(),
8671
+ documentId: import_zod39.z.string().optional(),
8672
+ turnId: import_zod39.z.string().optional(),
8673
+ attachmentId: import_zod39.z.string().optional(),
8674
+ text: import_zod39.z.string().describe("Text excerpt from the source"),
8675
+ relevance: import_zod39.z.number().min(0).max(1),
8676
+ metadata: import_zod39.z.array(import_zod39.z.object({ key: import_zod39.z.string(), value: import_zod39.z.string() })).optional()
8677
+ });
8678
+ var AttachmentInterpretationSchema = import_zod39.z.object({
8679
+ summary: import_zod39.z.string().describe("Concise summary of what the attachment shows or contains"),
8680
+ extractedFacts: import_zod39.z.array(import_zod39.z.string()).describe("Specific observable or document facts grounded in the attachment"),
8681
+ recommendedFocus: import_zod39.z.array(import_zod39.z.string()).describe("Important details to incorporate when answering follow-up questions"),
8682
+ confidence: import_zod39.z.number().min(0).max(1)
8683
+ });
8684
+ var RetrievalResultSchema = import_zod39.z.object({
8685
+ subQuestion: import_zod39.z.string(),
8686
+ evidence: import_zod39.z.array(EvidenceItemSchema)
8687
+ });
8688
+ var CitationSchema = import_zod39.z.object({
8689
+ index: import_zod39.z.number().describe("Citation number [1], [2], etc."),
8690
+ chunkId: import_zod39.z.string().describe("Source chunk ID, e.g. doc-123:coverage:2"),
8691
+ documentId: import_zod39.z.string(),
8692
+ documentType: import_zod39.z.enum(["policy", "quote"]).optional(),
8693
+ field: import_zod39.z.string().optional().describe("Specific field path, e.g. coverages[0].deductible"),
8694
+ quote: import_zod39.z.string().describe("Exact text from source that supports the claim"),
8695
+ relevance: import_zod39.z.number().min(0).max(1)
8696
+ });
8697
+ var SubAnswerSchema = import_zod39.z.object({
8698
+ subQuestion: import_zod39.z.string(),
8699
+ answer: import_zod39.z.string(),
8700
+ citations: import_zod39.z.array(CitationSchema),
8701
+ confidence: import_zod39.z.number().min(0).max(1),
8702
+ needsMoreContext: import_zod39.z.boolean().describe("True if evidence was insufficient to answer fully")
8703
+ });
8704
+ var VerifyResultSchema = import_zod39.z.object({
8705
+ approved: import_zod39.z.boolean().describe("Whether all sub-answers are adequately grounded"),
8706
+ issues: import_zod39.z.array(import_zod39.z.string()).describe("Specific grounding or consistency issues found"),
8707
+ retrySubQuestions: import_zod39.z.array(import_zod39.z.string()).optional().describe("Sub-questions that need additional retrieval or re-reasoning")
8708
+ });
8709
+ var QueryResultSchema = import_zod39.z.object({
8710
+ answer: import_zod39.z.string(),
8711
+ citations: import_zod39.z.array(CitationSchema),
8154
8712
  intent: QueryIntentSchema,
8155
- confidence: import_zod37.z.number().min(0).max(1),
8156
- followUp: import_zod37.z.string().optional().describe("Suggested follow-up question if applicable")
8713
+ confidence: import_zod39.z.number().min(0).max(1),
8714
+ followUp: import_zod39.z.string().optional().describe("Suggested follow-up question if applicable")
8157
8715
  });
8158
8716
 
8159
8717
  // src/query/retriever.ts
@@ -9159,6 +9717,7 @@ var AGENT_TOOLS = [
9159
9717
  CoverageSchema,
9160
9718
  CoverageTriggerSchema,
9161
9719
  CoverageValueTypeSchema,
9720
+ CoveredReasonSchema,
9162
9721
  CrimeDeclarationsSchema,
9163
9722
  CyberDeclarationsSchema,
9164
9723
  DEDUCTIBLE_TYPES,
@@ -9171,6 +9730,7 @@ var AGENT_TOOLS = [
9171
9730
  DeductibleScheduleSchema,
9172
9731
  DeductibleTypeSchema,
9173
9732
  DefenseCostTreatmentSchema,
9733
+ DefinitionSchema,
9174
9734
  DocumentTypeSchema,
9175
9735
  DriverRecordSchema,
9176
9736
  DwellingDetailsSchema,