@sigloch/contracts 10.14.0 → 11.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/se/analysis-freshness-rules.d.ts +49 -15
- package/dist/se/analysis-freshness-rules.js +73 -37
- package/dist/se/ao-rules.js +3 -3
- package/dist/se/conformance-rules.d.ts +4 -0
- package/dist/se/conformance-rules.js +37 -32
- package/dist/se/cr-quality-rules.js +4 -76
- package/dist/se/evaluate-all.d.ts +5 -0
- package/dist/se/evaluate-all.js +2 -1
- package/dist/se/fchain-quality-rules.js +4 -4
- package/dist/se/fmea-rules.js +4 -4
- package/dist/se/format-e-parser.js +1 -1
- package/dist/se/grammar-snapshot.d.ts +6 -6
- package/dist/se/grammar-snapshot.js +90 -90
- package/dist/se/index.d.ts +3 -2
- package/dist/se/index.js +4 -2
- package/dist/se/metric-rules.d.ts +3 -0
- package/dist/se/metric-rules.js +3 -3
- 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 +23 -4
- package/dist/se/ontology.js +36 -14
- package/dist/se/quality-rules.js +5 -5
- package/dist/se/readiness.d.ts +45 -47
- package/dist/se/readiness.js +57 -120
- package/dist/se/rule-due.d.ts +35 -0
- package/dist/se/rule-due.js +83 -0
- package/dist/se/rule-help.d.ts +2 -0
- package/dist/se/rule-help.js +51 -21
- package/dist/se/rules.d.ts +18 -0
- package/dist/se/rules.js +112 -72
- package/dist/se/schema-quality-rules.d.ts +1 -1
- package/dist/se/schema-quality-rules.js +1 -1
- package/dist/se/uc-quality-rules.js +4 -4
- package/dist/se/view-rules.js +6 -4
- package/package.json +1 -1
package/dist/se/rule-help.js
CHANGED
|
@@ -65,8 +65,8 @@ export const RULE_HELP = {
|
|
|
65
65
|
prompt: "se-fmea",
|
|
66
66
|
},
|
|
67
67
|
'AF-05': {
|
|
68
|
-
plain: "
|
|
69
|
-
se: "
|
|
68
|
+
plain: "Parts of the model are not built yet and nobody has ordered the work → derive the build order.",
|
|
69
|
+
se: "Unbuilt elements exist (`TEST` / `FUNC` / `SCHEMA` without a binding, the exemptions of R-19/R-20/R-26 apply) and no `CR` has `status: open`. The plan is the set of open CRs, not a stamp; it falls due again with every change (CR-SM-395).",
|
|
70
70
|
prompt: "se-plan",
|
|
71
71
|
},
|
|
72
72
|
'BQ-01': {
|
|
@@ -102,6 +102,7 @@ export const RULE_HELP = {
|
|
|
102
102
|
plain: "Someone only ever uses the system in one way, which usually means their other situations are missing → describe the scenarios you left out.",
|
|
103
103
|
se: "`ACTOR` whose `UC`s cover fewer than 2 distinct `operatingMode`s — a ConOps completeness signal.",
|
|
104
104
|
prompt: "se-conops",
|
|
105
|
+
vorschlag: 'Ordne den Akteuren {n} Abläufe in mindestens zwei Betriebsarten zu.',
|
|
105
106
|
},
|
|
106
107
|
'CR-01': {
|
|
107
108
|
plain: "Two parts exchange an unusually large amount of data, which usually means the boundary is in the wrong place → reconsider the cut.",
|
|
@@ -111,19 +112,17 @@ export const RULE_HELP = {
|
|
|
111
112
|
'CR-R01': {
|
|
112
113
|
plain: "A change is recorded but says nothing about what it changes → link it to what it touches.",
|
|
113
114
|
se: "`CR` with no `relation` traces. It tracks nothing, so it is not traceable evidence.",
|
|
115
|
+
vorschlag: 'Verbinde die Änderungsaufträge {n} mit dem, was sie ändern.',
|
|
114
116
|
},
|
|
115
117
|
'CR-R02': {
|
|
116
118
|
plain: "A change is marked finished but there is no commit proving it → record the commit, or set it back to open.",
|
|
117
119
|
se: "`CR` with `status:done` and no `commitRef` attribute. This is the graph-vs-reality check for change history: \"done\" without evidence.",
|
|
120
|
+
vorschlag: 'Trage bei den erledigten Änderungsaufträgen {n} den Commit nach.',
|
|
118
121
|
},
|
|
119
122
|
'CR-R03': {
|
|
120
123
|
plain: "Several open changes touch the same thing, so they will collide → sequence them or merge them.",
|
|
121
124
|
se: "One element tracked by more than one `CR` with `status` open/in-progress.",
|
|
122
|
-
|
|
123
|
-
'CR-R05': {
|
|
124
|
-
plain: "This smallest-piece requirement has no work order — no change request points at it or at the function that fulfils it, and that function is not built yet, so no plan will ever build it → attach it to the change request that builds it.",
|
|
125
|
-
se: "Leaf `REQ` (no `compose`→`REQ` children) with no build order: no `CR -relation->` on the REQ itself nor on a `FUNC` that `satisfy`s it (CR-SM-343; the REQ side of CR-R01). A `FUNC` that is already built — valid `realRef` or `external`, not `concept` — covers the REQ without a CR (CR-SM-375). A CR on a `MOD`/`SYS` carrier does not count — a module is a container; such REQs take a direct `CR -relation-> REQ`. Silent, and not scored, on a graph without any `CR` node (`RULE_PRECONDITION`).",
|
|
126
|
-
prompt: "se-plan",
|
|
125
|
+
vorschlag: 'Kläre, welcher der offenen Änderungsaufträge an {n} zuerst ändert.',
|
|
127
126
|
},
|
|
128
127
|
'FC-02': {
|
|
129
128
|
plain: "A scenario that is not broken into sub-scenarios has no described sequence of steps → add one, even if the steps are done by hand.",
|
|
@@ -150,16 +149,19 @@ export const RULE_HELP = {
|
|
|
150
149
|
plain: "A requirement is marked as a risk but carries no risk ratings → rate how bad, how likely and how detectable it is (1-10 each).",
|
|
151
150
|
se: "`REQ` with `role:\"risk\"` missing `severity` / `occurrence` / `detection` attributes (AIAG-VDA). The role is the requirement's motivation, not its kind — satisfy-neutral (CR-SM-365).",
|
|
152
151
|
prompt: "se-fmea",
|
|
152
|
+
vorschlag: 'Bewerte die Risiken {n} nach Schwere, Auftreten und Entdeckung.',
|
|
153
153
|
},
|
|
154
154
|
'FM-02': {
|
|
155
155
|
plain: "A known risk has nothing planned against it → write the countermeasure as its own requirement.",
|
|
156
156
|
se: "`REQ` with `role:\"risk\"` and no `compose`d `REQ` with `role:\"mitigation\"`. The mitigation keeps its own kind (functional or non-functional) and is satisfied like any REQ of that kind (CR-SM-365).",
|
|
157
157
|
prompt: "se-fmea",
|
|
158
|
+
vorschlag: 'Gib den Risiken {n} eine Gegenmaßnahme.',
|
|
158
159
|
},
|
|
159
160
|
'FM-03': {
|
|
160
161
|
plain: "A high risk has no test that actually passed → add a test proving the countermeasure works.",
|
|
161
162
|
se: "`REQ` with `role:\"risk\"`, Action Priority High (AIAG-VDA, RPN band as interim) and no verifying `TEST` whose every `testRefs` entry has `result:\"passed\"`.",
|
|
162
163
|
prompt: "se-fmea",
|
|
164
|
+
vorschlag: 'Gib den hohen Risiken {n} einen Test.',
|
|
163
165
|
},
|
|
164
166
|
'IO-01': {
|
|
165
167
|
plain: "Two steps in the same sequence have no described data passing between them → add the data one hands to the other.",
|
|
@@ -174,10 +176,12 @@ export const RULE_HELP = {
|
|
|
174
176
|
'MS-01': {
|
|
175
177
|
plain: "A milestone has no work assigned to it → assign the work items that belong to it.",
|
|
176
178
|
se: "`MS` with no `CR` `relation`.",
|
|
179
|
+
vorschlag: 'Ordne den Meilensteinen {n} ihren Umfang zu.',
|
|
177
180
|
},
|
|
178
181
|
'MS-02': {
|
|
179
182
|
plain: "A milestone waits on another milestone that doesn't exist → fix or remove the dependency.",
|
|
180
183
|
se: "`MS` `depends-on` relation targeting a missing `MS`.",
|
|
184
|
+
vorschlag: 'Korrigiere die Abhängigkeiten der Meilensteine {n}.',
|
|
181
185
|
},
|
|
182
186
|
'MS-03': {
|
|
183
187
|
plain: "A change is not assigned to any milestone, so it has no place in the plan → assign it.",
|
|
@@ -236,8 +240,14 @@ export const RULE_HELP = {
|
|
|
236
240
|
vorschlag: 'Ordne die Tests {n} den Anforderungen zu, die sie prüfen.',
|
|
237
241
|
},
|
|
238
242
|
'R-32': {
|
|
239
|
-
plain: "A data
|
|
240
|
-
se: "`SCHEMA` with
|
|
243
|
+
plain: "A data format is defined but no test exercises it as a contract → add a test that tries every variant, including the ones it must reject, and link it to the schema.",
|
|
244
|
+
se: "`SCHEMA` with no `TEST -verify-> SCHEMA` — every SCHEMA, bound or not (CR-SM-396; until then only those with a symbol `realRef`). RC-04 checks the parse at the boundary; this checks the contract test (CR-SM-319).",
|
|
245
|
+
vorschlag: 'Gib den Datenformaten {n} einen Vertragstest.',
|
|
246
|
+
},
|
|
247
|
+
'R-33': {
|
|
248
|
+
plain: "The model has no system yet — nothing says what is being built and where it ends → name the system.",
|
|
249
|
+
se: "No `SYS` element in the graph: the existence rule of stage 1. Everything else is composed below the system (CR-SM-395).",
|
|
250
|
+
vorschlag: 'Lege zuerst das System an und benenne, was gebaut wird.',
|
|
241
251
|
},
|
|
242
252
|
'R-08': {
|
|
243
253
|
plain: "A link points at something that no longer exists → repair or remove the broken link.",
|
|
@@ -265,8 +275,8 @@ export const RULE_HELP = {
|
|
|
265
275
|
vorschlag: 'Verbinde den Nutzer {n} über Datenflüsse mit den Funktionen.',
|
|
266
276
|
},
|
|
267
277
|
'R-17': {
|
|
268
|
-
plain: "
|
|
269
|
-
se: "`SYS` with no `compose` to `UC
|
|
278
|
+
plain: "Nothing says yet who uses the system for what → add the main use cases.",
|
|
279
|
+
se: "`SYS` with no `compose` to a `UC`: the existence rule of stage 2. Requirements or modules below the system do not stand in for a use case (CR-SM-396).",
|
|
270
280
|
vorschlag: 'Lege die Abläufe des Systems {n} an.',
|
|
271
281
|
},
|
|
272
282
|
'R-18': {
|
|
@@ -275,12 +285,16 @@ export const RULE_HELP = {
|
|
|
275
285
|
vorschlag: 'Korrigiere die unzulässigen Verbindungen an {n}.',
|
|
276
286
|
},
|
|
277
287
|
'R-19': {
|
|
278
|
-
plain: "
|
|
279
|
-
se: "
|
|
288
|
+
plain: "Building has started, and a test doesn't point to a test file yet → add the link to the test file.",
|
|
289
|
+
se: "`TEST` with no valid `testRefs` `[{file, case?, tool}, …]` (at least one entry)." +
|
|
290
|
+
" Stage 11: due only once the build is open — an open CR or a first `realRef`/`testRefs` in the graph; before that it is not evaluated, not passed (CR-SM-395).",
|
|
291
|
+
vorschlag: 'Verbinde die Tests {n} mit ihren Testdateien.',
|
|
280
292
|
},
|
|
281
293
|
'R-20': {
|
|
282
|
-
plain: "
|
|
283
|
-
se: "
|
|
294
|
+
plain: "Building has started, and a function doesn't point to its code yet → add the link to its code; or mark it as coming from an outside library.",
|
|
295
|
+
se: "`FUNC` with no valid `realRef` `{file, symbol}` (graph↔code binding); else `external:true`." +
|
|
296
|
+
" Stage 11: due only once the build is open — an open CR or a first `realRef`/`testRefs` in the graph; before that it is not evaluated, not passed (CR-SM-395).",
|
|
297
|
+
vorschlag: 'Verbinde die Funktionen {n} mit ihrem Code.',
|
|
284
298
|
},
|
|
285
299
|
'R-21': {
|
|
286
300
|
plain: "Two functions hand data over, but they are not in one chain together — or they are, and the chain is not covered: some function in it has no requirement, and no end-to-end test checks the chain → give each function of the chain a requirement it fulfils, or give the chain an end-to-end quality requirement and a test for it.",
|
|
@@ -298,12 +312,15 @@ export const RULE_HELP = {
|
|
|
298
312
|
vorschlag: 'Gib den Modulen {n} Funktionen oder entferne sie.',
|
|
299
313
|
},
|
|
300
314
|
'R-26': {
|
|
301
|
-
plain: "
|
|
302
|
-
se: "
|
|
315
|
+
plain: "Building has started, and a data format in the model isn't linked to the schema code that defines it yet → link it to the schema (or mark it as defined outside).",
|
|
316
|
+
se: "`SCHEMA` with no valid `realRef` `{file, symbol}` (graph↔Zod binding); else `external:true` (CR-211/228)." +
|
|
317
|
+
" Stage 11: due only once the build is open — an open CR or a first `realRef`/`testRefs` in the graph; before that it is not evaluated, not passed (CR-SM-395).",
|
|
318
|
+
vorschlag: 'Verbinde die Datenformate {n} mit ihrem Schema im Code.',
|
|
303
319
|
},
|
|
304
320
|
'R-29': {
|
|
305
321
|
plain: "Two acceptances claim the same test file, so a red run cannot be traced to one of them and the gate counts that evidence twice → give the file to the one acceptance it really proves, or split it.",
|
|
306
322
|
se: "Test file exclusivity (CR-SM-231): every file in `attributes.testRefs` belongs to at most one `TEST`. An acceptance may name n files (1:n) — a file may not name n acceptances. Severity `error`, deliberately sharper than R-19/R-20: a doubly claimed file makes gate numbers wrong, which is a mis-measurement, not a completeness signal. Purely structural — the file need not exist to be claimed twice.",
|
|
323
|
+
vorschlag: 'Gib jede Testdatei von {n} nur einem Test.',
|
|
307
324
|
},
|
|
308
325
|
'R-30': {
|
|
309
326
|
plain: "This function sits in no chain of effects, so nobody can say which use case it serves — and the checks that would prove its wiring never look at it → add it to the chain of the use case it belongs to.",
|
|
@@ -318,42 +335,52 @@ export const RULE_HELP = {
|
|
|
318
335
|
'RC-01': {
|
|
319
336
|
plain: "A function points to code that isn't there anymore (file moved or name changed) → repoint it to the current code.",
|
|
320
337
|
se: "FUNC `realRef` that does not resolve: file missing on disk or symbol not declared in it (CR-GC-253 conformance over CodeFacts).",
|
|
338
|
+
vorschlag: 'Korrigiere die Code-Verweise der Funktionen {n}, sie zeigen ins Leere.',
|
|
321
339
|
},
|
|
322
340
|
'RC-02': {
|
|
323
341
|
plain: "A test points to a test file or test name that isn't there anymore → repoint it to the current test.",
|
|
324
342
|
se: "A `testRefs` entry that does not resolve: file missing or `case` not declared as an it/test/describe (CR-GC-253). The message names the concrete path — with n entries the node id alone is not actionable.",
|
|
343
|
+
vorschlag: 'Korrigiere die Testverweise von {n}, die Testfälle gibt es nicht.',
|
|
325
344
|
},
|
|
326
345
|
'RC-03': {
|
|
327
346
|
plain: "A data format points to schema code that isn't there anymore (file moved or export renamed) → repoint it to the current schema.",
|
|
328
347
|
se: "SCHEMA `realRef` that does not resolve: file missing on disk or symbol not a declared export in it (CR-211/228 conformance over CodeFacts).",
|
|
348
|
+
vorschlag: 'Korrigiere die Code-Verweise der Datenformate {n}, sie zeigen ins Leere.',
|
|
329
349
|
},
|
|
330
350
|
'RC-04': {
|
|
331
351
|
plain: "A data format is defined but the function on that interface never actually checks incoming data against it → validate with it there.",
|
|
332
352
|
se: "Bound `SCHEMA` whose symbol is not imported+parsed (`.parse`/`.safeParse`) in any realized `FUNC` io-connected to it (CR-211); warn — the parse may sit in a framework layer.",
|
|
353
|
+
vorschlag: 'Lies die Datenformate {n} im Code an der Schnittstelle, an der das Modell sie führt.',
|
|
333
354
|
},
|
|
334
355
|
'RC-05': {
|
|
335
356
|
plain: "Code in one building block imports code in another, but the model never says those two are connected → draw the connection in the model, or drop the import.",
|
|
336
357
|
se: "File import crossing a `MOD` boundary with no documenting graph structure (no io/FLOW between the modules) — undocumented cross-module dependency (CR-212); warn indicator, not a blocker.",
|
|
358
|
+
vorschlag: 'Trage die Abhängigkeit der Module {n} ins Modell ein oder entferne den Import.',
|
|
337
359
|
},
|
|
338
360
|
'RC-06': {
|
|
339
361
|
plain: "This element points at code in a package your project does not actually install → either add the package, or point at the one that owns the symbol now.",
|
|
340
362
|
se: "An `external: true` `realRef` names a package that is in neither `dependencies` nor `devDependencies` of the consumer. Absent dependency data is SILENCE, not a violation — the extractor never looked, and treating that as \"declares nothing\" would report every external binding at once (CR-SM-262).",
|
|
363
|
+
vorschlag: 'Trage die Pakete, auf die {n} verweisen, als Abhängigkeit ein.',
|
|
341
364
|
},
|
|
342
365
|
'RC-07': {
|
|
343
366
|
plain: "A change request is marked done in the model but still open in the folder (or the other way round), or an open change request has no entry in the model → the folder decides; fix the model.",
|
|
344
367
|
se: "`CR` node whose `status` (closed = done; CR-SM-362) contradicts `docs/cr/open|done/`, or an OPEN CR file with no `CR` node (anchored at the first `SYS`). Nodes without a file are not reported — history. Absent `crFiles` is SILENCE (CR-SM-329).",
|
|
368
|
+
vorschlag: 'Gleiche die Änderungsaufträge {n} mit ihren Dateien ab.',
|
|
345
369
|
},
|
|
346
370
|
'RC-08': {
|
|
347
371
|
plain: "A data contract in the model points at a type, which vanishes at runtime → write it as a Zod schema, so whoever produces the data can prove it and whoever reads it can check it.",
|
|
348
372
|
se: "`SCHEMA` whose `realRef` symbol is declared but is not a Zod schema (extractor field `zodSymbols`). Every producer needs a checkable schema — \"nobody parses it\" only means the reader is not known yet. Absent `zodSymbols` is SILENCE. Owns the type-binding cause: RC-04 stays quiet on such a SCHEMA (CR-SM-358).",
|
|
373
|
+
vorschlag: 'Binde die Datenformate {n} an ein Schema statt an einen Typ.',
|
|
349
374
|
},
|
|
350
375
|
'RC-09': {
|
|
351
376
|
plain: "Code somewhere reads a data contract on its own, but the model does not know that place → go through the one translator the model names, or add the new translator to the model.",
|
|
352
377
|
se: "Zod-bound `SCHEMA` parsed (import + `.parse`/`.safeParse`) in a file that is neither its definition nor the `realRef` of a `FUNC` io-connected to a `FLOW` of this SCHEMA. The first code → model check: a second translator of one contract is a parallel path (spike CR-GC-637 — such paths share a contract, they are not similar). One finding per SCHEMA; test files exempt; runs only with `fileScope: 'all'` (CR-SM-358).",
|
|
378
|
+
vorschlag: 'Prüfe, wo die Datenformate {n} außerhalb ihrer Schnittstelle gelesen werden.',
|
|
353
379
|
},
|
|
354
380
|
'RC-10': {
|
|
355
381
|
plain: "No file in the code can be assigned to this building block, so nobody can check whether its imports cross boundaries the model does not know → give the block its source folder, or point one of its functions at its code.",
|
|
356
|
-
se: "`MOD` with neither a `path` attribute nor an allocated `FUNC` carrying a bound `realRef` — the only two ways a file resolves to a module. Without either, RC-05 and the boundary measurement are blind for this module by construction (sigllm: 0 RC-05 findings at 19 % import coverage, 8 at 81 %). The message names the cost from `importCoverage`. `
|
|
382
|
+
se: "`MOD` with neither a `path` attribute nor an allocated `FUNC` carrying a bound `realRef` — the only two ways a file resolves to a module. Without either, RC-05 and the boundary measurement are blind for this module by construction (sigllm: 0 RC-05 findings at 19 % import coverage, 8 at 81 %). The message names the cost from `importCoverage`. `external` modules are exempt, as for R-20 (CR-SM-344). Stage 11: due only once the build is open — an open CR or a first `realRef`/`testRefs` in the graph; before that it is not evaluated, not passed (CR-SM-395).",
|
|
383
|
+
vorschlag: 'Gib den Modulen {n} ihren Quellordner.',
|
|
357
384
|
},
|
|
358
385
|
'RD-01': {
|
|
359
386
|
plain: "A smallest-piece feature has nothing built to fulfil it → add what implements it.",
|
|
@@ -408,15 +435,18 @@ export const RULE_HELP = {
|
|
|
408
435
|
plain: "A test exists but no result was ever recorded, so nobody knows if it passed → record the outcome.",
|
|
409
436
|
se: "`TEST` with no `testResult` attribute — assumed pending, never assumed green.",
|
|
410
437
|
},
|
|
411
|
-
// CR-SM-355:
|
|
438
|
+
// CR-SM-355: die Ausgaenge von Variantenvergleich und Annahmen-Review. Sie melden erst, wenn die
|
|
439
|
+
// Analyse gestempelt ist — vorher schweigen sie von selbst (CR-SM-395).
|
|
412
440
|
'TR-01': {
|
|
413
441
|
plain: "The trade study is stamped, but the decision it produced is not on record as a CR (or the CR it names is missing or carries no decides edge) → record the decision as a CR and list its id in the stamp.",
|
|
414
442
|
se: "Task outcome rule (CR-SM-355): `analysisFreshness.trade.crRefs` names existing CR elements, each carrying a `relation` edge labelled `decides` (the SP-1 decision record).",
|
|
415
443
|
prompt: "se-trade",
|
|
444
|
+
vorschlag: 'Halte die Entscheidung des Variantenvergleichs für {n} als Änderungsauftrag fest.',
|
|
416
445
|
},
|
|
417
446
|
'IR-01': {
|
|
418
|
-
plain: "The assumption review names a
|
|
419
|
-
se: "Task outcome rule (CR-SM-355): every id in `analysisFreshness.assumption-review.
|
|
447
|
+
plain: "The assumption review names a requirement that does not exist → fix the reference or add the requirement with its test; an empty list is fine when no assumption was load-bearing.",
|
|
448
|
+
se: "Task outcome rule (CR-SM-355, CR-SM-397): every id in `analysisFreshness.assumption-review.reqRefs` resolves to a `REQ` element; empty is a legitimate outcome (low-risk assumptions stay in the record). The verifying `TEST` is R-01's finding. An analysis leaves requirements, never a build order.",
|
|
420
449
|
prompt: "se-irr",
|
|
450
|
+
vorschlag: 'Lege die Anforderungen an, die das Annahmen-Review für {n} nennt.',
|
|
421
451
|
},
|
|
422
452
|
};
|
package/dist/se/rules.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { z } from 'zod/v4';
|
|
7
7
|
import type { OntologyGraph } from './ontology.js';
|
|
8
8
|
import type { MetricPolicy } from './policy.js';
|
|
9
|
+
import type { RuleRole, RuleStage } from './readiness.js';
|
|
9
10
|
export declare const RuleSeverity: z.ZodEnum<{
|
|
10
11
|
error: "error";
|
|
11
12
|
info: "info";
|
|
@@ -306,6 +307,14 @@ export interface RuleDefinition {
|
|
|
306
307
|
id: string;
|
|
307
308
|
name: string;
|
|
308
309
|
severity: 'error' | 'warning' | 'info';
|
|
310
|
+
/**
|
|
311
|
+
* CR-SM-395: die STUFE — die spaeteste Menge, die die Regel braucht (`STAGE_SETS`), oder `'immer'`.
|
|
312
|
+
* Aus ihr folgen Rang und Marke (`markOfStage`); es gibt keine zweite Zuordnung. Pflichtfeld: ein
|
|
313
|
+
* Regeleintrag ohne Stufe bricht den Build.
|
|
314
|
+
*/
|
|
315
|
+
stage: RuleStage;
|
|
316
|
+
/** CR-SM-395: `existence` | `analysis` — oder nichts. */
|
|
317
|
+
role?: RuleRole;
|
|
309
318
|
/**
|
|
310
319
|
* CR-SM-236: `policy` steht jeder Regel zur Verfuegung, damit eine Urteilsschwelle nirgends
|
|
311
320
|
* als Literal im Regelcode zurueckbleibt. Regeln ohne Schwelle deklarieren den Parameter
|
|
@@ -369,6 +378,15 @@ export declare function decomposedFuncs(graph: OntologyGraph): Set<string>;
|
|
|
369
378
|
* die zweite Wahrheit, die CR-SM-286/-302 beseitigt haben.
|
|
370
379
|
*/
|
|
371
380
|
export declare function flowProducers(graph: OntologyGraph): Map<string, Set<string>>;
|
|
381
|
+
/** Der Anker eines Befunds an einem Graphen ohne SYS — kein Element traegt diese Id. */
|
|
382
|
+
export declare const GRAPH_ANCHOR = "graph";
|
|
383
|
+
/**
|
|
384
|
+
* CR-SM-395: das UNGEBAUTE — die Elemente, an denen die Praesenzregeln der Bindung melden wuerden
|
|
385
|
+
* (R-19 TEST, R-20 FUNC, R-26 SCHEMA), unabhaengig davon, ob sie schon faellig sind. EINE
|
|
386
|
+
* Definition samt Ausnahmen (`external`, Zerlegungs-Eltern mit gebundenen Kindern): AF-05 fragt
|
|
387
|
+
* damit „gibt es etwas zu bauen?", ohne die Ausnahmen ein zweites Mal zu schreiben.
|
|
388
|
+
*/
|
|
389
|
+
export declare function unbuiltElementIds(graph: OntologyGraph): string[];
|
|
372
390
|
export declare const V3_RULES: RuleDefinition[];
|
|
373
391
|
/** Run all rules against a graph. CR-SM-236: `policy` ist Pflicht — wie bei `evaluateAllRules`. */
|
|
374
392
|
export declare function evaluateRules(graph: OntologyGraph, policy: MetricPolicy): RuleViolation[];
|
package/dist/se/rules.js
CHANGED
|
@@ -7,6 +7,7 @@ import { z } from 'zod/v4';
|
|
|
7
7
|
import { ElementType, TraceType, readTestRefs, readRealRef } from './ontology.js';
|
|
8
8
|
import { traceRejection, admittingAlternatives, isValidTrace, BOUNDED_PATTERNS, REQUIRED_PATTERNS, maxOccurs } from './meta-model.js';
|
|
9
9
|
import { indexOf } from './graph-index.js';
|
|
10
|
+
import { whenDue } from './rule-due.js';
|
|
10
11
|
import { moduleCrossings, subtreeFuncs } from './module-crossings.js';
|
|
11
12
|
import { functionCriticality, chainsByFunc } from './function-criticality.js';
|
|
12
13
|
export const RuleSeverity = z.enum(['error', 'warning', 'info']);
|
|
@@ -200,6 +201,10 @@ elements, ref) {
|
|
|
200
201
|
}
|
|
201
202
|
// ---------------------------------------------------------------------------
|
|
202
203
|
// R-01: Every REQ must have at least one verify trace
|
|
204
|
+
//
|
|
205
|
+
// CR-SM-393: wieder genau das. CR-SM-391 hatte einen zweiten Befund angehaengt (Nicht-Konzept-REQ
|
|
206
|
+
// braucht einen Nicht-Konzept-TEST); mit dem Attribut `concept` ist sein Gegenstand entfallen.
|
|
207
|
+
// Ob der verifizierende TEST an eine Datei gebunden ist, fragt R-19 — ab Beginn der Realisierung.
|
|
203
208
|
// ---------------------------------------------------------------------------
|
|
204
209
|
function reqMustHaveVerification(graph) {
|
|
205
210
|
const idx = indexOf(graph);
|
|
@@ -845,19 +850,24 @@ function actorMustHaveTrace(graph) {
|
|
|
845
850
|
}));
|
|
846
851
|
}
|
|
847
852
|
// ---------------------------------------------------------------------------
|
|
848
|
-
// R-17: SYS must have at least
|
|
853
|
+
// R-17: SYS must have at least one use case (CR-117; neu gefasst CR-SM-396).
|
|
854
|
+
//
|
|
855
|
+
// Die Existenz-Regel der Stufe 2. Bis CR-SM-396 schwieg sie, sobald das SYS IRGENDETWAS komponierte
|
|
856
|
+
// (UC, REQ oder MOD) — ein Code-Import (SYS -compose-> MOD, kein UC) las damit SRR als erreicht,
|
|
857
|
+
// „0 von 0" an der Stufe Anwendungsfall. Verlangt ist der Anwendungsfall selbst: `SYS -compose-> UC`
|
|
858
|
+
// (im Meta-Modell `1..*`). Ein UC, der nicht am System haengt, genuegt nicht.
|
|
849
859
|
// ---------------------------------------------------------------------------
|
|
850
|
-
function
|
|
860
|
+
function sysMustHaveUseCase(graph) {
|
|
851
861
|
const idx = indexOf(graph);
|
|
852
862
|
const systems = idx.elementsOfType('SYS');
|
|
853
863
|
return systems
|
|
854
|
-
.filter(sys => idx.out(sys.id, 'compose').
|
|
864
|
+
.filter(sys => !idx.out(sys.id, 'compose').some(t => idx.typeOf(t.target) === 'UC'))
|
|
855
865
|
.map(sys => ({
|
|
856
866
|
rule_id: 'R-17',
|
|
857
867
|
severity: 'warning',
|
|
858
868
|
element_id: sys.id,
|
|
859
|
-
message: `${sys.id} has no
|
|
860
|
-
fix_hint:
|
|
869
|
+
message: `${sys.id} has no use case (no SYS -compose-> UC)`,
|
|
870
|
+
fix_hint: `Add at least one UC and a compose trace from ${sys.id} to it — a use case says who uses the system for what`,
|
|
861
871
|
context: {
|
|
862
872
|
element_type: sys.type,
|
|
863
873
|
element_name: sys.name,
|
|
@@ -1132,19 +1142,18 @@ function cardinalityViolations(graph) {
|
|
|
1132
1142
|
return violations;
|
|
1133
1143
|
}
|
|
1134
1144
|
// ---------------------------------------------------------------------------
|
|
1135
|
-
// R-19: Runnable TEST binding (CR-GC-205 Item 4) — a TEST
|
|
1136
|
-
//
|
|
1137
|
-
//
|
|
1138
|
-
//
|
|
1139
|
-
//
|
|
1140
|
-
//
|
|
1141
|
-
//
|
|
1142
|
-
//
|
|
1145
|
+
// R-19: Runnable TEST binding (CR-GC-205 Item 4) — a TEST should carry a valid testRefs
|
|
1146
|
+
// runnable binding so the deduced selective test set is trustworthy. WARNING (a completeness
|
|
1147
|
+
// signal like R-05, not a hard gate). File EXISTENCE is out of scope here (rules are pure, no
|
|
1148
|
+
// I/O — that is RC-02); this guards presence/shape only.
|
|
1149
|
+
//
|
|
1150
|
+
// CR-SM-393: keine Ausnahme je Element mehr (`concept` ist entfallen). „Noch nicht faellig" ist
|
|
1151
|
+
// eine Eigenschaft des Graphen: die Regel ist Stufe 11 und erst faellig, wenn der Bau eroeffnet
|
|
1152
|
+
// ist (`isDue`, CR-SM-395).
|
|
1143
1153
|
// ---------------------------------------------------------------------------
|
|
1144
1154
|
function testMustHaveRunnableBinding(graph) {
|
|
1145
1155
|
const idx = indexOf(graph);
|
|
1146
1156
|
return idx.elementsOfType('TEST')
|
|
1147
|
-
.filter(e => e.attributes?.concept !== true) // concept-only TESTs are exempt
|
|
1148
1157
|
// CR-SM-231: `testRefs` (Array, min 1) statt `testRef` (Objekt). Semantik unveraendert —
|
|
1149
1158
|
// Praesenz und Form, keine Datei-Existenz; die pruefst RC-02.
|
|
1150
1159
|
.filter(e => readTestRefs(e.attributes).state !== 'bound')
|
|
@@ -1153,7 +1162,7 @@ function testMustHaveRunnableBinding(graph) {
|
|
|
1153
1162
|
severity: 'warning',
|
|
1154
1163
|
element_id: test.id,
|
|
1155
1164
|
message: `${test.id} is a runnable TEST without a valid testRefs binding`,
|
|
1156
|
-
fix_hint: 'Add attributes.testRefs [{file, case?, tool, level?}, …] with at least one entry
|
|
1165
|
+
fix_hint: 'Add attributes.testRefs [{file, case?, tool, level?}, …] with at least one entry',
|
|
1157
1166
|
context: { element_type: test.type, element_name: test.name },
|
|
1158
1167
|
}));
|
|
1159
1168
|
}
|
|
@@ -1212,8 +1221,8 @@ function testFileExclusivity(graph) {
|
|
|
1212
1221
|
}
|
|
1213
1222
|
// ---------------------------------------------------------------------------
|
|
1214
1223
|
// R-20: FUNC realRef binding (CR-GC-205 Item 5, extended by CR-210, unified CR-228)
|
|
1215
|
-
// — a FUNC that is not
|
|
1216
|
-
//
|
|
1224
|
+
// — a FUNC that is not externally realized (attributes.external === true) counts as
|
|
1225
|
+
// BOUND when it EITHER
|
|
1217
1226
|
// carries a valid realRef {file, symbol?} OR is a blackbox parent whose compose→FUNC
|
|
1218
1227
|
// children are ALL (recursively) bound — the parent is realized by its children
|
|
1219
1228
|
// (e.g. FUNC-gesture-capture, gve CR-GVE-150). A partially-bound parent fires
|
|
@@ -1230,7 +1239,7 @@ function funcMustHaveCodeBinding(graph) {
|
|
|
1230
1239
|
.filter(t => t.source === id && t.type === 'compose' && funcById.has(t.target))
|
|
1231
1240
|
.map(t => t.target);
|
|
1232
1241
|
const hasCodeRef = (el) => readRealRef(el.attributes).state === 'bound';
|
|
1233
|
-
const isExempt = (el) => el.attributes?.
|
|
1242
|
+
const isExempt = (el) => el.attributes?.external === true;
|
|
1234
1243
|
// A FUNC is bound iff it is exempt, has a codeRef, or is a parent whose
|
|
1235
1244
|
// compose→FUNC children are all bound (recursive, cycle-safe).
|
|
1236
1245
|
const isBound = (id, stack) => {
|
|
@@ -1294,7 +1303,7 @@ function funcMustHaveCodeBinding(graph) {
|
|
|
1294
1303
|
severity: 'warning',
|
|
1295
1304
|
element_id: fn.id,
|
|
1296
1305
|
message: `${fn.id} is a FUNC without a valid realRef binding`,
|
|
1297
|
-
fix_hint: 'Add attributes.realRef {file, symbol, lang?}, or set attributes.
|
|
1306
|
+
fix_hint: 'Add attributes.realRef {file, symbol, lang?}, or set attributes.external:true if it is realized in another package',
|
|
1298
1307
|
context: { element_type: fn.type, element_name: fn.name },
|
|
1299
1308
|
});
|
|
1300
1309
|
}
|
|
@@ -1496,7 +1505,7 @@ function modMustHaveAllocatedFunc(graph) {
|
|
|
1496
1505
|
// REQ→MOD allocate edge as an invalid trace pattern.
|
|
1497
1506
|
// ---------------------------------------------------------------------------
|
|
1498
1507
|
// R-26: SCHEMA realRef presence (CR-211, unified CR-228) — a SCHEMA that is not
|
|
1499
|
-
//
|
|
1508
|
+
// external should carry a valid realRef {file, symbol?}
|
|
1500
1509
|
// so its Zod definition is machine-resolvable (RC-03 then checks it resolves, RC-04
|
|
1501
1510
|
// that it is parsed at the interface). WARNING, not error: currently-unbound SCHEMAs
|
|
1502
1511
|
// on the reference model must not turn readiness red before any binding exists — the
|
|
@@ -1506,54 +1515,45 @@ function modMustHaveAllocatedFunc(graph) {
|
|
|
1506
1515
|
function schemaMustHaveSchemaRef(graph) {
|
|
1507
1516
|
const idx = indexOf(graph);
|
|
1508
1517
|
return idx.elementsOfType('SCHEMA')
|
|
1509
|
-
.filter(e => e.attributes?.
|
|
1518
|
+
.filter(e => e.attributes?.external !== true)
|
|
1510
1519
|
.filter(e => readRealRef(e.attributes).state !== 'bound')
|
|
1511
1520
|
.map(sc => ({
|
|
1512
1521
|
rule_id: 'R-26',
|
|
1513
1522
|
severity: 'warning',
|
|
1514
1523
|
element_id: sc.id,
|
|
1515
1524
|
message: `${sc.id} is a SCHEMA without a valid realRef binding`,
|
|
1516
|
-
fix_hint: 'Add attributes.realRef {file, symbol, lang?}, or set attributes.
|
|
1525
|
+
fix_hint: 'Add attributes.realRef {file, symbol, lang?}, or set attributes.external:true if it is a foreign-API contract',
|
|
1517
1526
|
context: { element_type: sc.type, element_name: sc.name },
|
|
1518
1527
|
}));
|
|
1519
1528
|
}
|
|
1520
1529
|
// ---------------------------------------------------------------------------
|
|
1521
|
-
// R-32: Every
|
|
1522
|
-
// A SCHEMA
|
|
1523
|
-
//
|
|
1524
|
-
//
|
|
1525
|
-
//
|
|
1526
|
-
//
|
|
1527
|
-
//
|
|
1530
|
+
// R-32: Every SCHEMA must have a contract TEST (CR-SM-319, ITEM-2026-064; alle Schemas CR-SM-396).
|
|
1531
|
+
// A SCHEMA is a contract. RC-04 checks that it is PARSED at its boundary; this rule checks that it
|
|
1532
|
+
// is TESTED as a contract — every variant incl. rejection, independent of any scenario — via
|
|
1533
|
+
// `TEST -verify-> SCHEMA` (CR-SM-317). Chain tests (R-21) cover meaning end-to-end; they do not
|
|
1534
|
+
// cover the contract's variants. Owner's decision 2026-09-11: no exception, no KPI — a rule.
|
|
1535
|
+
//
|
|
1536
|
+
// CR-SM-396 (Entscheidung des Autors 2026-10-06): die Regel gilt fuer JEDES Schema. Bis hierher
|
|
1537
|
+
// pruefte sie nur Schemas mit Symbol-`realRef` — als Existenz-Regel der Stufe 9 brauchte sie damit
|
|
1538
|
+
// die Bindung (Stufe 11), und im Entwurf verlangte keine Regel den Vertragstest: TRR las erreicht,
|
|
1539
|
+
// ohne dass ein Schema getestet war. Der Test ist Teil der Spezifikation, nicht des Baus.
|
|
1528
1540
|
// ---------------------------------------------------------------------------
|
|
1529
1541
|
function schemaMustHaveContractTest(graph) {
|
|
1530
1542
|
const idx = indexOf(graph);
|
|
1531
1543
|
const typeOf = new Map(graph.elements.map(e => [e.id, e.type]));
|
|
1532
1544
|
const tests = idx.elementsOfType('TEST');
|
|
1533
1545
|
return idx.elementsOfType('SCHEMA')
|
|
1534
|
-
.filter(sc => sc.attributes?.concept !== true)
|
|
1535
|
-
.filter(sc => { const r = readRealRef(sc.attributes); return r.state === 'bound' && r.value.symbol !== undefined; })
|
|
1536
1546
|
.filter(sc => !graph.traces.some(t => t.type === 'verify' && t.target === sc.id && typeOf.get(t.source) === 'TEST'))
|
|
1537
1547
|
.map(sc => ({
|
|
1538
1548
|
rule_id: 'R-32',
|
|
1539
1549
|
severity: 'warning',
|
|
1540
1550
|
element_id: sc.id,
|
|
1541
|
-
message: `${sc.id} is a
|
|
1551
|
+
message: `${sc.id} is a SCHEMA without a contract TEST (no TEST -verify-> SCHEMA)`,
|
|
1542
1552
|
fix_hint: 'Add a TEST that exercises every variant of the contract incl. rejection, and link it via verify trace to this SCHEMA',
|
|
1543
1553
|
context: { element_type: sc.type, element_name: sc.name, candidate_targets: toCandidates(tests) },
|
|
1544
1554
|
}));
|
|
1545
1555
|
}
|
|
1546
1556
|
// ---------------------------------------------------------------------------
|
|
1547
|
-
// R-27: physical MOD realRef presence (CR-228) — the MOD arm of the unified
|
|
1548
|
-
// "element must have a realRef" rule (FUNC=R-20, SCHEMA=R-26, physical MOD=R-27).
|
|
1549
|
-
// A physical MOD (kind='physical') is a Bauteil realized by a CAD/geometry
|
|
1550
|
-
// artefact, not by code (RT-01: FUNCs never allocate directly to it). Logical/SW
|
|
1551
|
-
// MODs are realized through their FUNCs' code (R-20) and are NOT in scope here.
|
|
1552
|
-
// WARNING (presence signal like R-20/R-26); concept/external MODs are exempt.
|
|
1553
|
-
// Symbol is optional on a realRef (a geometry file has none) — presence = a valid
|
|
1554
|
-
// realRef with a file. RESOLUTION (file on disk) is a consumer/RC concern.
|
|
1555
|
-
// ---------------------------------------------------------------------------
|
|
1556
|
-
// ---------------------------------------------------------------------------
|
|
1557
1557
|
// R-28 (Ebenen-Präsenz) ist mit CR-SM-247 ersatzlos entfallen — nicht weil sie falsch war,
|
|
1558
1558
|
// sondern weil sie seit CR-GC-366 doppelt ist. Sie schloss das Vacuous-Complete-Loch (mit 0/1
|
|
1559
1559
|
// FUNC feuert keine Pro-Element-Regel, alles liest "fertig"); beide Hälften trägt heute je eine
|
|
@@ -1663,42 +1663,82 @@ function funcMustBeWired(graph) {
|
|
|
1663
1663
|
},
|
|
1664
1664
|
}));
|
|
1665
1665
|
}
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1666
|
+
// ---------------------------------------------------------------------------
|
|
1667
|
+
// R-33 (CR-SM-395): die Existenz-Regel des SYSTEMS (Stufe 1).
|
|
1668
|
+
//
|
|
1669
|
+
// Jede Pflichtmenge wird von einer Existenz-Regel der Stufe davor verlangt; eine leere Pflichtmenge
|
|
1670
|
+
// ist deshalb immer ein Befund und nie „0 von 0 bestanden". „Kein System" stand als Code im
|
|
1671
|
+
// Kaltstart von graphcode (`graph_generate`), nicht im Katalog. Ein Graph ohne SYS hat kein Element,
|
|
1672
|
+
// an dem der Befund haengen koennte — er traegt den Anker `GRAPH_ANCHOR`.
|
|
1673
|
+
//
|
|
1674
|
+
// R-34 („FLOW hat ein SCHEMA", Stufe 8) ist mit CR-SM-396 wieder gestrichen: deckungsgleich mit der
|
|
1675
|
+
// R-18-Untergrenze `FLOW -relation-> SCHEMA [1]` — alle 20 Befunde des Bestands standen an FLOWs
|
|
1676
|
+
// mit R-18-Fehler, R-34 konnte nie allein melden. Die Stufe 8 traegt keine eigene Existenz-Regel:
|
|
1677
|
+
// R-18 ist `'immer'` und haelt als Fehler jede Marke, das Gate lehnt den untypisierten FLOW schon
|
|
1678
|
+
// beim Schreiben ab; null Datenfluesse haelt R-31 (Stufe 6).
|
|
1679
|
+
// ---------------------------------------------------------------------------
|
|
1680
|
+
/** Der Anker eines Befunds an einem Graphen ohne SYS — kein Element traegt diese Id. */
|
|
1681
|
+
export const GRAPH_ANCHOR = 'graph';
|
|
1682
|
+
function graphMustHaveSystem(graph) {
|
|
1683
|
+
if (indexOf(graph).elementsOfType('SYS').length > 0)
|
|
1684
|
+
return [];
|
|
1685
|
+
return [{
|
|
1686
|
+
rule_id: 'R-33',
|
|
1687
|
+
severity: 'warning',
|
|
1688
|
+
element_id: GRAPH_ANCHOR,
|
|
1689
|
+
message: 'The graph has no SYS element — nothing names the system and its boundary',
|
|
1690
|
+
fix_hint: 'Add one SYS element that names the system; use cases, requirements and modules are composed below it',
|
|
1691
|
+
}];
|
|
1692
|
+
}
|
|
1693
|
+
/**
|
|
1694
|
+
* CR-SM-395: das UNGEBAUTE — die Elemente, an denen die Praesenzregeln der Bindung melden wuerden
|
|
1695
|
+
* (R-19 TEST, R-20 FUNC, R-26 SCHEMA), unabhaengig davon, ob sie schon faellig sind. EINE
|
|
1696
|
+
* Definition samt Ausnahmen (`external`, Zerlegungs-Eltern mit gebundenen Kindern): AF-05 fragt
|
|
1697
|
+
* damit „gibt es etwas zu bauen?", ohne die Ausnahmen ein zweites Mal zu schreiben.
|
|
1698
|
+
*/
|
|
1699
|
+
export function unbuiltElementIds(graph) {
|
|
1700
|
+
return [...testMustHaveRunnableBinding(graph), ...funcMustHaveCodeBinding(graph), ...schemaMustHaveSchemaRef(graph)]
|
|
1701
|
+
.map(v => v.element_id);
|
|
1702
|
+
}
|
|
1703
|
+
// CR-SM-395: die Faelligkeit haengt am KATALOG (`whenDue`), nicht am Auswerter und nicht im
|
|
1704
|
+
// Regelkoerper — die Regeln der Stufe 11 (R-19, R-20, R-26, R-29) schweigen, bis der Bau eroeffnet ist.
|
|
1705
|
+
export const V3_RULES = whenDue([
|
|
1706
|
+
{ id: 'R-33', name: 'Graph must have a SYS', severity: 'warning', stage: 1, role: 'existence', evaluate: graphMustHaveSystem, domain: ['graph'] },
|
|
1707
|
+
{ id: 'R-01', name: 'REQ must have verification', severity: 'error', stage: 9, role: 'existence', evaluate: reqMustHaveVerification, domain: ['REQ'] },
|
|
1708
|
+
{ id: 'R-02', name: 'FUNC must satisfy REQ', severity: 'warning', stage: 5, evaluate: funcMustSatisfyReq, domain: ['FUNC'] },
|
|
1669
1709
|
// CR-SM-243: domain ist MOD, nicht FUNC — die Regel iteriert Module und meldet am Modul,
|
|
1670
1710
|
// das ASIL-D und QM mischt. Die FUNCs sind der Anlass des Urteils, nicht seine Traeger.
|
|
1671
|
-
{ id: 'R-04', name: 'Module boundary width', severity: 'warning', evaluate: moduleBoundaryWidth, domain: ['MOD'] },
|
|
1672
|
-
{ id: 'R-05', name: 'TEST must verify REQ', severity: 'warning', evaluate: testMustVerifyReq, domain: ['TEST'] },
|
|
1673
|
-
{ id: 'R-15', name: 'FCHAIN completeness', severity: 'warning', evaluate: fchainCompleteness, domain: ['FCHAIN'] },
|
|
1674
|
-
{ id: 'R-16', name: 'ACTOR must have io', severity: 'warning', evaluate: actorMustHaveTrace, domain: ['ACTOR'] },
|
|
1675
|
-
{ id: 'R-17', name: 'SYS must have
|
|
1676
|
-
{ id: 'R-08', name: 'Trace consistency', severity: 'error', evaluate: traceConsistency, domain: ['all'] },
|
|
1711
|
+
{ id: 'R-04', name: 'Module boundary width', severity: 'warning', stage: 7, evaluate: moduleBoundaryWidth, domain: ['MOD'] },
|
|
1712
|
+
{ id: 'R-05', name: 'TEST must verify REQ', severity: 'warning', stage: 9, evaluate: testMustVerifyReq, domain: ['TEST'] },
|
|
1713
|
+
{ id: 'R-15', name: 'FCHAIN completeness', severity: 'warning', stage: 5, role: 'existence', evaluate: fchainCompleteness, domain: ['FCHAIN'] },
|
|
1714
|
+
{ id: 'R-16', name: 'ACTOR must have io', severity: 'warning', stage: 2, evaluate: actorMustHaveTrace, domain: ['ACTOR'] },
|
|
1715
|
+
{ id: 'R-17', name: 'SYS must have a use case', severity: 'warning', stage: 2, role: 'existence', evaluate: sysMustHaveUseCase, domain: ['SYS'] },
|
|
1716
|
+
{ id: 'R-08', name: 'Trace consistency', severity: 'error', stage: 'immer', evaluate: traceConsistency, domain: ['all'] },
|
|
1677
1717
|
// CR-SM-242: domain ist FLOW, nicht FUNC — die Regel iteriert ueber FLOWs und meldet am FLOW.
|
|
1678
1718
|
// Als ['FUNC'] deklariert erhoehte sie den Zaehler einer Grundgesamtheit, zu der ihre
|
|
1679
1719
|
// Verstoesse nicht gehoerten (bis zu 2 Legs je FLOW gegen einen FUNC-Nenner).
|
|
1680
|
-
{ id: 'R-10', name: 'FLOW completeness', severity: 'warning', evaluate: flowCompleteness, domain: ['FLOW'] },
|
|
1720
|
+
{ id: 'R-10', name: 'FLOW completeness', severity: 'warning', stage: 6, evaluate: flowCompleteness, domain: ['FLOW'] },
|
|
1681
1721
|
// Obergrenze zu R-10s Untergrenze — disjunkt, deshalb zwei IDs (CR-SM-307).
|
|
1682
|
-
{ id: 'IO-02', name: 'FLOW single producer', severity: 'error', evaluate: flowSingleProducer, domain: ['FLOW'] },
|
|
1683
|
-
{ id: 'R-12', name: 'No circular dependencies', severity: 'warning', evaluate: noDirectCircular, domain: ['FUNC'] },
|
|
1684
|
-
{ id: 'R-18', name: 'Valid trace pattern', severity: 'error', evaluate: validTracePattern, domain: ['all'] },
|
|
1685
|
-
{ id: 'R-19', name: 'Runnable TEST binding', severity: 'warning', evaluate: testMustHaveRunnableBinding, domain: ['TEST'] },
|
|
1686
|
-
{ id: 'R-29', name: 'Test file exclusivity', severity: 'error', evaluate: testFileExclusivity, domain: ['TEST'] },
|
|
1687
|
-
{ id: 'R-20', name: 'FUNC realRef binding', severity: 'warning', evaluate: funcMustHaveCodeBinding, domain: ['FUNC'] },
|
|
1688
|
-
{ id: 'R-21', name: 'FUNC↔FUNC handover needs a shared chain covered by member REQs or an integration test', severity: 'warning', evaluate: fchainMustHaveIntegrationTest, domain: ['FCHAIN', 'FUNC'] },
|
|
1689
|
-
{ id: 'R-22', name: 'FUNC must be allocated to MOD', severity: 'warning', evaluate: funcMustBeAllocated, domain: ['FUNC'] },
|
|
1690
|
-
{ id: 'R-23', name: 'MOD must have allocated FUNC', severity: 'warning', evaluate: modMustHaveAllocatedFunc, domain: ['MOD'] },
|
|
1691
|
-
{ id: 'R-26', name: 'SCHEMA must have realRef', severity: 'warning', evaluate: schemaMustHaveSchemaRef, domain: ['SCHEMA'] },
|
|
1692
|
-
{ id: 'R-32', name: 'SCHEMA must have contract TEST', severity: 'warning', evaluate: schemaMustHaveContractTest, domain: ['SCHEMA'] },
|
|
1693
|
-
{ id: 'RD-01', name: 'Unresolved requirement', severity: 'warning', evaluate: unresolvedRequirement, domain: ['REQ'] },
|
|
1694
|
-
{ id: 'RD-02', name: 'Decomposition consistency', severity: 'warning', evaluate: decompositionConsistency, domain: ['REQ'] },
|
|
1695
|
-
{ id: 'RD-04', name: 'Decomposition breadth', severity: 'warning', evaluate: decompositionBreadth, domain: ['FUNC', 'MOD', 'SYS'] },
|
|
1696
|
-
{ id: 'RD-05', name: 'Decomposition too narrow', severity: 'warning', evaluate: decompositionNarrow, domain: ['FUNC', 'MOD'] },
|
|
1697
|
-
{ id: 'MS-01', name: 'Milestone empty scope', severity: 'warning', evaluate: msEmptyScope, domain: ['MS'] },
|
|
1698
|
-
{ id: 'MS-02', name: 'Milestone dangling dependency', severity: 'warning', evaluate: msDanglingDependency, domain: ['MS'] },
|
|
1699
|
-
{ id: 'R-30', name: 'FUNC leaf must belong to a function chain', severity: 'warning', evaluate: funcMustBeInEffectChain, domain: ['FUNC'] },
|
|
1700
|
-
{ id: 'R-31', name: 'FUNC must be wired (io input + output)', severity: 'warning', evaluate: funcMustBeWired, domain: ['FUNC'] },
|
|
1701
|
-
];
|
|
1722
|
+
{ id: 'IO-02', name: 'FLOW single producer', severity: 'error', stage: 6, evaluate: flowSingleProducer, domain: ['FLOW'] },
|
|
1723
|
+
{ id: 'R-12', name: 'No circular dependencies', severity: 'warning', stage: 5, evaluate: noDirectCircular, domain: ['FUNC'] },
|
|
1724
|
+
{ id: 'R-18', name: 'Valid trace pattern', severity: 'error', stage: 'immer', evaluate: validTracePattern, domain: ['all'] },
|
|
1725
|
+
{ id: 'R-19', name: 'Runnable TEST binding', severity: 'warning', stage: 11, evaluate: testMustHaveRunnableBinding, domain: ['TEST'] },
|
|
1726
|
+
{ id: 'R-29', name: 'Test file exclusivity', severity: 'error', stage: 11, evaluate: testFileExclusivity, domain: ['TEST'] },
|
|
1727
|
+
{ id: 'R-20', name: 'FUNC realRef binding', severity: 'warning', stage: 11, evaluate: funcMustHaveCodeBinding, domain: ['FUNC'] },
|
|
1728
|
+
{ id: 'R-21', name: 'FUNC↔FUNC handover needs a shared chain covered by member REQs or an integration test', severity: 'warning', stage: 9, evaluate: fchainMustHaveIntegrationTest, domain: ['FCHAIN', 'FUNC'] },
|
|
1729
|
+
{ id: 'R-22', name: 'FUNC must be allocated to MOD', severity: 'warning', stage: 7, role: 'existence', evaluate: funcMustBeAllocated, domain: ['FUNC'] },
|
|
1730
|
+
{ id: 'R-23', name: 'MOD must have allocated FUNC', severity: 'warning', stage: 7, evaluate: modMustHaveAllocatedFunc, domain: ['MOD'] },
|
|
1731
|
+
{ id: 'R-26', name: 'SCHEMA must have realRef', severity: 'warning', stage: 11, evaluate: schemaMustHaveSchemaRef, domain: ['SCHEMA'] },
|
|
1732
|
+
{ id: 'R-32', name: 'SCHEMA must have contract TEST', severity: 'warning', stage: 9, role: 'existence', evaluate: schemaMustHaveContractTest, domain: ['SCHEMA'] },
|
|
1733
|
+
{ id: 'RD-01', name: 'Unresolved requirement', severity: 'warning', stage: 3, evaluate: unresolvedRequirement, domain: ['REQ'] },
|
|
1734
|
+
{ id: 'RD-02', name: 'Decomposition consistency', severity: 'warning', stage: 3, evaluate: decompositionConsistency, domain: ['REQ'] },
|
|
1735
|
+
{ id: 'RD-04', name: 'Decomposition breadth', severity: 'warning', stage: 7, evaluate: decompositionBreadth, domain: ['FUNC', 'MOD', 'SYS'] },
|
|
1736
|
+
{ id: 'RD-05', name: 'Decomposition too narrow', severity: 'warning', stage: 7, evaluate: decompositionNarrow, domain: ['FUNC', 'MOD'] },
|
|
1737
|
+
{ id: 'MS-01', name: 'Milestone empty scope', severity: 'warning', stage: 10, evaluate: msEmptyScope, domain: ['MS'] },
|
|
1738
|
+
{ id: 'MS-02', name: 'Milestone dangling dependency', severity: 'warning', stage: 10, evaluate: msDanglingDependency, domain: ['MS'] },
|
|
1739
|
+
{ id: 'R-30', name: 'FUNC leaf must belong to a function chain', severity: 'warning', stage: 5, evaluate: funcMustBeInEffectChain, domain: ['FUNC'] },
|
|
1740
|
+
{ id: 'R-31', name: 'FUNC must be wired (io input + output)', severity: 'warning', stage: 6, role: 'existence', evaluate: funcMustBeWired, domain: ['FUNC'] },
|
|
1741
|
+
]);
|
|
1702
1742
|
/** Run all rules against a graph. CR-SM-236: `policy` ist Pflicht — wie bei `evaluateAllRules`. */
|
|
1703
1743
|
export function evaluateRules(graph, policy) {
|
|
1704
1744
|
return V3_RULES.flatMap(rule => rule.evaluate(graph, policy));
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* attributes and fired on exactly the same elements (Jaccard 1.0 vs R-26). SC-03 had
|
|
7
7
|
* additionally become wrong — a SCHEMA correctly bound via `realRef` still fired it.
|
|
8
8
|
* `realRef` is the single SCHEMA binding truth (R-26 presence, RC-03/RC-04 resolution);
|
|
9
|
-
* a spec-only SCHEMA
|
|
9
|
+
* a spec-only SCHEMA simply has none yet, it does NOT carry a Zod body copy in the graph
|
|
10
10
|
* (same rule as TEST: bindings point at code, they never mirror it).
|
|
11
11
|
*
|
|
12
12
|
* What remains here is the one SCHEMA check that is NOT about binding: is the interface
|
|
@@ -32,7 +32,7 @@ export const SC_RULES = [
|
|
|
32
32
|
// Die Asymmetrie zur FLOW-Seite ist gewollt (CR-SM-242): SC-02 iteriert ueber SCHEMA
|
|
33
33
|
// („wird dieses SCHEMA benutzt"); die Gegenrichtung je FLOW („hat dieser FLOW einen
|
|
34
34
|
// Datenvertrag") traegt seit CR-SM-271 das R-18-Untergrenzen-Bein.
|
|
35
|
-
{ id: 'SC-02', name: 'Schema referenced by FLOW', severity: 'warning', evaluate: sc02IsReferenced, domain: ['SCHEMA'] },
|
|
35
|
+
{ id: 'SC-02', name: 'Schema referenced by FLOW', severity: 'warning', stage: 8, evaluate: sc02IsReferenced, domain: ['SCHEMA'] },
|
|
36
36
|
];
|
|
37
37
|
// CR-SM-236: `policy` wird durchgereicht, auch wo diese Familie heute keine Schwelle hat —
|
|
38
38
|
// ein Sonderweg je Familie waere genau der zweite Pfad, den der Regelsatz verbietet.
|