@sigloch/contracts 3.3.0 → 4.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/harness/index.d.ts +2 -2
- package/dist/se/action-priority.d.ts +101 -0
- package/dist/se/action-priority.js +124 -0
- package/dist/se/analysis-freshness-rules.d.ts +5 -0
- package/dist/se/analysis-freshness-rules.js +5 -5
- package/dist/se/ao-rules.d.ts +5 -39
- package/dist/se/ao-rules.js +20 -13
- package/dist/se/conformance-rules.d.ts +2 -2
- package/dist/se/conformance-rules.js +36 -30
- package/dist/se/cr-quality-rules.d.ts +2 -1
- package/dist/se/cr-quality-rules.js +9 -7
- package/dist/se/evaluate-all.d.ts +18 -3
- package/dist/se/evaluate-all.js +29 -26
- package/dist/se/fchain-quality-rules.d.ts +2 -1
- package/dist/se/fchain-quality-rules.js +8 -6
- package/dist/se/fmea-rules.d.ts +3 -11
- package/dist/se/fmea-rules.js +53 -16
- package/dist/se/format-e-parser.d.ts +14 -1
- package/dist/se/format-e-parser.js +8 -3
- package/dist/se/index.d.ts +4 -2
- package/dist/se/index.js +4 -2
- package/dist/se/metric-rules.d.ts +13 -5
- package/dist/se/metric-rules.js +23 -13
- package/dist/se/near-duplicate-rules.d.ts +2 -0
- package/dist/se/near-duplicate-rules.js +2 -2
- package/dist/se/ontology.d.ts +55 -4
- package/dist/se/ontology.js +46 -6
- package/dist/se/policy.d.ts +65 -0
- package/dist/se/policy.js +100 -0
- package/dist/se/quality-rules.d.ts +2 -1
- package/dist/se/quality-rules.js +9 -7
- package/dist/se/readiness.d.ts +9 -1
- package/dist/se/readiness.js +18 -2
- package/dist/se/rules.d.ts +25 -5
- package/dist/se/rules.js +112 -47
- package/dist/se/schema-quality-rules.d.ts +2 -1
- package/dist/se/schema-quality-rules.js +6 -4
- package/dist/se/uc-quality-rules.d.ts +2 -1
- package/dist/se/uc-quality-rules.js +10 -8
- package/dist/se/view-rules.d.ts +2 -6
- package/dist/se/view-rules.js +40 -13
- package/package.json +2 -1
package/dist/se/ontology.js
CHANGED
|
@@ -58,25 +58,65 @@ export const RepoRelativePathSchema = z
|
|
|
58
58
|
* Runnable binding for a TEST element (CR-GC-134, ontology bump 3.4.0).
|
|
59
59
|
* Resolves a TEST node to the concrete artefact a runner can execute, enabling
|
|
60
60
|
* bottom-up selective test deduction (`graph_tests`): change → impacted TESTs →
|
|
61
|
-
* `
|
|
61
|
+
* `testRefs` → minimal selective run command.
|
|
62
62
|
* - `file` : test file path, e.g. `tests/foo.test.ts` (the runner target).
|
|
63
63
|
* - `case` : optional named case/`describe`/`it` block within the file.
|
|
64
64
|
* - `tool` : the runner, e.g. `vitest`, `playwright`, `pytest`.
|
|
65
65
|
* - `level` : optional level, e.g. `unit`, `integration`, `validation`.
|
|
66
|
-
*
|
|
66
|
+
*
|
|
67
|
+
* `tool` steht bewusst **pro Eintrag**, nicht hochgezogen: eine Abnahme mischt real die
|
|
68
|
+
* Runner — ein TEST kann aus `tests/dashboard.test.mjs` (vitest) *und*
|
|
69
|
+
* `tests/visual/dashboard-render.spec.mjs` (playwright) bestehen. Ein Runner je TEST-Knoten
|
|
70
|
+
* wäre eine Lüge, die das alte 1:1-Schema nur deshalb nicht produzierte, weil es die zweite
|
|
71
|
+
* Datei gar nicht erst zuliess.
|
|
67
72
|
*/
|
|
68
73
|
export const TestRefSchema = z.object({
|
|
69
74
|
file: RepoRelativePathSchema,
|
|
70
75
|
case: z.string().optional(),
|
|
71
76
|
tool: z.string(),
|
|
72
77
|
level: z.string().optional(),
|
|
78
|
+
/**
|
|
79
|
+
* CR-SM-231b: das Ergebnis haengt **pro Eintrag**, aus demselben Grund wie `tool`.
|
|
80
|
+
*
|
|
81
|
+
* Vorher lag `testResult` am TEST-**Knoten**. Mit n Eintraegen ist das mehrdeutig: laeuft eine
|
|
82
|
+
* Abnahme als vitest *und* playwright, kann ein einzelnes Ergebnis nicht sagen, welcher Lauf
|
|
83
|
+
* gemeint ist — und „einer rot, einer gruen" ist gar nicht darstellbar. Genau der Zustand,
|
|
84
|
+
* den ein Gate wissen muss.
|
|
85
|
+
*
|
|
86
|
+
* Optional: ein Eintrag ohne Ergebnis ist noch nicht gelaufen, nicht „bestanden". VR-01
|
|
87
|
+
* meldet das.
|
|
88
|
+
*/
|
|
89
|
+
result: TestResult.optional(),
|
|
90
|
+
/** ISO-Zeitstempel des Laufs, der `result` erzeugt hat. Ohne ihn ist ein Ergebnis undatiert. */
|
|
91
|
+
ranAt: z.iso.datetime().optional(),
|
|
92
|
+
/** Repo-relativer Pfad zum Lauf-Artefakt (Report, Screenshot, Trace) — die Evidenz zur Aussage. */
|
|
93
|
+
evidence: RepoRelativePathSchema.optional(),
|
|
73
94
|
});
|
|
95
|
+
/**
|
|
96
|
+
* CR-SM-231: eine Abnahme, **n** Testdateien — 1:n, nie n:m.
|
|
97
|
+
*
|
|
98
|
+
* Vorher war `testRef` ein einzelnes Objekt: ein TEST-Knoten war an genau eine Datei bindbar.
|
|
99
|
+
* Eine Abnahme aus Unit- *und* Visual-Lauf konnte ihre Evidenz damit nicht vollstaendig
|
|
100
|
+
* deklarieren, und der Ausweichweg war belegt — dieselbe Spec-Datei stand im `testRef` zweier
|
|
101
|
+
* TEST-Knoten. Damit war die Relation faktisch n:m: ein roter Lauf war keiner Abnahme mehr
|
|
102
|
+
* eindeutig zuordenbar, waehrend der TRR-Gate dieselbe Evidenz doppelt zaehlte.
|
|
103
|
+
*
|
|
104
|
+
* **Warum n:m hier falsch ist.** n:m zwischen Abnahme und Anforderung ist bereits korrekt
|
|
105
|
+
* modelliert und in Gebrauch (`TEST -[verify]-> REQ`) — dafuer ist eine Kante da. Die Bindung
|
|
106
|
+
* an die Laufdatei ist etwas anderes: sie ist **Evidenz-Adresse**, kein Traceability-Link. Sie
|
|
107
|
+
* gehoert ins Attribut und bleibt 1:n — ein TEST kennt n Dateien, eine Datei gehoert zu
|
|
108
|
+
* hoechstens einem TEST. Die zweite Haelfte erzwingt R-29.
|
|
109
|
+
*
|
|
110
|
+
* Gespeichert unter `OntologyElement.attributes.testRefs`. Das alte `testRef` entfaellt
|
|
111
|
+
* ersatzlos — kein Union, kein Alias, keine parallelen Pfade.
|
|
112
|
+
*/
|
|
113
|
+
export const TestRefsSchema = z.array(TestRefSchema).min(1);
|
|
74
114
|
/**
|
|
75
115
|
* Realization binding for an element (CR-228, ontology bump 3.9.0) — unifies the
|
|
76
116
|
* byte-identical former `codeRef` (FUNC → code symbol) and `schemaRef` (SCHEMA →
|
|
77
117
|
* Zod export), and extends to MOD (physical part → CAD/geometry artefact). The
|
|
78
118
|
* *type* of the pointing element disambiguates what kind of realization it is:
|
|
79
|
-
* FUNC→code, SCHEMA→Zod-def, physical MOD→CAD. TEST keeps its own `
|
|
119
|
+
* FUNC→code, SCHEMA→Zod-def, physical MOD→CAD. TEST keeps its own `testRefs`
|
|
80
120
|
* (a TEST is not just located but *executed* — the runner is the extra value).
|
|
81
121
|
* - `file` : realization file path, e.g. `src/harness.ts`, `part.step`.
|
|
82
122
|
* - `symbol` : the realizing symbol (function/class/Zod export). Optional — a
|
|
@@ -181,10 +221,10 @@ export const MODELING_ELEMENT_TYPES = ElementType.options.filter(t => t !== 'SES
|
|
|
181
221
|
*/
|
|
182
222
|
export const ELEMENT_ATTRIBUTES = {
|
|
183
223
|
TEST: [
|
|
184
|
-
|
|
224
|
+
// CR-SM-231b: das knotenweite `testResult` ist weg — das Ergebnis haengt pro testRefs-Eintrag.
|
|
185
225
|
{ key: 'sourceFile', type: 'string', description: 'Test file path (e.g. tests/foo.test.ts)' },
|
|
186
|
-
{ key: '
|
|
187
|
-
{ key: 'concept', type: 'boolean', description: 'Concept-only TEST: no run artifact yet; exempt from the R-19
|
|
226
|
+
{ key: 'testRefs', type: 'array', description: 'Runnable bindings [{file, case?, tool, level?, result?, ranAt?, evidence?}, …] — one acceptance, n test files (1:n), each with its own outcome. See TestRefsSchema (CR-SM-231)' },
|
|
227
|
+
{ key: 'concept', type: 'boolean', description: 'Concept-only TEST: no run artifact yet; exempt from the R-19 testRefs-binding requirement (CR-GC-205)' },
|
|
188
228
|
],
|
|
189
229
|
REQ: [
|
|
190
230
|
{ key: 'severity', type: 'number', description: 'FMEA severity (1-10)' },
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CR-SM-233: Urteilsschwellen der Architektur-Metriken als Eingabe, nicht als Modulkonstante.
|
|
3
|
+
*
|
|
4
|
+
* Vorher stand die Schwelle als `const INSTABILITY_THRESHOLD = 0.7` in `metric-rules.ts`.
|
|
5
|
+
* Jede Konfigurierbarkeit von außen wäre damit automatisch ein zweiter Pfad gewesen
|
|
6
|
+
* (Config-Wert neben Code-Default) — und ein stillgelegter Wert hätte still weiterurteilt,
|
|
7
|
+
* weil der Default einspringt. Deshalb: Parameter ohne Fallback.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
/**
|
|
11
|
+
* Urteilsschwellen der Architektur-Metriken. `null` = messen, nicht urteilen.
|
|
12
|
+
*
|
|
13
|
+
* `null` ist ein erstklassiger Wert, kein „aus": die Kennzahl wird weiter gerechnet,
|
|
14
|
+
* exportiert und angezeigt; es entsteht nur kein Verstoß. Das ist die MT-03-Entscheidung
|
|
15
|
+
* (CR-SM-223) verallgemeinert — der Weg, einen unvalidierten Wert stillzulegen, ohne die
|
|
16
|
+
* Zahl zu verlieren.
|
|
17
|
+
*/
|
|
18
|
+
export declare const MetricPolicySchema: z.ZodObject<{
|
|
19
|
+
instability: z.ZodNullable<z.ZodNumber>;
|
|
20
|
+
lcom4: z.ZodNullable<z.ZodObject<{
|
|
21
|
+
info: z.ZodNumber;
|
|
22
|
+
warning: z.ZodNumber;
|
|
23
|
+
}, z.core.$strip>>;
|
|
24
|
+
crossingFlows: z.ZodNullable<z.ZodObject<{
|
|
25
|
+
warning: z.ZodNumber;
|
|
26
|
+
}, z.core.$strip>>;
|
|
27
|
+
riskRpn: z.ZodNullable<z.ZodNumber>;
|
|
28
|
+
apTable: z.ZodNullable<z.ZodObject<{
|
|
29
|
+
severityBands: z.ZodArray<z.ZodObject<{
|
|
30
|
+
from: z.ZodNumber;
|
|
31
|
+
to: z.ZodNumber;
|
|
32
|
+
}, z.core.$strip>>;
|
|
33
|
+
occurrenceBands: z.ZodArray<z.ZodObject<{
|
|
34
|
+
from: z.ZodNumber;
|
|
35
|
+
to: z.ZodNumber;
|
|
36
|
+
}, z.core.$strip>>;
|
|
37
|
+
detectionBands: z.ZodArray<z.ZodObject<{
|
|
38
|
+
from: z.ZodNumber;
|
|
39
|
+
to: z.ZodNumber;
|
|
40
|
+
}, z.core.$strip>>;
|
|
41
|
+
cells: z.ZodArray<z.ZodArray<z.ZodArray<z.ZodEnum<{
|
|
42
|
+
High: "High";
|
|
43
|
+
Medium: "Medium";
|
|
44
|
+
Low: "Low";
|
|
45
|
+
}>>>>;
|
|
46
|
+
}, z.core.$strip>>;
|
|
47
|
+
moduleSize: z.ZodNullable<z.ZodObject<{
|
|
48
|
+
large: z.ZodNumber;
|
|
49
|
+
coupled: z.ZodNumber;
|
|
50
|
+
crossings: z.ZodNumber;
|
|
51
|
+
}, z.core.$strip>>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
export type MetricPolicy = z.infer<typeof MetricPolicySchema>;
|
|
54
|
+
/**
|
|
55
|
+
* Der Startwert, sichtbar als solcher — **kein** Fallback in der Regel.
|
|
56
|
+
*
|
|
57
|
+
* Ein Aufrufer nimmt ihn bewusst oder ersetzt ihn; er steht an genau einer Stelle und ist
|
|
58
|
+
* grep-bar. Die Werte sind die bisherigen (0.7 / 4 / 6-statt-5-Grenze siehe unten) und
|
|
59
|
+
* ausdrücklich **unvalidiert** (CR-SM-223: „Validation … is deferred") — sie sind gesetzt,
|
|
60
|
+
* nicht gemessen.
|
|
61
|
+
*
|
|
62
|
+
* `lcom4.warning = 6` ist die unveränderte Alt-Semantik: vorher `>= 4 && <= 5` → info,
|
|
63
|
+
* `> 5` → warning, also warning ab 6.
|
|
64
|
+
*/
|
|
65
|
+
export declare const DEFAULT_METRIC_POLICY: MetricPolicy;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CR-SM-233: Urteilsschwellen der Architektur-Metriken als Eingabe, nicht als Modulkonstante.
|
|
3
|
+
*
|
|
4
|
+
* Vorher stand die Schwelle als `const INSTABILITY_THRESHOLD = 0.7` in `metric-rules.ts`.
|
|
5
|
+
* Jede Konfigurierbarkeit von außen wäre damit automatisch ein zweiter Pfad gewesen
|
|
6
|
+
* (Config-Wert neben Code-Default) — und ein stillgelegter Wert hätte still weiterurteilt,
|
|
7
|
+
* weil der Default einspringt. Deshalb: Parameter ohne Fallback.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { ApTableSchema } from './action-priority.js';
|
|
11
|
+
/**
|
|
12
|
+
* Urteilsschwellen der Architektur-Metriken. `null` = messen, nicht urteilen.
|
|
13
|
+
*
|
|
14
|
+
* `null` ist ein erstklassiger Wert, kein „aus": die Kennzahl wird weiter gerechnet,
|
|
15
|
+
* exportiert und angezeigt; es entsteht nur kein Verstoß. Das ist die MT-03-Entscheidung
|
|
16
|
+
* (CR-SM-223) verallgemeinert — der Weg, einen unvalidierten Wert stillzulegen, ohne die
|
|
17
|
+
* Zahl zu verlieren.
|
|
18
|
+
*/
|
|
19
|
+
export const MetricPolicySchema = z.object({
|
|
20
|
+
/** MT-01: Instabilität, ab der gewarnt wird (exklusiv). null → MT-01 feuert nie. */
|
|
21
|
+
instability: z.number().min(0).max(1).nullable(),
|
|
22
|
+
/** MT-02: LCOM4-Stufen (info ab, warning ab). null → MT-02 feuert nie. */
|
|
23
|
+
lcom4: z
|
|
24
|
+
.object({
|
|
25
|
+
info: z.number().int().min(2),
|
|
26
|
+
warning: z.number().int().min(2),
|
|
27
|
+
})
|
|
28
|
+
.nullable(),
|
|
29
|
+
/**
|
|
30
|
+
* CR-01: kreuzende io-Flows je Modulpaar, ab denen gewarnt wird (inklusiv).
|
|
31
|
+
*
|
|
32
|
+
* `null` → CR-01 meldet **nichts**, auch keine info. Das ist der Aus-Zustand, den die Regel
|
|
33
|
+
* vorher nicht hatte: sie meldete je Modulpaar mit ≥ 1 Kreuzung, und diese info-Fälle zählen
|
|
34
|
+
* in die `arch`-Dimension ein (CR-SM-236).
|
|
35
|
+
*/
|
|
36
|
+
crossingFlows: z.object({ warning: z.number().int().min(1) }).nullable(),
|
|
37
|
+
/**
|
|
38
|
+
* FM-03: RPN (severity · occurrence · detection), ab dem ein Risiko-REQ eine bestandene
|
|
39
|
+
* Verifikation braucht (exklusiv). null → FM-03 feuert nie.
|
|
40
|
+
*
|
|
41
|
+
* 100 ist Domänenstandard, aber skalenabhängig: bei anderer Belegung von S/O/D ist es die
|
|
42
|
+
* falsche Grenze.
|
|
43
|
+
*/
|
|
44
|
+
riskRpn: z.number().int().positive().nullable(),
|
|
45
|
+
/**
|
|
46
|
+
* CR-SM-229: die lizenzierte AIAG-VDA-Tabelle, wenn der Host eine hat.
|
|
47
|
+
*
|
|
48
|
+
* Sie reist im Policy-Objekt mit, **nicht** in einem zweiten Kontext-Parameter: seit
|
|
49
|
+
* CR-SM-233 ist `policy` der eine Kanal, über den eine Regel ihre Urteilsgrundlage bekommt.
|
|
50
|
+
* Ein zweiter daneben wäre genau der parallele Pfad, den der Regelsatz verbietet.
|
|
51
|
+
*
|
|
52
|
+
* `null` → der markierte Übergang gilt (bestätigte AP-Invarianten, sonst RPN-Bänder). Der
|
|
53
|
+
* Konsument lädt die Tabelle aus einer lokalen, nie eingecheckten Datei; **im Repo und im
|
|
54
|
+
* exportierten Graphen steht sie nie** (Zellwerte sind normative Wertung, keine Fakten).
|
|
55
|
+
*/
|
|
56
|
+
apTable: ApTableSchema.nullable(),
|
|
57
|
+
/**
|
|
58
|
+
* R-04: Modulgröße **gegen** Kreuzungen — die Regel wägt beides ab, ihr alter Name
|
|
59
|
+
* („Max module size") gab das nicht her. null → R-04 feuert nie.
|
|
60
|
+
*
|
|
61
|
+
* Drei Werte, weil die Regel drei Urteile fällt. Ein einzelner Schwellwert hätte zwei davon
|
|
62
|
+
* im Code gelassen — genau der Zustand, den dieser CR beseitigt.
|
|
63
|
+
*/
|
|
64
|
+
moduleSize: z
|
|
65
|
+
.object({
|
|
66
|
+
/** > `large` FUNCs: mit Kreuzungen warning, ohne Kreuzungen info („kohäsiv, nur groß"). */
|
|
67
|
+
large: z.number().int().min(1),
|
|
68
|
+
/** > `coupled` FUNCs ist die Untergrenze, ab der die Regel überhaupt hinsieht. */
|
|
69
|
+
coupled: z.number().int().min(1),
|
|
70
|
+
/** Kreuzungen, ab denen ein nur `coupled`-großes Modul warnt (exklusiv). */
|
|
71
|
+
crossings: z.number().int().min(0),
|
|
72
|
+
})
|
|
73
|
+
.nullable(),
|
|
74
|
+
});
|
|
75
|
+
/**
|
|
76
|
+
* Der Startwert, sichtbar als solcher — **kein** Fallback in der Regel.
|
|
77
|
+
*
|
|
78
|
+
* Ein Aufrufer nimmt ihn bewusst oder ersetzt ihn; er steht an genau einer Stelle und ist
|
|
79
|
+
* grep-bar. Die Werte sind die bisherigen (0.7 / 4 / 6-statt-5-Grenze siehe unten) und
|
|
80
|
+
* ausdrücklich **unvalidiert** (CR-SM-223: „Validation … is deferred") — sie sind gesetzt,
|
|
81
|
+
* nicht gemessen.
|
|
82
|
+
*
|
|
83
|
+
* `lcom4.warning = 6` ist die unveränderte Alt-Semantik: vorher `>= 4 && <= 5` → info,
|
|
84
|
+
* `> 5` → warning, also warning ab 6.
|
|
85
|
+
*/
|
|
86
|
+
export const DEFAULT_METRIC_POLICY = {
|
|
87
|
+
instability: 0.7,
|
|
88
|
+
lcom4: { info: 4, warning: 6 },
|
|
89
|
+
// CR-SM-236: die bisherigen Literale, jetzt an einer grep-baren Stelle.
|
|
90
|
+
// `crossingFlows.warning = 3` ist die unveränderte Alt-Semantik: vorher `count > 2` → warning.
|
|
91
|
+
crossingFlows: { warning: 3 },
|
|
92
|
+
riskRpn: 100,
|
|
93
|
+
// `large`/`coupled`/`crossings` = die drei Literale aus `maxModuleSize`: vorher
|
|
94
|
+
// `funcCount <= 8` → skip, `funcCount > 12` → groß, `crossings > 2` → gekoppelt.
|
|
95
|
+
moduleSize: { large: 12, coupled: 8, crossings: 2 },
|
|
96
|
+
// CR-SM-229: kein Startwert möglich und keiner gewollt — die Tabelle steht nur im Handbook.
|
|
97
|
+
// `null` heißt hier nicht „aus", sondern „markierter Übergang": bestätigte AP-Invarianten,
|
|
98
|
+
// sonst RPN-Bänder. `apMethod()` macht das für den Leser sichtbar.
|
|
99
|
+
apTable: null,
|
|
100
|
+
};
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { OntologyGraph } from './ontology.js';
|
|
7
7
|
import type { RuleDefinition, RuleViolation } from './rules.js';
|
|
8
|
+
import type { MetricPolicy } from './policy.js';
|
|
8
9
|
export declare function bq01Unambiguous(graph: OntologyGraph): RuleViolation[];
|
|
9
10
|
export declare function bq02Verifiable(graph: OntologyGraph): RuleViolation[];
|
|
10
11
|
/**
|
|
@@ -25,4 +26,4 @@ export declare function bq06Conforming(graph: OntologyGraph): RuleViolation[];
|
|
|
25
26
|
export declare function bq07Complete(graph: OntologyGraph): RuleViolation[];
|
|
26
27
|
export declare const BQ_RULES: RuleDefinition[];
|
|
27
28
|
/** Run all BQ rules against a graph, returning combined violations. */
|
|
28
|
-
export declare function evaluateBQRules(graph: OntologyGraph): RuleViolation[];
|
|
29
|
+
export declare function evaluateBQRules(graph: OntologyGraph, policy: MetricPolicy): RuleViolation[];
|
package/dist/se/quality-rules.js
CHANGED
|
@@ -194,13 +194,15 @@ export function bq07Complete(graph) {
|
|
|
194
194
|
// Aggregated array & convenience runner
|
|
195
195
|
// ---------------------------------------------------------------------------
|
|
196
196
|
export const BQ_RULES = [
|
|
197
|
-
{ id: 'BQ-01', name: 'Unambiguous', severity: 'warning', evaluate: bq01Unambiguous },
|
|
198
|
-
{ id: 'BQ-02', name: 'Verifiable', severity: 'warning', evaluate: bq02Verifiable },
|
|
199
|
-
{ id: 'BQ-04', name: 'Necessary', severity: 'warning', evaluate: bq04Necessary },
|
|
200
|
-
{ id: 'BQ-06', name: 'Conforming', severity: 'warning', evaluate: bq06Conforming },
|
|
201
|
-
{ id: 'BQ-07', name: 'Complete', severity: 'warning', evaluate: bq07Complete },
|
|
197
|
+
{ id: 'BQ-01', name: 'Unambiguous', severity: 'warning', evaluate: bq01Unambiguous, domain: ['REQ'] },
|
|
198
|
+
{ id: 'BQ-02', name: 'Verifiable', severity: 'warning', evaluate: bq02Verifiable, domain: ['REQ'] },
|
|
199
|
+
{ id: 'BQ-04', name: 'Necessary', severity: 'warning', evaluate: bq04Necessary, domain: ['REQ'] },
|
|
200
|
+
{ id: 'BQ-06', name: 'Conforming', severity: 'warning', evaluate: bq06Conforming, domain: ['REQ'] },
|
|
201
|
+
{ id: 'BQ-07', name: 'Complete', severity: 'warning', evaluate: bq07Complete, domain: ['REQ'] },
|
|
202
202
|
];
|
|
203
203
|
/** Run all BQ rules against a graph, returning combined violations. */
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
// CR-SM-236: `policy` wird durchgereicht, auch wo diese Familie heute keine Schwelle hat —
|
|
205
|
+
// ein Sonderweg je Familie waere genau der zweite Pfad, den der Regelsatz verbietet.
|
|
206
|
+
export function evaluateBQRules(graph, policy) {
|
|
207
|
+
return BQ_RULES.flatMap(rule => rule.evaluate(graph, policy));
|
|
206
208
|
}
|
package/dist/se/readiness.d.ts
CHANGED
|
@@ -36,6 +36,15 @@ export declare const ReadinessScore: z.ZodObject<{
|
|
|
36
36
|
ready: z.ZodBoolean;
|
|
37
37
|
}, z.core.$strip>;
|
|
38
38
|
export type ReadinessScoreType = z.infer<typeof ReadinessScore>;
|
|
39
|
+
/**
|
|
40
|
+
* CR-SM-237: `overallScore` ist weg. Es war das **ungewichtete** Mittel der acht
|
|
41
|
+
* Dimensions-Scores — `ms` (3 Regeln) zählte so viel wie `arch` (~20 Regeln über Hunderte
|
|
42
|
+
* Elemente), die Zahl bewegte sich also mit dem Größenverhältnis der Dimensionen und nicht mit
|
|
43
|
+
* dem Zustand des Modells. Gelesen hat sie ohnehin niemand: der einzige Zugriff in der Familie
|
|
44
|
+
* war eine Formprüfung (`'overallScore' in x`) im inzwischen gelöschten `weight-vector.ts`.
|
|
45
|
+
* Ein interpretierbarer Ersatz (`1 − Σviolations / Σapplicable`) kommt, wenn er einen
|
|
46
|
+
* Konsumenten hat — nicht auf Vorrat.
|
|
47
|
+
*/
|
|
39
48
|
export declare const ReadinessReport: z.ZodObject<{
|
|
40
49
|
scores: z.ZodArray<z.ZodObject<{
|
|
41
50
|
dimension: z.ZodEnum<{
|
|
@@ -53,7 +62,6 @@ export declare const ReadinessReport: z.ZodObject<{
|
|
|
53
62
|
applicable: z.ZodNumber;
|
|
54
63
|
ready: z.ZodBoolean;
|
|
55
64
|
}, z.core.$strip>>;
|
|
56
|
-
overallScore: z.ZodNumber;
|
|
57
65
|
timestamp: z.ZodISODateTime;
|
|
58
66
|
}, z.core.$strip>;
|
|
59
67
|
export type ReadinessReportType = z.infer<typeof ReadinessReport>;
|
package/dist/se/readiness.js
CHANGED
|
@@ -23,11 +23,21 @@ export const ReadinessScore = z.object({
|
|
|
23
23
|
score: z.number().min(0).max(1), // 1 - (violations / applicable)
|
|
24
24
|
violations: z.number().int(),
|
|
25
25
|
applicable: z.number().int(),
|
|
26
|
-
|
|
26
|
+
// CR-SM-235: `score >= readyThreshold`. Die Schwelle steht bewusst NICHT hier — sie ist
|
|
27
|
+
// Eingabe von `computeReadiness`, und eine Zahl im Kommentar wäre die dritte Meinung dazu.
|
|
28
|
+
ready: z.boolean(),
|
|
27
29
|
});
|
|
30
|
+
/**
|
|
31
|
+
* CR-SM-237: `overallScore` ist weg. Es war das **ungewichtete** Mittel der acht
|
|
32
|
+
* Dimensions-Scores — `ms` (3 Regeln) zählte so viel wie `arch` (~20 Regeln über Hunderte
|
|
33
|
+
* Elemente), die Zahl bewegte sich also mit dem Größenverhältnis der Dimensionen und nicht mit
|
|
34
|
+
* dem Zustand des Modells. Gelesen hat sie ohnehin niemand: der einzige Zugriff in der Familie
|
|
35
|
+
* war eine Formprüfung (`'overallScore' in x`) im inzwischen gelöschten `weight-vector.ts`.
|
|
36
|
+
* Ein interpretierbarer Ersatz (`1 − Σviolations / Σapplicable`) kommt, wenn er einen
|
|
37
|
+
* Konsumenten hat — nicht auf Vorrat.
|
|
38
|
+
*/
|
|
28
39
|
export const ReadinessReport = z.object({
|
|
29
40
|
scores: z.array(ReadinessScore),
|
|
30
|
-
overallScore: z.number().min(0).max(1),
|
|
31
41
|
timestamp: z.iso.datetime(),
|
|
32
42
|
});
|
|
33
43
|
/**
|
|
@@ -44,6 +54,9 @@ export const RULE_TO_DIMENSION = {
|
|
|
44
54
|
'RD-04': 'arch',
|
|
45
55
|
// trace/realization/allocation completeness rules (CR-228 D: previously unmapped → advisory fall-through)
|
|
46
56
|
'R-18': 'arch', 'R-19': 'ver', 'R-20': 'arch', 'R-21': 'ver',
|
|
57
|
+
// CR-SM-231: R-29 (Testdatei-Exklusivitaet) gehoert zu 'ver' wie R-19 — beide bewerten die
|
|
58
|
+
// Evidenz-Bindung einer Abnahme, R-19 ihre Praesenz, R-29 ihre Eindeutigkeit.
|
|
59
|
+
'R-29': 'ver',
|
|
47
60
|
'R-22': 'alloc', 'R-23': 'alloc', 'R-26': 'schema', 'R-27': 'arch',
|
|
48
61
|
// CR-SM-226: R-28 Ebenen-Präsenz (>1 FUNC needs FLOW+SCHEMA) is an architecture rule.
|
|
49
62
|
'R-28': 'arch',
|
|
@@ -148,6 +161,9 @@ export const RULE_TO_PHASE = {
|
|
|
148
161
|
'NFR-01': 'CDR',
|
|
149
162
|
// TRR — test readiness.
|
|
150
163
|
'R-01': 'TRR', 'R-05': 'TRR', 'R-19': 'TRR', 'R-20': 'TRR', 'R-21': 'TRR',
|
|
164
|
+
// CR-SM-231: eine doppelt beanspruchte Testdatei laesst den TRR-Gate dieselbe Evidenz
|
|
165
|
+
// doppelt zaehlen — der Befund gehoert genau an dieses Gate.
|
|
166
|
+
'R-29': 'TRR',
|
|
151
167
|
'VR-01': 'TRR',
|
|
152
168
|
'FM-03': 'TRR',
|
|
153
169
|
'CR-R02': 'TRR',
|
package/dist/se/rules.d.ts
CHANGED
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { z } from 'zod/v4';
|
|
7
7
|
import type { OntologyGraph } from './ontology.js';
|
|
8
|
+
import type { MetricPolicy } from './policy.js';
|
|
8
9
|
export declare const RuleSeverity: z.ZodEnum<{
|
|
9
10
|
error: "error";
|
|
10
|
-
warning: "warning";
|
|
11
11
|
info: "info";
|
|
12
|
+
warning: "warning";
|
|
12
13
|
}>;
|
|
13
14
|
export type RuleSeverity = z.infer<typeof RuleSeverity>;
|
|
14
15
|
/** Candidate target for resolving a violation (e.g. a REQ to satisfy, a TEST to link). */
|
|
@@ -89,8 +90,8 @@ export declare const RuleViolation: z.ZodObject<{
|
|
|
89
90
|
rule_id: z.ZodString;
|
|
90
91
|
severity: z.ZodEnum<{
|
|
91
92
|
error: "error";
|
|
92
|
-
warning: "warning";
|
|
93
93
|
info: "info";
|
|
94
|
+
warning: "warning";
|
|
94
95
|
}>;
|
|
95
96
|
element_id: z.ZodString;
|
|
96
97
|
message: z.ZodString;
|
|
@@ -152,8 +153,27 @@ export interface RuleDefinition {
|
|
|
152
153
|
id: string;
|
|
153
154
|
name: string;
|
|
154
155
|
severity: 'error' | 'warning' | 'info';
|
|
155
|
-
|
|
156
|
+
/**
|
|
157
|
+
* CR-SM-236: `policy` steht jeder Regel zur Verfuegung, damit eine Urteilsschwelle nirgends
|
|
158
|
+
* als Literal im Regelcode zurueckbleibt. Regeln ohne Schwelle deklarieren den Parameter
|
|
159
|
+
* schlicht nicht — eine einstellige Funktion bleibt zuweisbar.
|
|
160
|
+
*/
|
|
161
|
+
evaluate: (graph: OntologyGraph, policy: MetricPolicy) => RuleViolation[];
|
|
162
|
+
/**
|
|
163
|
+
* CR-SM-235: die Grundgesamtheit, ueber die die Regel feuert — der Nenner ihres
|
|
164
|
+
* Readiness-Anteils. **Der Elementtyp, ueber den sie feuert, nicht das Thema, dem sie
|
|
165
|
+
* gehoert:** MS-03 („CR ohne Milestone") feuert je CR, nicht je MS.
|
|
166
|
+
*
|
|
167
|
+
* Pflichtfeld, damit ein neuer Regeleintrag ohne Grundgesamtheit den Build bricht. Vorher
|
|
168
|
+
* lag die Zuordnung als Handtabelle in einem anderen Paket (`se-steering`), 18 von 71 Regeln
|
|
169
|
+
* fehlten dort — sie erhoehten den Zaehler, nie den Nenner, und jede neue Regel senkte den
|
|
170
|
+
* Score automatisch, bis jemand die zweite Tabelle nachzog.
|
|
171
|
+
*
|
|
172
|
+
* Mehrere Typen, wo die Regel ueber mehrere feuert (RD-04: FUNC, MOD und SYS als Eltern
|
|
173
|
+
* einer Zerlegung). `['all']` = jedes Nicht-SESSION-Element (R-08/R-18 pruefen Traces).
|
|
174
|
+
*/
|
|
175
|
+
domain: readonly string[];
|
|
156
176
|
}
|
|
157
177
|
export declare const V3_RULES: RuleDefinition[];
|
|
158
|
-
/** Run all rules against a graph */
|
|
159
|
-
export declare function evaluateRules(graph: OntologyGraph): RuleViolation[];
|
|
178
|
+
/** Run all rules against a graph. CR-SM-236: `policy` ist Pflicht — wie bei `evaluateAllRules`. */
|
|
179
|
+
export declare function evaluateRules(graph: OntologyGraph, policy: MetricPolicy): RuleViolation[];
|