@the-cascade-protocol/cli 0.2.4 → 0.3.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.
Files changed (78) hide show
  1. package/dist/commands/convert.d.ts +8 -5
  2. package/dist/commands/convert.d.ts.map +1 -1
  3. package/dist/commands/convert.js +55 -7
  4. package/dist/commands/convert.js.map +1 -1
  5. package/dist/commands/pod/helpers.d.ts +2 -0
  6. package/dist/commands/pod/helpers.d.ts.map +1 -1
  7. package/dist/commands/pod/helpers.js +62 -1
  8. package/dist/commands/pod/helpers.js.map +1 -1
  9. package/dist/commands/pod/import.d.ts +20 -0
  10. package/dist/commands/pod/import.d.ts.map +1 -0
  11. package/dist/commands/pod/import.js +382 -0
  12. package/dist/commands/pod/import.js.map +1 -0
  13. package/dist/commands/pod/index.d.ts.map +1 -1
  14. package/dist/commands/pod/index.js +2 -0
  15. package/dist/commands/pod/index.js.map +1 -1
  16. package/dist/commands/reconcile.d.ts +32 -0
  17. package/dist/commands/reconcile.d.ts.map +1 -0
  18. package/dist/commands/reconcile.js +116 -0
  19. package/dist/commands/reconcile.js.map +1 -0
  20. package/dist/index.js +5 -3
  21. package/dist/index.js.map +1 -1
  22. package/dist/lib/fhir-converter/cascade-to-fhir-admin.d.ts +13 -0
  23. package/dist/lib/fhir-converter/cascade-to-fhir-admin.d.ts.map +1 -0
  24. package/dist/lib/fhir-converter/cascade-to-fhir-admin.js +70 -0
  25. package/dist/lib/fhir-converter/cascade-to-fhir-admin.js.map +1 -0
  26. package/dist/lib/fhir-converter/cascade-to-fhir-clinical.d.ts +36 -0
  27. package/dist/lib/fhir-converter/cascade-to-fhir-clinical.d.ts.map +1 -0
  28. package/dist/lib/fhir-converter/cascade-to-fhir-clinical.js +407 -0
  29. package/dist/lib/fhir-converter/cascade-to-fhir-clinical.js.map +1 -0
  30. package/dist/lib/fhir-converter/cascade-to-fhir-demographics.d.ts +15 -0
  31. package/dist/lib/fhir-converter/cascade-to-fhir-demographics.d.ts.map +1 -0
  32. package/dist/lib/fhir-converter/cascade-to-fhir-demographics.js +115 -0
  33. package/dist/lib/fhir-converter/cascade-to-fhir-demographics.js.map +1 -0
  34. package/dist/lib/fhir-converter/cascade-to-fhir.d.ts +9 -3
  35. package/dist/lib/fhir-converter/cascade-to-fhir.d.ts.map +1 -1
  36. package/dist/lib/fhir-converter/cascade-to-fhir.js +69 -290
  37. package/dist/lib/fhir-converter/cascade-to-fhir.js.map +1 -1
  38. package/dist/lib/fhir-converter/converters-clinical-admin.d.ts +16 -0
  39. package/dist/lib/fhir-converter/converters-clinical-admin.d.ts.map +1 -0
  40. package/dist/lib/fhir-converter/converters-clinical-admin.js +166 -0
  41. package/dist/lib/fhir-converter/converters-clinical-admin.js.map +1 -0
  42. package/dist/lib/fhir-converter/converters-clinical.d.ts +28 -0
  43. package/dist/lib/fhir-converter/converters-clinical.d.ts.map +1 -1
  44. package/dist/lib/fhir-converter/converters-clinical.js +436 -11
  45. package/dist/lib/fhir-converter/converters-clinical.js.map +1 -1
  46. package/dist/lib/fhir-converter/converters-demographics.d.ts.map +1 -1
  47. package/dist/lib/fhir-converter/converters-demographics.js +4 -5
  48. package/dist/lib/fhir-converter/converters-demographics.js.map +1 -1
  49. package/dist/lib/fhir-converter/converters-passthrough.d.ts +29 -0
  50. package/dist/lib/fhir-converter/converters-passthrough.d.ts.map +1 -0
  51. package/dist/lib/fhir-converter/converters-passthrough.js +86 -0
  52. package/dist/lib/fhir-converter/converters-passthrough.js.map +1 -0
  53. package/dist/lib/fhir-converter/fhir-to-cascade.d.ts +8 -4
  54. package/dist/lib/fhir-converter/fhir-to-cascade.d.ts.map +1 -1
  55. package/dist/lib/fhir-converter/fhir-to-cascade.js +41 -10
  56. package/dist/lib/fhir-converter/fhir-to-cascade.js.map +1 -1
  57. package/dist/lib/fhir-converter/import-manifest.d.ts +40 -0
  58. package/dist/lib/fhir-converter/import-manifest.d.ts.map +1 -0
  59. package/dist/lib/fhir-converter/import-manifest.js +66 -0
  60. package/dist/lib/fhir-converter/import-manifest.js.map +1 -0
  61. package/dist/lib/fhir-converter/index.d.ts +33 -13
  62. package/dist/lib/fhir-converter/index.d.ts.map +1 -1
  63. package/dist/lib/fhir-converter/index.js +53 -17
  64. package/dist/lib/fhir-converter/index.js.map +1 -1
  65. package/dist/lib/fhir-converter/types.d.ts +12 -1
  66. package/dist/lib/fhir-converter/types.d.ts.map +1 -1
  67. package/dist/lib/fhir-converter/types.js +67 -2
  68. package/dist/lib/fhir-converter/types.js.map +1 -1
  69. package/dist/lib/output.d.ts +5 -0
  70. package/dist/lib/output.d.ts.map +1 -1
  71. package/dist/lib/output.js +6 -1
  72. package/dist/lib/output.js.map +1 -1
  73. package/dist/lib/reconciler.d.ts +45 -0
  74. package/dist/lib/reconciler.d.ts.map +1 -0
  75. package/dist/lib/reconciler.js +397 -0
  76. package/dist/lib/reconciler.js.map +1 -0
  77. package/dist/shapes/checkup.shapes.ttl +10 -0
  78. package/package.json +1 -1
@@ -0,0 +1,397 @@
1
+ /**
2
+ * Core reconciliation logic extracted from the reconcile command.
3
+ *
4
+ * Exported so that other commands (e.g., pod import) can reuse reconciliation
5
+ * without going through the CLI layer.
6
+ */
7
+ import { Parser, Writer, DataFactory } from 'n3';
8
+ import { NS, TURTLE_PREFIXES } from './fhir-converter/types.js';
9
+ const { namedNode, literal, quad: makeQuad } = DataFactory;
10
+ const KNOWN_TYPES = {
11
+ [NS.health + 'MedicationRecord']: 'health:MedicationRecord',
12
+ [NS.health + 'ConditionRecord']: 'health:ConditionRecord',
13
+ [NS.health + 'AllergyRecord']: 'health:AllergyRecord',
14
+ [NS.health + 'LabResultRecord']: 'health:LabResultRecord',
15
+ [NS.health + 'ImmunizationRecord']: 'health:ImmunizationRecord',
16
+ [NS.clinical + 'VitalSign']: 'clinical:VitalSign',
17
+ [NS.cascade + 'PatientProfile']: 'cascade:PatientProfile',
18
+ [NS.coverage + 'InsurancePlan']: 'coverage:InsurancePlan',
19
+ };
20
+ export async function parseTurtle(turtle, defaultSystem) {
21
+ return new Promise((resolve, reject) => {
22
+ const parser = new Parser({ format: 'Turtle' });
23
+ const bySubject = new Map();
24
+ parser.parse(turtle, (error, quad) => {
25
+ if (error) {
26
+ reject(error);
27
+ return;
28
+ }
29
+ if (!quad) {
30
+ const records = [];
31
+ for (const [uri, triples] of bySubject) {
32
+ const typeTriple = triples.find(t => t.pred === NS.rdf + 'type');
33
+ if (!typeTriple || !KNOWN_TYPES[typeTriple.obj])
34
+ continue;
35
+ const properties = new Map();
36
+ for (const t of triples) {
37
+ const existing = properties.get(t.pred);
38
+ if (existing)
39
+ existing.push(t.obj);
40
+ else
41
+ properties.set(t.pred, [t.obj]);
42
+ }
43
+ const sourceSystem = properties.get(NS.cascade + 'sourceSystem')?.[0] ?? defaultSystem;
44
+ records.push({ uri, type: KNOWN_TYPES[typeTriple.obj], sourceSystem, properties });
45
+ }
46
+ resolve(records);
47
+ return;
48
+ }
49
+ const subj = quad.subject.value;
50
+ if (!bySubject.has(subj))
51
+ bySubject.set(subj, []);
52
+ bySubject.get(subj).push({ pred: quad.predicate.value, obj: quad.object.value });
53
+ });
54
+ });
55
+ }
56
+ // ---------------------------------------------------------------------------
57
+ // Matching helpers
58
+ // ---------------------------------------------------------------------------
59
+ export function normalizeMedName(name) {
60
+ return name.toLowerCase()
61
+ .replace(/\d+(\.\d+)?\s*(mg|mcg|g|ml|%|iu|units?|meq)\b/gi, '')
62
+ .replace(/\b(oral|tablet|capsule|solution|injection|extended|release|er|xr|cr|sr|hr)\b/gi, '')
63
+ .replace(/\s+/g, ' ').trim();
64
+ }
65
+ function normalizeConditionName(name) {
66
+ return name.toLowerCase().replace(/\([^)]*\)/g, '').replace(/\s+/g, ' ').trim();
67
+ }
68
+ function getProp(r, pred) {
69
+ return r.properties.get(pred)?.[0];
70
+ }
71
+ function codeFromUri(uri) {
72
+ return uri.split('/').pop() ?? uri.split('#').pop() ?? uri;
73
+ }
74
+ function dateOnly(dt) { return dt.split('T')[0] ?? dt; }
75
+ function matchMedications(a, b) {
76
+ const rxA = (a.properties.get(NS.health + 'rxNormCode') ?? []).map(codeFromUri);
77
+ const rxB = (b.properties.get(NS.health + 'rxNormCode') ?? []).map(codeFromUri);
78
+ const shared = rxA.find(c => c && rxB.includes(c));
79
+ if (shared)
80
+ return { match: true, confidence: 1.0, matchedOn: `rxnorm:${shared}` };
81
+ const nA = normalizeMedName(getProp(a, NS.health + 'medicationName') ?? '');
82
+ const nB = normalizeMedName(getProp(b, NS.health + 'medicationName') ?? '');
83
+ if (nA && nB && nA === nB)
84
+ return { match: true, confidence: 0.85, matchedOn: `name:"${nA}"` };
85
+ if (nA && nB && (nA.includes(nB) || nB.includes(nA)))
86
+ return { match: true, confidence: 0.70, matchedOn: `partial-name` };
87
+ return { match: false, confidence: 0, matchedOn: '' };
88
+ }
89
+ function matchConditions(a, b) {
90
+ const sA = getProp(a, NS.health + 'snomedCode');
91
+ const sB = getProp(b, NS.health + 'snomedCode');
92
+ if (sA && sB && codeFromUri(sA) === codeFromUri(sB))
93
+ return { match: true, confidence: 1.0, matchedOn: `snomed:${codeFromUri(sA)}` };
94
+ const iA = getProp(a, NS.health + 'icd10Code');
95
+ const iB = getProp(b, NS.health + 'icd10Code');
96
+ if (iA && iB && codeFromUri(iA) === codeFromUri(iB))
97
+ return { match: true, confidence: 0.95, matchedOn: `icd10:${codeFromUri(iA)}` };
98
+ const nA = normalizeConditionName(getProp(a, NS.health + 'conditionName') ?? '');
99
+ const nB = normalizeConditionName(getProp(b, NS.health + 'conditionName') ?? '');
100
+ if (nA && nB && nA === nB)
101
+ return { match: true, confidence: 0.80, matchedOn: `name:"${nA}"` };
102
+ return { match: false, confidence: 0, matchedOn: '' };
103
+ }
104
+ function matchAllergies(a, b) {
105
+ const nA = (getProp(a, NS.health + 'allergen') ?? '').toLowerCase().trim();
106
+ const nB = (getProp(b, NS.health + 'allergen') ?? '').toLowerCase().trim();
107
+ if (nA && nB && nA === nB)
108
+ return { match: true, confidence: 0.90, matchedOn: `allergen:"${nA}"` };
109
+ return { match: false, confidence: 0, matchedOn: '' };
110
+ }
111
+ function matchLabs(a, b, tol) {
112
+ const lA = getProp(a, NS.health + 'testCode');
113
+ const lB = getProp(b, NS.health + 'testCode');
114
+ const dA = dateOnly(getProp(a, NS.health + 'performedDate') ?? '');
115
+ const dB = dateOnly(getProp(b, NS.health + 'performedDate') ?? '');
116
+ const vA = parseFloat(getProp(a, NS.health + 'resultValue') ?? 'NaN');
117
+ const vB = parseFloat(getProp(b, NS.health + 'resultValue') ?? 'NaN');
118
+ const sameDay = dA && dB && dA === dB;
119
+ const sameLoinc = lA && lB && codeFromUri(lA) === codeFromUri(lB);
120
+ if (sameLoinc && sameDay) {
121
+ if (!isNaN(vA) && !isNaN(vB)) {
122
+ const diff = Math.abs(vA - vB) / Math.max(Math.abs(vA), 0.001);
123
+ const conf = diff <= tol ? (diff === 0 ? 1.0 : 0.90) : 0.85;
124
+ return { match: true, confidence: conf, matchedOn: `loinc:${codeFromUri(lA)}+${dA}` };
125
+ }
126
+ return { match: true, confidence: 0.90, matchedOn: `loinc:${codeFromUri(lA)}+${dA}` };
127
+ }
128
+ const nA = (getProp(a, NS.health + 'testName') ?? '').toLowerCase().trim();
129
+ const nB = (getProp(b, NS.health + 'testName') ?? '').toLowerCase().trim();
130
+ if (nA && nB && nA === nB && sameDay)
131
+ return { match: true, confidence: 0.75, matchedOn: `name:"${nA}"+${dA}` };
132
+ return { match: false, confidence: 0, matchedOn: '' };
133
+ }
134
+ function matchImmunizations(a, b) {
135
+ const cA = getProp(a, NS.health + 'cvxCode');
136
+ const cB = getProp(b, NS.health + 'cvxCode');
137
+ const dA = dateOnly(getProp(a, NS.health + 'administrationDate') ?? getProp(a, NS.health + 'startDate') ?? '');
138
+ const dB = dateOnly(getProp(b, NS.health + 'administrationDate') ?? getProp(b, NS.health + 'startDate') ?? '');
139
+ if (cA && cB && codeFromUri(cA) === codeFromUri(cB) && dA && dA === dB)
140
+ return { match: true, confidence: 1.0, matchedOn: `cvx:${codeFromUri(cA)}+${dA}` };
141
+ return { match: false, confidence: 0, matchedOn: '' };
142
+ }
143
+ function doRecordsMatch(a, b, tol) {
144
+ if (a.type !== b.type)
145
+ return { match: false, confidence: 0, matchedOn: '' };
146
+ switch (a.type) {
147
+ case 'health:MedicationRecord': return matchMedications(a, b);
148
+ case 'health:ConditionRecord': return matchConditions(a, b);
149
+ case 'health:AllergyRecord': return matchAllergies(a, b);
150
+ case 'health:LabResultRecord': return matchLabs(a, b, tol);
151
+ case 'health:ImmunizationRecord': return matchImmunizations(a, b);
152
+ default: return { match: false, confidence: 0, matchedOn: '' };
153
+ }
154
+ }
155
+ function classifyGroup(records, tol) {
156
+ if (records.length < 2)
157
+ return { matchType: 'pass_through' };
158
+ const [a, b] = records;
159
+ if (a.type === 'health:ConditionRecord') {
160
+ const sA = getProp(a, NS.health + 'status');
161
+ const sB = getProp(b, NS.health + 'status');
162
+ if (sA && sB && sA !== sB)
163
+ return { matchType: 'status_conflict', conflictField: 'health:status', conflictValues: { [a.sourceSystem]: sA, [b.sourceSystem]: sB } };
164
+ }
165
+ if (a.type === 'health:AllergyRecord') {
166
+ const sA = getProp(a, NS.health + 'allergySeverity');
167
+ const sB = getProp(b, NS.health + 'allergySeverity');
168
+ if (sA && sB && sA !== sB)
169
+ return { matchType: 'value_conflict', conflictField: 'health:allergySeverity', conflictValues: { [a.sourceSystem]: sA, [b.sourceSystem]: sB } };
170
+ }
171
+ if (a.type === 'health:LabResultRecord') {
172
+ const vA = parseFloat(getProp(a, NS.health + 'resultValue') ?? 'NaN');
173
+ const vB = parseFloat(getProp(b, NS.health + 'resultValue') ?? 'NaN');
174
+ if (!isNaN(vA) && !isNaN(vB)) {
175
+ const diff = Math.abs(vA - vB) / Math.max(Math.abs(vA), 0.001);
176
+ if (diff > tol)
177
+ return { matchType: 'value_conflict', conflictField: 'health:resultValue', conflictValues: { [a.sourceSystem]: String(vA), [b.sourceSystem]: String(vB) } };
178
+ if (diff > 0)
179
+ return { matchType: 'near_duplicate' };
180
+ }
181
+ }
182
+ if (a.type === 'health:MedicationRecord') {
183
+ const nA = normalizeMedName(getProp(a, NS.health + 'medicationName') ?? '');
184
+ const nB = normalizeMedName(getProp(b, NS.health + 'medicationName') ?? '');
185
+ if (nA !== nB)
186
+ return { matchType: 'near_duplicate' };
187
+ }
188
+ return { matchType: 'exact_duplicate' };
189
+ }
190
+ function completeness(r) {
191
+ const skip = new Set([NS.rdf + 'type', NS.cascade + 'dataProvenance', NS.cascade + 'schemaVersion', NS.cascade + 'sourceSystem']);
192
+ let n = 0;
193
+ for (const [p] of r.properties)
194
+ if (!skip.has(p))
195
+ n++;
196
+ return n;
197
+ }
198
+ function resolveGroup(g, trustScores, defaultTrust) {
199
+ const trust = (sys) => trustScores[sys] ?? defaultTrust;
200
+ if (g.records.length === 1) {
201
+ return { canonical: g.records[0], mergedUris: [g.records[0].uri], mergedSystems: [g.records[0].sourceSystem], strategy: 'pass_through', resolved: true };
202
+ }
203
+ const ranked = [...g.records].sort((a, b) => {
204
+ const td = trust(b.sourceSystem) - trust(a.sourceSystem);
205
+ return td !== 0 ? td : completeness(b) - completeness(a);
206
+ });
207
+ const winner = ranked[0];
208
+ const losers = ranked.slice(1);
209
+ let strategy = 'trust_priority';
210
+ let resolved = true;
211
+ if (g.matchType === 'near_duplicate') {
212
+ strategy = 'merge_values';
213
+ }
214
+ else if (g.matchType === 'status_conflict') {
215
+ const diff = Math.abs(trust(ranked[0].sourceSystem) - trust(ranked[1].sourceSystem));
216
+ if (diff < 0.05) {
217
+ strategy = 'flag_unresolved';
218
+ resolved = false;
219
+ }
220
+ }
221
+ // Merge missing fields from lower-trust sources
222
+ let canonical = winner;
223
+ if (strategy === 'merge_values') {
224
+ const mergedProps = new Map(winner.properties);
225
+ const metaPreds = new Set([NS.rdf + 'type', NS.cascade + 'dataProvenance', NS.cascade + 'schemaVersion', NS.cascade + 'sourceSystem']);
226
+ for (const src of losers) {
227
+ for (const [pred, vals] of src.properties) {
228
+ if (!metaPreds.has(pred) && !mergedProps.has(pred))
229
+ mergedProps.set(pred, vals);
230
+ }
231
+ }
232
+ canonical = { ...winner, properties: mergedProps };
233
+ }
234
+ return {
235
+ canonical,
236
+ mergedUris: g.records.map(r => r.uri),
237
+ mergedSystems: g.records.map(r => r.sourceSystem),
238
+ strategy,
239
+ resolved,
240
+ };
241
+ }
242
+ // ---------------------------------------------------------------------------
243
+ // Serializer: resolved groups → Turtle
244
+ // ---------------------------------------------------------------------------
245
+ async function serializeGroups(groups, resolutions) {
246
+ return new Promise((resolve, reject) => {
247
+ const writer = new Writer({ prefixes: TURTLE_PREFIXES });
248
+ for (let i = 0; i < groups.length; i++) {
249
+ const g = groups[i];
250
+ const res = resolutions[i];
251
+ const subj = namedNode(res.canonical.uri);
252
+ for (const [pred, vals] of res.canonical.properties) {
253
+ for (const val of vals) {
254
+ const obj = val.startsWith('http') || val.startsWith('urn:') ? namedNode(val) : literal(val);
255
+ writer.addQuad(makeQuad(subj, namedNode(pred), obj));
256
+ }
257
+ }
258
+ // Reconciliation status
259
+ const status = !res.resolved ? 'unresolved-conflict'
260
+ : g.matchType === 'pass_through' ? 'canonical'
261
+ : (g.matchType === 'status_conflict' || g.matchType === 'value_conflict') ? 'conflict-resolved'
262
+ : 'merged';
263
+ writer.addQuad(makeQuad(subj, namedNode(NS.cascade + 'reconciliationStatus'), literal(status)));
264
+ writer.addQuad(makeQuad(subj, namedNode(NS.cascade + 'sourceSystem'), literal(res.canonical.sourceSystem)));
265
+ if (g.matchType !== 'pass_through' && res.mergedUris.length > 1) {
266
+ for (const srcUri of res.mergedUris) {
267
+ writer.addQuad(makeQuad(subj, namedNode(NS.cascade + 'mergedFrom'), namedNode(srcUri)));
268
+ writer.addQuad(makeQuad(subj, namedNode(NS.prov + 'wasDerivedFrom'), namedNode(srcUri)));
269
+ }
270
+ writer.addQuad(makeQuad(subj, namedNode(NS.cascade + 'mergedSources'), literal(res.mergedSystems.join(', '))));
271
+ writer.addQuad(makeQuad(subj, namedNode(NS.cascade + 'conflictResolution'), literal(res.strategy)));
272
+ if (g.conflictField)
273
+ writer.addQuad(makeQuad(subj, namedNode(NS.cascade + 'conflictField'), literal(g.conflictField)));
274
+ if (g.conflictValues) {
275
+ const valDesc = Object.entries(g.conflictValues).map(([s, v]) => `${s}: "${v}"`).join(' vs ');
276
+ writer.addQuad(makeQuad(subj, namedNode(NS.cascade + 'conflictValues'), literal(valDesc)));
277
+ }
278
+ }
279
+ }
280
+ writer.end((err, result) => err ? reject(err) : resolve(result));
281
+ });
282
+ }
283
+ // ---------------------------------------------------------------------------
284
+ // Main exported function
285
+ // ---------------------------------------------------------------------------
286
+ export async function runReconciliation(inputs, options) {
287
+ const trustScores = {
288
+ 'primary-care': 0.90,
289
+ 'specialist': 0.85,
290
+ 'hospital': 0.95,
291
+ ...(options?.trustScores ?? {}),
292
+ };
293
+ const defaultTrust = 0.80;
294
+ const labTol = options?.labTolerance ?? 0.05;
295
+ // Parse all inputs
296
+ const allRecords = [];
297
+ const sourceInfo = [];
298
+ for (const input of inputs) {
299
+ const records = await parseTurtle(input.content, input.systemName);
300
+ allRecords.push(...records);
301
+ sourceInfo.push({ system: input.systemName, count: records.length });
302
+ }
303
+ // Match and group
304
+ const groups = [];
305
+ const assigned = new Set();
306
+ for (let i = 0; i < allRecords.length; i++) {
307
+ const a = allRecords[i];
308
+ if (assigned.has(a.uri))
309
+ continue;
310
+ if (a.type === 'cascade:PatientProfile' || a.type === 'coverage:InsurancePlan') {
311
+ groups.push({ matchType: 'pass_through', confidence: 1.0, records: [a], matchedOn: 'profile' });
312
+ assigned.add(a.uri);
313
+ continue;
314
+ }
315
+ const matched = [a];
316
+ let matchedOn = '';
317
+ let bestConf = 1.0;
318
+ for (let j = i + 1; j < allRecords.length; j++) {
319
+ const b = allRecords[j];
320
+ if (assigned.has(b.uri) || a.sourceSystem === b.sourceSystem)
321
+ continue;
322
+ const { match, confidence, matchedOn: mo } = doRecordsMatch(a, b, labTol);
323
+ if (match && confidence >= 0.65) {
324
+ matched.push(b);
325
+ assigned.add(b.uri);
326
+ if (!matchedOn) {
327
+ matchedOn = mo;
328
+ bestConf = confidence;
329
+ }
330
+ }
331
+ }
332
+ assigned.add(a.uri);
333
+ if (matched.length === 1) {
334
+ groups.push({ matchType: 'pass_through', confidence: 1.0, records: matched, matchedOn: '' });
335
+ }
336
+ else {
337
+ const { matchType, conflictField, conflictValues } = classifyGroup(matched, labTol);
338
+ groups.push({ matchType, confidence: bestConf, records: matched, matchedOn, conflictField, conflictValues });
339
+ }
340
+ }
341
+ // Resolve
342
+ const resolutions = groups.map(g => resolveGroup(g, trustScores, defaultTrust));
343
+ // Serialize
344
+ const turtle = await serializeGroups(groups, resolutions);
345
+ // Build report
346
+ let exactDups = 0, nearDups = 0, resolved = 0, unresolved = 0;
347
+ const transformations = [];
348
+ const unresolvedList = [];
349
+ for (let i = 0; i < groups.length; i++) {
350
+ const g = groups[i];
351
+ const res = resolutions[i];
352
+ const t = {
353
+ type: g.matchType,
354
+ recordType: g.records[0].type,
355
+ canonicalUri: res.canonical.uri,
356
+ sources: g.records.map(r => r.sourceSystem),
357
+ matchedOn: g.matchedOn,
358
+ strategy: res.strategy,
359
+ conflictField: g.conflictField,
360
+ conflictValues: g.conflictValues,
361
+ resolved: res.resolved,
362
+ };
363
+ switch (g.matchType) {
364
+ case 'exact_duplicate':
365
+ exactDups++;
366
+ break;
367
+ case 'near_duplicate':
368
+ nearDups++;
369
+ break;
370
+ case 'status_conflict':
371
+ case 'value_conflict':
372
+ res.resolved ? resolved++ : unresolved++;
373
+ break;
374
+ }
375
+ if (g.matchType !== 'pass_through')
376
+ transformations.push(t);
377
+ if (!res.resolved)
378
+ unresolvedList.push(t);
379
+ }
380
+ return {
381
+ turtle,
382
+ report: {
383
+ sources: sourceInfo,
384
+ summary: {
385
+ totalInputRecords: allRecords.length,
386
+ exactDuplicatesRemoved: exactDups,
387
+ nearDuplicatesMerged: nearDups,
388
+ conflictsResolved: resolved,
389
+ conflictsUnresolved: unresolved,
390
+ finalRecordCount: groups.length,
391
+ },
392
+ transformations,
393
+ unresolvedConflicts: unresolvedList,
394
+ },
395
+ };
396
+ }
397
+ //# sourceMappingURL=reconciler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconciler.js","sourceRoot":"","sources":["../../src/lib/reconciler.ts"],"names":[],"mappings":"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"}
@@ -476,6 +476,16 @@ checkup:MedicationSummaryShape a sh:NodeShape ;
476
476
  sh:severity sh:Info ;
477
477
  sh:name "Concerns For Doctor" ;
478
478
  sh:message "Concerns patient wants to discuss with provider"
479
+ ] ;
480
+
481
+ # v3.2: Computed supply end date (startDate + supplyDurationDays)
482
+ sh:property [
483
+ sh:path checkup:supplyEndDate ;
484
+ sh:datatype xsd:date ;
485
+ sh:maxCount 1 ;
486
+ sh:severity sh:Info ;
487
+ sh:name "Supply End Date" ;
488
+ sh:message "Computed date when medication supply is expected to be exhausted; used to infer currency when adherenceStatus is absent"
479
489
  ] .
480
490
 
481
491
  # ============================================================================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@the-cascade-protocol/cli",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "description": "Cascade Protocol CLI - Validate, convert, and manage health data",
5
5
  "bin": {
6
6
  "cascade": "dist/index.js"