@sigloch/contracts 1.0.0 → 2.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.
@@ -5,7 +5,7 @@
5
5
  /** Ontology schema version (element types + trace types). */
6
6
  export declare const ONTOLOGY_VERSION = "4.0.0";
7
7
  /** Rules engine version (validation rules incl. RC conformance). */
8
- export declare const RULES_VERSION = "2.20.0";
8
+ export declare const RULES_VERSION = "2.21.0";
9
9
  /** Meta-model version (trace pattern constraints + format-e parser). */
10
10
  export declare const META_MODEL_VERSION = "1.4.0";
11
11
  export * from './ontology.js';
package/dist/se/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  /** Ontology schema version (element types + trace types). */
6
6
  export const ONTOLOGY_VERSION = '4.0.0'; // BREAKING: `SemanticId` (`Name.TypeAbbr.Counter`) deleted, `ElementUid` (`<TYPE>-<slug>`) is the family canon — the old canon was used by no production graph of the family while 626 of 1145 elements already carried TYPE-slug (CR-SM-217); realRef unifies codeRef+schemaRef (+physical-MOD CAD ref), symbol optional; testRef stays separate (CR-228 C); +RepoRelativePathSchema on testRef/realRef .file — no absolute/`..` paths (CR-GC-255)
7
7
  /** Rules engine version (validation rules incl. RC conformance). */
8
- export const RULES_VERSION = '2.20.0'; // +RD-04 decomposition breadth (>11 children per level → warning) and MT-03 recalibrated to FLOW-transitive connection pairs — counting raw io traces reported internal=0 on every real SE graph (15/15 false positives), because the meta-model routes FUNC↔FUNC through FLOW; 'RD-' added to the se profile prefixes, where RD-01..04 were silently missing (CR-SM-221); -SC-01/-SC-03 deleted (BOK-CR-026): `realRef` is the single SCHEMA binding truth (R-26 presence, RC-03/RC-04 resolution); the legacy `zodDefinition`/`sourceFile`/`sourceExport` attributes are gone from every producer, SC_RULES = [SC-02]; R-20/R-26/RC-01/RC-03/RC-04 read realRef (unified codeRef+schemaRef); +R-27 physical-MOD realRef presence (CR-228 C); -R-24/R-25 REQ→MOD allocation rules deleted (CR-228 A: REQ→MOD allocate no longer a valid pattern, R-18 flags residual edges); NFR-01 budget target split physical→MOD / behavioral→FCHAIN; RULE_TO_DIMENSION completeness (R-18..R-23/R-26/MS-03/CR-R04 mapped, no advisory fall-through) (CR-228 B/D); +BQ-01/02/04/06/07 base-quality rules promoted from aimpro (K2-b, completes rule consolidation); +ND-01/02 near-duplicate + AO-D01/D03/CR-01/RT-01/PH-01/CA-01/IO-01 architecture rules promoted from aimpro (K2-b); +CR-R01..04/MS-03 change-request rules promoted from aimpro (K2-b); +FM-01..03/NFR-01 FMEA + VR-01/CL-01 view rules promoted from aimpro (K2-b); +MT-01..03 architecture metrics promoted from aimpro (K2-b); +SC-01..03/UC-01..06/FC-01..03 quality rules promoted from aimpro (K2-a); +RC-05 cross-module import drift (CR-212); +R-26/RC-03/RC-04 schemaRef (CR-211); +R-22..R-25/R-10/R-20 (CR-201/202/208/209/210)
8
+ export const RULES_VERSION = '2.21.0'; // -MT-03 retired as a rule and reborn as the `allocationCohesion` measurement (CR-SM-223): the 80 % threshold fired on 6/7 graphcode, 4/4 gve and 10/11 family modules — in a flow-routed architecture cross-boundary interaction is the design, not a defect; the metric now reports internal/external per MOD, worst-first, and stays out of the violation stream so it cannot depress the readiness score; +RD-04 decomposition breadth (>11 children per level → warning) and MT-03 recalibrated to FLOW-transitive connection pairs — counting raw io traces reported internal=0 on every real SE graph (15/15 false positives), because the meta-model routes FUNC↔FUNC through FLOW; 'RD-' added to the se profile prefixes, where RD-01..04 were silently missing (CR-SM-221); -SC-01/-SC-03 deleted (BOK-CR-026): `realRef` is the single SCHEMA binding truth (R-26 presence, RC-03/RC-04 resolution); the legacy `zodDefinition`/`sourceFile`/`sourceExport` attributes are gone from every producer, SC_RULES = [SC-02]; R-20/R-26/RC-01/RC-03/RC-04 read realRef (unified codeRef+schemaRef); +R-27 physical-MOD realRef presence (CR-228 C); -R-24/R-25 REQ→MOD allocation rules deleted (CR-228 A: REQ→MOD allocate no longer a valid pattern, R-18 flags residual edges); NFR-01 budget target split physical→MOD / behavioral→FCHAIN; RULE_TO_DIMENSION completeness (R-18..R-23/R-26/MS-03/CR-R04 mapped, no advisory fall-through) (CR-228 B/D); +BQ-01/02/04/06/07 base-quality rules promoted from aimpro (K2-b, completes rule consolidation); +ND-01/02 near-duplicate + AO-D01/D03/CR-01/RT-01/PH-01/CA-01/IO-01 architecture rules promoted from aimpro (K2-b); +CR-R01..04/MS-03 change-request rules promoted from aimpro (K2-b); +FM-01..03/NFR-01 FMEA + VR-01/CL-01 view rules promoted from aimpro (K2-b); +MT-01..03 architecture metrics promoted from aimpro (K2-b); +SC-01..03/UC-01..06/FC-01..03 quality rules promoted from aimpro (K2-a); +RC-05 cross-module import drift (CR-212); +R-26/RC-03/RC-04 schemaRef (CR-211); +R-22..R-25/R-10/R-20 (CR-201/202/208/209/210)
9
9
  /** Meta-model version (trace pattern constraints + format-e parser). */
10
10
  export const META_MODEL_VERSION = '1.4.0'; // -REQ→MOD allocate pattern removed (CR-228 A); +FUNC→FUNC compose (blackbox function decomposition)
11
11
  export * from './ontology.js';
@@ -18,14 +18,41 @@ export declare function mt01Instability(graph: OntologyGraph): RuleViolation[];
18
18
  * Components > 1 → info.
19
19
  */
20
20
  export declare function mt02Lcom4(graph: OntologyGraph): RuleViolation[];
21
+ /** One module's allocation-cohesion measurement (CR-SM-223). */
22
+ export interface AllocationCohesion {
23
+ moduleId: string;
24
+ moduleName: string;
25
+ /** Connection pairs with both endpoints allocated to this module. */
26
+ internal: number;
27
+ /** Connection pairs with exactly one endpoint allocated to this module. */
28
+ external: number;
29
+ /** internal / (internal + external), in [0, 1]. */
30
+ cohesion: number;
31
+ }
21
32
  /**
22
- * MT-03: Allocation Cohesion (CR-191 reformulated, CR-SM-221 recalibrated).
23
- * cohesion = internal / (internal + external), over FLOW-transitive connection pairs.
24
- * internal = both endpoints allocated to this module.
25
- * external = exactly one endpoint allocated to this module.
26
- * If external === 0 cohesion = 100% OK.
33
+ * Allocation cohesion a **measurement, not a rule** (CR-SM-223, decision 2026-07-29).
34
+ *
35
+ * It used to be MT-03 with an 80 % threshold, and it fired on nearly every module of
36
+ * every real graph: 6 of 7 on graphcode, 4 of 4 on graph-view-edit, 10 of 11 on the
37
+ * family graph. `CR-SM-221` first suspected the edge definition and made it
38
+ * FLOW-transitive — the hit rate did not move. The threshold was the miscalibration:
39
+ * in a flow-routed layered architecture, module interaction crosses boundaries by
40
+ * design, so "80 % of interaction is internal" describes a monolith, not a healthy
41
+ * module.
42
+ *
43
+ * Rather than fit a cut-off to 11 data points, this reports the number and lets the
44
+ * architect judge. Returned worst-first, so the head of the list is where to look.
45
+ * Modules with fewer than two allocated FUNCs, or with no external connection at all,
46
+ * carry no signal and are omitted.
47
+ *
48
+ * Deliberately NOT a `RuleDefinition`: `computeReadiness` counts every violation into
49
+ * its dimension score regardless of severity, so a per-module advisory would depress
50
+ * the `alloc` score permanently. A measurement must not masquerade as a defect.
51
+ *
52
+ * Validation of this metric — and of MT-01/MT-02, which are thresholded the same way —
53
+ * is deferred (CR-SM-223).
27
54
  */
28
- export declare function mt03AllocationCohesion(graph: OntologyGraph): RuleViolation[];
55
+ export declare function allocationCohesion(graph: OntologyGraph): AllocationCohesion[];
29
56
  export declare const MT_RULES: readonly [{
30
57
  readonly id: "MT-01";
31
58
  readonly name: "Module instability";
@@ -36,10 +63,5 @@ export declare const MT_RULES: readonly [{
36
63
  readonly name: "Module cohesion (LCOM4)";
37
64
  readonly severity: "info";
38
65
  readonly evaluate: typeof mt02Lcom4;
39
- }, {
40
- readonly id: "MT-03";
41
- readonly name: "Allocation cohesion";
42
- readonly severity: "info";
43
- readonly evaluate: typeof mt03AllocationCohesion;
44
66
  }];
45
67
  export declare function evaluateMTRules(graph: OntologyGraph): RuleViolation[];
@@ -204,20 +204,34 @@ function connectionPairs(graph) {
204
204
  return pairs;
205
205
  }
206
206
  /**
207
- * MT-03: Allocation Cohesion (CR-191 reformulated, CR-SM-221 recalibrated).
208
- * cohesion = internal / (internal + external), over FLOW-transitive connection pairs.
209
- * internal = both endpoints allocated to this module.
210
- * external = exactly one endpoint allocated to this module.
211
- * If external === 0 cohesion = 100% OK.
207
+ * Allocation cohesion a **measurement, not a rule** (CR-SM-223, decision 2026-07-29).
208
+ *
209
+ * It used to be MT-03 with an 80 % threshold, and it fired on nearly every module of
210
+ * every real graph: 6 of 7 on graphcode, 4 of 4 on graph-view-edit, 10 of 11 on the
211
+ * family graph. `CR-SM-221` first suspected the edge definition and made it
212
+ * FLOW-transitive — the hit rate did not move. The threshold was the miscalibration:
213
+ * in a flow-routed layered architecture, module interaction crosses boundaries by
214
+ * design, so "80 % of interaction is internal" describes a monolith, not a healthy
215
+ * module.
216
+ *
217
+ * Rather than fit a cut-off to 11 data points, this reports the number and lets the
218
+ * architect judge. Returned worst-first, so the head of the list is where to look.
219
+ * Modules with fewer than two allocated FUNCs, or with no external connection at all,
220
+ * carry no signal and are omitted.
221
+ *
222
+ * Deliberately NOT a `RuleDefinition`: `computeReadiness` counts every violation into
223
+ * its dimension score regardless of severity, so a per-module advisory would depress
224
+ * the `alloc` score permanently. A measurement must not masquerade as a defect.
225
+ *
226
+ * Validation of this metric — and of MT-01/MT-02, which are thresholded the same way —
227
+ * is deferred (CR-SM-223).
212
228
  */
213
- export function mt03AllocationCohesion(graph) {
214
- const violations = [];
229
+ export function allocationCohesion(graph) {
230
+ const measurements = [];
215
231
  const mods = graph.elements.filter(e => e.type === 'MOD');
216
- const COHESION_THRESHOLD = 0.8;
217
232
  const pairs = [...connectionPairs(graph)].map(p => p.split('|'));
218
233
  for (const mod of mods) {
219
- const allocTraces = graph.traces.filter(t => t.type === 'allocate' && t.target === mod.id);
220
- const funcIds = new Set(allocTraces.map(t => t.source));
234
+ const funcIds = new Set(graph.traces.filter(t => t.type === 'allocate' && t.target === mod.id).map(t => t.source));
221
235
  if (funcIds.size < 2)
222
236
  continue;
223
237
  let internal = 0;
@@ -230,25 +244,24 @@ export function mt03AllocationCohesion(graph) {
230
244
  else if (aIn || bIn)
231
245
  external++;
232
246
  }
233
- // No external connections → cohesion = 100% OK
247
+ // No external connections → nothing to compare against, no signal.
234
248
  if (external === 0)
235
249
  continue;
236
- const cohesion = internal / (internal + external);
237
- if (cohesion < COHESION_THRESHOLD) {
238
- violations.push({
239
- rule_id: 'MT-03',
240
- severity: 'info',
241
- element_id: mod.id,
242
- message: `${mod.name} allocation cohesion ${Math.round(cohesion * 100)}% (<${COHESION_THRESHOLD * 100}%). internal=${internal}, external=${external}`,
243
- });
244
- }
250
+ measurements.push({
251
+ moduleId: mod.id,
252
+ moduleName: mod.name,
253
+ internal,
254
+ external,
255
+ cohesion: internal / (internal + external),
256
+ });
245
257
  }
246
- return violations;
258
+ // Worst first; stable by id so the ranking is deterministic.
259
+ return measurements.sort((a, b) => a.cohesion - b.cohesion || (a.moduleId < b.moduleId ? -1 : a.moduleId > b.moduleId ? 1 : 0));
247
260
  }
248
261
  export const MT_RULES = [
249
262
  { id: 'MT-01', name: 'Module instability', severity: 'warning', evaluate: mt01Instability },
250
263
  { id: 'MT-02', name: 'Module cohesion (LCOM4)', severity: 'info', evaluate: mt02Lcom4 },
251
- { id: 'MT-03', name: 'Allocation cohesion', severity: 'info', evaluate: mt03AllocationCohesion },
264
+ // MT-03 retired as a rule (CR-SM-223) see `allocationCohesion` above.
252
265
  ];
253
266
  export function evaluateMTRules(graph) {
254
267
  return MT_RULES.flatMap(r => r.evaluate(graph));
@@ -60,7 +60,9 @@ export const RULE_TO_DIMENSION = {
60
60
  // near-duplicate detection
61
61
  'ND-01': 'arch', 'ND-02': 'schema',
62
62
  // architecture metrics
63
- 'MT-01': 'alloc', 'MT-02': 'alloc', 'MT-03': 'alloc',
63
+ // MT-03 is no longer here: it became a measurement (`allocationCohesion`), not a
64
+ // rule (CR-SM-223) — a per-module advisory would depress this score permanently.
65
+ 'MT-01': 'alloc', 'MT-02': 'alloc',
64
66
  // CR traceability
65
67
  'CR-R01': 'cr', 'CR-R02': 'cr', 'CR-R03': 'cr', 'CR-R04': 'cr',
66
68
  // architecture optimization
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigloch/contracts",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",