yarramate 1.2.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.
- package/catalogues/core-enrichment.yaml +237 -2
- package/dist/adapters/visual/session-server.js +16 -1
- package/dist/adapters/visual/view-identity.d.ts +1 -1
- package/dist/adapters/visual/view-identity.js +61 -3
- package/dist/adapters/visual/wire.d.ts +30 -0
- package/dist/adapters/visual/workspace-model.d.ts +35 -3
- package/dist/adapters/visual/workspace-model.js +62 -2
- package/dist/ask-command.js +37 -14
- package/dist/cli-support.d.ts +1 -1
- package/dist/cli-support.js +1 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +26 -5
- package/dist/compiler.d.ts +13 -1
- package/dist/compiler.js +646 -0
- package/dist/concept-drafting.d.ts +13 -2
- package/dist/concept-drafting.js +15 -3
- package/dist/design-command.js +30 -4
- package/dist/evidence.js +25 -0
- package/dist/graph-projection.d.ts +10 -0
- package/dist/graph-projection.js +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/interrogate-command.d.ts +37 -1
- package/dist/interrogate-command.js +93 -42
- package/dist/interrogation-entry.d.ts +1 -1
- package/dist/layout-direction.d.ts +14 -0
- package/dist/layout-direction.js +5 -0
- package/dist/projection.d.ts +22 -6
- package/dist/projection.js +23 -2
- package/dist/relationship-drafting.d.ts +21 -2
- package/dist/relationship-drafting.js +49 -4
- package/dist/subject-references.js +5 -0
- package/dist/visual-app/assets/index-Rkq6smL2.css +1 -0
- package/dist/visual-app/assets/index-yCHtmQUH.js +394 -0
- package/dist/visual-app/index.html +2 -2
- package/dist/visual-app-lib/editor.js +29639 -27514
- package/dist/visual-app-lib/styles.css +1 -1
- package/dist/visual-app-lib/types/adapters/visual/view-identity.d.ts +1 -1
- package/dist/visual-app-lib/types/adapters/visual/wire.d.ts +30 -0
- package/dist/visual-app-lib/types/adapters/visual/workspace-model.d.ts +35 -3
- package/dist/visual-app-lib/types/compiler.d.ts +13 -1
- package/dist/visual-app-lib/types/concept-drafting.d.ts +13 -2
- package/dist/visual-app-lib/types/graph-projection.d.ts +10 -0
- package/dist/visual-app-lib/types/interrogate-command.d.ts +207 -0
- package/dist/visual-app-lib/types/layout-direction.d.ts +14 -0
- package/dist/visual-app-lib/types/projection.d.ts +22 -6
- package/dist/visual-app-lib/types/relationship-drafting.d.ts +21 -2
- package/dist/visual-app-lib/types/subject-identity.d.ts +34 -0
- package/dist/visual-app-lib/types/visual-app/App.d.ts +27 -2
- package/dist/visual-app-lib/types/visual-app/badges.d.ts +1 -0
- package/dist/visual-app-lib/types/visual-app/connection-panel.d.ts +9 -1
- package/dist/visual-app-lib/types/visual-app/context-menu-model.d.ts +15 -6
- package/dist/visual-app-lib/types/visual-app/graph-canvas.d.ts +77 -6
- package/dist/visual-app-lib/types/visual-app/kind-palette.d.ts +37 -0
- package/dist/visual-app-lib/types/visual-app/local-host.d.ts +42 -0
- package/dist/visual-app-lib/types/visual-app/mount.d.ts +73 -2
- package/dist/visual-app-lib/types/visual-app/open-questions.d.ts +15 -0
- package/dist/visual-app-lib/types/visual-app/query-fields.d.ts +3 -2
- package/dist/visual-app-lib/types/visual-app/query-panel.d.ts +8 -1
- package/dist/visual-app-lib/types/visual-app/save-view.d.ts +11 -5
- package/dist/visual-app-lib/types/visual-app/shipped-catalogue.d.ts +10 -0
- package/dist/visual-app-lib/types/visual-app/state.d.ts +15 -4
- package/dist/visual-app-lib/types/visual-app/subject-draft-panel.d.ts +13 -1
- package/dist/visual-app-lib/types/visual-app/subject-filter.d.ts +35 -0
- package/dist/visual-app-lib/types/visual-app/subject-form.d.ts +8 -0
- package/dist/visual-app-lib/types/visual-app/view-tree-model.d.ts +42 -9
- package/dist/visual-app-lib/types/visual-app/view-tree.d.ts +11 -2
- package/dist/visual-app-lib/types/visual-app/workspace-state.d.ts +81 -11
- package/dist/visual-app-lib/types/workspace.d.ts +2 -0
- package/dist/workspace.d.ts +2 -0
- package/dist/workspace.js +1 -0
- package/docs/CONSUMING-YARRAMATE.md +81 -0
- package/package.json +2 -1
- package/schema/yarramate-design-step.schema.json +26 -0
- package/schema/yarramate-document.schema.json +14 -0
- package/schema/yarramate-interrogation-report.schema.json +31 -0
- package/schema/yarramate-pattern.schema.json +133 -0
- package/schema/yarramate-projection.schema.json +9 -0
- package/schema/yarramate-question-catalogue.schema.json +34 -0
- package/schema/yarramate-visual-graph.schema.json +9 -0
- package/schema/yarramate-workspace.schema.json +4 -0
- package/skills/yarramate-architecture/SKILL.md +5 -0
- package/dist/visual-app/assets/index-CcmfL3oY.js +0 -394
- package/dist/visual-app/assets/index-DLutIWES.css +0 -1
|
@@ -12,11 +12,23 @@ import type { VisualKindOption } from '../adapters/visual/protocol-contract.js';
|
|
|
12
12
|
* than a transliteration of the name does. It is shown before landing, because
|
|
13
13
|
* a derived address the author never saw is one nobody agreed to.
|
|
14
14
|
*/
|
|
15
|
-
export declare const SubjectDraftPanel: ({ graph, kinds, documents, defaultDocument, onStage, onCancel, }: {
|
|
15
|
+
export declare const SubjectDraftPanel: ({ graph, kinds, documents, defaultDocument, initialKind, reservedIds, onStage, onCancel, }: {
|
|
16
16
|
readonly graph: CanvasGraph;
|
|
17
17
|
readonly kinds: readonly VisualKindOption[];
|
|
18
18
|
readonly documents: readonly string[];
|
|
19
19
|
readonly defaultDocument: string;
|
|
20
|
+
/** A kind the reviewer picked up on the way in - dragged from the palette
|
|
21
|
+
* or clicked there (#295). Their own choice arriving with the gesture, not
|
|
22
|
+
* a default this form chose for them, so the no-default rule below stands. */
|
|
23
|
+
readonly initialKind?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Ids the pending changeset already claims. The graph only knows what has
|
|
26
|
+
* landed, so without these a second subject slugging to the same id
|
|
27
|
+
* proposed it again and replace-by-target staging swallowed the first
|
|
28
|
+
* silently (#315). Required rather than defaulted: a caller has to say
|
|
29
|
+
* what is staged, even when the answer is nothing.
|
|
30
|
+
*/
|
|
31
|
+
readonly reservedIds: readonly string[];
|
|
20
32
|
readonly onStage: (operation: YarramateOperation) => void;
|
|
21
33
|
readonly onCancel: () => void;
|
|
22
34
|
}) => React.ReactElement;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one substring judgement every surface that filters subjects by typed
|
|
3
|
+
* text shares.
|
|
4
|
+
*
|
|
5
|
+
* #307 extracted the predicate inside `graph-canvas.tsx` so the canvas pass
|
|
6
|
+
* and the shell's empty-state honesty could not drift; #317 lifts it here so
|
|
7
|
+
* the rail's tree filter can share it too. It cannot simply be imported from
|
|
8
|
+
* `graph-canvas.tsx`: the rail's tree model (`view-tree-model.ts`) keeps a
|
|
9
|
+
* zero-dependency discipline — no React, no cytoscape — and merely loading
|
|
10
|
+
* the canvas module registers cytoscape-elk. So the predicate lives in this
|
|
11
|
+
* small pure module and both surfaces import it from here.
|
|
12
|
+
*/
|
|
13
|
+
import type { CanvasNode } from "../graph-projection.js";
|
|
14
|
+
/**
|
|
15
|
+
* The slice of a subject the predicate reads — the render data both the
|
|
16
|
+
* canvas and the rail already hold.
|
|
17
|
+
*/
|
|
18
|
+
export type FilterableSubject = Pick<CanvasNode, "id" | "name" | "kindLabel">;
|
|
19
|
+
/**
|
|
20
|
+
* Typed filter text made comparable: trimmed and lowercased, once, so every
|
|
21
|
+
* surface trims the same way before matching.
|
|
22
|
+
*/
|
|
23
|
+
export declare const normalizeFilterText: (text: string) => string;
|
|
24
|
+
/**
|
|
25
|
+
* Whether a subject survives the typed text: case-insensitive, against its
|
|
26
|
+
* id, name, and kind label. `name` and `kindLabel` are `unknown` because the
|
|
27
|
+
* canvas reads them out of cytoscape data, which types nothing.
|
|
28
|
+
*/
|
|
29
|
+
export declare function subjectMatchesQuickFilter(trimmedLowerFilter: string, id: string, name: unknown, kindLabel: unknown): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* How many of these subjects survive the typed text — the number a tree row
|
|
32
|
+
* shows while the filter narrows (#317). With no text every subject
|
|
33
|
+
* survives, so this is also the plain length.
|
|
34
|
+
*/
|
|
35
|
+
export declare const countMatchingSubjects: (subjects: readonly FilterableSubject[], filterText: string) => number;
|
|
@@ -32,6 +32,14 @@ export interface ConceptFormProps {
|
|
|
32
32
|
readonly onStageChange: (operation: YarramateOperation) => void;
|
|
33
33
|
}
|
|
34
34
|
export declare const ConceptForm: ({ node, model, operations, onStageChange }: ConceptFormProps) => import("react").JSX.Element;
|
|
35
|
+
export declare const ConceptFacts: ({ node, model, }: {
|
|
36
|
+
readonly node: CanvasNode;
|
|
37
|
+
readonly model: VisualRenderedModel;
|
|
38
|
+
}) => import("react").JSX.Element;
|
|
39
|
+
export declare const RelationshipFacts: ({ edge, model, }: {
|
|
40
|
+
readonly edge: CanvasEdge;
|
|
41
|
+
readonly model: VisualRenderedModel;
|
|
42
|
+
}) => import("react").JSX.Element;
|
|
35
43
|
export interface RelationshipFormProps {
|
|
36
44
|
readonly edge: CanvasEdge;
|
|
37
45
|
readonly model: VisualRenderedModel;
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* What the left rail shows, as data.
|
|
3
3
|
*
|
|
4
4
|
* The rail is two trees over things the session already has — the saved views
|
|
5
|
-
*
|
|
5
|
+
* with the reviewer's staged view operations merged over them (ADR 0114), and
|
|
6
|
+
* the subjects the model declares — so everything it decides is a pure
|
|
6
7
|
* function of those plus what the reviewer typed. It lives outside the
|
|
7
8
|
* component for the reason `filterToReresolve` does: this repo renders React
|
|
8
9
|
* with `renderToStaticMarkup` and has no DOM test environment, so logic that
|
|
@@ -13,7 +14,8 @@
|
|
|
13
14
|
*/
|
|
14
15
|
import type { CanvasNode } from "../graph-projection.js";
|
|
15
16
|
import type { Layer } from "../profile.js";
|
|
16
|
-
import type { VisualViewSummary } from "../adapters/visual/protocol-contract.js";
|
|
17
|
+
import type { VisualViewOperation, VisualViewSummary } from "../adapters/visual/protocol-contract.js";
|
|
18
|
+
import { type FilterableSubject } from "./subject-filter.js";
|
|
17
19
|
export declare const VIEWS_ROOT_KEY = "views";
|
|
18
20
|
export declare const MODEL_ROOT_KEY = "model";
|
|
19
21
|
/** Collapse keys are strings so one set holds every branch of both trees. */
|
|
@@ -24,12 +26,30 @@ export declare const layerKey: (layer: string) => string;
|
|
|
24
26
|
export declare const modelFolderKey: (folder: string) => string;
|
|
25
27
|
/** Where a subject with no resolved layer is grouped, last. */
|
|
26
28
|
export declare const UNLAYERED = "unlayered";
|
|
29
|
+
/**
|
|
30
|
+
* How a row relates to the pending changeset (ADR 0114). `"new"` is a staged
|
|
31
|
+
* `write-view` at a path nothing has landed; `"overwrite"` is one at a path a
|
|
32
|
+
* landed view occupies; `"delete"` is a staged `delete-view`. A landed row
|
|
33
|
+
* nothing pending touches carries `null`.
|
|
34
|
+
*/
|
|
35
|
+
export type ViewRowStaging = "new" | "overwrite" | "delete";
|
|
27
36
|
export interface ViewTreeRow {
|
|
28
37
|
readonly id: string;
|
|
29
38
|
readonly title: string;
|
|
30
39
|
readonly path: string;
|
|
31
|
-
|
|
40
|
+
/**
|
|
41
|
+
* `null` when nothing has measured it: a staged NEW view has no landed
|
|
42
|
+
* document, and resolving its query needs the semantic graph the browser
|
|
43
|
+
* does not hold — and, while the tree filter narrows, every landed view
|
|
44
|
+
* but the active one, whose subjects live only in that same graph (#317).
|
|
45
|
+
* A number is either the server's measure of what LANDED (a staged
|
|
46
|
+
* overwrite keeps the landed count, the same staleness story
|
|
47
|
+
* `VisualViewSummary.subjectCount` already tells) or, on the active row,
|
|
48
|
+
* a count of the drawn subjects that survive the typed filter.
|
|
49
|
+
*/
|
|
50
|
+
readonly subjectCount: number | null;
|
|
32
51
|
readonly active: boolean;
|
|
52
|
+
readonly staged: ViewRowStaging | null;
|
|
33
53
|
}
|
|
34
54
|
export interface ViewTreeFolder {
|
|
35
55
|
readonly key: string;
|
|
@@ -99,17 +119,30 @@ export declare const matchesFilter: (label: string, filterText: string) => boole
|
|
|
99
119
|
export declare const folderOf: (view: VisualViewSummary) => string;
|
|
100
120
|
export interface ViewTreeInput {
|
|
101
121
|
readonly views: readonly VisualViewSummary[];
|
|
122
|
+
/**
|
|
123
|
+
* The pending changeset's view operations, merged over `views` so the rail
|
|
124
|
+
* shows the reviewer's own staged intent beside landed truth (ADR 0114).
|
|
125
|
+
* A staged `write-view` at a new path becomes a row; one at a landed path
|
|
126
|
+
* marks that row and shows what WILL land; a staged `delete-view` marks the
|
|
127
|
+
* row rather than hiding it. Discarding an operation removes it from this
|
|
128
|
+
* list, which is the whole revert — the tree derives, it never remembers.
|
|
129
|
+
*/
|
|
130
|
+
readonly stagedOperations: readonly VisualViewOperation[];
|
|
102
131
|
readonly activeViewId: string;
|
|
103
132
|
/**
|
|
104
|
-
*
|
|
105
|
-
* filter's match set
|
|
106
|
-
*
|
|
107
|
-
*
|
|
133
|
+
* The subjects the active view is drawing right now, from the standing
|
|
134
|
+
* filter's match set, or `null` when nothing is filtering the canvas. The
|
|
135
|
+
* subjects themselves rather than their count (#317): the active row's
|
|
136
|
+
* number is how many of them survive the typed filter, which a
|
|
137
|
+
* pre-computed count could not answer. Unfiltered it is their plain
|
|
138
|
+
* length — the number the reviewer can check by looking, where the
|
|
139
|
+
* server's `subjectCount` was only true when the frame carrying it was
|
|
140
|
+
* sent.
|
|
108
141
|
*/
|
|
109
|
-
readonly
|
|
142
|
+
readonly activeSubjects: readonly FilterableSubject[] | null;
|
|
110
143
|
readonly filterText: string;
|
|
111
144
|
}
|
|
112
|
-
export declare const buildViewTree: ({ views, activeViewId,
|
|
145
|
+
export declare const buildViewTree: ({ views, stagedOperations, activeViewId, activeSubjects, filterText, }: ViewTreeInput) => ViewTree;
|
|
113
146
|
export interface ModelTreeInput {
|
|
114
147
|
readonly nodes: readonly CanvasNode[];
|
|
115
148
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { VisualViewSummary } from "../adapters/visual/protocol-contract.js";
|
|
1
|
+
import type { VisualViewOperation, VisualViewSummary } from "../adapters/visual/protocol-contract.js";
|
|
2
2
|
import type { CanvasNode } from "../graph-projection.js";
|
|
3
3
|
/**
|
|
4
4
|
* A right-click on a row, in viewport coordinates. The rail reports which row
|
|
@@ -14,6 +14,13 @@ export type TreeRowMenu = (row: {
|
|
|
14
14
|
}) => void;
|
|
15
15
|
export interface ViewTreeProps {
|
|
16
16
|
readonly views: readonly VisualViewSummary[];
|
|
17
|
+
/**
|
|
18
|
+
* The pending changeset's view operations, merged over `views` by
|
|
19
|
+
* `buildViewTree` so staged intent is visible beside landed truth
|
|
20
|
+
* (ADR 0114). Derived from the changeset at the call site, never stored:
|
|
21
|
+
* discarding the operation is the revert.
|
|
22
|
+
*/
|
|
23
|
+
readonly stagedViewOperations: readonly VisualViewOperation[];
|
|
17
24
|
readonly activeViewId: string;
|
|
18
25
|
/** Every subject the workspace declares, filtered or not. */
|
|
19
26
|
readonly nodes: readonly CanvasNode[];
|
|
@@ -28,5 +35,7 @@ export interface ViewTreeProps {
|
|
|
28
35
|
readonly onNewView: () => void;
|
|
29
36
|
readonly onSelectSubject: (id: string) => void;
|
|
30
37
|
readonly onRowMenu: TreeRowMenu;
|
|
38
|
+
/** A viewer, not an author (#298): the new-view affordance is absent. */
|
|
39
|
+
readonly readOnly?: boolean;
|
|
31
40
|
}
|
|
32
|
-
export declare function ViewTree({ views, activeViewId, nodes, inViewIds, filterText, collapsed, onFilterChange, onToggle, onSelectView, onClearView, onNewView, onSelectSubject, onRowMenu, }: ViewTreeProps): import("react").JSX.Element;
|
|
41
|
+
export declare function ViewTree({ views, stagedViewOperations, activeViewId, nodes, inViewIds, filterText, collapsed, onFilterChange, onToggle, onSelectView, onClearView, onNewView, onSelectSubject, onRowMenu, readOnly, }: ViewTreeProps): import("react").JSX.Element;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { CanvasEdge, CanvasGraph, CanvasNode } from "../graph-projection.js";
|
|
2
2
|
import { type NestingKind } from "../nesting.js";
|
|
3
|
+
import { type LayoutDirection } from "../layout-direction.js";
|
|
4
|
+
import type { DecorationMap } from "./graph-canvas.js";
|
|
3
5
|
import type { ContextMenuTarget } from "./context-menu-model.js";
|
|
4
6
|
import type { BottomPanelTabId } from "./query-panel.js";
|
|
5
7
|
export interface SelectedElement {
|
|
@@ -37,15 +39,59 @@ export interface ConnectionDraft {
|
|
|
37
39
|
}
|
|
38
40
|
export declare const normalizeSelectedElement: (node: CanvasNode) => SelectedElement;
|
|
39
41
|
export declare const normalizeSelectedRelationship: (edge: CanvasEdge, nodeTitles: ReadonlyMap<string, string>) => SelectedRelationship;
|
|
42
|
+
/**
|
|
43
|
+
* What the imperative methods read at the moment they are called (#297,
|
|
44
|
+
* ADR 0118). A getter rather than a captured value, because the pointer is
|
|
45
|
+
* handed up once and the graph changes under it with every commit - a method
|
|
46
|
+
* bound to the model that existed at mount time would answer for a model
|
|
47
|
+
* that is gone.
|
|
48
|
+
*/
|
|
49
|
+
export interface EditorPointerContext {
|
|
50
|
+
readonly graph: CanvasGraph | null;
|
|
51
|
+
readonly readOnly: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The host's way of pointing at the canvas (#297, ADR 0118): three methods,
|
|
55
|
+
* each the programmatic twin of a gesture the surface already has - a canvas
|
|
56
|
+
* tap, a palette pick, the inspector's Connect. Every method answers with
|
|
57
|
+
* whether it acted; false means nothing moved - the id named nothing, the
|
|
58
|
+
* model has not arrived, or the mount is a viewer (#298) and the gesture
|
|
59
|
+
* would have reached for the pen.
|
|
60
|
+
*/
|
|
61
|
+
export interface EditorPointer {
|
|
62
|
+
readonly select: (subjectId: string) => boolean;
|
|
63
|
+
readonly openDraft: (options?: {
|
|
64
|
+
readonly kind?: string;
|
|
65
|
+
}) => boolean;
|
|
66
|
+
readonly startConnection: (fromSubjectId: string) => boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Replaces the host's per-subject marks wholesale (#314, ADR 0119) - the
|
|
69
|
+
* map is the unit of exchange, never merged into what stood. Unlike its
|
|
70
|
+
* siblings this one needs no model and no pen: the marks are client state
|
|
71
|
+
* drawn when the graph (or its successor) is on screen, and decorating is
|
|
72
|
+
* reading, so a viewer accepts them too. It answers false only where every
|
|
73
|
+
* method does - a handle before the shell's first render or after disposal.
|
|
74
|
+
*/
|
|
75
|
+
readonly setDecorations: (decorations: DecorationMap) => boolean;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Builds the pointer over the shell's own dispatchers. Nothing here is a
|
|
79
|
+
* second write path: every method dispatches the same workspace action its
|
|
80
|
+
* on-screen twin dispatches, so what a host can reach is exactly what a
|
|
81
|
+
* reviewer can reach, and anything staged still lands through the changeset.
|
|
82
|
+
*/
|
|
83
|
+
export declare const editorPointerFor: (context: () => EditorPointerContext, dispatch: (action: VisualWorkspaceAction) => void, seedDraftKind: (kind: string | undefined) => void, replaceDecorations: (decorations: DecorationMap) => void) => EditorPointer;
|
|
40
84
|
/**
|
|
41
85
|
* The right column's sections, in the order they stack (#249, ADR-free: the
|
|
42
86
|
* design settles the order and nothing derives it).
|
|
43
87
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
88
|
+
* The palette leads (#295): it is the tool that makes subjects, and tools
|
|
89
|
+
* read above inspection - a reviewer reaches for what to add before what is
|
|
90
|
+
* selected. Chat is last because it is pinned at the foot and owns the
|
|
91
|
+
* session's own control - the reviewer ends the conversation beside the
|
|
92
|
+
* conversation, not from a strip that carries identity and nothing else.
|
|
47
93
|
*/
|
|
48
|
-
export declare const RIGHT_SECTIONS: readonly ["properties", "changes", "chat"];
|
|
94
|
+
export declare const RIGHT_SECTIONS: readonly ["palette", "properties", "questions", "changes", "chat"];
|
|
49
95
|
export type RightSectionId = (typeof RIGHT_SECTIONS)[number];
|
|
50
96
|
/** How short a section may be dragged before it is just a header. */
|
|
51
97
|
export declare const SECTION_MIN_HEIGHT = 96;
|
|
@@ -60,16 +106,26 @@ export declare const CONVERSATION_MIN_WIDTH = 320;
|
|
|
60
106
|
export declare const CONVERSATION_MAX_WIDTH = 640;
|
|
61
107
|
export interface VisualWorkspaceState {
|
|
62
108
|
/**
|
|
63
|
-
* The right column: one width,
|
|
109
|
+
* The right column: one width, whether the reviewer has put the whole
|
|
110
|
+
* column away, and the sections stacked inside it.
|
|
64
111
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
112
|
+
* The sections are collapsible one by one, and a reviewer who wants room
|
|
113
|
+
* shuts sections rather than the column - shut headers say what is behind
|
|
114
|
+
* them (#249). `hidden` is the further step for the moments that want the
|
|
115
|
+
* whole canvas - presenting, a projector, a laptop - and the reopen strip
|
|
116
|
+
* that stands in for the column carries what a shut header would have
|
|
117
|
+
* said: the unread count and a waiting choice (#294).
|
|
70
118
|
*/
|
|
71
119
|
readonly conversation: {
|
|
72
120
|
readonly width: number;
|
|
121
|
+
/**
|
|
122
|
+
* Whether the reviewer has put the whole column away (#294). A mode
|
|
123
|
+
* beside the width rather than a zero width, so the width stays what it
|
|
124
|
+
* was and reopening restores it - sections and splitters intact. The
|
|
125
|
+
* presenting moments are exactly when this is used, and presentation
|
|
126
|
+
* must not cost the reviewer their layout.
|
|
127
|
+
*/
|
|
128
|
+
readonly hidden: boolean;
|
|
73
129
|
readonly unread: number;
|
|
74
130
|
/** The sections the reviewer has shut. Held as what is CLOSED so a
|
|
75
131
|
* section added later arrives open rather than hidden behind a default
|
|
@@ -158,10 +214,18 @@ export interface VisualWorkspaceState {
|
|
|
158
214
|
* alone - the behaviour that shipped before a view could say.
|
|
159
215
|
*/
|
|
160
216
|
readonly nesting: readonly NestingKind[];
|
|
217
|
+
/**
|
|
218
|
+
* Which way the active view runs its layers (#274, ADR 0121). A view that
|
|
219
|
+
* says nothing runs `DEFAULT_DIRECTION`, the same rule `nesting` follows:
|
|
220
|
+
* silence restores the default rather than carrying the previous view's
|
|
221
|
+
* answer across.
|
|
222
|
+
*/
|
|
223
|
+
readonly direction: LayoutDirection;
|
|
161
224
|
readonly layout: "layered";
|
|
162
225
|
readonly showLifecycle: boolean;
|
|
163
226
|
readonly showEvidence: boolean;
|
|
164
227
|
readonly showOwnership: boolean;
|
|
228
|
+
readonly showNudges: boolean;
|
|
165
229
|
}
|
|
166
230
|
export type VisualWorkspaceAction = {
|
|
167
231
|
readonly type: "section.toggled";
|
|
@@ -173,6 +237,8 @@ export type VisualWorkspaceAction = {
|
|
|
173
237
|
} | {
|
|
174
238
|
readonly type: "conversation.resized";
|
|
175
239
|
readonly width: number;
|
|
240
|
+
} | {
|
|
241
|
+
readonly type: "conversation.toggled";
|
|
176
242
|
} | {
|
|
177
243
|
readonly type: "viewport.resized";
|
|
178
244
|
readonly viewportWidth: number;
|
|
@@ -236,12 +302,15 @@ export type VisualWorkspaceAction = {
|
|
|
236
302
|
} | {
|
|
237
303
|
readonly type: "nesting.set";
|
|
238
304
|
readonly nesting: readonly NestingKind[];
|
|
305
|
+
} | {
|
|
306
|
+
readonly type: "direction.set";
|
|
307
|
+
readonly direction: LayoutDirection;
|
|
239
308
|
} | {
|
|
240
309
|
readonly type: "layout.set";
|
|
241
310
|
readonly layout: "layered";
|
|
242
311
|
} | {
|
|
243
312
|
readonly type: "presentation.toggled";
|
|
244
|
-
readonly flag: "showLifecycle" | "showEvidence" | "showOwnership";
|
|
313
|
+
readonly flag: "showLifecycle" | "showEvidence" | "showOwnership" | "showNudges";
|
|
245
314
|
readonly value: boolean;
|
|
246
315
|
} | {
|
|
247
316
|
readonly type: "model.replaced";
|
|
@@ -252,6 +321,7 @@ export type VisualWorkspaceAction = {
|
|
|
252
321
|
export declare const presentationActionsFor: (presentation: {
|
|
253
322
|
readonly layout?: "layered";
|
|
254
323
|
readonly nesting?: readonly NestingKind[];
|
|
324
|
+
readonly direction?: LayoutDirection;
|
|
255
325
|
readonly showLifecycle?: boolean;
|
|
256
326
|
readonly showEvidence?: boolean;
|
|
257
327
|
readonly showOwnership?: boolean;
|
|
@@ -6,6 +6,7 @@ export interface WorkspaceManifest {
|
|
|
6
6
|
readonly profiles: readonly string[];
|
|
7
7
|
readonly projections: readonly string[];
|
|
8
8
|
readonly adapterMappings: readonly string[];
|
|
9
|
+
readonly patterns?: readonly string[];
|
|
9
10
|
readonly evidence?: readonly string[];
|
|
10
11
|
readonly contracts?: readonly string[];
|
|
11
12
|
}
|
|
@@ -15,6 +16,7 @@ export interface ResolvedWorkspace {
|
|
|
15
16
|
readonly profiles: readonly string[];
|
|
16
17
|
readonly projections: readonly string[];
|
|
17
18
|
readonly adapterMappings: readonly string[];
|
|
19
|
+
readonly patterns: readonly string[];
|
|
18
20
|
readonly evidence: readonly string[];
|
|
19
21
|
readonly contracts: readonly string[];
|
|
20
22
|
}
|
package/dist/workspace.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface WorkspaceManifest {
|
|
|
6
6
|
readonly profiles: readonly string[];
|
|
7
7
|
readonly projections: readonly string[];
|
|
8
8
|
readonly adapterMappings: readonly string[];
|
|
9
|
+
readonly patterns?: readonly string[];
|
|
9
10
|
readonly evidence?: readonly string[];
|
|
10
11
|
readonly contracts?: readonly string[];
|
|
11
12
|
}
|
|
@@ -15,6 +16,7 @@ export interface ResolvedWorkspace {
|
|
|
15
16
|
readonly profiles: readonly string[];
|
|
16
17
|
readonly projections: readonly string[];
|
|
17
18
|
readonly adapterMappings: readonly string[];
|
|
19
|
+
readonly patterns: readonly string[];
|
|
18
20
|
readonly evidence: readonly string[];
|
|
19
21
|
readonly contracts: readonly string[];
|
|
20
22
|
}
|
package/dist/workspace.js
CHANGED
|
@@ -106,6 +106,7 @@ export function loadWorkspaceManifest(source, cwd) {
|
|
|
106
106
|
profiles: expand('profiles', 'profile', value.profiles),
|
|
107
107
|
projections: expand('projections', 'projection', value.projections),
|
|
108
108
|
adapterMappings: expand('adapterMappings', 'adapter mapping', value.adapterMappings),
|
|
109
|
+
patterns: expand('patterns', 'pattern', value.patterns ?? []),
|
|
109
110
|
evidence: expand('evidence', 'evidence', value.evidence ?? []),
|
|
110
111
|
contracts: expand('contracts', 'Core contract', value.contracts ?? []),
|
|
111
112
|
};
|
|
@@ -298,6 +298,87 @@ const editor = mountEditor(document.querySelector('#editor')!, {
|
|
|
298
298
|
editor.unmount()
|
|
299
299
|
```
|
|
300
300
|
|
|
301
|
+
### The questions are yours
|
|
302
|
+
|
|
303
|
+
The questions section evaluates the shipped `core-enrichment` catalogue by
|
|
304
|
+
default. A host with its own interrogation supplies its own instead (#328):
|
|
305
|
+
|
|
306
|
+
```ts
|
|
307
|
+
const editor = mountEditor(element, {
|
|
308
|
+
store,
|
|
309
|
+
workspace,
|
|
310
|
+
sections: ['palette', 'properties', 'questions', 'changes'],
|
|
311
|
+
catalogue: { path: 'catalogues/consulting.yaml', source: catalogueText },
|
|
312
|
+
dismissed: [
|
|
313
|
+
{ questionId: 'register-fidelity', subject: 'crm-integration' },
|
|
314
|
+
{ questionId: 'engagement-framing' },
|
|
315
|
+
],
|
|
316
|
+
})
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
The division this draws is deliberate. **The engine is yarramate's and so is
|
|
320
|
+
the UI; the questions belong to whoever adopted it.** `core-enrichment` is a
|
|
321
|
+
general modelling interview — right for yarramate's own CLI, and right for a
|
|
322
|
+
host with no domain of its own — and wrong for a product whose interview is
|
|
323
|
+
about its own subject matter. Inheriting it would mean asking a consultant
|
|
324
|
+
about modelling hygiene in the pane where they are asking a client about
|
|
325
|
+
sign-off.
|
|
326
|
+
|
|
327
|
+
`catalogue` takes bytes, and a catalogue that does not load leaves the overlay
|
|
328
|
+
absent rather than failing the mount: the overlay is a garnish on the model,
|
|
329
|
+
and a model frame must not be blocked by it.
|
|
330
|
+
|
|
331
|
+
`dismissed` is what the host has already dealt with. A supplied catalogue
|
|
332
|
+
alone does not cover this — the editor evaluates the catalogue itself and
|
|
333
|
+
cannot know that a reviewer set a question aside, with a reason, recorded
|
|
334
|
+
somewhere the editor cannot see, so the pane would go on asking a question the
|
|
335
|
+
host's own product had answered. Naming a `subject` dismisses the question for
|
|
336
|
+
that subject alone; omitting it dismisses the question wherever it appears.
|
|
337
|
+
|
|
338
|
+
Dismissal decides what the **pane draws** and nothing else. The model is
|
|
339
|
+
untouched and `ask --open` still reports the question, because the interview is
|
|
340
|
+
not the editor's to settle.
|
|
341
|
+
|
|
342
|
+
Pass `readOnly: true` to mount a viewer over the same surface — for a frozen
|
|
343
|
+
published snapshot, say ([ADR 0117](adr/0117-a-mounted-editor-can-refuse-the-pen.md)).
|
|
344
|
+
The reviewer still selects, filters, navigates views and reads questions and
|
|
345
|
+
properties (as values, not forms), but every affordance that stages or commits
|
|
346
|
+
is absent rather than disabled: no Add subject, no palette or changes
|
|
347
|
+
sections, no Connect/Delete, no view create/rename/delete, and drags move
|
|
348
|
+
nodes without writing layouts. With no `sections` named, a read-only mount
|
|
349
|
+
defaults to `['properties', 'questions']`. This is a UI posture only — pair it
|
|
350
|
+
with a store that refuses writes; the two defenses are independent.
|
|
351
|
+
`mountEditorWith` takes the same flag as its trailing parameter.
|
|
352
|
+
|
|
353
|
+
The returned handle can also point at the canvas
|
|
354
|
+
([ADR 0118](adr/0118-the-host-can-point-at-the-canvas.md)):
|
|
355
|
+
`select(subjectId)` selects a concept or relationship exactly as a canvas tap
|
|
356
|
+
would, which also scopes the Open questions section to it;
|
|
357
|
+
`openDraft({ kind })` opens the Add-subject dialog with the kind preselected
|
|
358
|
+
the way a palette pick seeds it (omit `kind` for the plain no-default form);
|
|
359
|
+
and `startConnection(fromSubjectId)` arms the Connect flow from that subject —
|
|
360
|
+
the relationship-with-one-endpoint-fixed affordance an interrogation trigger
|
|
361
|
+
describes. Each returns `false`, rather than throwing, when it moved nothing:
|
|
362
|
+
an id the current model does not name, a model that has not arrived yet, or —
|
|
363
|
+
for `openDraft` and `startConnection` — a read-only mount. These are the
|
|
364
|
+
programmatic twins of tap, palette and Connect, never a second write path:
|
|
365
|
+
anything they lead to still stages through the changeset and commits through
|
|
366
|
+
the same validated batch.
|
|
367
|
+
|
|
368
|
+
The viewer also accepts per-subject marks
|
|
369
|
+
([ADR 0119](adr/0119-the-viewer-accepts-the-hosts-marks.md)): pass
|
|
370
|
+
`decorations: { [subjectId]: 'added' | 'removed' | 'changed' }` — concepts and
|
|
371
|
+
relationships alike — and the canvas renders them as visual treatments (added
|
|
372
|
+
an eucalyptus border, removed a quiet dashed one, changed ochre; a fault still
|
|
373
|
+
outranks any mark). Comparison semantics stay on your side of the seam: the
|
|
374
|
+
viewer never diffs, it draws the map it is handed, so what a mark means — and
|
|
375
|
+
any legend saying so — is yours. The option is the initial map; the handle's
|
|
376
|
+
`setDecorations(decorations)` replaces it wholesale (never a merge, `{}`
|
|
377
|
+
clears) for a live comparison, works under `readOnly` and before the first
|
|
378
|
+
model frame, and ids the model does not name are silently inert. It shares the
|
|
379
|
+
pointer methods' one false window: before the shell's first render, or after
|
|
380
|
+
unmount.
|
|
381
|
+
|
|
301
382
|
`store` is the caller's synchronous `SourceStore`; `workspace` is the caller's
|
|
302
383
|
pre-resolved `ResolvedWorkspace`. The local host compiles, projects, filters,
|
|
303
384
|
commits and saves layouts over that store. A changeset's model and view writes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yarramate",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Tool-neutral semantic architecture engine and guided methodology",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"./visual-app/styles.css": "./dist/visual-app-lib/styles.css",
|
|
66
66
|
"./schema/document": "./schema/yarramate-document.schema.json",
|
|
67
67
|
"./schema/profile": "./schema/yarramate-profile.schema.json",
|
|
68
|
+
"./schema/pattern": "./schema/yarramate-pattern.schema.json",
|
|
68
69
|
"./schema/projection": "./schema/yarramate-projection.schema.json",
|
|
69
70
|
"./schema/projection-result": "./schema/yarramate-projection-result.schema.json",
|
|
70
71
|
"./schema/adapter-mapping": "./schema/yarramate-adapter-mapping.schema.json",
|
|
@@ -533,6 +533,32 @@
|
|
|
533
533
|
"const": "unscoped-succession"
|
|
534
534
|
}
|
|
535
535
|
}
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
"type": "object",
|
|
539
|
+
"additionalProperties": false,
|
|
540
|
+
"description": "The workspace holds at least one concept (#334, ADR 0125). The guard a late wave needs to say \"only once the model has substance\": an empty model is not an architecture at rest, it has not started, and asking it how the planned architecture becomes real greets someone ahead of question one.",
|
|
541
|
+
"required": [
|
|
542
|
+
"condition"
|
|
543
|
+
],
|
|
544
|
+
"properties": {
|
|
545
|
+
"condition": {
|
|
546
|
+
"const": "has-any-subject"
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
"type": "object",
|
|
552
|
+
"additionalProperties": false,
|
|
553
|
+
"description": "The workspace's evidence overlay records observations and every one is a frictionless confirmation: no contradicted, unknown, or not-observed result, and no recorded search (ADR 0107). A discovery that never records anything but success never tested a claim it might fail. The one condition that reads the evidence overlay rather than the compiled graph; where the evaluating consumer supplies no overlay it stays quiet (ADR 0120).",
|
|
554
|
+
"required": [
|
|
555
|
+
"condition"
|
|
556
|
+
],
|
|
557
|
+
"properties": {
|
|
558
|
+
"condition": {
|
|
559
|
+
"const": "unchallenged-evidence"
|
|
560
|
+
}
|
|
561
|
+
}
|
|
536
562
|
}
|
|
537
563
|
]
|
|
538
564
|
},
|
|
@@ -151,6 +151,20 @@
|
|
|
151
151
|
"$ref": "#/$defs/constraint"
|
|
152
152
|
}
|
|
153
153
|
},
|
|
154
|
+
"parts": {
|
|
155
|
+
"description": "The subjects that fill this instance's pattern slots, by slot name (ADR 0123). Valid only on a kind that has a pattern; the compiler mints the pattern's wiring between the instance and what these name, and refuses any authored relationship that contradicts it. Binding, not generation: a part keeps its own name, owner, evidence and outside edges.",
|
|
156
|
+
"type": "object",
|
|
157
|
+
"minProperties": 1,
|
|
158
|
+
"additionalProperties": false,
|
|
159
|
+
"propertyNames": {
|
|
160
|
+
"pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$"
|
|
161
|
+
},
|
|
162
|
+
"patternProperties": {
|
|
163
|
+
"^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$": {
|
|
164
|
+
"$ref": "#/$defs/reference"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
},
|
|
154
168
|
"references": {
|
|
155
169
|
"$ref": "#/$defs/identifiedReferences"
|
|
156
170
|
},
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"required": [
|
|
67
67
|
"id",
|
|
68
68
|
"name",
|
|
69
|
+
"opened",
|
|
69
70
|
"questions"
|
|
70
71
|
],
|
|
71
72
|
"properties": {
|
|
@@ -77,6 +78,10 @@
|
|
|
77
78
|
"type": "string",
|
|
78
79
|
"minLength": 1
|
|
79
80
|
},
|
|
81
|
+
"opened": {
|
|
82
|
+
"description": "Whether this wave's gate is met (#334, ADR 0125). A wave with no `opensWhen` is always true. A wave reported false asks nothing and carries no questions: they are premature rather than answered, which is the third state a progress rail needs so a closed wave is not counted as done. Its questions are excluded from `summary` for the same reason.",
|
|
83
|
+
"type": "boolean"
|
|
84
|
+
},
|
|
80
85
|
"questions": {
|
|
81
86
|
"type": "array",
|
|
82
87
|
"items": {
|
|
@@ -532,6 +537,32 @@
|
|
|
532
537
|
"const": "unscoped-succession"
|
|
533
538
|
}
|
|
534
539
|
}
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
"type": "object",
|
|
543
|
+
"additionalProperties": false,
|
|
544
|
+
"description": "The workspace holds at least one concept (#334, ADR 0125). The guard a late wave needs to say \"only once the model has substance\": an empty model is not an architecture at rest, it has not started, and asking it how the planned architecture becomes real greets someone ahead of question one.",
|
|
545
|
+
"required": [
|
|
546
|
+
"condition"
|
|
547
|
+
],
|
|
548
|
+
"properties": {
|
|
549
|
+
"condition": {
|
|
550
|
+
"const": "has-any-subject"
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
"type": "object",
|
|
556
|
+
"additionalProperties": false,
|
|
557
|
+
"description": "The workspace's evidence overlay records observations and every one is a frictionless confirmation: no contradicted, unknown, or not-observed result, and no recorded search (ADR 0107). A discovery that never records anything but success never tested a claim it might fail. The one condition that reads the evidence overlay rather than the compiled graph; where the evaluating consumer supplies no overlay it stays quiet (ADR 0120).",
|
|
558
|
+
"required": [
|
|
559
|
+
"condition"
|
|
560
|
+
],
|
|
561
|
+
"properties": {
|
|
562
|
+
"condition": {
|
|
563
|
+
"const": "unchallenged-evidence"
|
|
564
|
+
}
|
|
565
|
+
}
|
|
535
566
|
}
|
|
536
567
|
]
|
|
537
568
|
},
|