reploid 0.0.0-stage → 0.1.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/apps/poolday/config/chat-files.json +27 -0
- package/apps/poolday/config/partition-generation.js +21 -0
- package/apps/poolday/config/partition-policy.json +74 -0
- package/apps/poolday/config/partition-releases.json +3 -0
- package/apps/poolday/config/work-profile.json +122 -0
- package/apps/poolday/host/chat-view.js +47 -0
- package/apps/poolday/host/earning/client.js +199 -0
- package/apps/poolday/host/earning/contribution.js +168 -0
- package/apps/poolday/host/partition-release.js +33 -0
- package/apps/poolday/host/work-partition-artifact-source.js +37 -0
- package/apps/poolday/host/work-partition-capsule.js +39 -0
- package/apps/poolday/host/work-partition-plan.js +167 -0
- package/apps/poolday/host/work-partition-tokenizer-guard.js +21 -0
- package/apps/poolday/infrastructure/model-storage-lock.js +22 -0
- package/apps/poolday/infrastructure/pack-release-storage.js +52 -0
- package/apps/poolday/pool/pack-operation.js +161 -0
- package/apps/poolday/pool/pack-release-policy.js +44 -0
- package/apps/poolday/pool/peer-pack-data-channel.js +217 -0
- package/apps/poolday/providers/work-adapter.js +67 -0
- package/apps/poolday/providers/work-device.js +33 -0
- package/apps/poolday/providers/work-generation-completion.js +55 -0
- package/apps/poolday/providers/work-provider.js +209 -0
- package/apps/poolday/providers/work-resident-provider.js +113 -0
- package/deploy/artifacts/doppler-gpu-0.7.1.tgz +0 -0
- package/docs/fleet-service.md +214 -0
- package/docs/native-participant.md +534 -0
- package/native-delivery.json +1174 -0
- package/package.json +29 -4
- package/packages/reploid/src/artifacts/binary.js +25 -0
- package/packages/reploid/src/artifacts/canonical-json.js +23 -0
- package/packages/reploid/src/artifacts/custody/exchange.js +402 -0
- package/packages/reploid/src/artifacts/custody/piece-acquisition.js +70 -0
- package/packages/reploid/src/artifacts/custody/runtime.js +404 -0
- package/packages/reploid/src/artifacts/custody/supply-budget.js +19 -0
- package/packages/reploid/src/artifacts/custody-certificate.js +123 -0
- package/packages/reploid/src/artifacts/delivery-attestation.js +64 -0
- package/packages/reploid/src/artifacts/generation-terminal.js +36 -0
- package/packages/reploid/src/artifacts/identity.js +91 -0
- package/packages/reploid/src/artifacts/participant-proofs.js +159 -0
- package/packages/reploid/src/artifacts/receipt.js +131 -0
- package/packages/reploid/src/artifacts/signatures.js +94 -0
- package/packages/reploid/src/artifacts/whole-model-receipt.js +42 -0
- package/packages/reploid/src/cancellation.js +44 -0
- package/packages/reploid/src/config/defaults.json +110 -0
- package/packages/reploid/src/config/index.js +209 -0
- package/packages/reploid/src/config/request-overrides.json +9 -0
- package/packages/reploid/src/config/transport-defaults.json +7 -0
- package/packages/reploid/src/hashing.js +30 -0
- package/packages/reploid/src/measurement/capacity-utilization.js +321 -0
- package/packages/reploid/src/measurement/index.js +5 -0
- package/packages/reploid/src/measurement/readiness-records.js +310 -0
- package/packages/reploid/src/mesh/computer-identity.js +50 -0
- package/packages/reploid/src/mesh/computer-identity.policy.json +8 -0
- package/packages/reploid/src/mesh/contribution.js +141 -0
- package/packages/reploid/src/mesh/generation-recovery.js +58 -0
- package/packages/reploid/src/mesh/gpu-signature-shader.js +27 -0
- package/packages/reploid/src/mesh/gpu-signature.js +136 -0
- package/packages/reploid/src/mesh/gpu-signature.policy.json +11 -0
- package/packages/reploid/src/mesh/index.js +66 -0
- package/packages/reploid/src/mesh/partitions/automatic-ordered-partitions.js +540 -0
- package/packages/reploid/src/mesh/partitions/automatic-partitions.js +298 -0
- package/packages/reploid/src/mesh/partitions/partition-attempt-evidence.js +282 -0
- package/packages/reploid/src/mesh/partitions/partition-attempt-queue-policy.json +6 -0
- package/packages/reploid/src/mesh/partitions/partition-attempt-queue.js +112 -0
- package/packages/reploid/src/mesh/partitions/partition-canonical-contract.js +167 -0
- package/packages/reploid/src/mesh/partitions/partition-canonical-execution.js +168 -0
- package/packages/reploid/src/mesh/partitions/partition-chat-canonical.js +49 -0
- package/packages/reploid/src/mesh/partitions/partition-chat.js +125 -0
- package/packages/reploid/src/mesh/partitions/partition-contract.js +192 -0
- package/packages/reploid/src/mesh/partitions/partition-device-admission.js +96 -0
- package/packages/reploid/src/mesh/partitions/partition-discovery.js +96 -0
- package/packages/reploid/src/mesh/partitions/partition-entry-publication.js +183 -0
- package/packages/reploid/src/mesh/partitions/partition-entry.js +434 -0
- package/packages/reploid/src/mesh/partitions/partition-generation-request.js +33 -0
- package/packages/reploid/src/mesh/partitions/partition-grants.js +277 -0
- package/packages/reploid/src/mesh/partitions/partition-link.js +103 -0
- package/packages/reploid/src/mesh/partitions/partition-network.js +109 -0
- package/packages/reploid/src/mesh/partitions/partition-ordered-chat.js +290 -0
- package/packages/reploid/src/mesh/partitions/partition-ordered-peer.js +415 -0
- package/packages/reploid/src/mesh/partitions/partition-ordered-publication.js +100 -0
- package/packages/reploid/src/mesh/partitions/partition-peer.js +314 -0
- package/packages/reploid/src/mesh/partitions/partition-placement.js +143 -0
- package/packages/reploid/src/mesh/partitions/partition-preparation-progress.js +25 -0
- package/packages/reploid/src/mesh/partitions/partition-receiver-policy.json +7 -0
- package/packages/reploid/src/mesh/partitions/partition-reservations.js +75 -0
- package/packages/reploid/src/mesh/partitions/partition-route-envelope-policy.json +16 -0
- package/packages/reploid/src/mesh/partitions/partition-route-envelope.js +74 -0
- package/packages/reploid/src/mesh/partitions/partition-route-execution.js +409 -0
- package/packages/reploid/src/mesh/partitions/partition-route-network.js +179 -0
- package/packages/reploid/src/mesh/partitions/partition-route-ranking.js +268 -0
- package/packages/reploid/src/mesh/partitions/partition-runner.js +319 -0
- package/packages/reploid/src/mesh/partitions/partition-stage-assignment.js +109 -0
- package/packages/reploid/src/mesh/partitions/partition-stage-commit.js +103 -0
- package/packages/reploid/src/mesh/partitions/partition-step-receiver.js +291 -0
- package/packages/reploid/src/mesh/partitions/partition-summary.js +122 -0
- package/packages/reploid/src/mesh/partitions/preparation-owner.js +40 -0
- package/packages/reploid/src/mesh/partitions/resident-error-codes.json +10 -0
- package/packages/reploid/src/mesh/partitions/resident-partition.js +333 -0
- package/packages/reploid/src/mesh/partitions/resident-route.js +46 -0
- package/packages/reploid/src/mesh/partitions/signed-resident-factory.js +59 -0
- package/packages/reploid/src/mesh/peer-generation.js +896 -0
- package/packages/reploid/src/mesh/peer-identity.js +87 -0
- package/packages/reploid/src/mesh/placement-beliefs.js +107 -0
- package/packages/reploid/src/mesh/preparation-progress.js +46 -0
- package/packages/reploid/src/mesh/provider-hardware.js +11 -0
- package/packages/reploid/src/mesh/remote-generation-requests.js +53 -0
- package/packages/reploid/src/mesh/swarm-coordination.js +140 -0
- package/packages/reploid/src/mesh/web-access-network.js +112 -0
- package/packages/reploid/src/mesh/web-access-policy.json +17 -0
- package/packages/reploid/src/retrieval/citations.js +156 -0
- package/packages/reploid/src/retrieval/claim-support.js +113 -0
- package/packages/reploid/src/retrieval/costs.js +101 -0
- package/packages/reploid/src/retrieval/fixed-provider.js +34 -0
- package/packages/reploid/src/retrieval/index.js +20 -0
- package/packages/reploid/src/retrieval/lexical-support.js +27 -0
- package/packages/reploid/src/retrieval/model-reviewer.js +67 -0
- package/packages/reploid/src/retrieval/page-fetch.json +10 -0
- package/packages/reploid/src/retrieval/page-text.js +182 -0
- package/packages/reploid/src/retrieval/passage.js +37 -0
- package/packages/reploid/src/retrieval/policy.json +14 -0
- package/packages/reploid/src/retrieval/retrieval.js +23 -0
- package/packages/reploid/src/retrieval/review-queue.js +76 -0
- package/packages/reploid/src/retrieval/sources.js +263 -0
- package/packages/reploid/src/retrieval/support-review.js +155 -0
- package/packages/reploid/src/retrieval/text.js +21 -0
- package/packages/reploid/src/rules/contribution.rules.json +8 -0
- package/packages/reploid/src/rules/routing.rules.json +24 -0
- package/packages/reploid/src/transport/assignment.js +571 -0
- package/packages/reploid/src/transport/bounded-channel-writer.js +46 -0
- package/packages/reploid/src/transport/index.js +11 -0
- package/packages/reploid/src/transport/introduction-admission.js +24 -0
- package/packages/reploid/src/transport/introduction-bootstrap.js +112 -0
- package/packages/reploid/src/transport/introduction-policy.json +12 -0
- package/packages/reploid/src/transport/introduction-records.js +90 -0
- package/packages/reploid/src/transport/introductions.js +209 -0
- package/packages/reploid/src/transport/partition-data-channel.js +421 -0
- package/packages/reploid/src/transport/partition-errors.json +16 -0
- package/packages/reploid/src/transport/retry-policy.js +36 -0
- package/packages/reploid/src/transport/room.js +502 -0
- package/packages/reploid/src/transport/sdp-fingerprint.js +5 -0
- package/packages/reploid/src/transport/signaling.js +571 -0
- package/packages/reploid/src/transport/swarm.js +1247 -0
- package/packages/reploid/src/transport/tool-offer-channel.js +137 -0
- package/server/browser-roots.js +42 -0
- package/server/browser-web-worker.js +94 -0
- package/server/chat-completions.js +45 -0
- package/server/fleet/browser-bridge.js +145 -0
- package/server/fleet/contract.js +42 -0
- package/server/fleet/credit-evidence.js +103 -0
- package/server/fleet/credit-recovery.js +175 -0
- package/server/fleet/credits.js +178 -0
- package/server/fleet/execution-admission.js +32 -0
- package/server/fleet/native-host.js +817 -0
- package/server/fleet/placement.js +132 -0
- package/server/fleet/requester.js +346 -0
- package/server/fleet/service.js +311 -0
- package/server/fleet/terminal-policy.js +83 -0
- package/server/fleet/text-api.js +94 -0
- package/server/hashing.js +35 -0
- package/server/http-request-owner.js +49 -0
- package/server/messages.js +57 -0
- package/server/native-canonical-epochs.js +90 -0
- package/server/native-change-log.js +40 -0
- package/server/native-earning.js +203 -0
- package/server/native-generation-journal.js +46 -0
- package/server/native-model-config.js +57 -0
- package/server/native-model-files.js +382 -0
- package/server/native-model-origin.js +54 -0
- package/server/native-model-origins.json +12 -0
- package/server/native-node.js +83 -0
- package/server/native-owner/controls.js +162 -0
- package/server/native-owner/monitor.js +251 -0
- package/server/native-owner/policy.js +273 -0
- package/server/native-owner/rate.js +92 -0
- package/server/native-participant.js +866 -0
- package/server/native-readiness-log.js +30 -0
- package/server/native-release-storage.js +64 -0
- package/server/native-shader-cache.js +369 -0
- package/server/native-supply-budget.js +66 -0
- package/server/native-whole-earning.js +67 -0
- package/server/native-whole-model-fill.js +182 -0
- package/server/native-whole-model.js +130 -0
- package/server/public-web-worker.js +66 -0
- package/server/responses.js +92 -0
- package/server/search/errors.js +47 -0
- package/server/search/page-fetch.js +185 -0
- package/server/text-api.js +83 -0
- package/server/text-recovery.js +45 -0
- package/server/text-request-options.js +23 -0
- package/server/text-requester.js +231 -0
- package/server/token-auth.js +9 -0
- package/server/whole-model-requester.js +99 -0
- package/shared/config/chat-models.json +4685 -0
- package/shared/config/doppler-execution-contracts.js +32 -0
- package/shared/config/doppler-execution-contracts.json +43 -0
- package/shared/config/doppler-generation-contract.js +223 -0
- package/shared/config/doppler-local-models.js +79 -0
- package/shared/config/doppler-package.json +7 -0
- package/shared/config/model-manifests/a0dc69e917133a82780823d17fc771c0f6b882d7c86c571deeaef45be2ff108b.json +6434 -0
- package/shared/config/model-manifests/e985e3cdad60d0cb57d84b436161e66ab5b3f6589a168de6f00b4610e5f1fb59.json +16534 -0
- package/shared/config/model-manifests/fa6eb7bbc3ba63571f8cede780b877d9272bde948697af93dd3d33837cb46137.json +7175 -0
- package/shared/config/model-pieces/qwen-0-8b-pieces.json +1506 -0
- package/shared/config/model-pieces/qwen-2b-pieces.json +4800 -0
- package/shared/config/model-pieces/qwen35b-q4_0-pieces.json +28880 -0
- package/shared/config/reploid-library.json +49 -0
- package/shared/config/swarm-bootstrap.json +21 -0
- package/shared/infrastructure/doppler-runtime-service.js +261 -0
- package/shared/pool/executable-pack.js +87 -0
- package/shared/pool/pack-operation-adapters.js +124 -0
- package/shared/pool/pack-operation-policy.js +75 -0
- package/shared/pool/pool-config.json +2280 -0
- package/shared/vendor/reploid/adapters/doppler-session.js +372 -0
- package/shared/vendor/reploid/artifacts/binary.js +25 -0
- package/shared/vendor/reploid/artifacts/canonical-json.js +23 -0
- package/shared/vendor/reploid/artifacts/delivery-attestation.js +64 -0
- package/shared/vendor/reploid/artifacts/identity.js +91 -0
- package/shared/vendor/reploid/artifacts/manifest-identity.js +17 -0
- package/shared/vendor/reploid/artifacts/participant-proofs.js +159 -0
- package/shared/vendor/reploid/artifacts/signatures.js +94 -0
- package/shared/vendor/reploid/config/defaults.json +110 -0
- package/shared/vendor/reploid/config/index.js +209 -0
- package/shared/vendor/reploid/config/request-overrides.json +9 -0
- package/shared/vendor/reploid/hashing.js +30 -0
- package/shared/vendor/reploid/mesh/generation-context-cache.js +97 -0
- package/shared/vendor/reploid/mesh/partitions/partition-attempt-evidence.js +282 -0
- package/shared/vendor/reploid/mesh/partitions/partition-contract.js +192 -0
- package/shared/vendor/reploid/mesh/partitions/partition-receiver-policy.json +7 -0
- package/shared/vendor/reploid/mesh/partitions/partition-route-ranking.js +268 -0
- package/shared/vendor/reploid/mesh/preparation-progress.js +46 -0
- package/shared/vendor/reploid/mesh/provider-hardware.js +11 -0
- package/shared/vendor/reploid/rules/routing.rules.json +24 -0
- package/shared/vendor/reploid/transport/partition-errors.json +16 -0
- package/README.md +0 -3
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/** Entailment review of mapped claims. A reviewer receives a blinded packet (question, answer, retained passages,
|
|
2
|
+
* claims and their cited spans; no generator, model, adapter, route or contributor identity) and returns judgments.
|
|
3
|
+
* The generating model can never certify its own claims: every judgment file is checked against the generator
|
|
4
|
+
* identity, which the caller keeps outside the packet. Deterministic validity (claim-support.js) is applied first;
|
|
5
|
+
* a reviewer can only decide claims that have at least one valid citation. */
|
|
6
|
+
import { SHA256, sha256Text } from './text.js';
|
|
7
|
+
import { validSpan } from './claim-support.js';
|
|
8
|
+
|
|
9
|
+
export const SUPPORT_REVIEW_PACKET_SCHEMA = 'reploid.claim-support-review-packet/v1';
|
|
10
|
+
export const SUPPORT_JUDGMENTS_SCHEMA = 'reploid.claim-support-judgments/v1';
|
|
11
|
+
export const SUPPORT_RESULT_SCHEMA = 'reploid.claim-support-result/v1';
|
|
12
|
+
export const REVIEW_VERDICTS = Object.freeze(['supported', 'unsupported', 'unverified']);
|
|
13
|
+
export const SUPPORT_REVIEW_INSTRUCTIONS = Object.freeze([
|
|
14
|
+
'Judge each claim only against the recorded passages of the sources it cites. Do not use other knowledge to support it.',
|
|
15
|
+
'supported: a cited passage states the claim or directly entails it. Name the span you relied on by source number and character offsets in that passage.',
|
|
16
|
+
'unsupported: no cited passage states or entails the claim, or a cited passage contradicts it. A passage on the same topic that does not state the claim does not support it.',
|
|
17
|
+
'unverified: you cannot decide from the recorded passages. Say what was missing.',
|
|
18
|
+
'The suggested span is a lexical pointer, not evidence of support; you may cite another span of the same cited passage.',
|
|
19
|
+
'Give a basis of one or two sentences for every judgment.'
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
const assert = (ok, message) => { if (!ok) throw new Error(message); };
|
|
23
|
+
const text = (value, max) => typeof value === 'string' && value.trim() && value.length <= max;
|
|
24
|
+
/** JSON with sorted keys, so a packet's hash does not depend on how it was serialized. */
|
|
25
|
+
export function canonicalJson(value) {
|
|
26
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(',')}]`;
|
|
27
|
+
if (value && typeof value === 'object') return `{${Object.keys(value).sort().filter(key => value[key] !== undefined)
|
|
28
|
+
.map(key => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(',')}}`;
|
|
29
|
+
return JSON.stringify(value);
|
|
30
|
+
}
|
|
31
|
+
export const supportPacketHash = packet => sha256Text(canonicalJson(packet));
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The blinded packet for the claims of one answer that have a valid citation. `claimSupport` comes from
|
|
35
|
+
* mapClaimSpans over the same answer and record. Only cited sources' passages are included.
|
|
36
|
+
*/
|
|
37
|
+
export function createSupportReviewPacket({ id, question, answer, record, claimSupport }) {
|
|
38
|
+
assert(text(id, 200) && /^[\x21-\x7e]+$/.test(id), 'Review packet id required');
|
|
39
|
+
assert(typeof question === 'string' && typeof answer === 'string', 'Review packet needs the question and the answer');
|
|
40
|
+
assert(claimSupport?.schema === 'reploid.claim-support/v1' && Array.isArray(record?.sources), 'Review packet needs the claim mapping and its record');
|
|
41
|
+
const claims = claimSupport.claims.filter(claim => claim.reviewable).map(claim => ({ id: claim.id, text: claim.text,
|
|
42
|
+
quote: { start: claim.start, end: claim.end }, citations: claim.citations.filter(citation => citation.valid)
|
|
43
|
+
.map(citation => ({ source: citation.marker, suggestedSpan: { start: citation.span.start, end: citation.span.end,
|
|
44
|
+
text: citation.span.text, sha256: citation.span.sha256 } })) }));
|
|
45
|
+
const cited = new Set(claims.flatMap(claim => claim.citations.map(citation => citation.source)));
|
|
46
|
+
return { schema: SUPPORT_REVIEW_PACKET_SCHEMA, id, instructions: [...SUPPORT_REVIEW_INSTRUCTIONS], question, answer,
|
|
47
|
+
sources: record.sources.filter(source => cited.has(source.number)).map(source => ({ number: source.number, title: source.title,
|
|
48
|
+
url: source.url, retrievedAt: source.retrievedAt, passage: source.passage, passageSha256: source.passageHash })),
|
|
49
|
+
claims };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const normalizedName = value => String(value ?? '').toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
53
|
+
/** The model that wrote the answer: its catalog id and content identity, from the attempt, never from the packet. */
|
|
54
|
+
export function validateGenerator(generator) {
|
|
55
|
+
assert(generator && text(generator.modelId, 256) && SHA256.test(generator.modelIdentity), 'The generating model identity is required');
|
|
56
|
+
return { modelId: generator.modelId, modelIdentity: generator.modelIdentity };
|
|
57
|
+
}
|
|
58
|
+
/** A reviewer may judge only when it is not the generating model, by name or content identity. */
|
|
59
|
+
export function assertIndependentReviewer(reviewer, generator) {
|
|
60
|
+
const made = validateGenerator(generator);
|
|
61
|
+
assert(reviewer && ['human', 'model'].includes(reviewer.kind) && text(reviewer.id, 256), 'Reviewer identity is required');
|
|
62
|
+
const names = [reviewer.id, reviewer.model?.name].filter(Boolean).map(normalizedName);
|
|
63
|
+
assert(!names.includes(normalizedName(made.modelId)) && reviewer.model?.identity !== made.modelIdentity && reviewer.id !== made.modelIdentity,
|
|
64
|
+
'The generating model cannot certify its own claims');
|
|
65
|
+
if (reviewer.kind === 'model') assert(text(reviewer.model?.name, 256) && text(reviewer.model?.provider, 256), 'A model reviewer names its model and provider');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Validates a judgment file against its packet and the generator; returns the per-claim judgments it makes. */
|
|
69
|
+
export async function validateSupportJudgments({ packet, judgments, generator }) {
|
|
70
|
+
assert(judgments?.schema === SUPPORT_JUDGMENTS_SCHEMA, 'Invalid support judgments');
|
|
71
|
+
assert(judgments.packet?.id === packet.id && judgments.packet?.sha256 === await supportPacketHash(packet),
|
|
72
|
+
'Judgments do not belong to this review packet');
|
|
73
|
+
assertIndependentReviewer(judgments.reviewer, generator);
|
|
74
|
+
assert(Array.isArray(judgments.judgments), 'Invalid support judgments');
|
|
75
|
+
const claims = new Map(packet.claims.map(claim => [claim.id, claim])), passages = new Map(packet.sources.map(source => [source.number, source.passage]));
|
|
76
|
+
const seen = new Set(), decided = new Map();
|
|
77
|
+
for (const item of judgments.judgments) {
|
|
78
|
+
assert(item && claims.has(item.claim) && !seen.has(item.claim) && REVIEW_VERDICTS.includes(item.verdict) && text(item.basis, 2000),
|
|
79
|
+
'Each judgment names one packet claim once, a verdict and a basis');
|
|
80
|
+
seen.add(item.claim);
|
|
81
|
+
const claim = claims.get(item.claim), cited = new Set(claim.citations.map(citation => citation.source));
|
|
82
|
+
const spans = [];
|
|
83
|
+
for (const span of Array.isArray(item.spans) ? item.spans : []) {
|
|
84
|
+
const passage = passages.get(span?.source);
|
|
85
|
+
if (!cited.has(span?.source) || passage === undefined) continue;
|
|
86
|
+
// A span is given by offsets, or by an exact quote located at its first occurrence in the passage.
|
|
87
|
+
const start = typeof span.quote === 'string' && span.quote ? passage.indexOf(span.quote) : span.start;
|
|
88
|
+
const end = typeof span.quote === 'string' && span.quote ? start + span.quote.length : span.end;
|
|
89
|
+
if (!(Number.isSafeInteger(start) && start >= 0 && Number.isSafeInteger(end))) continue;
|
|
90
|
+
const slice = { start, end, text: passage.slice(start, end) };
|
|
91
|
+
slice.sha256 = await sha256Text(slice.text);
|
|
92
|
+
if (await validSpan(passage, slice)) spans.push({ source: span.source, ...slice });
|
|
93
|
+
}
|
|
94
|
+
// Support must rest on an exact span of a cited, recorded passage; otherwise it is not established.
|
|
95
|
+
const judged = item.verdict === 'supported' && !spans.length
|
|
96
|
+
? { verdict: 'unverified', basis: `Marked supported without a valid span of a cited passage. Reviewer basis: ${item.basis.trim()}` }
|
|
97
|
+
: { verdict: item.verdict, basis: item.basis.trim() };
|
|
98
|
+
decided.set(item.claim, { ...judged, spans });
|
|
99
|
+
}
|
|
100
|
+
return decided;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Per-claim outcome for one answer: deterministic results for claims no reviewer can decide, and for reviewable
|
|
105
|
+
* claims the reviewers' verdicts. When reviewers disagree, a third review decides: a verdict held by a strict majority
|
|
106
|
+
* of at least three reviews settles the claim, and every review stays in the result. Without such a majority the claim
|
|
107
|
+
* stays disputed and unverified. A claim no reviewer judged stays unverified.
|
|
108
|
+
*/
|
|
109
|
+
export async function applySupportJudgments({ packet, claimSupport, judgments = [], generator }) {
|
|
110
|
+
assert(packet?.schema === SUPPORT_REVIEW_PACKET_SCHEMA && claimSupport?.schema === 'reploid.claim-support/v1', 'Invalid review inputs');
|
|
111
|
+
validateGenerator(generator);
|
|
112
|
+
const files = [];
|
|
113
|
+
for (const file of judgments) files.push({ reviewer: file.reviewer, decided: await validateSupportJudgments({ packet, judgments: file, generator }) });
|
|
114
|
+
const ids = files.map(file => `${file.reviewer.kind}:${file.reviewer.id}`);
|
|
115
|
+
assert(new Set(ids).size === ids.length, 'Each reviewer submits one judgment file per packet');
|
|
116
|
+
const claims = claimSupport.claims.map(claim => {
|
|
117
|
+
const evidence = claim.citations.filter(citation => citation.valid).map(citation => ({ source: citation.marker, url: citation.url,
|
|
118
|
+
passageHash: citation.passageHash, span: citation.span, ...(citation.document ? { document: citation.document } : {}) }));
|
|
119
|
+
const base = { id: claim.id, text: claim.text, start: claim.start, end: claim.end, citations: claim.citations, evidence };
|
|
120
|
+
if (!claim.reviewable) return { ...base, verdict: claim.verdict, reason: claim.reason, reviews: [], disputed: false };
|
|
121
|
+
const reviews = files.flatMap(file => file.decided.has(claim.id)
|
|
122
|
+
? [{ reviewer: { kind: file.reviewer.kind, id: file.reviewer.id }, ...file.decided.get(claim.id) }] : []);
|
|
123
|
+
const verdicts = new Set(reviews.map(review => review.verdict));
|
|
124
|
+
if (!reviews.length) return { ...base, verdict: 'unverified', reason: 'awaiting-review', reviews, disputed: false };
|
|
125
|
+
if (verdicts.size > 1) {
|
|
126
|
+
const majority = [...verdicts].find(verdict => reviews.filter(review => review.verdict === verdict).length * 2 > reviews.length);
|
|
127
|
+
return reviews.length >= 3 && majority
|
|
128
|
+
? { ...base, verdict: majority, reason: 'third-review', reviews, disputed: false }
|
|
129
|
+
: { ...base, verdict: 'unverified', reason: 'disputed', reviews, disputed: true };
|
|
130
|
+
}
|
|
131
|
+
return { ...base, verdict: reviews[0].verdict, reason: 'reviewed', reviews, disputed: false };
|
|
132
|
+
});
|
|
133
|
+
const tally = name => claims.filter(claim => claim.verdict === name).length;
|
|
134
|
+
return { schema: SUPPORT_RESULT_SCHEMA, packet: { id: packet.id, sha256: await supportPacketHash(packet) },
|
|
135
|
+
reviewers: files.map(file => structuredClone(file.reviewer)), claims,
|
|
136
|
+
summary: { claims: claims.length, supported: tally('supported'), unsupported: tally('unsupported'), unverified: tally('unverified'),
|
|
137
|
+
disputed: claims.filter(claim => claim.disputed).length,
|
|
138
|
+
resolvedByThirdReview: claims.filter(claim => claim.reason === 'third-review').length, awaitingReview: claims.filter(claim => claim.reason === 'awaiting-review').length,
|
|
139
|
+
// Supported share of all material claims; unverified and disputed claims count against it.
|
|
140
|
+
supportRate: claims.length ? tally('supported') / claims.length : null } };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** The packet for human reading, in the style of the blinded answer-review packet. packet.json stays authoritative. */
|
|
144
|
+
export function renderSupportReviewPacketMarkdown(packet) {
|
|
145
|
+
const fence = value => '```text\n' + String(value).replace(/```/g, '```') + '\n```';
|
|
146
|
+
return [`# Citation support review packet ${packet.id}`, '',
|
|
147
|
+
'Blinded: the packet names no model, adapter, execution route or contributor. Judge each claim against the cited passages only.', '',
|
|
148
|
+
...packet.instructions.map(line => `- ${line}`), '', '## Question', '', fence(packet.question), '', '## Answer', '', fence(packet.answer), '',
|
|
149
|
+
'## Sources', '', ...packet.sources.flatMap(source => [`### [${source.number}] ${source.title}`, '',
|
|
150
|
+
`- URL: ${source.url}`, `- Retrieved: ${new Date(source.retrievedAt).toISOString()}`, `- Passage sha256: \`${source.passageSha256}\``, '',
|
|
151
|
+
fence(source.passage), '']),
|
|
152
|
+
'## Claims', '', ...packet.claims.flatMap(claim => [`### ${claim.id}`, '', fence(claim.text), '',
|
|
153
|
+
...claim.citations.map(citation => `- Cites [${citation.source}]; suggested span ${citation.suggestedSpan.start}-${citation.suggestedSpan.end}: "${citation.suggestedSpan.text}"`),
|
|
154
|
+
'', '| Verdict | Source | Span start | Span end | Basis |', '|---|---|---|---|---|', '| | | | | |', ''])].join('\n');
|
|
155
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Text identity and word tokens shared by retrieval, citation checks and the fixed test provider. */
|
|
2
|
+
import { sha256Hex } from '../artifacts/signatures.js';
|
|
3
|
+
|
|
4
|
+
export const SHA256 = /^sha256:[a-f0-9]{64}$/;
|
|
5
|
+
|
|
6
|
+
export const sha256Text = text => sha256Hex(String(text));
|
|
7
|
+
|
|
8
|
+
// Function words carry no checkable content. Negations are deliberately absent.
|
|
9
|
+
export const STOPWORDS = new Set(('a an and are as at be been being but by can could did do does for from had has have he her his '
|
|
10
|
+
+ 'i if in into is it its may me might my of on or our she should so than that the their them then there these they this '
|
|
11
|
+
+ 'those to was we were what when where which who whom why will with would you your also about after before over under '
|
|
12
|
+
+ 'such per via').split(' '));
|
|
13
|
+
|
|
14
|
+
/** Lowercase words and numbers; thousands separators are removed so 1,200 and 1200 compare equal. */
|
|
15
|
+
export function wordTokens(text) {
|
|
16
|
+
return (String(text).normalize('NFKC').toLowerCase().match(/[\p{L}\p{N}]+(?:[.,'’][\p{L}\p{N}]+)*/gu) || [])
|
|
17
|
+
.map(token => /^\d{1,3}(?:,\d{3})+(?:\.\d+)?$/.test(token) ? token.replace(/,/g, '') : token);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const contentWords = text => [...new Set(wordTokens(text))].filter(token => !STOPWORDS.has(token)
|
|
21
|
+
&& (token.length > 1 || /\p{N}/u.test(token)));
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "reploid.rules/v1",
|
|
3
|
+
"rules": [
|
|
4
|
+
{
|
|
5
|
+
"id": "local-only",
|
|
6
|
+
"order": [
|
|
7
|
+
"local"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "local-first",
|
|
12
|
+
"order": [
|
|
13
|
+
"local",
|
|
14
|
+
"remote"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": "remote-only",
|
|
19
|
+
"order": [
|
|
20
|
+
"remote"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|