yarramate 1.19.0 → 1.19.1

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/compiler.js CHANGED
@@ -428,63 +428,95 @@ function compileWorkspaceResolved(parsed) {
428
428
  continue;
429
429
  }
430
430
  const resolvedConceptKinds = new Map(parentProfile.conceptKinds);
431
- for (const [index, kind] of value.conceptKinds.entries()) {
432
- if (resolvedConceptKinds.has(kind.id)) {
433
- const position = positionFor(['conceptKinds', index, 'id']);
434
- profileDiagnostics.push({
435
- severity: 'error',
436
- code: 'YM409',
437
- message: `Concept kind "${kind.id}" conflicts with an inherited kind`,
438
- path: input.path,
439
- pointer: `/conceptKinds/${index}/id`,
440
- line: position.line,
441
- column: position.col,
442
- });
443
- continue;
444
- }
445
- const parent = conceptKindByIdentity.get(kind.parent);
446
- if (parent === undefined) {
447
- const position = positionFor(['conceptKinds', index, 'parent']);
448
- profileDiagnostics.push({
449
- severity: 'error',
450
- code: 'YM407',
451
- message: `Concept parent "${kind.parent}" is not available`,
452
- path: input.path,
453
- pointer: `/conceptKinds/${index}/parent`,
454
- line: position.line,
455
- column: position.col,
456
- });
457
- continue;
458
- }
459
- // OntoClean: an anti-rigid kind cannot subsume a rigid one. The
460
- // parent's lineage is the full ancestor chain, and subsumption is
461
- // transitive, so an unannotated kind sitting in between does not
462
- // launder the violation (ADR 0078).
463
- if (kind.rigidity === 'rigid') {
464
- const antiRigidAncestor = parent.lineage.find((ancestor) => conceptKindByIdentity.get(ancestor)?.rigidity === 'anti-rigid');
465
- if (antiRigidAncestor !== undefined) {
466
- const position = positionFor(['conceptKinds', index, 'rigidity']);
431
+ // A profile is a SET of kind declarations, so a kind whose parent is
432
+ // declared below it resolves like any other (#470). This used to be one
433
+ // pass in declaration order, which made a forward reference
434
+ // indistinguishable from a parent that does not exist - and `YM407` says
435
+ // "not available", so an author went looking for a missing kind while the
436
+ // file in front of them already declared it three lines down.
437
+ //
438
+ // Rounds until one adds nothing. Everything that compiled before compiles
439
+ // now and resolves on the first round, because parent-first was the only
440
+ // order that worked.
441
+ let pendingKinds = [...value.conceptKinds.entries()];
442
+ for (;;) {
443
+ const deferred = [];
444
+ for (const [index, kind] of pendingKinds) {
445
+ if (resolvedConceptKinds.has(kind.id)) {
446
+ const position = positionFor(['conceptKinds', index, 'id']);
467
447
  profileDiagnostics.push({
468
448
  severity: 'error',
469
- code: 'YM413',
470
- message: `Rigid concept kind "${kind.id}" specializes anti-rigid kind "${antiRigidAncestor}"; nothing is essentially of an anti-rigid kind, so parent "${kind.id}" under an entity kind, or drop its "rigid" annotation`,
449
+ code: 'YM409',
450
+ message: `Concept kind "${kind.id}" conflicts with an inherited kind`,
471
451
  path: input.path,
472
- pointer: `/conceptKinds/${index}/rigidity`,
452
+ pointer: `/conceptKinds/${index}/id`,
473
453
  line: position.line,
474
454
  column: position.col,
475
455
  });
476
456
  continue;
477
457
  }
458
+ const parent = conceptKindByIdentity.get(kind.parent);
459
+ if (parent === undefined) {
460
+ // Might resolve in a later round. Whether it never resolves at all
461
+ // is decided once the rounds stop, not here.
462
+ deferred.push([index, kind]);
463
+ continue;
464
+ }
465
+ // OntoClean: an anti-rigid kind cannot subsume a rigid one. The
466
+ // parent's lineage is the full ancestor chain, and subsumption is
467
+ // transitive, so an unannotated kind sitting in between does not
468
+ // launder the violation (ADR 0078).
469
+ if (kind.rigidity === 'rigid') {
470
+ const antiRigidAncestor = parent.lineage.find((ancestor) => conceptKindByIdentity.get(ancestor)?.rigidity === 'anti-rigid');
471
+ if (antiRigidAncestor !== undefined) {
472
+ const position = positionFor(['conceptKinds', index, 'rigidity']);
473
+ profileDiagnostics.push({
474
+ severity: 'error',
475
+ code: 'YM413',
476
+ message: `Rigid concept kind "${kind.id}" specializes anti-rigid kind "${antiRigidAncestor}"; nothing is essentially of an anti-rigid kind, so parent "${kind.id}" under an entity kind, or drop its "rigid" annotation`,
477
+ path: input.path,
478
+ pointer: `/conceptKinds/${index}/rigidity`,
479
+ line: position.line,
480
+ column: position.col,
481
+ });
482
+ continue;
483
+ }
484
+ }
485
+ const resolved = {
486
+ identity: `${identity}#${kind.id}`,
487
+ aspect: parent.aspect,
488
+ layer: kind.layer ?? parent.layer,
489
+ lineage: [...parent.lineage, `${identity}#${kind.id}`],
490
+ ...(kind.rigidity === undefined ? {} : { rigidity: kind.rigidity }),
491
+ };
492
+ resolvedConceptKinds.set(kind.id, resolved);
493
+ conceptKindByIdentity.set(resolved.identity, resolved);
478
494
  }
479
- const resolved = {
480
- identity: `${identity}#${kind.id}`,
481
- aspect: parent.aspect,
482
- layer: kind.layer ?? parent.layer,
483
- lineage: [...parent.lineage, `${identity}#${kind.id}`],
484
- ...(kind.rigidity === undefined ? {} : { rigidity: kind.rigidity }),
485
- };
486
- resolvedConceptKinds.set(kind.id, resolved);
487
- conceptKindByIdentity.set(resolved.identity, resolved);
495
+ // No round can help what the last one could not.
496
+ if (deferred.length === 0 || deferred.length === pendingKinds.length) {
497
+ pendingKinds = deferred;
498
+ break;
499
+ }
500
+ pendingKinds = deferred;
501
+ }
502
+ // What survived every round names a parent that never arrives. Two
503
+ // causes, and they are different problems for the author: the parent is
504
+ // declared nowhere, or it is in a cycle with this kind and neither can
505
+ // ever have a lineage.
506
+ const unresolvableIds = new Set(pendingKinds.map(([, kind]) => `${identity}#${kind.id}`));
507
+ for (const [index, kind] of pendingKinds) {
508
+ const position = positionFor(['conceptKinds', index, 'parent']);
509
+ profileDiagnostics.push({
510
+ severity: 'error',
511
+ code: 'YM407',
512
+ message: unresolvableIds.has(kind.parent)
513
+ ? `Concept parent "${kind.parent}" cannot resolve: it is in a parent cycle with "${kind.id}", so neither kind has a lineage`
514
+ : `Concept parent "${kind.parent}" is not available`,
515
+ path: input.path,
516
+ pointer: `/conceptKinds/${index}/parent`,
517
+ line: position.line,
518
+ column: position.col,
519
+ });
488
520
  }
489
521
  const resolvedRelationshipKinds = new Map(parentProfile.relationshipKinds);
490
522
  for (const [index, kind] of value.relationshipKinds.entries()) {
@@ -99301,75 +99301,87 @@ function KS(e) {
99301
99301
  });
99302
99302
  continue;
99303
99303
  }
99304
- let f = new Map(d.conceptKinds);
99305
- for (let [e, t] of s.conceptKinds.entries()) {
99306
- if (f.has(t.id)) {
99307
- let n = u([
99308
- "conceptKinds",
99309
- e,
99310
- "id"
99311
- ]);
99312
- l.push({
99313
- severity: "error",
99314
- code: "YM409",
99315
- message: `Concept kind "${t.id}" conflicts with an inherited kind`,
99316
- path: r.path,
99317
- pointer: `/conceptKinds/${e}/id`,
99318
- line: n.line,
99319
- column: n.col
99320
- });
99321
- continue;
99322
- }
99323
- let n = a.get(t.parent);
99324
- if (n === void 0) {
99325
- let n = u([
99326
- "conceptKinds",
99327
- e,
99328
- "parent"
99329
- ]);
99330
- l.push({
99331
- severity: "error",
99332
- code: "YM407",
99333
- message: `Concept parent "${t.parent}" is not available`,
99334
- path: r.path,
99335
- pointer: `/conceptKinds/${e}/parent`,
99336
- line: n.line,
99337
- column: n.col
99338
- });
99339
- continue;
99340
- }
99341
- if (t.rigidity === "rigid") {
99342
- let i = n.lineage.find((e) => a.get(e)?.rigidity === "anti-rigid");
99343
- if (i !== void 0) {
99344
- let n = u([
99304
+ let f = new Map(d.conceptKinds), p = [...s.conceptKinds.entries()];
99305
+ for (;;) {
99306
+ let e = [];
99307
+ for (let [t, n] of p) {
99308
+ if (f.has(n.id)) {
99309
+ let e = u([
99345
99310
  "conceptKinds",
99346
- e,
99347
- "rigidity"
99311
+ t,
99312
+ "id"
99348
99313
  ]);
99349
99314
  l.push({
99350
99315
  severity: "error",
99351
- code: "YM413",
99352
- message: `Rigid concept kind "${t.id}" specializes anti-rigid kind "${i}"; nothing is essentially of an anti-rigid kind, so parent "${t.id}" under an entity kind, or drop its "rigid" annotation`,
99316
+ code: "YM409",
99317
+ message: `Concept kind "${n.id}" conflicts with an inherited kind`,
99353
99318
  path: r.path,
99354
- pointer: `/conceptKinds/${e}/rigidity`,
99355
- line: n.line,
99356
- column: n.col
99319
+ pointer: `/conceptKinds/${t}/id`,
99320
+ line: e.line,
99321
+ column: e.col
99357
99322
  });
99358
99323
  continue;
99359
99324
  }
99325
+ let i = a.get(n.parent);
99326
+ if (i === void 0) {
99327
+ e.push([t, n]);
99328
+ continue;
99329
+ }
99330
+ if (n.rigidity === "rigid") {
99331
+ let e = i.lineage.find((e) => a.get(e)?.rigidity === "anti-rigid");
99332
+ if (e !== void 0) {
99333
+ let i = u([
99334
+ "conceptKinds",
99335
+ t,
99336
+ "rigidity"
99337
+ ]);
99338
+ l.push({
99339
+ severity: "error",
99340
+ code: "YM413",
99341
+ message: `Rigid concept kind "${n.id}" specializes anti-rigid kind "${e}"; nothing is essentially of an anti-rigid kind, so parent "${n.id}" under an entity kind, or drop its "rigid" annotation`,
99342
+ path: r.path,
99343
+ pointer: `/conceptKinds/${t}/rigidity`,
99344
+ line: i.line,
99345
+ column: i.col
99346
+ });
99347
+ continue;
99348
+ }
99349
+ }
99350
+ let o = {
99351
+ identity: `${c}#${n.id}`,
99352
+ aspect: i.aspect,
99353
+ layer: n.layer ?? i.layer,
99354
+ lineage: [...i.lineage, `${c}#${n.id}`],
99355
+ ...n.rigidity === void 0 ? {} : { rigidity: n.rigidity }
99356
+ };
99357
+ f.set(n.id, o), a.set(o.identity, o);
99360
99358
  }
99361
- let i = {
99362
- identity: `${c}#${t.id}`,
99363
- aspect: n.aspect,
99364
- layer: t.layer ?? n.layer,
99365
- lineage: [...n.lineage, `${c}#${t.id}`],
99366
- ...t.rigidity === void 0 ? {} : { rigidity: t.rigidity }
99367
- };
99368
- f.set(t.id, i), a.set(i.identity, i);
99359
+ if (e.length === 0 || e.length === p.length) {
99360
+ p = e;
99361
+ break;
99362
+ }
99363
+ p = e;
99364
+ }
99365
+ let m = new Set(p.map(([, e]) => `${c}#${e.id}`));
99366
+ for (let [e, t] of p) {
99367
+ let n = u([
99368
+ "conceptKinds",
99369
+ e,
99370
+ "parent"
99371
+ ]);
99372
+ l.push({
99373
+ severity: "error",
99374
+ code: "YM407",
99375
+ message: m.has(t.parent) ? `Concept parent "${t.parent}" cannot resolve: it is in a parent cycle with "${t.id}", so neither kind has a lineage` : `Concept parent "${t.parent}" is not available`,
99376
+ path: r.path,
99377
+ pointer: `/conceptKinds/${e}/parent`,
99378
+ line: n.line,
99379
+ column: n.col
99380
+ });
99369
99381
  }
99370
- let p = new Map(d.relationshipKinds);
99382
+ let h = new Map(d.relationshipKinds);
99371
99383
  for (let [e, t] of s.relationshipKinds.entries()) {
99372
- if (p.has(t.id)) {
99384
+ if (h.has(t.id)) {
99373
99385
  let n = u([
99374
99386
  "relationshipKinds",
99375
99387
  e,
@@ -99432,13 +99444,13 @@ function KS(e) {
99432
99444
  sourceAspects: t.sourceAspects ?? n.sourceAspects,
99433
99445
  targetAspects: t.targetAspects ?? n.targetAspects
99434
99446
  };
99435
- p.set(t.id, a), o.set(a.identity, a);
99447
+ h.set(t.id, a), o.set(a.identity, a);
99436
99448
  }
99437
99449
  i.set(c, {
99438
99450
  identity: c,
99439
99451
  lineage: [...d.lineage, c],
99440
99452
  conceptKinds: f,
99441
- relationshipKinds: p
99453
+ relationshipKinds: h
99442
99454
  }), t = !0;
99443
99455
  }
99444
99456
  if (!t) {
@@ -409,7 +409,7 @@ marked anywhere.
409
409
  | `YM1xx` | YAML parsing | `YM101` malformed YAML |
410
410
  | `YM2xx` | Document structure | `YM201` JSON Schema violation |
411
411
  | `YM3xx` | Identity and references | `YM301` duplicate local ID; `YM302` unresolved concept reference; `YM303` duplicate document ID; `YM304` unresolved owner or attestation authority; `YM305` unresolved constraint; `YM306` duplicate constraint ID; `YM307` unresolved architecture state; `YM308` unresolved subject reference; `YM309` duplicate reference ID; `YM310` unresolved distinct-from reference; `YM311` self-referential distinct-from; `YM312` unresolved succession reference; `YM313` self-referential succession; `YM314` cross-document duplicate ID; `YM315` unresolved or doubly-bound pattern part |
412
- | `YM4xx` | Profile conformance | `YM401` unknown concept kind; `YM402` unknown relationship kind; `YM403` unavailable profile; `YM404` incompatible endpoint; `YM405` misplaced controlled field; `YM406` unavailable parent profile; `YM407`/`YM408` unavailable semantic parent; `YM409`/`YM410` inherited-name collision; `YM411` duplicate profile; `YM412` broadened constraint; `YM413` rigid kind specializing an anti-rigid one; `YM414` mixed relationship kinds on one junction; `YM415` relationship forbidden by a declared constraint; `YM416` unbound required part; `YM417` part of the wrong kind; `YM418` relationship contradicting a pattern's wiring; `YM419` parts on a kind with no pattern, or an undeclared slot; `YM420` derived wiring or expansion id already taken; `YM421` macro edge with an unbound landing slot |
412
+ | `YM4xx` | Profile conformance | `YM401` unknown concept kind; `YM402` unknown relationship kind; `YM403` unavailable profile; `YM404` incompatible endpoint; `YM405` misplaced controlled field; `YM406` unavailable parent profile; `YM407`/`YM408` unavailable semantic parent, or one in a parent cycle; `YM409`/`YM410` inherited-name collision; `YM411` duplicate profile; `YM412` broadened constraint; `YM413` rigid kind specializing an anti-rigid one; `YM414` mixed relationship kinds on one junction; `YM415` relationship forbidden by a declared constraint; `YM416` unbound required part; `YM417` part of the wrong kind; `YM418` relationship contradicting a pattern's wiring; `YM419` parts on a kind with no pattern, or an undeclared slot; `YM420` derived wiring or expansion id already taken; `YM421` macro edge with an unbound landing slot |
413
413
  | `YM5xx` | Claim consistency | `YM501` competing whole-part claims; `YM502` cyclic state ordering; `YM503` relationship present without an endpoint; `YM504` cyclic succession |
414
414
  | `YM6xx` | Adapter mapping integrity | `YM601` unknown native subject; `YM602` subject type mismatch; `YM603` duplicate native mapping; `YM604` duplicate external mapping; `YM605` duplicate versioned mapping |
415
415
  | `YM7xx` | Workspace resolution | `YM701` unsafe pattern; `YM702` unmatched pattern; `YM703` cross-category file |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yarramate",
3
- "version": "1.19.0",
3
+ "version": "1.19.1",
4
4
  "description": "Tool-neutral semantic architecture engine and guided methodology",
5
5
  "license": "MIT",
6
6
  "repository": {