@sigloch/graph-api-core 2.0.0 → 3.0.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/dist/audit.d.ts +22 -0
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +1 -1
- package/dist/format-e-codec.d.ts +15 -0
- package/dist/format-e-codec.js +36 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/rule-engine.d.ts +19 -0
- package/dist/rule-engine.js +6 -1
- package/dist/se-descriptor.d.ts +10 -1
- package/dist/se-descriptor.js +92 -32
- package/dist/types.d.ts +1 -1
- package/package.json +3 -3
package/dist/audit.d.ts
CHANGED
|
@@ -18,6 +18,28 @@ export interface AuditEntry {
|
|
|
18
18
|
result: 'applied' | 'rejected' | 'partial';
|
|
19
19
|
violations?: RuleViolation[];
|
|
20
20
|
graphVersion: number;
|
|
21
|
+
/**
|
|
22
|
+
* The POSITIVE half of the finding (CR-GC-314): rule IDs that were evaluated for this
|
|
23
|
+
* mutation and returned nothing.
|
|
24
|
+
*
|
|
25
|
+
* `violations` records only what went wrong, so an accepted mutation leaves an empty
|
|
26
|
+
* field — and "rule R-18 checked this edit and passed it" is not recoverable from
|
|
27
|
+
* "no violation". A later learning mechanism can learn from the first statement and
|
|
28
|
+
* nothing at all from the second; that asymmetry is the whole reason this field exists.
|
|
29
|
+
*
|
|
30
|
+
* Rule IDs only, never rule text (REQ-A04). Optional and purely additive: an entry
|
|
31
|
+
* written before this field means "not recorded", NOT "passed nothing" — a consumer
|
|
32
|
+
* must not read absence as an empty pass set (REQ-A05). Old records are deliberately
|
|
33
|
+
* not back-filled: reconstructing them would evaluate against a rule version that did
|
|
34
|
+
* not hold at mutation time, which is itself a provenance violation.
|
|
35
|
+
*/
|
|
36
|
+
rulesPassed?: string[];
|
|
37
|
+
/**
|
|
38
|
+
* Version of the rule set this mutation was evaluated against (REQ-A02) — read from
|
|
39
|
+
* the loaded package, never from config, so a rule-set change is visible in the trail
|
|
40
|
+
* at exactly the records it affected.
|
|
41
|
+
*/
|
|
42
|
+
rulesetVersion?: string;
|
|
21
43
|
}
|
|
22
44
|
export interface AuditLog {
|
|
23
45
|
record(entry: AuditEntry): Promise<void>;
|
package/dist/browser.d.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
export { findRoot } from './find-root.js';
|
|
15
15
|
export type { RootQueryGraph } from './find-root.js';
|
|
16
|
-
export { SE_DESCRIPTOR, projectToOntologyGraph } from './se-descriptor.js';
|
|
16
|
+
export { SE_DESCRIPTOR, createSeDescriptor, projectToOntologyGraph } from './se-descriptor.js';
|
|
17
17
|
export { FormatECodec } from './format-e-codec.js';
|
|
18
18
|
export { isValidTrace, tracePatternsOf } from './types.js';
|
|
19
19
|
export type { GraphNode, GraphEdge, Graph } from './types.js';
|
package/dist/browser.js
CHANGED
|
@@ -12,6 +12,6 @@
|
|
|
12
12
|
* @author andreas@siglochconsulting
|
|
13
13
|
*/
|
|
14
14
|
export { findRoot } from './find-root.js';
|
|
15
|
-
export { SE_DESCRIPTOR, projectToOntologyGraph } from './se-descriptor.js';
|
|
15
|
+
export { SE_DESCRIPTOR, createSeDescriptor, projectToOntologyGraph } from './se-descriptor.js';
|
|
16
16
|
export { FormatECodec } from './format-e-codec.js';
|
|
17
17
|
export { isValidTrace, tracePatternsOf } from './types.js';
|
package/dist/format-e-codec.d.ts
CHANGED
|
@@ -38,6 +38,21 @@ export declare class FormatECodec {
|
|
|
38
38
|
* `localeCompare`, which is locale-dependent.
|
|
39
39
|
*/
|
|
40
40
|
private serializeEdges;
|
|
41
|
+
/**
|
|
42
|
+
* CR-GC-334: an object attribute has no place in the inline block — `[k:v,k:v]` splits on
|
|
43
|
+
* commas, and `String({…})` produced the literal `[object Object]`, i.e. the binding was
|
|
44
|
+
* destroyed on write. Structured values therefore go to `@key {json}` follow-lines
|
|
45
|
+
* (`structuredAttrLines`), which `parse()` hydrates back into objects.
|
|
46
|
+
*
|
|
47
|
+
* EDGES keep the inline block (they must stay single-line, see `serializeEdges`), so an
|
|
48
|
+
* object on an EDGE is JSON-stringified inline — legible, but it round-trips only while it
|
|
49
|
+
* contains no comma. No edge in the SE ontology carries a structured attribute today; if one
|
|
50
|
+
* ever does, the inline block is the thing to replace, not this escape.
|
|
51
|
+
*/
|
|
41
52
|
private serializeAttrs;
|
|
53
|
+
/** CR-GC-334: object/array attributes as `@key {json}` lines below the node entry. */
|
|
54
|
+
private structuredAttrLines;
|
|
55
|
+
/** Inline block for an EDGE — structured values stringified, see `serializeAttrs`. */
|
|
56
|
+
private serializeEdgeAttrs;
|
|
42
57
|
private edgeTypeToArrow;
|
|
43
58
|
}
|
package/dist/format-e-codec.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* family (`TYPE-slug`, `Name.TypeAbbr.Counter`, `cand_<hex>`); typing by spelling made
|
|
8
8
|
* every foreign convention fail silently instead of loudly.
|
|
9
9
|
*/
|
|
10
|
+
import { hydrateAttrValue } from '@sigloch/contracts/se';
|
|
10
11
|
import { isValidTrace, tracePatternsOf } from './types.js';
|
|
11
12
|
// ---------------------------------------------------------------------------
|
|
12
13
|
// Regex patterns
|
|
@@ -73,7 +74,11 @@ export class FormatECodec {
|
|
|
73
74
|
if (lastOp && (lastOp.type === 'add_node' || lastOp.type === 'update_node' || lastOp.type === 'strict_add_node')) {
|
|
74
75
|
if (!lastOp.attributes)
|
|
75
76
|
lastOp.attributes = {};
|
|
76
|
-
|
|
77
|
+
// CR-GC-334: `serialize()` writes objects as `@key {json}`, so `parse()` must read
|
|
78
|
+
// them back as objects. Kept as a string, `realRef`/`testRef` fail their schema and
|
|
79
|
+
// the element reads as UNBOUND — R-19/R-20 fired on every node authored through this
|
|
80
|
+
// path. Same rule as the contracts parser, imported, not re-implemented.
|
|
81
|
+
lastOp.attributes[attrMatch[1]] = hydrateAttrValue(attrMatch[2].trim());
|
|
77
82
|
}
|
|
78
83
|
else {
|
|
79
84
|
errors.push(`@attribute line without preceding node: "${line}"`);
|
|
@@ -166,6 +171,9 @@ export class FormatECodec {
|
|
|
166
171
|
const descr = node.description ? `|${node.description}` : '';
|
|
167
172
|
const attrs = this.serializeAttrs(node.attributes);
|
|
168
173
|
lines.push(`+ ${node.uid}${descr}${attrs}`);
|
|
174
|
+
// CR-GC-334: realRef/testRef & friends as @key {json} — the inline block above
|
|
175
|
+
// cannot carry them, and dropping them here is what made bindings vanish.
|
|
176
|
+
lines.push(...this.structuredAttrLines(node.attributes));
|
|
169
177
|
}
|
|
170
178
|
}
|
|
171
179
|
}
|
|
@@ -327,7 +335,7 @@ export class FormatECodec {
|
|
|
327
335
|
const entries = [];
|
|
328
336
|
const groups = new Map();
|
|
329
337
|
for (const edge of edges) {
|
|
330
|
-
const attrs = this.
|
|
338
|
+
const attrs = this.serializeEdgeAttrs(edge.attributes);
|
|
331
339
|
if (attrs) {
|
|
332
340
|
entries.push({ sourceId: edge.sourceId, edgeType: edge.edgeType, targets: [edge.targetId], attrs });
|
|
333
341
|
continue;
|
|
@@ -352,13 +360,38 @@ export class FormatECodec {
|
|
|
352
360
|
|| cmp(a.attrs, b.attrs));
|
|
353
361
|
return entries.map(e => `+ ${e.sourceId} -${this.edgeTypeToArrow(e.edgeType)}-> ${e.targets.join(', ')}${e.attrs}`);
|
|
354
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* CR-GC-334: an object attribute has no place in the inline block — `[k:v,k:v]` splits on
|
|
365
|
+
* commas, and `String({…})` produced the literal `[object Object]`, i.e. the binding was
|
|
366
|
+
* destroyed on write. Structured values therefore go to `@key {json}` follow-lines
|
|
367
|
+
* (`structuredAttrLines`), which `parse()` hydrates back into objects.
|
|
368
|
+
*
|
|
369
|
+
* EDGES keep the inline block (they must stay single-line, see `serializeEdges`), so an
|
|
370
|
+
* object on an EDGE is JSON-stringified inline — legible, but it round-trips only while it
|
|
371
|
+
* contains no comma. No edge in the SE ontology carries a structured attribute today; if one
|
|
372
|
+
* ever does, the inline block is the thing to replace, not this escape.
|
|
373
|
+
*/
|
|
355
374
|
serializeAttrs(attrs) {
|
|
356
|
-
const entries = Object.entries(attrs).filter(([, v]) => v != null && v !== '');
|
|
375
|
+
const entries = Object.entries(attrs).filter(([, v]) => v != null && v !== '' && typeof v !== 'object');
|
|
357
376
|
if (entries.length === 0)
|
|
358
377
|
return '';
|
|
359
378
|
const pairs = entries.map(([k, v]) => `${k}:${String(v)}`);
|
|
360
379
|
return ` [${pairs.join(',')}]`;
|
|
361
380
|
}
|
|
381
|
+
/** CR-GC-334: object/array attributes as `@key {json}` lines below the node entry. */
|
|
382
|
+
structuredAttrLines(attrs) {
|
|
383
|
+
return Object.entries(attrs)
|
|
384
|
+
.filter(([, v]) => v != null && typeof v === 'object')
|
|
385
|
+
.map(([k, v]) => `@${k} ${JSON.stringify(v)}`);
|
|
386
|
+
}
|
|
387
|
+
/** Inline block for an EDGE — structured values stringified, see `serializeAttrs`. */
|
|
388
|
+
serializeEdgeAttrs(attrs) {
|
|
389
|
+
const entries = Object.entries(attrs).filter(([, v]) => v != null && v !== '');
|
|
390
|
+
if (entries.length === 0)
|
|
391
|
+
return '';
|
|
392
|
+
const pairs = entries.map(([k, v]) => `${k}:${typeof v === 'object' ? JSON.stringify(v) : String(v)}`);
|
|
393
|
+
return ` [${pairs.join(',')}]`;
|
|
394
|
+
}
|
|
362
395
|
edgeTypeToArrow(edgeType) {
|
|
363
396
|
// Use first defined arrow alias
|
|
364
397
|
const desc = this.ontology.edgeTypes[edgeType];
|
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export { MemoryAdapter } from './memory-adapter.js';
|
|
|
22
22
|
export type { TransportAdapter, TransportConfig } from './transport-adapter.js';
|
|
23
23
|
export { createGraphApi } from './factory.js';
|
|
24
24
|
export type { GraphApiConfig } from './factory.js';
|
|
25
|
-
export { SE_DESCRIPTOR, projectToOntologyGraph } from './se-descriptor.js';
|
|
25
|
+
export { SE_DESCRIPTOR, createSeDescriptor, projectToOntologyGraph } from './se-descriptor.js';
|
|
26
26
|
export { findRoot } from './find-root.js';
|
|
27
27
|
export type { RootQueryGraph } from './find-root.js';
|
|
28
28
|
export { applyEdgeOps, updateEdge, mergeNodes } from './edge-ops.js';
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ export { MemoryAdapter } from './memory-adapter.js';
|
|
|
19
19
|
// Factory
|
|
20
20
|
export { createGraphApi } from './factory.js';
|
|
21
21
|
// SE OntologyDescriptor (derived from @sigloch/contracts/se) [CR-195a]
|
|
22
|
-
export { SE_DESCRIPTOR, projectToOntologyGraph } from './se-descriptor.js';
|
|
22
|
+
export { SE_DESCRIPTOR, createSeDescriptor, projectToOntologyGraph } from './se-descriptor.js';
|
|
23
23
|
// Root-Suche — strukturelle Wurzel (SYS ohne eingehende compose), statt UID-Hardcode
|
|
24
24
|
export { findRoot } from './find-root.js';
|
|
25
25
|
// Edge ops — update-edge (flip/retype) + merge-nodes, shared by GraphService.mutate()
|
package/dist/rule-engine.d.ts
CHANGED
|
@@ -12,11 +12,30 @@ export interface RuleViolation {
|
|
|
12
12
|
fixHint?: string;
|
|
13
13
|
/** Carried from the contracts rule: candidate_targets / existing_traces context for fix automation. */
|
|
14
14
|
context?: unknown;
|
|
15
|
+
/**
|
|
16
|
+
* Stamped by the engine from the rule that produced this violation (CR-GC-312).
|
|
17
|
+
* `false` = visible but not gate-relevant. Absent means gating, so every existing
|
|
18
|
+
* consumer keeps its behaviour without reading the field.
|
|
19
|
+
*/
|
|
20
|
+
gating?: boolean;
|
|
15
21
|
}
|
|
16
22
|
export interface Rule {
|
|
17
23
|
id: string;
|
|
18
24
|
name: string;
|
|
19
25
|
severity: 'error' | 'warning' | 'info';
|
|
26
|
+
/**
|
|
27
|
+
* May an `error` from this rule BLOCK a write? (CR-GC-312) Default `true`.
|
|
28
|
+
*
|
|
29
|
+
* Severity says how bad a finding is; this says whether the gate acts on it. The
|
|
30
|
+
* two are separate because a rule family can be correct and worth surfacing long
|
|
31
|
+
* before a repo has paid off its backlog — switching one on would otherwise freeze
|
|
32
|
+
* every write on debt the writer did not create. Set `false` to surface a rule in
|
|
33
|
+
* `evaluate`/readiness while it is still being worked down, then promote it.
|
|
34
|
+
*
|
|
35
|
+
* NOT a severity downgrade: the violation keeps `severity: 'error'` and reads as one
|
|
36
|
+
* everywhere it is displayed.
|
|
37
|
+
*/
|
|
38
|
+
gating?: boolean;
|
|
20
39
|
evaluate: (graph: Graph) => RuleViolation[];
|
|
21
40
|
}
|
|
22
41
|
export interface RuleEngine {
|
package/dist/rule-engine.js
CHANGED
|
@@ -10,7 +10,12 @@ export class DefaultRuleEngine {
|
|
|
10
10
|
evaluate(graph) {
|
|
11
11
|
const violations = [];
|
|
12
12
|
for (const rule of this.rules) {
|
|
13
|
-
|
|
13
|
+
// CR-GC-312: stamp `gating` from the rule so a consumer's gate can filter
|
|
14
|
+
// without a second lookup into the catalog. Only stamped when the rule opts
|
|
15
|
+
// OUT — an absent field means gating, the pre-existing behaviour.
|
|
16
|
+
const stamp = rule.gating === false ? { gating: false } : undefined;
|
|
17
|
+
for (const v of rule.evaluate(graph))
|
|
18
|
+
violations.push(stamp ? { ...v, ...stamp } : v);
|
|
14
19
|
}
|
|
15
20
|
return violations;
|
|
16
21
|
}
|
package/dist/se-descriptor.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - Graph (nodes/edges) ⟷ OntologyGraph (elements/traces)
|
|
10
10
|
* - RuleViolation (ruleId/…) ⟷ contracts RuleViolation (rule_id/…)
|
|
11
11
|
*/
|
|
12
|
-
import { type OntologyGraph } from '@sigloch/contracts/se';
|
|
12
|
+
import { type MetricPolicy, type OntologyGraph } from '@sigloch/contracts/se';
|
|
13
13
|
import type { Graph, OntologyDescriptor } from './types.js';
|
|
14
14
|
/**
|
|
15
15
|
* Project an ontology-agnostic Graph (nodes/edges) onto the SE OntologyGraph
|
|
@@ -21,4 +21,13 @@ export declare function projectToOntologyGraph(graph: Graph): OntologyGraph;
|
|
|
21
21
|
* Canonical SE OntologyDescriptor (ontology + V3 rules + MT metrics), version-pinned
|
|
22
22
|
* to contracts/se ONTOLOGY_VERSION. Plug into GraphService / FormatECodec.
|
|
23
23
|
*/
|
|
24
|
+
export declare function createSeDescriptor(policy: MetricPolicy): OntologyDescriptor;
|
|
25
|
+
/**
|
|
26
|
+
* The descriptor for a host without its own metric policy — judged with contracts'
|
|
27
|
+
* `DEFAULT_METRIC_POLICY`, which is a named, grep-able value, not a hidden fallback.
|
|
28
|
+
*
|
|
29
|
+
* A host that holds a configuration builds its own with `createSeDescriptor(policy)`
|
|
30
|
+
* and must then use only that one; two descriptors in one process would be the two
|
|
31
|
+
* thresholds CR-SM-233 removed.
|
|
32
|
+
*/
|
|
24
33
|
export declare const SE_DESCRIPTOR: OntologyDescriptor;
|
package/dist/se-descriptor.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - Graph (nodes/edges) ⟷ OntologyGraph (elements/traces)
|
|
10
10
|
* - RuleViolation (ruleId/…) ⟷ contracts RuleViolation (rule_id/…)
|
|
11
11
|
*/
|
|
12
|
-
import { ElementType, TraceType, TRACE_PATTERNS, V3_RULES, MT_RULES, ONTOLOGY_VERSION, } from '@sigloch/contracts/se';
|
|
12
|
+
import { ElementType, TraceType, TRACE_PATTERNS, V3_RULES, MT_RULES, UC_RULES, FC_RULES, SC_RULES, CR_RULES, AO_RULES, FM_RULES, VIEW_RULES, AF_RULES, ONTOLOGY_VERSION, DEFAULT_METRIC_POLICY, } from '@sigloch/contracts/se';
|
|
13
13
|
/**
|
|
14
14
|
* Project an ontology-agnostic Graph (nodes/edges) onto the SE OntologyGraph
|
|
15
15
|
* (elements/traces) that contracts/se rules evaluate against. Type-specific
|
|
@@ -45,28 +45,77 @@ export function projectToOntologyGraph(graph) {
|
|
|
45
45
|
/**
|
|
46
46
|
* The contracts/se rule catalog, adapted to graph-api-core's Rule shape.
|
|
47
47
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
48
|
+
* CR-GC-312: this used to be `[...V3_RULES, ...MT_RULES]` — two of the twelve families
|
|
49
|
+
* contracts exports. Everything else (UC, FC, SC, CR, AO, FM, VIEW, AF) was written,
|
|
50
|
+
* versioned and shipped, and then evaluated by nobody: consumers register exactly
|
|
51
|
+
* `SE_DESCRIPTOR.rules`, so ten families were dead weight in the package. Measured on
|
|
52
|
+
* graphcode's SSOT the day this was found: 2 violations reported, 276 findable — among
|
|
53
|
+
* them `CR-R02` ("done but no commitRef", 91×), precisely the graph-vs-reality check
|
|
54
|
+
* the repo believed it had. A use case with no operational chain went unflagged for
|
|
55
|
+
* weeks because `UC-03`/`FC-02` existed and never ran.
|
|
56
|
+
*
|
|
57
|
+
* Two families stay out on purpose:
|
|
58
|
+
* - BQ/ND are the CODING profile (`getRuleDefsForProfile('coding')`), not SE.
|
|
59
|
+
* - RC (conformance) needs `CodeFacts` from a repo checkout, which this package has
|
|
60
|
+
* no access to; graphcode evaluates those itself in `src/conformance.ts`.
|
|
61
|
+
*
|
|
62
|
+
* `gating` (see `Rule`) is what makes the switch-on safe. V3/MT keep their gate power;
|
|
63
|
+
* the newly wired families are advisory until a repo has worked its backlog down —
|
|
64
|
+
* otherwise the 114 pre-existing errors in graphcode's own graph would block every
|
|
65
|
+
* write on debt the writer did not create. Promotion is a per-family decision, not a
|
|
66
|
+
* side effect of being registered.
|
|
53
67
|
*/
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
const GATING_PREFIXES = ['R-', 'RD-', 'MT-'];
|
|
69
|
+
const SE_RULE_DEFS = [
|
|
70
|
+
...V3_RULES,
|
|
71
|
+
...UC_RULES,
|
|
72
|
+
...FC_RULES,
|
|
73
|
+
...SC_RULES,
|
|
74
|
+
...CR_RULES,
|
|
75
|
+
...AO_RULES,
|
|
76
|
+
...FM_RULES,
|
|
77
|
+
...VIEW_RULES,
|
|
78
|
+
...AF_RULES,
|
|
79
|
+
];
|
|
80
|
+
function adapt(def, evaluate) {
|
|
81
|
+
// (evaluate is already policy-bound by the caller — see seRules below)
|
|
82
|
+
return {
|
|
83
|
+
id: def.id,
|
|
84
|
+
name: def.name,
|
|
85
|
+
severity: def.severity,
|
|
86
|
+
gating: GATING_PREFIXES.some((p) => def.id.startsWith(p)),
|
|
87
|
+
evaluate: (graph) => evaluate(projectToOntologyGraph(graph)).map((v) => ({
|
|
88
|
+
ruleId: v.rule_id,
|
|
89
|
+
ruleName: def.name,
|
|
90
|
+
severity: v.severity,
|
|
91
|
+
message: v.message,
|
|
92
|
+
elementId: v.element_id,
|
|
93
|
+
// CR-GC-203 item 1: carry the fix-context through instead of discarding it,
|
|
94
|
+
// so rules_get_violations hands the agent candidates + a hint, not just a message.
|
|
95
|
+
fixHint: v.fix_hint,
|
|
96
|
+
context: v.context,
|
|
97
|
+
})),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Every rule bound to the judging policy (CR-SM-233, extended by CR-SM-236).
|
|
102
|
+
*
|
|
103
|
+
* A threshold is input, not a constant, and it therefore cannot live in a descriptor
|
|
104
|
+
* constant: a host that configures the value (graphcode's `graphcode.config.jsonc`,
|
|
105
|
+
* CR-GC-329) would otherwise judge against its own number while the gate judged against
|
|
106
|
+
* a second one baked in here.
|
|
107
|
+
*
|
|
108
|
+
* CR-SM-236 removed the former split into a policy-free `SE_RULES` constant plus a
|
|
109
|
+
* policy-bound metric list. MT-01/MT-02 stopped being the only rules with a threshold
|
|
110
|
+
* (CR-01, FM-03 and R-04 joined them), so a policy-free rule constant had become a
|
|
111
|
+
* second, silently-judging path — exactly what CR-SM-233 set out to remove.
|
|
112
|
+
*
|
|
113
|
+
* A `null` threshold means measure, don't judge: the rule stays registered and simply
|
|
114
|
+
* reports nothing.
|
|
115
|
+
*/
|
|
116
|
+
function seRules(policy) {
|
|
117
|
+
return [...SE_RULE_DEFS, ...MT_RULES].map((def) => adapt(def, (g) => def.evaluate(g, policy)));
|
|
118
|
+
}
|
|
70
119
|
// `label` is the node-table identifier (kuzu table name) — must be a valid
|
|
71
120
|
// identifier, so it's the ElementType key (SYS, UC, …), not the human
|
|
72
121
|
// ELEMENT_DESCRIPTIONS text which would break DDL.
|
|
@@ -80,13 +129,24 @@ const edgeTypes = Object.fromEntries(TraceType.options.map((tt) => {
|
|
|
80
129
|
* Canonical SE OntologyDescriptor (ontology + V3 rules + MT metrics), version-pinned
|
|
81
130
|
* to contracts/se ONTOLOGY_VERSION. Plug into GraphService / FormatECodec.
|
|
82
131
|
*/
|
|
83
|
-
export
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
132
|
+
export function createSeDescriptor(policy) {
|
|
133
|
+
return {
|
|
134
|
+
name: 'se',
|
|
135
|
+
version: ONTOLOGY_VERSION,
|
|
136
|
+
nodeTypes,
|
|
137
|
+
edgeTypes,
|
|
138
|
+
// CR-GC-247: TRACE_PATTERNS is the trace-legality SSOT; validPairs above is kept
|
|
139
|
+
// only for Format-E arrow/menu enumeration. isValidTrace validates against these.
|
|
140
|
+
patterns: TRACE_PATTERNS,
|
|
141
|
+
rules: seRules(policy),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* The descriptor for a host without its own metric policy — judged with contracts'
|
|
146
|
+
* `DEFAULT_METRIC_POLICY`, which is a named, grep-able value, not a hidden fallback.
|
|
147
|
+
*
|
|
148
|
+
* A host that holds a configuration builds its own with `createSeDescriptor(policy)`
|
|
149
|
+
* and must then use only that one; two descriptors in one process would be the two
|
|
150
|
+
* thresholds CR-SM-233 removed.
|
|
151
|
+
*/
|
|
152
|
+
export const SE_DESCRIPTOR = createSeDescriptor(DEFAULT_METRIC_POLICY);
|
package/dist/types.d.ts
CHANGED
|
@@ -113,7 +113,7 @@ export interface FormatEOperation {
|
|
|
113
113
|
description?: string;
|
|
114
114
|
/**
|
|
115
115
|
* BOK-CR-026: `unknown`, not `string` — object-valued bindings (`realRef`,
|
|
116
|
-
* `
|
|
116
|
+
* `testRefs`) must survive a Format-E mutation as objects/arrays, or the element reads as
|
|
117
117
|
* unbound. GraphService already handled them as unknown internally; this is the
|
|
118
118
|
* public type catching up (a plain `@key value` line still yields a string).
|
|
119
119
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigloch/graph-api-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
"prepublishOnly": "npm run build && npm run test"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@sigloch/contracts": "^
|
|
24
|
+
"@sigloch/contracts": "^4.0.0",
|
|
25
25
|
"zod": "^4.3.6"
|
|
26
26
|
},
|
|
27
27
|
"license": "MIT",
|
|
28
|
-
"description": "Framework-agnostic graph engine core
|
|
28
|
+
"description": "Framework-agnostic graph engine core \u2014 ontology-typed nodes/traces, rule evaluation, views",
|
|
29
29
|
"author": "sigloch-consulting",
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|