@gate-forge/core 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 +202 -0
- package/dist/baselines/adoption.d.ts +76 -0
- package/dist/baselines/adoption.d.ts.map +1 -0
- package/dist/baselines/adoption.js +163 -0
- package/dist/baselines/adoption.js.map +1 -0
- package/dist/baselines/index.d.ts +102 -0
- package/dist/baselines/index.d.ts.map +1 -0
- package/dist/baselines/index.js +186 -0
- package/dist/baselines/index.js.map +1 -0
- package/dist/canonical-json.d.ts +51 -0
- package/dist/canonical-json.d.ts.map +1 -0
- package/dist/canonical-json.js +112 -0
- package/dist/canonical-json.js.map +1 -0
- package/dist/classifier/bind.d.ts +64 -0
- package/dist/classifier/bind.d.ts.map +1 -0
- package/dist/classifier/bind.js +188 -0
- package/dist/classifier/bind.js.map +1 -0
- package/dist/classifier/classify.d.ts +154 -0
- package/dist/classifier/classify.d.ts.map +1 -0
- package/dist/classifier/classify.js +1207 -0
- package/dist/classifier/classify.js.map +1 -0
- package/dist/classifier/glob.d.ts +48 -0
- package/dist/classifier/glob.d.ts.map +1 -0
- package/dist/classifier/glob.js +104 -0
- package/dist/classifier/glob.js.map +1 -0
- package/dist/classifier/index.d.ts +10 -0
- package/dist/classifier/index.d.ts.map +1 -0
- package/dist/classifier/index.js +21 -0
- package/dist/classifier/index.js.map +1 -0
- package/dist/classifier/schema.d.ts +150 -0
- package/dist/classifier/schema.d.ts.map +1 -0
- package/dist/classifier/schema.js +139 -0
- package/dist/classifier/schema.js.map +1 -0
- package/dist/config/index.d.ts +259 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +523 -0
- package/dist/config/index.js.map +1 -0
- package/dist/fingerprints.d.ts +56 -0
- package/dist/fingerprints.d.ts.map +1 -0
- package/dist/fingerprints.js +59 -0
- package/dist/fingerprints.js.map +1 -0
- package/dist/graph/build.d.ts +16 -0
- package/dist/graph/build.d.ts.map +1 -0
- package/dist/graph/build.js +423 -0
- package/dist/graph/build.js.map +1 -0
- package/dist/graph/index.d.ts +12 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +10 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/schema.d.ts +448 -0
- package/dist/graph/schema.d.ts.map +1 -0
- package/dist/graph/schema.js +237 -0
- package/dist/graph/schema.js.map +1 -0
- package/dist/graph/symbols.d.ts +129 -0
- package/dist/graph/symbols.d.ts.map +1 -0
- package/dist/graph/symbols.js +177 -0
- package/dist/graph/symbols.js.map +1 -0
- package/dist/graph/util.d.ts +40 -0
- package/dist/graph/util.d.ts.map +1 -0
- package/dist/graph/util.js +41 -0
- package/dist/graph/util.js.map +1 -0
- package/dist/index.d.ts +683 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +563 -0
- package/dist/index.js.map +1 -0
- package/dist/mapping/resolve.d.ts +177 -0
- package/dist/mapping/resolve.d.ts.map +1 -0
- package/dist/mapping/resolve.js +523 -0
- package/dist/mapping/resolve.js.map +1 -0
- package/dist/policy/coverage.d.ts +79 -0
- package/dist/policy/coverage.d.ts.map +1 -0
- package/dist/policy/coverage.js +119 -0
- package/dist/policy/coverage.js.map +1 -0
- package/dist/policy/evaluate.d.ts +275 -0
- package/dist/policy/evaluate.d.ts.map +1 -0
- package/dist/policy/evaluate.js +382 -0
- package/dist/policy/evaluate.js.map +1 -0
- package/dist/policy/index.d.ts +15 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +14 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/policy/trusted.d.ts +59 -0
- package/dist/policy/trusted.d.ts.map +1 -0
- package/dist/policy/trusted.js +96 -0
- package/dist/policy/trusted.js.map +1 -0
- package/dist/provenance.d.ts +170 -0
- package/dist/provenance.d.ts.map +1 -0
- package/dist/provenance.js +306 -0
- package/dist/provenance.js.map +1 -0
- package/dist/receipt/index.d.ts +74 -0
- package/dist/receipt/index.d.ts.map +1 -0
- package/dist/receipt/index.js +154 -0
- package/dist/receipt/index.js.map +1 -0
- package/dist/report/index.d.ts +100 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +355 -0
- package/dist/report/index.js.map +1 -0
- package/dist/schemas/adoption.d.ts +40 -0
- package/dist/schemas/adoption.d.ts.map +1 -0
- package/dist/schemas/adoption.js +87 -0
- package/dist/schemas/adoption.js.map +1 -0
- package/dist/schemas/baseline.d.ts +19 -0
- package/dist/schemas/baseline.d.ts.map +1 -0
- package/dist/schemas/baseline.js +45 -0
- package/dist/schemas/baseline.js.map +1 -0
- package/dist/schemas/claim.d.ts +32 -0
- package/dist/schemas/claim.d.ts.map +1 -0
- package/dist/schemas/claim.js +34 -0
- package/dist/schemas/claim.js.map +1 -0
- package/dist/schemas/classification-policy.d.ts +84 -0
- package/dist/schemas/classification-policy.d.ts.map +1 -0
- package/dist/schemas/classification-policy.js +130 -0
- package/dist/schemas/classification-policy.js.map +1 -0
- package/dist/schemas/classification-signal.d.ts +125 -0
- package/dist/schemas/classification-signal.d.ts.map +1 -0
- package/dist/schemas/classification-signal.js +126 -0
- package/dist/schemas/classification-signal.js.map +1 -0
- package/dist/schemas/classification.d.ts +120 -0
- package/dist/schemas/classification.d.ts.map +1 -0
- package/dist/schemas/classification.js +154 -0
- package/dist/schemas/classification.js.map +1 -0
- package/dist/schemas/common.d.ts +73 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +60 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/schemas/coverage-policy.d.ts +89 -0
- package/dist/schemas/coverage-policy.d.ts.map +1 -0
- package/dist/schemas/coverage-policy.js +81 -0
- package/dist/schemas/coverage-policy.js.map +1 -0
- package/dist/schemas/evidence.d.ts +65 -0
- package/dist/schemas/evidence.d.ts.map +1 -0
- package/dist/schemas/evidence.js +64 -0
- package/dist/schemas/evidence.js.map +1 -0
- package/dist/schemas/execution-result.d.ts +214 -0
- package/dist/schemas/execution-result.d.ts.map +1 -0
- package/dist/schemas/execution-result.js +240 -0
- package/dist/schemas/execution-result.js.map +1 -0
- package/dist/schemas/gate-receipt.d.ts +86 -0
- package/dist/schemas/gate-receipt.d.ts.map +1 -0
- package/dist/schemas/gate-receipt.js +193 -0
- package/dist/schemas/gate-receipt.js.map +1 -0
- package/dist/schemas/index.d.ts +22 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +22 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/obligation.d.ts +37 -0
- package/dist/schemas/obligation.d.ts.map +1 -0
- package/dist/schemas/obligation.js +46 -0
- package/dist/schemas/obligation.js.map +1 -0
- package/dist/schemas/plugin.d.ts +19 -0
- package/dist/schemas/plugin.d.ts.map +1 -0
- package/dist/schemas/plugin.js +20 -0
- package/dist/schemas/plugin.js.map +1 -0
- package/dist/schemas/policy.d.ts +73 -0
- package/dist/schemas/policy.d.ts.map +1 -0
- package/dist/schemas/policy.js +46 -0
- package/dist/schemas/policy.js.map +1 -0
- package/dist/schemas/resource.d.ts +26 -0
- package/dist/schemas/resource.d.ts.map +1 -0
- package/dist/schemas/resource.js +29 -0
- package/dist/schemas/resource.js.map +1 -0
- package/dist/schemas/run-manifest.d.ts +72 -0
- package/dist/schemas/run-manifest.d.ts.map +1 -0
- package/dist/schemas/run-manifest.js +125 -0
- package/dist/schemas/run-manifest.js.map +1 -0
- package/dist/schemas/runner-adapter.d.ts +169 -0
- package/dist/schemas/runner-adapter.d.ts.map +1 -0
- package/dist/schemas/runner-adapter.js +2 -0
- package/dist/schemas/runner-adapter.js.map +1 -0
- package/dist/schemas/test-catalog.d.ts +472 -0
- package/dist/schemas/test-catalog.d.ts.map +1 -0
- package/dist/schemas/test-catalog.js +311 -0
- package/dist/schemas/test-catalog.js.map +1 -0
- package/dist/schemas/test-map.d.ts +99 -0
- package/dist/schemas/test-map.d.ts.map +1 -0
- package/dist/schemas/test-map.js +103 -0
- package/dist/schemas/test-map.js.map +1 -0
- package/dist/schemas/verdict.d.ts +73 -0
- package/dist/schemas/verdict.d.ts.map +1 -0
- package/dist/schemas/verdict.js +92 -0
- package/dist/schemas/verdict.js.map +1 -0
- package/dist/schemas/waiver.d.ts +36 -0
- package/dist/schemas/waiver.d.ts.map +1 -0
- package/dist/schemas/waiver.js +42 -0
- package/dist/schemas/waiver.js.map +1 -0
- package/dist/supervision/index.d.ts +170 -0
- package/dist/supervision/index.d.ts.map +1 -0
- package/dist/supervision/index.js +354 -0
- package/dist/supervision/index.js.map +1 -0
- package/dist/testing/clock.d.ts +50 -0
- package/dist/testing/clock.d.ts.map +1 -0
- package/dist/testing/clock.js +75 -0
- package/dist/testing/clock.js.map +1 -0
- package/dist/testing/env.d.ts +66 -0
- package/dist/testing/env.d.ts.map +1 -0
- package/dist/testing/env.js +106 -0
- package/dist/testing/env.js.map +1 -0
- package/dist/testing/gate-runner.d.ts +141 -0
- package/dist/testing/gate-runner.d.ts.map +1 -0
- package/dist/testing/gate-runner.js +173 -0
- package/dist/testing/gate-runner.js.map +1 -0
- package/dist/testing/gf19.d.ts +106 -0
- package/dist/testing/gf19.d.ts.map +1 -0
- package/dist/testing/gf19.js +282 -0
- package/dist/testing/gf19.js.map +1 -0
- package/dist/testing/index.d.ts +20 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +14 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/red-probe.d.ts +138 -0
- package/dist/testing/red-probe.d.ts.map +1 -0
- package/dist/testing/red-probe.js +251 -0
- package/dist/testing/red-probe.js.map +1 -0
- package/dist/testing/temp-repo.d.ts +126 -0
- package/dist/testing/temp-repo.d.ts.map +1 -0
- package/dist/testing/temp-repo.js +214 -0
- package/dist/testing/temp-repo.js.map +1 -0
- package/dist/verdict/cause.d.ts +99 -0
- package/dist/verdict/cause.d.ts.map +1 -0
- package/dist/verdict/cause.js +206 -0
- package/dist/verdict/cause.js.map +1 -0
- package/dist/verdict/evaluate.d.ts +135 -0
- package/dist/verdict/evaluate.d.ts.map +1 -0
- package/dist/verdict/evaluate.js +1513 -0
- package/dist/verdict/evaluate.js.map +1 -0
- package/dist/verdict/index.d.ts +21 -0
- package/dist/verdict/index.d.ts.map +1 -0
- package/dist/verdict/index.js +20 -0
- package/dist/verdict/index.js.map +1 -0
- package/dist/verdict/pack-verifiers.d.ts +97 -0
- package/dist/verdict/pack-verifiers.d.ts.map +1 -0
- package/dist/verdict/pack-verifiers.js +763 -0
- package/dist/verdict/pack-verifiers.js.map +1 -0
- package/dist/verdict/registry.d.ts +180 -0
- package/dist/verdict/registry.d.ts.map +1 -0
- package/dist/verdict/registry.js +67 -0
- package/dist/verdict/registry.js.map +1 -0
- package/dist/waivers/index.d.ts +103 -0
- package/dist/waivers/index.d.ts.map +1 -0
- package/dist/waivers/index.js +192 -0
- package/dist/waivers/index.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Baselines (pin #3, invariant 4): `.gateforge/baselines/obligations.json`
|
|
3
|
+
* — `{schemaVersion: 1, fingerprints: string[]}` storing forgiven
|
|
4
|
+
* obligation fingerprints (pin #2). Baselines may only ever SHRINK to a
|
|
5
|
+
* strict subset: `[A, B] → [A, NEW]` is rejected (GF-07), `[A, B] → [A]`
|
|
6
|
+
* passes (GF-08). Loading and writing are synchronous, matching
|
|
7
|
+
* `loadConfig`'s convention.
|
|
8
|
+
*/
|
|
9
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { dirname } from 'node:path';
|
|
11
|
+
import { compareStrings } from '../graph/util.js';
|
|
12
|
+
import { BaselineSchema } from '../schemas/baseline.js';
|
|
13
|
+
/**
|
|
14
|
+
* Error raised for any fail-closed baseline problem: missing file,
|
|
15
|
+
* unparsable JSON, schema violation, or a non-strict-subset update
|
|
16
|
+
* (GF-07's count-preserving debt laundering).
|
|
17
|
+
*/
|
|
18
|
+
export class GateforgeBaselineError extends Error {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = 'GateforgeBaselineError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Loads and validates a baseline document. Fail-closed: a missing,
|
|
26
|
+
* unparsable, or schema-violating file throws — callers decide whether
|
|
27
|
+
* that means "no baseline yet" for their flow.
|
|
28
|
+
*
|
|
29
|
+
* Args:
|
|
30
|
+
* path: baseline file path (default `.gateforge/baselines/obligations.json`).
|
|
31
|
+
*
|
|
32
|
+
* Returns:
|
|
33
|
+
* Baseline: the validated document (sorted, duplicate-free fingerprints).
|
|
34
|
+
*
|
|
35
|
+
* Throws:
|
|
36
|
+
* GateforgeBaselineError: on any load or validation failure.
|
|
37
|
+
*/
|
|
38
|
+
export function loadBaseline(path) {
|
|
39
|
+
let document;
|
|
40
|
+
try {
|
|
41
|
+
document = JSON.parse(readFileSync(path, 'utf8'));
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw new GateforgeBaselineError(`baseline '${path}' could not be loaded: ${error instanceof Error ? error.message : String(error)}`);
|
|
45
|
+
}
|
|
46
|
+
const result = BaselineSchema.safeParse(document);
|
|
47
|
+
if (!result.success) {
|
|
48
|
+
const issues = result.error.issues
|
|
49
|
+
.map((issue) => `${issue.path.join('.') || '<baseline>'}: ${issue.message}`)
|
|
50
|
+
.join('; ');
|
|
51
|
+
throw new GateforgeBaselineError(`baseline '${path}' failed validation: ${issues}`);
|
|
52
|
+
}
|
|
53
|
+
return result.data;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Whether a baseline update is a strict subset (invariant 4): every
|
|
57
|
+
* fingerprint in `next` exists in `current` AND at least one fingerprint
|
|
58
|
+
* is removed. `[A, B] → [A, B]` is not an update (nothing was resolved)
|
|
59
|
+
* and `[A, B] → [A, NEW]` fails (GF-07); `[A, B] → [A]` passes (GF-08).
|
|
60
|
+
*
|
|
61
|
+
* Args:
|
|
62
|
+
* current: the baseline on disk.
|
|
63
|
+
* next: the proposed replacement.
|
|
64
|
+
*
|
|
65
|
+
* Returns:
|
|
66
|
+
* boolean: true only for a non-empty proper subset.
|
|
67
|
+
*/
|
|
68
|
+
export function canUpdate(current, next) {
|
|
69
|
+
if (next.fingerprints.length >= current.fingerprints.length)
|
|
70
|
+
return false;
|
|
71
|
+
const known = {};
|
|
72
|
+
for (const fingerprint of current.fingerprints)
|
|
73
|
+
known[fingerprint] = true;
|
|
74
|
+
return next.fingerprints.every((fingerprint) => fingerprint in known);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* THE ONE SANCTIONED BULK-ADD (phase 8 workstream C, `gateforge adopt`):
|
|
78
|
+
* builds the adoption baseline from every currently-unresolved
|
|
79
|
+
* fingerprint, WITHOUT the strict-subset check. This is the controlled
|
|
80
|
+
* escape GF-07/08's anti-laundering invariant demands: adoption is a
|
|
81
|
+
* dated, count-annotated, loudly-printed event recorded in
|
|
82
|
+
* `adoption.json` (see baselines/adoption.ts), and it happens at most
|
|
83
|
+
* once per repo — the adopt command refuses a second bulk-add and sends
|
|
84
|
+
* subsequent debt to `updateBaseline` (shrink-only) or the gate itself.
|
|
85
|
+
* The companion record gates enforcement: `check` honors a baseline only
|
|
86
|
+
* when its adoption record exists, so this function's output can never
|
|
87
|
+
* forgive silently. Input order is irrelevant; duplicates are collapsed
|
|
88
|
+
* (the red set is collected from disjoint sources — verdicts and
|
|
89
|
+
* blocking entries — so duplicates are expected to be absent, not an
|
|
90
|
+
* error like in `updateBaseline`).
|
|
91
|
+
*
|
|
92
|
+
* Args:
|
|
93
|
+
* fingerprints: the unresolved fingerprints captured at adoption time.
|
|
94
|
+
*
|
|
95
|
+
* Returns:
|
|
96
|
+
* Baseline: the validated initial baseline document (sorted, unique).
|
|
97
|
+
*/
|
|
98
|
+
export function adoptBaseline(fingerprints) {
|
|
99
|
+
const seen = {};
|
|
100
|
+
const unique = [];
|
|
101
|
+
for (const fingerprint of fingerprints) {
|
|
102
|
+
if (fingerprint in seen)
|
|
103
|
+
continue;
|
|
104
|
+
seen[fingerprint] = true;
|
|
105
|
+
unique.push(fingerprint);
|
|
106
|
+
}
|
|
107
|
+
unique.sort(compareStrings);
|
|
108
|
+
return BaselineSchema.parse({ schemaVersion: 1, fingerprints: unique });
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Builds the next baseline from raw fingerprints, enforcing the strict-
|
|
112
|
+
* subset rule (invariant 4) against `current`. Input order is irrelevant:
|
|
113
|
+
* the result is sorted; duplicates in the input are an error.
|
|
114
|
+
*
|
|
115
|
+
* Args:
|
|
116
|
+
* current: the baseline on disk.
|
|
117
|
+
* fingerprints: the resolved fingerprints to keep.
|
|
118
|
+
*
|
|
119
|
+
* Returns:
|
|
120
|
+
* Baseline: the validated next document.
|
|
121
|
+
*
|
|
122
|
+
* Throws:
|
|
123
|
+
* GateforgeBaselineError: on duplicates or a non-strict-subset update
|
|
124
|
+
* (naming the added fingerprints — GF-07's laundering attempt).
|
|
125
|
+
*/
|
|
126
|
+
export function updateBaseline(current, fingerprints) {
|
|
127
|
+
const seen = {};
|
|
128
|
+
const unique = [];
|
|
129
|
+
for (const fingerprint of fingerprints) {
|
|
130
|
+
if (fingerprint in seen)
|
|
131
|
+
continue;
|
|
132
|
+
seen[fingerprint] = true;
|
|
133
|
+
unique.push(fingerprint);
|
|
134
|
+
}
|
|
135
|
+
if (unique.length !== fingerprints.length) {
|
|
136
|
+
throw new GateforgeBaselineError('baseline update input contains duplicate fingerprints');
|
|
137
|
+
}
|
|
138
|
+
unique.sort(compareStrings);
|
|
139
|
+
const next = BaselineSchema.parse({ schemaVersion: 1, fingerprints: unique });
|
|
140
|
+
if (!canUpdate(current, next)) {
|
|
141
|
+
const known = {};
|
|
142
|
+
for (const fingerprint of current.fingerprints)
|
|
143
|
+
known[fingerprint] = true;
|
|
144
|
+
const added = unique.filter((fingerprint) => !(fingerprint in known));
|
|
145
|
+
throw new GateforgeBaselineError(`baseline update rejected: not a strict subset of the current baseline ` +
|
|
146
|
+
`(invariant 4) — added ${added.length} new fingerprint(s): ` +
|
|
147
|
+
`${added.join(', ') || '<none>'}; new (never-adopted) obligations do not belong in the ` +
|
|
148
|
+
'baseline — prove them with witnessed test evidence (docs/guides/new-table-playbook.md) ' +
|
|
149
|
+
'or waive them (`gateforge waive`)');
|
|
150
|
+
}
|
|
151
|
+
return next;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Serializes a baseline for on-disk storage: sorted 2-space JSON with a
|
|
155
|
+
* trailing newline (reviewable in diffs; canonical hashing is a separate
|
|
156
|
+
* pin-#1 concern and does not apply to this file's formatting).
|
|
157
|
+
*
|
|
158
|
+
* Args:
|
|
159
|
+
* baseline: the document to serialize.
|
|
160
|
+
*
|
|
161
|
+
* Returns:
|
|
162
|
+
* string: the file content.
|
|
163
|
+
*/
|
|
164
|
+
export function serializeBaseline(baseline) {
|
|
165
|
+
return `${JSON.stringify(baseline, null, 2)}\n`;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Writes a baseline to disk, creating parent directories as needed.
|
|
169
|
+
*
|
|
170
|
+
* Args:
|
|
171
|
+
* path: destination file path.
|
|
172
|
+
* baseline: the document to write.
|
|
173
|
+
*
|
|
174
|
+
* Throws:
|
|
175
|
+
* GateforgeBaselineError: when the file cannot be written.
|
|
176
|
+
*/
|
|
177
|
+
export function writeBaseline(path, baseline) {
|
|
178
|
+
try {
|
|
179
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
180
|
+
writeFileSync(path, serializeBaseline(baseline), 'utf8');
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
throw new GateforgeBaselineError(`baseline '${path}' could not be written: ${error instanceof Error ? error.message : String(error)}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/baselines/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** Any JSON-representable value. */
|
|
2
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
3
|
+
[key: string]: JsonValue;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Type predicate narrowing an unknown value to {@link JsonValue}.
|
|
7
|
+
* Accepts plain objects and arrays only — class instances (Date, Map,
|
|
8
|
+
* custom types) are rejected even when property-less.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isJsonValue(value: unknown): value is JsonValue;
|
|
11
|
+
/**
|
|
12
|
+
* Serializes a value to its GF-canonical-JSON string form (pin #1).
|
|
13
|
+
*
|
|
14
|
+
* Object keys are sorted recursively (by UTF-16 code units, matching the
|
|
15
|
+
* JS default string comparison). No whitespace is emitted. Integers are
|
|
16
|
+
* serialized plain; non-integer finite numbers fall back to the shortest
|
|
17
|
+
* round-trip decimal form (out of v1 scope, but deterministic). NaN and
|
|
18
|
+
* Infinity throw — they have no canonical representation.
|
|
19
|
+
*
|
|
20
|
+
* Array order is preserved: arrays are ordered values, never sorted.
|
|
21
|
+
*
|
|
22
|
+
* Args:
|
|
23
|
+
* value: JSON-representable value to canonicalize.
|
|
24
|
+
*
|
|
25
|
+
* Returns:
|
|
26
|
+
* string: GF-canonical-JSON text, ready to hash or compare byte-wise.
|
|
27
|
+
*/
|
|
28
|
+
export declare function canonicalJson(value: JsonValue): string;
|
|
29
|
+
/**
|
|
30
|
+
* Computes the lowercase hex sha256 digest of a string or byte buffer.
|
|
31
|
+
*
|
|
32
|
+
* Args:
|
|
33
|
+
* input: UTF-8 text (e.g. a canonical JSON string) or raw bytes.
|
|
34
|
+
*
|
|
35
|
+
* Returns:
|
|
36
|
+
* string: 64-char lowercase hex digest.
|
|
37
|
+
*/
|
|
38
|
+
export declare function sha256Hex(input: string | Uint8Array): string;
|
|
39
|
+
/**
|
|
40
|
+
* Hashes a value as GF-canonical-JSON: `sha256(canonicalJson(value))` (pin #1).
|
|
41
|
+
* This is the single primitive behind fingerprints, GPP/3 digests, and
|
|
42
|
+
* witness record ids.
|
|
43
|
+
*
|
|
44
|
+
* Args:
|
|
45
|
+
* value: JSON-representable value to hash.
|
|
46
|
+
*
|
|
47
|
+
* Returns:
|
|
48
|
+
* string: 64-char lowercase hex digest of the canonical form.
|
|
49
|
+
*/
|
|
50
|
+
export declare function sha256Canonical(value: JsonValue): string;
|
|
51
|
+
//# sourceMappingURL=canonical-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical-json.d.ts","sourceRoot":"","sources":["../src/canonical-json.ts"],"names":[],"mappings":"AAaA,oCAAoC;AACpC,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,EAAE,GACX;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEjC;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAsB9D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CA2BtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAE5D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAExD"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GF-canonical-JSON and sha256 helpers (Interface pin #1).
|
|
3
|
+
*
|
|
4
|
+
* GF-canonical-JSON: UTF-8 text, object keys recursively sorted, no
|
|
5
|
+
* whitespace between tokens, integers serialized plain (`1`, not `1.0`).
|
|
6
|
+
* ALL gateforge hashes — fingerprints, GPP digests, witness record ids —
|
|
7
|
+
* are `sha256` hex digests over the GF-canonical-JSON of the named object.
|
|
8
|
+
* This is deliberately NOT RFC 8785: v1 payloads contain only strings,
|
|
9
|
+
* integers, booleans, null, arrays, and objects (no floats), so the
|
|
10
|
+
* canonical form is fully defined by key sorting plus JSON escaping.
|
|
11
|
+
*/
|
|
12
|
+
import { createHash } from 'node:crypto';
|
|
13
|
+
/**
|
|
14
|
+
* Type predicate narrowing an unknown value to {@link JsonValue}.
|
|
15
|
+
* Accepts plain objects and arrays only — class instances (Date, Map,
|
|
16
|
+
* custom types) are rejected even when property-less.
|
|
17
|
+
*/
|
|
18
|
+
export function isJsonValue(value) {
|
|
19
|
+
if (value === null ||
|
|
20
|
+
typeof value === 'string' ||
|
|
21
|
+
typeof value === 'boolean') {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
if (typeof value === 'number') {
|
|
25
|
+
return Number.isFinite(value);
|
|
26
|
+
}
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
return value.every(isJsonValue);
|
|
29
|
+
}
|
|
30
|
+
if (typeof value === 'object') {
|
|
31
|
+
const proto = Object.getPrototypeOf(value);
|
|
32
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return Object.values(value).every(isJsonValue);
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Serializes a value to its GF-canonical-JSON string form (pin #1).
|
|
41
|
+
*
|
|
42
|
+
* Object keys are sorted recursively (by UTF-16 code units, matching the
|
|
43
|
+
* JS default string comparison). No whitespace is emitted. Integers are
|
|
44
|
+
* serialized plain; non-integer finite numbers fall back to the shortest
|
|
45
|
+
* round-trip decimal form (out of v1 scope, but deterministic). NaN and
|
|
46
|
+
* Infinity throw — they have no canonical representation.
|
|
47
|
+
*
|
|
48
|
+
* Array order is preserved: arrays are ordered values, never sorted.
|
|
49
|
+
*
|
|
50
|
+
* Args:
|
|
51
|
+
* value: JSON-representable value to canonicalize.
|
|
52
|
+
*
|
|
53
|
+
* Returns:
|
|
54
|
+
* string: GF-canonical-JSON text, ready to hash or compare byte-wise.
|
|
55
|
+
*/
|
|
56
|
+
export function canonicalJson(value) {
|
|
57
|
+
if (value === null)
|
|
58
|
+
return 'null';
|
|
59
|
+
if (typeof value === 'string')
|
|
60
|
+
return JSON.stringify(value);
|
|
61
|
+
if (typeof value === 'boolean')
|
|
62
|
+
return value ? 'true' : 'false';
|
|
63
|
+
if (typeof value === 'number') {
|
|
64
|
+
if (!Number.isFinite(value)) {
|
|
65
|
+
throw new TypeError(`canonicalJson: ${String(value)} has no canonical JSON representation`);
|
|
66
|
+
}
|
|
67
|
+
return Number.isInteger(value) ? String(value) : JSON.stringify(value);
|
|
68
|
+
}
|
|
69
|
+
if (Array.isArray(value)) {
|
|
70
|
+
return `[${value.map(canonicalJson).join(',')}]`;
|
|
71
|
+
}
|
|
72
|
+
const keys = Object.keys(value).sort();
|
|
73
|
+
const members = [];
|
|
74
|
+
for (const key of keys) {
|
|
75
|
+
const member = value[key];
|
|
76
|
+
// An explicitly-undefined member is ABSENT for hashing purposes —
|
|
77
|
+
// identical to the key not being present (JSON.stringify semantics).
|
|
78
|
+
// Without this, zod-parsed artifacts carrying optional keys as
|
|
79
|
+
// explicit undefined values would crash fingerprinting.
|
|
80
|
+
if (member === undefined)
|
|
81
|
+
continue;
|
|
82
|
+
members.push(`${JSON.stringify(key)}:${canonicalJson(member)}`);
|
|
83
|
+
}
|
|
84
|
+
return `{${members.join(',')}}`;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Computes the lowercase hex sha256 digest of a string or byte buffer.
|
|
88
|
+
*
|
|
89
|
+
* Args:
|
|
90
|
+
* input: UTF-8 text (e.g. a canonical JSON string) or raw bytes.
|
|
91
|
+
*
|
|
92
|
+
* Returns:
|
|
93
|
+
* string: 64-char lowercase hex digest.
|
|
94
|
+
*/
|
|
95
|
+
export function sha256Hex(input) {
|
|
96
|
+
return createHash('sha256').update(input).digest('hex');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Hashes a value as GF-canonical-JSON: `sha256(canonicalJson(value))` (pin #1).
|
|
100
|
+
* This is the single primitive behind fingerprints, GPP/3 digests, and
|
|
101
|
+
* witness record ids.
|
|
102
|
+
*
|
|
103
|
+
* Args:
|
|
104
|
+
* value: JSON-representable value to hash.
|
|
105
|
+
*
|
|
106
|
+
* Returns:
|
|
107
|
+
* string: 64-char lowercase hex digest of the canonical form.
|
|
108
|
+
*/
|
|
109
|
+
export function sha256Canonical(value) {
|
|
110
|
+
return sha256Hex(canonicalJson(value));
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=canonical-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical-json.js","sourceRoot":"","sources":["../src/canonical-json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { GraphResource, ResourceGraph } from '../graph/schema.js';
|
|
2
|
+
import type { BlockingEntry } from '../policy/index.js';
|
|
3
|
+
import type { ClassificationSignal } from '../schemas/classification-signal.js';
|
|
4
|
+
import type { ClassificationPolicy } from '../schemas/classification-policy.js';
|
|
5
|
+
import { type ClassificationResult, type ClassifierResourceRef } from './classify.js';
|
|
6
|
+
/** Everything one classification pass over a graph needs. */
|
|
7
|
+
export interface RunClassificationInput {
|
|
8
|
+
/** The built resource graph (pre-binding). */
|
|
9
|
+
graph: ResourceGraph;
|
|
10
|
+
/** Every detector contribution's `classificationSignals`, config order. */
|
|
11
|
+
signals: readonly ClassificationSignal[];
|
|
12
|
+
/**
|
|
13
|
+
* HOST-ISSUED authority signals (declarations / closed-world proofs
|
|
14
|
+
* minted by the engine, e.g. from configured source-declaration
|
|
15
|
+
* markers). Never forwarded plugin output.
|
|
16
|
+
*/
|
|
17
|
+
authority?: readonly ClassificationSignal[];
|
|
18
|
+
/** The validated classification policy. */
|
|
19
|
+
policy: ClassificationPolicy;
|
|
20
|
+
/** Reviewed adapter names available for binding. */
|
|
21
|
+
adapters: readonly string[];
|
|
22
|
+
scan?: {
|
|
23
|
+
requestedPaths: string[];
|
|
24
|
+
scannedPaths: string[];
|
|
25
|
+
/** Per-detector coverage reports (judged against policy.coverage). */
|
|
26
|
+
coverage?: Array<{
|
|
27
|
+
detector: string;
|
|
28
|
+
scannedPaths: string[];
|
|
29
|
+
}>;
|
|
30
|
+
configuredDetectors: number;
|
|
31
|
+
successfulDetectors: number;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** The result of one classification pass over a graph. */
|
|
35
|
+
export interface GraphClassification {
|
|
36
|
+
/** The graph with decisions bound (deterministically re-sorted). */
|
|
37
|
+
graph: ResourceGraph;
|
|
38
|
+
/** The raw classifier result (decisions, stale/invalid signals). */
|
|
39
|
+
classification: ClassificationResult;
|
|
40
|
+
/** Classifier blocks projected as policy-engine blocking entries. */
|
|
41
|
+
blocking: BlockingEntry[];
|
|
42
|
+
}
|
|
43
|
+
/** Projects one graph resource into the classifier's resource reference. */
|
|
44
|
+
export declare function resourceRef(resource: GraphResource): ClassifierResourceRef;
|
|
45
|
+
/**
|
|
46
|
+
* Runs the deterministic classifier over the graph and rebinds its
|
|
47
|
+
* decisions. See the module doc for the contract.
|
|
48
|
+
*
|
|
49
|
+
* Args:
|
|
50
|
+
* input: graph, detector signals, classification policy, adapters.
|
|
51
|
+
*
|
|
52
|
+
* Returns:
|
|
53
|
+
* GraphClassification: bound graph, raw result, blocking entries.
|
|
54
|
+
*/
|
|
55
|
+
export declare function runClassification(input: RunClassificationInput): GraphClassification;
|
|
56
|
+
/**
|
|
57
|
+
* Projects classifier blocks into policy-engine blocking entries:
|
|
58
|
+
* per-decision blocks (contradictions, incomplete proofs, unresolved
|
|
59
|
+
* delete semantics, missing adapters) plus document-level stale targets
|
|
60
|
+
* and invalid signals. Every entry names its typed code so an AI can
|
|
61
|
+
* resolve it in code — never by obtaining human approval.
|
|
62
|
+
*/
|
|
63
|
+
export declare function classifierBlocking(result: ClassificationResult, graph: ResourceGraph): BlockingEntry[];
|
|
64
|
+
//# sourceMappingURL=bind.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../../src/classifier/bind.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAChF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAChF,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAC;AAEvB,6DAA6D;AAC7D,MAAM,WAAW,sBAAsB;IACrC,8CAA8C;IAC9C,KAAK,EAAE,aAAa,CAAC;IACrB,2EAA2E;IAC3E,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACzC;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC5C,2CAA2C;IAC3C,MAAM,EAAE,oBAAoB,CAAC;IAC7B,oDAAoD;IACpD,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,IAAI,CAAC,EAAE;QACL,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,sEAAsE;QACtE,QAAQ,CAAC,EAAE,KAAK,CAAC;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,YAAY,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC,CAAC;QAC/D,mBAAmB,EAAE,MAAM,CAAC;QAC5B,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC;CACH;AACD,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,KAAK,EAAE,aAAa,CAAC;IACrB,oEAAoE;IACpE,cAAc,EAAE,oBAAoB,CAAC;IACrC,qEAAqE;IACrE,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,aAAa,GAAG,qBAAqB,CAU1E;AAwED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,mBAAmB,CAgDpF;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,oBAAoB,EAC5B,KAAK,EAAE,aAAa,GACnB,aAAa,EAAE,CA8CjB"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { compareLocations, compareStrings } from '../graph/util.js';
|
|
2
|
+
import { classifyResources, } from './classify.js';
|
|
3
|
+
/** Projects one graph resource into the classifier's resource reference. */
|
|
4
|
+
export function resourceRef(resource) {
|
|
5
|
+
return {
|
|
6
|
+
name: resource.name,
|
|
7
|
+
id: resource.id,
|
|
8
|
+
kind: resource.kind,
|
|
9
|
+
source: resource.source,
|
|
10
|
+
location: resource.location,
|
|
11
|
+
detector: resource.detector,
|
|
12
|
+
attributes: resource.attributes,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The binding key of a resource or decision: the exact (name, kind,
|
|
17
|
+
* source, location) tuple — unique per resource declaration and stable
|
|
18
|
+
* across the sort the classifier applies to its decisions.
|
|
19
|
+
*/
|
|
20
|
+
function bindingKey(part) {
|
|
21
|
+
return (`${part.name}\u0000${part.kind}\u0000${part.source}\u0000` +
|
|
22
|
+
`${part.location.file}\u0000${part.location.line}\u0000${part.location.col}`);
|
|
23
|
+
}
|
|
24
|
+
/** Sorts bound resources exactly like the graph builder does. */
|
|
25
|
+
function sortResources(resources) {
|
|
26
|
+
return [...resources].sort((a, b) => {
|
|
27
|
+
if (a.id !== null && b.id !== null) {
|
|
28
|
+
const byId = compareStrings(a.id, b.id);
|
|
29
|
+
if (byId !== 0)
|
|
30
|
+
return byId;
|
|
31
|
+
}
|
|
32
|
+
if (a.id !== null)
|
|
33
|
+
return -1;
|
|
34
|
+
if (b.id !== null)
|
|
35
|
+
return 1;
|
|
36
|
+
return (compareStrings(a.name, b.name) ||
|
|
37
|
+
compareStrings(a.source, b.source) ||
|
|
38
|
+
compareLocations(a.location, b.location));
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/** Binds one decision's classification onto one graph resource. */
|
|
42
|
+
function bindDecision(resource, decision) {
|
|
43
|
+
if (decision === undefined || decision.classification === null)
|
|
44
|
+
return resource;
|
|
45
|
+
const bound = decision.classification;
|
|
46
|
+
const { exposure, plane, primaryKey, evidenceAdapter, evidenceLane } = bound;
|
|
47
|
+
return {
|
|
48
|
+
...resource,
|
|
49
|
+
id: `${plane}.${resource.name}`,
|
|
50
|
+
plane,
|
|
51
|
+
exposure,
|
|
52
|
+
classification: {
|
|
53
|
+
exposure,
|
|
54
|
+
plane,
|
|
55
|
+
lifecycle: bound.lifecycle,
|
|
56
|
+
primaryKey,
|
|
57
|
+
// The claims lane rides with the classification: without it a
|
|
58
|
+
// user-facing endpoint bound here would fail ClassificationSchema
|
|
59
|
+
// (user-facing without adapter) at graph validation.
|
|
60
|
+
...(evidenceLane !== undefined ? { evidenceLane } : {}),
|
|
61
|
+
...(evidenceAdapter !== undefined ? { evidenceAdapter } : {}),
|
|
62
|
+
},
|
|
63
|
+
classificationTrace: {
|
|
64
|
+
rules: [...bound.rules],
|
|
65
|
+
defaultsApplied: [...bound.defaultsApplied],
|
|
66
|
+
contributingSignalIds: [...bound.contributingSignalIds],
|
|
67
|
+
contributingDetectors: [...bound.contributingDetectors],
|
|
68
|
+
contradictions: bound.contradictions.map((entry) => ({ ...entry })),
|
|
69
|
+
unresolvedDimensions: [...bound.unresolvedDimensions],
|
|
70
|
+
decisionFingerprint: bound.decisionFingerprint,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Runs the deterministic classifier over the graph and rebinds its
|
|
76
|
+
* decisions. See the module doc for the contract.
|
|
77
|
+
*
|
|
78
|
+
* Args:
|
|
79
|
+
* input: graph, detector signals, classification policy, adapters.
|
|
80
|
+
*
|
|
81
|
+
* Returns:
|
|
82
|
+
* GraphClassification: bound graph, raw result, blocking entries.
|
|
83
|
+
*/
|
|
84
|
+
export function runClassification(input) {
|
|
85
|
+
const refs = input.graph.resources.map(resourceRef);
|
|
86
|
+
const result = classifyResources({
|
|
87
|
+
resources: refs,
|
|
88
|
+
signals: [...input.signals],
|
|
89
|
+
authority: input.authority ? [...input.authority] : [],
|
|
90
|
+
policy: input.policy,
|
|
91
|
+
adapters: input.adapters,
|
|
92
|
+
scan: {
|
|
93
|
+
requestedPaths: input.scan?.requestedPaths ?? [],
|
|
94
|
+
scannedPaths: input.scan?.scannedPaths ?? [],
|
|
95
|
+
coverage: input.scan?.coverage,
|
|
96
|
+
configuredDetectors: input.scan?.configuredDetectors ?? 1,
|
|
97
|
+
successfulDetectors: input.scan?.successfulDetectors ?? 1,
|
|
98
|
+
findings: input.graph.findings.map((finding) => ({
|
|
99
|
+
code: finding.code,
|
|
100
|
+
locations: finding.locations,
|
|
101
|
+
})),
|
|
102
|
+
unresolved: input.graph.unresolved.map((entry) => ({ location: entry.reason.location })),
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
const byKey = new Map();
|
|
106
|
+
for (const decision of result.decisions)
|
|
107
|
+
byKey.set(bindingKey(decision), decision);
|
|
108
|
+
const resources = input.graph.resources.map((resource) => bindDecision(resource, byKey.get(bindingKey(resource))));
|
|
109
|
+
const postBindingFindings = [...input.graph.findings];
|
|
110
|
+
const byId = new Map();
|
|
111
|
+
for (const resource of resources) {
|
|
112
|
+
if (resource.id === null)
|
|
113
|
+
continue;
|
|
114
|
+
const group = byId.get(resource.id) ?? [];
|
|
115
|
+
group.push(resource);
|
|
116
|
+
byId.set(resource.id, group);
|
|
117
|
+
}
|
|
118
|
+
for (const [id, group] of byId) {
|
|
119
|
+
if (group.length < 2)
|
|
120
|
+
continue;
|
|
121
|
+
postBindingFindings.push({
|
|
122
|
+
code: 'DUPLICATE_BOUND_RESOURCE_ID',
|
|
123
|
+
detail: `resources ${group.map((resource) => resource.name).join(', ')} bind to duplicate id '${id}'`,
|
|
124
|
+
locations: group.map((resource) => resource.location),
|
|
125
|
+
detectorId: 'gateforge.classifier',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
graph: { ...input.graph, findings: postBindingFindings, resources: sortResources(resources) },
|
|
130
|
+
classification: result,
|
|
131
|
+
blocking: classifierBlocking(result, { ...input.graph, findings: postBindingFindings }),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Projects classifier blocks into policy-engine blocking entries:
|
|
136
|
+
* per-decision blocks (contradictions, incomplete proofs, unresolved
|
|
137
|
+
* delete semantics, missing adapters) plus document-level stale targets
|
|
138
|
+
* and invalid signals. Every entry names its typed code so an AI can
|
|
139
|
+
* resolve it in code — never by obtaining human approval.
|
|
140
|
+
*/
|
|
141
|
+
export function classifierBlocking(result, graph) {
|
|
142
|
+
const locations = new Map();
|
|
143
|
+
for (const resource of graph.resources) {
|
|
144
|
+
locations.set(bindingKey(resource), resource.location);
|
|
145
|
+
}
|
|
146
|
+
const entries = [];
|
|
147
|
+
for (const decision of result.decisions) {
|
|
148
|
+
const fallback = locations.get(bindingKey(decision)) ?? null;
|
|
149
|
+
for (const block of decision.blocks) {
|
|
150
|
+
entries.push({
|
|
151
|
+
kind: 'classification',
|
|
152
|
+
resourceId: block.resourceId ?? decision.resourceId,
|
|
153
|
+
name: decision.name,
|
|
154
|
+
detail: `[${block.code}] ${block.detail}`,
|
|
155
|
+
location: block.locations[0] ?? fallback,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
for (const stale of result.staleTargets) {
|
|
160
|
+
entries.push({
|
|
161
|
+
kind: 'classification',
|
|
162
|
+
resourceId: null,
|
|
163
|
+
name: null,
|
|
164
|
+
detail: `[${stale.code}] ${stale.detail}`,
|
|
165
|
+
location: stale.locations[0] ?? null,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
for (const invalid of result.invalidSignals) {
|
|
169
|
+
entries.push({
|
|
170
|
+
kind: 'classification',
|
|
171
|
+
resourceId: null,
|
|
172
|
+
name: null,
|
|
173
|
+
detail: `[${invalid.code}] ${invalid.detail}`,
|
|
174
|
+
location: invalid.locations[0] ?? null,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
for (const unauthorized of result.unauthorizedSuppressive) {
|
|
178
|
+
entries.push({
|
|
179
|
+
kind: 'classification',
|
|
180
|
+
resourceId: null,
|
|
181
|
+
name: null,
|
|
182
|
+
detail: `[${unauthorized.code}] ${unauthorized.detail}`,
|
|
183
|
+
location: unauthorized.locations[0] ?? null,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
return entries;
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=bind.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../../src/classifier/bind.ts"],"names":[],"mappings":"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"}
|