/** * Schema-mapping producer profile — EVIDENCED-ONTOLOGY layer. * * Every other semantic-layer mapping is unaudited config. Here every mapping * shows its work: proposals carry schema-doc evidence, confidence, and * rationale; they flow through Survey's candidate → review machinery before * any mapping is accepted. Nothing here silently decides (ADR 0003 §4). * * The wedge: in every other semantic layer the mapping is unaudited config; * here every mapping shows its work. * * Integration pattern: * 1. Call surveySchemaMapping(context, extractor, options) to produce a * SurveyInput from two or more system schemas. * 2. Review the CandidateSets (kind: "needs-review" or "conflict"). * 3. Call mappingReviewToSurface(reviewedMappings) to project accepted * mappings into a TrustBundle where each accepted mapping is BOTH: * (a) a Claim (subjectType "system-field", fieldOrBehavior "maps-to") * (b) an IdentityLink with relation/conversion and mappingClaimId * so that resolveInquiry can resolve across systems with weakest-link * capping. */ import type { TrustBundle } from "@kontourai/surface"; import type { AutoAcceptWarning } from "./producer-profile.js"; import type { Candidate, CandidateSet, ReviewOutcome, SurveyInput } from "./types.js"; /** * A stable reference to one field within one system's schema. */ export interface SystemFieldRef { /** The system identifier (e.g. "crm", "erp", "salesforce"). */ system: string; /** The entity/table/resource name within that system. */ entity: string; /** The field/column/attribute name within that entity. */ field: string; /** * Optional structural locator within a schema document (e.g. * "json:$.definitions.Contact.properties.phoneNumber"). */ locator?: string; } /** * A proposed link between two SystemFieldRefs, with evidence from schema * documents or profiling output. * * This is the "show your work" record: every mapping carries excerpts from * the relevant schema docs, a confidence score, a rationale, and the name * of the extractor that produced the proposal. Nothing is accepted until * it flows through review. */ export interface MappingProposalRecord { id: string; /** The source field being mapped. */ sourceField: SystemFieldRef; /** The target field being mapped. */ targetField: SystemFieldRef; /** * Semantic relation between the two fields. * "equivalent" — same real-world fact, same unit. * "subsumes" — the source field contains / is a superset of the target. * "converts" — related by a numeric unit/scale conversion; supply conversion. */ relation: "equivalent" | "subsumes" | "converts"; /** * Numeric conversion parameters. Only meaningful when relation = "converts". * target_value = source_value * factor + offset */ conversion?: { factor?: number; offset?: number; note?: string; }; /** * Schema document excerpts that support the proposal. * One entry per system that the extractor consulted. */ evidence: Array<{ system: string; excerpt: string; }>; /** Extractor confidence in the mapping (0–1). */ confidence: number; /** Human-readable rationale for the proposal. */ rationale: string; /** Name of the SchemaMappingExtractor that produced this proposal. */ proposedBy: string; /** ISO 8601 timestamp. */ proposedAt: string; } /** * Pluggable interface for proposing field mappings across system schemas. * * Implementations may be deterministic (like referenceSchemaExtractor below), * embedding-based, or LLM-backed — but they are always proposers: their output * carries full provenance and goes through review before it counts. * * Supports both synchronous and async implementations. */ export interface SchemaMappingExtractor { name: string; extract(context: { systems: Array<{ system: string; schemaText: string; }>; }): MappingProposalRecord[] | Promise; } export interface SchemaMappingOptions { /** * If set, proposals at or above this confidence threshold are auto-accepted * as "assumed" (mirrors applyAutoAcceptPolicy in inquiry-mapping). * Conflicting proposals are never auto-accepted. * * Experimental: the gate trusts the proposer's self-reported confidence. * Must be a finite number in (0, 1] (otherwise `RangeError`); a proposal * whose confidence is not a finite number in [0, 1] is never auto-accepted. */ autoAcceptMinConfidence?: number; /** ISO 8601 timestamp; defaults to new Date().toISOString(). */ generatedAt?: string; /** Identifies the Survey producer run. */ source?: string; } /** * The schema-mapping profile's own payload, carried verbatim under the core's * canonical `Candidate.metadata` key (see `./producer-profile.js`). Covers * every field read across `mappingReviewToSurface`'s read-back sites and * written at Candidate-projection time below. */ /** * The value a schema-mapping candidate and its claim carry: the whole mapping, * source field included, so a reviewed claim's value is exactly the reviewed * candidate value. */ export type SchemaMappingValue = Pick; /** * Run the extractor against the provided system schemas and project the * resulting proposals into the standard Survey chain: * * RawSource (kind "system-schema") per system * → Extraction per proposal * → Candidate per proposal * → CandidateSet per field pair * status "conflict" when proposals disagree about the same field pair * status "needs-review" otherwise * * If options.autoAcceptMinConfidence is set, non-conflicting proposals above * the threshold gain a ReviewOutcome with status "assumed". * * The returned SurveyInput is ready for buildSurveyTrustBundle (for provenance * storage) or for mappingReviewToSurface after human review. */ export declare function surveySchemaMapping(context: { systems: Array<{ system: string; schemaText: string; }>; }, extractor: SchemaMappingExtractor, options?: SchemaMappingOptions): Promise<{ surveyInput: SurveyInput; proposals: MappingProposalRecord[]; candidateSets: CandidateSet[]; /** * Proposals the auto-accept policy refused because their confidence is not * a finite number in [0, 1]. Present only when non-empty; those proposals * stay in human review. */ autoAcceptWarnings?: AutoAcceptWarning[]; }>; /** * A reviewed (accepted or rejected) mapping record: the CandidateSet, the * selected candidate, and the review outcome. */ export interface ReviewedMapping { pairKey: string; candidateSet: CandidateSet; /** The selected candidate (winner of review). */ selectedCandidate: Candidate; reviewOutcome: ReviewOutcome; /** Original proposal record. */ proposal: MappingProposalRecord; } /** * Project reviewed (accepted) mappings into a TrustBundle. * * For each accepted mapping, the bundle contains BOTH: * (a) a Claim: subjectType "system-field", fieldOrBehavior "maps-to" * whose status reflects the review outcome; disputing this claim caps * the identity-link answer via weakest-link (see mappingClaimId). * (b) an IdentityLink: links the source and target system-field subjects * with relation/conversion, and sets mappingClaimId to the claim id. * * This means resolveInquiry can traverse the link when asked about system B's * field while only system A's claim exists in the bundle, with the mapping * claim's status as the weakest-link ceiling. * * Rejected mappings are omitted from the bundle (but can be retained for * audit by calling buildSurveyTrustBundle on the original SurveyInput). */ export declare function mappingReviewToSurface(reviewedMappings: ReviewedMapping[], options?: { source?: string; generatedAt?: string; }): TrustBundle; /** * Reference SchemaMappingExtractor for tests. * * REFERENCE IMPLEMENTATION ONLY — not suitable for production matching. * * Matching strategy: two fields are proposed as "equivalent" when they share * the same field name (case-insensitive) and the same inferred type token * ("string", "number", "boolean", "date", or absent) across two system schemas. * * Schema text format expected by this reference extractor: * Each non-empty line is: ".[:]" * e.g. "Contact.email:string" or "Account.revenue:number" * * This format is intentionally simple and transparent so tests can be * deterministic without depending on any schema parsing library. */ export declare const referenceSchemaExtractor: SchemaMappingExtractor;