@shuji-bonji/pdf-constraints 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 shuji-bonji
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.
package/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # @shuji-bonji/pdf-constraints
2
+
3
+ [![CI](https://github.com/shuji-bonji/pdf-constraints/actions/workflows/ci.yml/badge.svg)](https://github.com/shuji-bonji/pdf-constraints/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/@shuji-bonji/pdf-constraints.svg)](https://www.npmjs.com/package/@shuji-bonji/pdf-constraints)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
6
+
7
+ ISO 32000 の条文を「**ファイルが構造上どういう状態か**」へ写像した制約テーブルと、その決定論的評価器です。
8
+
9
+ これは PDF family の共有基盤ライブラリで、MCP サーバではありません。
10
+ MCP としての露出は [pdf-verify-mcp](https://github.com/shuji-bonji/pdf-verify-mcp) の `validate_clauses` が担います。
11
+
12
+ ## 何のためのものか
13
+
14
+ family の各メンバーが答える問いを並べると、このパッケージの位置が決まります。
15
+
16
+ | 誰が | 答える問い |
17
+ |---|---|
18
+ | [pdf-spec-mcp](https://github.com/shuji-bonji/pdf-spec-mcp) | 条文は**何を要求する**か |
19
+ | [pdf-reader-mcp](https://github.com/shuji-bonji/pdf-reader-mcp) | ファイルに**何がある**か |
20
+ | **pdf-constraints** | **条文を満たすとはどういう状態か** |
21
+ | [pdf-verify-mcp](https://github.com/shuji-bonji/pdf-verify-mcp) | **どこが破られている**か |
22
+ | [pdf-writer-mcp](https://github.com/shuji-bonji/pdf-writer-mcp) | それを**どう書く**か |
23
+
24
+ veraPDF は PDF/A・PDF/UA を判定しますが、**ISO 32000 本体の条文違反は見ません**。
25
+ そこが空いていたために「CFF フォントを `FontFile2` で埋め込む」という shall 違反が、
26
+ ビューアの警告として「無害」と誤分類されたまま残ったことがあります。本パッケージはその穴を埋めます。
27
+
28
+ > [!IMPORTANT]
29
+ > **fail が無いことは適合の証明ではありません。** 「収録した制約の範囲で反証できなかった」以上を意味しません。
30
+ > 適合は証明できず、反証できるだけです。
31
+
32
+ ## 使い方
33
+
34
+ ```sh
35
+ npx @shuji-bonji/pdf-constraints check document.pdf
36
+ npx @shuji-bonji/pdf-constraints check document.pdf --domain font-embedding --given isSubset=true
37
+ ```
38
+
39
+ 終了コードは 3 値です。**判定できなかったことを合格や違反と混ぜません**。
40
+
41
+ | code | 意味 |
42
+ |---|---|
43
+ | 0 | 収録した制約では違反を見つけられなかった(適合の証明ではない) |
44
+ | 1 | 違反あり |
45
+ | 2 | 判定不能(ファイルが開けない・引数不正など) |
46
+
47
+ ライブラリとして:
48
+
49
+ ```ts
50
+ import { checkFile, loadTable, evaluateConstraint } from '@shuji-bonji/pdf-constraints';
51
+
52
+ const report = await checkFile('/abs/path/document.pdf', { given: { isSubset: true } });
53
+ report.violations; // 違反数
54
+ report.packageVersion; // どの版のテーブルで判定したか(決定論の由来)
55
+ ```
56
+
57
+ 制約テーブル(JSON)は直接読めます。
58
+
59
+ ```ts
60
+ import table from '@shuji-bonji/pdf-constraints/tables/font-embedding.json' with { type: 'json' };
61
+ ```
62
+
63
+ ## 収録テーブル
64
+
65
+ | ドメイン | 条文 | 制約 |
66
+ |---|---|---|
67
+ | `font-embedding` | §9.9.1 / §9.9.2 / §9.7.4.2(Table 124 / 125 含む) | CT-FONT-1〜5 — 埋め込みキーと中身の一致、サブセット名タグ、`Length1` |
68
+ | `document-metadata` | §14.3.2 / §14.3.3 / §14.3.4 / §7.9.4 | CT-META-1〜6 — メタデータストリームの型、日付書式、Info↔XMP の等価、`Trapped` |
69
+
70
+ ## 4 つの状態
71
+
72
+ 制約ごとに次のどれかを返します。**verdict(推奨判定)は出しません** — それは
73
+ pdf-verify-mcp の `evaluate_policy` の役割です。
74
+
75
+ | 状態 | 意味 |
76
+ |---|---|
77
+ | `pass` | 収録した検査では反証できなかった |
78
+ | `fail` | 反証できた |
79
+ | `not_applicable` | 適用条件を満たさない(この文書には関係ない条文) |
80
+ | `needs_external_fact` | 外部事実が供給されておらず判定に到達できない |
81
+
82
+ ### `given.*` — ファイルの外にある事実
83
+
84
+ 条文には、ファイル単体からは判定できない前提を持つものがあります。たとえば
85
+ R-9.9.2-2「**サブセットフォントの**名前は 6 大文字タグで始まる shall」の「サブセットか否か」は、
86
+ PDF の中には書かれていません(作った側だけが知っている)。
87
+
88
+ こうした事実は `--given isSubset=true` で供給します。渡さなければ、その制約は
89
+ `needs_external_fact` に縮退します — **既定値で埋めて沈黙合格や冤罪を作らない**ためです。
90
+
91
+ ### 「違反」と「違反の痕跡」
92
+
93
+ 条文の主語が PDF processor(書き込み行為)である場合、ファイルから観測できるのは
94
+ **誰かが破った痕跡**であって、直近の書き手の違反とは限りません(§14.3.4 は、既存の不整合を
95
+ そのまま残すことを許しています)。そうした制約は `subjectNote` を持ち、レポートでも
96
+ 「違反の痕跡」と述べます。
97
+
98
+ ## やらないこと
99
+
100
+ - **条文原文の提供** — pdf-spec-mcp の役割です。テーブルは clause ID で参照するだけで原文を複製しません
101
+ - **適合の証明** — 反証できるだけです
102
+ - **verdict・推奨判定** — `evaluate_policy` の役割です
103
+ - **veraPDF の代替** — PDF/A の判定主体は veraPDF です。収録は ISO 32000-1/-2 本体条文のみ
104
+ - **内容の真偽判定** — 条文に適合したファイルが嘘を述べることはあります
105
+
106
+ ## 開発
107
+
108
+ ```sh
109
+ npm install
110
+ npm run build
111
+ npm test
112
+ npm run validate:tables # 制約テーブル自身を tables/schema.json で検証
113
+ ```
114
+
115
+ テーブルを増やすときは `tables/*.json` を足して `validate:tables` を通します。
116
+ 述語(op)を増やす場合は `tables/schema.json` と `src/evaluate.ts` を対で更新してください —
117
+ テーブルと評価意味論が同一バージョンで結束していることが、このパッケージの決定論の担保です。
118
+
119
+ ## ライセンス
120
+
121
+ MIT © shuji-bonji
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 高水準 API — ファイルを読んでテーブルを当てる。
3
+ *
4
+ * ここが CLI と pdf-verify-mcp の `validate_clauses` の共通入口になる。
5
+ * 返り値には**必ずテーブルとパッケージの版を含める**(同じ facts から同じ結果が出ることの
6
+ * 由来を「どの版のテーブルで判定したか」まで言えるようにするため。specs/18 §4.5)。
7
+ */
8
+ import type { CheckReport, ConstraintTable } from './types.js';
9
+ /** 同梱テーブルの名前一覧 */
10
+ export declare function listTables(): string[];
11
+ export declare function loadTable(name: string): ConstraintTable;
12
+ export interface CheckOptions {
13
+ /** 対象ドメイン。省略時は同梱テーブル全部 */
14
+ domains?: string[];
15
+ /**
16
+ * 外部事実(`isSubset` など)。**ファイル単体からは決定できない事実**を供給する口。
17
+ * 渡さなければ、それを要求する制約は `needs_external_fact` に縮退する(沈黙合格しない)。
18
+ */
19
+ given?: Record<string, unknown>;
20
+ }
21
+ /** PDF のバイト列に制約テーブルを当てる */
22
+ export declare function checkBytes(bytes: Uint8Array, options?: CheckOptions): Promise<CheckReport>;
23
+ /** ファイルパス版 */
24
+ export declare function checkFile(path: string, options?: CheckOptions): Promise<CheckReport>;
25
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAgB,MAAM,YAAY,CAAC;AAM7E,kBAAkB;AAClB,wBAAgB,UAAU,IAAI,MAAM,EAAE,CAErC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAEvD;AAED,MAAM,WAAW,YAAY;IAC3B,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,2BAA2B;AAC3B,wBAAsB,UAAU,CAC9B,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CA0CtB;AAED,cAAc;AACd,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAE9F"}
package/dist/check.js ADDED
@@ -0,0 +1,67 @@
1
+ /**
2
+ * 高水準 API — ファイルを読んでテーブルを当てる。
3
+ *
4
+ * ここが CLI と pdf-verify-mcp の `validate_clauses` の共通入口になる。
5
+ * 返り値には**必ずテーブルとパッケージの版を含める**(同じ facts から同じ結果が出ることの
6
+ * 由来を「どの版のテーブルで判定したか」まで言えるようにするため。specs/18 §4.5)。
7
+ */
8
+ import { readFileSync } from 'node:fs';
9
+ import { createRequire } from 'node:module';
10
+ import { dirname, join } from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { PDFDocument } from 'pdf-lib';
13
+ import { evaluateConstraint, evaluateDocumentAsserts } from './evaluate.js';
14
+ import { collectSubjects } from './facts/registry.js';
15
+ const here = dirname(fileURLToPath(import.meta.url));
16
+ const tablesDir = join(here, '..', 'tables');
17
+ const packageVersion = createRequire(import.meta.url)('../package.json').version;
18
+ /** 同梱テーブルの名前一覧 */
19
+ export function listTables() {
20
+ return ['font-embedding', 'document-metadata'];
21
+ }
22
+ export function loadTable(name) {
23
+ return JSON.parse(readFileSync(join(tablesDir, `${name}.json`), 'utf8'));
24
+ }
25
+ /** PDF のバイト列に制約テーブルを当てる */
26
+ export async function checkBytes(bytes, options = {}) {
27
+ const tables = (options.domains ?? listTables()).map(loadTable);
28
+ const given = Object.fromEntries(Object.entries(options.given ?? {}).map(([key, value]) => [`given.${key}`, value]));
29
+ const doc = await PDFDocument.load(bytes, { updateMetadata: false });
30
+ const scopes = tables.flatMap((t) => t.constraints.map((c) => c.appliesTo));
31
+ const subjectsByScope = collectSubjects(doc, scopes, given);
32
+ const report = {
33
+ packageVersion,
34
+ tables: tables.map((t) => ({ name: t.name, version: t.version })),
35
+ subjects: [...subjectsByScope.values()].reduce((sum, list) => sum + list.length, 0),
36
+ results: [],
37
+ violations: 0,
38
+ };
39
+ for (const table of tables) {
40
+ for (const constraint of table.constraints) {
41
+ const subjects = subjectsByScope.get(constraint.appliesTo) ?? [];
42
+ for (const subject of subjects) {
43
+ const result = evaluateConstraint(constraint, subject.facts);
44
+ result.target = subject.label;
45
+ report.results.push(result);
46
+ report.violations += result.failures?.length ?? 0;
47
+ }
48
+ // 文書横断の検査(subject を跨ぐので個別評価とは別立て)
49
+ const crossFailures = evaluateDocumentAsserts(constraint, subjects, given);
50
+ if (crossFailures.length > 0) {
51
+ report.results.push({
52
+ constraint: constraint.id,
53
+ target: '(document)',
54
+ status: 'fail',
55
+ failures: crossFailures,
56
+ });
57
+ report.violations += crossFailures.length;
58
+ }
59
+ }
60
+ }
61
+ return report;
62
+ }
63
+ /** ファイルパス版 */
64
+ export async function checkFile(path, options = {}) {
65
+ return checkBytes(readFileSync(path), options);
66
+ }
67
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7C,MAAM,cAAc,GAAW,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC;AAEzF,kBAAkB;AAClB,MAAM,UAAU,UAAU;IACxB,OAAO,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,OAAO,CAAC,EAAE,MAAM,CAAC,CAAoB,CAAC;AAC9F,CAAC;AAYD,2BAA2B;AAC3B,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,KAAiB,EACjB,UAAwB,EAAE;IAE1B,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAChE,MAAM,KAAK,GAAU,MAAM,CAAC,WAAW,CACrC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,CACnF,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,MAAM,MAAM,GAAY,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACrF,MAAM,eAAe,GAAG,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAE5D,MAAM,MAAM,GAAgB;QAC1B,cAAc;QACd,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACjE,QAAQ,EAAE,CAAC,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACnF,OAAO,EAAE,EAAE;QACX,UAAU,EAAE,CAAC;KACd,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YACjE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC7D,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;gBAC9B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC5B,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC;YACpD,CAAC;YACD,kCAAkC;YAClC,MAAM,aAAa,GAAG,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC3E,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;oBAClB,UAAU,EAAE,UAAU,CAAC,EAAE;oBACzB,MAAM,EAAE,YAAY;oBACpB,MAAM,EAAE,MAAM;oBACd,QAAQ,EAAE,aAAa;iBACxB,CAAC,CAAC;gBACH,MAAM,CAAC,UAAU,IAAI,aAAa,CAAC,MAAM,CAAC;YAC5C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,cAAc;AACd,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,UAAwB,EAAE;IACtE,OAAO,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI — MCP 抜きで制約テーブルを当てる(CI の回帰などに使う)。
4
+ *
5
+ * **exit code は 3 値**:
6
+ * 0 = 違反なし(収録した制約の範囲で反証できなかった。適合の証明ではない)
7
+ * 1 = 違反あり
8
+ * 2 = 判定不能(引数不正・ファイルが開けない・評価に到達できない)
9
+ *
10
+ * 2 を分けているのは、**判定できなかったことを「合格」や「違反」と混ぜないため**。
11
+ * exit 0 を成功と読んだ結果を取り違えた事例(pdfnative 監査 G-1)の再演を避ける。
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
package/dist/cli.js ADDED
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI — MCP 抜きで制約テーブルを当てる(CI の回帰などに使う)。
4
+ *
5
+ * **exit code は 3 値**:
6
+ * 0 = 違反なし(収録した制約の範囲で反証できなかった。適合の証明ではない)
7
+ * 1 = 違反あり
8
+ * 2 = 判定不能(引数不正・ファイルが開けない・評価に到達できない)
9
+ *
10
+ * 2 を分けているのは、**判定できなかったことを「合格」や「違反」と混ぜないため**。
11
+ * exit 0 を成功と読んだ結果を取り違えた事例(pdfnative 監査 G-1)の再演を避ける。
12
+ */
13
+ import { checkFile, listTables } from './check.js';
14
+ const USAGE = `Usage: pdf-constraints check <file.pdf> [options]
15
+
16
+ Options:
17
+ --domain <name> Table to apply (repeatable). Default: all bundled tables
18
+ --given <k=v> Supply an external fact (repeatable), e.g. --given isSubset=true
19
+ --json Print the raw report as JSON
20
+
21
+ Bundled tables: ${listTables().join(', ')}
22
+
23
+ Exit: 0 = no violations found, 1 = violations found, 2 = could not decide`;
24
+ function formatReport(report) {
25
+ const lines = [];
26
+ lines.push(`# Constraint check (pdf-constraints@${report.packageVersion}; ` +
27
+ `${report.tables.map((t) => `${t.name} v${t.version}`).join(', ')})`, '');
28
+ for (const result of report.results) {
29
+ if (result.status === 'fail') {
30
+ for (const failure of result.failures ?? []) {
31
+ // 主語が processor の条文は「違反」と断定しない(specs/18 §1 / F-5)
32
+ const kind = failure.traceOnly ? 'TRACE' : 'FAIL ';
33
+ lines.push(`${kind} ${result.constraint} [${failure.clauses.join(', ')}] ${result.target}`, ` ${failure.message}`, ` ${failure.fact} = ${JSON.stringify(failure.actual)}`);
34
+ }
35
+ }
36
+ else if (result.status === 'needs_external_fact') {
37
+ lines.push(`SKIP ${result.constraint} ${result.target} — needs ${result.missing} ` +
38
+ `(pass にも fail にも倒していない)`);
39
+ }
40
+ }
41
+ if (report.violations === 0)
42
+ lines.push('No violations found in the constraints checked.');
43
+ // 縮退した制約は要約にも出す。exit 0 は「違反が無かった」であって
44
+ // 「全部を検査できた」ではない — その差を数字で見せておかないと読み違えられる
45
+ const skipped = report.results.filter((r) => r.status === 'needs_external_fact').length;
46
+ lines.push('', `Subjects: ${report.subjects} Violations: ${report.violations}` +
47
+ (skipped > 0 ? ` Not decided: ${skipped} (missing external facts — see --given)` : ''), 'Note: the absence of failures is not proof of conformance — only that nothing in the', 'bundled constraints could be disproved.');
48
+ return lines.join('\n');
49
+ }
50
+ async function main(argv) {
51
+ if (argv[0] !== 'check' || !argv[1]) {
52
+ console.error(USAGE);
53
+ return 2;
54
+ }
55
+ const file = argv[1];
56
+ const domains = [];
57
+ const given = {};
58
+ let asJson = false;
59
+ for (let i = 2; i < argv.length; i++) {
60
+ const arg = argv[i];
61
+ if (arg === '--domain' && argv[i + 1])
62
+ domains.push(argv[++i]);
63
+ else if (arg === '--json')
64
+ asJson = true;
65
+ else if (arg === '--given' && argv[i + 1]) {
66
+ const [key, raw] = argv[++i].split('=');
67
+ given[key] = raw === 'true' ? true : raw === 'false' ? false : raw;
68
+ }
69
+ else {
70
+ console.error(`Unknown argument: ${arg}\n\n${USAGE}`);
71
+ return 2;
72
+ }
73
+ }
74
+ let report;
75
+ try {
76
+ report = await checkFile(file, {
77
+ domains: domains.length > 0 ? domains : undefined,
78
+ given,
79
+ });
80
+ }
81
+ catch (error) {
82
+ // 開けない・壊れている・テーブルが無い — いずれも「判定できなかった」
83
+ console.error(`Could not decide: ${error instanceof Error ? error.message : String(error)}`);
84
+ return 2;
85
+ }
86
+ console.log(asJson ? JSON.stringify(report, null, 2) : formatReport(report));
87
+ return report.violations > 0 ? 1 : 0;
88
+ }
89
+ main(process.argv.slice(2))
90
+ .then((code) => process.exit(code))
91
+ .catch((error) => {
92
+ console.error(`Could not decide: ${error instanceof Error ? error.message : String(error)}`);
93
+ process.exit(2);
94
+ });
95
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * 述語評価器 — 依存ゼロの純粋関数。
3
+ *
4
+ * **同じ facts からは常に同じ結果**を返す(evaluate_policy のルールエンジンと同じ規律)。
5
+ * ここに I/O・時刻・乱数を持ち込まないこと。判定の再現性がこのパッケージの価値であり、
6
+ * テーブルと評価意味論が同一バージョンで結束していることがその担保になっている。
7
+ */
8
+ import type { Constraint, ConstraintResult, Facts, Failure, Predicate, Subject } from './types.js';
9
+ /**
10
+ * PDF 日付文字列(ISO 32000-2 §7.9.4)→ epoch ms。文法違反・値域外は null。
11
+ *
12
+ * §7.9.4 の既定値規則(MM/DD は 01、他は 0)と UT オフセットを解釈する。
13
+ * 「D:」以降は前方のフィールドが揃っている限り任意の位置で切れてよい(R-7.9.4-12)。
14
+ */
15
+ export declare function parsePdfDate(value: unknown): number | null;
16
+ /** 述語 1 つを評価する */
17
+ export declare function evaluatePredicate(predicate: Predicate, facts: Facts): boolean;
18
+ /**
19
+ * 制約 1 件を 1 つの subject に対して評価する。
20
+ *
21
+ * `given.*`(外部事実)が未供給のときは **pass にも fail にも倒さず** `needs_external_fact` を返す。
22
+ * 「サブセットか否か」のようにファイル単体から決定できない事実があり、
23
+ * それを既定値で埋めると沈黙合格(または冤罪)になるため。
24
+ */
25
+ export declare function evaluateConstraint(constraint: Constraint, facts: Facts): ConstraintResult;
26
+ /**
27
+ * 文書横断の検査。今は「同一フォントの別サブセットが別タグを持つか」(R-9.9.2-3 後段)のみ。
28
+ * 合成 fact `doc.subsetTagsPerBaseName` を subjects から組み立てて評価する。
29
+ */
30
+ export declare function evaluateDocumentAsserts(constraint: Constraint, subjects: Subject[], facts: Facts): Failure[];
31
+ //# sourceMappingURL=evaluate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../src/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAEV,UAAU,EACV,gBAAgB,EAChB,KAAK,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACR,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CA4B1D;AAED,kBAAkB;AAClB,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAkC7E;AAoBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,gBAAgB,CAiBzF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,KAAK,GACX,OAAO,EAAE,CA8BX"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * 述語評価器 — 依存ゼロの純粋関数。
3
+ *
4
+ * **同じ facts からは常に同じ結果**を返す(evaluate_policy のルールエンジンと同じ規律)。
5
+ * ここに I/O・時刻・乱数を持ち込まないこと。判定の再現性がこのパッケージの価値であり、
6
+ * テーブルと評価意味論が同一バージョンで結束していることがその担保になっている。
7
+ */
8
+ /**
9
+ * PDF 日付文字列(ISO 32000-2 §7.9.4)→ epoch ms。文法違反・値域外は null。
10
+ *
11
+ * §7.9.4 の既定値規則(MM/DD は 01、他は 0)と UT オフセットを解釈する。
12
+ * 「D:」以降は前方のフィールドが揃っている限り任意の位置で切れてよい(R-7.9.4-12)。
13
+ */
14
+ export function parsePdfDate(value) {
15
+ if (typeof value !== 'string')
16
+ return null;
17
+ const m = /^D:(\d{4})(\d{2})?(\d{2})?(\d{2})?(\d{2})?(\d{2})?(?:([Z+-])(?:(\d{2})'?(\d{2})?'?)?)?$/.exec(value);
18
+ if (!m)
19
+ return null;
20
+ const [, year, month = '01', day = '01', hour = '00', min = '00', sec = '00', sign, oh = '00', om = '00',] = m;
21
+ const mo = Number(month);
22
+ const d = Number(day);
23
+ const h = Number(hour);
24
+ const mi = Number(min);
25
+ const s = Number(sec);
26
+ if (mo < 1 || mo > 12 || d < 1 || d > 31 || h > 23 || mi > 59 || s > 59)
27
+ return null;
28
+ const offsetMinutes = sign === '+' || sign === '-' ? (Number(oh) * 60 + Number(om)) * (sign === '-' ? -1 : 1) : 0; // R-7.9.4-17: UT 情報が無ければ GMT とみなす
29
+ return Date.UTC(Number(year), mo - 1, d, h, mi, s) - offsetMinutes * 60_000;
30
+ }
31
+ /** 述語 1 つを評価する */
32
+ export function evaluatePredicate(predicate, facts) {
33
+ const actual = facts[predicate.fact];
34
+ switch (predicate.op) {
35
+ case 'eq':
36
+ return actual === predicate.value;
37
+ case 'in':
38
+ return Array.isArray(predicate.value) && predicate.value.includes(actual);
39
+ case 'exists':
40
+ return (actual !== null && actual !== undefined) === predicate.value;
41
+ case 'matches':
42
+ return typeof actual === 'string' && new RegExp(String(predicate.value)).test(actual);
43
+ case 'superset':
44
+ return (Array.isArray(actual) &&
45
+ Array.isArray(predicate.value) &&
46
+ predicate.value.every((needle) => actual.includes(needle)));
47
+ case 'eqFact':
48
+ return actual === facts[String(predicate.value)];
49
+ case 'dateEquiv': {
50
+ // 「fully equivalent」は文字列一致ではなく**同一時点**(R-14.3.4-2/-4/-5)。
51
+ // 左は PDF 日付文字列、右は fact 参照(ISO 8601)。
52
+ const left = parsePdfDate(actual);
53
+ const right = Date.parse(String(facts[String(predicate.value)]));
54
+ return left !== null && !Number.isNaN(right) && left === right;
55
+ }
56
+ case 'allDistinct':
57
+ return Array.isArray(actual) && new Set(actual).size === actual.length;
58
+ default: {
59
+ // 未知の op はテーブルと評価器の版ずれを意味する。黙って false(= 違反)にしない
60
+ const exhaustive = predicate.op;
61
+ throw new Error(`unknown predicate op: ${String(exhaustive)}`);
62
+ }
63
+ }
64
+ }
65
+ function checkAssertion(assertion, facts, constraint) {
66
+ if (assertion.onlyWhen && !assertion.onlyWhen.every((p) => evaluatePredicate(p, facts))) {
67
+ return undefined;
68
+ }
69
+ if (evaluatePredicate(assertion, facts))
70
+ return undefined;
71
+ return {
72
+ clauses: constraint.clauses,
73
+ message: assertion.onFail,
74
+ fact: assertion.fact,
75
+ actual: facts[assertion.fact],
76
+ traceOnly: constraint.subjectNote !== undefined,
77
+ };
78
+ }
79
+ /**
80
+ * 制約 1 件を 1 つの subject に対して評価する。
81
+ *
82
+ * `given.*`(外部事実)が未供給のときは **pass にも fail にも倒さず** `needs_external_fact` を返す。
83
+ * 「サブセットか否か」のようにファイル単体から決定できない事実があり、
84
+ * それを既定値で埋めると沈黙合格(または冤罪)になるため。
85
+ */
86
+ export function evaluateConstraint(constraint, facts) {
87
+ const base = { constraint: constraint.id, target: '' };
88
+ for (const condition of constraint.when) {
89
+ if (condition.fact.startsWith('given.') && facts[condition.fact] === undefined) {
90
+ return { ...base, status: 'needs_external_fact', missing: condition.fact };
91
+ }
92
+ if (!evaluatePredicate(condition, facts)) {
93
+ return { ...base, status: 'not_applicable' };
94
+ }
95
+ }
96
+ const failures = constraint.assert
97
+ .map((assertion) => checkAssertion(assertion, facts, constraint))
98
+ .filter((f) => f !== undefined);
99
+ return failures.length > 0 ? { ...base, status: 'fail', failures } : { ...base, status: 'pass' };
100
+ }
101
+ /**
102
+ * 文書横断の検査。今は「同一フォントの別サブセットが別タグを持つか」(R-9.9.2-3 後段)のみ。
103
+ * 合成 fact `doc.subsetTagsPerBaseName` を subjects から組み立てて評価する。
104
+ */
105
+ export function evaluateDocumentAsserts(constraint, subjects, facts) {
106
+ const failures = [];
107
+ for (const assertion of constraint.documentAssert ?? []) {
108
+ if (assertion.fact !== 'doc.subsetTagsPerBaseName' || assertion.op !== 'allDistinct')
109
+ continue;
110
+ // サブセット前提の検査なので、given が無ければ黙って飛ばす(needs_external_fact は
111
+ // 制約本体の評価が返している)
112
+ for (const condition of constraint.when) {
113
+ if (condition.fact.startsWith('given.') && !evaluatePredicate(condition, facts))
114
+ return [];
115
+ }
116
+ const tagsByBaseName = new Map();
117
+ for (const subject of subjects) {
118
+ const parsed = /^([A-Z]{6})\+(.+)$/.exec(String(subject.facts['font.baseFont'] ?? ''));
119
+ if (!parsed)
120
+ continue;
121
+ const [, tag, baseName] = parsed;
122
+ tagsByBaseName.set(baseName, [...(tagsByBaseName.get(baseName) ?? []), tag]);
123
+ }
124
+ for (const [baseName, tags] of tagsByBaseName) {
125
+ if (new Set(tags).size !== tags.length) {
126
+ failures.push({
127
+ clauses: constraint.clauses,
128
+ message: `${assertion.onFail} (base=${baseName}, tags=${tags.join(',')})`,
129
+ fact: assertion.fact,
130
+ actual: tags,
131
+ traceOnly: constraint.subjectNote !== undefined,
132
+ });
133
+ }
134
+ }
135
+ }
136
+ return failures;
137
+ }
138
+ //# sourceMappingURL=evaluate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../src/evaluate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * scope `document` の fact 抽出(Info 辞書と XMP)。
3
+ *
4
+ * XMP は**外形しか見ない**(xpacket + x:xmpmeta があるか)。R-14.3.2-2 は文法が
5
+ * ISO 16684-1 に従うことまで要求するが、その規格は family のコーパス外なので
6
+ * ここでの検査は近似である — テーブル側の `notMapped` にその旨を書いてある。
7
+ */
8
+ import { type PDFDocument } from 'pdf-lib';
9
+ import type { Facts, Subject } from '../types.js';
10
+ export declare function extractDocumentFacts(doc: PDFDocument, given: Facts): Subject;
11
+ //# sourceMappingURL=document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/facts/document.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAA+B,KAAK,WAAW,EAAyB,MAAM,SAAS,CAAC;AAC/F,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAgBlD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAwD5E"}