@claritylabs/cl-sdk 3.2.5 → 3.2.6

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
@@ -3952,6 +3952,16 @@ var OPERATIONAL_COVERAGE_TERM_KINDS2 = [
3952
3952
  "other"
3953
3953
  ];
3954
3954
  var OperationalCoverageTermKindSchema = import_zod21.z.enum(OPERATIONAL_COVERAGE_TERM_KINDS2);
3955
+ var CleanupTermSchema = import_zod21.z.object({
3956
+ kind: OperationalCoverageTermKindSchema,
3957
+ label: import_zod21.z.string(),
3958
+ value: import_zod21.z.string(),
3959
+ amount: import_zod21.z.number().nullable().optional(),
3960
+ appliesTo: import_zod21.z.string().nullable().optional(),
3961
+ sourceNodeIds: import_zod21.z.array(import_zod21.z.string()).optional(),
3962
+ sourceSpanIds: import_zod21.z.array(import_zod21.z.string()).optional(),
3963
+ reason: import_zod21.z.string().optional()
3964
+ });
3955
3965
  var OperationalProfileCleanupSchema = import_zod21.z.object({
3956
3966
  coverageDecisions: import_zod21.z.array(import_zod21.z.object({
3957
3967
  coverageIndex: import_zod21.z.number().int().nonnegative(),
@@ -3975,7 +3985,8 @@ var OperationalProfileCleanupSchema = import_zod21.z.object({
3975
3985
  appliesTo: import_zod21.z.string().nullable().optional(),
3976
3986
  sourceNodeIds: import_zod21.z.array(import_zod21.z.string()).optional(),
3977
3987
  sourceSpanIds: import_zod21.z.array(import_zod21.z.string()).optional()
3978
- })).optional()
3988
+ })).optional(),
3989
+ termAdditions: import_zod21.z.array(CleanupTermSchema).optional()
3979
3990
  })).default([]),
3980
3991
  warnings: import_zod21.z.array(import_zod21.z.string()).default([])
3981
3992
  });
@@ -4153,19 +4164,22 @@ Projection defects to look for:
4153
4164
  - Item references such as "shown in Item 7" or bare item numbers treated as money amounts.
4154
4165
  - Policy wording, exclusions, or unsupported prose copied into operational limit/deductible fields.
4155
4166
  - Header/value splits where "Limit of Liability", "Deductible", "Retroactive Date", "Aggregate", "Each Claim", or similar terms are attached to the wrong coverage row.
4167
+ - Collapsed combined bases where one candidate term says "Each Claim / Aggregate", "Each Loss / Aggregate", "Each Proceeding / Aggregate", or a continuation line supplies a separate policy aggregate, sub-limit, deductible, retention, retroactive date, or coinsurance term.
4156
4168
  - Repeated schedule headings projected as separate coverages when they only introduce the next coverage group.
4157
4169
 
4158
4170
  Rules:
4159
4171
  - Use internal reasoning, but return JSON decisions only.
4160
- - Do not invent policy facts. Keep, drop, or update only existing coverageIndex and termIndex entries.
4172
+ - Do not invent policy facts. Keep, drop, or update only existing coverageIndex and termIndex entries, except for source-backed termAdditions on an existing coverage.
4161
4173
  - Use sourceNodeIds and sourceSpanIds only from the provided source nodes or from the existing candidate entry.
4162
4174
  - Prefer dropping a malformed fact over speculative rewriting.
4163
4175
  - Keep a coverage when it is a real operational coverage/benefit even if only one term needs cleanup.
4164
4176
  - When changing a term's semantic meaning, set kind to the corrected normalized term kind.
4165
- - Do not add new coverage rows or new terms; this pass cleans the existing projection.
4166
- - If one existing term combines multiple real limit bases, such as "Each Claim / Aggregate", keep the combined term unless another existing term already represents the other basis. Do not relabel it to only one basis and lose information.
4177
+ - Do not add new coverage rows.
4178
+ - Add termAdditions only when a provided source node directly supports the missing term and the candidate already has the correct coverage row.
4179
+ - When replacing one combined term with split terms, drop the combined term and add one term per basis. For example, "$1,000,000 Each Claim / Aggregate" should become one each_claim_limit term and one aggregate_limit term, both with value "$1,000,000".
4180
+ - When a schedule continues onto the next page before the next item marker, attach continuation terms such as "Aggregate", "Policy Aggregate", coinsurance, deductible, or retroactive date to the previous coverage row.
4167
4181
  - Include every JSON key in each decision. Use null for scalar fields you are not changing and [] for source ID lists you are not changing.
4168
- - For each coverage decision, always include termDecisions. Use [] when no terms need cleanup.
4182
+ - For each coverage decision, always include termDecisions and termAdditions. Use [] when no existing terms need cleanup or no new terms are needed.
4169
4183
  - Keep reasons concise and factual.
4170
4184
 
4171
4185
  Candidate projection:
@@ -4306,9 +4320,50 @@ function applyTermCleanupDecision(term, decision, validNodeIds, validSpanIds) {
4306
4320
  }
4307
4321
  return next;
4308
4322
  }
4323
+ function termAdditionTouches(addition, predicate) {
4324
+ return predicate({
4325
+ kind: addition.kind,
4326
+ label: cleanProfileValue(addition.label) ?? "",
4327
+ value: cleanProfileValue(addition.value) ?? ""
4328
+ });
4329
+ }
4309
4330
  function termDecisionsTouch(coverage, decisions, predicate) {
4310
4331
  return decisions.filter((decision) => decision.action !== "keep").some((decision) => termDecisionTouches(coverage, decision, predicate));
4311
4332
  }
4333
+ function termAdditionsTouch(additions, predicate) {
4334
+ return additions.some((addition) => termAdditionTouches(addition, predicate));
4335
+ }
4336
+ function termKey(term) {
4337
+ return [
4338
+ term.kind,
4339
+ cleanProfileValue(term.label)?.toLowerCase(),
4340
+ cleanProfileValue(term.value)?.toLowerCase()
4341
+ ].join("|");
4342
+ }
4343
+ function applyTermAddition(addition, validNodeIds, validSpanIds) {
4344
+ const label = cleanProfileValue(addition.label);
4345
+ const value = cleanProfileValue(addition.value);
4346
+ if (!label || !value) return void 0;
4347
+ const sourceNodeIds = validIds(addition.sourceNodeIds, validNodeIds);
4348
+ const sourceSpanIds = validIds(addition.sourceSpanIds, validSpanIds);
4349
+ if (sourceNodeIds.length === 0 && sourceSpanIds.length === 0) return void 0;
4350
+ const term = {
4351
+ kind: addition.kind,
4352
+ label,
4353
+ value,
4354
+ sourceNodeIds,
4355
+ sourceSpanIds
4356
+ };
4357
+ if (typeof addition.amount === "number" && Number.isFinite(addition.amount)) {
4358
+ term.amount = addition.amount;
4359
+ } else if (term.kind !== "retroactive_date") {
4360
+ const amount = amountFromOperationalValue(value);
4361
+ if (amount !== void 0) term.amount = amount;
4362
+ }
4363
+ const appliesTo = cleanProfileValue(addition.appliesTo);
4364
+ if (appliesTo) term.appliesTo = appliesTo;
4365
+ return term;
4366
+ }
4312
4367
  function applyCoverageCleanupDecision(coverage, decision, validNodeIds, validSpanIds) {
4313
4368
  if (!decision || decision.action === "keep") return coverage;
4314
4369
  if (decision.action === "drop") return void 0;
@@ -4339,23 +4394,31 @@ function applyCoverageCleanupDecision(coverage, decision, validNodeIds, validSpa
4339
4394
  const termDecisions = (decision.termDecisions ?? []).filter((termDecision) => termDecision.termIndex < coverage.limits.length);
4340
4395
  const termDecisionByIndex = new Map(termDecisions.map((termDecision) => [termDecision.termIndex, termDecision]));
4341
4396
  next.limits = coverage.limits.map((term, index) => applyTermCleanupDecision(term, termDecisionByIndex.get(index), validNodeIds, validSpanIds)).filter((term) => Boolean(term));
4342
- if (termDecisions.length > 0) {
4343
- if (decision.limit == null && termDecisionsTouch(coverage, termDecisions, isLimitTerm)) {
4397
+ const termAdditions = (decision.termAdditions ?? []).map((addition) => applyTermAddition(addition, validNodeIds, validSpanIds)).filter((term) => Boolean(term));
4398
+ const existingTermKeys = new Set(next.limits.map(termKey));
4399
+ for (const term of termAdditions) {
4400
+ const key = termKey(term);
4401
+ if (existingTermKeys.has(key)) continue;
4402
+ next.limits.push(term);
4403
+ existingTermKeys.add(key);
4404
+ }
4405
+ if (termDecisions.length > 0 || termAdditions.length > 0) {
4406
+ if (decision.limit == null && (termDecisionsTouch(coverage, termDecisions, isLimitTerm) || termAdditionsTouch(termAdditions, isLimitTerm))) {
4344
4407
  const value = primaryLimitFromTerms(next.limits);
4345
4408
  if (value) next.limit = value;
4346
4409
  else delete next.limit;
4347
4410
  }
4348
- if (decision.deductible == null && termDecisionsTouch(coverage, termDecisions, isDeductibleTerm)) {
4411
+ if (decision.deductible == null && (termDecisionsTouch(coverage, termDecisions, isDeductibleTerm) || termAdditionsTouch(termAdditions, isDeductibleTerm))) {
4349
4412
  const value = deductibleFromTerms(next.limits);
4350
4413
  if (value) next.deductible = value;
4351
4414
  else delete next.deductible;
4352
4415
  }
4353
- if (decision.premium == null && termDecisionsTouch(coverage, termDecisions, isPremiumTerm)) {
4416
+ if (decision.premium == null && (termDecisionsTouch(coverage, termDecisions, isPremiumTerm) || termAdditionsTouch(termAdditions, isPremiumTerm))) {
4354
4417
  const value = premiumFromTerms(next.limits);
4355
4418
  if (value) next.premium = value;
4356
4419
  else delete next.premium;
4357
4420
  }
4358
- if (decision.retroactiveDate == null && termDecisionsTouch(coverage, termDecisions, isRetroactiveDateTerm)) {
4421
+ if (decision.retroactiveDate == null && (termDecisionsTouch(coverage, termDecisions, isRetroactiveDateTerm) || termAdditionsTouch(termAdditions, isRetroactiveDateTerm))) {
4359
4422
  const value = retroactiveDateFromTerms(next.limits);
4360
4423
  if (value) next.retroactiveDate = value;
4361
4424
  else delete next.retroactiveDate;