@kontourai/survey 0.2.1 → 0.4.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 +30 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +2 -0
- package/dist/src/reviewed-candidate-resolution.d.ts +18 -0
- package/dist/src/reviewed-candidate-resolution.js +36 -0
- package/dist/src/reviewed-current-proposed-resolution.d.ts +10 -0
- package/dist/src/reviewed-current-proposed-resolution.js +49 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -183,6 +183,36 @@ preserved. Producers still own scalar semantics, validation, candidate ranking,
|
|
|
183
183
|
review policy, and whether a value should be verified, proposed, rejected, or
|
|
184
184
|
assumed.
|
|
185
185
|
|
|
186
|
+
## Reviewed candidate resolutions
|
|
187
|
+
|
|
188
|
+
Use `reviewedCandidateResolution` when a producer has multiple candidate
|
|
189
|
+
observations for the same target and a review outcome selects one candidate.
|
|
190
|
+
The helper wraps `candidateReviewRecord`, attaches the review outcome to the
|
|
191
|
+
selected candidate, defaults the candidate set to `resolved`, defaults the
|
|
192
|
+
selected claim status from the review outcome, and defaults unselected
|
|
193
|
+
candidates to `superseded`. Producers can override selected or unselected claim
|
|
194
|
+
statuses when their domain workflow needs a different posture.
|
|
195
|
+
|
|
196
|
+
This is useful for corrected documents, source-of-truth choices, and review
|
|
197
|
+
queues where losing candidates should remain visible for transparency rather
|
|
198
|
+
than disappearing from the trust trail.
|
|
199
|
+
|
|
200
|
+
## Reviewed current/proposed resolutions
|
|
201
|
+
|
|
202
|
+
Use `reviewedCurrentProposedResolution` when a producer has exactly two
|
|
203
|
+
candidate roles for the same target: the current value the producer would keep
|
|
204
|
+
absent a change, and a proposed value introduced by new source material,
|
|
205
|
+
extraction, or review work. The helper consumes full observations, selects
|
|
206
|
+
either the current or proposed candidate through `selectedCandidateRole`, and
|
|
207
|
+
wraps the result with `reviewedCandidateResolution`.
|
|
208
|
+
|
|
209
|
+
The helper may promote the selected candidate to a caller-supplied
|
|
210
|
+
`selectedClaimId`. The unselected observation keeps its caller-authored claim
|
|
211
|
+
id, so producers can keep losing candidates as candidate-specific history.
|
|
212
|
+
Survey does not decide producer policy: callers still own review status,
|
|
213
|
+
selected and unselected claim statuses, source details, claim vocabulary, and
|
|
214
|
+
domain metadata.
|
|
215
|
+
|
|
186
216
|
## Repeated observations
|
|
187
217
|
|
|
188
218
|
Use `repeatedObservation` when a producer wants to describe a repeated field or
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export type { CandidateSetStatus, Candidate, CandidateSet, ClaimTarget, Extraction, LocatorScheme, RawSource, RawSourceKind, ReviewOutcome, ReviewStatus, SurveyInput, } from "./types.js";
|
|
2
2
|
export { candidateReviewRecord, SurveyInputBuilder } from "./builder.js";
|
|
3
3
|
export type { CandidateReviewRecordInput, SurveyClaimRecord, SurveyInputBuilderArgs, SurveyObservationInput, } from "./builder.js";
|
|
4
|
+
export { reviewedCandidateResolution } from "./reviewed-candidate-resolution.js";
|
|
5
|
+
export type { ReviewedCandidateResolutionInput } from "./reviewed-candidate-resolution.js";
|
|
6
|
+
export { reviewedCurrentProposedResolution } from "./reviewed-current-proposed-resolution.js";
|
|
7
|
+
export type { CurrentProposedCandidateRole, ReviewedCurrentProposedResolutionInput, } from "./reviewed-current-proposed-resolution.js";
|
|
4
8
|
export { buildSurveyTrustInput } from "./to-surface.js";
|
|
5
9
|
export { fieldObservation } from "./field-observation.js";
|
|
6
10
|
export type { FieldObservationInput } from "./field-observation.js";
|
package/dist/src/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { candidateReviewRecord, SurveyInputBuilder } from "./builder.js";
|
|
2
|
+
export { reviewedCandidateResolution } from "./reviewed-candidate-resolution.js";
|
|
3
|
+
export { reviewedCurrentProposedResolution } from "./reviewed-current-proposed-resolution.js";
|
|
2
4
|
export { buildSurveyTrustInput } from "./to-surface.js";
|
|
3
5
|
export { fieldObservation } from "./field-observation.js";
|
|
4
6
|
export { repeatedObservation } from "./repeated-observation.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type SurveyClaimRecord, type SurveyObservationInput } from "./builder.js";
|
|
2
|
+
import type { CandidateSet, ClaimTarget, ReviewOutcome } from "./types.js";
|
|
3
|
+
export interface ReviewedCandidateResolutionInput {
|
|
4
|
+
id: string;
|
|
5
|
+
target: string;
|
|
6
|
+
observations: SurveyObservationInput[];
|
|
7
|
+
selectedCandidateId: string;
|
|
8
|
+
rationale?: string;
|
|
9
|
+
metadata?: Record<string, unknown>;
|
|
10
|
+
status?: CandidateSet["status"];
|
|
11
|
+
reviewOutcome: Omit<ReviewOutcome, "id" | "candidateSetId" | "candidateId"> & {
|
|
12
|
+
id?: string;
|
|
13
|
+
candidateId?: string;
|
|
14
|
+
};
|
|
15
|
+
selectedClaimStatus?: ClaimTarget["status"];
|
|
16
|
+
unselectedClaimStatus?: ClaimTarget["status"];
|
|
17
|
+
}
|
|
18
|
+
export declare function reviewedCandidateResolution(input: ReviewedCandidateResolutionInput): SurveyClaimRecord[];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { candidateReviewRecord } from "./builder.js";
|
|
2
|
+
export function reviewedCandidateResolution(input) {
|
|
3
|
+
return candidateReviewRecord({
|
|
4
|
+
id: input.id,
|
|
5
|
+
target: input.target,
|
|
6
|
+
selectedCandidateId: input.selectedCandidateId,
|
|
7
|
+
status: input.status ?? candidateSetStatusForReview(input.reviewOutcome.status),
|
|
8
|
+
rationale: input.rationale,
|
|
9
|
+
metadata: input.metadata,
|
|
10
|
+
reviewOutcome: {
|
|
11
|
+
...input.reviewOutcome,
|
|
12
|
+
candidateId: input.reviewOutcome.candidateId ?? input.selectedCandidateId,
|
|
13
|
+
},
|
|
14
|
+
observations: input.observations.map((observation) => ({
|
|
15
|
+
...observation,
|
|
16
|
+
claim: {
|
|
17
|
+
...observation.claim,
|
|
18
|
+
status: observation.claim.status ?? claimStatusForObservation(input, observation),
|
|
19
|
+
},
|
|
20
|
+
})),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function claimStatusForObservation(input, observation) {
|
|
24
|
+
if (observationCandidateId(observation) === input.selectedCandidateId) {
|
|
25
|
+
return input.selectedClaimStatus ?? input.reviewOutcome.status;
|
|
26
|
+
}
|
|
27
|
+
return input.unselectedClaimStatus ?? "superseded";
|
|
28
|
+
}
|
|
29
|
+
function observationCandidateId(observation) {
|
|
30
|
+
return observation.candidate?.id ?? `${observation.id}.candidate`;
|
|
31
|
+
}
|
|
32
|
+
function candidateSetStatusForReview(status) {
|
|
33
|
+
if (status === "proposed")
|
|
34
|
+
return "needs-review";
|
|
35
|
+
return "resolved";
|
|
36
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ReviewedCandidateResolutionInput } from "./reviewed-candidate-resolution.js";
|
|
2
|
+
import type { SurveyClaimRecord, SurveyObservationInput } from "./builder.js";
|
|
3
|
+
export type CurrentProposedCandidateRole = "current" | "proposed";
|
|
4
|
+
export interface ReviewedCurrentProposedResolutionInput extends Omit<ReviewedCandidateResolutionInput, "observations" | "selectedCandidateId"> {
|
|
5
|
+
currentObservation: SurveyObservationInput;
|
|
6
|
+
proposedObservation: SurveyObservationInput;
|
|
7
|
+
selectedCandidateRole: CurrentProposedCandidateRole;
|
|
8
|
+
selectedClaimId?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function reviewedCurrentProposedResolution(input: ReviewedCurrentProposedResolutionInput): SurveyClaimRecord[];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { reviewedCandidateResolution } from "./reviewed-candidate-resolution.js";
|
|
2
|
+
export function reviewedCurrentProposedResolution(input) {
|
|
3
|
+
const currentCandidateId = candidateIdFor(input, "current", input.currentObservation);
|
|
4
|
+
const proposedCandidateId = candidateIdFor(input, "proposed", input.proposedObservation);
|
|
5
|
+
const selectedCandidateId = input.selectedCandidateRole === "current"
|
|
6
|
+
? currentCandidateId
|
|
7
|
+
: proposedCandidateId;
|
|
8
|
+
return reviewedCandidateResolution({
|
|
9
|
+
...input,
|
|
10
|
+
selectedCandidateId,
|
|
11
|
+
observations: [
|
|
12
|
+
observationForRole({
|
|
13
|
+
input,
|
|
14
|
+
role: "current",
|
|
15
|
+
candidateId: currentCandidateId,
|
|
16
|
+
observation: input.currentObservation,
|
|
17
|
+
}),
|
|
18
|
+
observationForRole({
|
|
19
|
+
input,
|
|
20
|
+
role: "proposed",
|
|
21
|
+
candidateId: proposedCandidateId,
|
|
22
|
+
observation: input.proposedObservation,
|
|
23
|
+
}),
|
|
24
|
+
],
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function observationForRole(input) {
|
|
28
|
+
const selected = input.input.selectedCandidateRole === input.role;
|
|
29
|
+
return {
|
|
30
|
+
...input.observation,
|
|
31
|
+
candidate: {
|
|
32
|
+
...input.observation.candidate,
|
|
33
|
+
id: input.candidateId,
|
|
34
|
+
metadata: {
|
|
35
|
+
...input.observation.candidate?.metadata,
|
|
36
|
+
candidateRole: input.role,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
claim: {
|
|
40
|
+
...input.observation.claim,
|
|
41
|
+
id: selected && input.input.selectedClaimId
|
|
42
|
+
? input.input.selectedClaimId
|
|
43
|
+
: input.observation.claim.id,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function candidateIdFor(input, role, observation) {
|
|
48
|
+
return observation.candidate?.id ?? `${input.id}.${role}.candidate`;
|
|
49
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kontourai/survey",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.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",
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
"build": "rm -rf dist && tsc",
|
|
32
32
|
"typecheck": "tsc --noEmit",
|
|
33
33
|
"test": "npm run build && node --test dist/tests/*.test.js",
|
|
34
|
-
"verify": "npm run typecheck && npm test"
|
|
34
|
+
"verify": "node scripts/check-content-boundary.cjs && npm run typecheck && npm test",
|
|
35
|
+
"check:content-boundary": "node scripts/check-content-boundary.cjs"
|
|
35
36
|
},
|
|
36
37
|
"dependencies": {
|
|
37
38
|
"@kontourai/surface": "^0.5.0"
|