@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
package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/method-result.schema.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* This file was automatically generated by json-schema-to-typescript.
|
|
4
|
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
5
|
+
* and run json-schema-to-typescript to regenerate this file.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type HttpsSchemasOpaceAgencyContentIntegrityV1MethodResultSchemaJson = {
|
|
9
|
+
[k: string]: unknown;
|
|
10
|
+
} & {
|
|
11
|
+
id: string;
|
|
12
|
+
category: "detector" | "watermark" | "provenance" | "unicode" | "pattern" | "fidelity";
|
|
13
|
+
provider_or_method: string;
|
|
14
|
+
version: string;
|
|
15
|
+
status: "pass" | "attention" | "fail" | "inconclusive" | "unsupported" | "not_configured" | "not_run" | "error";
|
|
16
|
+
availability?: "available" | "restricted" | "not_available";
|
|
17
|
+
native_outcome?: string;
|
|
18
|
+
score: number | null;
|
|
19
|
+
score_scale?: {
|
|
20
|
+
[k: string]: unknown;
|
|
21
|
+
} | null;
|
|
22
|
+
threshold: {
|
|
23
|
+
[k: string]: unknown;
|
|
24
|
+
} | null;
|
|
25
|
+
segments: {
|
|
26
|
+
[k: string]: unknown;
|
|
27
|
+
}[];
|
|
28
|
+
evidence: {
|
|
29
|
+
[k: string]: unknown;
|
|
30
|
+
}[];
|
|
31
|
+
/**
|
|
32
|
+
* @minItems 1
|
|
33
|
+
*/
|
|
34
|
+
limitations: [string, ...string[]];
|
|
35
|
+
started_at: string;
|
|
36
|
+
completed_at: string;
|
|
37
|
+
privacy_route: "browser" | "wordpress_local" | "local_service" | "hub_provider" | "commercial_byok";
|
|
38
|
+
[k: string]: unknown;
|
|
39
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* This file was automatically generated by json-schema-to-typescript.
|
|
4
|
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
5
|
+
* and run json-schema-to-typescript to regenerate this file.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface HttpsSchemasOpaceAgencyContentIntegrityV1PatternFindingSchemaJson {
|
|
9
|
+
rule_id: string;
|
|
10
|
+
rule_version: string;
|
|
11
|
+
severity: "note" | "low" | "medium" | "high";
|
|
12
|
+
message: string;
|
|
13
|
+
suggestion?: string;
|
|
14
|
+
span: {
|
|
15
|
+
start_utf16: number;
|
|
16
|
+
end_utf16: number;
|
|
17
|
+
start_codepoint: number;
|
|
18
|
+
end_codepoint: number;
|
|
19
|
+
[k: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
matched_text_hash: string;
|
|
22
|
+
evidence: {
|
|
23
|
+
[k: string]: unknown;
|
|
24
|
+
};
|
|
25
|
+
[k: string]: unknown;
|
|
26
|
+
}
|
package/node_modules/@opacedev/ai-content-checker-contracts/src/generated/protected-span.schema.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* This file was automatically generated by json-schema-to-typescript.
|
|
4
|
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
5
|
+
* and run json-schema-to-typescript to regenerate this file.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface HttpsSchemasOpaceAgencyContentIntegrityV1ProtectedSpanSchemaJson {
|
|
9
|
+
id: string;
|
|
10
|
+
kind:
|
|
11
|
+
| "name"
|
|
12
|
+
| "organisation"
|
|
13
|
+
| "number"
|
|
14
|
+
| "date"
|
|
15
|
+
| "time"
|
|
16
|
+
| "currency"
|
|
17
|
+
| "unit"
|
|
18
|
+
| "url"
|
|
19
|
+
| "email"
|
|
20
|
+
| "quote"
|
|
21
|
+
| "citation"
|
|
22
|
+
| "code"
|
|
23
|
+
| "user_selected";
|
|
24
|
+
text: string;
|
|
25
|
+
start_utf16: number;
|
|
26
|
+
end_utf16: number;
|
|
27
|
+
start_codepoint: number;
|
|
28
|
+
end_codepoint: number;
|
|
29
|
+
normalised_value?: unknown;
|
|
30
|
+
policy: "exact" | "equivalent_format" | "must_remain_supported" | "user_review";
|
|
31
|
+
source: "deterministic" | "ner" | "citation_parser" | "user";
|
|
32
|
+
confidence?: number | null;
|
|
33
|
+
content_hash: string;
|
|
34
|
+
[k: string]: unknown;
|
|
35
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* This file was automatically generated by json-schema-to-typescript.
|
|
4
|
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
5
|
+
* and run json-schema-to-typescript to regenerate this file.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface HttpsSchemasOpaceAgencyContentIntegrityV1RewriteRequestSchemaJson {
|
|
9
|
+
schema_version: "1.0";
|
|
10
|
+
contract_version: string;
|
|
11
|
+
request_id: string;
|
|
12
|
+
created_at: string;
|
|
13
|
+
source: Source;
|
|
14
|
+
protected_spans: HttpsSchemasOpaceAgencyContentIntegrityV1ProtectedSpanSchemaJson[];
|
|
15
|
+
candidate_count: number;
|
|
16
|
+
/**
|
|
17
|
+
* @minItems 1
|
|
18
|
+
*/
|
|
19
|
+
allowed_routes: [
|
|
20
|
+
"browser" | "wordpress_local" | "local_service" | "hub_provider" | "commercial_byok",
|
|
21
|
+
...("browser" | "wordpress_local" | "local_service" | "hub_provider" | "commercial_byok")[]
|
|
22
|
+
];
|
|
23
|
+
checks: string[];
|
|
24
|
+
gate_policy: "strict" | "manual_review";
|
|
25
|
+
style_brief?: string;
|
|
26
|
+
[k: string]: unknown;
|
|
27
|
+
}
|
|
28
|
+
export interface Source {
|
|
29
|
+
content: string;
|
|
30
|
+
content_type: "plain_text" | "html" | "markdown";
|
|
31
|
+
language: string;
|
|
32
|
+
title?: string;
|
|
33
|
+
source_uri?: string;
|
|
34
|
+
content_hash?: string;
|
|
35
|
+
normalised_hash?: string;
|
|
36
|
+
[k: string]: unknown;
|
|
37
|
+
}
|
|
38
|
+
export interface HttpsSchemasOpaceAgencyContentIntegrityV1ProtectedSpanSchemaJson {
|
|
39
|
+
id: string;
|
|
40
|
+
kind:
|
|
41
|
+
| "name"
|
|
42
|
+
| "organisation"
|
|
43
|
+
| "number"
|
|
44
|
+
| "date"
|
|
45
|
+
| "time"
|
|
46
|
+
| "currency"
|
|
47
|
+
| "unit"
|
|
48
|
+
| "url"
|
|
49
|
+
| "email"
|
|
50
|
+
| "quote"
|
|
51
|
+
| "citation"
|
|
52
|
+
| "code"
|
|
53
|
+
| "user_selected";
|
|
54
|
+
text: string;
|
|
55
|
+
start_utf16: number;
|
|
56
|
+
end_utf16: number;
|
|
57
|
+
start_codepoint: number;
|
|
58
|
+
end_codepoint: number;
|
|
59
|
+
normalised_value?: unknown;
|
|
60
|
+
policy: "exact" | "equivalent_format" | "must_remain_supported" | "user_review";
|
|
61
|
+
source: "deterministic" | "ner" | "citation_parser" | "user";
|
|
62
|
+
confidence?: number | null;
|
|
63
|
+
content_hash: string;
|
|
64
|
+
[k: string]: unknown;
|
|
65
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export const SCHEMA_VERSION = "1.0" as const;
|
|
2
|
+
export const CONTRACT_VERSION = "1.0.0" as const;
|
|
3
|
+
export const WORDPRESS_REST_NAMESPACE = "oaci/v1" as const;
|
|
4
|
+
export const WORDPRESS_ADMIN_PAGE = "admin.php?page=oaci-lab" as const;
|
|
5
|
+
export const LOCAL_ENGINE_ORIGIN = "http://127.0.0.1:8741" as const;
|
|
6
|
+
export const PUBLIC_API_IDENTITY = "Opace\\ContentIntegrity\\Integration\\PublicApi::instance()" as const;
|
|
7
|
+
export const READY_HOOK = "oaci_ready" as const;
|
|
8
|
+
export const PHP_PUBLIC_API_METHODS = ["version", "is_compatible", "capabilities", "register_source_adapter", "create_session", "get_session", "approve", "get_approved_output", "mark_applied", "get_receipt", "asset_handles"] as const;
|
|
9
|
+
export const JS_MOUNT_CONTRACT = {
|
|
10
|
+
global: "OpaceContentIntegrity",
|
|
11
|
+
apiVersion: "1.0",
|
|
12
|
+
requiredOptions: ["surface", "sourceRef", "sourceHash", "getContent", "onApproved", "onClose"],
|
|
13
|
+
returns: ["destroy", "refresh", "getState"],
|
|
14
|
+
events: ["oaci:statechange", "oaci:approved", "oaci:error"]
|
|
15
|
+
} as const;
|
|
16
|
+
|
|
17
|
+
export const METHOD_STATUSES = ["pass", "attention", "fail", "inconclusive", "unsupported", "not_configured", "not_run", "error"] as const;
|
|
18
|
+
export type MethodStatus = (typeof METHOD_STATUSES)[number];
|
|
19
|
+
|
|
20
|
+
export const PRIVACY_ROUTES = ["browser", "wordpress_local", "local_service", "hub_provider", "commercial_byok"] as const;
|
|
21
|
+
export type PrivacyRoute = (typeof PRIVACY_ROUTES)[number];
|
|
22
|
+
|
|
23
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1EnvelopeSchemaJson as ContractEnvelope } from "./generated/envelope.schema.js";
|
|
24
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1MethodResultSchemaJson as MethodResult } from "./generated/method-result.schema.js";
|
|
25
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1AnalysisRequestSchemaJson as AnalysisRequest } from "./generated/analysis-request.schema.js";
|
|
26
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1AnalysisResultSchemaJson as AnalysisResult } from "./generated/analysis-result.schema.js";
|
|
27
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1ProtectedSpanSchemaJson as ProtectedSpan } from "./generated/protected-span.schema.js";
|
|
28
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1PatternFindingSchemaJson as PatternFinding } from "./generated/pattern-finding.schema.js";
|
|
29
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1GateResultSchemaJson as GateResult } from "./generated/gate-result.schema.js";
|
|
30
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1CandidateSchemaJson as Candidate } from "./generated/candidate.schema.js";
|
|
31
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1RewriteRequestSchemaJson as RewriteRequest } from "./generated/rewrite-request.schema.js";
|
|
32
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1JobSchemaJson as Job } from "./generated/job.schema.js";
|
|
33
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1CapabilitiesSchemaJson as Capabilities } from "./generated/capabilities.schema.js";
|
|
34
|
+
export type { HttpsSchemasOpaceAgencyContentIntegrityV1IntegrityReceiptSchemaJson as IntegrityReceipt } from "./generated/integrity-receipt.schema.js";
|
|
35
|
+
export type { OpaceAIContentIntegrityCheckerResult as CheckerResult } from "./generated/checker-result.schema.js";
|
|
36
|
+
|
|
37
|
+
export interface AnthropicUnsupportedMethodResultV1 {
|
|
38
|
+
id: "watermark.anthropic";
|
|
39
|
+
category: "watermark";
|
|
40
|
+
provider_or_method: string;
|
|
41
|
+
version: "unavailable-2026-08-26";
|
|
42
|
+
status: "unsupported";
|
|
43
|
+
availability: "not_available";
|
|
44
|
+
native_outcome?: "not_available";
|
|
45
|
+
score: null;
|
|
46
|
+
threshold: null;
|
|
47
|
+
segments: Record<string, unknown>[];
|
|
48
|
+
evidence: Record<string, unknown>[];
|
|
49
|
+
limitations: [string, ...string[]];
|
|
50
|
+
started_at: string;
|
|
51
|
+
completed_at: string;
|
|
52
|
+
privacy_route: PrivacyRoute;
|
|
53
|
+
[key: string]: unknown;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface JsMountOptionsV1 {
|
|
57
|
+
surface: string;
|
|
58
|
+
sourceRef: string;
|
|
59
|
+
sourceHash: string;
|
|
60
|
+
getContent(): string | Promise<string>;
|
|
61
|
+
onApproved(payload: unknown): void;
|
|
62
|
+
onClose(): void;
|
|
63
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const HASH_PATTERN = /^sha256:[a-f0-9]{64}$/;
|
|
2
|
+
|
|
3
|
+
function result(valid, errors = []) {
|
|
4
|
+
return { valid, errors };
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function validateProtectedSpan(span) {
|
|
8
|
+
const errors = [];
|
|
9
|
+
if (span.end_utf16 <= span.start_utf16) errors.push("utf16_range_empty_or_reversed");
|
|
10
|
+
if (span.end_codepoint <= span.start_codepoint) errors.push("codepoint_range_empty_or_reversed");
|
|
11
|
+
if (typeof span.text === "string") {
|
|
12
|
+
if (span.end_utf16 - span.start_utf16 !== span.text.length) errors.push("utf16_length_mismatch");
|
|
13
|
+
if (span.end_codepoint - span.start_codepoint !== [...span.text].length) errors.push("codepoint_length_mismatch");
|
|
14
|
+
}
|
|
15
|
+
if (!HASH_PATTERN.test(span.content_hash ?? "")) errors.push("source_hash_invalid");
|
|
16
|
+
return result(errors.length === 0, errors);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function validatePatternFinding(finding) {
|
|
20
|
+
const errors = [];
|
|
21
|
+
const span = finding.span ?? {};
|
|
22
|
+
if (span.end_utf16 <= span.start_utf16) errors.push("utf16_range_empty_or_reversed");
|
|
23
|
+
if (span.end_codepoint <= span.start_codepoint) errors.push("codepoint_range_empty_or_reversed");
|
|
24
|
+
if (!HASH_PATTERN.test(finding.matched_text_hash ?? "")) errors.push("matched_text_hash_invalid");
|
|
25
|
+
return result(errors.length === 0, errors);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function validateContractSemantics(schemaName, value) {
|
|
29
|
+
if (schemaName === "protected-span.schema.json") return validateProtectedSpan(value);
|
|
30
|
+
if (schemaName === "pattern-finding.schema.json") return validatePatternFinding(value);
|
|
31
|
+
return result(true);
|
|
32
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Opace Ltd
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# @opacedev/ai-content-checker-core
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Deterministic, offline content-integrity engine: invisible-Unicode and homoglyph forensics, named writing-signal rules with an editorial score, protected spans, safe-fix previews, diffs, gates and RFC 8785 hash-only receipts. This is the single analysis implementation used by every Opace surface (web checker, WordPress plugin, Chrome extension, Astro integration, CLI).
|
|
6
|
+
|
|
7
|
+
- Consumes `@opacedev/ai-content-checker-contracts` contract `1.0.0`
|
|
8
|
+
- Browser/SSR-safe ESM, transport-free by design: no network call, telemetry or postinstall download
|
|
9
|
+
- Unicode carriers: 38 rules over 415 code points, with context exemptions for emoji, cursive/Indic scripts and French typography (`unicode:2026.08.2`)
|
|
10
|
+
- Homoglyphs: 60 Cyrillic/Greek confusables with a mixed-script gate
|
|
11
|
+
- Writing signals: 113 weighted categories (116 named rules, including 7 rhythm and cadence stylometrics and 3 chat-export formatting rules, measured, not calibrated to a clean sheet: on 1,200 human long-form documents these rules flag 24.8% of them, and any claim that they produce no false positives is withdrawn — see the measured rates below) at `en-signals:2026.08.6`, with a raise-only evidence-based escalation policy recorded in an explanatory `escalation` result field. 95 of the 116 fire on real documents: one is recorded inactive and twenty dormant, with the measured per-rule inventory in `tests/battery/rule-liveness.json`
|
|
12
|
+
- Protected spans: 12 kinds including name, organisation and citation
|
|
13
|
+
- `watermark.anthropic` remains visibly `unsupported` until an official interface exists; the browser checker runs a separate live known-key scan (`@opace/watermark-lab`) rather than presenting that boundary as a check
|
|
14
|
+
- Licence: MIT for the Opace-authored package
|
|
15
|
+
|
|
16
|
+
A pass applies only to its named disclosed check and does not prove authorship or detector clearance. The full capability inventory is in the repository's [capability register](../../docs/CAPABILITIES.md); every test total and evaluation behind it is indexed in the [evidence index](../../docs/EVIDENCE-INDEX.md).
|
|
17
|
+
|
|
18
|
+
> Release state: a 0.1.0 npm candidate is prepared locally but is not published. The install command below applies only after owner-approved publication.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
npm install @opacedev/ai-content-checker-core
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Targets ESM on modern browsers and Node.js 20 or newer.
|
|
27
|
+
|
|
28
|
+
## API
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
import {
|
|
32
|
+
inspect, // full analysis over an AnalysisRequest
|
|
33
|
+
computeEditorialSignals, // 0-100 writing-signal score for plain text
|
|
34
|
+
inspectSignalsV2, // raw signal findings
|
|
35
|
+
inspectUnicode, // carrier/homoglyph findings for a string
|
|
36
|
+
extractProtectedSpans, // 12 protected-span kinds
|
|
37
|
+
previewSafeFixes, diff, validateCandidate,
|
|
38
|
+
buildReceipt, verifyReceipt,
|
|
39
|
+
presentCycle5Result, composeCheckerAxes,
|
|
40
|
+
buildContentFreeSharePayload, assertCheckerResultInvariants,
|
|
41
|
+
listMethods, registerPatternPack,
|
|
42
|
+
projectVisibleText, prefixedSha256, sha256Hex, utf8Bytes,
|
|
43
|
+
UNICODE_RULES_VERSION, EN_SIGNALS_PATTERN_VERSION,
|
|
44
|
+
} from "@opacedev/ai-content-checker-core";
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The checker-result helpers are presentation/contract logic, not a bundled detector. They freeze the
|
|
48
|
+
Cycle-5 identity and five `signal-*` level ids, format all scores once per run, preserve the three
|
|
49
|
+
independent axes and reject model/route/section/export contradictions. A full-checker adapter supplies
|
|
50
|
+
the measured model result; without one, `notAssessedAiPattern()` is the only honest AI axis.
|
|
51
|
+
|
|
52
|
+
### Full inspection
|
|
53
|
+
|
|
54
|
+
`inspect(request)` takes a contract `AnalysisRequest` and returns a frozen `AnalysisResult` with per-method statuses, evidence, limitations and hashes. Verified example (output from the built package):
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
const result = await inspect({
|
|
58
|
+
schema_version: "1.0",
|
|
59
|
+
contract_version: "1.0.0",
|
|
60
|
+
request_id: "req_readme_demo",
|
|
61
|
+
created_at: new Date().toISOString(),
|
|
62
|
+
source: { content: "In today's rapidly evolving landscape, Opace quoted £1,250.",
|
|
63
|
+
content_type: "plain_text", language: "en-GB" },
|
|
64
|
+
checks: ["unicode.invisible", "style.patterns", "watermark.anthropic"],
|
|
65
|
+
privacy: { allowed_routes: ["browser"], save_receipt: false, retain_content: false }
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
result.summary;
|
|
69
|
+
// { pass: 0, attention: 2, fail: 0, inconclusive: 0, unsupported: 1, not_configured: 0, not_run: 0, error: 0 }
|
|
70
|
+
result.methods.map(m => [m.id, m.status]);
|
|
71
|
+
// [["unicode.invisible","attention"], ["style.patterns","attention"], ["watermark.anthropic","unsupported"]]
|
|
72
|
+
result.protected_spans.map(s => s.kind);
|
|
73
|
+
// ["currency", "number"]
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The zero-width space hidden in the sample content is what turns `unicode.invisible` to `attention`. Statuses come from the fixed vocabulary `pass | attention | fail | inconclusive | unsupported | not_configured | not_run | error`; unrun checks are never collapsed into a pass, and a zero-finding pattern run carries a scope note stating it is not evidence of human authorship.
|
|
77
|
+
|
|
78
|
+
### Editorial signals score
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
const signals = computeEditorialSignals(draftText);
|
|
82
|
+
// { score: 23, classification: "mixed_signals", probabilities, confidence: "low",
|
|
83
|
+
// categoriesHit, findingCount, wordCount, version: "en-signals:2026.08.6",
|
|
84
|
+
// status: "scored", escalation: null, description }
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Classification is trinary (`human_like` / `mixed_signals` / `ai_like`), false-negative-biased by design, and probability-consistent: the label is always the argmax of the published probabilities. The evidence-based escalation policy (artefact floor, citation co-occurrence, artefact-plus-score, formatting floor, formatting cluster, furniture gate, finding breadth) can only raise a classification and, when it does, `escalation` names the policy and reason. Never present the score as authorship detection: clean, well-prompted AI prose scores low on any rule tier, which is why the result vocabulary says "no strong AI-style signals" rather than "human".
|
|
88
|
+
|
|
89
|
+
Measured on the fresh 5,558-document long-form corpus (`services/local-engine/research/longform-corpus/`), this rules tier detects **45.1%** of AI writing and wrongly flags **24.8%** of human writing. It flags roughly one human document in four, which is why it is editorial suggestion only and contributes nothing to any AI verdict. The older provider-eval aggregate is superseded and must not be quoted: its human side was 169 documents, 76% of them encyclopaedic and question-and-answer text, so its rate described that corpus and not published prose. See `docs/CAPABILITIES.md` §7.2 and §7.3.
|
|
90
|
+
|
|
91
|
+
### Unicode findings
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
inspectUnicode("claimed");
|
|
95
|
+
// [{ code_point: "U+200B", severity: "medium", fix: "remove", span: {...},
|
|
96
|
+
// matched_text_hash: "sha256:...", limitations: [...] }]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Test and integration boundary
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
npm ci
|
|
103
|
+
npm test
|
|
104
|
+
npm run pack:check
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Use the typed exports rather than copying algorithms into a consumer; browser, Astro, CLI and extension adapters must produce the same stable fields for the same projected input, and the repository's cross-surface battery enforces this. Consumers remain responsible for explicit user consent before inspecting content and for keeping content out of logs and receipts.
|
|
108
|
+
|
|
109
|
+
## Attribution
|
|
110
|
+
|
|
111
|
+
This engine was built on existing open-source work by deliberate choice, so the projects it
|
|
112
|
+
stands on are named here rather than only in a licence file.
|
|
113
|
+
|
|
114
|
+
- [avoid-ai-writing](https://github.com/conorbronsdon/avoid-ai-writing) — MIT, Conor Bronsdon and contributors. 46 of the 51 v2 writing-pattern rule categories, the stylometric methods, the weights and the classifier logic, adapted to TypeScript, plus Cyrillic and Greek lookalike map data. One upstream bug was fixed in the port.
|
|
115
|
+
- [watermarks-remover](https://github.com/guillaumemeyer/watermarks-remover) — MIT, Guillaume Meyer. The invisible-character and space-substitute carrier tables and the explicit-carrier inspection model. Table data only; no upstream code is distributed.
|
|
116
|
+
- [Unicode Consortium character data](https://www.unicode.org/Public/UCD/latest/) — Unicode licence. The 415-code-point carrier inventory across 38 rules and the 60-entry confusable set.
|
|
117
|
+
- [antislop-sampler](https://github.com/sam-paech/antislop-sampler) — Apache-2.0, Sam Paech. Fiction phrase and over-represented name data behind the `fiction-slop-phrase` and `fiction-promptonym` rules.
|
|
118
|
+
- [slop-forensics](https://github.com/sam-paech/slop-forensics) — MIT, Sam Paech. Per-model observations corroborating the fiction-lane rules.
|
|
119
|
+
- [SLOP_Detector](https://github.com/SicariusSicariiStuff/SLOP_Detector) — Apache-2.0, SicariusSicariiStuff. The graded penalty-class weighting approach.
|
|
120
|
+
- [slop-gate](https://github.com/hwajongpark/slop-gate) — MIT, hwajongpark. Promotional-register and buzz-phrase pattern data.
|
|
121
|
+
- [anti-ai-writing](https://github.com/avectats7/anti-ai-writing) — MIT, avectats7. Buzz-phrase and weak-verb observation data.
|
|
122
|
+
- [anti-slop](https://github.com/kjmagnan1s/anti-slop) — MIT, kjmagnan1s. Faux-insight phrase data and the protect-list and context-profile design.
|
|
123
|
+
- [claude-slop-detector](https://github.com/aplaceforallmystuff/claude-slop-detector) — MIT, aplaceforallmystuff. Staccato-fragment and tripled-negation observations.
|
|
124
|
+
- [Wikipedia, *Signs of AI writing*](https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing) — CC BY-SA 4.0. Editorial guidance independently re-expressed with no verbatim excerpts, credited as the licence requires.
|
|
125
|
+
- [Project Gutenberg](https://www.gutenberg.org) public-domain texts, all published before 1929 — the embedded human-prose reference corpus behind the rhythm and register signals.
|
|
126
|
+
- [canonicalize](https://github.com/cyberphone/json-canonicalization) — Apache-2.0. RFC 8785 canonicalisation.
|
|
127
|
+
- Published academic findings by Liang et al. (ICML 2024), Kobak et al. (*Science Advances* 2025), Juzek & Ward (COLING 2025), Reinhart et al. (PNAS 2025), Geng & Trotta (2024) and Pew Research (2026), used as rule thresholds and lexicon facts.
|
|
128
|
+
|
|
129
|
+
Several well-known detector repositories were cloned and read during the research phase and are
|
|
130
|
+
credited as exactly that — read, not used. Nothing in this package derives from `fast-detect-gpt`,
|
|
131
|
+
`Binoculars`, `RADAR`, `DIPPER`, `ai-detector-bench`, `BIRA`, `SIRA` or `MarkLLM`.
|
|
132
|
+
|
|
133
|
+
Full records, with versions, snapshot commits and file-level destinations:
|
|
134
|
+
[THIRD_PARTY_NOTICES.md](https://github.com/OpaceDigitalAgency/opace-ai-content-checker-detector/blob/main/THIRD_PARTY_NOTICES.md) ·
|
|
135
|
+
[DEPENDENCY-LEDGER.md](https://github.com/OpaceDigitalAgency/opace-ai-content-checker-detector/blob/main/docs/legal/DEPENDENCY-LEDGER.md).
|
|
136
|
+
|
|
137
|
+
## Troubleshooting and links
|
|
138
|
+
|
|
139
|
+
- **A check reports `unsupported`:** preserve that result. Do not replace it with a different method or a pass.
|
|
140
|
+
- **Browser and server output differ:** confirm both adapters supplied the same projected UTF-8 text and use the same contract/core versions (`UNICODE_RULES_VERSION`, `EN_SIGNALS_PATTERN_VERSION` are exported for exactly this).
|
|
141
|
+
- **A safe fix changes protected content:** reject the candidate and inspect the protected-span gate before applying any text.
|
|
142
|
+
|
|
143
|
+
Report security concerns through the repository [security policy](https://github.com/OpaceDigitalAgency/opace-ai-content-checker-detector/blob/main/SECURITY.md). For non-sensitive help, use [Opace AI Content Checker & Detector support](https://opace.agency/get-in-touch/). Changes follow the repository [contribution guide](../../CONTRIBUTING.md) and [changelog](../../CHANGELOG.md).
|
|
144
|
+
|
|
145
|
+
[Opace AI Content Checker & Detector](https://opace.agency/tools/ai/content-verification-integrity/) · [Browser checker](https://opace.agency/tools/ai/content-verification-integrity/checker/) · [Capability register](../../docs/CAPABILITIES.md) · [Opace](https://opace.agency/) · [Opace Digital Agency on GitHub](https://github.com/OpaceDigitalAgency) · [Related contracts package](../contracts/README.md)
|
|
146
|
+
|
|
147
|
+
## Where this is weakest, measured
|
|
148
|
+
|
|
149
|
+
This package ships the deterministic character forensics and editorial writing rules. It does
|
|
150
|
+
**not** contain the trained model that produces an AI reading; Cycle 5 runs only in the web
|
|
151
|
+
checker. The model results are disclosed here so package users can distinguish the two systems.
|
|
152
|
+
|
|
153
|
+
**The writing rules are editorial feedback, not detection.** On 922 machine and 1,200 held-out
|
|
154
|
+
human long-form documents, they detect 45.1% of machine writing while flagging **24.8% of human
|
|
155
|
+
writing** — one human document in four. `computeEditorialSignals` returns a writing score, never
|
|
156
|
+
an authorship reading, and must not be presented as one.
|
|
157
|
+
|
|
158
|
+
The deployed Cycle 5 model (`tier3-cycle5-v1`, margin rule
|
|
159
|
+
`max(m1, m2+0.34) >= 3.571`) was measured separately through both live runtimes on the full
|
|
160
|
+
5,558-document long-form evaluation corpus. That corpus is not wholly independent: 654/922 AI
|
|
161
|
+
documents are independent of every Cycle 2 split and 268 are not; 11/4,636 human documents
|
|
162
|
+
overlap. The separate topic-matched held-out slice is the independent evasion measurement.
|
|
163
|
+
|
|
164
|
+
| Cycle 5 measurement | result | denominator and runtime |
|
|
165
|
+
|---|---:|---|
|
|
166
|
+
| AI documents flagged | **97.8%** | 902/922, EU server fp32 |
|
|
167
|
+
| human documents wrongly flagged | **0.99%** | 46/4,636, EU server fp32 |
|
|
168
|
+
| AI documents flagged | **97.6%** | 900/922, browser int8 |
|
|
169
|
+
| human documents wrongly flagged | **1.57%** | 73/4,636, browser int8 |
|
|
170
|
+
| topic-matched held-out AI flagged | **86.9%** | 153/176, server evaluation route |
|
|
171
|
+
| structured human partners wrongly flagged | **0.2%** | 1/418, server evaluation route |
|
|
172
|
+
| human fiction wrongly flagged | **3.1% / 3.5%** | 7/227 server / 8/227 browser |
|
|
173
|
+
| held-out 100-word AI flagged | **76.8%** | 43/56, server evaluation route |
|
|
174
|
+
| heavy AI edits of human originals flagged | **28.5%** | 39/137, server evaluation view |
|
|
175
|
+
| academic human documents wrongly flagged | **0.8%** | 15/1,992, server evaluation view |
|
|
176
|
+
|
|
177
|
+
The 100-word cell is small, fiction remains higher-risk than the overall human set, and treating
|
|
178
|
+
heavy AI edits as machine-assisted is a product boundary rather than proof of authorship. Do not
|
|
179
|
+
use a result for an academic misconduct decision about one student.
|
|
180
|
+
|
|
181
|
+
*Historical, not current:* Cycle 2 (`tier3-cycle2-v1`, live 28 August – 1 September 2026) produced
|
|
182
|
+
the earlier 883/922 server, 889/922 browser, 45/4,636 server-human and 90/4,636 browser-human
|
|
183
|
+
figures. Its fiction and length rows are retired and must not be mixed with Cycle 5.
|
|
184
|
+
|
|
185
|
+
Complete list with sources: [Honest limitations](https://github.com/OpaceDigitalAgency/opace-ai-content-checker-detector#honest-limitations).
|
|
186
|
+
The same figures plotted, with the 50% acceptance floor drawn in: [result charts](https://github.com/OpaceDigitalAgency/opace-ai-content-checker-detector#what-it-measures-and-where-it-fails).
|