@opacedev/astro-ai-content-checker 0.3.1
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/CHANGELOG.md +138 -0
- package/LICENSE +9 -0
- package/README.md +236 -0
- package/SBOM.cdx.json +172 -0
- package/SECURITY.md +9 -0
- package/THIRD_PARTY_NOTICES.md +36 -0
- package/dist/build-report-html.d.ts +3 -0
- package/dist/highlight.js +155 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +43 -0
- package/dist/options.d.ts +21 -0
- package/dist/options.js +6 -0
- package/dist/receipt.d.ts +15 -0
- package/dist/receipt.js +100 -0
- package/dist/report.d.ts +55 -0
- package/dist/report.js +12 -0
- package/dist/sections.js +181 -0
- package/dist/share.d.ts +47 -0
- package/dist/share.js +72 -0
- package/dist/shared-EX54KI6H.js +1503 -0
- package/dist/shared-MMXWTX2U.js +43 -0
- package/dist/toolbar.js +13478 -0
- package/node_modules/@opacedev/ai-content-checker-browser/LICENSE +21 -0
- package/node_modules/@opacedev/ai-content-checker-browser/README.md +145 -0
- package/node_modules/@opacedev/ai-content-checker-browser/dist/dom/visible-text.d.ts +14 -0
- package/node_modules/@opacedev/ai-content-checker-browser/dist/dom/visible-text.js +47 -0
- package/node_modules/@opacedev/ai-content-checker-browser/dist/index.d.ts +3 -0
- package/node_modules/@opacedev/ai-content-checker-browser/dist/index.js +99 -0
- package/node_modules/@opacedev/ai-content-checker-browser/dist/worker/client.d.ts +12 -0
- package/node_modules/@opacedev/ai-content-checker-browser/dist/worker/client.js +17 -0
- package/node_modules/@opacedev/ai-content-checker-browser/dist/worker/entry.d.ts +1 -0
- package/node_modules/@opacedev/ai-content-checker-browser/dist/worker/entry.js +3984 -0
- package/node_modules/@opacedev/ai-content-checker-browser/dist/worker/protocol.d.ts +30 -0
- package/node_modules/@opacedev/ai-content-checker-browser/dist/worker/protocol.js +1 -0
- package/node_modules/@opacedev/ai-content-checker-browser/package.json +60 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/LICENSE +21 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/README.md +93 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/dist/index.d.ts +58 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/dist/index.js +17 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/package.json +57 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/analysis-request.schema.d.ts +44 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/analysis-result.schema.d.ts +122 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/candidate.schema.d.ts +81 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/capabilities.schema.d.ts +24 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/checker-result.schema.d.ts +342 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/common.schema.d.ts +10 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/envelope.schema.d.ts +14 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/gate-result.schema.d.ts +19 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/integrity-receipt.schema.d.ts +122 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/job.schema.d.ts +188 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/method-result.schema.d.ts +39 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/pattern-finding.schema.d.ts +26 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/protected-span.schema.d.ts +35 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/rewrite-request.schema.d.ts +65 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/index.ts +63 -0
- package/node_modules/@opacedev/ai-content-checker-contracts/src/semantic-validation.mjs +32 -0
- package/node_modules/@opacedev/ai-content-checker-core/LICENSE +21 -0
- package/node_modules/@opacedev/ai-content-checker-core/README.md +186 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/bundle.js +4744 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/capabilities.d.ts +16 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/capabilities.js +7 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/diff/diff.d.ts +17 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/diff/diff.js +76 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/fixes/preview.d.ts +27 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/fixes/preview.js +47 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/gates/policy.d.ts +14 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/gates/policy.js +16 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/index.d.ts +15 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/index.js +15 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/inspect.d.ts +8 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/inspect.js +84 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-gb-v1.d.ts +12 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-gb-v1.js +68 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v2-data.d.ts +73 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v2-data.js +499 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v2.d.ts +76 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v2.js +1067 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v3-data.d.ts +165 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v3-data.js +614 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v3.d.ts +19 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v3.js +542 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v4-corpus.d.ts +40 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v4-corpus.js +40 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v4-data.d.ts +138 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v4-data.js +200 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v4.d.ts +71 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/patterns/en-signals-v4.js +388 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/protected/extract.d.ts +17 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/protected/extract.js +75 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/protected/validate.d.ts +3 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/protected/validate.js +17 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/provenance/c2pa-text.d.ts +55 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/provenance/c2pa-text.js +86 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/receipts/build.d.ts +48 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/receipts/build.js +61 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/report/checker-result.d.ts +241 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/report/checker-result.js +419 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/source/offsets.d.ts +34 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/source/offsets.js +51 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/source/utf8.d.ts +3 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/source/utf8.js +58 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/source/visible-text.d.ts +12 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/source/visible-text.js +30 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/unicode/data.d.ts +22 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/unicode/data.js +137 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/unicode/inspect.d.ts +16 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/unicode/inspect.js +84 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/verdict/combine.d.ts +162 -0
- package/node_modules/@opacedev/ai-content-checker-core/dist/verdict/combine.js +501 -0
- package/node_modules/@opacedev/ai-content-checker-core/package.json +62 -0
- package/node_modules/canonicalize/LICENSE +201 -0
- package/node_modules/canonicalize/README.md +65 -0
- package/node_modules/canonicalize/bin/canonicalize.js +17 -0
- package/node_modules/canonicalize/lib/canonicalize.d.ts +2 -0
- package/node_modules/canonicalize/lib/canonicalize.js +74 -0
- package/node_modules/canonicalize/package.json +64 -0
- package/node_modules/entities/LICENSE +11 -0
- package/node_modules/entities/lib/decode.d.ts +211 -0
- package/node_modules/entities/lib/decode.d.ts.map +1 -0
- package/node_modules/entities/lib/decode.js +536 -0
- package/node_modules/entities/lib/decode.js.map +1 -0
- package/node_modules/entities/lib/decode_codepoint.d.ts +19 -0
- package/node_modules/entities/lib/decode_codepoint.d.ts.map +1 -0
- package/node_modules/entities/lib/decode_codepoint.js +76 -0
- package/node_modules/entities/lib/decode_codepoint.js.map +1 -0
- package/node_modules/entities/lib/encode.d.ts +22 -0
- package/node_modules/entities/lib/encode.d.ts.map +1 -0
- package/node_modules/entities/lib/encode.js +77 -0
- package/node_modules/entities/lib/encode.js.map +1 -0
- package/node_modules/entities/lib/escape.d.ts +43 -0
- package/node_modules/entities/lib/escape.d.ts.map +1 -0
- package/node_modules/entities/lib/escape.js +122 -0
- package/node_modules/entities/lib/escape.js.map +1 -0
- package/node_modules/entities/lib/esm/decode.d.ts +211 -0
- package/node_modules/entities/lib/esm/decode.d.ts.map +1 -0
- package/node_modules/entities/lib/esm/decode.js +496 -0
- package/node_modules/entities/lib/esm/decode.js.map +1 -0
- package/node_modules/entities/lib/esm/decode_codepoint.d.ts +19 -0
- package/node_modules/entities/lib/esm/decode_codepoint.d.ts.map +1 -0
- package/node_modules/entities/lib/esm/decode_codepoint.js +71 -0
- package/node_modules/entities/lib/esm/decode_codepoint.js.map +1 -0
- package/node_modules/entities/lib/esm/encode.d.ts +22 -0
- package/node_modules/entities/lib/esm/encode.d.ts.map +1 -0
- package/node_modules/entities/lib/esm/encode.js +69 -0
- package/node_modules/entities/lib/esm/encode.js.map +1 -0
- package/node_modules/entities/lib/esm/escape.d.ts +43 -0
- package/node_modules/entities/lib/esm/escape.d.ts.map +1 -0
- package/node_modules/entities/lib/esm/escape.js +116 -0
- package/node_modules/entities/lib/esm/escape.js.map +1 -0
- package/node_modules/entities/lib/esm/generated/decode-data-html.d.ts +3 -0
- package/node_modules/entities/lib/esm/generated/decode-data-html.d.ts.map +1 -0
- package/node_modules/entities/lib/esm/generated/decode-data-html.js +7 -0
- package/node_modules/entities/lib/esm/generated/decode-data-html.js.map +1 -0
- package/node_modules/entities/lib/esm/generated/decode-data-xml.d.ts +3 -0
- package/node_modules/entities/lib/esm/generated/decode-data-xml.d.ts.map +1 -0
- package/node_modules/entities/lib/esm/generated/decode-data-xml.js +7 -0
- package/node_modules/entities/lib/esm/generated/decode-data-xml.js.map +1 -0
- package/node_modules/entities/lib/esm/generated/encode-html.d.ts +8 -0
- package/node_modules/entities/lib/esm/generated/encode-html.d.ts.map +1 -0
- package/node_modules/entities/lib/esm/generated/encode-html.js +10 -0
- package/node_modules/entities/lib/esm/generated/encode-html.js.map +1 -0
- package/node_modules/entities/lib/esm/index.d.ts +96 -0
- package/node_modules/entities/lib/esm/index.d.ts.map +1 -0
- package/node_modules/entities/lib/esm/index.js +99 -0
- package/node_modules/entities/lib/esm/index.js.map +1 -0
- package/node_modules/entities/lib/esm/package.json +1 -0
- package/node_modules/entities/lib/generated/decode-data-html.d.ts +3 -0
- package/node_modules/entities/lib/generated/decode-data-html.d.ts.map +1 -0
- package/node_modules/entities/lib/generated/decode-data-html.js +9 -0
- package/node_modules/entities/lib/generated/decode-data-html.js.map +1 -0
- package/node_modules/entities/lib/generated/decode-data-xml.d.ts +3 -0
- package/node_modules/entities/lib/generated/decode-data-xml.d.ts.map +1 -0
- package/node_modules/entities/lib/generated/decode-data-xml.js +9 -0
- package/node_modules/entities/lib/generated/decode-data-xml.js.map +1 -0
- package/node_modules/entities/lib/generated/encode-html.d.ts +8 -0
- package/node_modules/entities/lib/generated/encode-html.d.ts.map +1 -0
- package/node_modules/entities/lib/generated/encode-html.js +12 -0
- package/node_modules/entities/lib/generated/encode-html.js.map +1 -0
- package/node_modules/entities/lib/index.d.ts +96 -0
- package/node_modules/entities/lib/index.d.ts.map +1 -0
- package/node_modules/entities/lib/index.js +126 -0
- package/node_modules/entities/lib/index.js.map +1 -0
- package/node_modules/entities/package.json +90 -0
- package/node_modules/entities/readme.md +122 -0
- package/package.json +91 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { IntegrityReceipt, MethodResult, GateResult } from "@opacedev/ai-content-checker-contracts";
|
|
2
|
+
export interface ReceiptInput {
|
|
3
|
+
receipt_id: string;
|
|
4
|
+
product_version: string;
|
|
5
|
+
created_at: string;
|
|
6
|
+
source: {
|
|
7
|
+
content: string;
|
|
8
|
+
content_type: "plain_text" | "html" | "markdown";
|
|
9
|
+
language: string;
|
|
10
|
+
normalised_text?: string;
|
|
11
|
+
};
|
|
12
|
+
policy: {
|
|
13
|
+
id: string;
|
|
14
|
+
version: string;
|
|
15
|
+
requested_checks: string[];
|
|
16
|
+
allowed_routes: Array<"browser" | "wordpress_local" | "local_service" | "hub_provider" | "commercial_byok">;
|
|
17
|
+
retain_content: boolean;
|
|
18
|
+
};
|
|
19
|
+
methods: MethodResult[];
|
|
20
|
+
rewrite?: {
|
|
21
|
+
source_hash: string;
|
|
22
|
+
candidate_hash: string;
|
|
23
|
+
generator: {
|
|
24
|
+
route: "browser" | "wordpress_local" | "local_service" | "hub_provider" | "commercial_byok";
|
|
25
|
+
provider: string;
|
|
26
|
+
model: string;
|
|
27
|
+
prompt_template: string;
|
|
28
|
+
parameters?: Record<string, unknown>;
|
|
29
|
+
};
|
|
30
|
+
gates: GateResult[];
|
|
31
|
+
selected_candidate: string | null;
|
|
32
|
+
candidate_content?: string;
|
|
33
|
+
} | null;
|
|
34
|
+
approval: {
|
|
35
|
+
actor_id?: string;
|
|
36
|
+
at?: string;
|
|
37
|
+
scope: "whole" | "sentences" | "none";
|
|
38
|
+
sentence_ids?: string[];
|
|
39
|
+
};
|
|
40
|
+
limitations: string[];
|
|
41
|
+
contains_content: boolean;
|
|
42
|
+
}
|
|
43
|
+
export declare function buildReceipt(input: ReceiptInput): Promise<IntegrityReceipt>;
|
|
44
|
+
export declare function verifyReceipt(receipt: IntegrityReceipt): {
|
|
45
|
+
valid: boolean;
|
|
46
|
+
errors: string[];
|
|
47
|
+
payload_hash: string;
|
|
48
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import canonicalize from "canonicalize";
|
|
2
|
+
import { prefixedSha256 } from "../source/utf8.js";
|
|
3
|
+
const payloadForHash = (receipt) => { const clone = structuredClone(receipt); delete clone.integrity?.payload_hash; delete clone.integrity?.signature; return clone; };
|
|
4
|
+
const canonical = (value) => { const output = canonicalize(value); if (output === undefined)
|
|
5
|
+
throw new Error("receipt_canonicalisation_failed"); return output; };
|
|
6
|
+
export async function buildReceipt(input) {
|
|
7
|
+
if (input.contains_content !== input.policy.retain_content)
|
|
8
|
+
throw new Error("receipt_content_consent_mismatch");
|
|
9
|
+
if (input.contains_content && input.rewrite && !input.rewrite.candidate_content)
|
|
10
|
+
throw new Error("receipt_candidate_content_required");
|
|
11
|
+
const sourceHash = prefixedSha256(input.source.content), normalisedHash = prefixedSha256(input.source.normalised_text ?? input.source.content);
|
|
12
|
+
const source = { content_hash: sourceHash, normalised_hash: normalisedHash, content_type: input.source.content_type, language: input.source.language, word_count: (input.source.content.trim().match(/\S+/g) ?? []).length };
|
|
13
|
+
if (input.contains_content)
|
|
14
|
+
source.content = input.source.content;
|
|
15
|
+
const rewrite = input.rewrite ? (() => { const { candidate_content, source_content: _callerSourceContent, ...metadata } = input.rewrite; return { ...metadata, ...(input.contains_content ? { source_content: input.source.content, candidate_content } : {}) }; })() : null;
|
|
16
|
+
const receipt = { schema_version: "1.0", contract_version: "1.0.0", product_version: input.product_version, receipt_id: input.receipt_id, created_at: input.created_at, source, policy: input.policy, methods: input.methods, rewrite, approval: input.approval, limitations: input.limitations, contains_content: input.contains_content, integrity: { canonicalisation: "RFC8785", payload_hash: "sha256:" + "0".repeat(64) } };
|
|
17
|
+
receipt.integrity.payload_hash = prefixedSha256(canonical(payloadForHash(receipt)));
|
|
18
|
+
return deepFreeze(receipt);
|
|
19
|
+
}
|
|
20
|
+
export function verifyReceipt(receipt) { const errors = validateReceiptShape(receipt); let expected = ""; try {
|
|
21
|
+
expected = prefixedSha256(canonical(payloadForHash(receipt)));
|
|
22
|
+
if (expected !== receipt?.integrity?.payload_hash)
|
|
23
|
+
errors.push("payload_hash_mismatch");
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
errors.push("receipt_canonicalisation_failed");
|
|
27
|
+
} return { valid: errors.length === 0, errors: [...new Set(errors)], payload_hash: expected }; }
|
|
28
|
+
const isHash = (value) => typeof value === "string" && /^sha256:[a-f0-9]{64}$/.test(value);
|
|
29
|
+
const isTime = (value) => typeof value === "string" && !Number.isNaN(Date.parse(value));
|
|
30
|
+
function validateReceiptShape(receipt) { const e = []; if (!receipt || typeof receipt !== "object")
|
|
31
|
+
return ["invalid_receipt"]; if (receipt.schema_version !== "1.0")
|
|
32
|
+
e.push("unsupported_schema"); if (typeof receipt.contract_version !== "string" || !receipt.contract_version.startsWith("1."))
|
|
33
|
+
e.push("contract_incompatible"); for (const key of ["product_version", "receipt_id"])
|
|
34
|
+
if (typeof receipt[key] !== "string" || !receipt[key])
|
|
35
|
+
e.push(`missing_${key}`); if (!isTime(receipt.created_at))
|
|
36
|
+
e.push("invalid_created_at"); if (!receipt.source || !isHash(receipt.source.content_hash) || !isHash(receipt.source.normalised_hash) || !Number.isInteger(receipt.source.word_count) || receipt.source.word_count < 0 || !["plain_text", "html", "markdown"].includes(receipt.source.content_type) || typeof receipt.source.language !== "string")
|
|
37
|
+
e.push("invalid_source"); if (!receipt.policy || typeof receipt.policy.retain_content !== "boolean" || !Array.isArray(receipt.policy.requested_checks) || !Array.isArray(receipt.policy.allowed_routes))
|
|
38
|
+
e.push("invalid_policy"); if (typeof receipt.contains_content !== "boolean")
|
|
39
|
+
e.push("invalid_contains_content"); if (receipt.policy && receipt.contains_content !== receipt.policy.retain_content)
|
|
40
|
+
e.push("receipt_content_consent_mismatch"); if (receipt.source && receipt.contains_content !== Object.hasOwn(receipt.source, "content"))
|
|
41
|
+
e.push("receipt_content_flag_mismatch"); if (receipt.rewrite) {
|
|
42
|
+
if (!isHash(receipt.rewrite.source_hash) || !isHash(receipt.rewrite.candidate_hash) || !receipt.rewrite.generator || !Array.isArray(receipt.rewrite.gates) || !(typeof receipt.rewrite.selected_candidate === "string" || receipt.rewrite.selected_candidate === null))
|
|
43
|
+
e.push("invalid_rewrite");
|
|
44
|
+
const hasSource = Object.hasOwn(receipt.rewrite, "source_content"), hasCandidate = Object.hasOwn(receipt.rewrite, "candidate_content");
|
|
45
|
+
if (receipt.contains_content ? (!hasSource || !hasCandidate) : (hasSource || hasCandidate))
|
|
46
|
+
e.push("rewrite_content_flag_mismatch");
|
|
47
|
+
} if (!Array.isArray(receipt.methods))
|
|
48
|
+
e.push("invalid_methods");
|
|
49
|
+
else
|
|
50
|
+
for (const method of receipt.methods) {
|
|
51
|
+
if (!method || typeof method.id !== "string" || typeof method.version !== "string" || !["pass", "attention", "fail", "inconclusive", "unsupported", "not_configured", "not_run", "error"].includes(method.status) || !isTime(method.started_at) || !isTime(method.completed_at) || !Array.isArray(method.limitations) || !method.limitations.length)
|
|
52
|
+
e.push("invalid_method");
|
|
53
|
+
} if (!receipt.approval || !["whole", "sentences", "none"].includes(receipt.approval.scope))
|
|
54
|
+
e.push("invalid_approval"); if (!Array.isArray(receipt.limitations) || !receipt.limitations.length)
|
|
55
|
+
e.push("invalid_limitations"); if (receipt.integrity?.canonicalisation !== "RFC8785" || !isHash(receipt.integrity?.payload_hash))
|
|
56
|
+
e.push("invalid_integrity"); return e; }
|
|
57
|
+
function deepFreeze(value) { if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
58
|
+
Object.freeze(value);
|
|
59
|
+
for (const child of Object.values(value))
|
|
60
|
+
deepFreeze(child);
|
|
61
|
+
} return value; }
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import type { CheckerResult } from "@opacedev/ai-content-checker-contracts";
|
|
2
|
+
import type { CombinedVerdictResult } from "../verdict/combine.js";
|
|
3
|
+
/** Portable result/presentation semantics shared by every checker surface. */
|
|
4
|
+
export declare const CHECKER_RESULT_RUNTIME_VERSION: "checker-result:2026.09.1";
|
|
5
|
+
export declare const CYCLE5_MODEL_IDENTITY: {
|
|
6
|
+
readonly identity: "tier3-cycle5-v1";
|
|
7
|
+
readonly serverRegistryIdentity: "tier3-cycle5-full";
|
|
8
|
+
readonly segmentationContract: "segments-v3";
|
|
9
|
+
readonly inputContract: "raw-v1";
|
|
10
|
+
readonly featuresContract: "features-v1";
|
|
11
|
+
readonly scoringContract: "margin-v1";
|
|
12
|
+
readonly flagRule: {
|
|
13
|
+
readonly expression: "max(m1, m2 + 0.34) >= 3.570935";
|
|
14
|
+
readonly primaryMargin: 3.570935;
|
|
15
|
+
readonly secondaryGap: 0.34;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export declare const CHECKER_SCORE_SCALE: "zero_to_one_pattern_similarity";
|
|
19
|
+
export declare const CHECKER_HONESTY_LINE: "No AI checker can prove who wrote a text \u2014 this is a pattern reading.";
|
|
20
|
+
export declare const CHECKER_LEVELS: {
|
|
21
|
+
readonly "signal-strongly-ai": {
|
|
22
|
+
readonly name: "Strongly AI";
|
|
23
|
+
readonly support: "This draft very strongly matches AI writing — the kind of match we rarely see in human work.";
|
|
24
|
+
};
|
|
25
|
+
readonly "signal-likely-ai": {
|
|
26
|
+
readonly name: "Likely AI";
|
|
27
|
+
readonly support: "Much of this draft reads like AI writing.";
|
|
28
|
+
};
|
|
29
|
+
readonly "signal-potentially-ai": {
|
|
30
|
+
readonly name: "Potentially AI";
|
|
31
|
+
readonly support: "Parts of this draft resemble AI writing, but the match is not strong enough to be sure.";
|
|
32
|
+
};
|
|
33
|
+
readonly "signal-unclear": {
|
|
34
|
+
readonly name: "Unclear";
|
|
35
|
+
readonly support: "We can't call this one either way. Some passages read slightly machine-like, but people write that way too.";
|
|
36
|
+
};
|
|
37
|
+
readonly "signal-likely-human": {
|
|
38
|
+
readonly name: "Likely human";
|
|
39
|
+
readonly support: "This reads like human writing. Nothing here matches the AI patterns we test for — though a heavily disguised AI draft can slip past any checker, ours included.";
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export type CheckerLevelId = keyof typeof CHECKER_LEVELS;
|
|
43
|
+
export type Cycle5BandId = "very_likely_ai" | "uncertain" | "likely_human" | "very_likely_human";
|
|
44
|
+
/**
|
|
45
|
+
* Map the model's measured band to the five product bands. The secondary
|
|
46
|
+
* threshold only refines the model's uncertain band; it never decides the
|
|
47
|
+
* underlying model flag, which remains the margin-v1 rule.
|
|
48
|
+
*/
|
|
49
|
+
export declare function levelForCycle5Score(rawScore: number, bandId: Cycle5BandId, secondaryThreshold?: number): CheckerLevelId;
|
|
50
|
+
/**
|
|
51
|
+
* Format every score in one run together. Precision rises only for values
|
|
52
|
+
* which would otherwise print the same number beside different level names.
|
|
53
|
+
*/
|
|
54
|
+
export declare function formatCheckerScoreTexts(entries: readonly {
|
|
55
|
+
rawScore: number;
|
|
56
|
+
level: CheckerLevelId;
|
|
57
|
+
}[], startDecimals?: number, maxDecimals?: number): string[];
|
|
58
|
+
export interface CheckerEvidenceInput {
|
|
59
|
+
id: string;
|
|
60
|
+
kind: "trained_model" | "measured_pattern" | "editorial_rule" | "character" | "provenance" | "watermark" | "limitation";
|
|
61
|
+
summary: string;
|
|
62
|
+
detail?: string;
|
|
63
|
+
basis?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface Cycle5SectionInput {
|
|
66
|
+
index: number;
|
|
67
|
+
startUtf16: number;
|
|
68
|
+
endUtf16: number;
|
|
69
|
+
wordCount: number;
|
|
70
|
+
rawScore: number;
|
|
71
|
+
rawMargin: number;
|
|
72
|
+
bandId: Cycle5BandId;
|
|
73
|
+
passage?: string;
|
|
74
|
+
locator?: {
|
|
75
|
+
content_hash: string;
|
|
76
|
+
start_utf16: number;
|
|
77
|
+
end_utf16: number;
|
|
78
|
+
};
|
|
79
|
+
evidence: readonly CheckerEvidenceInput[];
|
|
80
|
+
}
|
|
81
|
+
export interface Cycle5PresentationInput {
|
|
82
|
+
source: string;
|
|
83
|
+
rawScore: number;
|
|
84
|
+
rawMargin: number;
|
|
85
|
+
bandId: Cycle5BandId;
|
|
86
|
+
/** Probability-space display equivalent of the primary margin boundary. It never decides the flag. */
|
|
87
|
+
primaryDisplayThreshold: number;
|
|
88
|
+
/** Probability-space display equivalent of m2 + gap. It refines the visible band but never decides the flag. */
|
|
89
|
+
secondaryDisplayThreshold: number;
|
|
90
|
+
flagged: boolean;
|
|
91
|
+
flagReason: "primary" | "secondary" | null;
|
|
92
|
+
sections: readonly Cycle5SectionInput[];
|
|
93
|
+
reason?: string;
|
|
94
|
+
limitations?: readonly string[];
|
|
95
|
+
}
|
|
96
|
+
export interface PresentedCycle5Section {
|
|
97
|
+
index: number;
|
|
98
|
+
start_utf16: number;
|
|
99
|
+
end_utf16: number;
|
|
100
|
+
word_count: number;
|
|
101
|
+
raw_score: number;
|
|
102
|
+
raw_margin: number;
|
|
103
|
+
display_score: string;
|
|
104
|
+
level: CheckerLevelId;
|
|
105
|
+
band_id: Cycle5BandId;
|
|
106
|
+
passage?: string;
|
|
107
|
+
locator?: {
|
|
108
|
+
content_hash: string;
|
|
109
|
+
start_utf16: number;
|
|
110
|
+
end_utf16: number;
|
|
111
|
+
};
|
|
112
|
+
evidence: CheckerEvidenceInput[];
|
|
113
|
+
}
|
|
114
|
+
export interface PresentedCycle5Result {
|
|
115
|
+
ai_pattern: {
|
|
116
|
+
assessment_status: "assessed";
|
|
117
|
+
method_status: "pass" | "attention";
|
|
118
|
+
source: string;
|
|
119
|
+
raw_score: number;
|
|
120
|
+
raw_margin: number;
|
|
121
|
+
display_score: string;
|
|
122
|
+
score_scale: typeof CHECKER_SCORE_SCALE;
|
|
123
|
+
level: CheckerLevelId;
|
|
124
|
+
primary_display_threshold: number;
|
|
125
|
+
secondary_display_threshold: number;
|
|
126
|
+
flagged: boolean;
|
|
127
|
+
flag_reason: "primary" | "secondary" | null;
|
|
128
|
+
strongest_section_index: number;
|
|
129
|
+
reason: string;
|
|
130
|
+
limitations: [string, ...string[]];
|
|
131
|
+
};
|
|
132
|
+
sections: PresentedCycle5Section[];
|
|
133
|
+
}
|
|
134
|
+
/** Build the only canonical five-band AI presentation used by pages, reports and shares. */
|
|
135
|
+
export declare function presentCycle5Result(input: Cycle5PresentationInput): Readonly<PresentedCycle5Result>;
|
|
136
|
+
export declare function notAssessedAiPattern(reason?: string): Readonly<{
|
|
137
|
+
assessment_status: "not_assessed";
|
|
138
|
+
method_status: "not_run";
|
|
139
|
+
source: null;
|
|
140
|
+
raw_score: null;
|
|
141
|
+
raw_margin: null;
|
|
142
|
+
display_score: null;
|
|
143
|
+
score_scale: "zero_to_one_pattern_similarity";
|
|
144
|
+
level: null;
|
|
145
|
+
primary_display_threshold: null;
|
|
146
|
+
secondary_display_threshold: null;
|
|
147
|
+
flagged: null;
|
|
148
|
+
flag_reason: null;
|
|
149
|
+
strongest_section_index: null;
|
|
150
|
+
reason: string;
|
|
151
|
+
limitations: [string, ...string[]];
|
|
152
|
+
}>;
|
|
153
|
+
/**
|
|
154
|
+
* Reuse the compiled core's independent integrity/editorial axes without
|
|
155
|
+
* letting either one manufacture an AI result.
|
|
156
|
+
*/
|
|
157
|
+
export declare function composeCheckerAxes(combined: CombinedVerdictResult, presented?: Readonly<PresentedCycle5Result>): Readonly<{
|
|
158
|
+
ai_pattern: {
|
|
159
|
+
assessment_status: "assessed";
|
|
160
|
+
method_status: "pass" | "attention";
|
|
161
|
+
source: string;
|
|
162
|
+
raw_score: number;
|
|
163
|
+
raw_margin: number;
|
|
164
|
+
display_score: string;
|
|
165
|
+
score_scale: typeof CHECKER_SCORE_SCALE;
|
|
166
|
+
level: CheckerLevelId;
|
|
167
|
+
primary_display_threshold: number;
|
|
168
|
+
secondary_display_threshold: number;
|
|
169
|
+
flagged: boolean;
|
|
170
|
+
flag_reason: "primary" | "secondary" | null;
|
|
171
|
+
strongest_section_index: number;
|
|
172
|
+
reason: string;
|
|
173
|
+
limitations: [string, ...string[]];
|
|
174
|
+
} | Readonly<{
|
|
175
|
+
assessment_status: "not_assessed";
|
|
176
|
+
method_status: "not_run";
|
|
177
|
+
source: null;
|
|
178
|
+
raw_score: null;
|
|
179
|
+
raw_margin: null;
|
|
180
|
+
display_score: null;
|
|
181
|
+
score_scale: "zero_to_one_pattern_similarity";
|
|
182
|
+
level: null;
|
|
183
|
+
primary_display_threshold: null;
|
|
184
|
+
secondary_display_threshold: null;
|
|
185
|
+
flagged: null;
|
|
186
|
+
flag_reason: null;
|
|
187
|
+
strongest_section_index: null;
|
|
188
|
+
reason: string;
|
|
189
|
+
limitations: [string, ...string[]];
|
|
190
|
+
}>;
|
|
191
|
+
text_integrity: {
|
|
192
|
+
method_status: "pass" | "attention";
|
|
193
|
+
reading: import("../verdict/combine.js").IntegrityStatus;
|
|
194
|
+
reason: string;
|
|
195
|
+
findings: {
|
|
196
|
+
applied: string;
|
|
197
|
+
status: import("../verdict/combine.js").IntegrityStatus;
|
|
198
|
+
reason: string;
|
|
199
|
+
}[];
|
|
200
|
+
limitations: [string, ...string[]];
|
|
201
|
+
};
|
|
202
|
+
editorial: {
|
|
203
|
+
method_status: "pass" | "attention";
|
|
204
|
+
reading: import("../verdict/combine.js").SuggestionLevel;
|
|
205
|
+
reason: string;
|
|
206
|
+
findings: {
|
|
207
|
+
category: string;
|
|
208
|
+
}[];
|
|
209
|
+
limitations: [string, ...string[]];
|
|
210
|
+
};
|
|
211
|
+
}>;
|
|
212
|
+
export interface SharePayloadInput {
|
|
213
|
+
resultId: string;
|
|
214
|
+
generatedAt: string;
|
|
215
|
+
wordCount: number;
|
|
216
|
+
modelVersion: string;
|
|
217
|
+
presented: Readonly<PresentedCycle5Result>;
|
|
218
|
+
}
|
|
219
|
+
/** Build a share/export object whose type cannot accept draft text or evidence. */
|
|
220
|
+
export declare function buildContentFreeSharePayload(input: SharePayloadInput): Readonly<{
|
|
221
|
+
version: 1;
|
|
222
|
+
result_id: string;
|
|
223
|
+
level: "signal-strongly-ai" | "signal-likely-ai" | "signal-potentially-ai" | "signal-unclear" | "signal-likely-human";
|
|
224
|
+
display_score: string;
|
|
225
|
+
sections: {
|
|
226
|
+
index: number;
|
|
227
|
+
raw_score: number;
|
|
228
|
+
display_score: string;
|
|
229
|
+
level: "signal-strongly-ai" | "signal-likely-ai" | "signal-potentially-ai" | "signal-unclear" | "signal-likely-human";
|
|
230
|
+
}[];
|
|
231
|
+
word_count: number;
|
|
232
|
+
date: string;
|
|
233
|
+
model_version: string;
|
|
234
|
+
honesty_line: "No AI checker can prove who wrote a text — this is a pattern reading.";
|
|
235
|
+
contains_content: false;
|
|
236
|
+
}>;
|
|
237
|
+
/**
|
|
238
|
+
* Producer-side semantic checks complement the additive-field-tolerant JSON
|
|
239
|
+
* Schema. Run this immediately before serialising, sharing or rendering.
|
|
240
|
+
*/
|
|
241
|
+
export declare function assertCheckerResultInvariants(result: CheckerResult): void;
|