@kontourai/survey 6.1.0 → 7.0.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/example-data/public-directory-review-resource.d.ts +3 -3
- package/dist/src/canonical-reviewed-trust-input.js +30 -1
- package/dist/src/console/review-console-server.js +22 -4
- package/dist/src/index.d.ts +3 -3
- package/dist/src/index.js +1 -1
- package/dist/src/mcp/review-mcp.js +139 -36
- package/dist/src/review-resource.d.ts +7 -0
- package/dist/src/review-session-file.d.ts +7 -0
- package/dist/src/review-workbench/audit-rows.d.ts +1 -1
- package/dist/src/review-workbench/audit-rows.js +1 -0
- package/dist/src/review-workbench/queue-binding.d.ts +45 -2
- package/dist/src/review-workbench/queue-binding.js +45 -0
- package/dist/src/review-workbench/review-presentation.d.ts +23 -0
- package/dist/src/review-workbench/review-presentation.js +51 -10
- package/dist/src/review-workbench/review-queue-session.d.ts +47 -4
- package/dist/src/review-workbench/review-queue-session.js +73 -8
- package/dist/src/review-workbench/review-session-replay.d.ts +11 -1
- package/dist/src/review-workbench/review-session-replay.js +35 -1
- package/dist/src/review-workbench/review-workbench-css.generated.js +94 -0
- package/dist/src/review-workbench/review-workbench-element.d.ts +10 -0
- package/dist/src/review-workbench/review-workbench-element.js +21 -3
- package/dist/src/review-workbench/review-workbench.css +94 -0
- package/dist/src/review-workbench/review-workbench.d.ts +28 -8
- package/dist/src/review-workbench/review-workbench.js +157 -62
- package/dist/src/review-workbench/review-workbench.standalone.css +94 -0
- package/dist/src/review-workbench/server-review-session.d.ts +18 -0
- package/dist/src/review-workbench/server-review-session.js +20 -2
- package/dist/src/surface-reviewed-extraction.d.ts +23 -0
- package/dist/src/surface-reviewed-extraction.js +64 -1
- package/dist/src/to-surface.js +32 -3
- package/package.json +1 -1
|
@@ -35,12 +35,12 @@ export declare const publicDirectoryReviewItemExample: {
|
|
|
35
35
|
excerpt: string;
|
|
36
36
|
};
|
|
37
37
|
extraction: {
|
|
38
|
-
model?: undefined;
|
|
39
38
|
extractionId: string;
|
|
40
39
|
target: string;
|
|
41
40
|
confidence: number;
|
|
42
41
|
extractor: string;
|
|
43
42
|
extractedAt: string;
|
|
43
|
+
model?: undefined;
|
|
44
44
|
};
|
|
45
45
|
claimTarget: {
|
|
46
46
|
claimId: string;
|
|
@@ -61,13 +61,13 @@ export declare const publicDirectoryReviewItemExample: {
|
|
|
61
61
|
claimId: string;
|
|
62
62
|
};
|
|
63
63
|
producer: {
|
|
64
|
-
proposalId?: undefined;
|
|
65
|
-
oldValue?: undefined;
|
|
66
64
|
sourceAuthority: {
|
|
67
65
|
authorityClass: string;
|
|
68
66
|
declaredBy: string;
|
|
69
67
|
scope: string;
|
|
70
68
|
};
|
|
69
|
+
proposalId?: undefined;
|
|
70
|
+
oldValue?: undefined;
|
|
71
71
|
};
|
|
72
72
|
} | {
|
|
73
73
|
id: string;
|
|
@@ -39,10 +39,17 @@ export function buildCanonicalReviewedTrustInput(options) {
|
|
|
39
39
|
const rejectsAll = selectsNone && result.decision === "reject-proposed";
|
|
40
40
|
const rejectedRole = workbenchDecisionDefinitions[result.decision].candidateRole;
|
|
41
41
|
const rejectAllReason = result.rationale?.trim() || "Every proposed value for this claim was rejected.";
|
|
42
|
+
// A choice of one conflicting value passes over the others: each keeps a
|
|
43
|
+
// record that it was seen and not chosen (and so its own rejected-candidate
|
|
44
|
+
// learning), never silently dropped.
|
|
45
|
+
const unchosenIds = new Set(result.decision === "select-proposed" ? result.reviewDecision.spec.unselectedCandidateIds ?? [] : []);
|
|
46
|
+
const notChosenReason = `Not chosen: the reviewer chose candidate ${recordIdFor(item, result.selectedCandidateId ?? "")} for this claim.`;
|
|
42
47
|
const candidates = item.spec.candidates.map((candidate) => {
|
|
43
48
|
const records = projectCandidate(item, rejectsAll && candidate.role === rejectedRole
|
|
44
49
|
? { ...candidate, rejectionReason: candidate.rejectionReason ?? rejectAllReason }
|
|
45
|
-
: candidate)
|
|
50
|
+
: unchosenIds.has(candidate.id)
|
|
51
|
+
? { ...candidate, rejectionReason: candidate.rejectionReason ?? notChosenReason }
|
|
52
|
+
: candidate);
|
|
46
53
|
addConsistent(rawSources, records.rawSource, "raw source");
|
|
47
54
|
addConsistent(extractions, records.extraction, "extraction");
|
|
48
55
|
return records.candidate;
|
|
@@ -96,6 +103,9 @@ export function buildCanonicalReviewedTrustInput(options) {
|
|
|
96
103
|
metadata: {
|
|
97
104
|
workbenchDecision: result.decision,
|
|
98
105
|
...(result.editedValue !== undefined ? { editedValue: result.editedValue } : {}),
|
|
106
|
+
...(decision.unselectedCandidateIds?.length
|
|
107
|
+
? { unselectedCandidateIds: decision.unselectedCandidateIds.map((id) => recordIdFor(item, id)) }
|
|
108
|
+
: {}),
|
|
99
109
|
},
|
|
100
110
|
};
|
|
101
111
|
addConsistent(reviewOutcomes, reviewOutcome, "review outcome");
|
|
@@ -192,6 +202,20 @@ function assertCanonicalResult(item, result) {
|
|
|
192
202
|
|| canonicalJson(decision.editedValue) !== canonicalJson(result.editedValue)) {
|
|
193
203
|
throw new Error(`Review result ${result.reviewItemName} contradicts its canonical ReviewDecision.`);
|
|
194
204
|
}
|
|
205
|
+
// Accepting one value of a conflict would project it as if it had been the
|
|
206
|
+
// only value; a choice between conflicting values is select-proposed.
|
|
207
|
+
if (result.decision === "accept-proposed" && item.spec.candidates.filter((candidate) => candidate.role === "proposed").length > 1) {
|
|
208
|
+
throw new Error(`Review result ${result.reviewItemName} accepts one proposed value of a conflict; a choice between conflicting values must be a select-proposed decision that records the values it passed over.`);
|
|
209
|
+
}
|
|
210
|
+
// A choice names exactly the proposed values it passed over; no other
|
|
211
|
+
// decision names any.
|
|
212
|
+
const expectedUnselected = result.decision === "select-proposed" && selected
|
|
213
|
+
? item.spec.candidates.filter((candidate) => candidate.role === "proposed" && candidate.id !== selected.id).map((candidate) => candidate.id)
|
|
214
|
+
: [];
|
|
215
|
+
if (canonicalJson(decision.unselectedCandidateIds ?? []) !== canonicalJson(expectedUnselected)
|
|
216
|
+
|| (result.decision === "select-proposed" && expectedUnselected.length === 0)) {
|
|
217
|
+
throw new Error(`Review result ${result.reviewItemName} does not record the proposed values its ${result.decision} decision passed over.`);
|
|
218
|
+
}
|
|
195
219
|
if ((result.decision === "could-not-confirm") !== (decision.resolution === "could_not_confirm")) {
|
|
196
220
|
throw new Error(`Review result ${result.reviewItemName} contradicts its canonical review resolution.`);
|
|
197
221
|
}
|
|
@@ -210,6 +234,11 @@ function assertCanonicalResult(item, result) {
|
|
|
210
234
|
}
|
|
211
235
|
}
|
|
212
236
|
}
|
|
237
|
+
/** The projected Candidate record id of a ReviewItem candidate. */
|
|
238
|
+
function recordIdFor(item, candidateId) {
|
|
239
|
+
const candidate = item.spec.candidates.find((entry) => entry.id === candidateId);
|
|
240
|
+
return candidate?.projection?.candidateId ?? candidateId;
|
|
241
|
+
}
|
|
213
242
|
function claimTargetIdentity(target) {
|
|
214
243
|
const { claimId: _claimId, ...identity } = target;
|
|
215
244
|
return identity;
|
|
@@ -18,6 +18,7 @@ import { readFile as readFileAsync } from "node:fs/promises";
|
|
|
18
18
|
import { resolve, join, dirname, extname, normalize, sep } from "node:path";
|
|
19
19
|
import { fileURLToPath } from "node:url";
|
|
20
20
|
import { createServerReviewSessionRecord, currentSessionState, deriveServerReviewSessionApplyResult, } from "../review-workbench/server-review-session.js";
|
|
21
|
+
import { attestReviewQueueExtraction } from "../review-workbench/queue-binding.js";
|
|
21
22
|
import { appendReviewSessionEvents, readReviewSessionFile, reviewSessionRevision, storedReviewSessionName, updateReviewSessionFile, } from "../review-session-file.js";
|
|
22
23
|
// ---------------------------------------------------------------------------
|
|
23
24
|
// Constants
|
|
@@ -404,9 +405,15 @@ let activeItemName = null;
|
|
|
404
405
|
async function fetchAndMount() {
|
|
405
406
|
try {
|
|
406
407
|
const res = await fetch("/api/session");
|
|
407
|
-
if (!res.ok)
|
|
408
|
+
if (!res.ok) {
|
|
409
|
+
const body = await res.json().catch(() => ({}));
|
|
410
|
+
showSaveStatus(body.error || ("The session could not be loaded (HTTP " + res.status + ")."));
|
|
411
|
+
const root = document.getElementById("review-workbench");
|
|
412
|
+
if (root) root.innerHTML = "";
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
408
415
|
const data = await res.json();
|
|
409
|
-
const { snapshot, events, revision } = data;
|
|
416
|
+
const { snapshot, events, revision, extractionImport } = data;
|
|
410
417
|
const state = events && events.length > 0
|
|
411
418
|
? replayReviewSessionEvents(snapshot, events)
|
|
412
419
|
: snapshot;
|
|
@@ -419,7 +426,7 @@ async function fetchAndMount() {
|
|
|
419
426
|
const root = document.getElementById("review-workbench");
|
|
420
427
|
if (!root) return;
|
|
421
428
|
|
|
422
|
-
mountReviewWorkbench(root, state, { eventStore: createConsoleEventStore(revision) });
|
|
429
|
+
mountReviewWorkbench(root, state, { eventStore: createConsoleEventStore(revision), ...(extractionImport ? { extractionImport } : {}) });
|
|
423
430
|
} catch (err) {
|
|
424
431
|
console.error("[console] Mount error:", err);
|
|
425
432
|
}
|
|
@@ -602,12 +609,22 @@ export async function startReviewConsoleServer(options) {
|
|
|
602
609
|
// ---- Session read ----
|
|
603
610
|
if (pathname === "/api/session" && req.method === "GET") {
|
|
604
611
|
const content = await readSession(sessionPath);
|
|
612
|
+
// A queue that does not match the extraction import stored with it is
|
|
613
|
+
// not served for review; one without a stored import is served, and the
|
|
614
|
+
// workbench marks it unverified.
|
|
615
|
+
const attestation = attestReviewQueueExtraction(content.snapshot.items, content.extractionImport);
|
|
616
|
+
if (attestation.state === "diverges") {
|
|
617
|
+
sendJson(res, 409, { error: attestation.message, queueAttestation: attestation.state });
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
605
620
|
sendJson(res, 200, {
|
|
606
621
|
session: content.session,
|
|
607
622
|
snapshot: content.snapshot,
|
|
608
623
|
events: content.events,
|
|
609
624
|
revision: reviewSessionRevision(content.events),
|
|
610
625
|
state: currentSessionState(content.snapshot, content.events),
|
|
626
|
+
queueAttestation: attestation.state,
|
|
627
|
+
...(content.extractionImport !== undefined ? { extractionImport: content.extractionImport } : {}),
|
|
611
628
|
});
|
|
612
629
|
return;
|
|
613
630
|
}
|
|
@@ -660,6 +677,7 @@ export async function startReviewConsoleServer(options) {
|
|
|
660
677
|
record,
|
|
661
678
|
events: nextEvents,
|
|
662
679
|
requiredResolvedItems: "none",
|
|
680
|
+
extractionImport: content.extractionImport,
|
|
663
681
|
});
|
|
664
682
|
issueMessages = applyResult.ok
|
|
665
683
|
? []
|
|
@@ -672,7 +690,7 @@ export async function startReviewConsoleServer(options) {
|
|
|
672
690
|
return { result: { status: 422, body: { error: `Validation failed: ${issueMessages.join("; ")}` } } };
|
|
673
691
|
}
|
|
674
692
|
return {
|
|
675
|
-
next: { session: content.session, snapshot, events: nextEvents },
|
|
693
|
+
next: { ...content, session: content.session, snapshot, events: nextEvents },
|
|
676
694
|
result: {
|
|
677
695
|
status: 200,
|
|
678
696
|
body: { ok: true, eventCount: nextEvents.length, revision: reviewSessionRevision(nextEvents) },
|
package/dist/src/index.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ export { SURVEY_INPUT_CONTRACT_VERSION } from "./types.js";
|
|
|
3
3
|
export { reviewResourceApiVersion } from "./review-resource.js";
|
|
4
4
|
export { buildReviewItemsFromExtractionEnvelopeImport, createExtractionEnvelopeResolutionIdentity, exportExtractionEnvelopeImport, extractionEnvelopeImportApiVersion, importExtractionEnvelope, portableExtractionResultFormat, portableExtractionResultVersion, reimportExtractionEnvelope, validateExtractionEnvelopeImport, } from "./extraction-envelope.js";
|
|
5
5
|
export { buildExtractionInspectorModel, exportExtractionInspector, inspectorSourcePosture, filterExtractionInspectorCandidates, } from "./review-workbench/extraction-inspector.js";
|
|
6
|
-
export { assertReviewQueueAgainstExtractionImport, assertReviewQueueBinding, bindReviewQueue, hashReviewQueueSnapshot, UnattestedExtractionQueueError, UnattestedReviewQueueError, validateReviewQueueAgainstExtractionImport, validateReviewQueueBinding, } from "./review-workbench/queue-binding.js";
|
|
7
|
-
export type { BindReviewQueueOptions, ReviewQueueBinding, ReviewQueueBindingIssue, ReviewQueueBindingIssueCode, ReviewQueueExtractionIssue, ReviewQueueExtractionIssueCode, ValidateReviewQueueBindingOptions, } from "./review-workbench/queue-binding.js";
|
|
6
|
+
export { assertReviewQueueAgainstExtractionImport, assertReviewQueueBinding, attestReviewQueueExtraction, bindReviewQueue, reviewItemCarriesExtractionBinding, unverifiedExtractionQueueSentence, hashReviewQueueSnapshot, UnattestedExtractionQueueError, UnattestedReviewQueueError, validateReviewQueueAgainstExtractionImport, validateReviewQueueBinding, } from "./review-workbench/queue-binding.js";
|
|
7
|
+
export type { BindReviewQueueOptions, ReviewQueueBinding, ReviewQueueBindingIssue, ReviewQueueBindingIssueCode, ReviewQueueExtractionAttestation, ReviewQueueExtractionIssue, ReviewQueueExtractionIssueCode, ValidateReviewQueueBindingOptions, } from "./review-workbench/queue-binding.js";
|
|
8
8
|
export { resolvePortablePdfRegion } from "./pdf-layout.js";
|
|
9
9
|
export type { PortablePdfBoundingBox, PortablePdfLayout, PortablePdfPageGeometry, PortablePdfRegionContext, PortablePdfTable, PortablePdfTableCell, PortablePdfTextElement, PortablePdfTextRange, } from "./pdf-layout.js";
|
|
10
10
|
export type { ExtractionAlignmentState, ArtifactUnavailableCode, BuiltExtractionInspectorCandidate, BuiltExtractionInspectorModel, ExtractionInspectorCandidate, ExtractionInspectorEntry, ExtractionInspectorExportOptions, ExtractionInspectorFilters, ExtractionInspectorInput, ExtractionInspectorModel, ExtractionInspectorSource, ResolvedExtractionArtifact, } from "./review-workbench/extraction-inspector.js";
|
|
@@ -38,7 +38,7 @@ export type { SourceAuthorityClass, SourceAuthorityMetadata, SourceOfAuthorityOb
|
|
|
38
38
|
export { buildCandidateVerification, candidateVerificationKind, DEFAULT_SUPPORT_VERIFIER_TIMEOUT_MS, MAX_SUPPORT_VERIFIER_TIMEOUT_MS, foldCandidateVerifications, runSupportVerifier, supportVerificationInputDigest, validateCandidateVerification, valueDigest, } from "./candidate-verification.js";
|
|
39
39
|
export type { BuildCandidateVerificationInput, CandidateVerification, CandidateVerificationInapplicableReason, CandidateVerificationStatus, CandidateVerificationSubject, FoldCandidateVerificationsResult, RunSupportVerifierOptions, SupportAbstainReason, SupportEvidence, SupportVerdict, SupportVerificationInput, SupportVerificationMethod, SupportVerificationResult, SupportVerifier, } from "./candidate-verification.js";
|
|
40
40
|
export { buildInterpretationReadingPresentation, buildReviewCandidatePresentation, buildReviewItemPresentation, buildReviewResultPresentation, candidateVerificationNotes, humanizeIdentifier, } from "./review-workbench/review-presentation.js";
|
|
41
|
-
export type { CandidateVerificationNote, CandidateVerificationRecordPresentation, InterpretationReadingPresentation, InterpretationReadingSource, ReviewCandidatePresentation, ReviewCandidatePresentationContext, ReviewItemPresentation, ReviewItemPresentationContext, ReviewPresentationAdapter, ReviewPresentationLink, ReviewResultPresentation, ReviewTracePresentationContext, ReviewTraceRef, ReviewValuePresentationContext, } from "./review-workbench/review-presentation.js";
|
|
41
|
+
export type { CandidateVerificationNote, CandidateVerificationRecordPresentation, ExcludedProposalPresentation, ExcludedProposalsUnreadable, InterpretationReadingPresentation, InterpretationReadingSource, ReviewCandidatePresentation, ReviewCandidatePresentationContext, ReviewItemPresentation, ReviewItemPresentationContext, ReviewPresentationAdapter, ReviewPresentationLink, ReviewResultPresentation, ReviewTracePresentationContext, ReviewTraceRef, ReviewValuePresentationContext, } from "./review-workbench/review-presentation.js";
|
|
42
42
|
export { apiRecordSource, manualEntrySource, policyStandardSource, uploadedDocumentSource, webPageSource, } from "./raw-source.js";
|
|
43
43
|
export type { ApiRecordSourceInput, ChecksumInput, ManualEntrySourceInput, PolicyStandardMetadata, PolicyStandardSourceInput, RawSourceInput, UploadedDocumentSourceInput, WebPageSourceInput, } from "./raw-source.js";
|
|
44
44
|
export { applyAutoAcceptPolicy, applyMappingReview, buildMappingReviewItems, lookupMapping, lookupRejectedMapping, normalizeQuestion, proposalsToCandidateSet, referenceMappingProposer, resolveQuestion, } from "./inquiry-mapping.js";
|
package/dist/src/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { SURVEY_INPUT_CONTRACT_VERSION } from "./types.js";
|
|
|
2
2
|
export { reviewResourceApiVersion } from "./review-resource.js";
|
|
3
3
|
export { buildReviewItemsFromExtractionEnvelopeImport, createExtractionEnvelopeResolutionIdentity, exportExtractionEnvelopeImport, extractionEnvelopeImportApiVersion, importExtractionEnvelope, portableExtractionResultFormat, portableExtractionResultVersion, reimportExtractionEnvelope, validateExtractionEnvelopeImport, } from "./extraction-envelope.js";
|
|
4
4
|
export { buildExtractionInspectorModel, exportExtractionInspector, inspectorSourcePosture, filterExtractionInspectorCandidates, } from "./review-workbench/extraction-inspector.js";
|
|
5
|
-
export { assertReviewQueueAgainstExtractionImport, assertReviewQueueBinding, bindReviewQueue, hashReviewQueueSnapshot, UnattestedExtractionQueueError, UnattestedReviewQueueError, validateReviewQueueAgainstExtractionImport, validateReviewQueueBinding, } from "./review-workbench/queue-binding.js";
|
|
5
|
+
export { assertReviewQueueAgainstExtractionImport, assertReviewQueueBinding, attestReviewQueueExtraction, bindReviewQueue, reviewItemCarriesExtractionBinding, unverifiedExtractionQueueSentence, hashReviewQueueSnapshot, UnattestedExtractionQueueError, UnattestedReviewQueueError, validateReviewQueueAgainstExtractionImport, validateReviewQueueBinding, } from "./review-workbench/queue-binding.js";
|
|
6
6
|
export { resolvePortablePdfRegion } from "./pdf-layout.js";
|
|
7
7
|
export { toSurfaceReviewedExtractionDecision, toSurfaceReviewedExtractionImport, toSurfaceReviewedExtractionItem, } from "./surface-reviewed-extraction.js";
|
|
8
8
|
export { candidateReviewRecord, candidateSetStatusFor, SurveyInputBuilder } from "./builder.js";
|