yarramate 1.3.0 → 1.4.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 (32) hide show
  1. package/catalogues/core-enrichment.yaml +13 -1
  2. package/dist/adapters/visual/workspace-model.d.ts +14 -2
  3. package/dist/adapters/visual/workspace-model.js +19 -9
  4. package/dist/ask-command.js +8 -1
  5. package/dist/compiler.d.ts +13 -1
  6. package/dist/compiler.js +646 -0
  7. package/dist/design-command.js +14 -3
  8. package/dist/graph-projection.d.ts +10 -0
  9. package/dist/graph-projection.js +1 -0
  10. package/dist/interrogate-command.d.ts +17 -0
  11. package/dist/interrogate-command.js +72 -40
  12. package/dist/relationship-drafting.js +16 -1
  13. package/dist/visual-app/assets/{index-C3i9SxTe.js → index-yCHtmQUH.js} +1 -1
  14. package/dist/visual-app/index.html +1 -1
  15. package/dist/visual-app-lib/editor.js +22875 -22261
  16. package/dist/visual-app-lib/types/adapters/visual/workspace-model.d.ts +14 -2
  17. package/dist/visual-app-lib/types/compiler.d.ts +13 -1
  18. package/dist/visual-app-lib/types/graph-projection.d.ts +10 -0
  19. package/dist/visual-app-lib/types/interrogate-command.d.ts +17 -0
  20. package/dist/visual-app-lib/types/visual-app/local-host.d.ts +42 -0
  21. package/dist/visual-app-lib/types/workspace.d.ts +2 -0
  22. package/dist/workspace.d.ts +2 -0
  23. package/dist/workspace.js +1 -0
  24. package/docs/CONSUMING-YARRAMATE.md +41 -0
  25. package/package.json +2 -1
  26. package/schema/yarramate-design-step.schema.json +13 -0
  27. package/schema/yarramate-document.schema.json +14 -0
  28. package/schema/yarramate-interrogation-report.schema.json +18 -0
  29. package/schema/yarramate-pattern.schema.json +133 -0
  30. package/schema/yarramate-question-catalogue.schema.json +21 -0
  31. package/schema/yarramate-visual-graph.schema.json +9 -0
  32. package/schema/yarramate-workspace.schema.json +4 -0
@@ -1,6 +1,6 @@
1
1
  format: yarramate/question-catalogue/v1
2
2
  id: core-enrichment
3
- version: "1.2"
3
+ version: "1.3"
4
4
  profile: yarramate/core@0.1
5
5
  presentation:
6
6
  title: Core enrichment interview
@@ -25,27 +25,39 @@ waves:
25
25
  Load-bearing hops: the behavior a component is assigned to or the
26
26
  interface it composes, the serving/triggering/flow mechanism,
27
27
  payload, trust, reliability, and capacity. Hygiene waits.
28
+ opensWhen:
29
+ - condition: has-any-subject
28
30
  - id: business
29
31
  name: Business
30
32
  description: Who acts, what is served, and what information matters.
33
+ opensWhen:
34
+ - condition: has-any-subject
31
35
  - id: application
32
36
  name: Application
33
37
  description: >-
34
38
  How declared services are realized, performed, and fed with
35
39
  information.
40
+ opensWhen:
41
+ - condition: has-any-subject
36
42
  - id: technology
37
43
  name: Technology
38
44
  description: >-
39
45
  Where the declared applications actually run and what materializes
40
46
  them.
47
+ opensWhen:
48
+ - condition: has-any-subject
41
49
  - id: implementation
42
50
  name: Implementation
43
51
  description: >-
44
52
  How the planned architecture becomes real: work, deliverables, and
45
53
  the plateaus between here and there.
54
+ opensWhen:
55
+ - condition: has-any-subject
46
56
  - id: hygiene
47
57
  name: Model hygiene
48
58
  description: Cross-cutting completeness that keeps every wave honest.
59
+ opensWhen:
60
+ - condition: has-any-subject
49
61
 
50
62
  questions:
51
63
  # ---- motivation ----------------------------------------------------------
@@ -49,13 +49,25 @@ export declare const conceptCountOf: (graph: SemanticGraph, query: ProjectionQue
49
49
  * Subject ids come from the same compiled graph as `CanvasNode.id`, so the
50
50
  * join in the browser is a plain lookup.
51
51
  */
52
+ export interface DismissedQuestion {
53
+ readonly questionId: string;
54
+ /** Absent dismisses the question wherever it appears. */
55
+ readonly subject?: string;
56
+ }
52
57
  export declare const interrogationOverlayOf: (compiled: {
53
58
  readonly graph: SemanticGraph;
54
59
  readonly profileContext: ResolvedProfileContext;
55
60
  }, catalogue: {
56
61
  readonly path: string;
57
62
  readonly source: string;
58
- }) => VisualInterrogationOverlay | undefined;
63
+ },
64
+ /**
65
+ * What the host has already dealt with (#328). Evaluation is unchanged and
66
+ * the model is untouched: this decides only what the pane draws, because a
67
+ * question set aside in the host's own product should not be asked again by
68
+ * a pane embedded in it.
69
+ */
70
+ dismissed?: readonly DismissedQuestion[]) => VisualInterrogationOverlay | undefined;
59
71
  /**
60
72
  * Rebuilds the shared editor workspace from one successful compile.
61
73
  *
@@ -71,7 +83,7 @@ export declare const renderedWorkspaceOf: (compiled: {
71
83
  }, views: readonly VisualViewSummary[], metadata: Omit<VisualRenderedModel, "graph" | "vocabulary" | "interrogation">, catalogue?: {
72
84
  readonly path: string;
73
85
  readonly source: string;
74
- }) => {
86
+ }, dismissed?: readonly DismissedQuestion[]) => {
75
87
  readonly model: VisualRenderedModel;
76
88
  readonly views: readonly VisualViewSummary[];
77
89
  };
@@ -46,25 +46,32 @@ export const kindOptionsOf = (lineages) => [...lineages.keys()].map((id) => ({
46
46
  * them would read as five, and the reviewer counting boxes would find three.
47
47
  */
48
48
  export const conceptCountOf = (graph, query, profileContext) => evaluateProjection(graph, adHoc(query), profileContext).subjects.filter(({ type }) => type === "concept").length;
49
+ export const interrogationOverlayOf = (compiled, catalogue,
49
50
  /**
50
- * Folds one interrogation report into what the canvas draws (#292).
51
- *
52
- * Undefined never a throw when the catalogue does not load: the overlay
53
- * is a garnish on the model, and a model frame must not be blocked by it.
54
- * Subject ids come from the same compiled graph as `CanvasNode.id`, so the
55
- * join in the browser is a plain lookup.
51
+ * What the host has already dealt with (#328). Evaluation is unchanged and
52
+ * the model is untouched: this decides only what the pane draws, because a
53
+ * question set aside in the host's own product should not be asked again by
54
+ * a pane embedded in it.
56
55
  */
57
- export const interrogationOverlayOf = (compiled, catalogue) => {
56
+ dismissed = []) => {
58
57
  const loaded = loadQuestionCatalogue(catalogue);
59
58
  if (!loaded.ok)
60
59
  return undefined;
61
60
  const report = evaluateCatalogue(loaded.catalogue, compiled.graph, compiled.profileContext);
61
+ const dismissedEverywhere = new Set(dismissed
62
+ .filter(({ subject }) => subject === undefined)
63
+ .map(({ questionId }) => questionId));
64
+ const dismissedForSubject = new Set(dismissed
65
+ .filter(({ subject }) => subject !== undefined)
66
+ .map(({ questionId, subject }) => `${questionId}\u0000${subject}`));
62
67
  const workspace = [];
63
68
  const subjects = {};
64
69
  for (const wave of report.waves) {
65
70
  for (const question of wave.questions) {
66
71
  if (!question.open)
67
72
  continue;
73
+ if (dismissedEverywhere.has(question.id))
74
+ continue;
68
75
  const base = {
69
76
  questionId: question.id,
70
77
  authority: question.authority,
@@ -75,6 +82,9 @@ export const interrogationOverlayOf = (compiled, catalogue) => {
75
82
  continue;
76
83
  }
77
84
  for (const subject of question.subjects) {
85
+ if (dismissedForSubject.has(`${question.id}\u0000${subject.id}`)) {
86
+ continue;
87
+ }
78
88
  (subjects[subject.id] ??= []).push({
79
89
  ...base,
80
90
  question: subject.question,
@@ -98,14 +108,14 @@ export const interrogationOverlayOf = (compiled, catalogue) => {
98
108
  * is the question catalogue's bytes — this module cannot read files, so
99
109
  * whoever can hands them over; omitting it ships a model with no overlay.
100
110
  */
101
- export const renderedWorkspaceOf = (compiled, views, metadata, catalogue) => {
111
+ export const renderedWorkspaceOf = (compiled, views, metadata, catalogue, dismissed) => {
102
112
  const refreshedViews = views.map((view) => ({
103
113
  ...view,
104
114
  subjectCount: conceptCountOf(compiled.graph, view.query, compiled.profileContext),
105
115
  }));
106
116
  const interrogation = catalogue === undefined
107
117
  ? undefined
108
- : interrogationOverlayOf(compiled, catalogue);
118
+ : interrogationOverlayOf(compiled, catalogue, dismissed);
109
119
  return {
110
120
  model: {
111
121
  ...metadata,
@@ -500,8 +500,15 @@ export function runAskCommand(options, cwd) {
500
500
  if (reconciliation !== undefined) {
501
501
  lines.push(reconciliationLine(reconciliation));
502
502
  }
503
+ // Zero open has two causes and only one is complete (#334): a
504
+ // catalogue whose waves are all gated shut has asked nothing, and
505
+ // reporting that as a finished interview is the same empty-set
506
+ // flattery the wave rail carried.
507
+ const askedAnything = report.waves.some((wave) => wave.questions.length > 0);
503
508
  lines.push(report.summary.open === 0
504
- ? `Design interview complete (catalogue ${report.catalogue}): no open questions.`
509
+ ? askedAnything
510
+ ? `Design interview complete (catalogue ${report.catalogue}): no open questions.`
511
+ : `Design interview not started (catalogue ${report.catalogue}): no wave has opened yet.`
505
512
  : `Design interview: ${plural(report.summary.open, 'open question')} (catalogue ${report.catalogue}) — continue: yarramate design ${workspacePath}`, '', 'Backlog — planned, dependency order:', ...plannedLines(planned), '', `Current: ${plural(current.length, 'subject')} · Retired: ${retired.length} ` +
506
513
  `(roster: yarramate ask ${workspacePath} --subjects)`);
507
514
  return emit(result, `${lines.join('\n')}\n`);
@@ -74,6 +74,18 @@ export interface ResolvedProfileContext {
74
74
  /** Kind identity -> the core kind it resolves to through lineage. */
75
75
  readonly conceptKindCoreAncestors: ReadonlyMap<string, CoreConceptKindId>;
76
76
  readonly relationshipKindCoreAncestors: ReadonlyMap<string, RelationshipKind>;
77
+ /**
78
+ * The core relationship kinds a pattern PORTS for a concept kind (#268
79
+ * phase 3, ADR 0124), keyed by kind identity. Only kinds that have a
80
+ * pattern with ports appear.
81
+ *
82
+ * A macro edge needs both ends to port its kind, so a consumer offering a
83
+ * palette between two instances intersects the two sets. Two raw groupings
84
+ * permit ten of the eleven kinds, which is no narrowing at all; the ports
85
+ * are what restore the guidance the relationship table gives everywhere
86
+ * else.
87
+ */
88
+ readonly patternPortKinds: ReadonlyMap<string, readonly RelationshipKind[]>;
77
89
  /**
78
90
  * The core relationship kinds the ArchiMate table permits between two
79
91
  * concept kind identities, resolved through lineage; undefined when either
@@ -104,7 +116,7 @@ export type ContextualCompilationResult = {
104
116
  */
105
117
  export interface ParsedWorkspaceSource {
106
118
  readonly source: string;
107
- readonly kind: 'profile' | 'document';
119
+ readonly kind: 'profile' | 'document' | 'pattern';
108
120
  readonly value: unknown;
109
121
  readonly schemaDiagnostics: readonly Diagnostic[];
110
122
  /**