@claritylabs/cl-sdk 3.0.13 → 3.0.15

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
@@ -2700,7 +2700,7 @@ function isDiscardableBoilerplate(text, unit) {
2700
2700
  }
2701
2701
  function isBoilerplateLine(line) {
2702
2702
  const cleaned = normalizeWhitespace(line.replace(/\bColumn\s+\d+:\s*/gi, ""));
2703
- return isDiscardableBoilerplate(cleaned) || /^IMPORTANT NOTICE\s*[-—]\s*/i.test(cleaned) || /^THIS IS A CLAIMS-MADE AND REPORTED POLICY\.? PLEASE READ IT CAREFULLY\.?$/i.test(cleaned);
2703
+ return isDiscardableBoilerplate(cleaned) || /^THIS IS A CLAIMS-MADE AND REPORTED POLICY\.? PLEASE READ IT CAREFULLY\.?$/i.test(cleaned);
2704
2704
  }
2705
2705
  function removedBoilerplateLines(text) {
2706
2706
  return text.split(/\s{2,}|\r?\n/).map(normalizeWhitespace).filter((line) => line && isBoilerplateLine(line));
@@ -2999,7 +2999,18 @@ function metadataString(metadata, key) {
2999
2999
  }
3000
3000
  function isTitleContentNode(node) {
3001
3001
  if (node.kind !== "text") return false;
3002
- return metadataString(node.metadata, "elementType") === "title" || metadataString(node.metadata, "sourceUnit") === "title";
3002
+ const isMarkedTitle = metadataString(node.metadata, "elementType") === "title" || metadataString(node.metadata, "sourceUnit") === "title";
3003
+ if (!isMarkedTitle) return false;
3004
+ const text = normalizeWhitespace2(node.textExcerpt ?? node.title);
3005
+ if (!text || text.length > 140) return false;
3006
+ const words = text.split(/\s+/);
3007
+ if (words.length > 14) return false;
3008
+ const startsWithStructuredHeading = /^(section|item|part|coverage part|endorsement|schedule|article)\b|^[A-Z]\.\s|\b[IVX]+\.\s/i.test(text);
3009
+ const uppercaseLetters = [...text].filter((char) => /[A-Z]/.test(char)).length;
3010
+ const lowercaseLetters = [...text].filter((char) => /[a-z]/.test(char)).length;
3011
+ const mostlyUppercase = uppercaseLetters > 0 && uppercaseLetters >= lowercaseLetters * 1.6;
3012
+ const sentenceLike = /\b(is|are|was|were|will|shall|may|must|means|includes|provided|subject|available|attached|remain|constitutes)\b/i.test(text) && /[a-z]/.test(text);
3013
+ return startsWithStructuredHeading || mostlyUppercase && !sentenceLike;
3003
3014
  }
3004
3015
  function nodePageEnd(node) {
3005
3016
  return node.pageEnd ?? node.pageStart;
@@ -3039,10 +3050,10 @@ function groupPageContentByTitles(nodes) {
3039
3050
  const bbox = evidenceNodes.flatMap((node) => node.bbox ?? []).slice(0, 12);
3040
3051
  byId.set(activeTitle.id, {
3041
3052
  ...activeTitle,
3042
- kind: "section",
3053
+ kind: "text",
3043
3054
  title,
3044
3055
  description: nodeTextDescription({
3045
- kind: "section",
3056
+ kind: "text",
3046
3057
  title,
3047
3058
  text: evidenceNodes.map((node) => node.textExcerpt).filter(Boolean).join("\n\n"),
3048
3059
  page: activeTitle.pageStart
@@ -9599,6 +9610,7 @@ function looksLikeDeclarationsContinuation(node) {
9599
9610
  function looksLikePolicyFormStart(node) {
9600
9611
  const text = sourceNodeText(node);
9601
9612
  const excerpt = cleanText(node.textExcerpt, "");
9613
+ if (isAdministrativeNoticeNode(node) || looksLikeDeclarationsStart(node)) return false;
9602
9614
  return /\bpolicy form\b/i.test(node.title) || /^policy\s+form\b/i.test(excerpt) || /\btechnology errors?\s*&?\s*omissions\b/i.test(text) && /\bplease read this entire policy carefully\b/i.test(text) || /\bform\s+[A-Z]{2,}-[A-Z0-9-]+\s+\d{2}\s+\d{2}\b/i.test(text);
9603
9615
  }
9604
9616
  function looksLikePolicyFormContinuation(node) {
@@ -9607,9 +9619,9 @@ function looksLikePolicyFormContinuation(node) {
9607
9619
  return /\b(insuring agreement|definitions?|exclusions?|conditions?|claim means|insured means|wrongful act means|limits of liability|notice of claim|cancellation by|action against the company)\b/i.test(text);
9608
9620
  }
9609
9621
  function groupAdjacentChildren(params) {
9610
- if (params.childIds.length < 2) return params.sourceTree;
9622
+ if (params.childIds.length < 1) return params.sourceTree;
9611
9623
  const children = params.childIds.map((id2) => params.children.find((child) => child.id === id2)).filter((child) => Boolean(child));
9612
- if (children.length < 2) return params.sourceTree;
9624
+ if (children.length < 1) return params.sourceTree;
9613
9625
  const parentId = children[0].parentId;
9614
9626
  if (!children.every((child) => child.parentId === parentId)) return params.sourceTree;
9615
9627
  const documentId = children[0].documentId;
@@ -9718,6 +9730,11 @@ function applySemanticPageGrouping(sourceTree) {
9718
9730
  for (let index = policyStartIndex; index < children.length; index += 1) {
9719
9731
  const child = children[index];
9720
9732
  if (index > policyStartIndex && looksLikeEndorsementStart(child)) break;
9733
+ if (isAdministrativeNoticeNode(child) || looksLikeDeclarationsStart(child)) break;
9734
+ if (index > policyStartIndex && child.kind === "page") {
9735
+ policyIds.push(child.id);
9736
+ continue;
9737
+ }
9721
9738
  if (!looksLikePolicyFormContinuation(child)) break;
9722
9739
  policyIds.push(child.id);
9723
9740
  }
@@ -9745,6 +9762,9 @@ function rejectsOrganizerGroup(group, children) {
9745
9762
  function isEndorsementGroup(node) {
9746
9763
  return node.kind === "page_group" && /^endorsements?\b/i.test(node.title);
9747
9764
  }
9765
+ function isNoticesGroup(node) {
9766
+ return node.kind === "page_group" && /^notices?\s+and\s+jacket$/i.test(node.title);
9767
+ }
9748
9768
  function endorsementGroupNodeId(documentId, parentId) {
9749
9769
  return [
9750
9770
  documentId.replace(/[^a-zA-Z0-9_.:-]/g, "_"),
@@ -9760,6 +9780,56 @@ function isPolicyFormNode(node) {
9760
9780
  function isDeclarationsNode(node) {
9761
9781
  return node.kind === "page_group" && node.title === "Declarations";
9762
9782
  }
9783
+ function isAdministrativeNoticeNode(node) {
9784
+ const text = sourceNodeText(node);
9785
+ return /\b(specimen policy|policy jacket|important notice|privacy notice|ofac advisory|terrorism risk insurance act|tria|trade or economic sanctions|economic sanctions limitation|signature|countersignature|how to report a claim)\b/i.test(text);
9786
+ }
9787
+ function mergeAdministrativeNoticesIntoFrontMatter(sourceTree) {
9788
+ const rootId = sourceTreeRootId(sourceTree);
9789
+ if (!rootId) return sourceTree;
9790
+ const children = (nodesByParent(sourceTree).get(rootId) ?? []).filter((node) => node.kind !== "document");
9791
+ const noticesGroup = children.find(isNoticesGroup);
9792
+ if (!noticesGroup) return sourceTree;
9793
+ const noticesGroupChildren = new Set(
9794
+ (nodesByParent(sourceTree).get(noticesGroup.id) ?? []).map((node) => node.id)
9795
+ );
9796
+ const noticeIds = new Set(
9797
+ children.filter(
9798
+ (node) => node.id !== noticesGroup.id && !noticesGroupChildren.has(node.id) && node.kind === "page" && isAdministrativeNoticeNode(node)
9799
+ ).map((node) => node.id)
9800
+ );
9801
+ if (noticeIds.size === 0) return sourceTree;
9802
+ return sourceTree.map(
9803
+ (node) => noticeIds.has(node.id) ? {
9804
+ ...node,
9805
+ parentId: noticesGroup.id,
9806
+ metadata: {
9807
+ ...node.metadata,
9808
+ organizerRepair: "merge_administrative_notice"
9809
+ }
9810
+ } : node
9811
+ );
9812
+ }
9813
+ function rootSemanticRank(node) {
9814
+ if (isNoticesGroup(node)) return 0;
9815
+ if (node.title === "Declarations") return 1;
9816
+ if (node.title === "Policy Form") return 2;
9817
+ if (isEndorsementGroup(node)) return 3;
9818
+ if (isAdministrativeNoticeNode(node)) return 0.5;
9819
+ return 2.5;
9820
+ }
9821
+ function normalizeRootSemanticOrder(sourceTree) {
9822
+ const rootId = sourceTreeRootId(sourceTree);
9823
+ if (!rootId) return sourceTree;
9824
+ const rootChildren2 = (nodesByParent(sourceTree).get(rootId) ?? []).filter((node) => node.kind !== "document").sort(
9825
+ (left, right) => rootSemanticRank(left) - rootSemanticRank(right) || (left.pageStart ?? Number.MAX_SAFE_INTEGER) - (right.pageStart ?? Number.MAX_SAFE_INTEGER) || left.order - right.order || left.id.localeCompare(right.id)
9826
+ );
9827
+ const orderById = new Map(rootChildren2.map((node, index) => [node.id, index + 1]));
9828
+ return sourceTree.map((node) => {
9829
+ const order = orderById.get(node.id);
9830
+ return order === void 0 ? node : { ...node, order };
9831
+ });
9832
+ }
9763
9833
  function normalizePolicyFormStructure(sourceTree) {
9764
9834
  let nextTree = sourceTree;
9765
9835
  const byParent = nodesByParent(nextTree);
@@ -9868,9 +9938,10 @@ function normalizeSemanticHierarchy(sourceTree) {
9868
9938
  )
9869
9939
  );
9870
9940
  const nested = normalizeDocumentSourceTreePaths(nestEndorsementContinuationPages(normalized));
9871
- const withEvidence = normalizeContainerEvidenceFromChildren(nested);
9941
+ const mergedNotices = normalizeDocumentSourceTreePaths(mergeAdministrativeNoticesIntoFrontMatter(nested));
9942
+ const withEvidence = normalizeContainerEvidenceFromChildren(mergedNotices);
9872
9943
  return normalizeDocumentSourceTreePaths(
9873
- normalizeContainerEvidenceFromChildren(withEvidence)
9944
+ normalizeRootSemanticOrder(normalizeContainerEvidenceFromChildren(withEvidence))
9874
9945
  );
9875
9946
  }
9876
9947
  function applyEndorsementGrouping(sourceTree) {