@claritylabs/cl-sdk 4.1.0 → 4.3.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.mjs CHANGED
@@ -1060,7 +1060,8 @@ var InsurerInfoSchema = z9.object({
1060
1060
  amBestRating: z9.string().optional(),
1061
1061
  amBestNumber: z9.string().optional(),
1062
1062
  admittedStatus: AdmittedStatusSchema.optional(),
1063
- stateOfDomicile: z9.string().optional()
1063
+ stateOfDomicile: z9.string().optional(),
1064
+ address: AddressSchema.optional()
1064
1065
  }).merge(SourceProvenanceSchema);
1065
1066
  var ProducerInfoSchema = z9.object({
1066
1067
  agencyName: z9.string(),
@@ -2416,6 +2417,7 @@ var OperationalCoverageTermSchema = z21.object({
2416
2417
  });
2417
2418
  var OperationalCoverageLineSchema = z21.object({
2418
2419
  name: z21.string(),
2420
+ lineOfBusiness: AcordLobCodeSchema.optional(),
2419
2421
  coverageCode: z21.string().optional(),
2420
2422
  limit: z21.string().optional(),
2421
2423
  deductible: z21.string().optional(),
@@ -2431,6 +2433,7 @@ var OperationalCoverageLineSchema = z21.object({
2431
2433
  var OperationalPartySchema = z21.object({
2432
2434
  role: z21.string(),
2433
2435
  name: z21.string(),
2436
+ address: OperationalAddressSchema.optional(),
2434
2437
  sourceNodeIds: z21.array(z21.string().min(1)).default([]),
2435
2438
  sourceSpanIds: z21.array(z21.string().min(1)).default([])
2436
2439
  });
@@ -2468,6 +2471,7 @@ var PolicyOperationalProfileSchema = z21.preprocess(
2468
2471
  expirationDate: SourceBackedValueSchema.optional(),
2469
2472
  retroactiveDate: SourceBackedValueSchema.optional(),
2470
2473
  premium: SourceBackedValueSchema.optional(),
2474
+ operationsDescription: SourceBackedValueSchema.optional(),
2471
2475
  declarationFacts: z21.array(OperationalDeclarationFactSchema).default([]),
2472
2476
  coverages: z21.array(OperationalCoverageLineSchema).default([]),
2473
2477
  parties: z21.array(OperationalPartySchema).default([]),
@@ -2525,6 +2529,9 @@ function normalizeWhitespace(value) {
2525
2529
  function hasSpecificLineOfBusiness(codes) {
2526
2530
  return codes.some((code) => code !== "UN");
2527
2531
  }
2532
+ function specificLineOfBusinessCodes(codes) {
2533
+ return Array.from(new Set(codes.filter((code) => code !== "UN")));
2534
+ }
2528
2535
  function linesOfBusinessFromText(value) {
2529
2536
  const text = normalizeWhitespace(value ?? "");
2530
2537
  if (!text) return [];
@@ -2533,20 +2540,53 @@ function linesOfBusinessFromText(value) {
2533
2540
  const inferred = LOB_TEXT_PATTERNS.flatMap(({ codes, pattern }) => pattern.test(text) ? codes : []);
2534
2541
  return Array.from(new Set(inferred));
2535
2542
  }
2543
+ function coverageLineOfBusinessCandidates(coverage) {
2544
+ const limits = coverage.limits ?? [];
2545
+ const text = [
2546
+ coverage.coverageCode,
2547
+ coverage.formNumber,
2548
+ coverage.sectionRef,
2549
+ coverage.name,
2550
+ ...limits.map((term) => term.appliesTo)
2551
+ ].filter((value) => typeof value === "string" && value.trim().length > 0);
2552
+ const inferred = [];
2553
+ for (const value of text) {
2554
+ for (const code of linesOfBusinessFromText(value)) {
2555
+ if (code !== "UN" && !inferred.includes(code)) inferred.push(code);
2556
+ }
2557
+ }
2558
+ return inferred;
2559
+ }
2560
+ function explicitCoverageLineOfBusiness(coverage) {
2561
+ if (!coverage.lineOfBusiness) return void 0;
2562
+ const [code] = normalizeOperationalLinesOfBusiness([coverage.lineOfBusiness]);
2563
+ return code && code !== "UN" ? code : void 0;
2564
+ }
2565
+ function inferLineOfBusinessForOperationalCoverage(coverage, profileLinesOfBusiness) {
2566
+ const explicit = explicitCoverageLineOfBusiness(coverage);
2567
+ if (explicit) return explicit;
2568
+ const inferred = coverageLineOfBusinessCandidates(coverage);
2569
+ if (inferred.length === 1) return inferred[0];
2570
+ if (inferred.length > 1) return void 0;
2571
+ const fallback = specificLineOfBusinessCodes(normalizeOperationalLinesOfBusiness(profileLinesOfBusiness));
2572
+ return fallback.length === 1 ? fallback[0] : void 0;
2573
+ }
2574
+ function annotateOperationalCoverageLinesOfBusiness(coverages, profileLinesOfBusiness) {
2575
+ return coverages.map((coverage) => {
2576
+ const lineOfBusiness = inferLineOfBusinessForOperationalCoverage(coverage, profileLinesOfBusiness);
2577
+ if (lineOfBusiness) return { ...coverage, lineOfBusiness };
2578
+ const next = { ...coverage };
2579
+ delete next.lineOfBusiness;
2580
+ return next;
2581
+ });
2582
+ }
2536
2583
  function inferLinesOfBusinessFromOperationalCoverages(coverages) {
2537
2584
  const inferred = [];
2538
2585
  for (const coverage of coverages) {
2539
- const limits = coverage.limits ?? [];
2540
- const text = [
2541
- coverage.coverageCode,
2542
- coverage.formNumber,
2543
- coverage.name,
2544
- ...limits.flatMap((term) => [term.appliesTo, term.label])
2545
- ].filter((value) => typeof value === "string" && value.trim().length > 0);
2546
- for (const value of text) {
2547
- for (const code of linesOfBusinessFromText(value)) {
2548
- if (!inferred.includes(code)) inferred.push(code);
2549
- }
2586
+ const explicit = explicitCoverageLineOfBusiness(coverage);
2587
+ if (explicit && !inferred.includes(explicit)) inferred.push(explicit);
2588
+ for (const code of coverageLineOfBusinessCandidates(coverage)) {
2589
+ if (!inferred.includes(code)) inferred.push(code);
2550
2590
  }
2551
2591
  }
2552
2592
  return inferred.slice(0, 6);
@@ -3802,9 +3842,42 @@ function cleanValue(value) {
3802
3842
  if (!value) return void 0;
3803
3843
  return normalizeWhitespace4(value.replace(/^[\s:;#-]+|[\s;,.]+$/g, ""));
3804
3844
  }
3845
+ function cleanCoverageLineOfBusiness(value) {
3846
+ if (typeof value !== "string" || !value.trim()) return void 0;
3847
+ const [code] = normalizeOperationalLinesOfBusiness([value]);
3848
+ return code && code !== "UN" ? code : void 0;
3849
+ }
3805
3850
  function normalizedFactValue(value) {
3806
3851
  return value.toLowerCase().replace(/&/g, " and ").replace(/[.,#]/g, " ").replace(/\s+/g, " ").trim();
3807
3852
  }
3853
+ var OPERATIONAL_ADDRESS_FIELDS = [
3854
+ "street1",
3855
+ "street2",
3856
+ "city",
3857
+ "state",
3858
+ "zip",
3859
+ "country",
3860
+ "formatted"
3861
+ ];
3862
+ function normalizeOperationalAddress(value) {
3863
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
3864
+ const record = value;
3865
+ const address = Object.fromEntries(
3866
+ OPERATIONAL_ADDRESS_FIELDS.flatMap((field) => {
3867
+ const cleaned = typeof record[field] === "string" ? cleanValue(record[field]) : void 0;
3868
+ return cleaned ? [[field, cleaned]] : [];
3869
+ })
3870
+ );
3871
+ return Object.keys(address).length > 0 ? address : void 0;
3872
+ }
3873
+ function normalizeOperationalPartyRole(value) {
3874
+ const normalized = value.toLowerCase().replace(/[\s-]+/g, "_");
3875
+ if (normalized === "namedinsured" || normalized === "insured") return "named_insured";
3876
+ if (normalized === "managing_general_agent") return "mga";
3877
+ if (normalized === "managing_general_underwriter") return "mga";
3878
+ if (normalized === "third_party_administrator") return "administrator";
3879
+ return normalized;
3880
+ }
3808
3881
  var OPERATIONAL_COVERAGE_TERM_KINDS = /* @__PURE__ */ new Set([
3809
3882
  "each_claim_limit",
3810
3883
  "each_occurrence_limit",
@@ -3903,6 +3976,7 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3903
3976
  const expirationDate = mergeValue(base.expirationDate, candidate.expirationDate);
3904
3977
  const retroactiveDate = mergeValue(base.retroactiveDate, candidate.retroactiveDate);
3905
3978
  const premium = mergeValue(base.premium, candidate.premium);
3979
+ const operationsDescription = mergeValue(base.operationsDescription, candidate.operationsDescription);
3906
3980
  const candidateDeclarationFacts = Array.isArray(candidate.declarationFacts) ? candidate.declarationFacts.map(mergeDeclarationFact).filter((fact) => Boolean(fact)) : [];
3907
3981
  const declarationFacts = [
3908
3982
  ...base.declarationFacts,
@@ -3927,7 +4001,8 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3927
4001
  effectiveDate,
3928
4002
  expirationDate,
3929
4003
  retroactiveDate,
3930
- premium
4004
+ premium,
4005
+ operationsDescription
3931
4006
  ].filter((value) => Boolean(value));
3932
4007
  const coverages = base.coverages.length > 0 ? base.coverages : Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => {
3933
4008
  const record = coverage;
@@ -3961,6 +4036,7 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3961
4036
  if (!name || sourceNodeIds2.length === 0 && sourceSpanIds2.length === 0) return void 0;
3962
4037
  return {
3963
4038
  name,
4039
+ lineOfBusiness: cleanCoverageLineOfBusiness(record.lineOfBusiness),
3964
4040
  coverageCode: typeof record.coverageCode === "string" ? cleanValue(record.coverageCode) : void 0,
3965
4041
  limit: typeof record.limit === "string" ? cleanValue(record.limit) : void 0,
3966
4042
  deductible: typeof record.deductible === "string" ? cleanValue(record.deductible) : void 0,
@@ -3985,14 +4061,21 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3985
4061
  const record = party;
3986
4062
  const role = typeof record.role === "string" ? cleanValue(record.role) : void 0;
3987
4063
  const name = typeof record.name === "string" ? cleanValue(record.name) : void 0;
4064
+ const address = normalizeOperationalAddress(record.address);
3988
4065
  const sourceNodeIds2 = keepIds(record.sourceNodeIds, validNodeIds);
3989
4066
  const sourceSpanIds2 = keepIds(record.sourceSpanIds, validSpanIds);
3990
4067
  if (!role || !name || sourceNodeIds2.length === 0 && sourceSpanIds2.length === 0) return [];
3991
- return [{ role, name, sourceNodeIds: sourceNodeIds2, sourceSpanIds: sourceSpanIds2 }];
4068
+ return [{
4069
+ role: normalizeOperationalPartyRole(role),
4070
+ name,
4071
+ address,
4072
+ sourceNodeIds: sourceNodeIds2,
4073
+ sourceSpanIds: sourceSpanIds2
4074
+ }];
3992
4075
  }) : [];
3993
4076
  const parties = [
3994
- ...base.parties,
3995
4077
  ...candidateParties,
4078
+ ...base.parties,
3996
4079
  sourceBackedParty("named_insured", namedInsured),
3997
4080
  sourceBackedParty("insurer", insurer),
3998
4081
  sourceBackedParty("broker", broker)
@@ -4050,6 +4133,10 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
4050
4133
  existingLinesOfBusiness: baseLinesOfBusiness,
4051
4134
  coverages
4052
4135
  });
4136
+ const annotatedCoverages = annotateOperationalCoverageLinesOfBusiness(
4137
+ coverages,
4138
+ resolvedLinesOfBusiness.linesOfBusiness
4139
+ );
4053
4140
  return PolicyOperationalProfileSchema.parse({
4054
4141
  ...base,
4055
4142
  documentType: candidate.documentType === "policy" ? "policy" : base.documentType,
@@ -4062,8 +4149,9 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
4062
4149
  expirationDate,
4063
4150
  retroactiveDate,
4064
4151
  premium,
4152
+ operationsDescription,
4065
4153
  declarationFacts,
4066
- coverages,
4154
+ coverages: annotatedCoverages,
4067
4155
  parties,
4068
4156
  endorsementSupport,
4069
4157
  sourceNodeIds,
@@ -4093,6 +4181,7 @@ var OperationalProfileCleanupSchema = z22.object({
4093
4181
  action: z22.enum(["keep", "drop", "update"]),
4094
4182
  reason: z22.string().optional(),
4095
4183
  name: z22.string().optional(),
4184
+ lineOfBusiness: z22.string().nullable().optional(),
4096
4185
  limit: z22.string().nullable().optional(),
4097
4186
  deductible: z22.string().nullable().optional(),
4098
4187
  premium: z22.string().nullable().optional(),
@@ -4137,6 +4226,7 @@ function compactCoverageForCleanup(coverage, coverageIndex) {
4137
4226
  return {
4138
4227
  coverageIndex,
4139
4228
  name: coverage.name,
4229
+ lineOfBusiness: coverage.lineOfBusiness,
4140
4230
  limit: coverage.limit,
4141
4231
  deductible: coverage.deductible,
4142
4232
  premium: coverage.premium,
@@ -4166,6 +4256,7 @@ function nodeTextForSelection(node) {
4166
4256
  function coverageTextForSelection(coverage) {
4167
4257
  return [
4168
4258
  coverage.name,
4259
+ coverage.lineOfBusiness,
4169
4260
  coverage.coverageCode,
4170
4261
  coverage.limit,
4171
4262
  coverage.deductible,
@@ -4459,6 +4550,15 @@ function applyCoverageCleanupDecision(coverage, decision, validNodeIds, validSpa
4459
4550
  };
4460
4551
  const name = cleanProfileValue(decision.name);
4461
4552
  if (name) next.name = name;
4553
+ if (decision.lineOfBusiness != null) {
4554
+ const value = cleanProfileValue(decision.lineOfBusiness);
4555
+ if (value) {
4556
+ const parsed = AcordLobCodeSchema.safeParse(value);
4557
+ if (parsed.success && parsed.data !== "UN") next.lineOfBusiness = parsed.data;
4558
+ } else {
4559
+ delete next.lineOfBusiness;
4560
+ }
4561
+ }
4462
4562
  if (decision.limit != null) {
4463
4563
  const value = cleanProfileValue(decision.limit);
4464
4564
  if (value) next.limit = value;
@@ -4523,7 +4623,8 @@ function sourceIdsFromOperationalProfile(profile) {
4523
4623
  profile.effectiveDate,
4524
4624
  profile.expirationDate,
4525
4625
  profile.retroactiveDate,
4526
- profile.premium
4626
+ profile.premium,
4627
+ profile.operationsDescription
4527
4628
  ].filter(Boolean);
4528
4629
  return {
4529
4630
  sourceNodeIds: uniqueStrings([
@@ -4607,6 +4708,21 @@ var OperationalDeclarationFactForPromptSchema = z23.object({
4607
4708
  sourceNodeIds: z23.array(z23.string()),
4608
4709
  sourceSpanIds: z23.array(z23.string())
4609
4710
  });
4711
+ var OperationalPartyForPromptSchema = z23.object({
4712
+ role: z23.enum([
4713
+ "named_insured",
4714
+ "producer",
4715
+ "broker",
4716
+ "insurer",
4717
+ "carrier",
4718
+ "mga",
4719
+ "administrator"
4720
+ ]),
4721
+ name: z23.string(),
4722
+ address: OperationalAddressForPromptSchema.optional(),
4723
+ sourceNodeIds: z23.array(z23.string()),
4724
+ sourceSpanIds: z23.array(z23.string())
4725
+ });
4610
4726
  var OperationalProfilePromptSchema = z23.object({
4611
4727
  documentType: z23.enum(["policy", "quote"]).optional(),
4612
4728
  linesOfBusiness: z23.array(z23.string()).optional(),
@@ -4618,9 +4734,12 @@ var OperationalProfilePromptSchema = z23.object({
4618
4734
  expirationDate: SourceBackedValueForPromptSchema.optional(),
4619
4735
  retroactiveDate: SourceBackedValueForPromptSchema.optional(),
4620
4736
  premium: SourceBackedValueForPromptSchema.optional(),
4737
+ operationsDescription: SourceBackedValueForPromptSchema.optional(),
4621
4738
  declarationFacts: z23.array(OperationalDeclarationFactForPromptSchema).optional(),
4739
+ parties: z23.array(OperationalPartyForPromptSchema).optional(),
4622
4740
  coverages: z23.array(z23.object({
4623
4741
  name: z23.string(),
4742
+ lineOfBusiness: z23.string().optional(),
4624
4743
  coverageCode: z23.string().optional(),
4625
4744
  limit: z23.string().optional(),
4626
4745
  deductible: z23.string().optional(),
@@ -5529,6 +5648,9 @@ function operationalEvidenceScore(span) {
5529
5648
  if (span.metadata?.elementType === "title") score += 4;
5530
5649
  if (span.sourceUnit === "page") score -= 3;
5531
5650
  if (/\b(policy\s*(number|period|term)|effective date|expiration date|expiry date|named insured|insurer|carrier|security|broker|producer|premium|total due)\b/i.test(text)) score += 12;
5651
+ if (/\b(mailing address|business address|address|managing general (?:agent|underwriter)|mga|administrator|description of operations|operations description|nature of business|business description)\b/i.test(text)) score += 12;
5652
+ if (/\b\d{1,6}\s+[A-Z0-9][^\n,]{1,80}\b(?:street|st|avenue|ave|road|rd|boulevard|blvd|drive|dr|lane|ln|way|court|ct|highway|hwy)\b/i.test(text)) score += 10;
5653
+ if (/\b[A-Za-z][A-Za-z .'-]+,\s*[A-Z]{2}\s+\d{5}(?:-\d{4})?\b/.test(text)) score += 10;
5532
5654
  if (/\b(coverage part|limit(?:s)? of liability|deductible|retention|retroactive date|aggregate|sublimit|sub-limit|each claim|each loss|each occurrence|coinsurance)\b/i.test(text)) score += 14;
5533
5655
  if (/\bendorsement\s+(?:no\.?|number|#)?\s*[A-Z0-9]|forms? and endorsements?|attached at inception|schedule\b/i.test(text)) score += 8;
5534
5656
  if (/\bitem\s+\d+\.?\s*(?:named insured|policy number|policy period|renewal|form of business|coverage parts?|premium|extended reporting|producer|forms? and endorsements?)\b/i.test(text)) score += 10;
@@ -5548,10 +5670,13 @@ function isOperationalEvidenceAnchor(span) {
5548
5670
  const text = cleanText([span.text, span.formNumber].filter(Boolean).join(" "), "");
5549
5671
  if (!text) return false;
5550
5672
  if (sourceUnit3 === "page") {
5551
- return hasSubstantiveDeclarationsScheduleText(text) || /\b(declarations?|named insured|policy number|policy period|effective date|expiration date|premium|total due|producer)\b/i.test(text);
5673
+ return hasSubstantiveDeclarationsScheduleText(text) || /\b(declarations?|named insured|policy number|policy period|effective date|expiration date|premium|total due|producer|mailing address|mga|administrator|description of operations|nature of business|business description)\b/i.test(text);
5552
5674
  }
5553
5675
  if (/\bitem\s+\d+\.?\s*(?:named insured|policy number|policy period|renewal|form of business|coverage parts?|premium|extended reporting|producer|forms? and endorsements?)\b/i.test(text)) return true;
5554
5676
  if (/\b(policy\s*(number|period)|effective date|expiration date|expiry date|named insured|insurer|carrier|broker|producer|premium|total due)\b/i.test(text)) return true;
5677
+ if (/\b(mailing address|business address|address|managing general (?:agent|underwriter)|mga|administrator|description of operations|operations description|nature of business|business description)\b/i.test(text)) return true;
5678
+ if (/\b\d{1,6}\s+[A-Z0-9][^\n,]{1,80}\b(?:street|st|avenue|ave|road|rd|boulevard|blvd|drive|dr|lane|ln|way|court|ct|highway|hwy)\b/i.test(text)) return true;
5679
+ if (/\b[A-Za-z][A-Za-z .'-]+,\s*[A-Z]{2}\s+\d{5}(?:-\d{4})?\b/.test(text)) return true;
5555
5680
  if (/\b(coverage part|forms? and endorsements?|attached at inception|endorsement\s+(?:no\.?|number|#)?\s*[A-Z0-9])\b/i.test(text)) return true;
5556
5681
  if (/\$[\d,.]+|[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{2,4}|[0-9]{1,2}\s+[A-Za-z]{3,9}\s+[0-9]{4}/.test(text)) return true;
5557
5682
  return false;
@@ -5569,6 +5694,7 @@ function operationalEvidencePages(sourceSpans) {
5569
5694
  if (/\bcoverage parts?,?\s+limits? of liability,?\s+deductibles?,?\s+and retroactive dates\b/i.test(text)) score += 24;
5570
5695
  if (/\b(policy\s*(number|period|term)|effective date|expiration date|expiry date|named insured|insurer|carrier|security)\b/i.test(text)) score += 12;
5571
5696
  if (/\b(premium|total due|tax|fee|producer|broker)\b/i.test(text)) score += 10;
5697
+ if (/\b(mailing address|business address|managing general (?:agent|underwriter)|mga|administrator|description of operations|operations description|nature of business|business description)\b/i.test(text)) score += 16;
5572
5698
  if (/\b(endorsement\s+(?:no\.?|number|#)?\s*[A-Z0-9]|attached at inception|forms? and endorsements?)\b/i.test(text)) score += 8;
5573
5699
  if (/\b(definitions?|exclusions?|conditions?|duties in the event|action against|cancellation by)\b/i.test(text)) score -= 12;
5574
5700
  if (score > 0) scores.set(page, (scores.get(page) ?? 0) + score);
@@ -5643,7 +5769,7 @@ function operationalProfilePromptNodes(sourceTree) {
5643
5769
  return true;
5644
5770
  }
5645
5771
  const text = [node.title, node.path, node.description, node.textExcerpt].filter(Boolean).join(" ");
5646
- return /\b(policy\s*(number|period)|named insured|insurer|carrier|broker|producer|premium|coverage|limit|liability|deductible|retention|retroactive|aggregate|sublimit|sub-limit|endorsement)\b/i.test(text);
5772
+ return /\b(policy\s*(number|period)|named insured|insurer|carrier|broker|producer|managing general (?:agent|underwriter)|mga|administrator|mailing address|description of operations|operations description|nature of business|business description|premium|coverage|limit|liability|deductible|retention|retroactive|aggregate|sublimit|sub-limit|endorsement)\b/i.test(text);
5647
5773
  }).slice(0, 420);
5648
5774
  }
5649
5775
  function emptyOperationalProfile() {
@@ -5667,10 +5793,12 @@ function buildOperationalProfilePrompt(sourceTree, sourceSpans) {
5667
5793
  return `Extract a source-backed operational profile for an insurance policy.
5668
5794
 
5669
5795
  Return only high-value operational facts needed for policy lists, Q&A, compliance, and certificate generation:
5670
- - policy number, named insured, insurer/carrier/security, broker/producer, policy period, retroactive date, premium
5796
+ - policy number, named insured, insurer/carrier/security, broker/producer, policy period, retroactive date, premium, and the insured's description of operations
5797
+ - parties[] rows for named insured, producer/broker, insurer/carrier, and MGA/administrator identities and their mailing addresses
5671
5798
  - source-backed declarationFacts for named-insured identity details: named insured, mailing address, DBA, entity type, tax ID/FEIN, additional named insureds, and other durable declaration-page identity facts
5672
5799
  - coverage units with their own nested limit terms, deductibles/retentions, retroactive dates, premiums, and form references
5673
5800
  - coverage type labels
5801
+ - coverage lineOfBusiness ACORD codes when a coverage unit can be assigned to one specific line
5674
5802
 
5675
5803
  Rules:
5676
5804
  - Every returned value must include sourceNodeIds or sourceSpanIds from the provided evidence.
@@ -5678,12 +5806,17 @@ Rules:
5678
5806
  - If a value is not directly supported, omit it.
5679
5807
  - Prefer declarations, schedules, premium tables, and endorsement schedules over generic policy wording.
5680
5808
  - Put named-insured mailing address in declarationFacts[] with field "mailingAddress", valueKind "address", a user-facing value string, and structured address fields when present. Do not put producer, broker, insurer, mortgagee, loss-payee, or certificate-holder addresses in mailingAddress.
5809
+ - Put every source-backed policy party in parties[] using only these canonical roles: "named_insured", "producer", "broker", "insurer", "carrier", "mga", or "administrator". Keep producer/broker, insurer/carrier, and MGA/administrator addresses policy-scoped in parties[]; never represent them as the named-insured mailingAddress declaration fact.
5810
+ - When a party's address is present, return its available street1, street2, city, state, zip, country, and formatted parts under parties[].address. Partial addresses are allowed in parties[], but never guess a missing component. The party row must cite the source node or source span that supports both the identity and address.
5811
+ - Put the insured's directly stated business or operations description in operationsDescription. Do not synthesize it from coverages, industry inference, website research, or generic policy wording.
5681
5812
  - Put DBA or trade name in declarationFacts[] with field "dba"; entity/legal form in field "entityType"; FEIN/tax ID in field "taxId"; each additional named insured in field "additionalNamedInsured".
5682
5813
  - For effective, expiration, retroactive, and other date fields, return a normalized YYYY-MM-DD value when the source date is unambiguous, including month-name dates such as "20 Feb 2026". Do not emit fragmented date text such as "20 2 2026".
5683
5814
  - For broker/producer, extract the agency or company legal name, not the license role, credential, or type. In a block like "Bayshore Insurance Brokers, LLC" followed by "Surplus Lines Broker - CA License No. ...", broker.value must be "Bayshore Insurance Brokers, LLC"; the surplus-lines role and license number are not the broker name.
5684
5815
  - On declarations pages, treat "Item N" labels as section boundaries. Use Item 6 or equivalent coverage-schedule rows for coverage limits, deductibles, aggregate terms, and retroactive dates; do not merge Item 7 premium, Item 8 ERP, Item 9 producer, or Item 10 forms into Item 6 coverage facts.
5685
5816
  - Premium, tax, fee, payment-plan, rating, exposure, and reporting-value schedules are billing evidence, not coverage schedules. Extract the total policy premium into premium when supported, but do not create coverages[] entries from premium-only or fee-only rows, and never use Total Premium, MGA Fee, tax, stamping fee, reporting values, or exposure annual rate as a coverage limit.
5686
5817
  - A coverage schedule row's coverage name should come from the "Coverage Part" or equivalent row label. Limit, deductible, aggregate, sublimit, retention, and retroactive-date values belong as nested terms under that coverage, not in the coverage title.
5818
+ - Put the ACORD line of business code for each coverage unit in coverages[].lineOfBusiness only when the row belongs to one specific line, such as CGL, AUTOB, WORK, UMBRC, EXLIA, EO, OLIB, EPLI, DO, FIDUC, CRIME, INMRC, COMAR, PROPC, PROP, BOP, HOME, DFIRE, FLOOD, or GARAG. Do not use limit labels such as Each Occurrence, Aggregate, Products-Completed Operations Aggregate, deductible, retention, retroactive date, or sublimit as lines of business.
5819
+ - If a package or multi-line row cannot be assigned to exactly one ACORD line, omit coverages[].lineOfBusiness for that coverage.
5687
5820
  - If a coverage schedule continues onto the next page before the next item marker, include the continuation rows in the same coverage or declaration item.
5688
5821
  - If one schedule row or continuation row states the same amount with multiple bases, such as "$1,000,000 Each Claim / Aggregate", return separate limit terms for each basis using the same value instead of one combined "Each Claim / Aggregate" term.
5689
5822
  - LiteParse text can fragment visual table cells into adjacent lines. Before extracting coverage terms, mentally join adjacent lines in the same declaration item or schedule row. For example, "$2,000,000 Policy Each Claim" followed immediately by "Aggregate" means "$2,000,000 Policy Aggregate"; a line ending with "/" followed by "Aggregate ..." means the limit cell continues, not a new coverage.
@@ -5745,13 +5878,6 @@ function valueOf(profile, key) {
5745
5878
  }
5746
5879
  return String(value.value);
5747
5880
  }
5748
- function provenanceOf(value) {
5749
- if (!value?.sourceSpanIds.length) return void 0;
5750
- return {
5751
- sourceSpanIds: value.sourceSpanIds,
5752
- ...value.sourceNodeIds[0] ? { documentNodeId: value.sourceNodeIds[0] } : {}
5753
- };
5754
- }
5755
5881
  function provenanceFromIds(sourceSpanIds, sourceNodeIds) {
5756
5882
  if (sourceSpanIds.length === 0) return void 0;
5757
5883
  return {
@@ -5759,6 +5885,33 @@ function provenanceFromIds(sourceSpanIds, sourceNodeIds) {
5759
5885
  ...sourceNodeIds[0] ? { documentNodeId: sourceNodeIds[0] } : {}
5760
5886
  };
5761
5887
  }
5888
+ function combinedProvenance(...values) {
5889
+ const sourceSpanIds = [...new Set(values.flatMap((value) => value?.sourceSpanIds ?? []))];
5890
+ const sourceNodeIds = [...new Set(values.flatMap((value) => value?.sourceNodeIds ?? []))];
5891
+ return provenanceFromIds(sourceSpanIds, sourceNodeIds);
5892
+ }
5893
+ function firstOperationalParty(profile, roles) {
5894
+ const candidates = roles.flatMap(
5895
+ (role) => profile.parties.filter((candidate) => candidate.role === role && candidate.name.trim())
5896
+ );
5897
+ return candidates.find((candidate) => candidate.address) ?? candidates[0];
5898
+ }
5899
+ function completeOperationalAddress(address) {
5900
+ if (!address?.street1 || !address.city || !address.state || !address.zip) return void 0;
5901
+ return {
5902
+ street1: address.street1,
5903
+ street2: address.street2,
5904
+ city: address.city,
5905
+ state: address.state,
5906
+ zip: address.zip,
5907
+ country: address.country
5908
+ };
5909
+ }
5910
+ function sourceBackedAddressFromParty(party) {
5911
+ const address = completeOperationalAddress(party?.address);
5912
+ const provenance = party ? provenanceFromIds(party.sourceSpanIds, party.sourceNodeIds) : void 0;
5913
+ return address && provenance ? { ...address, ...provenance } : void 0;
5914
+ }
5762
5915
  function declarationFactsByField(profile, field) {
5763
5916
  return profile.declarationFacts.filter((fact) => fact.field === field && fact.value.trim());
5764
5917
  }
@@ -5809,16 +5962,21 @@ function declarationFieldName(fact) {
5809
5962
  function materializeDocument(params) {
5810
5963
  const profile = params.operationalProfile;
5811
5964
  const policyNumber = valueOf(profile, "policyNumber") ?? "Unknown";
5812
- const insuredName = valueOf(profile, "namedInsured") ?? "Unknown";
5813
- const carrier = valueOf(profile, "insurer") ?? "Unknown";
5965
+ const namedInsuredParty = firstOperationalParty(profile, ["named_insured"]);
5966
+ const insurerParty = firstOperationalParty(profile, ["insurer", "carrier"]);
5967
+ const producerParty = firstOperationalParty(profile, ["producer", "broker"]);
5968
+ const insuredName = valueOf(profile, "namedInsured") ?? namedInsuredParty?.name ?? "Unknown";
5969
+ const carrier = valueOf(profile, "insurer") ?? insurerParty?.name ?? "Unknown";
5814
5970
  const effectiveDate = valueOf(profile, "effectiveDate") ?? "Unknown";
5815
5971
  const expirationDate = valueOf(profile, "expirationDate") ?? "Unknown";
5816
5972
  const premium = valueOf(profile, "premium");
5817
- const insurerProvenance = provenanceOf(profile.insurer);
5818
- const broker = valueOf(profile, "broker");
5819
- const brokerProvenance = provenanceOf(profile.broker);
5973
+ const insurerProvenance = combinedProvenance(profile.insurer, insurerParty);
5974
+ const insurerAddress = completeOperationalAddress(insurerParty?.address);
5975
+ const broker = valueOf(profile, "broker") ?? producerParty?.name;
5976
+ const brokerProvenance = combinedProvenance(profile.broker, producerParty);
5977
+ const producerAddress = completeOperationalAddress(producerParty?.address);
5820
5978
  const mailingAddressFact = firstDeclarationFact(profile, "mailingAddress");
5821
- const insuredAddress = sourceBackedAddressFromFact(mailingAddressFact);
5979
+ const insuredAddress = sourceBackedAddressFromParty(namedInsuredParty) ?? sourceBackedAddressFromFact(mailingAddressFact);
5822
5980
  const insuredDba = firstDeclarationFact(profile, "dba")?.value;
5823
5981
  const insuredEntityType = normalizedEntityType(firstDeclarationFact(profile, "entityType")?.value);
5824
5982
  const insuredFein = firstDeclarationFact(profile, "taxId")?.value;
@@ -5828,6 +5986,7 @@ function materializeDocument(params) {
5828
5986
  });
5829
5987
  const coverages = profile.coverages.map((coverage) => ({
5830
5988
  name: coverage.name,
5989
+ lineOfBusiness: coverage.lineOfBusiness,
5831
5990
  coverageCode: coverage.coverageCode,
5832
5991
  limit: coverage.limit,
5833
5992
  deductible: coverage.deductible,
@@ -5881,10 +6040,20 @@ function materializeDocument(params) {
5881
6040
  insuredEntityType,
5882
6041
  insuredFein,
5883
6042
  ...additionalNamedInsureds.length > 0 ? { additionalNamedInsureds } : {},
5884
- ...insurerProvenance ? { insurer: { legalName: carrier, ...insurerProvenance } } : {},
6043
+ ...insurerProvenance ? {
6044
+ insurer: {
6045
+ legalName: carrier,
6046
+ ...insurerAddress ? { address: insurerAddress } : {},
6047
+ ...insurerProvenance
6048
+ }
6049
+ } : {},
5885
6050
  ...broker && brokerProvenance ? {
5886
6051
  brokerAgency: broker,
5887
- producer: { agencyName: broker, ...brokerProvenance }
6052
+ producer: {
6053
+ agencyName: broker,
6054
+ ...producerAddress ? { address: producerAddress } : {},
6055
+ ...brokerProvenance
6056
+ }
5888
6057
  } : {},
5889
6058
  linesOfBusiness: profile.linesOfBusiness,
5890
6059
  formInventory: params.formInventory.filter((form) => typeof form.formNumber === "string" && form.formNumber.trim().length > 0).map((form) => ({
@@ -13338,6 +13507,7 @@ export {
13338
13507
  VerifyResultSchema,
13339
13508
  WatercraftDeclarationsSchema,
13340
13509
  WorkersCompDeclarationsSchema,
13510
+ annotateOperationalCoverageLinesOfBusiness,
13341
13511
  applyApplicationAnswers,
13342
13512
  buildAcroFormMappingPrompt,
13343
13513
  buildAgentSystemPrompt,
@@ -13404,6 +13574,7 @@ export {
13404
13574
  getNextApplicationQuestions,
13405
13575
  getPdfPageCount,
13406
13576
  getTemplate,
13577
+ inferLineOfBusinessForOperationalCoverage,
13407
13578
  inferLinesOfBusinessFromOperationalCoverages,
13408
13579
  isDoclingExtractionInput,
13409
13580
  isFileReference,