@sigloch/contracts 10.14.0 → 12.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 (40) hide show
  1. package/dist/se/analysis-freshness-rules.d.ts +37 -30
  2. package/dist/se/analysis-freshness-rules.js +41 -81
  3. package/dist/se/ao-rules.js +3 -3
  4. package/dist/se/chain-metrics.d.ts +116 -0
  5. package/dist/se/chain-metrics.js +311 -0
  6. package/dist/se/conformance-rules.d.ts +4 -0
  7. package/dist/se/conformance-rules.js +37 -32
  8. package/dist/se/cr-quality-rules.js +4 -76
  9. package/dist/se/evaluate-all.d.ts +7 -3
  10. package/dist/se/evaluate-all.js +3 -4
  11. package/dist/se/fchain-quality-rules.js +4 -4
  12. package/dist/se/fmea-rules.js +4 -4
  13. package/dist/se/format-e-parser.js +1 -1
  14. package/dist/se/grammar-snapshot.d.ts +6 -6
  15. package/dist/se/grammar-snapshot.js +90 -103
  16. package/dist/se/index.d.ts +4 -2
  17. package/dist/se/index.js +6 -2
  18. package/dist/se/metric-rules.d.ts +9 -5
  19. package/dist/se/metric-rules.js +10 -9
  20. package/dist/se/module-crossings.d.ts +10 -0
  21. package/dist/se/module-crossings.js +3 -1
  22. package/dist/se/near-duplicate-rules.d.ts +2 -0
  23. package/dist/se/near-duplicate-rules.js +2 -2
  24. package/dist/se/ontology.d.ts +23 -7
  25. package/dist/se/ontology.js +29 -26
  26. package/dist/se/quality-rules.js +5 -5
  27. package/dist/se/readiness.d.ts +41 -149
  28. package/dist/se/readiness.js +50 -280
  29. package/dist/se/rule-due.d.ts +26 -0
  30. package/dist/se/rule-due.js +72 -0
  31. package/dist/se/rule-help.d.ts +3 -1
  32. package/dist/se/rule-help.js +47 -31
  33. package/dist/se/rules.d.ts +23 -13
  34. package/dist/se/rules.js +112 -72
  35. package/dist/se/schema-quality-rules.d.ts +1 -1
  36. package/dist/se/schema-quality-rules.js +1 -1
  37. package/dist/se/similarity.js +4 -10
  38. package/dist/se/uc-quality-rules.js +4 -4
  39. package/dist/se/view-rules.js +6 -4
  40. package/package.json +1 -1
@@ -0,0 +1,72 @@
1
+ /**
2
+ * FAELLIGKEIT (CR-SM-395) — der EINE Mechanismus, mit dem eine Regel auf ihren Zeitpunkt wartet.
3
+ *
4
+ * Jede Regel hat eine Menge: die Elemente, die sie prueft. Faellig ist sie, sobald die Menge nicht
5
+ * leer ist. Fuer die Stufen 1 bis 10 ist die Menge die `domain` der Regel — eine Regel ueber eine
6
+ * leere Menge schweigt von selbst, dort ist nichts zu bauen. Fuer die Stufen 11 (Bindung) und 12
7
+ * (Abgleich Modell gegen Code) ist die Menge der BAU: er ist eroeffnet, sobald es einen offenen
8
+ * AUFTRAG gibt (`hasOpenOrder` — eine Entscheidung ist ein erledigter Auftrag) oder irgendeine
9
+ * Bindung. Vorher ist die Regel NICHT AUSGEWERTET — nicht bestanden.
10
+ *
11
+ * Zwei Leser, eine Funktion:
12
+ * - AUSWERTUNG: `whenDue` wickelt das `evaluate` der Regeln der Stufen 11 und 12 am Katalog
13
+ * (`V3_RULES`, `VIEW_RULES`, `CODE_CONFORMANCE_RULES`). Wer immer die Regel ruft, bekommt das
14
+ * Schweigen — auch ein direkter `rule.evaluate`-Aufruf.
15
+ * - READINESS: wer einen Anteil bildet, fragt `isDue` und laesst eine nicht faellige Regel aus
16
+ * Zaehler UND Nenner — sonst liest sich ihr Schweigen als Erfolg.
17
+ *
18
+ * Ersetzt `RULE_PRECONDITION` / `ruleApplies` / `withPrecondition` / `realizationBegun`
19
+ * (CR-SM-392): dort war „der Bau hat begonnen" eine benannte Vorbedingung an vier Regeln, mit dem
20
+ * Bauplan-Stempel als Ausloeser. Der Stempel wird nicht mehr gelesen; die Fuehrung uebernimmt
21
+ * AF-05 („es gibt Ungebautes, aber keinen offenen Auftrag").
22
+ */
23
+ import { readRealRef, readTestRefs } from './ontology.js';
24
+ import { toEvaluableGraph } from './flat-graph.js';
25
+ /**
26
+ * Gibt es einen offenen Auftrag — einen CR mit `status: open`? Er muss nicht auf die Elemente zeigen.
27
+ *
28
+ * CR-SM-400 (Entscheidung des Autors 2026-10-07): ein offener CR IST ein Bauauftrag. Eine
29
+ * Entscheidung — das Ergebnis einer Analyse oder Optimierung — ist ein ERLEDIGTER Auftrag und
30
+ * eroeffnet deshalb keinen Bau. Der Filter auf `relation [label: decides]` (CR-SM-396) ist ohne
31
+ * Ersatz entfallen.
32
+ */
33
+ export function hasOpenOrder(graph) {
34
+ return toEvaluableGraph(graph).elements.some((e) => e.type === 'CR' && e.attributes?.status === 'open');
35
+ }
36
+ const BUILD_OPEN = new WeakMap();
37
+ /**
38
+ * Ist der Bau eroeffnet? Ein offener Auftrag ODER eine Bindung — ein `realRef` an irgendeinem
39
+ * Element oder `testRefs` an einem TEST. Eine Bindung von Hand, ohne Bauplan, zaehlt genauso.
40
+ * Gezaehlt wird die ANWESENHEIT des Attributs, nicht seine Gueltigkeit: eine ungueltige Bindung
41
+ * (leere Liste, alte Objektform) ist ein Bindungsversuch, und R-19/R-20/R-26 sind die einzigen
42
+ * Regeln, die sie melden — an „gueltig" gebunden schwiegen sie genau dort.
43
+ *
44
+ * Nimmt die flache wie die genestete Form; das Ergebnis haengt an der Graph-Identitaet wie `indexOf`.
45
+ */
46
+ function buildOpen(graph) {
47
+ const cached = BUILD_OPEN.get(graph);
48
+ if (cached !== undefined)
49
+ return cached;
50
+ const open = hasOpenOrder(graph) ||
51
+ toEvaluableGraph(graph).elements.some((e) => readRealRef(e.attributes).state !== 'absent' ||
52
+ (e.type === 'TEST' && readTestRefs(e.attributes).state !== 'absent'));
53
+ BUILD_OPEN.set(graph, open);
54
+ return open;
55
+ }
56
+ /** Ist die Regel an diesem Graphen faellig — ist ihre Menge nicht leer? */
57
+ export function isDue(rule, graph) {
58
+ if (rule.stage === 11 || rule.stage === 12)
59
+ return buildOpen(graph);
60
+ if (rule.domain.includes('graph'))
61
+ return true;
62
+ return graph.elements.some((e) => rule.domain.includes('all') || rule.domain.includes(e.type));
63
+ }
64
+ /**
65
+ * Wickelt das `evaluate` der Regeln, deren Menge nicht ihre `domain` ist (Stufen 11 und 12) — am
66
+ * Katalog, einmal. Die uebrigen Regeln kommen unveraendert (dieselbe Referenz) zurueck.
67
+ */
68
+ export function whenDue(rules) {
69
+ return rules.map((rule) => rule.stage === 11 || rule.stage === 12
70
+ ? { ...rule, evaluate: (graph, ...rest) => (isDue(rule, graph) ? rule.evaluate(graph, ...rest) : []) }
71
+ : rule);
72
+ }
@@ -12,7 +12,7 @@
12
12
  * ## Was hier NICHT steht
13
13
  *
14
14
  * - **Abgeleitetes** — Titel, Severity, Meldung und `fix_hint` stehen an der Regeldefinition
15
- * (`ALL_RULE_DEFS`), die Dimensions-/Phasenzuordnung in `readiness.ts`. Kein Wort davon wird
15
+ * (`ALL_RULE_DEFS`), ebenso Stufe und Marke. Kein Wort davon wird
16
16
  * hier wiederholt; ein zweiter Speicher derselben Wahrheit laeuft auseinander.
17
17
  * - **`fix_hint` gegen `plain`/`se`** — `fix_hint` ist die Anweisung an den AGENTEN („Add a
18
18
  * `verify` trace"), `plain`/`se` die Erklaerung fuer den MENSCHEN („was ist hier eigentlich
@@ -56,6 +56,8 @@ export interface RuleHelpEntry {
56
56
  * Fix-Vorlage — der Nutzer entscheidet, der Agent fuehrt aus (graphcode CR-GC-729/730). Genau an den
57
57
  * Regeln, die den Kern-Fokus stellen koennen: Task `kern`, Schwere nicht `info`, kein Eintrittspunkt
58
58
  * einer Analyse (die haben ihren eigenen Satz beim Konsumenten). Beidseitig erzwungen im Test.
59
+ * CR-SM-395: seit die Arbeitsschritt-Zuordnung auf die Anforderungsqualitaet gekuerzt ist, sind das
60
+ * auch die Regeln ueber Risiken, Auftraege, Meilensteine, Bindung und Abgleich.
59
61
  */
60
62
  readonly vorschlag?: string;
61
63
  }
@@ -12,7 +12,7 @@
12
12
  * ## Was hier NICHT steht
13
13
  *
14
14
  * - **Abgeleitetes** — Titel, Severity, Meldung und `fix_hint` stehen an der Regeldefinition
15
- * (`ALL_RULE_DEFS`), die Dimensions-/Phasenzuordnung in `readiness.ts`. Kein Wort davon wird
15
+ * (`ALL_RULE_DEFS`), ebenso Stufe und Marke. Kein Wort davon wird
16
16
  * hier wiederholt; ein zweiter Speicher derselben Wahrheit laeuft auseinander.
17
17
  * - **`fix_hint` gegen `plain`/`se`** — `fix_hint` ist die Anweisung an den AGENTEN („Add a
18
18
  * `verify` trace"), `plain`/`se` die Erklaerung fuer den MENSCHEN („was ist hier eigentlich
@@ -65,8 +65,8 @@ export const RULE_HELP = {
65
65
  prompt: "se-fmea",
66
66
  },
67
67
  'AF-05': {
68
- plain: "No implementation plan is on record → derive the build order.",
69
- se: "No `analysisFreshness.implplan` stamp under `SYS.attributes`.",
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.",
@@ -205,7 +209,7 @@ export const RULE_HELP = {
205
209
  },
206
210
  'ND-02': {
207
211
  plain: "Two data contracts describe the same thing twice → merge them, or say what distinguishes them.",
208
- se: "Near-duplicate `SCHEMA` above 0.85 similarity (name, description, fields and legal trace partners). Partners are filtered through `isValidTrace`: a rule must not reach its verdict via an edge R-18 rejects (CR-SM-286).",
212
+ se: "Near-duplicate `SCHEMA` above 0.85 similarity (name, description and legal trace partners). Partners are filtered through `isValidTrace`: a rule must not reach its verdict via an edge R-18 rejects (CR-SM-286).",
209
213
  vorschlag: 'Führe die doppelten Datenformate {n} zusammen oder grenze sie ab.',
210
214
  },
211
215
  'NFR-01': {
@@ -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 contract exists in code 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.",
240
- se: "`SCHEMA` with a symbol `realRef` (a Zod contract) and no `TEST -verify-> SCHEMA`. RC-04 checks the parse at the boundary; this checks the contract test (CR-SM-319).",
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: "The top level of your project is empty — nothing is inside it → add the main use cases, features, or modules.",
269
- se: "`SYS` with no `compose` to `UC` / `REQ` / `MOD`.",
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: "A test that's meant to run doesn't point to a test file → add the link to the test file, or, if it isn't written yet, mark it not-yet-written.",
279
- se: "Realized `TEST` with no valid `testRefs` `[{file, case?, tool}, …]` (at least one entry); else set `concept:true` (a stub).",
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: "A function is supposed to be built but doesn't point to its code → add the link to its code; or mark it not-built-yet / from-an-outside-library.",
283
- se: "Realized `FUNC` with no valid `realRef` `{file, symbol}` (graph↔code binding); else `concept:true` / `external:true`.",
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: "A data format in the model isn't linked to the schema code that defines it → link it to the schema (or mark it concept/outside).",
302
- se: "Realized `SCHEMA` with no valid `realRef` `{file, symbol}` (graph↔Zod binding); else `concept:true` / `external:true` (CR-211/228).",
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`. `concept`/`external` modules are exempt, as for R-20 (CR-SM-344).",
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,4 @@ 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: Task-Ausgaenge — sichtbar nur im Task trade / irr.
412
- 'TR-01': {
413
- 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
- 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
- prompt: "se-trade",
416
- },
417
- 'IR-01': {
418
- plain: "The assumption review names a CR that does not exist → fix the reference or add the CR; an empty list is fine when no assumption was load-bearing.",
419
- se: "Task outcome rule (CR-SM-355): every id in `analysisFreshness.assumption-review.crRefs` resolves to a CR element; empty is a legitimate outcome (low-risk assumptions stay in the record).",
420
- prompt: "se-irr",
421
- },
422
438
  };
@@ -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
@@ -313,14 +322,12 @@ export interface RuleDefinition {
313
322
  */
314
323
  evaluate: (graph: OntologyGraph, policy: MetricPolicy) => RuleViolation[];
315
324
  /**
316
- * CR-SM-235: die Grundgesamtheit, ueber die die Regel feuert — der Nenner ihres
317
- * Readiness-Anteils. **Der Elementtyp, ueber den sie feuert, nicht das Thema, dem sie
318
- * gehoert:** MS-03 („CR ohne Milestone") feuert je CR, nicht je MS.
325
+ * CR-SM-235: die Grundgesamtheit, ueber die die Regel feuert — die Menge, an der ihre
326
+ * Faelligkeit haengt (`isDue`). **Der Elementtyp, ueber den sie feuert, nicht das Thema, dem
327
+ * sie gehoert:** MS-03 („CR ohne Milestone") feuert je CR, nicht je MS.
319
328
  *
320
- * Pflichtfeld, damit ein neuer Regeleintrag ohne Grundgesamtheit den Build bricht. Vorher
321
- * lag die Zuordnung als Handtabelle in einem anderen Paket (`se-steering`), 18 von 71 Regeln
322
- * fehlten dort — sie erhoehten den Zaehler, nie den Nenner, und jede neue Regel senkte den
323
- * Score automatisch, bis jemand die zweite Tabelle nachzog.
329
+ * Pflichtfeld, damit ein neuer Regeleintrag ohne Grundgesamtheit den Build bricht. (Bis
330
+ * CR-SM-401 war sie auch der Nenner eines Prozentwerts je Dimension; den gibt es nicht mehr.)
324
331
  *
325
332
  * Mehrere Typen, wo die Regel ueber mehrere feuert (RD-04: FUNC, MOD und SYS als Eltern
326
333
  * einer Zerlegung). `['all']` = jedes Nicht-SESSION-Element (R-08/R-18 pruefen Traces).
@@ -330,12 +337,6 @@ export interface RuleDefinition {
330
337
  * Analyse-Freshness-Stempel (AF-01..05). Sie tragen KEINE
331
338
  * Grundgesamtheit bei, denn sie haben keine — der Stempel haengt zwar unter SYS, geprueft
332
339
  * wird aber der Graph, nicht das Element.
333
- *
334
- * Warum das zaehlt: mit `['SYS']` deklariert waren sie eine Ein-Element-Gruppe mit fast
335
- * sicherem Verstoss. Eine Dimension ohne eigene Elemente (z. B. `req` in einem Graphen ohne
336
- * eine einzige REQ) las dadurch **0 %** statt „nichts zu messen" — und der Executor
337
- * fokussierte sie. Ein Graph-Check verfeinert eine Dimension, die es gibt; er erschafft
338
- * keine.
339
340
  */
340
341
  domain: readonly string[];
341
342
  }
@@ -369,6 +370,15 @@ export declare function decomposedFuncs(graph: OntologyGraph): Set<string>;
369
370
  * die zweite Wahrheit, die CR-SM-286/-302 beseitigt haben.
370
371
  */
371
372
  export declare function flowProducers(graph: OntologyGraph): Map<string, Set<string>>;
373
+ /** Der Anker eines Befunds an einem Graphen ohne SYS — kein Element traegt diese Id. */
374
+ export declare const GRAPH_ANCHOR = "graph";
375
+ /**
376
+ * CR-SM-395: das UNGEBAUTE — die Elemente, an denen die Praesenzregeln der Bindung melden wuerden
377
+ * (R-19 TEST, R-20 FUNC, R-26 SCHEMA), unabhaengig davon, ob sie schon faellig sind. EINE
378
+ * Definition samt Ausnahmen (`external`, Zerlegungs-Eltern mit gebundenen Kindern): AF-05 fragt
379
+ * damit „gibt es etwas zu bauen?", ohne die Ausnahmen ein zweites Mal zu schreiben.
380
+ */
381
+ export declare function unbuiltElementIds(graph: OntologyGraph): string[];
372
382
  export declare const V3_RULES: RuleDefinition[];
373
383
  /** Run all rules against a graph. CR-SM-236: `policy` ist Pflicht — wie bei `evaluateAllRules`. */
374
384
  export declare function evaluateRules(graph: OntologyGraph, policy: MetricPolicy): RuleViolation[];