yarramate 1.22.1 → 1.23.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/adapters/visual/protocol-contract.d.ts +54 -0
- package/dist/adapters/visual/wire.d.ts +10 -1
- package/dist/adapters/visual/workspace-model.d.ts +18 -2
- package/dist/adapters/visual/workspace-model.js +72 -2
- package/dist/compiler.d.ts +63 -0
- package/dist/compiler.js +30 -0
- package/dist/concept-drafting.d.ts +70 -0
- package/dist/concept-drafting.js +134 -0
- package/dist/index.d.ts +1 -1
- package/dist/visual-app/assets/index-5aKNHeZ0.js +394 -0
- package/dist/visual-app/assets/index-CnldeUHL.css +1 -0
- package/dist/visual-app/index.html +2 -2
- package/dist/visual-app-lib/editor.js +27601 -27139
- package/dist/visual-app-lib/styles.css +1 -1
- package/dist/visual-app-lib/types/adapters/visual/protocol-contract.d.ts +54 -0
- package/dist/visual-app-lib/types/adapters/visual/wire.d.ts +10 -1
- package/dist/visual-app-lib/types/adapters/visual/workspace-model.d.ts +18 -2
- package/dist/visual-app-lib/types/compiler.d.ts +63 -0
- package/dist/visual-app-lib/types/concept-drafting.d.ts +70 -0
- package/dist/visual-app-lib/types/visual-app/instance-draft-panel.d.ts +30 -0
- package/dist/visual-app-lib/types/visual-app/kind-palette.d.ts +29 -3
- package/dist/visual-app-lib/types/visual-app/slots-model.d.ts +18 -1
- package/docs/CONSUMING-YARRAMATE.md +34 -0
- package/package.json +1 -1
- package/schema/yarramate-visual-event.schema.json +6 -0
- package/dist/visual-app/assets/index-CM1MWXT2.js +0 -394
- package/dist/visual-app/assets/index-DF3anVfS.css +0 -1
|
@@ -147,9 +147,63 @@ export interface VisualViewSummary {
|
|
|
147
147
|
*/
|
|
148
148
|
readonly subjectCount: number;
|
|
149
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* One pattern a browser may offer, with everything a form needs to ask for its
|
|
152
|
+
* parts (#473 phase 4, ADR 0146).
|
|
153
|
+
*
|
|
154
|
+
* Built in `workspace-model.ts` so both hosts agree, for the reason the
|
|
155
|
+
* containment tree is: two derivations of what a pattern holds would be two
|
|
156
|
+
* answers to one question.
|
|
157
|
+
*/
|
|
158
|
+
export interface VisualPatternOption {
|
|
159
|
+
/** The concept kind that IS this pattern. */
|
|
160
|
+
readonly kind: string;
|
|
161
|
+
readonly label: string;
|
|
162
|
+
/** The core kind the pattern's own kind descends from. */
|
|
163
|
+
readonly coreLabel: string;
|
|
164
|
+
/** The pattern document that declared it, by path. */
|
|
165
|
+
readonly document: string;
|
|
166
|
+
/** The profile's display name for the kind, where it authored one. */
|
|
167
|
+
readonly name?: string;
|
|
168
|
+
readonly slots: readonly {
|
|
169
|
+
readonly name: string;
|
|
170
|
+
readonly required: boolean;
|
|
171
|
+
readonly wiring: "owned" | "context" | "unwired";
|
|
172
|
+
/**
|
|
173
|
+
* The kind LABELS this slot accepts, descendants already resolved.
|
|
174
|
+
*
|
|
175
|
+
* Resolved here rather than in the browser because it needs the lineage
|
|
176
|
+
* map: a slot declaring `kindMatching: descendants` admits a family, and a
|
|
177
|
+
* picker that offered only the declared kind would refuse subjects the
|
|
178
|
+
* compiler accepts.
|
|
179
|
+
*/
|
|
180
|
+
readonly admits: readonly string[];
|
|
181
|
+
}[];
|
|
182
|
+
readonly wiring: readonly {
|
|
183
|
+
readonly from: string;
|
|
184
|
+
readonly kind: string;
|
|
185
|
+
readonly to: string;
|
|
186
|
+
}[];
|
|
187
|
+
readonly ports: readonly {
|
|
188
|
+
readonly kind: string;
|
|
189
|
+
readonly out: string;
|
|
190
|
+
readonly in: string;
|
|
191
|
+
}[];
|
|
192
|
+
}
|
|
150
193
|
export interface VisualKindOption {
|
|
151
194
|
readonly id: string;
|
|
152
195
|
readonly label: string;
|
|
196
|
+
/**
|
|
197
|
+
* The pattern this kind IS, which for a pattern kind is its own id (#473
|
|
198
|
+
* phase 4). Absent on a kind no pattern declares, which is most of them.
|
|
199
|
+
*/
|
|
200
|
+
readonly pattern?: string;
|
|
201
|
+
/**
|
|
202
|
+
* The display name the profile authored, where it authored one. `label`
|
|
203
|
+
* stays the local id, because that is what a drag payload and an operation
|
|
204
|
+
* carry and the two must not drift.
|
|
205
|
+
*/
|
|
206
|
+
readonly name?: string;
|
|
153
207
|
/**
|
|
154
208
|
* The nearest core-profile kind this one descends from, as a label — the
|
|
155
209
|
* same resolution `CanvasNode.coreKindLabel` and `CanvasEdge.coreKindLabel`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CanvasGraph } from '../../graph-projection.js';
|
|
2
2
|
import type { PatternMembership, PatternVacancy } from '../../compiler.js';
|
|
3
|
-
import type { VISUAL_PROTOCOL_VERSION, VisualApplyResultPayload, VisualAuthority, VisualBrowserInput, VisualCapabilities, VisualChoicePresentPayload, VisualDiagnostic, VisualFilterResultPayload, VisualFreezeReason, VisualKindOption, VisualLayoutPositions, VisualLayoutSaveResultPayload, VisualResponse, VisualTerminationReason, VisualViewSummary } from './protocol-contract.js';
|
|
3
|
+
import type { VISUAL_PROTOCOL_VERSION, VisualApplyResultPayload, VisualAuthority, VisualBrowserInput, VisualCapabilities, VisualChoicePresentPayload, VisualDiagnostic, VisualFilterResultPayload, VisualFreezeReason, VisualKindOption, VisualPatternOption, VisualLayoutPositions, VisualLayoutSaveResultPayload, VisualResponse, VisualTerminationReason, VisualViewSummary } from './protocol-contract.js';
|
|
4
4
|
/**
|
|
5
5
|
* Transport shapes the session server and the browser application both speak.
|
|
6
6
|
*
|
|
@@ -51,6 +51,15 @@ export interface VisualRenderedModel {
|
|
|
51
51
|
readonly vocabulary: {
|
|
52
52
|
readonly conceptKinds: readonly VisualKindOption[];
|
|
53
53
|
readonly relationshipKinds: readonly VisualKindOption[];
|
|
54
|
+
/**
|
|
55
|
+
* The patterns this workspace declares, with their slots resolved to what
|
|
56
|
+
* each admits (#473 phase 4, ADR 0146).
|
|
57
|
+
*
|
|
58
|
+
* Optional, and ABSENT rather than empty where the workspace declares none:
|
|
59
|
+
* an empty list is a workspace with no patterns, while absence is a host
|
|
60
|
+
* that never looked, and a palette should be able to tell those apart.
|
|
61
|
+
*/
|
|
62
|
+
readonly patterns?: readonly VisualPatternOption[];
|
|
54
63
|
};
|
|
55
64
|
/** Every saved layout sidecar, keyed by projection id (Plan-level decision 1). */
|
|
56
65
|
readonly layouts: {
|
|
@@ -2,10 +2,11 @@ import type { Diagnostic } from "../../compiler.js";
|
|
|
2
2
|
import type { PendingWrite, SourceStore } from "../../source-store.js";
|
|
3
3
|
import type { ResolvedWorkspace } from "../../workspace.js";
|
|
4
4
|
import type { VisualDiagnostic, VisualViewOperation } from "./protocol-contract.js";
|
|
5
|
+
import type { PatternShape } from "../../compiler.js";
|
|
5
6
|
import type { NestingKind, ProjectionDefinition, ProjectionExclusion, ProjectionQuery } from "../../projection.js";
|
|
6
7
|
import type { ResolvedProfileContext, SemanticGraph } from "../../compiler.js";
|
|
7
8
|
import { type CataloguePatternMembership, type CataloguePatternVacancy } from "../../interrogate-command.js";
|
|
8
|
-
import type { VisualKindOption, VisualViewSummary } from "./protocol-contract.js";
|
|
9
|
+
import type { VisualKindOption, VisualPatternOption, VisualViewSummary } from "./protocol-contract.js";
|
|
9
10
|
import type { VisualInterrogationOverlay, VisualRenderedModel } from "./wire.js";
|
|
10
11
|
/**
|
|
11
12
|
* What a workspace looks like to the editor, however the editor is being run
|
|
@@ -31,7 +32,22 @@ import type { VisualInterrogationOverlay, VisualRenderedModel } from "./wire.js"
|
|
|
31
32
|
* keyed on core kinds, so offering an extension kind unchecked puts a `YM404`
|
|
32
33
|
* one click away.
|
|
33
34
|
*/
|
|
34
|
-
export declare const kindOptionsOf: (lineages: ReadonlyMap<string, readonly string[]
|
|
35
|
+
export declare const kindOptionsOf: (lineages: ReadonlyMap<string, readonly string[]>,
|
|
36
|
+
/** Which kinds ARE patterns, so a palette can group them (#473 phase 4). */
|
|
37
|
+
patterns?: ReadonlyMap<string, PatternShape>,
|
|
38
|
+
/** The profile's display names, where it authored any. */
|
|
39
|
+
names?: ReadonlyMap<string, string>) => readonly VisualKindOption[];
|
|
40
|
+
/**
|
|
41
|
+
* Every pattern a browser may offer, with its slots resolved to what they
|
|
42
|
+
* admit.
|
|
43
|
+
*
|
|
44
|
+
* `admits` is the expensive part and the reason this lives here rather than in
|
|
45
|
+
* the browser: a slot declaring `kindMatching: descendants` accepts a whole
|
|
46
|
+
* family, and resolving that needs the lineage map the frame does not carry.
|
|
47
|
+
* A picker built from the declared kind alone would refuse subjects the
|
|
48
|
+
* compiler accepts.
|
|
49
|
+
*/
|
|
50
|
+
export declare const patternOptionsOf: (patterns: readonly PatternShape[], lineages: ReadonlyMap<string, readonly string[]>, names?: ReadonlyMap<string, string>) => readonly VisualPatternOption[];
|
|
35
51
|
/**
|
|
36
52
|
* How many SUBJECTS a query matches, which is not the size of its match set.
|
|
37
53
|
*
|
|
@@ -31,11 +31,70 @@ import { evaluateCatalogue, composeCatalogues, } from "../../interrogate-command
|
|
|
31
31
|
* keyed on core kinds, so offering an extension kind unchecked puts a `YM404`
|
|
32
32
|
* one click away.
|
|
33
33
|
*/
|
|
34
|
-
export const kindOptionsOf = (lineages
|
|
34
|
+
export const kindOptionsOf = (lineages,
|
|
35
|
+
/** Which kinds ARE patterns, so a palette can group them (#473 phase 4). */
|
|
36
|
+
patterns = new Map(),
|
|
37
|
+
/** The profile's display names, where it authored any. */
|
|
38
|
+
names = new Map()) => [...lineages.keys()].map((id) => ({
|
|
35
39
|
id,
|
|
36
40
|
label: kindLabelOf(id),
|
|
37
41
|
coreLabel: kindLabelOf(lineages.get(id)?.[0] ?? id),
|
|
42
|
+
...(patterns.has(id) ? { pattern: id } : {}),
|
|
43
|
+
...(names.has(id) ? { name: names.get(id) } : {}),
|
|
38
44
|
}));
|
|
45
|
+
/**
|
|
46
|
+
* Every pattern a browser may offer, with its slots resolved to what they
|
|
47
|
+
* admit.
|
|
48
|
+
*
|
|
49
|
+
* `admits` is the expensive part and the reason this lives here rather than in
|
|
50
|
+
* the browser: a slot declaring `kindMatching: descendants` accepts a whole
|
|
51
|
+
* family, and resolving that needs the lineage map the frame does not carry.
|
|
52
|
+
* A picker built from the declared kind alone would refuse subjects the
|
|
53
|
+
* compiler accepts.
|
|
54
|
+
*/
|
|
55
|
+
export const patternOptionsOf = (patterns, lineages, names = new Map()) => patterns.map((pattern) => ({
|
|
56
|
+
kind: pattern.kindIdentity,
|
|
57
|
+
label: kindLabelOf(pattern.kindIdentity),
|
|
58
|
+
coreLabel: kindLabelOf(lineages.get(pattern.kindIdentity)?.[0] ?? pattern.kindIdentity),
|
|
59
|
+
document: pattern.declaredBy,
|
|
60
|
+
...(names.has(pattern.kindIdentity)
|
|
61
|
+
? { name: names.get(pattern.kindIdentity) }
|
|
62
|
+
: {}),
|
|
63
|
+
slots: pattern.slots.map((slot) => ({
|
|
64
|
+
name: slot.name,
|
|
65
|
+
required: slot.required,
|
|
66
|
+
wiring: wiringOf(pattern, slot.name),
|
|
67
|
+
admits: slot.kindMatching === "exact"
|
|
68
|
+
? [kindLabelOf(slot.kindIdentity)]
|
|
69
|
+
: [...lineages]
|
|
70
|
+
.filter(([, lineage]) => lineage.includes(slot.kindIdentity))
|
|
71
|
+
.map(([id]) => kindLabelOf(id))
|
|
72
|
+
.sort(),
|
|
73
|
+
})),
|
|
74
|
+
wiring: pattern.wiring.map((wire) => ({
|
|
75
|
+
from: wire.from,
|
|
76
|
+
kind: kindLabelOf(wire.kindIdentity),
|
|
77
|
+
to: wire.to,
|
|
78
|
+
})),
|
|
79
|
+
ports: pattern.ports.map((port) => ({
|
|
80
|
+
kind: kindLabelOf(port.kindIdentity),
|
|
81
|
+
out: port.out,
|
|
82
|
+
in: port.in,
|
|
83
|
+
})),
|
|
84
|
+
}));
|
|
85
|
+
/**
|
|
86
|
+
* How a pattern's wiring relates a slot to the instance, by the same rule the
|
|
87
|
+
* compiler applies (ADR 0143): `self -> slot` is owned, `slot -> self` is
|
|
88
|
+
* context, neither is unwired, and BOTH is owned, because the instance holding
|
|
89
|
+
* something out is the stronger statement.
|
|
90
|
+
*/
|
|
91
|
+
const wiringOf = (pattern, slot) => {
|
|
92
|
+
const out = pattern.wiring.some((wire) => wire.from === "self" && wire.to === slot);
|
|
93
|
+
const back = pattern.wiring.some((wire) => wire.from === slot && wire.to === "self");
|
|
94
|
+
if (out)
|
|
95
|
+
return "owned";
|
|
96
|
+
return back ? "context" : "unwired";
|
|
97
|
+
};
|
|
39
98
|
/**
|
|
40
99
|
* How many SUBJECTS a query matches, which is not the size of its match set.
|
|
41
100
|
*
|
|
@@ -135,8 +194,19 @@ export const renderedWorkspaceOf = (compiled, views, metadata, catalogue, dismis
|
|
|
135
194
|
...metadata,
|
|
136
195
|
graph: projectGraphForCanvas(compiled.graph, compiled.profileContext),
|
|
137
196
|
vocabulary: {
|
|
138
|
-
conceptKinds: kindOptionsOf(compiled.profileContext.conceptKindLineages)
|
|
197
|
+
conceptKinds: kindOptionsOf(compiled.profileContext.conceptKindLineages, new Map((compiled.profileContext.patterns ?? []).map((pattern) => [
|
|
198
|
+
pattern.kindIdentity,
|
|
199
|
+
pattern,
|
|
200
|
+
])), compiled.profileContext.conceptKindNames ?? new Map()),
|
|
139
201
|
relationshipKinds: kindOptionsOf(compiled.profileContext.relationshipKindLineages),
|
|
202
|
+
// Only where the workspace HAS patterns. An empty list would say the
|
|
203
|
+
// workspace declares none, which is a different claim from a host that
|
|
204
|
+
// never looked (rule 2), and the field is optional for exactly that.
|
|
205
|
+
...((compiled.profileContext.patterns ?? []).length === 0
|
|
206
|
+
? {}
|
|
207
|
+
: {
|
|
208
|
+
patterns: patternOptionsOf(compiled.profileContext.patterns ?? [], compiled.profileContext.conceptKindLineages, compiled.profileContext.conceptKindNames ?? new Map()),
|
|
209
|
+
}),
|
|
140
210
|
},
|
|
141
211
|
...(interrogation === undefined ? {} : { interrogation }),
|
|
142
212
|
// Containment context, forwarded rather than re-derived (#473). Both
|
package/dist/compiler.d.ts
CHANGED
|
@@ -29,6 +29,52 @@ export interface Diagnostic {
|
|
|
29
29
|
*/
|
|
30
30
|
readonly subjects?: readonly string[];
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* One slot of a pattern, as a CONSUMER reads it (#473 phase 4, ADR 0146).
|
|
34
|
+
*
|
|
35
|
+
* The resolved shape rather than the authored one: `kindIdentity` is qualified
|
|
36
|
+
* and `kindMatching` is explicit, so a caller deciding what a slot admits does
|
|
37
|
+
* not have to re-resolve the document it came from.
|
|
38
|
+
*/
|
|
39
|
+
export interface PatternSlotShape {
|
|
40
|
+
readonly name: string;
|
|
41
|
+
readonly kindIdentity: string;
|
|
42
|
+
readonly required: boolean;
|
|
43
|
+
readonly kindMatching: 'exact' | 'descendants';
|
|
44
|
+
}
|
|
45
|
+
/** A wire the pattern declares, `self` naming the instance. */
|
|
46
|
+
export interface PatternWireShape {
|
|
47
|
+
readonly from: string;
|
|
48
|
+
readonly to: string;
|
|
49
|
+
readonly kindIdentity: string;
|
|
50
|
+
}
|
|
51
|
+
/** Where a macro edge of one kind leaves and arrives (ADR 0124). */
|
|
52
|
+
export interface PatternPortShape {
|
|
53
|
+
readonly kindIdentity: string;
|
|
54
|
+
readonly out: string;
|
|
55
|
+
readonly in: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A pattern as the workspace resolved it.
|
|
59
|
+
*
|
|
60
|
+
* The pattern DOCUMENT has had a JSON schema since ADR 0123 and never a public
|
|
61
|
+
* TypeScript type, so a host that wanted to offer patterns had to re-read the
|
|
62
|
+
* YAML or guess. Slots come as an ordered array rather than a map because the
|
|
63
|
+
* order a pattern DECLARES them is the order a form should ask for them, and a
|
|
64
|
+
* map's iteration order is not something a consumer should have to trust.
|
|
65
|
+
*/
|
|
66
|
+
export interface PatternShape {
|
|
67
|
+
readonly kindIdentity: string;
|
|
68
|
+
/**
|
|
69
|
+
* The PATH of the pattern document that declared it, not that document's id.
|
|
70
|
+
* It is the same string a duplicate-declaration diagnostic names, so a host
|
|
71
|
+
* grouping patterns by document groups them by the thing a reader can open.
|
|
72
|
+
*/
|
|
73
|
+
readonly declaredBy: string;
|
|
74
|
+
readonly slots: readonly PatternSlotShape[];
|
|
75
|
+
readonly wiring: readonly PatternWireShape[];
|
|
76
|
+
readonly ports: readonly PatternPortShape[];
|
|
77
|
+
}
|
|
32
78
|
export interface GraphSource {
|
|
33
79
|
readonly document: string;
|
|
34
80
|
readonly path: string;
|
|
@@ -86,6 +132,23 @@ export interface ResolvedProfileContext {
|
|
|
86
132
|
* else.
|
|
87
133
|
*/
|
|
88
134
|
readonly patternPortKinds: ReadonlyMap<string, readonly RelationshipKind[]>;
|
|
135
|
+
/**
|
|
136
|
+
* Every pattern the workspace resolved, in kind order (#473 phase 4).
|
|
137
|
+
*
|
|
138
|
+
* Optional for the reason `patternMemberships` is: this shape is published
|
|
139
|
+
* and a required addition is free for readers and a break for CONSTRUCTORS.
|
|
140
|
+
* Read it as `?? []`. Absent, a host offers no patterns rather than offering
|
|
141
|
+
* an empty list of them.
|
|
142
|
+
*/
|
|
143
|
+
readonly patterns?: readonly PatternShape[];
|
|
144
|
+
/**
|
|
145
|
+
* Kind identity -> the display name its PROFILE authored (#473 phase 4).
|
|
146
|
+
*
|
|
147
|
+
* Only profile-declared kinds appear: a core kind's name is the vocabulary's
|
|
148
|
+
* own and a consumer already has it. Optional for the reason `patterns` is,
|
|
149
|
+
* and read as `?? new Map()`.
|
|
150
|
+
*/
|
|
151
|
+
readonly conceptKindNames?: ReadonlyMap<string, string>;
|
|
89
152
|
/**
|
|
90
153
|
* The core relationship kinds the ArchiMate table permits between two
|
|
91
154
|
* concept kind identities, resolved through lineage; undefined when either
|
package/dist/compiler.js
CHANGED
|
@@ -296,6 +296,10 @@ function compileWorkspaceResolved(parsed) {
|
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
298
|
const profiles = new Map();
|
|
299
|
+
// Kind identity -> the display name the profile authored for it (#473 phase
|
|
300
|
+
// 4). Resolution keeps identity, lineage, layer and aspect and drops the
|
|
301
|
+
// name, so a palette had nothing to show but the local id.
|
|
302
|
+
const conceptKindNames = new Map();
|
|
299
303
|
const conceptKindByIdentity = new Map();
|
|
300
304
|
const relationshipKindByIdentity = new Map();
|
|
301
305
|
const coreConceptKinds = new Map();
|
|
@@ -509,6 +513,7 @@ function compileWorkspaceResolved(parsed) {
|
|
|
509
513
|
};
|
|
510
514
|
resolvedConceptKinds.set(kind.id, resolved);
|
|
511
515
|
conceptKindByIdentity.set(resolved.identity, resolved);
|
|
516
|
+
conceptKindNames.set(resolved.identity, kind.name);
|
|
512
517
|
}
|
|
513
518
|
// No round can help what the last one could not.
|
|
514
519
|
if (deferred.length === 0 || deferred.length === pendingKinds.length) {
|
|
@@ -2578,6 +2583,31 @@ function compileWorkspaceResolved(parsed) {
|
|
|
2578
2583
|
relationshipKindCoreAncestors: immutableMap([...relationshipKindByIdentity]
|
|
2579
2584
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
2580
2585
|
.map(([identity, kind]) => [identity, kind.coreKind])),
|
|
2586
|
+
// Ordered by kind, and each pattern's slots in the order the document
|
|
2587
|
+
// DECLARED them, because that is the order a form should ask for them.
|
|
2588
|
+
conceptKindNames: immutableMap([...conceptKindNames].sort(([left], [right]) => left.localeCompare(right))),
|
|
2589
|
+
patterns: Object.freeze([...patternsByKind]
|
|
2590
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
2591
|
+
.map(([identity, pattern]) => ({
|
|
2592
|
+
kindIdentity: identity,
|
|
2593
|
+
declaredBy: pattern.declaredBy,
|
|
2594
|
+
slots: Object.freeze([...pattern.slots.values()].map((slot) => ({
|
|
2595
|
+
name: slot.name,
|
|
2596
|
+
kindIdentity: slot.kindIdentity,
|
|
2597
|
+
required: slot.required,
|
|
2598
|
+
kindMatching: slot.kindMatching,
|
|
2599
|
+
}))),
|
|
2600
|
+
wiring: Object.freeze(pattern.wiring.map((wire) => ({
|
|
2601
|
+
from: wire.from,
|
|
2602
|
+
to: wire.to,
|
|
2603
|
+
kindIdentity: wire.kindIdentity,
|
|
2604
|
+
}))),
|
|
2605
|
+
ports: Object.freeze([...pattern.ports].map(([kindIdentity, port]) => ({
|
|
2606
|
+
kindIdentity,
|
|
2607
|
+
out: port.out,
|
|
2608
|
+
in: port.in,
|
|
2609
|
+
}))),
|
|
2610
|
+
}))),
|
|
2581
2611
|
patternPortKinds: immutableMap([...patternsByKind]
|
|
2582
2612
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
2583
2613
|
.flatMap(([identity, pattern]) => pattern.ports.size === 0
|
|
@@ -36,3 +36,73 @@ export declare const draftConcept: (graph: CanvasGraph, input: {
|
|
|
36
36
|
readonly kind: string;
|
|
37
37
|
readonly document: string;
|
|
38
38
|
}, kinds: readonly string[], reserved?: Iterable<string>) => YarramateOperation | null;
|
|
39
|
+
/**
|
|
40
|
+
* What a reviewer chose for one slot of a pattern instance (#473 phase 4).
|
|
41
|
+
*
|
|
42
|
+
* `null` is a slot left alone, which is legal for an optional slot and is what
|
|
43
|
+
* the interview later asks about (ADR 0140). A required slot left null is
|
|
44
|
+
* refused here rather than staged and refused by the compiler, because a
|
|
45
|
+
* changeset that cannot land is worse than a form that will not submit.
|
|
46
|
+
*/
|
|
47
|
+
export type SlotBinding = {
|
|
48
|
+
readonly mode: 'existing';
|
|
49
|
+
readonly subject: string;
|
|
50
|
+
} | {
|
|
51
|
+
readonly mode: 'new';
|
|
52
|
+
readonly name: string;
|
|
53
|
+
readonly kind: string;
|
|
54
|
+
} | null;
|
|
55
|
+
export interface InstanceDraft {
|
|
56
|
+
readonly name: string;
|
|
57
|
+
readonly document: string;
|
|
58
|
+
/** The pattern's own kind, as a label, the same spelling an operation uses. */
|
|
59
|
+
readonly kind: string;
|
|
60
|
+
readonly slots: readonly {
|
|
61
|
+
readonly name: string;
|
|
62
|
+
readonly required: boolean;
|
|
63
|
+
/** Kind labels this slot accepts, descendants already resolved. */
|
|
64
|
+
readonly admits: readonly string[];
|
|
65
|
+
}[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A pattern instance and every child it mints, as ONE batch.
|
|
69
|
+
*
|
|
70
|
+
* Children first and the instance last, though `apply` compiles the whole
|
|
71
|
+
* candidate workspace atomically and would take either order: item 4.1 proved
|
|
72
|
+
* both, and emitting the order a reader would write by hand costs nothing and
|
|
73
|
+
* makes the diff read forwards.
|
|
74
|
+
*
|
|
75
|
+
* Every minted id is reserved as it is proposed, so two slots filled with the
|
|
76
|
+
* same name do not both slug to `payload` and have the second silently replace
|
|
77
|
+
* the first (#315, the defect that made `reservedIds` required).
|
|
78
|
+
*
|
|
79
|
+
* `null` rather than a partial batch when anything is wrong: a form that stages
|
|
80
|
+
* half an instance leaves the reviewer to discover the rest from a compile
|
|
81
|
+
* error.
|
|
82
|
+
*/
|
|
83
|
+
export declare const draftInstance: (graph: CanvasGraph, input: InstanceDraft, bindings: ReadonlyMap<string, SlotBinding>, reserved?: Iterable<string>) => readonly YarramateOperation[] | null;
|
|
84
|
+
/**
|
|
85
|
+
* Filling ONE slot of an instance that already exists (#473 phase 4).
|
|
86
|
+
*
|
|
87
|
+
* The other half of {@link draftInstance}: that one mints an instance and its
|
|
88
|
+
* parts together, this one answers a slot left open, which is what a
|
|
89
|
+
* `missing-part` card asks about (ADR 0140, #447). Both stage the same shape,
|
|
90
|
+
* so the model cannot tell which surface a binding came from.
|
|
91
|
+
*
|
|
92
|
+
* Merges BY SLOT, per ADR 0062's recorded convention: the operation names only
|
|
93
|
+
* the slot being filled, and the slots it does not mention are left alone
|
|
94
|
+
* (#448). There is no null idiom for retraction here, because retraction is
|
|
95
|
+
* coarse `remove: ['parts']` and is a different gesture from filling one.
|
|
96
|
+
*
|
|
97
|
+
* `null` rather than a partial batch: a child minted without the binding that
|
|
98
|
+
* uses it is a subject nobody asked for.
|
|
99
|
+
*/
|
|
100
|
+
export declare const draftSlotBinding: (graph: CanvasGraph, input: {
|
|
101
|
+
/** The instance whose slot is being filled. */
|
|
102
|
+
readonly instance: string;
|
|
103
|
+
readonly slot: string;
|
|
104
|
+
/** The document the operation writes to, and any minted child with it. */
|
|
105
|
+
readonly document: string;
|
|
106
|
+
/** Kind labels the slot accepts, descendants already resolved. */
|
|
107
|
+
readonly admits: readonly string[];
|
|
108
|
+
}, binding: SlotBinding, reserved?: Iterable<string>) => readonly YarramateOperation[] | null;
|
package/dist/concept-drafting.js
CHANGED
|
@@ -85,3 +85,137 @@ export const draftConcept = (graph, input, kinds, reserved = []) => {
|
|
|
85
85
|
concept: { id, kind: input.kind, name },
|
|
86
86
|
};
|
|
87
87
|
};
|
|
88
|
+
/**
|
|
89
|
+
* A pattern instance and every child it mints, as ONE batch.
|
|
90
|
+
*
|
|
91
|
+
* Children first and the instance last, though `apply` compiles the whole
|
|
92
|
+
* candidate workspace atomically and would take either order: item 4.1 proved
|
|
93
|
+
* both, and emitting the order a reader would write by hand costs nothing and
|
|
94
|
+
* makes the diff read forwards.
|
|
95
|
+
*
|
|
96
|
+
* Every minted id is reserved as it is proposed, so two slots filled with the
|
|
97
|
+
* same name do not both slug to `payload` and have the second silently replace
|
|
98
|
+
* the first (#315, the defect that made `reservedIds` required).
|
|
99
|
+
*
|
|
100
|
+
* `null` rather than a partial batch when anything is wrong: a form that stages
|
|
101
|
+
* half an instance leaves the reviewer to discover the rest from a compile
|
|
102
|
+
* error.
|
|
103
|
+
*/
|
|
104
|
+
export const draftInstance = (graph, input, bindings, reserved = []) => {
|
|
105
|
+
if (input.document === '')
|
|
106
|
+
return null;
|
|
107
|
+
const name = input.name.trim();
|
|
108
|
+
if (name === '')
|
|
109
|
+
return null;
|
|
110
|
+
const claimed = new Set(reserved);
|
|
111
|
+
const children = [];
|
|
112
|
+
const parts = {};
|
|
113
|
+
for (const slot of input.slots) {
|
|
114
|
+
const binding = bindings.get(slot.name) ?? null;
|
|
115
|
+
if (binding === null) {
|
|
116
|
+
// The model does not stand up without it, so the form cannot stage it.
|
|
117
|
+
if (slot.required)
|
|
118
|
+
return null;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (binding.mode === 'existing') {
|
|
122
|
+
if (binding.subject === '')
|
|
123
|
+
return null;
|
|
124
|
+
parts[slot.name] = binding.subject;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
// A minted child: its kind has to be one the slot admits, or the compiler
|
|
128
|
+
// refuses the binding and the reviewer learns it from a diagnostic.
|
|
129
|
+
if (!slot.admits.includes(binding.kind))
|
|
130
|
+
return null;
|
|
131
|
+
const childName = binding.name.trim();
|
|
132
|
+
if (childName === '')
|
|
133
|
+
return null;
|
|
134
|
+
const childId = proposeConceptId(graph, childName, claimed);
|
|
135
|
+
if (childId === null)
|
|
136
|
+
return null;
|
|
137
|
+
claimed.add(childId);
|
|
138
|
+
children.push({
|
|
139
|
+
op: 'add-concept',
|
|
140
|
+
// The instance's document, not a choice: a part authored somewhere else
|
|
141
|
+
// is a part the reader has to go looking for.
|
|
142
|
+
document: input.document,
|
|
143
|
+
concept: { id: childId, kind: binding.kind, name: childName },
|
|
144
|
+
});
|
|
145
|
+
parts[slot.name] = childId;
|
|
146
|
+
}
|
|
147
|
+
const instanceId = proposeConceptId(graph, name, claimed);
|
|
148
|
+
if (instanceId === null)
|
|
149
|
+
return null;
|
|
150
|
+
return [
|
|
151
|
+
...children,
|
|
152
|
+
{
|
|
153
|
+
op: 'add-concept',
|
|
154
|
+
document: input.document,
|
|
155
|
+
concept: {
|
|
156
|
+
id: instanceId,
|
|
157
|
+
kind: input.kind,
|
|
158
|
+
name,
|
|
159
|
+
// Omitted rather than empty where nothing was bound: an empty `parts`
|
|
160
|
+
// says the instance binds nothing, and the compiler reads the two the
|
|
161
|
+
// same way but a reader does not.
|
|
162
|
+
...(Object.keys(parts).length === 0 ? {} : { parts }),
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
];
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Filling ONE slot of an instance that already exists (#473 phase 4).
|
|
169
|
+
*
|
|
170
|
+
* The other half of {@link draftInstance}: that one mints an instance and its
|
|
171
|
+
* parts together, this one answers a slot left open, which is what a
|
|
172
|
+
* `missing-part` card asks about (ADR 0140, #447). Both stage the same shape,
|
|
173
|
+
* so the model cannot tell which surface a binding came from.
|
|
174
|
+
*
|
|
175
|
+
* Merges BY SLOT, per ADR 0062's recorded convention: the operation names only
|
|
176
|
+
* the slot being filled, and the slots it does not mention are left alone
|
|
177
|
+
* (#448). There is no null idiom for retraction here, because retraction is
|
|
178
|
+
* coarse `remove: ['parts']` and is a different gesture from filling one.
|
|
179
|
+
*
|
|
180
|
+
* `null` rather than a partial batch: a child minted without the binding that
|
|
181
|
+
* uses it is a subject nobody asked for.
|
|
182
|
+
*/
|
|
183
|
+
export const draftSlotBinding = (graph, input, binding, reserved = []) => {
|
|
184
|
+
if (binding === null)
|
|
185
|
+
return null;
|
|
186
|
+
if (input.document === '')
|
|
187
|
+
return null;
|
|
188
|
+
if (input.slot === '')
|
|
189
|
+
return null;
|
|
190
|
+
if (binding.mode === 'existing') {
|
|
191
|
+
if (binding.subject === '')
|
|
192
|
+
return null;
|
|
193
|
+
return [
|
|
194
|
+
{
|
|
195
|
+
op: 'update-concept',
|
|
196
|
+
document: input.document,
|
|
197
|
+
concept: { id: input.instance, parts: { [input.slot]: binding.subject } },
|
|
198
|
+
},
|
|
199
|
+
];
|
|
200
|
+
}
|
|
201
|
+
if (!input.admits.includes(binding.kind))
|
|
202
|
+
return null;
|
|
203
|
+
const childName = binding.name.trim();
|
|
204
|
+
if (childName === '')
|
|
205
|
+
return null;
|
|
206
|
+
const childId = proposeConceptId(graph, childName, reserved);
|
|
207
|
+
if (childId === null)
|
|
208
|
+
return null;
|
|
209
|
+
return [
|
|
210
|
+
{
|
|
211
|
+
op: 'add-concept',
|
|
212
|
+
document: input.document,
|
|
213
|
+
concept: { id: childId, kind: binding.kind, name: childName },
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
op: 'update-concept',
|
|
217
|
+
document: input.document,
|
|
218
|
+
concept: { id: input.instance, parts: { [input.slot]: childId } },
|
|
219
|
+
},
|
|
220
|
+
];
|
|
221
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export { constraintExpectsPredicate, reconcileEvidenceReports, type AssertedRela
|
|
|
10
10
|
export { deriveAttestationStaleness } from './attestation-staleness.js';
|
|
11
11
|
export { deriveArtifactCoverage, type ArtifactCoverage, type CoverageScopePattern, } from './artifact-coverage.js';
|
|
12
12
|
export { buildRtm, renderRtmMarkdown, type RequirementsTraceabilityMatrix, type RtmAttestation, type RtmContextEntry, type RtmDescopedEntry, type RtmEvidenceVerdict, type RtmLineageEntry, type RtmRealizer, type RtmRow, type RtmSource, } from './rtm.js';
|
|
13
|
-
export type { CompilationCache, CompilationResult, ContextualCompilationResult, IncrementalCompilationResult, ParsedWorkspaceSource, PatternMembership, PatternVacancy, Diagnostic, GraphClaim, GraphSource, SemanticGraph, ResolvedProfileContext, WorkspaceSource, } from './compiler.js';
|
|
13
|
+
export type { CompilationCache, CompilationResult, ContextualCompilationResult, IncrementalCompilationResult, ParsedWorkspaceSource, PatternMembership, PatternPortShape, PatternShape, PatternSlotShape, PatternVacancy, PatternWireShape, Diagnostic, GraphClaim, GraphSource, SemanticGraph, ResolvedProfileContext, WorkspaceSource, } from './compiler.js';
|
|
14
14
|
export { canonicalProjection, evaluateProjection, explainProjection, instanceClosureOf, loadProjection, renderProjectionMarkdown, type ConceptFacet, type ProjectionExclusion, } from './projection.js';
|
|
15
15
|
export { loadAdapterMapping, validateAdapterMapping, validateAdapterMappings, type AdapterMapping, type AdapterMappingLoadResult, type AdapterMappingValidationResult, type AdapterMappingsValidationResult, type AdapterSubjectMapping, } from './adapter-mapping.js';
|
|
16
16
|
export type { LifecycleStatus, ProjectionDefinition, ProjectionLoadResult, ProjectionResult, } from './projection.js';
|