@sigloch/contracts 6.3.0 → 10.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.
Files changed (41) hide show
  1. package/dist/se/ao-rules.d.ts +12 -12
  2. package/dist/se/ao-rules.js +88 -225
  3. package/dist/se/conformance-rules.d.ts +28 -0
  4. package/dist/se/conformance-rules.js +40 -17
  5. package/dist/se/cr-quality-rules.js +75 -58
  6. package/dist/se/evaluate-all.d.ts +4 -2
  7. package/dist/se/evaluate-all.js +40 -24
  8. package/dist/se/fchain-quality-rules.d.ts +0 -1
  9. package/dist/se/fchain-quality-rules.js +0 -44
  10. package/dist/se/flat-graph.d.ts +9 -1
  11. package/dist/se/flat-graph.js +15 -6
  12. package/dist/se/format-e-parser.d.ts +14 -2
  13. package/dist/se/format-e-parser.js +33 -9
  14. package/dist/se/grammar-snapshot.d.ts +10 -7
  15. package/dist/se/grammar-snapshot.js +172 -27
  16. package/dist/se/index.d.ts +4 -3
  17. package/dist/se/index.js +4 -3
  18. package/dist/se/meta-model.d.ts +99 -7
  19. package/dist/se/meta-model.js +155 -14
  20. package/dist/se/metric-rules.d.ts +20 -1
  21. package/dist/se/metric-rules.js +97 -58
  22. package/dist/se/module-crossings.d.ts +102 -0
  23. package/dist/se/module-crossings.js +196 -0
  24. package/dist/se/near-duplicate-rules.d.ts +16 -24
  25. package/dist/se/near-duplicate-rules.js +21 -92
  26. package/dist/se/ontology.d.ts +32 -47
  27. package/dist/se/ontology.js +56 -13
  28. package/dist/se/policy.d.ts +6 -0
  29. package/dist/se/policy.js +53 -2
  30. package/dist/se/quality-rules.d.ts +18 -0
  31. package/dist/se/quality-rules.js +68 -12
  32. package/dist/se/readiness.d.ts +7 -5
  33. package/dist/se/readiness.js +40 -22
  34. package/dist/se/rules.d.ts +6 -7
  35. package/dist/se/rules.js +358 -128
  36. package/dist/se/schema-quality-rules.d.ts +0 -1
  37. package/dist/se/schema-quality-rules.js +7 -28
  38. package/dist/se/similarity.d.ts +61 -0
  39. package/dist/se/similarity.js +116 -0
  40. package/dist/se/uc-quality-rules.js +31 -12
  41. package/package.json +3 -2
package/dist/se/policy.js CHANGED
@@ -34,6 +34,27 @@ export const MetricPolicySchema = z.object({
34
34
  * in die `arch`-Dimension ein (CR-SM-236).
35
35
  */
36
36
  crossingFlows: z.object({ warning: z.number().int().min(1) }).nullable(),
37
+ /**
38
+ * CR-SM-282: Kinderzahl je Blackbox (RD-04). Stand bis hierher als
39
+ * `DECOMPOSITION_BREADTH_MAX = 11` inline in `rules.ts` — eine Urteilsschwelle, die sich
40
+ * weder per grep noch aus dem Regelnamen ablesen liess (dieselbe Klasse, die CR-SM-236 fuer
41
+ * R-04 aufgeloest hat). `null` -> messen, nicht urteilen: die Regel schweigt.
42
+ *
43
+ * Der Default bleibt 11 und ist damit verhaltensgleich zum Bisherigen. Die Doktrin
44
+ * (`se:top-level`: „max 5 per level") ist bewusst NICHT der Default: `info` bei 5 haette am
45
+ * graphcode-Selbstmodell 20 zusaetzliche Befunde erzeugt, und `readiness` zaehlt `info`
46
+ * ungefiltert in den Nenner (`score = 1 - Verstoesse / applicable`) — genau der Grund, aus dem
47
+ * MT-03 zur Messung statt zur Regel wurde. Wer doktrin-streng fahren will, setzt 5.
48
+ */
49
+ decompositionBreadth: z.object({ warning: z.number().int().min(2) }).nullable(),
50
+ /**
51
+ * CR-SM-283: Randbreite je Blackbox (BW-02) — verschiedene Vertraege, die den Rand queren.
52
+ * Bewusst OHNE `info`-Stufe: die Verteilung gibt sie nicht her. bok und graph-view-edit enden
53
+ * beide bei 3; eine info-Schwelle dort truege bok 4 Befunde auf 9 Blackboxes, und `readiness`
54
+ * zaehlt `info` ungefiltert in den Nenner (`score = 1 - Verstoesse / applicable`) — der Grund,
55
+ * aus dem MT-03 zur Messung statt zur Regel wurde. `null` -> messen, nicht urteilen.
56
+ */
57
+ boundaryWidth: z.object({ warning: z.number().int().min(1) }).nullable(),
37
58
  /**
38
59
  * FM-03: RPN (severity · occurrence · detection), ab dem ein Risiko-REQ eine bestandene
39
60
  * Verifikation braucht (exklusiv). null → FM-03 feuert nie.
@@ -84,15 +105,45 @@ export const MetricPolicySchema = z.object({
84
105
  * `> 5` → warning, also warning ab 6.
85
106
  */
86
107
  export const DEFAULT_METRIC_POLICY = {
87
- instability: 0.7,
108
+ // CR-SM-293: `null` — MESSEN, NICHT URTEILEN. Die 0.7 stand hier als Startwert und war laut
109
+ // CR-SM-223 ausdruecklich "gesetzt, nicht gemessen". Nachdem MT-01 nur noch Kopplung zaehlt,
110
+ // ist die Verteilung ueber 149 messbare Module ZWEIGIPFLIG: 44 liegen exakt auf 0.00 (reine
111
+ // Produzenten), 45 exakt auf 1.00 (reine Konsumenten), und 45 der 51 Befunde bei 0.7 sind
112
+ // genau die 1.00. Aus einer solchen Verteilung laesst sich keine Schwelle ABLESEN (Praezedenz
113
+ // CR-SM-283/BW-02), und der Grund ist Struktur, nicht Zaehlweise: die meisten Module tragen
114
+ // zwei bis drei kreuzende Vertraege, da ist das Verhaeltnis 0 oder 1.
115
+ //
116
+ // Tiefer liegt der Einwand von Martin selbst: I ist eine KOORDINATE, kein Defekt. Sein Satz
117
+ // lautet "in Richtung Stabilitaet abhaengen", nicht "I klein halten" — ein Blattmodul mit
118
+ // I = 1.0 ist richtig, nicht kaputt. Damit fehlt MT-01 die Eigenschaft, die CR-SM-287 §2 von
119
+ // einer Steuerdimension verlangt: GERICHTET, "weniger ist besser, ohne Diskussion".
120
+ //
121
+ // Die Zahl bleibt vollstaendig erhalten — in jeder Modulzeile von `graph_metrics`, im Export
122
+ // und im gve-Dashboard, das den Zustand bereits rendert ("Instabilitaet wird hier nur
123
+ // gemessen"). Es entsteht nur kein Verstoss. graphcode faehrt das seit CR-GC-329 in seiner
124
+ // eigenen Config; dieser Default macht aus der Konfigurationszufaelligkeit eine Entscheidung.
125
+ instability: null,
88
126
  lcom4: { info: 4, warning: 6 },
89
127
  // CR-SM-236: die bisherigen Literale, jetzt an einer grep-baren Stelle.
90
128
  // `crossingFlows.warning = 3` ist die unveränderte Alt-Semantik: vorher `count > 2` → warning.
91
129
  crossingFlows: { warning: 3 },
130
+ // CR-SM-282: unveraenderte Alt-Semantik (`DECOMPOSITION_BREADTH_MAX = 11`, `> max` meldet).
131
+ // CR-SM-296: 7+-2 ist die Doktrin (`se:top-level`), 9 ist ihre Obergrenze. Bis hierher stand
132
+ // hier 11 -- gesetzt, nicht abgelesen. CR-SM-282 hatte gegen die Doktrin-Zahl 5 entschieden,
133
+ // weil `info` bei 5 den readiness-Nenner verwaessert haette; das Argument traegt fuer die
134
+ // OBERgrenze nicht, denn RD-04 meldet als `warning`. Die Zahl steht jetzt an EINER Stelle und
135
+ // gilt fuer beide Zerlegungsfragen -- Sub-FUNC und Sub-MOD.
136
+ decompositionBreadth: { warning: 9 },
137
+ // CR-SM-283: aus der Verteilung abgelesen — bok/gve max 3, graphcode 19, moneyflow 17.
138
+ boundaryWidth: { warning: 5 },
92
139
  riskRpn: 100,
93
140
  // `large`/`coupled`/`crossings` = die drei Literale aus `maxModuleSize`: vorher
94
141
  // `funcCount <= 8` → skip, `funcCount > 12` → groß, `crossings > 2` → gekoppelt.
95
- moduleSize: { large: 12, coupled: 8, crossings: 2 },
142
+ // CR-SM-296: an dieselbe Doktrin gebunden statt danebengesetzt. R-04 ist seit diesem CR ALLEIN
143
+ // fuer die Modulgroesse zustaendig (RD-04 hat ihr Allokations-Bein abgegeben), also gilt hier
144
+ // dieselbe 7+-2: `large` = 9 (Obergrenze), `coupled` = 7 (Untergrenze, ab der die Regel
145
+ // hinsieht). Vorher 12/8 -- zwei Zahlen fuer dieselbe Frage, unverbunden mit den 11 darueber.
146
+ moduleSize: { large: 9, coupled: 7, crossings: 2 },
96
147
  // CR-SM-229: kein Startwert möglich und keiner gewollt — die Tabelle steht nur im Handbook.
97
148
  // `null` heißt hier nicht „aus", sondern „markierter Übergang": bestätigte AP-Invarianten,
98
149
  // sonst RPN-Bänder. `apMethod()` macht das für den Leser sichtbar.
@@ -20,6 +20,24 @@ export declare function setBQ04SimilarityMatrix(data: {
20
20
  /**
21
21
  * BQ-04 checks for duplicate / near-duplicate requirements using
22
22
  * pre-computed embedding similarity. Returns [] when no matrix is set.
23
+ *
24
+ * CR-SM-286: **bewusst NICHT angeschlossen — anders als ND-01/ND-02.**
25
+ *
26
+ * Die Naht ist dieselbe und sie ist genauso tot: `setBQ04SimilarityMatrix()` ruft im gesamten
27
+ * Familienbaum niemand (CR-SM-278, erneut geprueft). Der Unterschied liegt in der Eingabe. ND-01
28
+ * und ND-02 nennen deterministische Formeln ueber Graphinhalt (Jaccard ueber Beschreibung,
29
+ * Verb, io-Topologie, Felder) — die konnten nach `similarity.ts` wandern und tun dort dasselbe.
30
+ * BQ-04 verlangt laut eigener Zeile "pre-computed EMBEDDING similarity", und Embeddings kann ein
31
+ * reines Vertragspaket nicht berechnen: kein Modell, kein Netz, kein Zufall.
32
+ *
33
+ * Ein Ersatzmass haette ich erfinden muessen. Ein Versuch mit 0.7*Beschreibung + 0.3*Name lief:
34
+ * **0 Befunde an allen neun Familiengraphen** und 4950 an einer templatierten Fixture — also
35
+ * genau die zwei Gate-7-Ausreisser zugleich ("0 Befunde am Selbstmodell" und "quadratisch mit
36
+ * der Graphgroesse"). Erfundene Gewichte ohne Messung sind keine Reparatur.
37
+ *
38
+ * Damit ist BQ-04 der naechste AO-D03-Fall: entweder eine Eingabe, die der Host liefern MUSS
39
+ * (dann gehoert die Regel nicht in ein reines Paket), oder streichen. Das ist eine
40
+ * Grammatik-Entscheidung — `se-grammar-review`, eigener CR, nicht hier nebenbei.
23
41
  */
24
42
  export declare function bq04Necessary(graph: OntologyGraph): RuleViolation[];
25
43
  export declare function bq06Conforming(graph: OntologyGraph): RuleViolation[];
@@ -1,3 +1,4 @@
1
+ import { normalizeReqKinds } from './ontology.js';
1
2
  // ---------------------------------------------------------------------------
2
3
  // Weasel words list (BQ-01)
3
4
  // ---------------------------------------------------------------------------
@@ -22,14 +23,37 @@ const measurablePattern = /(\d+[\s]*(ms|s|sec|min|%|percent|byte|MB|GB|times|x|s
22
23
  function reqElements(graph) {
23
24
  return graph.elements.filter(e => e.type === 'REQ');
24
25
  }
26
+ /**
27
+ * CR-SM-275: `description` ist im Zod-Schema Pflicht, aber die Regeln bekommen Graphen aus
28
+ * Store/Import ohne Re-Parse — dort fehlt das Feld. `req.description.trim()` warf dann
29
+ * `TypeError` und riss `evaluateAllRules` ab (gemessen am kadjar-Graphen, Spike CR-GC-438 §7).
30
+ * EIN Normalisierungspunkt statt eines Guards je Fundstelle: eine fehlende Beschreibung ist
31
+ * die leere Beschreibung — ein BEFUND (BQ-06/BQ-07 melden sie), kein Absturz.
32
+ */
33
+ /**
34
+ * CR-SM-285: `?? ''` faengt nur `null`/`undefined`. Ein Graph aus einer fremden Quelle (Import,
35
+ * fremdes Tool, handgeschriebene Fixture) kann `description` als Zahl, Objekt oder Array tragen —
36
+ * dann warf `.trim()` und `evaluateAllRules` STARB, statt zu urteilen. Am Gate heisst das:
37
+ * Stacktrace statt `block`-Verdict, der Aufrufer sieht kein Urteil.
38
+ *
39
+ * Gemessen vor dem Fix: `null` ok, `42`/`{}`/`[]`/`true` -> "descriptionOf(...).trim is not a
40
+ * function". Vier von fuenf Typen.
41
+ *
42
+ * Nicht-Strings werden zu `''` — also behandelt wie "keine Beschreibung". Das ist die richtige
43
+ * Deutung: ein Objekt IST keine Beschreibung, und die Regel soll das melden statt zu raten oder
44
+ * zu sterben.
45
+ */
46
+ function descriptionOf(el) {
47
+ return typeof el.description === 'string' ? el.description : '';
48
+ }
25
49
  // ---------------------------------------------------------------------------
26
50
  // BQ-01 Unambiguous — detect weasel words in REQ descriptions
27
51
  // ---------------------------------------------------------------------------
28
52
  export function bq01Unambiguous(graph) {
29
53
  return reqElements(graph)
30
- .filter(req => weaselPattern.test(req.description))
54
+ .filter(req => weaselPattern.test(descriptionOf(req)))
31
55
  .map(req => {
32
- const match = req.description.match(weaselPattern);
56
+ const match = descriptionOf(req).match(weaselPattern);
33
57
  return {
34
58
  rule_id: 'BQ-01',
35
59
  severity: 'warning',
@@ -49,7 +73,7 @@ export function bq01Unambiguous(graph) {
49
73
  // ---------------------------------------------------------------------------
50
74
  export function bq02Verifiable(graph) {
51
75
  return reqElements(graph)
52
- .filter(req => !measurablePattern.test(req.description))
76
+ .filter(req => !measurablePattern.test(descriptionOf(req)))
53
77
  .map(req => ({
54
78
  rule_id: 'BQ-02',
55
79
  severity: 'warning',
@@ -84,6 +108,24 @@ export function setBQ04SimilarityMatrix(data) {
84
108
  /**
85
109
  * BQ-04 checks for duplicate / near-duplicate requirements using
86
110
  * pre-computed embedding similarity. Returns [] when no matrix is set.
111
+ *
112
+ * CR-SM-286: **bewusst NICHT angeschlossen — anders als ND-01/ND-02.**
113
+ *
114
+ * Die Naht ist dieselbe und sie ist genauso tot: `setBQ04SimilarityMatrix()` ruft im gesamten
115
+ * Familienbaum niemand (CR-SM-278, erneut geprueft). Der Unterschied liegt in der Eingabe. ND-01
116
+ * und ND-02 nennen deterministische Formeln ueber Graphinhalt (Jaccard ueber Beschreibung,
117
+ * Verb, io-Topologie, Felder) — die konnten nach `similarity.ts` wandern und tun dort dasselbe.
118
+ * BQ-04 verlangt laut eigener Zeile "pre-computed EMBEDDING similarity", und Embeddings kann ein
119
+ * reines Vertragspaket nicht berechnen: kein Modell, kein Netz, kein Zufall.
120
+ *
121
+ * Ein Ersatzmass haette ich erfinden muessen. Ein Versuch mit 0.7*Beschreibung + 0.3*Name lief:
122
+ * **0 Befunde an allen neun Familiengraphen** und 4950 an einer templatierten Fixture — also
123
+ * genau die zwei Gate-7-Ausreisser zugleich ("0 Befunde am Selbstmodell" und "quadratisch mit
124
+ * der Graphgroesse"). Erfundene Gewichte ohne Messung sind keine Reparatur.
125
+ *
126
+ * Damit ist BQ-04 der naechste AO-D03-Fall: entweder eine Eingabe, die der Host liefern MUSS
127
+ * (dann gehoert die Regel nicht in ein reines Paket), oder streichen. Das ist eine
128
+ * Grammatik-Entscheidung — `se-grammar-review`, eigener CR, nicht hier nebenbei.
87
129
  */
88
130
  export function bq04Necessary(graph) {
89
131
  if (!_bq04Matrix)
@@ -140,7 +182,7 @@ const conformingPatternDE = /\b(soll|muss|darf nicht)\s+\w+/i;
140
182
  export function bq06Conforming(graph) {
141
183
  return reqElements(graph)
142
184
  .filter(req => {
143
- const desc = req.description.trim();
185
+ const desc = descriptionOf(req).trim();
144
186
  return !conformingPattern.test(desc) && !conformingPatternDE.test(desc);
145
187
  })
146
188
  .map(req => ({
@@ -162,20 +204,34 @@ export function bq06Conforming(graph) {
162
204
  const placeholderPattern = /\b(TBD|TBR|TODO|placeholder|to be determined)\b|needs\s.*review/i;
163
205
  const BQ07_MIN_DESC_LENGTH = 20;
164
206
  export function bq07Complete(graph) {
207
+ // CR-SM-266 REQ-X06: `kinds` ist Pflicht am REQ — hier als DRITTER Grund derselben Regel,
208
+ // bewusst ohne neue Regel-ID (Gate 6 des Grammatik-Reviews: eine ID kostet dauerhaft einen
209
+ // Nenner-Anteil, eine Katalogzeile, eine readiness-Zuordnung und einen Golden-File-Eintrag).
210
+ // BQ-07 heisst "Complete" und sammelt bereits mehrere Unvollstaendigkeits-Gruende in EINEN
211
+ // Befund; ein REQ ohne Klassifikation ist genau das — unvollstaendig, nicht falsch.
212
+ //
213
+ // Die DURCHSETZENDE Haelfte liegt woanders: `satisfiesPredicate` (meta-model.ts) lehnt jede
214
+ // satisfy-Kante auf ein REQ ohne `kinds` ab, weil dort nicht entscheidbar ist, ob sie
215
+ // zulaessig ist. Das ist die Fehlmessung und deshalb R-18/error; das blosse Fehlen der
216
+ // Angabe ist ein Vollstaendigkeitssignal und deshalb hier/warning — dieselbe Trennung, die
217
+ // CR-SM-262 fuer RC-06 begruendet hat.
218
+ const isIncomplete = (req) => descriptionOf(req).trim().length < BQ07_MIN_DESC_LENGTH ||
219
+ placeholderPattern.test(descriptionOf(req)) ||
220
+ normalizeReqKinds(req.kinds).length === 0;
165
221
  return reqElements(graph)
166
- .filter(req => {
167
- const tooShort = req.description.trim().length < BQ07_MIN_DESC_LENGTH;
168
- const hasPlaceholder = placeholderPattern.test(req.description);
169
- return tooShort || hasPlaceholder;
170
- })
222
+ .filter(isIncomplete)
171
223
  .map(req => {
224
+ const desc = descriptionOf(req);
172
225
  const reasons = [];
173
- if (req.description.trim().length < BQ07_MIN_DESC_LENGTH) {
174
- reasons.push(`description too short (${req.description.trim().length}/${BQ07_MIN_DESC_LENGTH} chars)`);
226
+ if (desc.trim().length < BQ07_MIN_DESC_LENGTH) {
227
+ reasons.push(`description too short (${desc.trim().length}/${BQ07_MIN_DESC_LENGTH} chars)`);
175
228
  }
176
- if (placeholderPattern.test(req.description)) {
229
+ if (placeholderPattern.test(desc)) {
177
230
  reasons.push('contains placeholder');
178
231
  }
232
+ if (normalizeReqKinds(req.kinds).length === 0) {
233
+ reasons.push('no kinds declared');
234
+ }
179
235
  return {
180
236
  rule_id: 'BQ-07',
181
237
  severity: 'warning',
@@ -9,30 +9,31 @@
9
9
  */
10
10
  import { z } from 'zod/v4';
11
11
  export declare const ReadinessDimension: z.ZodEnum<{
12
+ schema: "schema";
12
13
  req: "req";
13
14
  uc: "uc";
14
15
  arch: "arch";
15
16
  alloc: "alloc";
16
17
  ver: "ver";
17
- schema: "schema";
18
18
  cr: "cr";
19
19
  ms: "ms";
20
20
  }>;
21
21
  export type ReadinessDimensionType = z.infer<typeof ReadinessDimension>;
22
22
  export declare const ReadinessScore: z.ZodObject<{
23
23
  dimension: z.ZodEnum<{
24
+ schema: "schema";
24
25
  req: "req";
25
26
  uc: "uc";
26
27
  arch: "arch";
27
28
  alloc: "alloc";
28
29
  ver: "ver";
29
- schema: "schema";
30
30
  cr: "cr";
31
31
  ms: "ms";
32
32
  }>;
33
- score: z.ZodNumber;
33
+ score: z.ZodNullable<z.ZodNumber>;
34
34
  violations: z.ZodNumber;
35
35
  applicable: z.ZodNumber;
36
+ coreApplicable: z.ZodNumber;
36
37
  ready: z.ZodBoolean;
37
38
  }, z.core.$strip>;
38
39
  export type ReadinessScoreType = z.infer<typeof ReadinessScore>;
@@ -48,18 +49,19 @@ export type ReadinessScoreType = z.infer<typeof ReadinessScore>;
48
49
  export declare const ReadinessReport: z.ZodObject<{
49
50
  scores: z.ZodArray<z.ZodObject<{
50
51
  dimension: z.ZodEnum<{
52
+ schema: "schema";
51
53
  req: "req";
52
54
  uc: "uc";
53
55
  arch: "arch";
54
56
  alloc: "alloc";
55
57
  ver: "ver";
56
- schema: "schema";
57
58
  cr: "cr";
58
59
  ms: "ms";
59
60
  }>;
60
- score: z.ZodNumber;
61
+ score: z.ZodNullable<z.ZodNumber>;
61
62
  violations: z.ZodNumber;
62
63
  applicable: z.ZodNumber;
64
+ coreApplicable: z.ZodNumber;
63
65
  ready: z.ZodBoolean;
64
66
  }, z.core.$strip>>;
65
67
  timestamp: z.ZodISODateTime;
@@ -14,17 +14,39 @@ export const ReadinessDimension = z.enum([
14
14
  'arch', // Functional architecture (R-02, R-03, R-10, R-12)
15
15
  'alloc', // Module allocation (R-04)
16
16
  'ver', // Test coverage (R-01, R-05)
17
- 'schema', // Interface completeness (R-26 binding, SC-02/SC-04 usage)
17
+ 'schema', // Interface completeness (R-26 binding, SC-02 usage)
18
18
  'cr', // CR traceability (CR-R01..R03)
19
19
  'ms', // Milestone planning (MS-01..02)
20
20
  ]);
21
21
  export const ReadinessScore = z.object({
22
22
  dimension: ReadinessDimension,
23
- score: z.number().min(0).max(1), // 1 - (violations / applicable)
23
+ /**
24
+ * `1 - (violations / applicable)` — oder **`null`**, wenn die Dimension nicht messbar ist
25
+ * (CR-SM-270).
26
+ *
27
+ * `null` heisst nie 0 %, so wie schon bei `graph_metrics` (CR-GC-326): "a value that is not
28
+ * measurable is not zero percent". Der Anlass war die Gegenrichtung — ein Modell ohne einen
29
+ * einzigen Use Case meldete `uc: 0,997, ready: true`, weil 306 FUNC ueber eine einzige
30
+ * Fremdtyp-Regel (FC-03) den Nenner fuellten, waehrend die dreizehn Regeln, die wirklich Use
31
+ * Cases pruefen, nichts zu pruefen hatten und ihr SCHWEIGEN sich als Erfolg las. Der Score
32
+ * zeigte damit in die falsche Richtung: je mehr importierte FUNCs ein Repo ohne Wozu-Ebene
33
+ * hat, desto reifer sah seine uc-Readiness aus.
34
+ */
35
+ score: z.number().min(0).max(1).nullable(),
24
36
  violations: z.number().int(),
25
37
  applicable: z.number().int(),
38
+ /**
39
+ * CR-SM-270: die Kernmenge der Dimension — die Elemente der Typen, die die MEHRHEIT ihrer
40
+ * Regeln prueft (uc → UC/FCHAIN/ACTOR, arch → FUNC/MOD). Ist sie 0, ist `score` `null`.
41
+ *
42
+ * Sie steht im Bericht, weil sonst niemand das `null` erklaeren kann: `applicable` allein
43
+ * unterscheidet "nichts zu pruefen" (0) nicht von "nur Fremdtypen" (307). Genau die
44
+ * Unterscheidung, an der der dokumentierte Ausweg aus CR-SM-237 gescheitert ist.
45
+ */
46
+ coreApplicable: z.number().int(),
26
47
  // CR-SM-235: `score >= readyThreshold`. Die Schwelle steht bewusst NICHT hier — sie ist
27
48
  // Eingabe von `computeReadiness`, und eine Zahl im Kommentar wäre die dritte Meinung dazu.
49
+ // CR-SM-270: bei `score === null` ist `ready` immer `false` — nicht messbar ist nicht bereit.
28
50
  ready: z.boolean(),
29
51
  });
30
52
  /**
@@ -57,8 +79,7 @@ export const RULE_TO_DIMENSION = {
57
79
  // CR-SM-231: R-29 (Testdatei-Exklusivitaet) gehoert zu 'ver' wie R-19 — beide bewerten die
58
80
  // Evidenz-Bindung einer Abnahme, R-19 ihre Praesenz, R-29 ihre Eindeutigkeit.
59
81
  'R-29': 'ver',
60
- 'R-22': 'alloc', 'R-23': 'alloc', 'R-26': 'schema', 'R-27': 'arch',
61
- // CR-GC-366: R-30 (Wirkketten-Bindung) und R-31 (io-Verdrahtung) bewerten beide, ob ein
82
+ 'R-22': 'alloc', 'R-23': 'alloc', 'R-26': 'schema', // CR-GC-366: R-30 (Wirkketten-Bindung) und R-31 (io-Verdrahtung) bewerten beide, ob ein
62
83
  // Funktionsblock ueberhaupt im Bauplan haengt — dieselbe Dimension wie R-20 (realRef).
63
84
  // NICHT 'uc': R-14..R-17 fragen, ob ein Behaelter gefuellt ist;
64
85
  // diese beiden fragen von der FUNC aus, ob sie angeschlossen ist.
@@ -66,19 +87,19 @@ export const RULE_TO_DIMENSION = {
66
87
  // uc
67
88
  'UC-01': 'uc', 'UC-02': 'uc', 'UC-03': 'uc', 'UC-04': 'uc',
68
89
  'UC-05': 'uc', 'UC-06': 'uc',
69
- 'R-14': 'uc', 'R-15': 'uc', 'R-16': 'uc', 'R-17': 'uc',
90
+ 'R-15': 'uc', 'R-16': 'uc', 'R-17': 'uc',
70
91
  // FC-04 (CR-SM-226): FCHAIN actor-bounded (trigger+consumer) — same dimension as FC-01..03.
71
- 'FC-01': 'uc', 'FC-02': 'uc', 'FC-03': 'uc', 'FC-04': 'uc',
92
+ 'FC-02': 'uc', 'FC-03': 'uc', 'FC-04': 'uc',
72
93
  // arch
73
- 'R-02': 'arch', 'R-03': 'arch', 'R-10': 'arch', 'R-12': 'arch',
94
+ 'R-02': 'arch', 'R-10': 'arch', 'R-12': 'arch',
74
95
  // alloc
75
96
  'R-04': 'alloc',
76
97
  // ver
77
98
  'R-01': 'ver', 'R-05': 'ver',
78
99
  // schema
79
100
  'SC-02': 'schema', // SC-01/SC-03 deleted (BOK-CR-026) — R-26 is the binding rule
80
- // CR-SM-226: SC-04 sharp per-FLOW SCHEMA-binding check same dimension as SC-02.
81
- 'SC-04': 'schema',
101
+ // SC-04 entfiel mit CR-SM-271: FLOW ohne SCHEMA ist jetzt Grammatik (R-18-Bein, error)
102
+ // und zaehlt damit unter R-18/'arch' statt als eigene 'schema'-Zeile.
82
103
  // structural rules without primary dimension → assigned by closest concern
83
104
  'R-08': 'arch',
84
105
  // near-duplicate detection
@@ -88,12 +109,12 @@ export const RULE_TO_DIMENSION = {
88
109
  // rule (CR-SM-223) — a per-module advisory would depress this score permanently.
89
110
  'MT-01': 'alloc', 'MT-02': 'alloc',
90
111
  // CR traceability
91
- 'CR-R01': 'cr', 'CR-R02': 'cr', 'CR-R03': 'cr', 'CR-R04': 'cr',
92
- // architecture optimization
93
- 'AO-D01': 'arch', 'AO-D03': 'arch',
112
+ 'CR-R01': 'cr', 'CR-R02': 'cr', 'CR-R03': 'cr', // architecture optimization
113
+ // CR-SM-283: BW-02 (Whitebox-Randbreite) ersetzt AO-D03 an dieser Stelle — dieselbe
114
+ // Dimension, denn beide fragen nach der Struktur des Funktionsschnitts, nicht nach Evidenz.
115
+ 'BW-02': 'arch',
94
116
  // allocation rules (CR-191)
95
- 'CR-01': 'arch', 'RT-01': 'arch', 'PH-01': 'arch', 'CA-01': 'arch',
96
- // milestone planning
117
+ 'CR-01': 'arch', // milestone planning
97
118
  'MS-01': 'ms', 'MS-02': 'ms', 'MS-03': 'ms',
98
119
  // FMEA / risk
99
120
  'FM-01': 'req', 'FM-02': 'req', 'FM-03': 'ver',
@@ -139,7 +160,7 @@ export const RULE_TO_PHASE = {
139
160
  'BQ-01': 'SRR', 'BQ-02': 'SRR', 'BQ-04': 'SRR', 'BQ-06': 'SRR', 'BQ-07': 'SRR',
140
161
  'RD-01': 'SRR', 'RD-02': 'SRR', 'RD-03': 'SRR',
141
162
  'UC-01': 'SRR', 'UC-02': 'SRR', 'UC-03': 'SRR', 'UC-04': 'SRR', 'UC-05': 'SRR', 'UC-06': 'SRR',
142
- 'R-14': 'SRR', 'R-16': 'SRR', 'R-17': 'SRR',
163
+ 'R-16': 'SRR', 'R-17': 'SRR',
143
164
  'FC-02': 'SRR',
144
165
  'CL-01': 'SRR',
145
166
  'FM-01': 'SRR', 'FM-02': 'SRR',
@@ -147,21 +168,18 @@ export const RULE_TO_PHASE = {
147
168
  'MS-01': 'SRR', 'MS-02': 'SRR', 'MS-03': 'SRR',
148
169
  // PDR — architecture/functional completeness.
149
170
  'RD-04': 'PDR',
150
- 'R-02': 'PDR', 'R-03': 'PDR', 'R-08': 'PDR', 'R-10': 'PDR', 'R-12': 'PDR', 'R-18': 'PDR',
171
+ 'R-02': 'PDR', 'R-08': 'PDR', 'R-10': 'PDR', 'R-12': 'PDR', 'R-18': 'PDR',
151
172
  'R-04': 'PDR', 'R-22': 'PDR', 'R-23': 'PDR',
152
173
  'R-15': 'PDR',
153
- 'FC-01': 'PDR', 'FC-03': 'PDR', 'FC-04': 'PDR',
174
+ 'FC-03': 'PDR', 'FC-04': 'PDR',
154
175
  // CR-GC-366: Anschluss des Funktionsbaus — gehoert an dasselbe Gate wie R-15/IO-01,
155
176
  // die auf derselben Kette aufsetzen.
156
177
  'R-30': 'PDR', 'R-31': 'PDR',
157
178
  'MT-01': 'PDR', 'MT-02': 'PDR',
158
179
  'ND-01': 'PDR',
159
- 'AO-D01': 'PDR', 'AO-D03': 'PDR', 'CR-01': 'PDR', 'RT-01': 'PDR', 'PH-01': 'PDR', 'CA-01': 'PDR',
160
- 'IO-01': 'PDR', // CR-SM-226: extended to all FCHAIN FUNC-pairs, added to the phase axis.
161
- 'CR-R04': 'PDR',
180
+ 'BW-02': 'PDR', 'CR-01': 'PDR', 'IO-01': 'PDR', // CR-SM-226: extended to all FCHAIN FUNC-pairs, added to the phase axis.
162
181
  // CDR — critical design/schema completeness.
163
- 'R-26': 'CDR', 'R-27': 'CDR',
164
- 'SC-02': 'CDR', 'SC-04': 'CDR', // SC-04: FLOW→SCHEMA sharp rule (CR-SM-226)
182
+ 'R-26': 'CDR', 'SC-02': 'CDR', // SC-04 entfiel mit CR-SM-271 — der FLOW-ohne-SCHEMA-Fall haengt an R-18/PDR
165
183
  'ND-02': 'CDR',
166
184
  'NFR-01': 'CDR',
167
185
  // TRR — test readiness.
@@ -26,7 +26,6 @@ export declare const ViolationCandidate: z.ZodObject<{
26
26
  TEST: "TEST";
27
27
  MOD: "MOD";
28
28
  SCHEMA: "SCHEMA";
29
- SESSION: "SESSION";
30
29
  CR: "CR";
31
30
  MS: "MS";
32
31
  }>;
@@ -46,7 +45,6 @@ export declare const ViolationContext: z.ZodObject<{
46
45
  TEST: "TEST";
47
46
  MOD: "MOD";
48
47
  SCHEMA: "SCHEMA";
49
- SESSION: "SESSION";
50
48
  CR: "CR";
51
49
  MS: "MS";
52
50
  }>>;
@@ -64,7 +62,6 @@ export declare const ViolationContext: z.ZodObject<{
64
62
  TEST: "TEST";
65
63
  MOD: "MOD";
66
64
  SCHEMA: "SCHEMA";
67
- SESSION: "SESSION";
68
65
  CR: "CR";
69
66
  MS: "MS";
70
67
  }>;
@@ -79,11 +76,13 @@ export declare const ViolationContext: z.ZodObject<{
79
76
  verify: "verify";
80
77
  allocate: "allocate";
81
78
  relation: "relation";
82
- produces: "produces";
83
79
  }>;
84
80
  }, z.core.$strip>>>;
85
81
  parent_module: z.ZodOptional<z.ZodString>;
86
82
  current_description: z.ZodOptional<z.ZodString>;
83
+ also_affects: z.ZodOptional<z.ZodArray<z.ZodString>>;
84
+ value: z.ZodOptional<z.ZodNumber>;
85
+ threshold: z.ZodOptional<z.ZodNumber>;
87
86
  }, z.core.$strip>;
88
87
  export type ViolationContext = z.infer<typeof ViolationContext>;
89
88
  export declare const RuleViolation: z.ZodObject<{
@@ -108,7 +107,6 @@ export declare const RuleViolation: z.ZodObject<{
108
107
  TEST: "TEST";
109
108
  MOD: "MOD";
110
109
  SCHEMA: "SCHEMA";
111
- SESSION: "SESSION";
112
110
  CR: "CR";
113
111
  MS: "MS";
114
112
  }>>;
@@ -126,7 +124,6 @@ export declare const RuleViolation: z.ZodObject<{
126
124
  TEST: "TEST";
127
125
  MOD: "MOD";
128
126
  SCHEMA: "SCHEMA";
129
- SESSION: "SESSION";
130
127
  CR: "CR";
131
128
  MS: "MS";
132
129
  }>;
@@ -141,11 +138,13 @@ export declare const RuleViolation: z.ZodObject<{
141
138
  verify: "verify";
142
139
  allocate: "allocate";
143
140
  relation: "relation";
144
- produces: "produces";
145
141
  }>;
146
142
  }, z.core.$strip>>>;
147
143
  parent_module: z.ZodOptional<z.ZodString>;
148
144
  current_description: z.ZodOptional<z.ZodString>;
145
+ also_affects: z.ZodOptional<z.ZodArray<z.ZodString>>;
146
+ value: z.ZodOptional<z.ZodNumber>;
147
+ threshold: z.ZodOptional<z.ZodNumber>;
149
148
  }, z.core.$strip>>;
150
149
  }, z.core.$strip>;
151
150
  export type RuleViolation = z.infer<typeof RuleViolation>;