@claritylabs/cl-sdk 3.0.21 → 3.0.23

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
@@ -2045,14 +2045,38 @@ var SourceBackedValueSchema = z20.object({
2045
2045
  sourceNodeIds: z20.array(z20.string().min(1)).default([]),
2046
2046
  sourceSpanIds: z20.array(z20.string().min(1)).default([])
2047
2047
  });
2048
+ var OperationalCoverageTermSchema = z20.object({
2049
+ kind: z20.enum([
2050
+ "each_claim_limit",
2051
+ "each_occurrence_limit",
2052
+ "each_loss_limit",
2053
+ "aggregate_limit",
2054
+ "sublimit",
2055
+ "retention",
2056
+ "deductible",
2057
+ "retroactive_date",
2058
+ "premium",
2059
+ "other"
2060
+ ]).default("other"),
2061
+ label: z20.string(),
2062
+ value: z20.string(),
2063
+ amount: z20.number().optional(),
2064
+ appliesTo: z20.string().optional(),
2065
+ sourceNodeIds: z20.array(z20.string().min(1)).default([]),
2066
+ sourceSpanIds: z20.array(z20.string().min(1)).default([])
2067
+ });
2048
2068
  var OperationalCoverageLineSchema = z20.object({
2049
2069
  name: z20.string(),
2050
2070
  coverageCode: z20.string().optional(),
2051
2071
  limit: z20.string().optional(),
2052
2072
  deductible: z20.string().optional(),
2053
2073
  premium: z20.string().optional(),
2074
+ retroactiveDate: z20.string().optional(),
2054
2075
  formNumber: z20.string().optional(),
2055
2076
  sectionRef: z20.string().optional(),
2077
+ coverageOrigin: z20.enum(["core", "endorsement"]).optional(),
2078
+ endorsementNumber: z20.string().optional(),
2079
+ limits: z20.array(OperationalCoverageTermSchema).default([]),
2056
2080
  sourceNodeIds: z20.array(z20.string().min(1)).default([]),
2057
2081
  sourceSpanIds: z20.array(z20.string().min(1)).default([])
2058
2082
  });
@@ -2995,14 +3019,265 @@ function deductibleFromText(text) {
2995
3019
  function premiumFromText(text) {
2996
3020
  return moneyValue(text.match(/\b(?:premium|total premium|total cost|amount due)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?)/i)?.[1]);
2997
3021
  }
3022
+ function moneyAmount(value) {
3023
+ const match = value?.match(/\$?\s*([0-9][0-9,]*(?:\.\d+)?)/);
3024
+ if (!match) return void 0;
3025
+ const amount = Number(match[1].replace(/,/g, ""));
3026
+ return Number.isFinite(amount) ? amount : void 0;
3027
+ }
3028
+ function normalizeLabel(value) {
3029
+ return normalizeWhitespace3(value ?? "").toLowerCase();
3030
+ }
3031
+ var OPERATIONAL_COVERAGE_TERM_KINDS = /* @__PURE__ */ new Set([
3032
+ "each_claim_limit",
3033
+ "each_occurrence_limit",
3034
+ "each_loss_limit",
3035
+ "aggregate_limit",
3036
+ "sublimit",
3037
+ "retention",
3038
+ "deductible",
3039
+ "retroactive_date",
3040
+ "premium",
3041
+ "other"
3042
+ ]);
3043
+ function termKind(label, value) {
3044
+ const text = normalizeLabel(`${label} ${value}`);
3045
+ if (/\bretroactive\b/.test(text)) return "retroactive_date";
3046
+ if (/\b(self[-\s]?insured retention|retention|sir)\b/.test(text)) return "retention";
3047
+ if (/\bdeductible\b/.test(text)) return "deductible";
3048
+ if (/\bpremium\b/.test(text)) return "premium";
3049
+ if (/\bsub[-\s]?limit\b/.test(text)) return "sublimit";
3050
+ if (/\baggregate\b/.test(text)) return "aggregate_limit";
3051
+ if (/\beach\s+claim|per\s+claim\b/.test(text)) return "each_claim_limit";
3052
+ if (/\beach\s+occurrence|per\s+occurrence\b/.test(text)) return "each_occurrence_limit";
3053
+ if (/\beach\s+loss|per\s+loss\b/.test(text)) return "each_loss_limit";
3054
+ if (/\blimit\b/.test(text)) return "other";
3055
+ return "other";
3056
+ }
3057
+ function normalizeTermKind(value, label, termValue) {
3058
+ return typeof value === "string" && OPERATIONAL_COVERAGE_TERM_KINDS.has(value) ? value : termKind(label, termValue);
3059
+ }
3060
+ function isValueCell(label, value) {
3061
+ const normalizedLabel = normalizeLabel(label);
3062
+ const normalizedValue = normalizeLabel(value);
3063
+ if (!value || normalizedValue === "\u2014") return false;
3064
+ if (/\b(policy\s*(number|no|#)|named insured|insured|carrier|company|broker|producer|agent|coverage|coverage part|description|item|name|form|source)\b/.test(normalizedLabel)) {
3065
+ return false;
3066
+ }
3067
+ return /\b(limit|aggregate|retention|deductible|sir|retroactive|premium|amount)\b/.test(normalizedLabel) || moneyAmount(value) !== void 0 || /\b(full prior acts|none|included|not included|as stated)\b/.test(normalizedValue);
3068
+ }
3069
+ function isNameCell(label, value) {
3070
+ const normalizedLabel = normalizeLabel(label);
3071
+ const normalizedValue = normalizeLabel(value);
3072
+ if (!value || moneyAmount(value) !== void 0) return false;
3073
+ if (/\b(coverage|coverage part|insuring agreement|description|item|name)\b/.test(normalizedLabel)) {
3074
+ return true;
3075
+ }
3076
+ if (/^column\s+\d+$/.test(normalizedLabel) && /\b(coverage|sub[-\s]?limit|liability|expense|part\s+[a-z])\b/.test(normalizedValue)) {
3077
+ return true;
3078
+ }
3079
+ return false;
3080
+ }
3081
+ function childMap(nodes) {
3082
+ const children = /* @__PURE__ */ new Map();
3083
+ for (const node of nodes) {
3084
+ const group = children.get(node.parentId) ?? [];
3085
+ group.push(node);
3086
+ children.set(node.parentId, group);
3087
+ }
3088
+ for (const group of children.values()) group.sort((left, right) => left.order - right.order);
3089
+ return children;
3090
+ }
3091
+ function cellRows(row, children) {
3092
+ return (children.get(row.id) ?? []).filter((child) => child.kind === "table_cell").map((cell) => ({
3093
+ label: cleanValue(cell.title) ?? "Value",
3094
+ value: cleanValue(cell.textExcerpt ?? cell.description ?? cell.title) ?? "",
3095
+ node: cell
3096
+ })).filter((cell) => cell.value);
3097
+ }
3098
+ function directChildren(parent, children) {
3099
+ return children.get(parent.id) ?? [];
3100
+ }
3101
+ function descendants(parent, children) {
3102
+ const stack = [...directChildren(parent, children)];
3103
+ const result = [];
3104
+ while (stack.length > 0) {
3105
+ const node = stack.shift();
3106
+ result.push(node);
3107
+ stack.unshift(...directChildren(node, children));
3108
+ }
3109
+ return result;
3110
+ }
3111
+ function ancestry(node, byId) {
3112
+ const result = [];
3113
+ let current = node.parentId ? byId.get(node.parentId) : void 0;
3114
+ while (current) {
3115
+ result.push(current);
3116
+ current = current.parentId ? byId.get(current.parentId) : void 0;
3117
+ }
3118
+ return result;
3119
+ }
3120
+ function endorsementAncestor(node, byId) {
3121
+ return ancestry(node, byId).find((ancestor) => ancestor.kind === "endorsement");
3122
+ }
3123
+ function endorsementNumberFrom(value) {
3124
+ return cleanValue(value?.match(/\bendorsement\s+no\.?\s*([0-9A-Z-]+)/i)?.[1]);
3125
+ }
3126
+ function sourceIds(nodes) {
3127
+ return {
3128
+ sourceNodeIds: [...new Set(nodes.map((node) => node.id))],
3129
+ sourceSpanIds: [...new Set(nodes.flatMap((node) => node.sourceSpanIds))]
3130
+ };
3131
+ }
3132
+ function termFromCell(params) {
3133
+ const value = cleanValue(params.value);
3134
+ if (!value) return void 0;
3135
+ const nodes = [params.row, params.cell].filter((node) => Boolean(node));
3136
+ return {
3137
+ kind: termKind(params.label, value),
3138
+ label: params.label,
3139
+ value,
3140
+ ...moneyAmount(value) !== void 0 ? { amount: moneyAmount(value) } : {},
3141
+ ...params.appliesTo ? { appliesTo: params.appliesTo } : {},
3142
+ ...sourceIds(nodes)
3143
+ };
3144
+ }
3145
+ function termsFromRow(row, children) {
3146
+ const cells = cellRows(row, children);
3147
+ if (cells.length > 0) {
3148
+ return cells.filter((cell) => isValueCell(cell.label, cell.value)).map((cell) => termFromCell({ row, cell: cell.node, label: cell.label, value: cell.value })).filter((term) => Boolean(term));
3149
+ }
3150
+ const text = normalizeWhitespace3(row.textExcerpt ?? row.description ?? nodeText(row));
3151
+ const terms = [];
3152
+ for (const part of text.split(/\s+\|\s+/)) {
3153
+ const match = part.match(/^([^:]{2,80}):\s*(.+)$/);
3154
+ if (!match) continue;
3155
+ if (!isValueCell(match[1], match[2])) continue;
3156
+ const term = termFromCell({ row, label: cleanValue(match[1]) ?? "Value", value: match[2] });
3157
+ if (term) terms.push(term);
3158
+ }
3159
+ if (terms.length === 0) {
3160
+ const limit = limitFromText(text);
3161
+ if (limit) {
3162
+ const term = termFromCell({ row, label: "Limit", value: limit });
3163
+ if (term) terms.push(term);
3164
+ }
3165
+ const deductible = deductibleFromText(text);
3166
+ if (deductible) {
3167
+ const term = termFromCell({ row, label: "Deductible", value: deductible });
3168
+ if (term) terms.push(term);
3169
+ }
3170
+ }
3171
+ return terms;
3172
+ }
3173
+ function nameFromRow(row, children) {
3174
+ const cells = cellRows(row, children);
3175
+ const named = cells.find((cell) => isNameCell(cell.label, cell.value));
3176
+ if (named) return cleanValue(named.value);
3177
+ return coverageNameFromRow(nodeText(row));
3178
+ }
3179
+ function legacyLimit(terms) {
3180
+ return terms.find(
3181
+ (term) => ["each_claim_limit", "each_occurrence_limit", "each_loss_limit", "aggregate_limit", "sublimit", "other"].includes(term.kind)
3182
+ )?.value;
3183
+ }
3184
+ function legacyDeductible(terms) {
3185
+ return terms.find((term) => term.kind === "deductible" || term.kind === "retention")?.value;
3186
+ }
3187
+ function legacyPremium(terms) {
3188
+ return terms.find((term) => term.kind === "premium")?.value;
3189
+ }
3190
+ function retroDate(terms) {
3191
+ return terms.find((term) => term.kind === "retroactive_date")?.value;
3192
+ }
3193
+ function uniqueTerms(terms) {
3194
+ const seen = /* @__PURE__ */ new Set();
3195
+ const result = [];
3196
+ for (const term of terms) {
3197
+ const key = [term.kind, term.label.toLowerCase(), term.value.toLowerCase(), term.appliesTo ?? ""].join("|");
3198
+ if (seen.has(key)) continue;
3199
+ seen.add(key);
3200
+ result.push(term);
3201
+ }
3202
+ return result;
3203
+ }
3204
+ function coverageFromTableRow(row, children, byId) {
3205
+ if (row.metadata?.isHeader === true || row.metadata?.isHeader === "true") return void 0;
3206
+ const name = nameFromRow(row, children);
3207
+ const terms = uniqueTerms(termsFromRow(row, children));
3208
+ if (!name || terms.length === 0) return void 0;
3209
+ const ids = sourceIds([row, ...directChildren(row, children)]);
3210
+ const endorsement = endorsementAncestor(row, byId);
3211
+ return {
3212
+ name,
3213
+ limit: legacyLimit(terms),
3214
+ deductible: legacyDeductible(terms),
3215
+ premium: legacyPremium(terms),
3216
+ retroactiveDate: retroDate(terms),
3217
+ formNumber: typeof row.metadata?.formNumber === "string" ? row.metadata.formNumber : void 0,
3218
+ sectionRef: endorsement?.title,
3219
+ coverageOrigin: endorsement ? "endorsement" : "core",
3220
+ endorsementNumber: endorsementNumberFrom(endorsement?.title),
3221
+ limits: terms,
3222
+ ...ids
3223
+ };
3224
+ }
3225
+ function coverageFromEndorsement(endorsement, children) {
3226
+ const rows = descendants(endorsement, children).filter((node) => node.kind === "table_row");
3227
+ const terms = uniqueTerms(rows.flatMap(
3228
+ (row) => termsFromRow(row, children).map((term) => {
3229
+ const appliesTo = nameFromRow(row, children);
3230
+ return appliesTo && !/^(each claim limit|aggregate limit|retroactive date)$/i.test(appliesTo) ? { ...term, appliesTo } : term;
3231
+ })
3232
+ ));
3233
+ if (terms.length === 0) return void 0;
3234
+ const ids = sourceIds([endorsement, ...rows, ...rows.flatMap((row) => directChildren(row, children))]);
3235
+ return {
3236
+ name: endorsement.title,
3237
+ limit: legacyLimit(terms),
3238
+ deductible: legacyDeductible(terms),
3239
+ premium: legacyPremium(terms),
3240
+ retroactiveDate: retroDate(terms),
3241
+ formNumber: typeof endorsement.metadata?.formNumber === "string" ? endorsement.metadata.formNumber : void 0,
3242
+ sectionRef: endorsement.title,
3243
+ coverageOrigin: "endorsement",
3244
+ endorsementNumber: endorsementNumberFrom(endorsement.title),
3245
+ limits: terms,
3246
+ ...ids
3247
+ };
3248
+ }
2998
3249
  function buildCoverages(nodes) {
3250
+ const children = childMap(nodes);
3251
+ const byId = new Map(nodes.map((node) => [node.id, node]));
3252
+ const coverages = [];
3253
+ const seen = /* @__PURE__ */ new Set();
3254
+ for (const endorsement of nodes.filter((node) => node.kind === "endorsement")) {
3255
+ const coverage = coverageFromEndorsement(endorsement, children);
3256
+ if (!coverage) continue;
3257
+ const key = [coverage.name.toLowerCase(), coverage.sourceNodeIds.join(",")].join("|");
3258
+ if (seen.has(key)) continue;
3259
+ seen.add(key);
3260
+ coverages.push(coverage);
3261
+ }
2999
3262
  const rows = nodes.filter((node) => {
3000
3263
  const text = nodeText(node);
3001
- return (node.kind === "table_row" || node.kind === "schedule" || node.kind === "text") && /\b(coverage|limit|deductible|aggregate|occurrence|liability|premium)\b/i.test(text);
3264
+ return (node.kind === "table_row" || node.kind === "schedule" || node.kind === "text") && /\b(coverage|limit|deductible|aggregate|occurrence|liability|premium|retroactive|retention)\b/i.test(text);
3002
3265
  });
3003
- const coverages = [];
3004
- const seen = /* @__PURE__ */ new Set();
3005
3266
  for (const row of rows) {
3267
+ if (endorsementAncestor(row, byId)) continue;
3268
+ const structured = row.kind === "table_row" ? coverageFromTableRow(row, children, byId) : void 0;
3269
+ if (structured) {
3270
+ const key2 = [
3271
+ structured.name.toLowerCase(),
3272
+ structured.limits.map((term) => `${term.kind}:${term.value}`).join(","),
3273
+ structured.sourceNodeIds.join(",")
3274
+ ].join("|");
3275
+ if (seen.has(key2)) continue;
3276
+ seen.add(key2);
3277
+ coverages.push(structured);
3278
+ if (coverages.length >= 60) break;
3279
+ continue;
3280
+ }
3006
3281
  const text = nodeText(row);
3007
3282
  const name = coverageNameFromRow(text);
3008
3283
  const limit = limitFromText(text);
@@ -3018,6 +3293,8 @@ function buildCoverages(nodes) {
3018
3293
  deductible,
3019
3294
  premium,
3020
3295
  formNumber: typeof row.metadata?.formNumber === "string" ? row.metadata.formNumber : void 0,
3296
+ coverageOrigin: "core",
3297
+ limits: [],
3021
3298
  sourceNodeIds: [row.id],
3022
3299
  sourceSpanIds: row.sourceSpanIds
3023
3300
  });
@@ -3159,11 +3436,33 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3159
3436
  sourceSpanIds
3160
3437
  };
3161
3438
  };
3162
- const coverages = Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => ({
3163
- ...coverage,
3164
- sourceNodeIds: keepIds(coverage.sourceNodeIds, validNodeIds),
3165
- sourceSpanIds: keepIds(coverage.sourceSpanIds, validSpanIds)
3166
- })).filter((coverage) => coverage.name && (coverage.sourceNodeIds.length > 0 || coverage.sourceSpanIds.length > 0)) : base.coverages;
3439
+ const coverages = Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => {
3440
+ const record = coverage;
3441
+ const limits = Array.isArray(record.limits) ? record.limits.filter(
3442
+ (term) => Boolean(term) && typeof term === "object" && !Array.isArray(term)
3443
+ ).flatMap((term) => {
3444
+ const label = typeof term.label === "string" ? cleanValue(term.label) : void 0;
3445
+ const value = typeof term.value === "string" ? cleanValue(term.value) : void 0;
3446
+ const sourceNodeIds = keepIds(term.sourceNodeIds, validNodeIds);
3447
+ const sourceSpanIds = keepIds(term.sourceSpanIds, validSpanIds);
3448
+ if (!label || !value || sourceNodeIds.length === 0 && sourceSpanIds.length === 0) return [];
3449
+ return [{
3450
+ kind: normalizeTermKind(term.kind, label, value),
3451
+ label,
3452
+ value,
3453
+ amount: typeof term.amount === "number" && Number.isFinite(term.amount) ? term.amount : void 0,
3454
+ appliesTo: typeof term.appliesTo === "string" ? term.appliesTo : void 0,
3455
+ sourceNodeIds,
3456
+ sourceSpanIds
3457
+ }];
3458
+ }) : [];
3459
+ return {
3460
+ ...coverage,
3461
+ limits,
3462
+ sourceNodeIds: keepIds(record.sourceNodeIds, validNodeIds),
3463
+ sourceSpanIds: keepIds(record.sourceSpanIds, validSpanIds)
3464
+ };
3465
+ }).filter((coverage) => coverage.name && (coverage.sourceNodeIds.length > 0 || coverage.sourceSpanIds.length > 0)) : base.coverages;
3167
3466
  return PolicyOperationalProfileSchema.parse({
3168
3467
  ...base,
3169
3468
  documentType: candidate.documentType === "quote" ? "quote" : candidate.documentType === "policy" ? "policy" : base.documentType,
@@ -9173,8 +9472,31 @@ var OperationalProfilePromptSchema = z41.object({
9173
9472
  limit: z41.string().optional(),
9174
9473
  deductible: z41.string().optional(),
9175
9474
  premium: z41.string().optional(),
9475
+ retroactiveDate: z41.string().optional(),
9176
9476
  formNumber: z41.string().optional(),
9177
9477
  sectionRef: z41.string().optional(),
9478
+ coverageOrigin: z41.enum(["core", "endorsement"]).optional(),
9479
+ endorsementNumber: z41.string().optional(),
9480
+ limits: z41.array(z41.object({
9481
+ kind: z41.enum([
9482
+ "each_claim_limit",
9483
+ "each_occurrence_limit",
9484
+ "each_loss_limit",
9485
+ "aggregate_limit",
9486
+ "sublimit",
9487
+ "retention",
9488
+ "deductible",
9489
+ "retroactive_date",
9490
+ "premium",
9491
+ "other"
9492
+ ]).optional(),
9493
+ label: z41.string(),
9494
+ value: z41.string(),
9495
+ amount: z41.number().optional(),
9496
+ appliesTo: z41.string().optional(),
9497
+ sourceNodeIds: z41.array(z41.string()),
9498
+ sourceSpanIds: z41.array(z41.string())
9499
+ })).optional(),
9178
9500
  sourceNodeIds: z41.array(z41.string()),
9179
9501
  sourceSpanIds: z41.array(z41.string())
9180
9502
  })).optional(),
@@ -9328,6 +9650,25 @@ function pageTitleFromText(text, fallback) {
9328
9650
  if (firstSentence && firstSentence.length <= 120) return firstSentence.replace(/[.]$/, "");
9329
9651
  return fallback;
9330
9652
  }
9653
+ function pageHeadingTitleFromText(text, fallback) {
9654
+ const normalized = cleanText(text, "");
9655
+ const headingText = normalized.replace(/^page\s+\d+\s*(?:\|\s*page\s*\|\s*page\s+\d+\s*\|?)?/i, "").slice(0, 700);
9656
+ const patterns = [
9657
+ /\bIMPORTANT NOTICE\s+[—-]\s+HOW TO REPORT A CLAIM\b/i,
9658
+ /\bPRIVACY NOTICE TO POLICYHOLDERS\b/i,
9659
+ /\bOFAC ADVISORY NOTICE\b/i,
9660
+ /\bTERRORISM RISK INSURANCE ACT\s*\(TRIA\)\s*DISCLOSURE AND REJECTION\b/i,
9661
+ /\bDECLARATIONS PAGE\b/i,
9662
+ /\bTECHNOLOGY ERRORS?\s*&\s*OMISSIONS AND CYBER LIABILITY INSURANCE POLICY\b/i,
9663
+ /\bTRADE OR ECONOMIC SANCTIONS LIMITATION\b/i,
9664
+ /\bFORMS? AND ENDORSEMENTS\b/i
9665
+ ];
9666
+ for (const pattern of patterns) {
9667
+ const match = headingText.match(pattern)?.[0];
9668
+ if (match) return cleanText(match, fallback);
9669
+ }
9670
+ return fallback;
9671
+ }
9331
9672
  function pageFormTypeFromText(text) {
9332
9673
  if (/\b(declarations?\s+page|declarations?\s+schedule)\b/i.test(text)) return "declarations";
9333
9674
  if (/\b(endorsement\s+(?:no\.?|number|#)|this endorsement changes the policy|[A-Z]{2,}-END\s+\d{2,})\b/i.test(text)) return "endorsement";
@@ -9591,7 +9932,7 @@ function applySemanticPageGrouping(sourceTree) {
9591
9932
  if (node.kind === "document" || node.kind === "page_group") return node;
9592
9933
  let nextNode = node;
9593
9934
  if (node.kind === "page" && /^page\s+\d+$/i.test(node.title)) {
9594
- const title = pageTitleFromText(sourceNodeText(node), node.title);
9935
+ const title = pageHeadingTitleFromText([node.textExcerpt, node.description].filter(Boolean).join(" "), node.title);
9595
9936
  if (title !== node.title) {
9596
9937
  nextNode = {
9597
9938
  ...node,
@@ -9969,8 +10310,8 @@ function applyTitleSectionHierarchy(sourceTree) {
9969
10310
  const current = updates.get(child.id) ?? child;
9970
10311
  const heading = sectionHeadingTitle(current, container);
9971
10312
  if (heading) {
9972
- const descendants = byParent.get(child.id) ?? [];
9973
- const hasOwnContent = descendants.some((descendant) => descendant.kind !== "table_row" && descendant.kind !== "table_cell");
10313
+ const descendants2 = byParent.get(child.id) ?? [];
10314
+ const hasOwnContent = descendants2.some((descendant) => descendant.kind !== "table_row" && descendant.kind !== "table_cell");
9974
10315
  let hasFollowingContent = false;
9975
10316
  for (const nextChild of directPageChildren.slice(index + 1)) {
9976
10317
  const next = updates.get(nextChild.id) ?? nextChild;
@@ -9988,7 +10329,7 @@ function applyTitleSectionHierarchy(sourceTree) {
9988
10329
  parentId: container.id,
9989
10330
  kind: sectionKindForTitle(heading),
9990
10331
  title: heading,
9991
- description: descriptionWithPages(cleanText([heading, "section"].join(" "), heading), [current, ...descendants]),
10332
+ description: descriptionWithPages(cleanText([heading, "section"].join(" "), heading), [current, ...descendants2]),
9992
10333
  metadata: {
9993
10334
  ...current.metadata,
9994
10335
  organizer: "title_section",
@@ -10318,13 +10659,16 @@ function buildOperationalProfilePrompt(sourceTree, fallback) {
10318
10659
 
10319
10660
  Return only high-value operational facts needed for policy lists, Q&A, compliance, and certificate generation:
10320
10661
  - policy number, named insured, insurer/carrier/security, broker/producer, policy period, retroactive date, premium
10321
- - coverage lines with limits, deductibles, premiums, and form references
10662
+ - coverage units with their own nested limit terms, deductibles/retentions, retroactive dates, premiums, and form references
10322
10663
  - coverage type labels
10323
10664
 
10324
10665
  Rules:
10325
10666
  - Every returned value must include sourceNodeIds or sourceSpanIds from the provided nodes.
10326
10667
  - If a value is not directly supported, omit it.
10327
10668
  - Prefer declarations, schedules, premium tables, and endorsement schedules over generic policy wording.
10669
+ - Treat an endorsement as one coverage unit when it contains a schedule. Do not split an endorsement schedule into generic rows like "Aggregate Limit".
10670
+ - For coverage schedules, put each claim, aggregate, sublimit, retention, deductible, and retroactive date values in coverages[].limits with labels and source IDs. Keep the legacy coverages[].limit as the primary display value only.
10671
+ - Use coverageOrigin: "endorsement" for endorsement units and "core" for declarations/core policy coverage units.
10328
10672
  - Do not copy entire policy wording into fields.
10329
10673
 
10330
10674
  Deterministic baseline:
@@ -10440,11 +10784,18 @@ function materializeDocument(params) {
10440
10784
  limit: coverage.limit,
10441
10785
  deductible: coverage.deductible,
10442
10786
  premium: coverage.premium,
10787
+ retroactiveDate: coverage.retroactiveDate,
10443
10788
  formNumber: coverage.formNumber,
10444
10789
  sectionRef: coverage.sectionRef,
10790
+ coverageOrigin: coverage.coverageOrigin,
10791
+ endorsementNumber: coverage.endorsementNumber,
10792
+ limits: coverage.limits,
10445
10793
  sourceSpanIds: coverage.sourceSpanIds,
10446
10794
  documentNodeId: coverage.sourceNodeIds[0],
10447
- originalContent: [coverage.name, coverage.limit, coverage.deductible, coverage.premium].filter(Boolean).join(" | ")
10795
+ originalContent: [
10796
+ coverage.name,
10797
+ ...coverage.limits?.length ? coverage.limits.map((term) => `${term.label}: ${term.value}`) : [coverage.limit, coverage.deductible, coverage.premium]
10798
+ ].filter(Boolean).join(" | ")
10448
10799
  }));
10449
10800
  const documentOutline = sourceTreeToOutline(params.sourceTree);
10450
10801
  const documentMetadata = {
@@ -15570,6 +15921,7 @@ export {
15570
15921
  MissingInfoQuestionSchema,
15571
15922
  NamedInsuredSchema,
15572
15923
  OperationalCoverageLineSchema,
15924
+ OperationalCoverageTermSchema,
15573
15925
  OperationalEndorsementSupportSchema,
15574
15926
  OperationalPartySchema,
15575
15927
  PERSONAL_AUTO_USAGES,