@sigloch/graph-api-core 1.0.0 → 2.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/dist/audit.d.ts +22 -0
- package/dist/rule-engine.d.ts +19 -0
- package/dist/rule-engine.js +6 -1
- package/dist/se-descriptor.js +35 -7
- package/package.json +2 -2
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/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.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, } 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,16 +45,44 @@ 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
|
|
68
|
+
const GATING_PREFIXES = ['R-', 'RD-', 'MT-'];
|
|
69
|
+
const SE_RULE_DEFS = [
|
|
70
|
+
...V3_RULES,
|
|
71
|
+
...MT_RULES,
|
|
72
|
+
...UC_RULES,
|
|
73
|
+
...FC_RULES,
|
|
74
|
+
...SC_RULES,
|
|
75
|
+
...CR_RULES,
|
|
76
|
+
...AO_RULES,
|
|
77
|
+
...FM_RULES,
|
|
78
|
+
...VIEW_RULES,
|
|
79
|
+
...AF_RULES,
|
|
80
|
+
];
|
|
81
|
+
const SE_RULES = SE_RULE_DEFS.map((def) => ({
|
|
55
82
|
id: def.id,
|
|
56
83
|
name: def.name,
|
|
57
84
|
severity: def.severity,
|
|
85
|
+
gating: GATING_PREFIXES.some((p) => def.id.startsWith(p)),
|
|
58
86
|
evaluate: (graph) => def.evaluate(projectToOntologyGraph(graph)).map((v) => ({
|
|
59
87
|
ruleId: v.rule_id,
|
|
60
88
|
ruleName: def.name,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigloch/graph-api-core",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"prepublishOnly": "npm run build && npm run test"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@sigloch/contracts": "^
|
|
24
|
+
"@sigloch/contracts": "^3.2.0",
|
|
25
25
|
"zod": "^4.3.6"
|
|
26
26
|
},
|
|
27
27
|
"license": "MIT",
|