@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.
Files changed (242) hide show
  1. package/LICENSE +202 -0
  2. package/dist/baselines/adoption.d.ts +76 -0
  3. package/dist/baselines/adoption.d.ts.map +1 -0
  4. package/dist/baselines/adoption.js +163 -0
  5. package/dist/baselines/adoption.js.map +1 -0
  6. package/dist/baselines/index.d.ts +102 -0
  7. package/dist/baselines/index.d.ts.map +1 -0
  8. package/dist/baselines/index.js +186 -0
  9. package/dist/baselines/index.js.map +1 -0
  10. package/dist/canonical-json.d.ts +51 -0
  11. package/dist/canonical-json.d.ts.map +1 -0
  12. package/dist/canonical-json.js +112 -0
  13. package/dist/canonical-json.js.map +1 -0
  14. package/dist/classifier/bind.d.ts +64 -0
  15. package/dist/classifier/bind.d.ts.map +1 -0
  16. package/dist/classifier/bind.js +188 -0
  17. package/dist/classifier/bind.js.map +1 -0
  18. package/dist/classifier/classify.d.ts +154 -0
  19. package/dist/classifier/classify.d.ts.map +1 -0
  20. package/dist/classifier/classify.js +1207 -0
  21. package/dist/classifier/classify.js.map +1 -0
  22. package/dist/classifier/glob.d.ts +48 -0
  23. package/dist/classifier/glob.d.ts.map +1 -0
  24. package/dist/classifier/glob.js +104 -0
  25. package/dist/classifier/glob.js.map +1 -0
  26. package/dist/classifier/index.d.ts +10 -0
  27. package/dist/classifier/index.d.ts.map +1 -0
  28. package/dist/classifier/index.js +21 -0
  29. package/dist/classifier/index.js.map +1 -0
  30. package/dist/classifier/schema.d.ts +150 -0
  31. package/dist/classifier/schema.d.ts.map +1 -0
  32. package/dist/classifier/schema.js +139 -0
  33. package/dist/classifier/schema.js.map +1 -0
  34. package/dist/config/index.d.ts +259 -0
  35. package/dist/config/index.d.ts.map +1 -0
  36. package/dist/config/index.js +523 -0
  37. package/dist/config/index.js.map +1 -0
  38. package/dist/fingerprints.d.ts +56 -0
  39. package/dist/fingerprints.d.ts.map +1 -0
  40. package/dist/fingerprints.js +59 -0
  41. package/dist/fingerprints.js.map +1 -0
  42. package/dist/graph/build.d.ts +16 -0
  43. package/dist/graph/build.d.ts.map +1 -0
  44. package/dist/graph/build.js +423 -0
  45. package/dist/graph/build.js.map +1 -0
  46. package/dist/graph/index.d.ts +12 -0
  47. package/dist/graph/index.d.ts.map +1 -0
  48. package/dist/graph/index.js +10 -0
  49. package/dist/graph/index.js.map +1 -0
  50. package/dist/graph/schema.d.ts +448 -0
  51. package/dist/graph/schema.d.ts.map +1 -0
  52. package/dist/graph/schema.js +237 -0
  53. package/dist/graph/schema.js.map +1 -0
  54. package/dist/graph/symbols.d.ts +129 -0
  55. package/dist/graph/symbols.d.ts.map +1 -0
  56. package/dist/graph/symbols.js +177 -0
  57. package/dist/graph/symbols.js.map +1 -0
  58. package/dist/graph/util.d.ts +40 -0
  59. package/dist/graph/util.d.ts.map +1 -0
  60. package/dist/graph/util.js +41 -0
  61. package/dist/graph/util.js.map +1 -0
  62. package/dist/index.d.ts +683 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +563 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/mapping/resolve.d.ts +177 -0
  67. package/dist/mapping/resolve.d.ts.map +1 -0
  68. package/dist/mapping/resolve.js +523 -0
  69. package/dist/mapping/resolve.js.map +1 -0
  70. package/dist/policy/coverage.d.ts +79 -0
  71. package/dist/policy/coverage.d.ts.map +1 -0
  72. package/dist/policy/coverage.js +119 -0
  73. package/dist/policy/coverage.js.map +1 -0
  74. package/dist/policy/evaluate.d.ts +275 -0
  75. package/dist/policy/evaluate.d.ts.map +1 -0
  76. package/dist/policy/evaluate.js +382 -0
  77. package/dist/policy/evaluate.js.map +1 -0
  78. package/dist/policy/index.d.ts +15 -0
  79. package/dist/policy/index.d.ts.map +1 -0
  80. package/dist/policy/index.js +14 -0
  81. package/dist/policy/index.js.map +1 -0
  82. package/dist/policy/trusted.d.ts +59 -0
  83. package/dist/policy/trusted.d.ts.map +1 -0
  84. package/dist/policy/trusted.js +96 -0
  85. package/dist/policy/trusted.js.map +1 -0
  86. package/dist/provenance.d.ts +170 -0
  87. package/dist/provenance.d.ts.map +1 -0
  88. package/dist/provenance.js +306 -0
  89. package/dist/provenance.js.map +1 -0
  90. package/dist/receipt/index.d.ts +74 -0
  91. package/dist/receipt/index.d.ts.map +1 -0
  92. package/dist/receipt/index.js +154 -0
  93. package/dist/receipt/index.js.map +1 -0
  94. package/dist/report/index.d.ts +100 -0
  95. package/dist/report/index.d.ts.map +1 -0
  96. package/dist/report/index.js +355 -0
  97. package/dist/report/index.js.map +1 -0
  98. package/dist/schemas/adoption.d.ts +40 -0
  99. package/dist/schemas/adoption.d.ts.map +1 -0
  100. package/dist/schemas/adoption.js +87 -0
  101. package/dist/schemas/adoption.js.map +1 -0
  102. package/dist/schemas/baseline.d.ts +19 -0
  103. package/dist/schemas/baseline.d.ts.map +1 -0
  104. package/dist/schemas/baseline.js +45 -0
  105. package/dist/schemas/baseline.js.map +1 -0
  106. package/dist/schemas/claim.d.ts +32 -0
  107. package/dist/schemas/claim.d.ts.map +1 -0
  108. package/dist/schemas/claim.js +34 -0
  109. package/dist/schemas/claim.js.map +1 -0
  110. package/dist/schemas/classification-policy.d.ts +84 -0
  111. package/dist/schemas/classification-policy.d.ts.map +1 -0
  112. package/dist/schemas/classification-policy.js +130 -0
  113. package/dist/schemas/classification-policy.js.map +1 -0
  114. package/dist/schemas/classification-signal.d.ts +125 -0
  115. package/dist/schemas/classification-signal.d.ts.map +1 -0
  116. package/dist/schemas/classification-signal.js +126 -0
  117. package/dist/schemas/classification-signal.js.map +1 -0
  118. package/dist/schemas/classification.d.ts +120 -0
  119. package/dist/schemas/classification.d.ts.map +1 -0
  120. package/dist/schemas/classification.js +154 -0
  121. package/dist/schemas/classification.js.map +1 -0
  122. package/dist/schemas/common.d.ts +73 -0
  123. package/dist/schemas/common.d.ts.map +1 -0
  124. package/dist/schemas/common.js +60 -0
  125. package/dist/schemas/common.js.map +1 -0
  126. package/dist/schemas/coverage-policy.d.ts +89 -0
  127. package/dist/schemas/coverage-policy.d.ts.map +1 -0
  128. package/dist/schemas/coverage-policy.js +81 -0
  129. package/dist/schemas/coverage-policy.js.map +1 -0
  130. package/dist/schemas/evidence.d.ts +65 -0
  131. package/dist/schemas/evidence.d.ts.map +1 -0
  132. package/dist/schemas/evidence.js +64 -0
  133. package/dist/schemas/evidence.js.map +1 -0
  134. package/dist/schemas/execution-result.d.ts +214 -0
  135. package/dist/schemas/execution-result.d.ts.map +1 -0
  136. package/dist/schemas/execution-result.js +240 -0
  137. package/dist/schemas/execution-result.js.map +1 -0
  138. package/dist/schemas/gate-receipt.d.ts +86 -0
  139. package/dist/schemas/gate-receipt.d.ts.map +1 -0
  140. package/dist/schemas/gate-receipt.js +193 -0
  141. package/dist/schemas/gate-receipt.js.map +1 -0
  142. package/dist/schemas/index.d.ts +22 -0
  143. package/dist/schemas/index.d.ts.map +1 -0
  144. package/dist/schemas/index.js +22 -0
  145. package/dist/schemas/index.js.map +1 -0
  146. package/dist/schemas/obligation.d.ts +37 -0
  147. package/dist/schemas/obligation.d.ts.map +1 -0
  148. package/dist/schemas/obligation.js +46 -0
  149. package/dist/schemas/obligation.js.map +1 -0
  150. package/dist/schemas/plugin.d.ts +19 -0
  151. package/dist/schemas/plugin.d.ts.map +1 -0
  152. package/dist/schemas/plugin.js +20 -0
  153. package/dist/schemas/plugin.js.map +1 -0
  154. package/dist/schemas/policy.d.ts +73 -0
  155. package/dist/schemas/policy.d.ts.map +1 -0
  156. package/dist/schemas/policy.js +46 -0
  157. package/dist/schemas/policy.js.map +1 -0
  158. package/dist/schemas/resource.d.ts +26 -0
  159. package/dist/schemas/resource.d.ts.map +1 -0
  160. package/dist/schemas/resource.js +29 -0
  161. package/dist/schemas/resource.js.map +1 -0
  162. package/dist/schemas/run-manifest.d.ts +72 -0
  163. package/dist/schemas/run-manifest.d.ts.map +1 -0
  164. package/dist/schemas/run-manifest.js +125 -0
  165. package/dist/schemas/run-manifest.js.map +1 -0
  166. package/dist/schemas/runner-adapter.d.ts +169 -0
  167. package/dist/schemas/runner-adapter.d.ts.map +1 -0
  168. package/dist/schemas/runner-adapter.js +2 -0
  169. package/dist/schemas/runner-adapter.js.map +1 -0
  170. package/dist/schemas/test-catalog.d.ts +472 -0
  171. package/dist/schemas/test-catalog.d.ts.map +1 -0
  172. package/dist/schemas/test-catalog.js +311 -0
  173. package/dist/schemas/test-catalog.js.map +1 -0
  174. package/dist/schemas/test-map.d.ts +99 -0
  175. package/dist/schemas/test-map.d.ts.map +1 -0
  176. package/dist/schemas/test-map.js +103 -0
  177. package/dist/schemas/test-map.js.map +1 -0
  178. package/dist/schemas/verdict.d.ts +73 -0
  179. package/dist/schemas/verdict.d.ts.map +1 -0
  180. package/dist/schemas/verdict.js +92 -0
  181. package/dist/schemas/verdict.js.map +1 -0
  182. package/dist/schemas/waiver.d.ts +36 -0
  183. package/dist/schemas/waiver.d.ts.map +1 -0
  184. package/dist/schemas/waiver.js +42 -0
  185. package/dist/schemas/waiver.js.map +1 -0
  186. package/dist/supervision/index.d.ts +170 -0
  187. package/dist/supervision/index.d.ts.map +1 -0
  188. package/dist/supervision/index.js +354 -0
  189. package/dist/supervision/index.js.map +1 -0
  190. package/dist/testing/clock.d.ts +50 -0
  191. package/dist/testing/clock.d.ts.map +1 -0
  192. package/dist/testing/clock.js +75 -0
  193. package/dist/testing/clock.js.map +1 -0
  194. package/dist/testing/env.d.ts +66 -0
  195. package/dist/testing/env.d.ts.map +1 -0
  196. package/dist/testing/env.js +106 -0
  197. package/dist/testing/env.js.map +1 -0
  198. package/dist/testing/gate-runner.d.ts +141 -0
  199. package/dist/testing/gate-runner.d.ts.map +1 -0
  200. package/dist/testing/gate-runner.js +173 -0
  201. package/dist/testing/gate-runner.js.map +1 -0
  202. package/dist/testing/gf19.d.ts +106 -0
  203. package/dist/testing/gf19.d.ts.map +1 -0
  204. package/dist/testing/gf19.js +282 -0
  205. package/dist/testing/gf19.js.map +1 -0
  206. package/dist/testing/index.d.ts +20 -0
  207. package/dist/testing/index.d.ts.map +1 -0
  208. package/dist/testing/index.js +14 -0
  209. package/dist/testing/index.js.map +1 -0
  210. package/dist/testing/red-probe.d.ts +138 -0
  211. package/dist/testing/red-probe.d.ts.map +1 -0
  212. package/dist/testing/red-probe.js +251 -0
  213. package/dist/testing/red-probe.js.map +1 -0
  214. package/dist/testing/temp-repo.d.ts +126 -0
  215. package/dist/testing/temp-repo.d.ts.map +1 -0
  216. package/dist/testing/temp-repo.js +214 -0
  217. package/dist/testing/temp-repo.js.map +1 -0
  218. package/dist/verdict/cause.d.ts +99 -0
  219. package/dist/verdict/cause.d.ts.map +1 -0
  220. package/dist/verdict/cause.js +206 -0
  221. package/dist/verdict/cause.js.map +1 -0
  222. package/dist/verdict/evaluate.d.ts +135 -0
  223. package/dist/verdict/evaluate.d.ts.map +1 -0
  224. package/dist/verdict/evaluate.js +1513 -0
  225. package/dist/verdict/evaluate.js.map +1 -0
  226. package/dist/verdict/index.d.ts +21 -0
  227. package/dist/verdict/index.d.ts.map +1 -0
  228. package/dist/verdict/index.js +20 -0
  229. package/dist/verdict/index.js.map +1 -0
  230. package/dist/verdict/pack-verifiers.d.ts +97 -0
  231. package/dist/verdict/pack-verifiers.d.ts.map +1 -0
  232. package/dist/verdict/pack-verifiers.js +763 -0
  233. package/dist/verdict/pack-verifiers.js.map +1 -0
  234. package/dist/verdict/registry.d.ts +180 -0
  235. package/dist/verdict/registry.d.ts.map +1 -0
  236. package/dist/verdict/registry.js +67 -0
  237. package/dist/verdict/registry.js.map +1 -0
  238. package/dist/waivers/index.d.ts +103 -0
  239. package/dist/waivers/index.d.ts.map +1 -0
  240. package/dist/waivers/index.js +192 -0
  241. package/dist/waivers/index.js.map +1 -0
  242. 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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"}