@kontourai/survey 2.2.0 → 2.2.2

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.
@@ -191,6 +191,9 @@ export function mountExtractionInspector(container, model, options = {}) {
191
191
  list.innerHTML = visible.map(c => `<li><button type="button" class="inspector-candidate" id="candidate-${safeId(c.id)}" data-candidate-id="${escapeHtml(c.id)}" aria-controls="highlight-${safeId(c.id)}"><strong>${escapeHtml(c.field)}</strong><span>${escapeHtml(c.provider)}${c.model ? ` / ${escapeHtml(c.model)}` : ""}</span><span>${escapeHtml(c.inferenceType)} ${escapeHtml(c.valueType)} · ${escapeHtml(c.alignment)}</span>${formatContext(c)}</button></li>`).join("") || "<li>No candidates match these filters.</li>";
192
192
  resultCount.textContent = matching.length === 0 ? "No matching candidates" : `${start + 1}–${Math.min(start + pageSize, matching.length)} of ${matching.length}`;
193
193
  pageLabel.textContent = `Page ${page + 1} of ${pageCount}`;
194
+ pageLabel.hidden = pageCount === 1;
195
+ previous.hidden = pageCount === 1;
196
+ next.hidden = pageCount === 1;
194
197
  previous.disabled = page === 0;
195
198
  next.disabled = page >= pageCount - 1;
196
199
  postures.innerHTML = model.sources.map(s => `<div class="inspector-posture ${s.alignment}" role="status"><strong>${escapeHtml(s.importName)}: ${escapeHtml(s.alignment)}</strong><span>${escapeHtml(s.message)}</span></div>`).join("");
@@ -423,7 +423,7 @@ export const facilityCredentialReviewItemExample = {
423
423
  selectedCandidateId: "facility-credential-review-operating-license:candidate:current",
424
424
  },
425
425
  };
426
- function queueFixture(name, target, currentValue, proposedValue, candidateSetStatus, feedbackTags) {
426
+ function queueFixture({ name, target, currentValue, proposedValue, candidateSetStatus, feedbackTags, proposalId, excerpts, }) {
427
427
  return {
428
428
  ...publicDirectoryReviewItemExample,
429
429
  metadata: {
@@ -450,6 +450,11 @@ function queueFixture(name, target, currentValue, proposedValue, candidateSetSta
450
450
  ...candidate.source,
451
451
  sourceId: `${name}:source:${role}`,
452
452
  },
453
+ locator: {
454
+ ...candidate.locator,
455
+ locator: `html:field=${target}`,
456
+ excerpt: role === "proposed" ? excerpts.proposed : excerpts.current,
457
+ },
453
458
  extraction: {
454
459
  ...candidate.extraction,
455
460
  extractionId: `${name}:extraction:${role}`,
@@ -471,6 +476,15 @@ function queueFixture(name, target, currentValue, proposedValue, candidateSetSta
471
476
  },
472
477
  producer: {
473
478
  ...candidate.producer,
479
+ ...(role === "proposed" ? { proposalId, oldValue: currentValue } : {}),
480
+ ...(candidate.producer?.sourceAuthority
481
+ ? {
482
+ sourceAuthority: {
483
+ ...candidate.producer.sourceAuthority,
484
+ scope: `${target} field on entity-123`,
485
+ },
486
+ }
487
+ : {}),
474
488
  },
475
489
  };
476
490
  }),
@@ -652,12 +666,60 @@ const dailyHoursNoSourceReviewItemExample = {
652
666
  status: { observedCandidateCount: 2 },
653
667
  };
654
668
  export const reviewWorkbenchQueueExamples = [
655
- queueFixture("public-directory-hours", "hours", "Weekdays 9am-5pm", "Weekdays 8am-6pm", "needs-review", ["hours-change", "crawler-suggested"]),
656
- queueFixture("public-directory-phone", "phoneNumber", "+1-555-0100", "+1-555-0199", "needs-review", ["contact-field", "source-conflict"]),
669
+ queueFixture({
670
+ name: "public-directory-hours",
671
+ target: "hours",
672
+ currentValue: "Weekdays 9am-5pm",
673
+ proposedValue: "Weekdays 8am-6pm",
674
+ candidateSetStatus: "needs-review",
675
+ feedbackTags: ["hours-change", "crawler-suggested"],
676
+ proposalId: "proposal-451",
677
+ excerpts: {
678
+ current: "Program hours: Weekdays 9am-5pm. Closed weekends and public holidays.",
679
+ proposed: "Extended schedule for the fall term — program hours are now Weekdays 8am-6pm.",
680
+ },
681
+ }),
682
+ queueFixture({
683
+ name: "public-directory-phone",
684
+ target: "phoneNumber",
685
+ currentValue: "+1-555-0100",
686
+ proposedValue: "+1-555-0199",
687
+ candidateSetStatus: "needs-review",
688
+ feedbackTags: ["contact-field", "source-conflict"],
689
+ proposalId: "proposal-452",
690
+ excerpts: {
691
+ current: "Questions? Call the main office at +1-555-0100.",
692
+ proposed: "Our enrollment line has moved. Call +1-555-0199 to reach the office.",
693
+ },
694
+ }),
657
695
  dropInPriceReviewItemExample,
658
696
  dailyHoursNoSourceReviewItemExample,
659
697
  publicDirectoryReviewItemExample,
660
- queueFixture("public-directory-address", "streetAddress", "100 Main Street", "102 Main Street", "needs-review", ["address-change", "producer-escalation-candidate"]),
661
- queueFixture("public-directory-license", "licenseStatus", "ACTIVE", "EXPIRED", "escalated", ["licensing", "manual-review-required"]),
698
+ queueFixture({
699
+ name: "public-directory-address",
700
+ target: "streetAddress",
701
+ currentValue: "100 Main Street",
702
+ proposedValue: "102 Main Street",
703
+ candidateSetStatus: "needs-review",
704
+ feedbackTags: ["address-change", "producer-escalation-candidate"],
705
+ proposalId: "proposal-453",
706
+ excerpts: {
707
+ current: "Find us at 100 Main Street, Example City.",
708
+ proposed: "We have moved one door down to 102 Main Street, Example City.",
709
+ },
710
+ }),
711
+ queueFixture({
712
+ name: "public-directory-license",
713
+ target: "licenseStatus",
714
+ currentValue: "ACTIVE",
715
+ proposedValue: "EXPIRED",
716
+ candidateSetStatus: "escalated",
717
+ feedbackTags: ["licensing", "manual-review-required"],
718
+ proposalId: "proposal-454",
719
+ excerpts: {
720
+ current: "Operating license status: ACTIVE (renewed 2025-06-01).",
721
+ proposed: "Operating license status: EXPIRED as of 2026-05-31. Renewal not yet filed.",
722
+ },
723
+ }),
662
724
  regulatedRuleConflictReviewItemExample,
663
725
  ];
@@ -572,11 +572,11 @@ function renderReviewQueueSessionHtml(session, presentationAdapter, queueView) {
572
572
  <span class="queue-result-count" aria-live="polite">
573
573
  ${window.totalMatching === 0 ? "No matching fields" : `${window.start + 1}–${window.end} of ${window.totalMatching}`}
574
574
  </span>
575
- <div class="queue-pager">
575
+ ${window.pageCount > 1 ? `<div class="queue-pager">
576
576
  <button type="button" data-testid="queue-previous"${window.page === 0 ? " disabled" : ""}>Previous</button>
577
577
  <span>Page ${window.page + 1} of ${window.pageCount}</span>
578
578
  <button type="button" data-testid="queue-next"${window.page >= window.pageCount - 1 ? " disabled" : ""}>Next</button>
579
- </div>
579
+ </div>` : ""}
580
580
  </nav>
581
581
  <div class="fields" data-testid="review-fields">
582
582
  ${window.items.map((item) => renderFieldCard(item, session, presentationAdapter)).join("")
@@ -61,8 +61,8 @@
61
61
  },
62
62
  "locator": {
63
63
  "scheme": "html",
64
- "locator": "html:field=availabilityStatus",
65
- "excerpt": "Availability is open for the example program."
64
+ "locator": "html:field=hours",
65
+ "excerpt": "Program hours: Weekdays 9am-5pm. Closed weekends and public holidays."
66
66
  },
67
67
  "extraction": {
68
68
  "extractionId": "public-directory-hours:extraction:current",
@@ -75,7 +75,7 @@
75
75
  "claimId": "public-field.entity-123.hours.current",
76
76
  "subjectType": "public-record.entity",
77
77
  "subjectId": "entity-123",
78
- "surface": "public-record.profile",
78
+ "facet": "public-record.profile",
79
79
  "claimType": "public-data.field",
80
80
  "fieldOrBehavior": "hours",
81
81
  "impactLevel": "medium",
@@ -92,7 +92,7 @@
92
92
  "sourceAuthority": {
93
93
  "authorityClass": "public-directory-listing",
94
94
  "declaredBy": "Example Program public directory",
95
- "scope": "availabilityStatus field on entity-123"
95
+ "scope": "hours field on entity-123"
96
96
  }
97
97
  }
98
98
  },
@@ -111,21 +111,22 @@
111
111
  },
112
112
  "locator": {
113
113
  "scheme": "html",
114
- "locator": "html:field=availabilityStatus",
115
- "excerpt": "Join the waitlist for this listing."
114
+ "locator": "html:field=hours",
115
+ "excerpt": "Extended schedule for the fall term — program hours are now Weekdays 8am-6pm."
116
116
  },
117
117
  "extraction": {
118
118
  "extractionId": "public-directory-hours:extraction:proposed",
119
119
  "target": "hours",
120
120
  "confidence": 0.82,
121
121
  "extractor": "example-crawl",
122
+ "model": "example-extraction-model-2026-05",
122
123
  "extractedAt": "2026-05-31T15:00:00.000Z"
123
124
  },
124
125
  "claimTarget": {
125
126
  "claimId": "public-field.entity-123.hours.proposed",
126
127
  "subjectType": "public-record.entity",
127
128
  "subjectId": "entity-123",
128
- "surface": "public-record.profile",
129
+ "facet": "public-record.profile",
129
130
  "claimType": "public-data.field-candidate",
130
131
  "fieldOrBehavior": "hours",
131
132
  "impactLevel": "medium",
@@ -139,12 +140,12 @@
139
140
  "claimId": "public-field.entity-123.hours.proposed"
140
141
  },
141
142
  "producer": {
142
- "proposalId": "proposal-456",
143
- "oldValue": "AVAILABLE",
143
+ "proposalId": "proposal-451",
144
+ "oldValue": "Weekdays 9am-5pm",
144
145
  "sourceAuthority": {
145
146
  "authorityClass": "public-directory-listing",
146
147
  "declaredBy": "Example Program public directory crawler",
147
- "scope": "availabilityStatus field on entity-123"
148
+ "scope": "hours field on entity-123"
148
149
  }
149
150
  }
150
151
  }
@@ -195,8 +196,8 @@
195
196
  },
196
197
  "locator": {
197
198
  "scheme": "html",
198
- "locator": "html:field=availabilityStatus",
199
- "excerpt": "Availability is open for the example program."
199
+ "locator": "html:field=phoneNumber",
200
+ "excerpt": "Questions? Call the main office at +1-555-0100."
200
201
  },
201
202
  "extraction": {
202
203
  "extractionId": "public-directory-phone:extraction:current",
@@ -209,7 +210,7 @@
209
210
  "claimId": "public-field.entity-123.phoneNumber.current",
210
211
  "subjectType": "public-record.entity",
211
212
  "subjectId": "entity-123",
212
- "surface": "public-record.profile",
213
+ "facet": "public-record.profile",
213
214
  "claimType": "public-data.field",
214
215
  "fieldOrBehavior": "phoneNumber",
215
216
  "impactLevel": "medium",
@@ -226,7 +227,7 @@
226
227
  "sourceAuthority": {
227
228
  "authorityClass": "public-directory-listing",
228
229
  "declaredBy": "Example Program public directory",
229
- "scope": "availabilityStatus field on entity-123"
230
+ "scope": "phoneNumber field on entity-123"
230
231
  }
231
232
  }
232
233
  },
@@ -245,21 +246,22 @@
245
246
  },
246
247
  "locator": {
247
248
  "scheme": "html",
248
- "locator": "html:field=availabilityStatus",
249
- "excerpt": "Join the waitlist for this listing."
249
+ "locator": "html:field=phoneNumber",
250
+ "excerpt": "Our enrollment line has moved. Call +1-555-0199 to reach the office."
250
251
  },
251
252
  "extraction": {
252
253
  "extractionId": "public-directory-phone:extraction:proposed",
253
254
  "target": "phoneNumber",
254
255
  "confidence": 0.82,
255
256
  "extractor": "example-crawl",
257
+ "model": "example-extraction-model-2026-05",
256
258
  "extractedAt": "2026-05-31T15:00:00.000Z"
257
259
  },
258
260
  "claimTarget": {
259
261
  "claimId": "public-field.entity-123.phoneNumber.proposed",
260
262
  "subjectType": "public-record.entity",
261
263
  "subjectId": "entity-123",
262
- "surface": "public-record.profile",
264
+ "facet": "public-record.profile",
263
265
  "claimType": "public-data.field-candidate",
264
266
  "fieldOrBehavior": "phoneNumber",
265
267
  "impactLevel": "medium",
@@ -273,12 +275,12 @@
273
275
  "claimId": "public-field.entity-123.phoneNumber.proposed"
274
276
  },
275
277
  "producer": {
276
- "proposalId": "proposal-456",
277
- "oldValue": "AVAILABLE",
278
+ "proposalId": "proposal-452",
279
+ "oldValue": "+1-555-0100",
278
280
  "sourceAuthority": {
279
281
  "authorityClass": "public-directory-listing",
280
282
  "declaredBy": "Example Program public directory crawler",
281
- "scope": "availabilityStatus field on entity-123"
283
+ "scope": "phoneNumber field on entity-123"
282
284
  }
283
285
  }
284
286
  }
@@ -343,7 +345,7 @@
343
345
  "claimId": "public-field.entity-123.availability-status.current",
344
346
  "subjectType": "public-record.entity",
345
347
  "subjectId": "entity-123",
346
- "surface": "public-record.profile",
348
+ "facet": "public-record.profile",
347
349
  "claimType": "public-data.field",
348
350
  "fieldOrBehavior": "availabilityStatus",
349
351
  "impactLevel": "medium",
@@ -388,13 +390,14 @@
388
390
  "target": "availabilityStatus",
389
391
  "confidence": 0.82,
390
392
  "extractor": "example-crawl",
393
+ "model": "example-extraction-model-2026-05",
391
394
  "extractedAt": "2026-05-31T15:00:00.000Z"
392
395
  },
393
396
  "claimTarget": {
394
397
  "claimId": "public-field.entity-123.availability-status.proposal-456",
395
398
  "subjectType": "public-record.entity",
396
399
  "subjectId": "entity-123",
397
- "surface": "public-record.profile",
400
+ "facet": "public-record.profile",
398
401
  "claimType": "public-data.field-candidate",
399
402
  "fieldOrBehavior": "availabilityStatus",
400
403
  "impactLevel": "medium",
@@ -459,8 +462,8 @@
459
462
  },
460
463
  "locator": {
461
464
  "scheme": "html",
462
- "locator": "html:field=availabilityStatus",
463
- "excerpt": "Availability is open for the example program."
465
+ "locator": "html:field=streetAddress",
466
+ "excerpt": "Find us at 100 Main Street, Example City."
464
467
  },
465
468
  "extraction": {
466
469
  "extractionId": "public-directory-address:extraction:current",
@@ -473,7 +476,7 @@
473
476
  "claimId": "public-field.entity-123.streetAddress.current",
474
477
  "subjectType": "public-record.entity",
475
478
  "subjectId": "entity-123",
476
- "surface": "public-record.profile",
479
+ "facet": "public-record.profile",
477
480
  "claimType": "public-data.field",
478
481
  "fieldOrBehavior": "streetAddress",
479
482
  "impactLevel": "medium",
@@ -490,7 +493,7 @@
490
493
  "sourceAuthority": {
491
494
  "authorityClass": "public-directory-listing",
492
495
  "declaredBy": "Example Program public directory",
493
- "scope": "availabilityStatus field on entity-123"
496
+ "scope": "streetAddress field on entity-123"
494
497
  }
495
498
  }
496
499
  },
@@ -509,21 +512,22 @@
509
512
  },
510
513
  "locator": {
511
514
  "scheme": "html",
512
- "locator": "html:field=availabilityStatus",
513
- "excerpt": "Join the waitlist for this listing."
515
+ "locator": "html:field=streetAddress",
516
+ "excerpt": "We have moved one door down to 102 Main Street, Example City."
514
517
  },
515
518
  "extraction": {
516
519
  "extractionId": "public-directory-address:extraction:proposed",
517
520
  "target": "streetAddress",
518
521
  "confidence": 0.82,
519
522
  "extractor": "example-crawl",
523
+ "model": "example-extraction-model-2026-05",
520
524
  "extractedAt": "2026-05-31T15:00:00.000Z"
521
525
  },
522
526
  "claimTarget": {
523
527
  "claimId": "public-field.entity-123.streetAddress.proposed",
524
528
  "subjectType": "public-record.entity",
525
529
  "subjectId": "entity-123",
526
- "surface": "public-record.profile",
530
+ "facet": "public-record.profile",
527
531
  "claimType": "public-data.field-candidate",
528
532
  "fieldOrBehavior": "streetAddress",
529
533
  "impactLevel": "medium",
@@ -537,12 +541,12 @@
537
541
  "claimId": "public-field.entity-123.streetAddress.proposed"
538
542
  },
539
543
  "producer": {
540
- "proposalId": "proposal-456",
541
- "oldValue": "AVAILABLE",
544
+ "proposalId": "proposal-453",
545
+ "oldValue": "100 Main Street",
542
546
  "sourceAuthority": {
543
547
  "authorityClass": "public-directory-listing",
544
548
  "declaredBy": "Example Program public directory crawler",
545
- "scope": "availabilityStatus field on entity-123"
549
+ "scope": "streetAddress field on entity-123"
546
550
  }
547
551
  }
548
552
  }
@@ -593,8 +597,8 @@
593
597
  },
594
598
  "locator": {
595
599
  "scheme": "html",
596
- "locator": "html:field=availabilityStatus",
597
- "excerpt": "Availability is open for the example program."
600
+ "locator": "html:field=licenseStatus",
601
+ "excerpt": "Operating license status: ACTIVE (renewed 2025-06-01)."
598
602
  },
599
603
  "extraction": {
600
604
  "extractionId": "public-directory-license:extraction:current",
@@ -607,7 +611,7 @@
607
611
  "claimId": "public-field.entity-123.licenseStatus.current",
608
612
  "subjectType": "public-record.entity",
609
613
  "subjectId": "entity-123",
610
- "surface": "public-record.profile",
614
+ "facet": "public-record.profile",
611
615
  "claimType": "public-data.field",
612
616
  "fieldOrBehavior": "licenseStatus",
613
617
  "impactLevel": "medium",
@@ -624,7 +628,7 @@
624
628
  "sourceAuthority": {
625
629
  "authorityClass": "public-directory-listing",
626
630
  "declaredBy": "Example Program public directory",
627
- "scope": "availabilityStatus field on entity-123"
631
+ "scope": "licenseStatus field on entity-123"
628
632
  }
629
633
  }
630
634
  },
@@ -643,21 +647,22 @@
643
647
  },
644
648
  "locator": {
645
649
  "scheme": "html",
646
- "locator": "html:field=availabilityStatus",
647
- "excerpt": "Join the waitlist for this listing."
650
+ "locator": "html:field=licenseStatus",
651
+ "excerpt": "Operating license status: EXPIRED as of 2026-05-31. Renewal not yet filed."
648
652
  },
649
653
  "extraction": {
650
654
  "extractionId": "public-directory-license:extraction:proposed",
651
655
  "target": "licenseStatus",
652
656
  "confidence": 0.82,
653
657
  "extractor": "example-crawl",
658
+ "model": "example-extraction-model-2026-05",
654
659
  "extractedAt": "2026-05-31T15:00:00.000Z"
655
660
  },
656
661
  "claimTarget": {
657
662
  "claimId": "public-field.entity-123.licenseStatus.proposed",
658
663
  "subjectType": "public-record.entity",
659
664
  "subjectId": "entity-123",
660
- "surface": "public-record.profile",
665
+ "facet": "public-record.profile",
661
666
  "claimType": "public-data.field-candidate",
662
667
  "fieldOrBehavior": "licenseStatus",
663
668
  "impactLevel": "medium",
@@ -671,12 +676,12 @@
671
676
  "claimId": "public-field.entity-123.licenseStatus.proposed"
672
677
  },
673
678
  "producer": {
674
- "proposalId": "proposal-456",
675
- "oldValue": "AVAILABLE",
679
+ "proposalId": "proposal-454",
680
+ "oldValue": "ACTIVE",
676
681
  "sourceAuthority": {
677
682
  "authorityClass": "public-directory-listing",
678
683
  "declaredBy": "Example Program public directory crawler",
679
- "scope": "availabilityStatus field on entity-123"
684
+ "scope": "licenseStatus field on entity-123"
680
685
  }
681
686
  }
682
687
  }
@@ -752,7 +757,7 @@
752
757
  "claimId": "regulated-rule.example-jurisdiction.2026.standard-threshold.current",
753
758
  "subjectType": "regulated-rule-source",
754
759
  "subjectId": "example-jurisdiction:2026:standardThreshold",
755
- "surface": "regulated.rules",
760
+ "facet": "regulated.rules",
756
761
  "claimType": "regulated.rule-source-value",
757
762
  "fieldOrBehavior": "standardThreshold",
758
763
  "impactLevel": "high",
@@ -800,7 +805,7 @@
800
805
  "claimId": "regulated-rule.example-jurisdiction.2026.standard-threshold.proposed",
801
806
  "subjectType": "regulated-rule-source",
802
807
  "subjectId": "example-jurisdiction:2026:standardThreshold",
803
- "surface": "regulated.rules",
808
+ "facet": "regulated.rules",
804
809
  "claimType": "regulated.rule-source-value",
805
810
  "fieldOrBehavior": "standardThreshold",
806
811
  "impactLevel": "high",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontourai/survey",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "description": "Producer-side source, extraction, candidate, and review contracts for projecting verified claims into Surface.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",