yarramate 1.2.0 → 1.3.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 (70) hide show
  1. package/catalogues/core-enrichment.yaml +225 -2
  2. package/dist/adapters/visual/session-server.js +16 -1
  3. package/dist/adapters/visual/view-identity.d.ts +1 -1
  4. package/dist/adapters/visual/view-identity.js +61 -3
  5. package/dist/adapters/visual/wire.d.ts +30 -0
  6. package/dist/adapters/visual/workspace-model.d.ts +23 -3
  7. package/dist/adapters/visual/workspace-model.js +52 -2
  8. package/dist/ask-command.js +29 -13
  9. package/dist/cli-support.d.ts +1 -1
  10. package/dist/cli-support.js +1 -1
  11. package/dist/cli.d.ts +1 -0
  12. package/dist/cli.js +26 -5
  13. package/dist/concept-drafting.d.ts +13 -2
  14. package/dist/concept-drafting.js +15 -3
  15. package/dist/design-command.js +16 -1
  16. package/dist/evidence.js +25 -0
  17. package/dist/index.d.ts +2 -2
  18. package/dist/index.js +1 -1
  19. package/dist/interrogate-command.d.ts +20 -1
  20. package/dist/interrogate-command.js +23 -4
  21. package/dist/interrogation-entry.d.ts +1 -1
  22. package/dist/layout-direction.d.ts +14 -0
  23. package/dist/layout-direction.js +5 -0
  24. package/dist/projection.d.ts +22 -6
  25. package/dist/projection.js +23 -2
  26. package/dist/relationship-drafting.d.ts +21 -2
  27. package/dist/relationship-drafting.js +33 -3
  28. package/dist/subject-references.js +5 -0
  29. package/dist/visual-app/assets/index-C3i9SxTe.js +394 -0
  30. package/dist/visual-app/assets/index-Rkq6smL2.css +1 -0
  31. package/dist/visual-app/index.html +2 -2
  32. package/dist/visual-app-lib/editor.js +28464 -26953
  33. package/dist/visual-app-lib/styles.css +1 -1
  34. package/dist/visual-app-lib/types/adapters/visual/view-identity.d.ts +1 -1
  35. package/dist/visual-app-lib/types/adapters/visual/wire.d.ts +30 -0
  36. package/dist/visual-app-lib/types/adapters/visual/workspace-model.d.ts +23 -3
  37. package/dist/visual-app-lib/types/concept-drafting.d.ts +13 -2
  38. package/dist/visual-app-lib/types/interrogate-command.d.ts +190 -0
  39. package/dist/visual-app-lib/types/layout-direction.d.ts +14 -0
  40. package/dist/visual-app-lib/types/projection.d.ts +22 -6
  41. package/dist/visual-app-lib/types/relationship-drafting.d.ts +21 -2
  42. package/dist/visual-app-lib/types/subject-identity.d.ts +34 -0
  43. package/dist/visual-app-lib/types/visual-app/App.d.ts +27 -2
  44. package/dist/visual-app-lib/types/visual-app/badges.d.ts +1 -0
  45. package/dist/visual-app-lib/types/visual-app/connection-panel.d.ts +9 -1
  46. package/dist/visual-app-lib/types/visual-app/context-menu-model.d.ts +15 -6
  47. package/dist/visual-app-lib/types/visual-app/graph-canvas.d.ts +77 -6
  48. package/dist/visual-app-lib/types/visual-app/kind-palette.d.ts +37 -0
  49. package/dist/visual-app-lib/types/visual-app/mount.d.ts +73 -2
  50. package/dist/visual-app-lib/types/visual-app/open-questions.d.ts +15 -0
  51. package/dist/visual-app-lib/types/visual-app/query-fields.d.ts +3 -2
  52. package/dist/visual-app-lib/types/visual-app/query-panel.d.ts +8 -1
  53. package/dist/visual-app-lib/types/visual-app/save-view.d.ts +11 -5
  54. package/dist/visual-app-lib/types/visual-app/shipped-catalogue.d.ts +10 -0
  55. package/dist/visual-app-lib/types/visual-app/state.d.ts +15 -4
  56. package/dist/visual-app-lib/types/visual-app/subject-draft-panel.d.ts +13 -1
  57. package/dist/visual-app-lib/types/visual-app/subject-filter.d.ts +35 -0
  58. package/dist/visual-app-lib/types/visual-app/subject-form.d.ts +8 -0
  59. package/dist/visual-app-lib/types/visual-app/view-tree-model.d.ts +42 -9
  60. package/dist/visual-app-lib/types/visual-app/view-tree.d.ts +11 -2
  61. package/dist/visual-app-lib/types/visual-app/workspace-state.d.ts +81 -11
  62. package/docs/CONSUMING-YARRAMATE.md +40 -0
  63. package/package.json +1 -1
  64. package/schema/yarramate-design-step.schema.json +13 -0
  65. package/schema/yarramate-interrogation-report.schema.json +13 -0
  66. package/schema/yarramate-projection.schema.json +9 -0
  67. package/schema/yarramate-question-catalogue.schema.json +13 -0
  68. package/skills/yarramate-architecture/SKILL.md +5 -0
  69. package/dist/visual-app/assets/index-CcmfL3oY.js +0 -394
  70. package/dist/visual-app/assets/index-DLutIWES.css +0 -1
@@ -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
- * and the subjects the model declares — so everything it decides is a pure
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
- readonly subjectCount: number;
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
- * How many subjects the active view is drawing right now, from the standing
105
- * filter's match set. The server's `subjectCount` was true when the frame
106
- * carrying it was sent; this one is true of the canvas beside it, which is
107
- * the number the reviewer can check by looking.
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 activeSubjectCount: number | null;
142
+ readonly activeSubjects: readonly FilterableSubject[] | null;
110
143
  readonly filterText: string;
111
144
  }
112
- export declare const buildViewTree: ({ views, activeViewId, activeSubjectCount, filterText, }: ViewTreeInput) => ViewTree;
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
- * Chat is last because it is pinned at the foot and owns the session's own
45
- * control - the reviewer ends the conversation beside the conversation, not
46
- * from a strip that carries identity and nothing else.
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, and the sections stacked inside it.
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
- * There is no longer an open/closed mode. The column is always drawn,
66
- * because the sections are collapsible one by one and a reviewer who wants
67
- * the canvas back shuts the sections rather than the column - which leaves
68
- * three headers saying what is behind them instead of a strip button
69
- * saying nothing (#249).
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;
@@ -298,6 +298,46 @@ const editor = mountEditor(document.querySelector('#editor')!, {
298
298
  editor.unmount()
299
299
  ```
300
300
 
301
+ Pass `readOnly: true` to mount a viewer over the same surface — for a frozen
302
+ published snapshot, say ([ADR 0117](adr/0117-a-mounted-editor-can-refuse-the-pen.md)).
303
+ The reviewer still selects, filters, navigates views and reads questions and
304
+ properties (as values, not forms), but every affordance that stages or commits
305
+ is absent rather than disabled: no Add subject, no palette or changes
306
+ sections, no Connect/Delete, no view create/rename/delete, and drags move
307
+ nodes without writing layouts. With no `sections` named, a read-only mount
308
+ defaults to `['properties', 'questions']`. This is a UI posture only — pair it
309
+ with a store that refuses writes; the two defenses are independent.
310
+ `mountEditorWith` takes the same flag as its trailing parameter.
311
+
312
+ The returned handle can also point at the canvas
313
+ ([ADR 0118](adr/0118-the-host-can-point-at-the-canvas.md)):
314
+ `select(subjectId)` selects a concept or relationship exactly as a canvas tap
315
+ would, which also scopes the Open questions section to it;
316
+ `openDraft({ kind })` opens the Add-subject dialog with the kind preselected
317
+ the way a palette pick seeds it (omit `kind` for the plain no-default form);
318
+ and `startConnection(fromSubjectId)` arms the Connect flow from that subject —
319
+ the relationship-with-one-endpoint-fixed affordance an interrogation trigger
320
+ describes. Each returns `false`, rather than throwing, when it moved nothing:
321
+ an id the current model does not name, a model that has not arrived yet, or —
322
+ for `openDraft` and `startConnection` — a read-only mount. These are the
323
+ programmatic twins of tap, palette and Connect, never a second write path:
324
+ anything they lead to still stages through the changeset and commits through
325
+ the same validated batch.
326
+
327
+ The viewer also accepts per-subject marks
328
+ ([ADR 0119](adr/0119-the-viewer-accepts-the-hosts-marks.md)): pass
329
+ `decorations: { [subjectId]: 'added' | 'removed' | 'changed' }` — concepts and
330
+ relationships alike — and the canvas renders them as visual treatments (added
331
+ an eucalyptus border, removed a quiet dashed one, changed ochre; a fault still
332
+ outranks any mark). Comparison semantics stay on your side of the seam: the
333
+ viewer never diffs, it draws the map it is handed, so what a mark means — and
334
+ any legend saying so — is yours. The option is the initial map; the handle's
335
+ `setDecorations(decorations)` replaces it wholesale (never a merge, `{}`
336
+ clears) for a live comparison, works under `readOnly` and before the first
337
+ model frame, and ids the model does not name are silently inert. It shares the
338
+ pointer methods' one false window: before the shell's first render, or after
339
+ unmount.
340
+
301
341
  `store` is the caller's synchronous `SourceStore`; `workspace` is the caller's
302
342
  pre-resolved `ResolvedWorkspace`. The local host compiles, projects, filters,
303
343
  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.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Tool-neutral semantic architecture engine and guided methodology",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -533,6 +533,19 @@
533
533
  "const": "unscoped-succession"
534
534
  }
535
535
  }
536
+ },
537
+ {
538
+ "type": "object",
539
+ "additionalProperties": false,
540
+ "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).",
541
+ "required": [
542
+ "condition"
543
+ ],
544
+ "properties": {
545
+ "condition": {
546
+ "const": "unchallenged-evidence"
547
+ }
548
+ }
536
549
  }
537
550
  ]
538
551
  },
@@ -532,6 +532,19 @@
532
532
  "const": "unscoped-succession"
533
533
  }
534
534
  }
535
+ },
536
+ {
537
+ "type": "object",
538
+ "additionalProperties": false,
539
+ "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).",
540
+ "required": [
541
+ "condition"
542
+ ],
543
+ "properties": {
544
+ "condition": {
545
+ "const": "unchallenged-evidence"
546
+ }
547
+ }
535
548
  }
536
549
  ]
537
550
  },
@@ -36,6 +36,15 @@
36
36
  "$ref": "#/$defs/subjectIdentity"
37
37
  }
38
38
  },
39
+ "exclude": {
40
+ "description": "Subjects this query would otherwise select and the author has taken out: the exception a rule cannot state (#267, ADR 0122). Applied after every other facet and after relationship expansion, so an excluded subject is out whichever way it would have come back in. Naming a subject no facet selects is allowed and inert until the model grows into the rule.",
41
+ "type": "array",
42
+ "minItems": 1,
43
+ "uniqueItems": true,
44
+ "items": {
45
+ "$ref": "#/$defs/subjectIdentity"
46
+ }
47
+ },
39
48
  "documents": {
40
49
  "type": "array",
41
50
  "uniqueItems": true,
@@ -502,6 +502,19 @@
502
502
  "const": "unscoped-succession"
503
503
  }
504
504
  }
505
+ },
506
+ {
507
+ "type": "object",
508
+ "additionalProperties": false,
509
+ "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).",
510
+ "required": [
511
+ "condition"
512
+ ],
513
+ "properties": {
514
+ "condition": {
515
+ "const": "unchallenged-evidence"
516
+ }
517
+ }
505
518
  }
506
519
  ]
507
520
  },
@@ -267,6 +267,11 @@ request
267
267
  -> End or failure: recover, optionally read the transcript, stop, resume
268
268
  ```
269
269
 
270
+ The canvas itself carries the interview: subjects with open questions wear
271
+ a count chip, and the Open questions panel scopes to the selected subject
272
+ (workspace-scoped questions show when nothing is selected). Landing answers
273
+ through the editor's changeset closes them on the next model frame.
274
+
270
275
  Read [references/visual-conversations.md](references/visual-conversations.md)
271
276
  before starting a session. It owns the request builder and its refusals, the
272
277
  capability test, the exact commands and documents, the delegated child's prompt