@issuegraph/editor 0.4.0 → 0.22.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.
Files changed (137) hide show
  1. package/README.md +65 -9
  2. package/dist/a11y/baseline.d.ts +182 -0
  3. package/dist/a11y/baseline.d.ts.map +1 -0
  4. package/dist/a11y/baseline.js +434 -0
  5. package/dist/a11y/baseline.js.map +1 -0
  6. package/dist/audit/findings.d.ts +107 -1
  7. package/dist/audit/findings.d.ts.map +1 -1
  8. package/dist/audit/findings.js +113 -6
  9. package/dist/audit/findings.js.map +1 -1
  10. package/dist/audit/panel.d.ts +277 -0
  11. package/dist/audit/panel.d.ts.map +1 -0
  12. package/dist/audit/panel.js +462 -0
  13. package/dist/audit/panel.js.map +1 -0
  14. package/dist/audit/refused.d.ts +99 -0
  15. package/dist/audit/refused.d.ts.map +1 -0
  16. package/dist/audit/refused.js +276 -0
  17. package/dist/audit/refused.js.map +1 -0
  18. package/dist/audit/styles.d.ts +1 -1
  19. package/dist/audit/styles.d.ts.map +1 -1
  20. package/dist/audit/styles.js +429 -1
  21. package/dist/audit/styles.js.map +1 -1
  22. package/dist/audit/surface.d.ts +54 -12
  23. package/dist/audit/surface.d.ts.map +1 -1
  24. package/dist/audit/surface.js +53 -13
  25. package/dist/audit/surface.js.map +1 -1
  26. package/dist/create/draft.d.ts +36 -0
  27. package/dist/create/draft.d.ts.map +1 -1
  28. package/dist/create/draft.js +40 -0
  29. package/dist/create/draft.js.map +1 -1
  30. package/dist/create/keys.d.ts +134 -9
  31. package/dist/create/keys.d.ts.map +1 -1
  32. package/dist/create/keys.js +119 -20
  33. package/dist/create/keys.js.map +1 -1
  34. package/dist/firstpass/candidates.d.ts +17 -1
  35. package/dist/firstpass/candidates.d.ts.map +1 -1
  36. package/dist/index.d.ts +42 -17
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +45 -14
  39. package/dist/index.js.map +1 -1
  40. package/dist/overlay/render.d.ts +11 -3
  41. package/dist/overlay/render.d.ts.map +1 -1
  42. package/dist/overlay/render.js +76 -20
  43. package/dist/overlay/render.js.map +1 -1
  44. package/dist/overlay/request.d.ts +71 -0
  45. package/dist/overlay/request.d.ts.map +1 -0
  46. package/dist/overlay/request.js +129 -0
  47. package/dist/overlay/request.js.map +1 -0
  48. package/dist/overlay/styles.d.ts +1 -1
  49. package/dist/overlay/styles.d.ts.map +1 -1
  50. package/dist/overlay/styles.js +78 -7
  51. package/dist/overlay/styles.js.map +1 -1
  52. package/dist/picker/render.d.ts +26 -16
  53. package/dist/picker/render.d.ts.map +1 -1
  54. package/dist/picker/render.js +25 -36
  55. package/dist/picker/render.js.map +1 -1
  56. package/dist/picker/styles.d.ts +7 -7
  57. package/dist/picker/styles.d.ts.map +1 -1
  58. package/dist/picker/styles.js +7 -36
  59. package/dist/picker/styles.js.map +1 -1
  60. package/dist/picker/view.d.ts +8 -4
  61. package/dist/picker/view.d.ts.map +1 -1
  62. package/dist/picker/view.js +4 -3
  63. package/dist/picker/view.js.map +1 -1
  64. package/dist/picker/words.d.ts +12 -10
  65. package/dist/picker/words.d.ts.map +1 -1
  66. package/dist/picker/words.js +12 -8
  67. package/dist/picker/words.js.map +1 -1
  68. package/dist/reevaluate/parts.d.ts +130 -0
  69. package/dist/reevaluate/parts.d.ts.map +1 -0
  70. package/dist/reevaluate/parts.js +260 -0
  71. package/dist/reevaluate/parts.js.map +1 -0
  72. package/dist/reevaluate/render.d.ts +18 -11
  73. package/dist/reevaluate/render.d.ts.map +1 -1
  74. package/dist/reevaluate/render.js +21 -135
  75. package/dist/reevaluate/render.js.map +1 -1
  76. package/dist/reevaluate/styles.d.ts +1 -1
  77. package/dist/reevaluate/styles.d.ts.map +1 -1
  78. package/dist/reevaluate/styles.js +26 -0
  79. package/dist/reevaluate/styles.js.map +1 -1
  80. package/dist/reevaluate/view.d.ts +16 -1
  81. package/dist/reevaluate/view.d.ts.map +1 -1
  82. package/dist/reevaluate/view.js +21 -1
  83. package/dist/reevaluate/view.js.map +1 -1
  84. package/dist/reevaluate/words.d.ts +7 -0
  85. package/dist/reevaluate/words.d.ts.map +1 -1
  86. package/dist/scale/ladder.d.ts +62 -6
  87. package/dist/scale/ladder.d.ts.map +1 -1
  88. package/dist/scale/ladder.js +129 -11
  89. package/dist/scale/ladder.js.map +1 -1
  90. package/dist/scale/render.d.ts +44 -0
  91. package/dist/scale/render.d.ts.map +1 -1
  92. package/dist/scale/render.js +206 -28
  93. package/dist/scale/render.js.map +1 -1
  94. package/dist/scale/styles.d.ts +11 -5
  95. package/dist/scale/styles.d.ts.map +1 -1
  96. package/dist/scale/styles.js +133 -4
  97. package/dist/scale/styles.js.map +1 -1
  98. package/dist/workspace/chrome.d.ts +1 -1
  99. package/dist/workspace/chrome.d.ts.map +1 -1
  100. package/dist/workspace/chrome.js +48 -0
  101. package/dist/workspace/chrome.js.map +1 -1
  102. package/dist/workspace/firstpass.d.ts +166 -0
  103. package/dist/workspace/firstpass.d.ts.map +1 -0
  104. package/dist/workspace/firstpass.js +151 -0
  105. package/dist/workspace/firstpass.js.map +1 -0
  106. package/dist/workspace/host.d.ts +283 -11
  107. package/dist/workspace/host.d.ts.map +1 -1
  108. package/dist/workspace/host.js +614 -43
  109. package/dist/workspace/host.js.map +1 -1
  110. package/dist/workspace/inspector.d.ts +72 -2
  111. package/dist/workspace/inspector.d.ts.map +1 -1
  112. package/dist/workspace/inspector.js +26 -0
  113. package/dist/workspace/inspector.js.map +1 -1
  114. package/dist/workspace/mount.d.ts +75 -6
  115. package/dist/workspace/mount.d.ts.map +1 -1
  116. package/dist/workspace/mount.js +1851 -60
  117. package/dist/workspace/mount.js.map +1 -1
  118. package/dist/workspace/rail.d.ts +5 -2
  119. package/dist/workspace/rail.d.ts.map +1 -1
  120. package/dist/workspace/rail.js.map +1 -1
  121. package/dist/workspace/recovery.d.ts +155 -0
  122. package/dist/workspace/recovery.d.ts.map +1 -0
  123. package/dist/workspace/recovery.js +156 -0
  124. package/dist/workspace/recovery.js.map +1 -0
  125. package/dist/workspace/render.d.ts +779 -2
  126. package/dist/workspace/render.d.ts.map +1 -1
  127. package/dist/workspace/render.js +1727 -61
  128. package/dist/workspace/render.js.map +1 -1
  129. package/dist/workspace/selection.d.ts +11 -0
  130. package/dist/workspace/selection.d.ts.map +1 -1
  131. package/dist/workspace/selection.js +10 -0
  132. package/dist/workspace/selection.js.map +1 -1
  133. package/dist/workspace/styles.d.ts +1 -1
  134. package/dist/workspace/styles.d.ts.map +1 -1
  135. package/dist/workspace/styles.js +1405 -42
  136. package/dist/workspace/styles.js.map +1 -1
  137. package/package.json +4 -4
@@ -26,17 +26,70 @@
26
26
  * of which a host reducer should know about, and each of which the demo now
27
27
  * handles beside the mount rather than through it.
28
28
  */
29
- import { type EdgeField } from '@issuegraph/core';
30
- import type { GraphDocument, MutationId, Proposal, StoredIssue } from '@issuegraph/store';
29
+ import type { EdgeId, GraphDocument, MutationId, Proposal, StoredIssue } from '@issuegraph/store';
31
30
  import { type CreateDraft } from '../create/draft.ts';
32
31
  import type { KeyIntent } from '../create/keys.ts';
33
32
  import type { Point } from '../create/placement.ts';
33
+ import type { CandidateId } from '../firstpass/candidates.ts';
34
34
  import { type ScaleState } from '../scale/commands.ts';
35
+ import { type FirstPassCommand, type FirstPassState } from './firstpass.ts';
35
36
  import { type WorkspaceSelection } from './selection.ts';
36
37
  export interface HostState {
37
38
  readonly selection: WorkspaceSelection;
38
39
  readonly scale: ScaleState;
39
40
  readonly auditFiltered: boolean;
41
+ /**
42
+ * Whether §17k's collapsed canvas has been opened.
43
+ *
44
+ * §17k's third row: below `1120` the canvas *"collapses to a strip that opens
45
+ * full-width on demand"*. This field is the demand.
46
+ *
47
+ * IT IS NOT A WIDTH, AND NOTHING HERE KNOWS ONE. §17k's implementation note
48
+ * forbids the package reading a viewport — *"a package that reads the window
49
+ * cannot be dropped into someone else's settings page"* — so the three
50
+ * layouts are the stylesheet's, chosen by a container query on the mount's
51
+ * own box, and this reducer holds only the two reader decisions those layouts
52
+ * need. At the two wider layouts the canvas is a zone rather than a strip and
53
+ * the stylesheet never reads this, so the state is simply not drawn.
54
+ */
55
+ readonly canvasOpen: boolean;
56
+ /**
57
+ * Whether the reader has dismissed §17k's lifted inspector since selecting.
58
+ *
59
+ * §17k's middle row: between `1120` and `1359` the inspector *"lifts to a
60
+ * `330` overlay over the canvas, opened by selection, Escape to dismiss"*.
61
+ * Those are two rules, and this field is the second: the first is not a state
62
+ * at all, because "opened by selection" is answerable from `selection` and
63
+ * needs no second copy that could disagree with it.
64
+ *
65
+ * STATED AS THE DISMISSAL, NOT AS THE OPENNESS, so that a new selection
66
+ * re-opens the panel without any arm having to remember to say so. `reduceHost`
67
+ * clears it wherever the selection moves — one place, rather than in each of
68
+ * the eight arms that can move it.
69
+ */
70
+ readonly inspectorDismissed: boolean;
71
+ /**
72
+ * Whether §17d's audit overlay is on screen.
73
+ *
74
+ * A SECOND FIELD RATHER THAN A REUSE OF `auditFiltered`, because the header
75
+ * count stopped being the filter. `RULINGS.md` §3 makes it this overlay's
76
+ * anchor and puts the filter in the panel head, so "which rows the rail
77
+ * shows" and "is the panel open" are two questions now. One boolean answering
78
+ * both is how a reader ended up unable to open the panel without narrowing
79
+ * the rail underneath it.
80
+ */
81
+ readonly auditOpen: boolean;
82
+ /**
83
+ * The rail rows whose provenance line the reader has opened, per §16f's
84
+ * `→ expand provenance`.
85
+ *
86
+ * THE HOST HOLDS IT BECAUSE THE VIEWER CANNOT. `@issuegraph/viewer` renders
87
+ * what it is given and keeps nothing across a redraw, so it publishes
88
+ * `expand:<key>` / `collapse:<key>` and this state is the answer it is handed
89
+ * back. Same shape as `auditFiltered` one field up: a reader's view
90
+ * preference, not a fact about the document.
91
+ */
92
+ readonly expanded: readonly string[];
40
93
  /** The rail window's first slot — a scroll offset in rows, never a rank. */
41
94
  readonly railStart: number;
42
95
  readonly draft: CreateDraft;
@@ -46,16 +99,37 @@ export interface HostState {
46
99
  readonly drag: string | null;
47
100
  /** Where a canvas drop landed, so the kind chooser can be placed there. */
48
101
  readonly drop: Point | null;
102
+ /** The first-pass surface: shut, scanning, failed, or holding a queue. */
103
+ readonly firstPass: FirstPassState;
104
+ /**
105
+ * Which conflicted write has its held document on show, if any.
106
+ *
107
+ * ONE AT A TIME: the difference is drawn inside a panel rather than a dialog,
108
+ * and two open at once would push the second past the fold on the surface
109
+ * whose whole job is to be read at a glance.
110
+ *
111
+ * PRUNED BY THE SHELL, NOT BY `reconcileHost`. Its lifetime is the WRITE
112
+ * LEDGER's and reconciliation sees only the landed document — a mutation id
113
+ * is not answerable from a `GraphDocument`. `mountWorkspace` already walks
114
+ * the ledger to prune `writeCarriers` and clears this in the same pass, on a
115
+ * rule stricter than "still in the ledger": a `retry on latest` reserves its
116
+ * record as `pending` and a resolve whose re-check refuses leaves it
117
+ * `invalid`, and in BOTH the record is still there with its held document
118
+ * gone. So the rule is "still a conflict".
119
+ */
120
+ readonly diffOpen: MutationId | null;
49
121
  }
50
122
  export declare const INITIAL_HOST_STATE: HostState;
51
123
  /**
52
124
  * What the shell saw.
53
125
  *
54
126
  * `control` carries a `data-ig-command` — the package's own vocabulary
55
- * (`select-edge`, `focus`, `search`, `retype`, `flip`, …) and the mount's
56
- * chrome (`add`, `kind`, `target`, `delete`, `retry`, …) share one channel
57
- * because the shell reads one attribute. `point` and `group` are the viewer's
58
- * two identities: a focusable issue key, and a mark naming an edge or a slot.
127
+ * (`select-edge`, `focus`, `add`, `kind`, `delete`, `cancel`, …) and the
128
+ * mount's chrome, which is now the handful of controls that need a DOM or a
129
+ * host's own surface (`target-query`, `target`, `audit-filter`, `retry`,
130
+ * `discard`) — share one channel because the shell reads one attribute.
131
+ * `point` and `group` are the viewer's two identities: a focusable issue key,
132
+ * and a mark naming an edge or a slot.
59
133
  */
60
134
  export type HostCommand = {
61
135
  readonly kind: 'point';
@@ -81,11 +155,38 @@ export type HostCommand = {
81
155
  readonly kind: 'drop';
82
156
  readonly key: string | null;
83
157
  readonly at: Point;
158
+ }
159
+ /**
160
+ * A first-pass act that did not arrive as a `data-ig-command` string.
161
+ *
162
+ * The keyboard's intent is already a typed {@link FirstPassCommand}-shaped
163
+ * value and a scan's answer is a list of candidates, so both reach this
164
+ * reducer as VALUES rather than being flattened into an attribute and parsed
165
+ * back out. The controls that DO arrive as attributes still come through
166
+ * `control`, and both routes end in the same arm below.
167
+ */
168
+ | {
169
+ readonly kind: 'first-pass';
170
+ readonly command: FirstPassCommand;
84
171
  };
85
172
  /** What the shell performs against the store after reducing. */
86
173
  export type HostEffect = {
87
174
  readonly kind: 'propose';
88
175
  readonly proposal: Proposal;
176
+ /**
177
+ * The issue this edit is about, answered ONCE — here, and never again.
178
+ *
179
+ * THE SHELL REMEMBERS IT AGAINST THE WRITE. A refusal arrives from the
180
+ * store long after the act that caused it, by which time a sibling write
181
+ * may have taken the relationship away; asking then is asking a document
182
+ * that no longer holds the answer. See {@link editCarrier} for what the
183
+ * remaining sources can and cannot say, and `mount.ts` for the map this
184
+ * value is recorded in.
185
+ *
186
+ * `null` when the document holds NEITHER end — there is no panel for an
187
+ * issue this backlog does not carry, so there is nowhere to state it.
188
+ */
189
+ readonly carrier: string | null;
89
190
  } | {
90
191
  readonly kind: 'retry';
91
192
  readonly mutationId: MutationId;
@@ -94,15 +195,148 @@ export type HostEffect = {
94
195
  readonly mutationId: MutationId;
95
196
  } | {
96
197
  readonly kind: 'dismiss-change';
198
+ }
199
+ /**
200
+ * Run the host's candidate scan under this generation.
201
+ *
202
+ * The port is asynchronous by declaration, so the scan is an EFFECT and its
203
+ * answer comes back as a command. The generation rides along because a close
204
+ * and a re-open can leave two scans in flight — see `firstpass.ts`.
205
+ */
206
+ | {
207
+ readonly kind: 'find-candidates';
208
+ readonly scan: number;
209
+ }
210
+ /**
211
+ * An `apply`: propose this create, and REMEMBER which candidate it was.
212
+ *
213
+ * Its own arm rather than a plain `propose`, because the shell has to be able
214
+ * to find this exact write again if the reader takes the answer back — and it
215
+ * cannot do that from the create's fields. `candidates.ts` mints a distinct
216
+ * {@link CandidateId} per finding precisely so two detectors proposing the
217
+ * same pair stay two findings, so `kind`/`from`/`to` does not identify a
218
+ * write; only the `MutationId` the store returns does, and only the shell
219
+ * ever sees it.
220
+ */
221
+ | {
222
+ readonly kind: 'first-pass-apply';
223
+ readonly candidateId: CandidateId;
224
+ readonly proposal: Proposal;
225
+ /** As on `propose`, and for the same reason — this arm emits a write too. */
226
+ readonly carrier: string | null;
227
+ }
228
+ /**
229
+ * An `undo` took back an `apply`, and the shell decides what the store can do
230
+ * about it.
231
+ *
232
+ * The CANDIDATE rather than a proposal: this reducer does not build a
233
+ * `Proposal` for a write it is not making, and the shell matches the create
234
+ * against the store's own records by the candidate's own fields.
235
+ */
236
+ | {
237
+ readonly kind: 'first-pass-withdraw';
238
+ readonly candidateId: CandidateId;
97
239
  };
98
240
  export interface HostResult {
99
241
  readonly state: HostState;
100
242
  readonly effects: readonly HostEffect[];
243
+ /**
244
+ * Whether this reducer HAS AN ARM for the command, rather than whether the
245
+ * command changed anything.
246
+ *
247
+ * The two are different and only one of them is answerable here. Plenty of
248
+ * arms settle without changing state — a `retype` with no edge selected, a
249
+ * `focus` that was already focused — and those are still this reducer's acts.
250
+ * What `false` means is narrower and is the `default` arm's own words: a
251
+ * command published on the same attribute that belongs to the HOST's chrome,
252
+ * which this reducer must not guess at.
253
+ *
254
+ * IT EXISTS FOR THE KEYBOARD. A shell activating a control from a key press
255
+ * has to cancel the press, or the browser's own activation behaviour fires a
256
+ * second click and the act happens twice — but cancelling a press whose
257
+ * command this reducer never owned suppresses the native click the host's own
258
+ * listener was waiting for, and the host's control silently stops answering
259
+ * the keyboard. The shell cannot tell those apart from the outside; this
260
+ * reducer already knows, so it says.
261
+ */
262
+ readonly claimed: boolean;
101
263
  }
102
- /** The one reducer. `document` is the landed document, for edge lookups. */
264
+ /**
265
+ * Which issue an edit is ABOUT — the panel that states it, and the panel it is
266
+ * refused on.
267
+ *
268
+ * THE SUBJECT OF AN EDIT IS DECIDED ONCE, AND THAT MEANS ONCE IN TIME AS WELL
269
+ * AS ONCE IN THE SOURCE. It used to be decided twice and in two vocabularies:
270
+ * the panel derived its own subject from the selection (canonicalized onto a
271
+ * together unit's lead), and the inspector separately asked whether the REFUSED
272
+ * EDGE's identity named that subject. Two derivations of one fact diverge, and
273
+ * they did, three times over. This function replaced the second derivation —
274
+ * and then a fourth divergence appeared inside it, because it was still being
275
+ * CALLED twice: once when the edit went out, and again when the refusal came
276
+ * back, against a document a sibling write had changed in between. So the shell
277
+ * calls it at the moment of emission, records the answer against the write, and
278
+ * reads the record afterwards. See `HostEffect`'s `carrier` and `mount.ts`.
279
+ *
280
+ * THE CARRIER'S END WINS, AND THE FAR END IS THE FALLBACK. The relationship is
281
+ * declared in the carrier's block, so that is the panel a reader made the edit
282
+ * from and the panel that can undo it. A create naming an unknown SOURCE has
283
+ * no such panel, and stating the refusal on the target's — the only issue the
284
+ * document holds — beats stating it nowhere.
285
+ *
286
+ * AND WITH ONLY AN IDENTITY LEFT, THE SAME RANKING APPLIES AS FAR AS THE FORMAT
287
+ * KEPT IT. `edgeIdentity` discards the declaring end of a SYMMETRIC pair and
288
+ * keeps it for a directed one, so `edgeIdentityEnd` names the carrier of a
289
+ * directed identity and answers `either` for a symmetric one — and both arms
290
+ * here rank by one rule instead of two. THIS ARM HAS BEEN WRONG IN BOTH
291
+ * DIRECTIONS: ranking a symmetric identity's segments invented an order the
292
+ * format had thrown away and stated a refusal on the far end's panel, and the
293
+ * correction — ranking nothing at all — discarded the order a DIRECTED identity
294
+ * still carries, so a host proposing on the shared store had its refusal placed
295
+ * under whichever end `document.issues` listed first. `either`, and a directed
296
+ * identity whose carrier this backlog does not hold, both fall through to the
297
+ * fallback this arm always had: "an issue this backlog holds and this edit was
298
+ * between", in the document's own order. The reader's own edits reach none of
299
+ * it, because their carrier was taken while the edge was still there.
300
+ *
301
+ * `null` when the document holds NEITHER end, which is not a refusal being
302
+ * dropped: there is no panel for an issue this backlog does not carry, so
303
+ * there is nowhere the reader could be standing to read it.
304
+ */
305
+ export declare function editCarrier(document: GraphDocument, proposal: Proposal): string | null;
306
+ /**
307
+ * Whether either of §17k's two transient surfaces is currently open.
308
+ *
309
+ * ONE PREDICATE, TWO CALLERS. `reduceHost`'s `narrow-dismiss` arm decides
310
+ * whether the press changed anything, and `mountWorkspace` decides whether to
311
+ * cancel it; those have to agree, and a shell that cancelled a press this
312
+ * reducer answered `unclaimed` to would take Escape away from whatever was
313
+ * listening outside. See {@link HostResult.claimed}.
314
+ *
315
+ * THE INSPECTOR HALF IS DERIVED FROM THE SELECTION, which is the point of
316
+ * storing the DISMISSAL rather than the openness: §17k opens the panel "by
317
+ * selection", so with nothing selected there is nothing lifted, whatever the
318
+ * reader last pressed.
319
+ */
320
+ export declare function narrowOverlayOpen(state: HostState): boolean;
321
+ /**
322
+ * The one reducer. `document` is the landed document, for edge lookups.
323
+ *
324
+ * ## The one rule this wrapper adds
325
+ *
326
+ * §17k's lifted inspector is *"opened by selection"*, and a selection moves
327
+ * from eight different arms below — a rail row, a canvas node, a mark, an audit
328
+ * remedy's `reveal-issue`, a hold's deep link, a drop, a create that settles,
329
+ * and reconciliation dropping a stale one. Clearing the dismissal in each of
330
+ * them is eight chances to forget, and forgetting reads as a panel that opens
331
+ * for some selections and not others.
332
+ *
333
+ * SO IT IS ASKED OF THE RESULT, ONCE: if the selection MOVED and now names
334
+ * something, the panel is open again. Comparing the two selections rather than
335
+ * listing the commands that change one is what makes a ninth arm free.
336
+ */
103
337
  export declare function reduceHost(state: HostState, command: HostCommand, document: GraphDocument): HostResult;
104
338
  /**
105
- * Bring the state back into agreement with a document that moved under it.
339
+ * Bring the state back into agreement with what the reader can SEE.
106
340
  *
107
341
  * The store re-renders on every landed write, and a write can remove what the
108
342
  * state names: a retype or a flip gives the edge a NEW identity, a delete
@@ -111,12 +345,50 @@ export declare function reduceHost(state: HostState, command: HostCommand, docum
111
345
  * the inspector showing a picker for nothing — the viewer already refuses a
112
346
  * stale selection the same way, so the host does too, from the document
113
347
  * rather than from memory of what it just proposed.
348
+ *
349
+ * ## `hidden` is the OTHER half of "no longer carries", and the landed
350
+ * document cannot state it
351
+ *
352
+ * `document` is what LANDED, and an unsettled retype or flip lands nothing —
353
+ * so the edge the reader was inspecting is still in it, and the check above
354
+ * passes, while the store's projection has already hidden that edge and the
355
+ * workspace has already stopped drawing it. Two documents were answering
356
+ * "does this selection resolve", and they disagreed for the whole life of the
357
+ * write: the panel resolved the selection to `none` and drew the empty
358
+ * sentence, and — because a refusal is only drawn for the subject it names —
359
+ * the reason the edit was refused was drawn nowhere at all. A reader who
360
+ * retyped an edge into a relationship that already exists saw the picker
361
+ * close and nothing else. `hidden` is the store's own set of landed edges its
362
+ * projection is not showing, so both halves of the question are asked here
363
+ * and the answer is one.
364
+ *
365
+ * A HIDDEN EDGE RETURNS THE PANEL TO ITS CARRIER, not to nothing. Through
366
+ * {@link carrierOf}, which is the same rule the refusal's own carrier was taken
367
+ * by when the edit went out — so the panel this lands on and the panel the
368
+ * refusal is stated under are one answer rather than two that agree. Clearing to `none`
369
+ * instead would be the same silence the check above already produced.
370
+ *
371
+ * IT IS A BACKSTOP NOW, NOT THE ONLY GUARD. `emitting` already puts the panel
372
+ * on the carrier the moment the reader's own edit goes out, so the route this
373
+ * paragraph was written for cannot reach here any more. What still can is a
374
+ * SIBLING write: another edit's retype or flip hiding the edge this selection
375
+ * names, which no act of the reader's announced.
376
+ *
377
+ * RECONCILING ONTO THE PROJECTED REPLACEMENT was the other candidate — follow
378
+ * the selection to the identity the edit produced — and it cannot be done from
379
+ * here or anywhere else. It works only when that identity happens to be
380
+ * landed, which is exactly one of the two refusals this route reaches:
381
+ * `duplicate-edge` produces an edge that already exists, but `cardinality`
382
+ * produces a PHANTOM, and a selection naming an edge the landed document does
383
+ * not carry is dropped by the first check in this very function on the next
384
+ * render. Measured: `reconcileHost` returns `{ kind: 'none' }` for it. That is
385
+ * the same vanishing one frame later, and it is the same decision the phantom
386
+ * capsule already records by publishing no `select-edge` — there is nothing
387
+ * there to select.
114
388
  */
115
- export declare function reconcileHost(state: HostState, document: GraphDocument): HostState;
389
+ export declare function reconcileHost(state: HostState, document: GraphDocument, hidden: ReadonlySet<EdgeId>): HostState;
116
390
  /** The issues a target search offers, by reference or title, never the source itself. */
117
391
  export declare function targetMatches(issues: readonly StoredIssue[], query: string, source: string | null, limit?: number): readonly StoredIssue[];
118
- /** The edge kinds, in the format's order — the keyboard path's `1`–`5` is this list. */
119
- export declare const KINDS: readonly EdgeField[];
120
392
  /** How far the reader may scroll into the rail window before it is re-cut around them, in rows. */
121
393
  export declare const RAIL_SLACK = 20;
122
394
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/workspace/host.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/workspace/host.ts"],"names":[],"mappings":"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"}