@finsys/core 4.6.0 → 4.8.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.d.cts CHANGED
@@ -842,6 +842,35 @@ interface CanonicalFieldSpec {
842
842
  readonly unit?: string;
843
843
  readonly range?: readonly [number, number];
844
844
  readonly description: string;
845
+ /**
846
+ * Global fact identifier marking this field as an ATTESTATION of a
847
+ * shared real-world fact (e.g. a company has exactly one
848
+ * incorporation date, no matter which document it was extracted
849
+ * from). Multiple categories may declare the SAME field name iff
850
+ * every declaring category carries the same `fact` id — each
851
+ * category's value is then an independent attestation of one fact,
852
+ * comparable across sources (the future disagreement-comparison
853
+ * feature's unit of comparison). A `fact` id is bound to exactly one
854
+ * field name registry-wide; by convention the field name IS the fact
855
+ * id. Uniquely-declared fields need no `fact` (but may carry one).
856
+ */
857
+ readonly fact?: string;
858
+ /**
859
+ * Field kind — a semantic refinement of `type`. Currently the only
860
+ * kind is `"enum"`: the field's value is one label out of a closed
861
+ * set. The category declares ONLY that the field is enumerated —
862
+ * never the values, never an ordering. Value sets are vendor
863
+ * territory: each adapter declares the exact labels it emits in its
864
+ * manifest's `enumValues` (host-validated), because two vendors
865
+ * implementing the same category may bucket differently. Ordering
866
+ * and scoring interpretation live even further out, in the consumer
867
+ * (an eval model's per-value mapping) — an enum label is data, what
868
+ * it is worth is opinion, and opinions don't belong in the data
869
+ * contract. An enum field MUST be `type: "string"` (labels are
870
+ * string-normalized) and MUST NOT declare a `range` (labels are
871
+ * unordered).
872
+ */
873
+ readonly kind?: "enum";
845
874
  }
846
875
  /**
847
876
  * Per-category schema bundle. Used by:
@@ -883,11 +912,30 @@ declare function allCategories(): ReadonlyArray<CategorySchema>;
883
912
  /**
884
913
  * Reverse lookup: which category declares a given canonical field?
885
914
  * Returns null if the field name isn't declared by any category in
886
- * this version of finsys-core. Useful when the host app is reading
887
- * canonical field values back from storage + wants to identify the
888
- * producing category for rendering. O(1).
915
+ * this version of finsys-core AND for shared-fact names (declared by
916
+ * more than one category), where "the" category is genuinely ambiguous.
917
+ * The null is deliberate: a caller holding a shared-fact name must
918
+ * decide per-attestation, via `categoriesAttestingFact(factOf(name))`,
919
+ * rather than being handed one arbitrary declarer. Useful when the
920
+ * host app is reading canonical field values back from storage + wants
921
+ * to identify the producing category for rendering. O(1).
889
922
  */
890
923
  declare function categoryForField(field: CanonicalFieldName): AdapterCategory | null;
924
+ /**
925
+ * The fact id a canonical field attests, or null when the field
926
+ * declares no fact (or isn't declared at all). By convention the fact
927
+ * id equals the field name, but callers must not assume it — read it
928
+ * from here. O(1).
929
+ */
930
+ declare function factOf(field: CanonicalFieldName): string | null;
931
+ /**
932
+ * Every category attesting a given shared fact, in data-file order.
933
+ * Empty for an unknown fact id. This is the lookup the disagreement-
934
+ * comparison feature keys on: each attesting category's value for the
935
+ * fact's field is an independent observation of the same real-world
936
+ * fact, so cross-category mismatches are surfaceable.
937
+ */
938
+ declare function categoriesAttestingFact(factId: string): ReadonlyArray<AdapterCategory>;
891
939
  /**
892
940
  * Runtime membership check — is `id` a category declared by this
893
941
  * version of finsys-core? Use this at trust boundaries (parsing a
@@ -1597,6 +1645,34 @@ interface AdapterManifest {
1597
1645
  * adapter is implemented.
1598
1646
  */
1599
1647
  readonly periods?: ReadonlyArray<PeriodDeclaration>;
1648
+ /**
1649
+ * Vendor-specific value sets for the enum-kind fields this adapter
1650
+ * produces. The category declares only THAT a field is enumerated
1651
+ * (`kind: "enum"` — no values, no ordering); the manifest declares
1652
+ * exactly WHICH labels this vendor emits, because two vendors
1653
+ * implementing the same category may bucket differently. Scoring
1654
+ * interpretation lives further out still, in the consumer (an eval
1655
+ * model's per-value mapping with a mandatory fallback) — never here.
1656
+ *
1657
+ * Host-validated at registration (same posture as `produces` ⊆
1658
+ * category fields):
1659
+ * - every key MUST appear in `produces`;
1660
+ * - every key MUST be declared `kind: "enum"` by the adapter's
1661
+ * category — a non-enum field with declared values is refused;
1662
+ * - every enum-kind field in `produces` MUST have an entry here —
1663
+ * an adapter that promises an enum field but not its labels
1664
+ * gives clients nothing to render or map against;
1665
+ * - each value set is a non-empty array of unique, string-
1666
+ * normalized labels (non-empty, no leading/trailing whitespace).
1667
+ *
1668
+ * At runtime the adapter emits labels from its declared set
1669
+ * VERBATIM; the host refuses out-of-set values at ingest, so a
1670
+ * vendor-side vocabulary change is a loud manifest-version bump,
1671
+ * never silent data drift. Clients (form-spec and eval-model
1672
+ * editors) read these sets through the registry-metadata surface to
1673
+ * offer the labels without hardcoding any vendor's vocabulary.
1674
+ */
1675
+ readonly enumValues?: Readonly<Record<CanonicalFieldName, ReadonlyArray<string>>>;
1600
1676
  /**
1601
1677
  * Optional free-form notes — useful for partner-side documentation
1602
1678
  * (where to find the adapter's source, who owns it, what version of
@@ -1740,4 +1816,4 @@ interface FieldMapEntry {
1740
1816
  readonly transform?: "identity" | "pct_to_ratio01" | "to_boolean" | "to_integer";
1741
1817
  }
1742
1818
 
1743
- export { ADAPTER_CATEGORY_IDS, ALL_AGGREGATION_OPS, type AdapterCategory, AdapterError, type AdapterErrorReason, type AdapterExtraction, type AdapterManifest, type AggregationOp, type ApplicantIdentity, BASE_FIELD_SPECS, BasicFormField, type CanonicalFieldName, type CanonicalFieldSpec, type CanonicalFieldValue, type CanonicalFieldValues, type Category, type CategorySchema, type CategorySpec, type Choice, DEFAULT_VALIDATOR_DEFINITIONS, type DeclarativeImplementation, type DocExtractionResult, DocExtractionStatus, type DocumentFileMetadata, type DocumentRow, type DocumentRowCapabilities, type DocumentTypeGroup, type DropdownOption, type EditorValidator, type ExtractionFileType, type ExtractionJobRecord, ExtractionJobStatus, type ExtractionPipelineImplementation, type ExtractionStatusResult, FIELD_TYPE_DEFINITIONS, type FieldAuthorization, type FieldData, type FieldGroup, type FieldMapEntry, type FieldReference, FieldType, type FileFieldTableData, type FileFieldTableItem, FileFieldTableType, FileFormField, FormField, FormFieldCategory, type FormFieldInputType, type FormFieldType, type FormFieldTypeDefinitions, FormFieldValidator, type FormIntakeFieldMapEntry, type FormIntakeImplementation, FormSpec, type FormValidatorDefinitions, IHS_FAILURE_STATUSES, IHS_FIELD_ORIGINS, IHS_TERMINAL_STATUSES, IHS_VALID_STATUSES, type IhsDetailCategory, type IhsFieldDetail, type IhsFieldOrigin, type IhsFieldProvenance, IhsStatus, IhsValueFormat, type InstanceRow, type InstanceValue, type ManualOverrideImplementation, type PageConfig, type PeriodDeclaration, type PeriodValues, type RHFSchemaOutput, type RHFStep, type RawPayload, type ResolvedField, Role, type SourceAdapter, type SurveyElementJSON, type SurveyJSON, type SurveyPageJSON, type TaggedFieldData, type TimePeriodUnit, type TypescriptImplementation, type UnifiedFormConfig, type Validator, type WireFormat, allCategories, applyAggregation, applyDynamicTitles, assertAdapterCategory, assertDocumentType, buildDocumentRows, buildFileFieldTables, buildFileFieldTablesFromInstances, categoryFieldsOf, categoryForField, categorySchemaOf, evaluateExpression, extractTimePeriods, formatDocumentSize, formatDocumentType, formatDocumentUploaded, generateRHFSchema, generateSurveyJson, getBaseCategories, getBaseFieldNames, getBaseFieldSpecMap, getBaseFieldSpecs, getCategoryName, getDisplayName, getDisplayNames, getDocDisplayNames, getDocumentTypeGroups, getExtractableDocTypes, getGroupDisplayNames, getPastMonthLabel, getPastYearLabel, getReuploadableDocTypes, getStepDefaultValues, getStepSchema, groupColumnsByInstance, groupColumnsByTimePeriod, groupDetailsByCategory, groupFieldsByCategory, groupFieldsByPattern, isAdapterCategory, isDocumentType, isFailureIhsStatus, isTerminalIhsStatus, isValidIhsFieldOrigin, isValidIhsStatus, parseFileField, processIhsDetails, resolveExtractionStatus, resolvePageFields, validateFormConfig, validateFormSpec, validatePagesConfig };
1819
+ export { ADAPTER_CATEGORY_IDS, ALL_AGGREGATION_OPS, type AdapterCategory, AdapterError, type AdapterErrorReason, type AdapterExtraction, type AdapterManifest, type AggregationOp, type ApplicantIdentity, BASE_FIELD_SPECS, BasicFormField, type CanonicalFieldName, type CanonicalFieldSpec, type CanonicalFieldValue, type CanonicalFieldValues, type Category, type CategorySchema, type CategorySpec, type Choice, DEFAULT_VALIDATOR_DEFINITIONS, type DeclarativeImplementation, type DocExtractionResult, DocExtractionStatus, type DocumentFileMetadata, type DocumentRow, type DocumentRowCapabilities, type DocumentTypeGroup, type DropdownOption, type EditorValidator, type ExtractionFileType, type ExtractionJobRecord, ExtractionJobStatus, type ExtractionPipelineImplementation, type ExtractionStatusResult, FIELD_TYPE_DEFINITIONS, type FieldAuthorization, type FieldData, type FieldGroup, type FieldMapEntry, type FieldReference, FieldType, type FileFieldTableData, type FileFieldTableItem, FileFieldTableType, FileFormField, FormField, FormFieldCategory, type FormFieldInputType, type FormFieldType, type FormFieldTypeDefinitions, FormFieldValidator, type FormIntakeFieldMapEntry, type FormIntakeImplementation, FormSpec, type FormValidatorDefinitions, IHS_FAILURE_STATUSES, IHS_FIELD_ORIGINS, IHS_TERMINAL_STATUSES, IHS_VALID_STATUSES, type IhsDetailCategory, type IhsFieldDetail, type IhsFieldOrigin, type IhsFieldProvenance, IhsStatus, IhsValueFormat, type InstanceRow, type InstanceValue, type ManualOverrideImplementation, type PageConfig, type PeriodDeclaration, type PeriodValues, type RHFSchemaOutput, type RHFStep, type RawPayload, type ResolvedField, Role, type SourceAdapter, type SurveyElementJSON, type SurveyJSON, type SurveyPageJSON, type TaggedFieldData, type TimePeriodUnit, type TypescriptImplementation, type UnifiedFormConfig, type Validator, type WireFormat, allCategories, applyAggregation, applyDynamicTitles, assertAdapterCategory, assertDocumentType, buildDocumentRows, buildFileFieldTables, buildFileFieldTablesFromInstances, categoriesAttestingFact, categoryFieldsOf, categoryForField, categorySchemaOf, evaluateExpression, extractTimePeriods, factOf, formatDocumentSize, formatDocumentType, formatDocumentUploaded, generateRHFSchema, generateSurveyJson, getBaseCategories, getBaseFieldNames, getBaseFieldSpecMap, getBaseFieldSpecs, getCategoryName, getDisplayName, getDisplayNames, getDocDisplayNames, getDocumentTypeGroups, getExtractableDocTypes, getGroupDisplayNames, getPastMonthLabel, getPastYearLabel, getReuploadableDocTypes, getStepDefaultValues, getStepSchema, groupColumnsByInstance, groupColumnsByTimePeriod, groupDetailsByCategory, groupFieldsByCategory, groupFieldsByPattern, isAdapterCategory, isDocumentType, isFailureIhsStatus, isTerminalIhsStatus, isValidIhsFieldOrigin, isValidIhsStatus, parseFileField, processIhsDetails, resolveExtractionStatus, resolvePageFields, validateFormConfig, validateFormSpec, validatePagesConfig };
package/dist/index.d.ts CHANGED
@@ -842,6 +842,35 @@ interface CanonicalFieldSpec {
842
842
  readonly unit?: string;
843
843
  readonly range?: readonly [number, number];
844
844
  readonly description: string;
845
+ /**
846
+ * Global fact identifier marking this field as an ATTESTATION of a
847
+ * shared real-world fact (e.g. a company has exactly one
848
+ * incorporation date, no matter which document it was extracted
849
+ * from). Multiple categories may declare the SAME field name iff
850
+ * every declaring category carries the same `fact` id — each
851
+ * category's value is then an independent attestation of one fact,
852
+ * comparable across sources (the future disagreement-comparison
853
+ * feature's unit of comparison). A `fact` id is bound to exactly one
854
+ * field name registry-wide; by convention the field name IS the fact
855
+ * id. Uniquely-declared fields need no `fact` (but may carry one).
856
+ */
857
+ readonly fact?: string;
858
+ /**
859
+ * Field kind — a semantic refinement of `type`. Currently the only
860
+ * kind is `"enum"`: the field's value is one label out of a closed
861
+ * set. The category declares ONLY that the field is enumerated —
862
+ * never the values, never an ordering. Value sets are vendor
863
+ * territory: each adapter declares the exact labels it emits in its
864
+ * manifest's `enumValues` (host-validated), because two vendors
865
+ * implementing the same category may bucket differently. Ordering
866
+ * and scoring interpretation live even further out, in the consumer
867
+ * (an eval model's per-value mapping) — an enum label is data, what
868
+ * it is worth is opinion, and opinions don't belong in the data
869
+ * contract. An enum field MUST be `type: "string"` (labels are
870
+ * string-normalized) and MUST NOT declare a `range` (labels are
871
+ * unordered).
872
+ */
873
+ readonly kind?: "enum";
845
874
  }
846
875
  /**
847
876
  * Per-category schema bundle. Used by:
@@ -883,11 +912,30 @@ declare function allCategories(): ReadonlyArray<CategorySchema>;
883
912
  /**
884
913
  * Reverse lookup: which category declares a given canonical field?
885
914
  * Returns null if the field name isn't declared by any category in
886
- * this version of finsys-core. Useful when the host app is reading
887
- * canonical field values back from storage + wants to identify the
888
- * producing category for rendering. O(1).
915
+ * this version of finsys-core AND for shared-fact names (declared by
916
+ * more than one category), where "the" category is genuinely ambiguous.
917
+ * The null is deliberate: a caller holding a shared-fact name must
918
+ * decide per-attestation, via `categoriesAttestingFact(factOf(name))`,
919
+ * rather than being handed one arbitrary declarer. Useful when the
920
+ * host app is reading canonical field values back from storage + wants
921
+ * to identify the producing category for rendering. O(1).
889
922
  */
890
923
  declare function categoryForField(field: CanonicalFieldName): AdapterCategory | null;
924
+ /**
925
+ * The fact id a canonical field attests, or null when the field
926
+ * declares no fact (or isn't declared at all). By convention the fact
927
+ * id equals the field name, but callers must not assume it — read it
928
+ * from here. O(1).
929
+ */
930
+ declare function factOf(field: CanonicalFieldName): string | null;
931
+ /**
932
+ * Every category attesting a given shared fact, in data-file order.
933
+ * Empty for an unknown fact id. This is the lookup the disagreement-
934
+ * comparison feature keys on: each attesting category's value for the
935
+ * fact's field is an independent observation of the same real-world
936
+ * fact, so cross-category mismatches are surfaceable.
937
+ */
938
+ declare function categoriesAttestingFact(factId: string): ReadonlyArray<AdapterCategory>;
891
939
  /**
892
940
  * Runtime membership check — is `id` a category declared by this
893
941
  * version of finsys-core? Use this at trust boundaries (parsing a
@@ -1597,6 +1645,34 @@ interface AdapterManifest {
1597
1645
  * adapter is implemented.
1598
1646
  */
1599
1647
  readonly periods?: ReadonlyArray<PeriodDeclaration>;
1648
+ /**
1649
+ * Vendor-specific value sets for the enum-kind fields this adapter
1650
+ * produces. The category declares only THAT a field is enumerated
1651
+ * (`kind: "enum"` — no values, no ordering); the manifest declares
1652
+ * exactly WHICH labels this vendor emits, because two vendors
1653
+ * implementing the same category may bucket differently. Scoring
1654
+ * interpretation lives further out still, in the consumer (an eval
1655
+ * model's per-value mapping with a mandatory fallback) — never here.
1656
+ *
1657
+ * Host-validated at registration (same posture as `produces` ⊆
1658
+ * category fields):
1659
+ * - every key MUST appear in `produces`;
1660
+ * - every key MUST be declared `kind: "enum"` by the adapter's
1661
+ * category — a non-enum field with declared values is refused;
1662
+ * - every enum-kind field in `produces` MUST have an entry here —
1663
+ * an adapter that promises an enum field but not its labels
1664
+ * gives clients nothing to render or map against;
1665
+ * - each value set is a non-empty array of unique, string-
1666
+ * normalized labels (non-empty, no leading/trailing whitespace).
1667
+ *
1668
+ * At runtime the adapter emits labels from its declared set
1669
+ * VERBATIM; the host refuses out-of-set values at ingest, so a
1670
+ * vendor-side vocabulary change is a loud manifest-version bump,
1671
+ * never silent data drift. Clients (form-spec and eval-model
1672
+ * editors) read these sets through the registry-metadata surface to
1673
+ * offer the labels without hardcoding any vendor's vocabulary.
1674
+ */
1675
+ readonly enumValues?: Readonly<Record<CanonicalFieldName, ReadonlyArray<string>>>;
1600
1676
  /**
1601
1677
  * Optional free-form notes — useful for partner-side documentation
1602
1678
  * (where to find the adapter's source, who owns it, what version of
@@ -1740,4 +1816,4 @@ interface FieldMapEntry {
1740
1816
  readonly transform?: "identity" | "pct_to_ratio01" | "to_boolean" | "to_integer";
1741
1817
  }
1742
1818
 
1743
- export { ADAPTER_CATEGORY_IDS, ALL_AGGREGATION_OPS, type AdapterCategory, AdapterError, type AdapterErrorReason, type AdapterExtraction, type AdapterManifest, type AggregationOp, type ApplicantIdentity, BASE_FIELD_SPECS, BasicFormField, type CanonicalFieldName, type CanonicalFieldSpec, type CanonicalFieldValue, type CanonicalFieldValues, type Category, type CategorySchema, type CategorySpec, type Choice, DEFAULT_VALIDATOR_DEFINITIONS, type DeclarativeImplementation, type DocExtractionResult, DocExtractionStatus, type DocumentFileMetadata, type DocumentRow, type DocumentRowCapabilities, type DocumentTypeGroup, type DropdownOption, type EditorValidator, type ExtractionFileType, type ExtractionJobRecord, ExtractionJobStatus, type ExtractionPipelineImplementation, type ExtractionStatusResult, FIELD_TYPE_DEFINITIONS, type FieldAuthorization, type FieldData, type FieldGroup, type FieldMapEntry, type FieldReference, FieldType, type FileFieldTableData, type FileFieldTableItem, FileFieldTableType, FileFormField, FormField, FormFieldCategory, type FormFieldInputType, type FormFieldType, type FormFieldTypeDefinitions, FormFieldValidator, type FormIntakeFieldMapEntry, type FormIntakeImplementation, FormSpec, type FormValidatorDefinitions, IHS_FAILURE_STATUSES, IHS_FIELD_ORIGINS, IHS_TERMINAL_STATUSES, IHS_VALID_STATUSES, type IhsDetailCategory, type IhsFieldDetail, type IhsFieldOrigin, type IhsFieldProvenance, IhsStatus, IhsValueFormat, type InstanceRow, type InstanceValue, type ManualOverrideImplementation, type PageConfig, type PeriodDeclaration, type PeriodValues, type RHFSchemaOutput, type RHFStep, type RawPayload, type ResolvedField, Role, type SourceAdapter, type SurveyElementJSON, type SurveyJSON, type SurveyPageJSON, type TaggedFieldData, type TimePeriodUnit, type TypescriptImplementation, type UnifiedFormConfig, type Validator, type WireFormat, allCategories, applyAggregation, applyDynamicTitles, assertAdapterCategory, assertDocumentType, buildDocumentRows, buildFileFieldTables, buildFileFieldTablesFromInstances, categoryFieldsOf, categoryForField, categorySchemaOf, evaluateExpression, extractTimePeriods, formatDocumentSize, formatDocumentType, formatDocumentUploaded, generateRHFSchema, generateSurveyJson, getBaseCategories, getBaseFieldNames, getBaseFieldSpecMap, getBaseFieldSpecs, getCategoryName, getDisplayName, getDisplayNames, getDocDisplayNames, getDocumentTypeGroups, getExtractableDocTypes, getGroupDisplayNames, getPastMonthLabel, getPastYearLabel, getReuploadableDocTypes, getStepDefaultValues, getStepSchema, groupColumnsByInstance, groupColumnsByTimePeriod, groupDetailsByCategory, groupFieldsByCategory, groupFieldsByPattern, isAdapterCategory, isDocumentType, isFailureIhsStatus, isTerminalIhsStatus, isValidIhsFieldOrigin, isValidIhsStatus, parseFileField, processIhsDetails, resolveExtractionStatus, resolvePageFields, validateFormConfig, validateFormSpec, validatePagesConfig };
1819
+ export { ADAPTER_CATEGORY_IDS, ALL_AGGREGATION_OPS, type AdapterCategory, AdapterError, type AdapterErrorReason, type AdapterExtraction, type AdapterManifest, type AggregationOp, type ApplicantIdentity, BASE_FIELD_SPECS, BasicFormField, type CanonicalFieldName, type CanonicalFieldSpec, type CanonicalFieldValue, type CanonicalFieldValues, type Category, type CategorySchema, type CategorySpec, type Choice, DEFAULT_VALIDATOR_DEFINITIONS, type DeclarativeImplementation, type DocExtractionResult, DocExtractionStatus, type DocumentFileMetadata, type DocumentRow, type DocumentRowCapabilities, type DocumentTypeGroup, type DropdownOption, type EditorValidator, type ExtractionFileType, type ExtractionJobRecord, ExtractionJobStatus, type ExtractionPipelineImplementation, type ExtractionStatusResult, FIELD_TYPE_DEFINITIONS, type FieldAuthorization, type FieldData, type FieldGroup, type FieldMapEntry, type FieldReference, FieldType, type FileFieldTableData, type FileFieldTableItem, FileFieldTableType, FileFormField, FormField, FormFieldCategory, type FormFieldInputType, type FormFieldType, type FormFieldTypeDefinitions, FormFieldValidator, type FormIntakeFieldMapEntry, type FormIntakeImplementation, FormSpec, type FormValidatorDefinitions, IHS_FAILURE_STATUSES, IHS_FIELD_ORIGINS, IHS_TERMINAL_STATUSES, IHS_VALID_STATUSES, type IhsDetailCategory, type IhsFieldDetail, type IhsFieldOrigin, type IhsFieldProvenance, IhsStatus, IhsValueFormat, type InstanceRow, type InstanceValue, type ManualOverrideImplementation, type PageConfig, type PeriodDeclaration, type PeriodValues, type RHFSchemaOutput, type RHFStep, type RawPayload, type ResolvedField, Role, type SourceAdapter, type SurveyElementJSON, type SurveyJSON, type SurveyPageJSON, type TaggedFieldData, type TimePeriodUnit, type TypescriptImplementation, type UnifiedFormConfig, type Validator, type WireFormat, allCategories, applyAggregation, applyDynamicTitles, assertAdapterCategory, assertDocumentType, buildDocumentRows, buildFileFieldTables, buildFileFieldTablesFromInstances, categoriesAttestingFact, categoryFieldsOf, categoryForField, categorySchemaOf, evaluateExpression, extractTimePeriods, factOf, formatDocumentSize, formatDocumentType, formatDocumentUploaded, generateRHFSchema, generateSurveyJson, getBaseCategories, getBaseFieldNames, getBaseFieldSpecMap, getBaseFieldSpecs, getCategoryName, getDisplayName, getDisplayNames, getDocDisplayNames, getDocumentTypeGroups, getExtractableDocTypes, getGroupDisplayNames, getPastMonthLabel, getPastYearLabel, getReuploadableDocTypes, getStepDefaultValues, getStepSchema, groupColumnsByInstance, groupColumnsByTimePeriod, groupDetailsByCategory, groupFieldsByCategory, groupFieldsByPattern, isAdapterCategory, isDocumentType, isFailureIhsStatus, isTerminalIhsStatus, isValidIhsFieldOrigin, isValidIhsStatus, parseFileField, processIhsDetails, resolveExtractionStatus, resolvePageFields, validateFormConfig, validateFormSpec, validatePagesConfig };
package/dist/index.js CHANGED
@@ -10211,7 +10211,7 @@ function applyAggregation(op, instances) {
10211
10211
 
10212
10212
  // src/data/adapter-categories.json
10213
10213
  var adapter_categories_default = {
10214
- schemaVersion: "1.0.0",
10214
+ schemaVersion: "1.2.0",
10215
10215
  categories: [
10216
10216
  {
10217
10217
  id: "telco-carrier",
@@ -10263,6 +10263,30 @@ var adapter_categories_default = {
10263
10263
  unit: "MYR",
10264
10264
  range: [0, 1e4],
10265
10265
  description: "Average Revenue Per User (monthly) in Malaysian Ringgit. Coarse spending-capacity proxy."
10266
+ },
10267
+ {
10268
+ name: "telcoPaymentReliabilityTier",
10269
+ type: "string",
10270
+ kind: "enum",
10271
+ description: "Coarse bill-payment reliability bucket, for partners that return a tier label instead of a continuous ratio. Parallel signal to telcoOnTimePaymentRatio24m. Labels are vendor-declared (see the adapter manifest's enumValues); ordering and scoring live in the consumer's per-value mapping."
10272
+ },
10273
+ {
10274
+ name: "telcoTenureTier",
10275
+ type: "string",
10276
+ kind: "enum",
10277
+ description: "Coarse account-age bucket, for partners that return a tenure tier label instead of a continuous month count. Parallel signal to telcoTenureMonths. Labels are vendor-declared (see the adapter manifest's enumValues)."
10278
+ },
10279
+ {
10280
+ name: "telcoDistressTier",
10281
+ type: "string",
10282
+ kind: "enum",
10283
+ description: "Coarse account-distress bucket, for partners that return a distress tier label instead of discrete counts. Parallel signal to telcoSuspensionsCount24m / telcoLateDays24m. Labels are vendor-declared (see the adapter manifest's enumValues)."
10284
+ },
10285
+ {
10286
+ name: "telcoHandsetRiskTier",
10287
+ type: "string",
10288
+ kind: "enum",
10289
+ description: "Coarse handset-financing risk bucket, for partners that return a tier label instead of the discrete handset flags. Parallel signal to telcoHandsetFinancingActive / telcoHandsetFinancingDelinquent. Labels are vendor-declared (see the adapter manifest's enumValues)."
10266
10290
  }
10267
10291
  ]
10268
10292
  },
@@ -10865,7 +10889,8 @@ var adapter_categories_default = {
10865
10889
  {
10866
10890
  name: "companyName",
10867
10891
  type: "string",
10868
- description: "Company name as stated on the document."
10892
+ fact: "companyName",
10893
+ description: "Company name as stated on the document. Attestation of the shared companyName fact \u2014 the SSM Form 9 extraction category attests the same fact from its own document."
10869
10894
  },
10870
10895
  {
10871
10896
  name: "financialYearEnd",
@@ -11584,6 +11609,121 @@ var adapter_categories_default = {
11584
11609
  description: "Cash-flow statement: cash and cash equivalents at the end of the financial year."
11585
11610
  }
11586
11611
  ]
11612
+ },
11613
+ {
11614
+ id: "finxtract-form9",
11615
+ displayName: "SSM Form 9 (Document Extraction)",
11616
+ description: "Fields extracted from an uploaded SSM Form 9 (Certificate of Incorporation of Private Company) document by the host's extraction pipeline. One instance per uploaded document. The company name and incorporation date are attestations of shared facts \u2014 the company-profile and financial-statement extraction categories attest the same real-world facts from their own documents.",
11617
+ canonicalTable: "ihs_alt_data_form9",
11618
+ fields: [
11619
+ {
11620
+ name: "companyName",
11621
+ type: "string",
11622
+ fact: "companyName",
11623
+ description: "Company name as printed on the certificate. Attestation of the shared companyName fact."
11624
+ },
11625
+ {
11626
+ name: "companyRegNo",
11627
+ type: "string",
11628
+ description: "Company registration number as printed on the certificate."
11629
+ },
11630
+ {
11631
+ name: "companyIncorporationDate",
11632
+ type: "string",
11633
+ fact: "companyIncorporationDate",
11634
+ description: "Date of incorporation as printed on the certificate, normalized to ISO YYYY-MM-DD. Attestation of the shared companyIncorporationDate fact \u2014 a company has exactly one incorporation date regardless of which document it was extracted from."
11635
+ }
11636
+ ]
11637
+ },
11638
+ {
11639
+ id: "finxtract-ssm",
11640
+ displayName: "SSM Company Profile (Document Extraction)",
11641
+ description: "Fields extracted from an uploaded SSM company-profile document (company or business registration extract) by the host's extraction pipeline. One instance per uploaded document. Covers registration identity, status, key dates, registered address, capital, and the officer/shareholder registers. The incorporation date is an attestation of a shared fact \u2014 the Form 9 extraction category attests the same real-world fact from its own document.",
11642
+ canonicalTable: "ihs_alt_data_ssm",
11643
+ fields: [
11644
+ {
11645
+ name: "ssmCompanyEntityType",
11646
+ type: "string",
11647
+ description: "Entity type stated on the profile (e.g. private limited company, enterprise)."
11648
+ },
11649
+ {
11650
+ name: "ssmCompanyName",
11651
+ type: "string",
11652
+ description: "Business or company name as stated on the profile."
11653
+ },
11654
+ {
11655
+ name: "ssmCompanyRegNo",
11656
+ type: "string",
11657
+ description: "Business or company registration number as stated on the profile."
11658
+ },
11659
+ {
11660
+ name: "companyStatus",
11661
+ type: "string",
11662
+ description: "Registration status as stated on the profile (e.g. existing, dissolved)."
11663
+ },
11664
+ {
11665
+ name: "businessOrigin",
11666
+ type: "string",
11667
+ description: "Business origin as stated on the profile."
11668
+ },
11669
+ {
11670
+ name: "companyIncorporationDate",
11671
+ type: "string",
11672
+ fact: "companyIncorporationDate",
11673
+ description: "Incorporation (or registration) date as stated on the profile, normalized to ISO YYYY-MM-DD. Attestation of the shared companyIncorporationDate fact \u2014 a company has exactly one incorporation date regardless of which document it was extracted from."
11674
+ },
11675
+ {
11676
+ name: "businessCommencementDate",
11677
+ type: "string",
11678
+ description: "Business commencement (or start) date as stated on the profile, normalized to ISO YYYY-MM-DD."
11679
+ },
11680
+ {
11681
+ name: "businessNature",
11682
+ type: "string",
11683
+ description: "Nature of business as stated on the profile."
11684
+ },
11685
+ {
11686
+ name: "registeredAddress",
11687
+ type: "string",
11688
+ description: "Registered business address as stated on the profile."
11689
+ },
11690
+ {
11691
+ name: "totalShareIssued",
11692
+ type: "number",
11693
+ description: "Total shares issued as stated on the profile."
11694
+ },
11695
+ {
11696
+ name: "ssmPaidUpCapital",
11697
+ type: "number",
11698
+ unit: "MYR",
11699
+ description: "Paid-up capital as stated on the profile (falls back to total shares issued when the profile omits an explicit paid-up figure)."
11700
+ },
11701
+ {
11702
+ name: "directors",
11703
+ type: "string",
11704
+ description: "JSON-encoded list of current directors/officers (for enterprises, the business owner normalized into the same shape)."
11705
+ },
11706
+ {
11707
+ name: "shareholders",
11708
+ type: "string",
11709
+ description: "JSON-encoded list of shareholders (for enterprises, the business owner normalized into the same shape)."
11710
+ },
11711
+ {
11712
+ name: "previousDirectors",
11713
+ type: "string",
11714
+ description: "JSON-encoded list of previous directors/officers."
11715
+ },
11716
+ {
11717
+ name: "companyLastOldName",
11718
+ type: "string",
11719
+ description: "The company's most recent former name, when the profile records a name change."
11720
+ },
11721
+ {
11722
+ name: "companyNameDateOfChange",
11723
+ type: "string",
11724
+ description: "Date of the most recent name change, normalized to ISO YYYY-MM-DD."
11725
+ }
11726
+ ]
11587
11727
  }
11588
11728
  ]
11589
11729
  };
@@ -11594,6 +11734,7 @@ var VALID_FIELD_TYPES = [
11594
11734
  "boolean",
11595
11735
  "string"
11596
11736
  ];
11737
+ var VALID_FIELD_KINDS = ["enum"];
11597
11738
  function buildCategoryRegistry(raw) {
11598
11739
  if (!raw || typeof raw !== "object") {
11599
11740
  throw new Error("adapter category data: expected an object");
@@ -11606,6 +11747,9 @@ function buildCategoryRegistry(raw) {
11606
11747
  }
11607
11748
  const byId = /* @__PURE__ */ new Map();
11608
11749
  const fieldToCategory = /* @__PURE__ */ new Map();
11750
+ const fieldToFact = /* @__PURE__ */ new Map();
11751
+ const factToCategories = /* @__PURE__ */ new Map();
11752
+ const declarations = /* @__PURE__ */ new Map();
11609
11753
  const tables = /* @__PURE__ */ new Set();
11610
11754
  const all = [];
11611
11755
  for (const cat of raw.categories) {
@@ -11640,16 +11784,62 @@ function buildCategoryRegistry(raw) {
11640
11784
  if (typeof f.name !== "string" || f.name.length === 0) {
11641
11785
  throw new Error(`adapter category data: ${where} has a field with no name`);
11642
11786
  }
11643
- if (fieldToCategory.has(f.name)) {
11787
+ if (f.fact !== void 0 && (typeof f.fact !== "string" || f.fact.length === 0)) {
11644
11788
  throw new Error(
11645
- `adapter category data: canonical field "${f.name}" declared by more than one category (${fieldToCategory.get(f.name)} + ${cat.id}) \u2014 field names must be globally unique`
11789
+ `adapter category data: field "${f.name}" (${where}) has an invalid fact \u2014 expected a non-empty string`
11646
11790
  );
11647
11791
  }
11792
+ const prior = declarations.get(f.name);
11793
+ if (prior) {
11794
+ if (prior.categories.includes(cat.id)) {
11795
+ throw new Error(
11796
+ `adapter category data: ${where} declares field "${f.name}" more than once`
11797
+ );
11798
+ }
11799
+ if (prior.fact === void 0 || f.fact === void 0 || prior.fact !== f.fact) {
11800
+ const describeFact = (fact) => fact === void 0 ? "no fact" : `fact "${fact}"`;
11801
+ throw new Error(
11802
+ `adapter category data: canonical field "${f.name}" declared by more than one category (${prior.categories.join(" + ")} with ${describeFact(prior.fact)} + ${cat.id} with ${describeFact(f.fact)}) \u2014 field names must be globally unique unless every declaring category attests the same fact`
11803
+ );
11804
+ }
11805
+ if (prior.kind !== f.kind) {
11806
+ const describeKind = (kind) => kind === void 0 ? "no kind" : `kind "${kind}"`;
11807
+ throw new Error(
11808
+ `adapter category data: canonical field "${f.name}" declared with ${describeKind(prior.kind)} by ${prior.categories.join(" + ")} but ${describeKind(f.kind)} by ${cat.id} \u2014 shared-fact attestations must agree on kind`
11809
+ );
11810
+ }
11811
+ }
11812
+ if (f.fact !== void 0) {
11813
+ for (const [otherName, otherFact] of fieldToFact) {
11814
+ if (otherFact === f.fact && otherName !== f.name) {
11815
+ throw new Error(
11816
+ `adapter category data: fact "${f.fact}" is carried by two different field names ("${otherName}" + "${f.name}") \u2014 a fact id must map to exactly one canonical field name`
11817
+ );
11818
+ }
11819
+ }
11820
+ }
11648
11821
  if (!VALID_FIELD_TYPES.includes(f.type)) {
11649
11822
  throw new Error(
11650
11823
  `adapter category data: field "${f.name}" (${where}) has invalid type "${f.type}"`
11651
11824
  );
11652
11825
  }
11826
+ if (f.kind !== void 0) {
11827
+ if (!VALID_FIELD_KINDS.includes(f.kind)) {
11828
+ throw new Error(
11829
+ `adapter category data: field "${f.name}" (${where}) has invalid kind "${String(f.kind)}"`
11830
+ );
11831
+ }
11832
+ if (f.type !== "string") {
11833
+ throw new Error(
11834
+ `adapter category data: field "${f.name}" (${where}) is kind "enum" but type "${f.type}" \u2014 enum labels are string-normalized, so an enum field must be type "string"`
11835
+ );
11836
+ }
11837
+ if (f.range !== void 0) {
11838
+ throw new Error(
11839
+ `adapter category data: field "${f.name}" (${where}) is kind "enum" but declares a range \u2014 enum labels are unordered; ordering belongs to the consumer, never the data contract`
11840
+ );
11841
+ }
11842
+ }
11653
11843
  if (typeof f.description !== "string" || f.description.length === 0) {
11654
11844
  throw new Error(
11655
11845
  `adapter category data: field "${f.name}" (${where}) needs a non-empty description`
@@ -11667,10 +11857,27 @@ function buildCategoryRegistry(raw) {
11667
11857
  type: f.type,
11668
11858
  ...f.unit !== void 0 ? { unit: f.unit } : {},
11669
11859
  ...f.range !== void 0 ? { range: Object.freeze([f.range[0], f.range[1]]) } : {},
11670
- description: f.description
11860
+ description: f.description,
11861
+ ...f.fact !== void 0 ? { fact: f.fact } : {},
11862
+ ...f.kind !== void 0 ? { kind: f.kind } : {}
11671
11863
  });
11672
11864
  fields.push(spec);
11673
- fieldToCategory.set(f.name, cat.id);
11865
+ if (prior) {
11866
+ prior.categories.push(cat.id);
11867
+ fieldToCategory.delete(f.name);
11868
+ } else {
11869
+ declarations.set(f.name, { fact: f.fact, kind: f.kind, categories: [cat.id] });
11870
+ fieldToCategory.set(f.name, cat.id);
11871
+ }
11872
+ if (f.fact !== void 0) {
11873
+ fieldToFact.set(f.name, f.fact);
11874
+ const attesters = factToCategories.get(f.fact);
11875
+ if (attesters) {
11876
+ attesters.push(cat.id);
11877
+ } else {
11878
+ factToCategories.set(f.fact, [cat.id]);
11879
+ }
11880
+ }
11674
11881
  }
11675
11882
  const schema = Object.freeze({
11676
11883
  id: cat.id,
@@ -11687,7 +11894,14 @@ function buildCategoryRegistry(raw) {
11687
11894
  all: Object.freeze(all),
11688
11895
  ids: Object.freeze(all.map((c) => c.id)),
11689
11896
  byId,
11690
- fieldToCategory
11897
+ fieldToCategory,
11898
+ fieldToFact,
11899
+ factToCategories: new Map(
11900
+ [...factToCategories].map(([fact, cats]) => [
11901
+ fact,
11902
+ Object.freeze(cats)
11903
+ ])
11904
+ )
11691
11905
  });
11692
11906
  }
11693
11907
  var registry = buildCategoryRegistry(adapter_categories_default);
@@ -11710,6 +11924,12 @@ function allCategories() {
11710
11924
  function categoryForField(field) {
11711
11925
  return registry.fieldToCategory.get(field) ?? null;
11712
11926
  }
11927
+ function factOf(field) {
11928
+ return registry.fieldToFact.get(field) ?? null;
11929
+ }
11930
+ function categoriesAttestingFact(factId) {
11931
+ return registry.factToCategories.get(factId) ?? [];
11932
+ }
11713
11933
  function isAdapterCategory(id) {
11714
11934
  return registry.byId.has(id);
11715
11935
  }
@@ -11753,11 +11973,13 @@ export {
11753
11973
  buildDocumentRows,
11754
11974
  buildFileFieldTables,
11755
11975
  buildFileFieldTablesFromInstances,
11976
+ categoriesAttestingFact,
11756
11977
  categoryFieldsOf,
11757
11978
  categoryForField,
11758
11979
  categorySchemaOf,
11759
11980
  evaluateExpression,
11760
11981
  extractTimePeriods,
11982
+ factOf,
11761
11983
  formatDocumentSize,
11762
11984
  formatDocumentType,
11763
11985
  formatDocumentUploaded,