@kontourai/survey 1.3.0 → 1.5.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/README.md +1 -1
- package/dist/example-data/corrected-document-candidates.js +2 -2
- package/dist/example-data/public-directory-review-resource.d.ts +2 -2
- package/dist/example-data/public-directory-review-resource.js +2 -2
- package/dist/example-data/public-field-review.js +2 -2
- package/dist/example-data/regulated-document-review-resource.d.ts +2 -2
- package/dist/example-data/regulated-document-review-resource.js +2 -2
- package/dist/examples/public-field-observation.js +1 -1
- package/dist/examples/review-workbench/downstream-public-directory-adapter.js +1 -1
- package/dist/src/agent-utterance.d.ts +25 -0
- package/dist/src/agent-utterance.js +207 -95
- package/dist/src/console/review-console-server.js +3 -7
- package/dist/src/field-observation.d.ts +2 -16
- package/dist/src/field-observation.js +2 -14
- package/dist/src/index.d.ts +1 -1
- package/dist/src/inquiry-mapping.d.ts +2 -46
- package/dist/src/inquiry-mapping.js +37 -39
- package/dist/src/mcp/review-mcp.js +12 -12
- package/dist/src/observation-helper.d.ts +47 -1
- package/dist/src/observation-helper.js +41 -2
- package/dist/src/oversight-metrics.d.ts +2 -2
- package/dist/src/oversight-metrics.js +1 -1
- package/dist/src/producer-discipline.d.ts +40 -0
- package/dist/src/producer-discipline.js +13 -0
- package/dist/src/producer-profile.d.ts +134 -0
- package/dist/src/producer-profile.js +124 -0
- package/dist/src/raw-source.d.ts +18 -0
- package/dist/src/raw-source.js +28 -13
- package/dist/src/repeated-observation.d.ts +2 -16
- package/dist/src/repeated-observation.js +2 -14
- package/dist/src/review-proof.d.ts +2 -2
- package/dist/src/review-proof.js +2 -2
- package/dist/src/review-resource.d.ts +5 -1
- package/dist/src/review-workbench/review-workbench-data.d.ts +10 -10
- package/dist/src/review-workbench/review-workbench-data.js +6 -6
- package/dist/src/review-workbench/review-workbench.js +1 -1
- package/dist/src/review-workbench/server-review-session.d.ts +14 -1
- package/dist/src/review-workbench/server-review-session.js +16 -0
- package/dist/src/schema-mapping.js +32 -38
- package/dist/src/source-of-authority-observation.js +6 -9
- package/dist/src/to-surface.js +8 -11
- package/dist/src/types.d.ts +6 -1
- package/dist/src/vocabulary.d.ts +46 -4
- package/dist/src/vocabulary.js +29 -3
- package/package.json +6 -3
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* so that resolveInquiry can resolve across systems with weakest-link
|
|
21
21
|
* capping.
|
|
22
22
|
*/
|
|
23
|
+
import { AUTO_ACCEPT_ACTOR, AUTO_ACCEPT_WITHIN_COMFORT_ZONE, getProducerProposal, meetsAutoAcceptThreshold, projectProposalsToCandidateSet, } from "./producer-profile.js";
|
|
23
24
|
import { buildSurveyTrustBundle } from "./to-surface.js";
|
|
24
25
|
// ---------------------------------------------------------------------------
|
|
25
26
|
// Canonical pair key
|
|
@@ -84,10 +85,7 @@ export async function surveySchemaMapping(context, extractor, options = {}) {
|
|
|
84
85
|
const subjectId = mappingSubjectId(first.sourceField, first.targetField);
|
|
85
86
|
const candidateSetId = `schema-mapping.candidate-set.${pairKey}`;
|
|
86
87
|
const claimId = `schema-mapping.claim.${pairKey}`;
|
|
87
|
-
|
|
88
|
-
const relations = new Set(pairProposals.map((p) => p.relation));
|
|
89
|
-
const status = relations.size > 1 ? "conflict" : "needs-review";
|
|
90
|
-
const candidates = pairProposals.map((proposal) => {
|
|
88
|
+
const candidateSetProposals = pairProposals.map((proposal) => {
|
|
91
89
|
// Use the source system's RawSource for this extraction
|
|
92
90
|
const rawSource = sourceById.get(proposal.sourceField.system) ?? rawSources[0];
|
|
93
91
|
const extractionId = `schema-mapping.extraction.${proposal.id}`;
|
|
@@ -120,7 +118,7 @@ export async function surveySchemaMapping(context, extractor, options = {}) {
|
|
|
120
118
|
};
|
|
121
119
|
extractions.push(extraction);
|
|
122
120
|
return {
|
|
123
|
-
|
|
121
|
+
candidateId: `schema-mapping.candidate.${proposal.id}`,
|
|
124
122
|
extractionId,
|
|
125
123
|
value: {
|
|
126
124
|
relation: proposal.relation,
|
|
@@ -128,45 +126,41 @@ export async function surveySchemaMapping(context, extractor, options = {}) {
|
|
|
128
126
|
conversion: proposal.conversion,
|
|
129
127
|
},
|
|
130
128
|
confidence: proposal.confidence,
|
|
129
|
+
equivalenceKey: proposal.relation,
|
|
131
130
|
metadata: {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
proposedAt: proposal.proposedAt,
|
|
143
|
-
},
|
|
131
|
+
proposalId: proposal.id,
|
|
132
|
+
sourceField: proposal.sourceField,
|
|
133
|
+
targetField: proposal.targetField,
|
|
134
|
+
relation: proposal.relation,
|
|
135
|
+
conversion: proposal.conversion,
|
|
136
|
+
evidence: proposal.evidence,
|
|
137
|
+
confidence: proposal.confidence,
|
|
138
|
+
rationale: proposal.rationale,
|
|
139
|
+
proposedBy: proposal.proposedBy,
|
|
140
|
+
proposedAt: proposal.proposedAt,
|
|
144
141
|
},
|
|
145
142
|
};
|
|
146
143
|
});
|
|
147
|
-
const candidateSet = {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
candidates,
|
|
151
|
-
selectedCandidateId: status !== "conflict" ? candidates[0]?.id : undefined,
|
|
152
|
-
status,
|
|
153
|
-
rationale: status === "conflict"
|
|
154
|
-
? `Proposals disagree on relation for pair ${pairKey}: ${[...relations].join(", ")}`
|
|
155
|
-
: `${candidates.length} proposal(s) agree on relation "${first.relation}" for pair ${pairKey}.`,
|
|
156
|
-
metadata: {
|
|
144
|
+
const { candidateSet, candidates } = projectProposalsToCandidateSet(`schema-mapping:${pairKey}`, candidateSetProposals, {
|
|
145
|
+
candidateSetId,
|
|
146
|
+
candidateSetMetadata: {
|
|
157
147
|
schemaMapping: {
|
|
158
148
|
pairKey,
|
|
159
149
|
sourceField: first.sourceField,
|
|
160
150
|
targetField: first.targetField,
|
|
161
151
|
},
|
|
162
152
|
},
|
|
163
|
-
|
|
153
|
+
candidateSetRationale: (status, proposals) => status === "conflict"
|
|
154
|
+
? `Proposals disagree on relation for pair ${pairKey}: ${[...new Set(proposals.map((p) => p.equivalenceKey))].join(", ")}`
|
|
155
|
+
: `${proposals.length} proposal(s) agree on relation "${first.relation}" for pair ${pairKey}.`,
|
|
156
|
+
});
|
|
157
|
+
candidateSet.selectedCandidateId = candidateSet.status !== "conflict" ? candidates[0]?.id : undefined;
|
|
164
158
|
candidateSets.push(candidateSet);
|
|
165
159
|
// Auto-accept policy: non-conflicting proposals above threshold → assumed
|
|
166
160
|
let autoReviewStatus;
|
|
167
|
-
if (status !== "conflict" && options.autoAcceptMinConfidence !== undefined) {
|
|
161
|
+
if (candidateSet.status !== "conflict" && options.autoAcceptMinConfidence !== undefined) {
|
|
168
162
|
const topConfidence = Math.max(...pairProposals.map((p) => p.confidence));
|
|
169
|
-
if (topConfidence
|
|
163
|
+
if (meetsAutoAcceptThreshold(topConfidence, options.autoAcceptMinConfidence)) {
|
|
170
164
|
autoReviewStatus = "assumed";
|
|
171
165
|
}
|
|
172
166
|
}
|
|
@@ -180,10 +174,10 @@ export async function surveySchemaMapping(context, extractor, options = {}) {
|
|
|
180
174
|
candidateSetId,
|
|
181
175
|
candidateId: selectedCandidate.id,
|
|
182
176
|
status: autoReviewStatus,
|
|
183
|
-
actor:
|
|
177
|
+
actor: AUTO_ACCEPT_ACTOR,
|
|
184
178
|
reviewedAt: generatedAt,
|
|
185
179
|
rationale: `Auto-accepted: confidence ${selectedCandidate.confidence} >= threshold ${options.autoAcceptMinConfidence}`,
|
|
186
|
-
withinComfortZone:
|
|
180
|
+
withinComfortZone: AUTO_ACCEPT_WITHIN_COMFORT_ZONE,
|
|
187
181
|
});
|
|
188
182
|
}
|
|
189
183
|
// Project to ClaimTarget (subjectType "system-field", fieldOrBehavior "maps-to")
|
|
@@ -191,14 +185,14 @@ export async function surveySchemaMapping(context, extractor, options = {}) {
|
|
|
191
185
|
const review = reviewOutcomes.find((r) => r.candidateSetId === candidateSetId);
|
|
192
186
|
const claimStatus = review
|
|
193
187
|
? review.status
|
|
194
|
-
: (status === "conflict" ? "disputed" : undefined);
|
|
188
|
+
: (candidateSet.status === "conflict" ? "disputed" : undefined);
|
|
195
189
|
const claimTarget = {
|
|
196
190
|
id: claimId,
|
|
197
191
|
candidateSetId,
|
|
198
192
|
candidateId: selectedCandidate.id,
|
|
199
193
|
subjectType: "system-field",
|
|
200
194
|
subjectId: subjectId,
|
|
201
|
-
|
|
195
|
+
facet: "schema-mapping.profile",
|
|
202
196
|
claimType: "schema-mapping.field-link",
|
|
203
197
|
fieldOrBehavior: "maps-to",
|
|
204
198
|
value: {
|
|
@@ -266,7 +260,7 @@ export function mappingReviewToSurface(reviewedMappings, options = {}) {
|
|
|
266
260
|
const rawSources = [];
|
|
267
261
|
const seenSources = new Set();
|
|
268
262
|
for (const rm of accepted) {
|
|
269
|
-
const meta = rm.selectedCandidate
|
|
263
|
+
const meta = getProducerProposal(rm.selectedCandidate);
|
|
270
264
|
const sourceField = meta?.sourceField ?? rm.proposal.sourceField;
|
|
271
265
|
const sourceId = `schema-mapping.source.${sourceField.system}`;
|
|
272
266
|
if (!seenSources.has(sourceId)) {
|
|
@@ -290,7 +284,7 @@ export function mappingReviewToSurface(reviewedMappings, options = {}) {
|
|
|
290
284
|
const reviewOutcomes = [];
|
|
291
285
|
const claims = [];
|
|
292
286
|
for (const rm of accepted) {
|
|
293
|
-
const meta = rm.selectedCandidate
|
|
287
|
+
const meta = getProducerProposal(rm.selectedCandidate);
|
|
294
288
|
const sourceField = meta?.sourceField ?? rm.proposal.sourceField;
|
|
295
289
|
const targetField = meta?.targetField ?? rm.proposal.targetField;
|
|
296
290
|
const relation = (meta?.relation ?? rm.proposal.relation);
|
|
@@ -342,7 +336,7 @@ export function mappingReviewToSurface(reviewedMappings, options = {}) {
|
|
|
342
336
|
candidateId: rm.selectedCandidate.id,
|
|
343
337
|
subjectType: "system-field",
|
|
344
338
|
subjectId,
|
|
345
|
-
|
|
339
|
+
facet: "schema-mapping.profile",
|
|
346
340
|
claimType: "schema-mapping.field-link",
|
|
347
341
|
fieldOrBehavior: "maps-to",
|
|
348
342
|
value: { relation, sourceField, targetField, conversion },
|
|
@@ -379,7 +373,7 @@ export function mappingReviewToSurface(reviewedMappings, options = {}) {
|
|
|
379
373
|
// subject and back-references the mapping claim via mappingClaimId.
|
|
380
374
|
const identityLinks = [];
|
|
381
375
|
for (const rm of accepted) {
|
|
382
|
-
const meta = rm.selectedCandidate
|
|
376
|
+
const meta = getProducerProposal(rm.selectedCandidate);
|
|
383
377
|
const sourceField = meta?.sourceField ?? rm.proposal.sourceField;
|
|
384
378
|
const targetField = meta?.targetField ?? rm.proposal.targetField;
|
|
385
379
|
const relation = (meta?.relation ?? rm.proposal.relation);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { buildObservation } from "./observation-helper.js";
|
|
2
|
+
import { assertReviewOutcomeDiscipline } from "./producer-discipline.js";
|
|
2
3
|
export class SourceOfAuthorityObservationBuilder {
|
|
3
4
|
state;
|
|
4
5
|
constructor(args) {
|
|
@@ -115,15 +116,11 @@ function assertVerifiedPosture(input) {
|
|
|
115
116
|
if (!input.extraction.locator) {
|
|
116
117
|
throw new Error(`Source-of-authority observation ${input.id} cannot be ${status} without a source locator`);
|
|
117
118
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
if (!input.reviewOutcome.reviewedAt) {
|
|
125
|
-
throw new Error(`Source-of-authority observation ${input.id} cannot be ${status} without reviewedAt`);
|
|
126
|
-
}
|
|
119
|
+
assertReviewOutcomeDiscipline({
|
|
120
|
+
subject: `Source-of-authority observation ${input.id}`,
|
|
121
|
+
status,
|
|
122
|
+
review: input.reviewOutcome,
|
|
123
|
+
});
|
|
127
124
|
}
|
|
128
125
|
function claimStatus(claimStatusValue, reviewStatus) {
|
|
129
126
|
return claimStatusValue ?? reviewStatus;
|
package/dist/src/to-surface.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { buildReviewProofAnchor } from "./review-proof.js";
|
|
2
|
+
import { assertReviewOutcomeDiscipline } from "./producer-discipline.js";
|
|
2
3
|
export function buildSurveyTrustBundle(input, options = {}) {
|
|
3
4
|
const rawSources = indexById(input.rawSources, "raw source");
|
|
4
5
|
const extractions = indexById(input.extractions, "extraction");
|
|
@@ -23,7 +24,7 @@ export function buildSurveyTrustBundle(input, options = {}) {
|
|
|
23
24
|
id: projection.id,
|
|
24
25
|
subjectType: projection.subjectType,
|
|
25
26
|
subjectId: projection.subjectId,
|
|
26
|
-
|
|
27
|
+
facet: projection.facet,
|
|
27
28
|
claimType: projection.claimType,
|
|
28
29
|
fieldOrBehavior: projection.fieldOrBehavior,
|
|
29
30
|
value: claimValue,
|
|
@@ -120,7 +121,7 @@ export function buildSurveyTrustBundle(input, options = {}) {
|
|
|
120
121
|
}
|
|
121
122
|
}
|
|
122
123
|
return {
|
|
123
|
-
schemaVersion:
|
|
124
|
+
schemaVersion: 5,
|
|
124
125
|
source: input.source,
|
|
125
126
|
claims,
|
|
126
127
|
evidence,
|
|
@@ -334,15 +335,11 @@ function statusFor(input) {
|
|
|
334
335
|
return "proposed";
|
|
335
336
|
}
|
|
336
337
|
function assertProducerDiscipline(input) {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
if ((input.status === "verified" || input.status === "assumed") && !input.review?.reviewedAt) {
|
|
344
|
-
throw new Error(`Claim ${input.projection.id} cannot be ${input.status} without reviewedAt`);
|
|
345
|
-
}
|
|
338
|
+
assertReviewOutcomeDiscipline({
|
|
339
|
+
subject: `Claim ${input.projection.id}`,
|
|
340
|
+
status: input.status,
|
|
341
|
+
review: input.review,
|
|
342
|
+
});
|
|
346
343
|
if (input.rawSource.kind !== "manual-entry" && !input.extraction.locator) {
|
|
347
344
|
throw new Error(`Claim ${input.projection.id} needs a source locator for ${input.rawSource.kind}`);
|
|
348
345
|
}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -111,7 +111,12 @@ export interface ClaimTarget {
|
|
|
111
111
|
candidateId?: string;
|
|
112
112
|
subjectType: string;
|
|
113
113
|
subjectId: string;
|
|
114
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Producer-defined grouping or namespace for this claim (Hachure schema 5,
|
|
116
|
+
* surface@2.0.0: Claim.surface -> Claim.facet). Projected onto the emitted
|
|
117
|
+
* Claim's `facet` field by {@link buildSurveyTrustBundle}.
|
|
118
|
+
*/
|
|
119
|
+
facet: string;
|
|
115
120
|
claimType: string;
|
|
116
121
|
fieldOrBehavior: string;
|
|
117
122
|
value?: unknown;
|
package/dist/src/vocabulary.d.ts
CHANGED
|
@@ -11,22 +11,64 @@ import type { ConfidenceBasis, ImpactLevel, TrustStatus } from "@kontourai/surfa
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function stableId(parts: ReadonlyArray<string | number>): string;
|
|
13
13
|
/**
|
|
14
|
-
* A product's Survey/Surface vocabulary: the subject type and
|
|
14
|
+
* A product's Survey/Surface vocabulary: the subject type and facet it
|
|
15
15
|
* projects onto, its claim-type names, and its decision-effect names. Generic
|
|
16
16
|
* over the caller's claim-type and decision-effect key maps so the concrete
|
|
17
17
|
* string literals stay visible to callers.
|
|
18
|
+
*
|
|
19
|
+
* `facet` mirrors Surface's `Claim.facet` (Hachure schema 5 facet rename:
|
|
20
|
+
* `Claim.surface` -> `Claim.facet`, surface@2.0.0). The now-deprecated
|
|
21
|
+
* `surface` property is kept, mirroring `facet`, for one release so existing
|
|
22
|
+
* readers of `.surface` do not break; read `.facet` going forward.
|
|
18
23
|
*/
|
|
19
24
|
export interface ProductVocabularyDefinition<TClaimTypes extends Readonly<Record<string, string>>, TDecisionEffects extends Readonly<Record<string, string>>> {
|
|
20
25
|
readonly subjectType: string;
|
|
26
|
+
readonly facet: string;
|
|
27
|
+
/**
|
|
28
|
+
* @deprecated Renamed to {@link ProductVocabularyDefinition.facet} (Hachure
|
|
29
|
+
* schema 5 facet rename: `Claim.surface` -> `Claim.facet`). Mirrors `facet`
|
|
30
|
+
* for one release; read `.facet` going forward.
|
|
31
|
+
*/
|
|
21
32
|
readonly surface: string;
|
|
22
33
|
readonly claimTypes: TClaimTypes;
|
|
23
34
|
readonly decisionEffects: TDecisionEffects;
|
|
24
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Input accepted by {@link defineProductVocabulary}: `facet` is the
|
|
38
|
+
* canonical name; the deprecated `surface` name is still accepted for one
|
|
39
|
+
* release as a read-compat alias (Hachure schema 5 facet rename). Exactly
|
|
40
|
+
* one of `facet` / `surface` is required — the union below is what makes
|
|
41
|
+
* "at least one of these two" a compile-time requirement rather than a
|
|
42
|
+
* runtime-only check.
|
|
43
|
+
*/
|
|
44
|
+
export type ProductVocabularyInput<TClaimTypes extends Readonly<Record<string, string>>, TDecisionEffects extends Readonly<Record<string, string>>> = {
|
|
45
|
+
readonly subjectType: string;
|
|
46
|
+
readonly claimTypes: TClaimTypes;
|
|
47
|
+
readonly decisionEffects: TDecisionEffects;
|
|
48
|
+
} & ({
|
|
49
|
+
readonly facet: string;
|
|
50
|
+
readonly surface?: string;
|
|
51
|
+
} | {
|
|
52
|
+
readonly facet?: undefined;
|
|
53
|
+
/**
|
|
54
|
+
* @deprecated Renamed to `facet` (Hachure schema 5 facet rename:
|
|
55
|
+
* `Claim.surface` -> `Claim.facet`). Accepted for one release; using it
|
|
56
|
+
* without also passing `facet` emits a single deprecation warning per
|
|
57
|
+
* process. Prefer `facet`.
|
|
58
|
+
*/
|
|
59
|
+
readonly surface: string;
|
|
60
|
+
});
|
|
25
61
|
/**
|
|
26
62
|
* Defines a product vocabulary as a deep-frozen, discoverable value that a
|
|
27
63
|
* `currentProposedReviewItem` caller can pass instead of loose top-level
|
|
28
|
-
* constants. Returns the same shape it received
|
|
29
|
-
*
|
|
64
|
+
* constants. Returns the same shape it received (plus the mirrored
|
|
65
|
+
* deprecated `surface` alias — see {@link ProductVocabularyDefinition}),
|
|
66
|
+
* frozen so callers cannot mutate a shared vocabulary at runtime.
|
|
67
|
+
*
|
|
68
|
+
* Accepts either the canonical `facet` option or the deprecated `surface`
|
|
69
|
+
* option (not both required — `facet` wins when both are supplied, and
|
|
70
|
+
* using `surface` alone emits a single deprecation warning per process; see
|
|
71
|
+
* {@link ProductVocabularyInput}).
|
|
30
72
|
*
|
|
31
73
|
* The type parameters carry the `const` modifier, so `claimTypes` and
|
|
32
74
|
* `decisionEffects` string properties keep their literal types whether or
|
|
@@ -40,7 +82,7 @@ export interface ProductVocabularyDefinition<TClaimTypes extends Readonly<Record
|
|
|
40
82
|
* `peerDependencies.typescript` and `docs/upgrade-guide.md`); this is a
|
|
41
83
|
* types-only floor and does not affect JavaScript consumers.
|
|
42
84
|
*/
|
|
43
|
-
export declare function defineProductVocabulary<const TClaimTypes extends Readonly<Record<string, string>>, const TDecisionEffects extends Readonly<Record<string, string>>>(definition:
|
|
85
|
+
export declare function defineProductVocabulary<const TClaimTypes extends Readonly<Record<string, string>>, const TDecisionEffects extends Readonly<Record<string, string>>>(definition: ProductVocabularyInput<TClaimTypes, TDecisionEffects>): ProductVocabularyDefinition<TClaimTypes, TDecisionEffects>;
|
|
44
86
|
export interface ConfidenceBasisForReviewInput {
|
|
45
87
|
readonly status: TrustStatus;
|
|
46
88
|
readonly impactLevel: ImpactLevel;
|
package/dist/src/vocabulary.js
CHANGED
|
@@ -16,11 +16,35 @@ export function stableId(parts) {
|
|
|
16
16
|
.toLowerCase())
|
|
17
17
|
.join(".");
|
|
18
18
|
}
|
|
19
|
+
let warnedLegacyVocabularySurfaceOnce = false;
|
|
20
|
+
function warnLegacyVocabularySurfaceOnce() {
|
|
21
|
+
if (warnedLegacyVocabularySurfaceOnce)
|
|
22
|
+
return;
|
|
23
|
+
warnedLegacyVocabularySurfaceOnce = true;
|
|
24
|
+
console.warn("[@kontourai/survey] deprecated: defineProductVocabulary's \"surface\" option is renamed to " +
|
|
25
|
+
"\"facet\" (Hachure schema 5 facet rename: Claim.surface -> Claim.facet, surface@2.0.0). " +
|
|
26
|
+
"Pass \"facet\" instead of \"surface\"; \"surface\" is accepted for one release as a read-compat alias.");
|
|
27
|
+
}
|
|
28
|
+
function resolveFacet(definition) {
|
|
29
|
+
if (definition.facet !== undefined)
|
|
30
|
+
return definition.facet;
|
|
31
|
+
if (definition.surface !== undefined) {
|
|
32
|
+
warnLegacyVocabularySurfaceOnce();
|
|
33
|
+
return definition.surface;
|
|
34
|
+
}
|
|
35
|
+
throw new Error('defineProductVocabulary requires "facet" (or deprecated "surface")');
|
|
36
|
+
}
|
|
19
37
|
/**
|
|
20
38
|
* Defines a product vocabulary as a deep-frozen, discoverable value that a
|
|
21
39
|
* `currentProposedReviewItem` caller can pass instead of loose top-level
|
|
22
|
-
* constants. Returns the same shape it received
|
|
23
|
-
*
|
|
40
|
+
* constants. Returns the same shape it received (plus the mirrored
|
|
41
|
+
* deprecated `surface` alias — see {@link ProductVocabularyDefinition}),
|
|
42
|
+
* frozen so callers cannot mutate a shared vocabulary at runtime.
|
|
43
|
+
*
|
|
44
|
+
* Accepts either the canonical `facet` option or the deprecated `surface`
|
|
45
|
+
* option (not both required — `facet` wins when both are supplied, and
|
|
46
|
+
* using `surface` alone emits a single deprecation warning per process; see
|
|
47
|
+
* {@link ProductVocabularyInput}).
|
|
24
48
|
*
|
|
25
49
|
* The type parameters carry the `const` modifier, so `claimTypes` and
|
|
26
50
|
* `decisionEffects` string properties keep their literal types whether or
|
|
@@ -35,9 +59,11 @@ export function stableId(parts) {
|
|
|
35
59
|
* types-only floor and does not affect JavaScript consumers.
|
|
36
60
|
*/
|
|
37
61
|
export function defineProductVocabulary(definition) {
|
|
62
|
+
const facet = resolveFacet(definition);
|
|
38
63
|
return deepFreeze({
|
|
39
64
|
subjectType: definition.subjectType,
|
|
40
|
-
|
|
65
|
+
facet,
|
|
66
|
+
surface: facet,
|
|
41
67
|
claimTypes: { ...definition.claimTypes },
|
|
42
68
|
decisionEffects: { ...definition.decisionEffects },
|
|
43
69
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kontourai/survey",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
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",
|
|
@@ -55,8 +55,11 @@
|
|
|
55
55
|
"typecheck": "tsc --noEmit",
|
|
56
56
|
"test": "npm run build && node --test dist/tests/*.test.js",
|
|
57
57
|
"test:browser": "playwright test",
|
|
58
|
-
"verify": "node scripts/check-content-boundary.cjs && npm run typecheck && npm test && npm run check:review-workbench-assets && npm run check:review-workbench && npm run test:browser",
|
|
58
|
+
"verify": "node scripts/check-content-boundary.cjs && npm run check:decisions && npm run typecheck && npm test && npm run check:review-workbench-assets && npm run check:review-workbench && npm run test:browser",
|
|
59
59
|
"check:content-boundary": "node scripts/check-content-boundary.cjs",
|
|
60
|
+
"check:decisions": "node scripts/check-decisions.cjs check",
|
|
61
|
+
"gen:decisions-index": "node scripts/check-decisions.cjs gen-index",
|
|
62
|
+
"freeze:adrs": "node scripts/freeze-adrs.mjs",
|
|
60
63
|
"sync:review-workbench-assets": "node scripts/sync-review-workbench-assets.cjs",
|
|
61
64
|
"check:review-workbench-assets": "node scripts/sync-review-workbench-assets.cjs --check",
|
|
62
65
|
"check:review-workbench": "npm run check:review-workbench:static && npm run check:generated-css",
|
|
@@ -68,7 +71,7 @@
|
|
|
68
71
|
"check:generated-css": "node scripts/copy-review-workbench-package-assets.cjs --check"
|
|
69
72
|
},
|
|
70
73
|
"dependencies": {
|
|
71
|
-
"@kontourai/surface": "^
|
|
74
|
+
"@kontourai/surface": "^2.0.0"
|
|
72
75
|
},
|
|
73
76
|
"peerDependencies": {
|
|
74
77
|
"@anthropic-ai/sdk": ">=0.20.0",
|