@jbrowse/core 5.0.0-beta.2 → 5.0.0-beta.4

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 (142) hide show
  1. package/README.md +70 -40
  2. package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.d.ts +2 -3
  3. package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.d.ts +4 -0
  4. package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.js +17 -0
  5. package/esm/BaseFeatureWidget/BaseFeatureDetail/index.js +4 -3
  6. package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.d.ts +2 -2
  7. package/esm/BaseFeatureWidget/index.d.ts +1 -1
  8. package/esm/BaseFeatureWidget/stateModelFactory.d.ts +8 -1
  9. package/esm/BaseFeatureWidget/stateModelFactory.js +6 -0
  10. package/esm/BaseFeatureWidget/types.d.ts +10 -2
  11. package/esm/PluginManager.d.ts +30 -1
  12. package/esm/PluginManager.js +107 -70
  13. package/esm/ReExports/BaseFeatureDetails.js +1 -1
  14. package/esm/ReExports/MuiDataGridReExports.d.ts +1 -0
  15. package/esm/ReExports/MuiDataGridReExports.js +2 -2
  16. package/esm/ReExports/barrelOnlyNames.d.ts +5 -0
  17. package/esm/ReExports/barrelOnlyNames.js +63 -0
  18. package/esm/ReExports/modules.js +28 -56
  19. package/esm/ReExports/publicTracks.d.ts +1 -0
  20. package/esm/ReExports/publicTracks.js +14 -0
  21. package/esm/ReExports/publicUi.d.ts +4 -0
  22. package/esm/ReExports/publicUi.js +33 -0
  23. package/esm/ReExports/publicUtil.d.ts +1 -1
  24. package/esm/ReExports/publicUtil.js +8 -4
  25. package/esm/ReExports/sharedModules.d.ts +1 -1
  26. package/esm/ReExports/sharedModules.js +8 -1
  27. package/esm/ReExports/uiStub.d.ts +1 -0
  28. package/esm/ReExports/uiStub.js +6 -8
  29. package/esm/ReExports/workerModules.js +9 -4
  30. package/esm/ReExports/workerNamespaceNames.d.ts +11 -0
  31. package/esm/ReExports/workerNamespaceNames.js +281 -0
  32. package/esm/configuration/configurationSchema.js +11 -0
  33. package/esm/configuration/index.d.ts +2 -2
  34. package/esm/configuration/index.js +1 -1
  35. package/esm/configuration/promotableDefaults.d.ts +54 -19
  36. package/esm/configuration/promotableDefaults.js +108 -45
  37. package/esm/configuration/promotablePin.d.ts +50 -40
  38. package/esm/configuration/promotableResolve.d.ts +1 -1
  39. package/esm/configuration/promotableResolve.js +1 -1
  40. package/esm/configuration/tabixIndexFields.d.ts +2 -2
  41. package/esm/configuration/tabixIndexFields.js +2 -2
  42. package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +4 -12
  43. package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +12 -0
  44. package/esm/data_adapters/BaseAdapter/featureDensity.js +15 -0
  45. package/esm/data_adapters/BaseAdapter/index.d.ts +2 -2
  46. package/esm/data_adapters/BaseAdapter/index.js +1 -1
  47. package/esm/data_adapters/BaseAdapter/types.d.ts +2 -8
  48. package/esm/pluggableElementTypes/AdapterType.d.ts +2 -1
  49. package/esm/pluggableElementTypes/AdapterType.js +1 -1
  50. package/esm/pluggableElementTypes/DisplayType.d.ts +3 -10
  51. package/esm/pluggableElementTypes/DisplayType.js +3 -45
  52. package/esm/pluggableElementTypes/LazyStateModelElement.d.ts +27 -0
  53. package/esm/pluggableElementTypes/LazyStateModelElement.js +71 -0
  54. package/esm/pluggableElementTypes/ViewType.d.ts +3 -10
  55. package/esm/pluggableElementTypes/ViewType.js +6 -51
  56. package/esm/pluggableElementTypes/extendElementType.d.ts +1 -2
  57. package/esm/pluggableElementTypes/extendElementType.js +1 -2
  58. package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +3 -3
  59. package/esm/pluggableElementTypes/models/BaseDisplayModel.js +1 -1
  60. package/esm/pluggableElementTypes/models/BaseTrackModel.js +1 -4
  61. package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +34 -34
  62. package/esm/pluggableElementTypes/models/BaseViewModel.js +19 -30
  63. package/esm/pluggableElementTypes/models/assertDisplayContract.d.ts +4 -3
  64. package/esm/pluggableElementTypes/models/assertDisplayContract.js +2 -2
  65. package/esm/pluggableElementTypes/models/baseTrackConfig.js +7 -1
  66. package/esm/ui/BaseExportSvgDialog.d.ts +1 -1
  67. package/esm/ui/ErrorMessageStackTraceDialog.js +5 -6
  68. package/esm/ui/ExportSvgDialog.d.ts +1 -1
  69. package/esm/ui/MenuTypes.d.ts +3 -3
  70. package/esm/ui/PinAdornment.js +22 -40
  71. package/esm/ui/ScrollChrome.d.ts +16 -0
  72. package/esm/ui/ScrollChrome.js +12 -0
  73. package/esm/ui/ScrollZoomToggle.d.ts +4 -3
  74. package/esm/ui/ScrollZoomToggle.js +4 -3
  75. package/esm/ui/SizeSliderRow.js +1 -1
  76. package/esm/ui/index.d.ts +2 -2
  77. package/esm/ui/index.js +3 -3
  78. package/esm/ui/legendMenuItem.d.ts +9 -15
  79. package/esm/ui/legendMenuItem.js +8 -19
  80. package/esm/ui/menuItemAdornment.d.ts +2 -3
  81. package/esm/ui/menuItemAdornment.js +2 -3
  82. package/esm/ui/menuItems.d.ts +1 -2
  83. package/esm/ui/menuItems.js +0 -1
  84. package/esm/ui/palette.d.ts +11 -11
  85. package/esm/ui/palette.js +11 -11
  86. package/esm/ui/promotablePinCoverage.d.ts +16 -2
  87. package/esm/ui/promotablePinCoverage.js +38 -2
  88. package/esm/ui/theme.js +5 -0
  89. package/esm/ui/toggleMenuItems.d.ts +13 -6
  90. package/esm/ui/toggleMenuItems.js +32 -15
  91. package/esm/util/Base1DUtils.d.ts +4 -2
  92. package/esm/util/Base1DUtils.js +12 -4
  93. package/esm/util/SvgCanvas.js +4 -3
  94. package/esm/util/adapterConfigKey.d.ts +12 -0
  95. package/esm/util/adapterConfigKey.js +14 -0
  96. package/esm/util/adapterMetadata.js +2 -1
  97. package/esm/util/analytics.js +4 -5
  98. package/esm/util/clampToContig.d.ts +17 -0
  99. package/esm/util/clampToContig.js +19 -0
  100. package/esm/util/colorBits.d.ts +2 -1
  101. package/esm/util/colorBits.js +2 -5
  102. package/esm/util/createStopTokenRotation.d.ts +8 -7
  103. package/esm/util/featureTypes.d.ts +24 -0
  104. package/esm/util/featureTypes.js +35 -0
  105. package/esm/util/fetchPhases.d.ts +1 -1
  106. package/esm/util/index.d.ts +4 -2
  107. package/esm/util/index.js +3 -1
  108. package/esm/util/installFetch.d.ts +29 -18
  109. package/esm/util/installFetch.js +17 -17
  110. package/esm/util/installInitAutorun.d.ts +6 -5
  111. package/esm/util/installInitAutorun.js +2 -2
  112. package/esm/util/installPrerequisiteFetch.d.ts +86 -0
  113. package/esm/util/installPrerequisiteFetch.js +73 -0
  114. package/esm/util/openFeatureWidget.d.ts +5 -0
  115. package/esm/util/openFeatureWidget.js +1 -0
  116. package/esm/util/openViews.d.ts +16 -0
  117. package/esm/util/openViews.js +22 -0
  118. package/esm/util/parentWalk.d.ts +1 -1
  119. package/esm/util/parentWalk.js +1 -1
  120. package/esm/util/renderToStaticMarkup.js +10 -0
  121. package/esm/util/scheduleDetachedDestroy.d.ts +18 -0
  122. package/esm/util/scheduleDetachedDestroy.js +24 -0
  123. package/esm/util/scrollLatch.d.ts +1 -0
  124. package/esm/util/scrollLatch.js +8 -0
  125. package/esm/util/stopToken.d.ts +6 -5
  126. package/esm/util/trackConfigDelta.d.ts +6 -6
  127. package/esm/util/trackConfigDelta.js +3 -3
  128. package/esm/util/types/index.d.ts +25 -20
  129. package/esm/util/usePanelVirtualScroll.d.ts +6 -2
  130. package/esm/util/usePanelVirtualScroll.js +6 -2
  131. package/esm/util/useRowVirtualScroll.d.ts +1 -1
  132. package/esm/util/useRowVirtualScroll.js +1 -1
  133. package/esm/util/useVirtualScrollWheel.js +11 -1
  134. package/esm/util/wheelZoom.d.ts +3 -1
  135. package/esm/util/wheelZoom.js +39 -14
  136. package/esm/util/whenViewSettled.d.ts +31 -6
  137. package/esm/util/whenViewSettled.js +33 -5
  138. package/esm/util/withLaunchInput.d.ts +47 -2
  139. package/esm/util/withLaunchInput.js +56 -11
  140. package/package.json +10 -5
  141. package/esm/ui/promotableMenuItems.d.ts +0 -19
  142. package/esm/ui/promotableMenuItems.js +0 -91
@@ -1,5 +1,7 @@
1
+ import { abgrToCssRgba } from '@jbrowse/render-core/marks/colorFill';
1
2
  import { getAlpha, getBlue, getGreen, getRed, newColor, parse, } from './color-bits/index.js';
2
3
  import { namedColorToHex } from './color/cssColorsLevel4.js';
4
+ export { abgrToCssRgba };
3
5
  export { alpha, blend, darken, formatHEX, formatHEXA, formatRGBA, getAlpha, getBlue, getGreen, getLuminance, getRed, lighten, newColor, parse, toHSLA, toRGBA, } from './color-bits/index.js';
4
6
  // Magenta sentinel for invalid input. User-written jexl color callbacks can
5
7
  // legitimately return undefined (e.g. when a feature lacks the field they
@@ -143,7 +145,6 @@ export function normalizedRgbToCss(c) {
143
145
  export function normalizedRgbToCssRgba(c, alpha) {
144
146
  return `rgba(${Math.round(c[0] * 255)},${Math.round(c[1] * 255)},${Math.round(c[2] * 255)},${alpha})`;
145
147
  }
146
- // Set fillStyle from an ABGR-packed u32.
147
148
  export function setAbgrFill(ctx, c) {
148
149
  ctx.fillStyle = abgrToCssRgba(c);
149
150
  }
@@ -165,10 +166,6 @@ export function abgrBlue(c) {
165
166
  export function abgrAlpha(c) {
166
167
  return (c >>> 24) & 0xff;
167
168
  }
168
- // Format an ABGR-packed u32 as a CSS rgba() string.
169
- export function abgrToCssRgba(c) {
170
- return `rgba(${abgrRed(c)},${abgrGreen(c)},${abgrBlue(c)},${abgrAlpha(c) / 255})`;
171
- }
172
169
  export function cssColorToNormalizedRgba(color) {
173
170
  const c = parseCssColor(color);
174
171
  return [
@@ -13,19 +13,20 @@ import type { IStateTreeNode } from '@jbrowse/mobx-state-tree';
13
13
  */
14
14
  export type StatusReporter = {
15
15
  /**
16
- * The host's own window, present on any display composing the LGV fetch
17
- * mixins. The rotation reports through it rather than opening a SECOND on
18
- * the same status field — which is what one-window-per-owner exists to
16
+ * The host's own window, present on any display composing `FetchMixin`.
17
+ * The rotation reports through it rather than opening a SECOND on the
18
+ * same status field — which is what one-window-per-owner exists to
19
19
  * prevent.
20
20
  */
21
21
  statusWindow: StatusWindow;
22
22
  setStatusMessage?: never;
23
23
  } | {
24
24
  /**
25
- * The sink for the window the rotation opens for itself. This is the mode
26
- * the displays this helper was written for are in (dotplot, synteny),
27
- * which compose no fetch mixin, along with every
28
- * {@link createStatusChannel} holder.
25
+ * The sink for the window the rotation opens for itself: the mode of a
26
+ * fetch on a host with no window of its own — the prerequisite reads,
27
+ * chord, the breakpoint overlay — along with every
28
+ * {@link createStatusChannel} holder. The comparative displays this
29
+ * helper was written for lend a window now (ADR-105).
29
30
  */
30
31
  setStatusMessage: (status?: RpcStatus) => void;
31
32
  statusWindow?: never;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Classification of a feature from its `type` string alone, for the plugins
3
+ * that decide something about a feature they did not parse. A type is the only
4
+ * thing a display, a menu or a widget can ask about a feature without knowing
5
+ * which adapter produced it, so these live in core rather than beside any one
6
+ * of their callers.
7
+ */
8
+ /**
9
+ * Whether the type names a unit of transcription — a gene, a transcript, or an
10
+ * RNA, including the pseudogene and V(D)J segment spellings. This is the
11
+ * question "does this feature have exons", not "can this feature be spliced":
12
+ * an alignment splices too and is deliberately not gene-like, because a caller
13
+ * that means to launch a protein view or read a CDS would be wrong about it.
14
+ */
15
+ export declare function isGeneLikeType(type: string | undefined): boolean;
16
+ /**
17
+ * Whether the type names a sequence alignment — SO `match` and its subtypes
18
+ * (`cDNA_match`, `EST_match`, `nucleotide_match`, `protein_match`,
19
+ * `translated_nucleotide_match`), whose `match_part` children are the aligned
20
+ * blocks and whose gaps between them are introns when the aligned sequence was
21
+ * a transcript. Separate from `isGeneLikeType` on purpose: an EST alignment is
22
+ * evidence for a gene, not one.
23
+ */
24
+ export declare function isSequenceMatchType(type: string | undefined): boolean;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Classification of a feature from its `type` string alone, for the plugins
3
+ * that decide something about a feature they did not parse. A type is the only
4
+ * thing a display, a menu or a widget can ask about a feature without knowing
5
+ * which adapter produced it, so these live in core rather than beside any one
6
+ * of their callers.
7
+ */
8
+ // Anchored at the end for gene and RNA so 'intergenic_region' is not a gene and
9
+ // 'rnapol_binding_site' is not an RNA. Unanchored for transcript, which SO
10
+ // spells both ways ('transcript', 'pseudogenic_transcript', 'transcript_region').
11
+ const GENE_LIKE_TYPE = /gene(_segment)?$|rna$|transcript/;
12
+ /**
13
+ * Whether the type names a unit of transcription — a gene, a transcript, or an
14
+ * RNA, including the pseudogene and V(D)J segment spellings. This is the
15
+ * question "does this feature have exons", not "can this feature be spliced":
16
+ * an alignment splices too and is deliberately not gene-like, because a caller
17
+ * that means to launch a protein view or read a CDS would be wrong about it.
18
+ */
19
+ export function isGeneLikeType(type) {
20
+ return type !== undefined && GENE_LIKE_TYPE.test(type.toLowerCase());
21
+ }
22
+ // SO `match` and every subtype of it is spelled `<something>_match`, so the
23
+ // suffix is the family. `match_part`, the child, is excluded by the anchor.
24
+ const SEQUENCE_MATCH_TYPE = /(^|_)match$/;
25
+ /**
26
+ * Whether the type names a sequence alignment — SO `match` and its subtypes
27
+ * (`cDNA_match`, `EST_match`, `nucleotide_match`, `protein_match`,
28
+ * `translated_nucleotide_match`), whose `match_part` children are the aligned
29
+ * blocks and whose gaps between them are introns when the aligned sequence was
30
+ * a transcript. Separate from `isGeneLikeType` on purpose: an EST alignment is
31
+ * evidence for a gene, not one.
32
+ */
33
+ export function isSequenceMatchType(type) {
34
+ return type !== undefined && SEQUENCE_MATCH_TYPE.test(type.toLowerCase());
35
+ }
@@ -43,7 +43,7 @@ export interface FetchPhases<TArgs, TResult, TCtx> {
43
43
  * gets a dead Retry button — see there.
44
44
  *
45
45
  * What it must **not** do is move a trigger read of its own under a bail-out.
46
- * See ARCHITECTURE.md §"The global-fetch trigger list must be read
46
+ * See reference/FETCH_SKELETON.md §"The global-fetch trigger list must be read
47
47
  * unconditionally".
48
48
  */
49
49
  prepare: () => TArgs | undefined;
@@ -22,7 +22,7 @@ export { MAX_ZOOM_RATE_PER_MS, SCROLL_ZOOM_FACTOR_DIVISOR, ZOOM_ACTIVE_WINDOW_MS
22
22
  export { avg, clamp, getDisplayStr, getNumberGrouping, max, maxFinite, min, minmax, polarToCartesian, radToDeg, reducePrecision, setNumberGrouping, sum, toLocale, } from './numericUtils.ts';
23
23
  export { type MinimalRegion, bpSpanPx, bpToPx, bytesForRegions, featureSpanPx, getBpDisplayStr, getTickDisplayStr, parseBpString, } from './bpUtils.ts';
24
24
  export { type BasicFeature, gatherOverlaps, mergeIntervals, } from './intervals.ts';
25
- export { clampToContig } from './clampToContig.ts';
25
+ export { clampToContig, clampToListedContig } from './clampToContig.ts';
26
26
  export { animationAllowed } from './animationAllowed.ts';
27
27
  export { springAnimate } from './springAnimate.ts';
28
28
  export { localStorageAvailable, localStorageGetBoolean, localStorageGetItem, localStorageGetJSON, localStorageGetNumber, localStorageGetStringArray, localStorageRemoveItem, localStorageSetBoolean, localStorageSetItem, localStorageSetJSON, localStorageSetNumber, notifyLocalStorageKey, subscribeToLocalStorageKey, } from './localStorage.ts';
@@ -44,7 +44,7 @@ export { downloadPhase, getLocationUri, resolveUri } from './getLocationUri.ts';
44
44
  export { measureGridWidth, resolveSelectedIds } from './dataGridUtils.ts';
45
45
  export { isRpcResult } from './rpc.ts';
46
46
  export { aesDecrypt, aesEncrypt, sha256, sha256Base64, sha256Base64Url, toBase64, toBase64Url, } from './crypto.ts';
47
- export { type FeatureWidgetTypeRef, notifyFeatureDetailsMiss, openFeatureWidget, } from './openFeatureWidget.ts';
47
+ export { type FeatureWidgetTypeRef, type ParentFeatureSummary, notifyFeatureDetailsMiss, openFeatureWidget, } from './openFeatureWidget.ts';
48
48
  export { withFeatureDetails } from './withFeatureDetails.ts';
49
49
  export { canonicalizeViewRefName, findParentThat, findParentThatIs, getAssemblyHost, getContainingDisplay, getContainingTrack, getContainingView, getEnv, getRenderingServices, launchOrReplaceView, getSession, hashCode, objectHash, } from './mstUtils.ts';
50
50
  export { getDialogHost, getNotificationSink, getPaletteHost, getRpcHost, getSessionServices, } from './sessionServices.ts';
@@ -68,9 +68,11 @@ export { saveAs } from './FileSaver/index.ts';
68
68
  export { type SaveSvgAsImageOptions, saveSvgAsImage, svgHtmlToPngBlob, } from '../svg/saveSvgAsImage.ts';
69
69
  export { type ActiveFetch, type StatusChannel, type StatusReporter, createStatusChannel, createStopTokenRotation, } from './createStopTokenRotation.ts';
70
70
  export { createSharedSetup } from './cachedSetup.ts';
71
+ export { scheduleDetachedDestroy } from './scheduleDetachedDestroy.ts';
71
72
  export { isDataCurrent } from './isDataCurrent.ts';
72
73
  export { handleFetchError, isAbortException, makeAbortError, } from './aborting.ts';
73
74
  export { linkify } from './linkify.ts';
75
+ export { isGeneLikeType, isSequenceMatchType } from './featureTypes.ts';
74
76
  export { locStringsToRegions } from './locStringsToRegions.ts';
75
77
  export type { RefNameSource } from './locStringsToRegions.ts';
76
78
  export { type ParsedLocString, UnknownRefNameError, assembleLocString, assembleLocStringRaw, assembleLocStrings, compareLocStrings, compareLocs, parseLocString, parseLocStringOneBased, stringify, } from './locString.ts';
package/esm/util/index.js CHANGED
@@ -29,7 +29,7 @@ export { MAX_ZOOM_RATE_PER_MS, SCROLL_ZOOM_FACTOR_DIVISOR, ZOOM_ACTIVE_WINDOW_MS
29
29
  export { avg, clamp, getDisplayStr, getNumberGrouping, max, maxFinite, min, minmax, polarToCartesian, radToDeg, reducePrecision, setNumberGrouping, sum, toLocale, } from './numericUtils.js';
30
30
  export { bpSpanPx, bpToPx, bytesForRegions, featureSpanPx, getBpDisplayStr, getTickDisplayStr, parseBpString, } from './bpUtils.js';
31
31
  export { gatherOverlaps, mergeIntervals, } from './intervals.js';
32
- export { clampToContig } from './clampToContig.js';
32
+ export { clampToContig, clampToListedContig } from './clampToContig.js';
33
33
  export { animationAllowed } from './animationAllowed.js';
34
34
  export { springAnimate } from './springAnimate.js';
35
35
  export { localStorageAvailable, localStorageGetBoolean, localStorageGetItem, localStorageGetJSON, localStorageGetNumber, localStorageGetStringArray, localStorageRemoveItem, localStorageSetBoolean, localStorageSetItem, localStorageSetJSON, localStorageSetNumber, notifyLocalStorageKey, subscribeToLocalStorageKey, } from './localStorage.js';
@@ -141,9 +141,11 @@ export { createStatusChannel, createStopTokenRotation, } from './createStopToken
141
141
  // through `fetchContext.ts`, which imports this barrel, so exporting it makes
142
142
  // the barrel initialize itself. Import it from `@jbrowse/core/util/installFetch`.
143
143
  export { createSharedSetup } from './cachedSetup.js';
144
+ export { scheduleDetachedDestroy } from './scheduleDetachedDestroy.js';
144
145
  export { isDataCurrent } from './isDataCurrent.js';
145
146
  export { handleFetchError, isAbortException, makeAbortError, } from './aborting.js';
146
147
  export { linkify } from './linkify.js';
148
+ export { isGeneLikeType, isSequenceMatchType } from './featureTypes.js';
147
149
  export { locStringsToRegions } from './locStringsToRegions.js';
148
150
  export { UnknownRefNameError, assembleLocString, assembleLocStringRaw, assembleLocStrings, compareLocStrings, compareLocs, parseLocString, parseLocStringOneBased, stringify, } from './locString.js';
149
151
  export { checkStopToken, checkStopTokenThrottled, createStopToken, createStopTokenChecker, hasSharedArrayBuffer, isStopToken, isStopped, markStopTokenStopped, registerStopTokenBroadcaster, stopStopToken, stopTokenSignal, withStopTokenCheck, withStopTokenSignal, } from './stopToken.js';
@@ -25,7 +25,7 @@ export interface FetchLifecycle {
25
25
  /**
26
26
  * Runs synchronously as the fetch starts, after the rotation has superseded
27
27
  * whatever it replaced: the loading flag (`FetchMixin`'s `activeStopToken`,
28
- * the comparative family's `fetching`), and anything a display blanks
28
+ * through `fetchMixinLifecycle`), and anything a display blanks
29
29
  * because it has no freshness signature to keep stale data honest with
30
30
  * (chord's refName map).
31
31
  *
@@ -127,7 +127,7 @@ interface InstallFetchOptionsBase<TArgs, TResult> extends FetchPhases<TArgs, TRe
127
127
  * also be invalidated by `reload()`, or Retry re-runs the body straight into
128
128
  * the same decline and the button is dead. Every layer that has one made
129
129
  * that pairing structural in the end — the global family after arc shipped
130
- * the bug (`GlobalFetchMixin.reload` drops `loadedFetchSignature` in the same
130
+ * the bug (`GlobalFetchMixin.reload` drops `loadedFetchKey` in the same
131
131
  * action as the bump) — and this is that move for the skeleton: a run whose
132
132
  * `reloadCounter` has advanced since the run that last ISSUED a fetch ignores
133
133
  * this gate, so nothing has to remember to clear anything. The multi-way
@@ -146,10 +146,10 @@ interface InstallFetchOptionsBase<TArgs, TResult> extends FetchPhases<TArgs, TRe
146
146
  */
147
147
  fetchKey?: (args: TArgs) => string;
148
148
  /**
149
- * The key of the data already committed, when the host keeps one — the
150
- * comparative displays stamp `loadedFetchKey`, which their `dataCurrent`
151
- * flag reads too, so a second stamp would be one more thing to disagree with
152
- * it. Omitted, the skeleton stamps its own at commit.
149
+ * The key of the data already committed, when the host keeps one —
150
+ * `KeyedFetchMixin` stamps `loadedFetchKey`, which its `dataCurrent` reads
151
+ * too, so a second stamp would be one more thing to disagree with it.
152
+ * Omitted, the skeleton stamps its own at commit.
153
153
  *
154
154
  * **Either way the stamp is observable**, and the read is tracked. Zoom A→B
155
155
  * issues a fetch for B; zoom back to A before B commits and the re-run
@@ -157,7 +157,21 @@ interface InstallFetchOptionsBase<TArgs, TResult> extends FetchPhases<TArgs, TRe
157
157
  * write is what wakes the autorun to fetch A again. A closure variable would
158
158
  * leave data B under viewport A until the next input moved.
159
159
  */
160
- committedKey?: () => string | undefined;
160
+ loadedKey?: () => string | undefined;
161
+ /**
162
+ * The predicate form of the freshness gate, for a fetch whose "I have exactly
163
+ * this already" is not string equality: the density tier holds bins over a
164
+ * buffered read and answers a viewport those bins *contain*, which no key can
165
+ * spell. Same rules as `fetchKey` — declined runs report `declined`, and a
166
+ * `reloadCounter` advanced since the last issued fetch overrides it — so the
167
+ * comparison lives here and not in `prepare`, where a reload could not reach
168
+ * it. Runs inside the autorun, so what it reads is tracked: read the
169
+ * committed state off an observable, and the commit that changes the answer
170
+ * wakes the declined run.
171
+ *
172
+ * Either this or `fetchKey`, not both.
173
+ */
174
+ heldAnswers?: (args: TArgs) => boolean;
161
175
  /**
162
176
  * Install the two display-contract checks under this name. Omitted
163
177
  * by a **secondary** fetch on a host whose primary foundation already
@@ -197,12 +211,13 @@ export type InstallFetchOptions<TArgs, TResult> = InstallFetchOptionsBase<TArgs,
197
211
  * unconditional trigger reads, the gates, and {@link runFetchOnce} under them.
198
212
  *
199
213
  * Every fetch in the tree is this shape except one family — the prerequisite
200
- * reads (HiC's header, the multi-sample sample list), the LGV global family
201
- * (`installGlobalFetchAutorun`, which lends `FetchMixin`'s rotation through the
202
- * `rotation` option so `cancelFetch` reaches the fetch it installs), both
203
- * comparative displays, the circular view's chord fetch, the breakpoint overlay
204
- * fetch and the multi-way synteny display's two DEPENDENT fetches (lane genes,
205
- * lane links, each gated on the key its own commit stamps) all take it. The
214
+ * reads (HiC's header, the multi-sample sample list), the two keyed families
215
+ * (`installGlobalFetchAutorun` and `installComparativeFetchAutorun`, which lend
216
+ * `FetchMixin`'s rotation through the `rotation` option so `cancelFetch` and
217
+ * the Cancel button reach the fetch they install), the circular view's chord
218
+ * fetch, the breakpoint overlay fetch and the multi-way synteny display's two
219
+ * DEPENDENT fetches (lane genes, lane links, each gated on the key its own
220
+ * commit stamps) all take it. The
206
221
  * exception is the per-region family's `FetchMixin.runFetch`: its trigger is
207
222
  * `planRegionFetch`'s autorun and its commits stream per region through
208
223
  * `ctx.commitRegion`, so it holds `runFetchOnce` directly and the autorun above
@@ -211,10 +226,6 @@ export type InstallFetchOptions<TArgs, TResult> = InstallFetchOptionsBase<TArgs,
211
226
  * What a caller supplies is exactly what differs between them: which reads wake
212
227
  * it (`prepare`, plus `gate`), what a round trip commits, where the loading
213
228
  * flag lives (`onBegin` / `onEnd`) and where the status goes (`report`).
214
- *
215
- * Returns the rotation's `cancel`, for a family whose model owns the user-facing
216
- * Cancel button: the flag alone is not a cancel — nothing rotates the token, the
217
- * stopped RPC stays current, and it commits over the load the user just stopped.
218
229
  */
219
- export declare function installFetch<TArgs, TResult>(self: FetchSkeletonHost, opts: InstallFetchOptions<TArgs, TResult>): () => void;
230
+ export declare function installFetch<TArgs, TResult>(self: FetchSkeletonHost, opts: InstallFetchOptions<TArgs, TResult>): void;
220
231
  export {};
@@ -90,12 +90,13 @@ function ownRotation(self, report) {
90
90
  * unconditional trigger reads, the gates, and {@link runFetchOnce} under them.
91
91
  *
92
92
  * Every fetch in the tree is this shape except one family — the prerequisite
93
- * reads (HiC's header, the multi-sample sample list), the LGV global family
94
- * (`installGlobalFetchAutorun`, which lends `FetchMixin`'s rotation through the
95
- * `rotation` option so `cancelFetch` reaches the fetch it installs), both
96
- * comparative displays, the circular view's chord fetch, the breakpoint overlay
97
- * fetch and the multi-way synteny display's two DEPENDENT fetches (lane genes,
98
- * lane links, each gated on the key its own commit stamps) all take it. The
93
+ * reads (HiC's header, the multi-sample sample list), the two keyed families
94
+ * (`installGlobalFetchAutorun` and `installComparativeFetchAutorun`, which lend
95
+ * `FetchMixin`'s rotation through the `rotation` option so `cancelFetch` and
96
+ * the Cancel button reach the fetch they install), the circular view's chord
97
+ * fetch, the breakpoint overlay fetch and the multi-way synteny display's two
98
+ * DEPENDENT fetches (lane genes, lane links, each gated on the key its own
99
+ * commit stamps) all take it. The
99
100
  * exception is the per-region family's `FetchMixin.runFetch`: its trigger is
100
101
  * `planRegionFetch`'s autorun and its commits stream per region through
101
102
  * `ctx.commitRegion`, so it holds `runFetchOnce` directly and the autorun above
@@ -104,13 +105,9 @@ function ownRotation(self, report) {
104
105
  * What a caller supplies is exactly what differs between them: which reads wake
105
106
  * it (`prepare`, plus `gate`), what a round trip commits, where the loading
106
107
  * flag lives (`onBegin` / `onEnd`) and where the status goes (`report`).
107
- *
108
- * Returns the rotation's `cancel`, for a family whose model owns the user-facing
109
- * Cancel button: the flag alone is not a cancel — nothing rotates the token, the
110
- * stopped RPC stays current, and it commits over the load the user just stopped.
111
108
  */
112
109
  export function installFetch(self, opts) {
113
- const { name, delay, gate, contract, fetchKey, committedKey, prepare, run, commit, setError, onBegin, onEnd, } = opts;
110
+ const { name, delay, gate, contract, fetchKey, loadedKey, heldAnswers, prepare, run, commit, setError, onBegin, onEnd, } = opts;
114
111
  const noteFetchAutorunRun = contract === undefined ? undefined : installContractChecks(self, contract);
115
112
  const lent = opts.rotation;
116
113
  const rotation = lent === undefined ? ownRotation(self, opts.report) : lent;
@@ -122,10 +119,16 @@ export function installFetch(self, opts) {
122
119
  // The skeleton's own stamp exists only where there is a key to stamp — a
123
120
  // fetch with no `fetchKey` never reads it, so allocating one would only feed
124
121
  // it `undefined` on every commit.
125
- const stamp = committedKey === undefined && fetchKey !== undefined
122
+ const stamp = loadedKey === undefined && fetchKey !== undefined
126
123
  ? observable.box()
127
124
  : undefined;
128
- const heldKey = committedKey ?? (() => stamp?.get());
125
+ const heldKey = loadedKey ?? (() => stamp?.get());
126
+ // the freshness gate in whichever form the caller declared it
127
+ const held = heldAnswers !== undefined
128
+ ? heldAnswers
129
+ : fetchKey !== undefined
130
+ ? (args) => isDataCurrent(heldKey(), fetchKey(args))
131
+ : undefined;
129
132
  const commitAndStamp = stamp
130
133
  ? (result, args) => {
131
134
  runInAction(() => {
@@ -173,9 +176,7 @@ export function installFetch(self, opts) {
173
176
  // consuming the retry here costs nothing — while a reload landing
174
177
  // mid-flight is answered by the re-run the counter read above already
175
178
  // guarantees.
176
- if (fetchKey !== undefined &&
177
- isDataCurrent(heldKey(), fetchKey(args)) &&
178
- reloadEpoch === issuedEpoch) {
179
+ if (held !== undefined && held(args) && reloadEpoch === issuedEpoch) {
179
180
  noteFetchAutorunRun?.('declined');
180
181
  return false;
181
182
  }
@@ -202,5 +203,4 @@ export function installFetch(self, opts) {
202
203
  },
203
204
  // #endregion
204
205
  { name, delay });
205
- return rotation.cancel;
206
206
  }
@@ -26,9 +26,10 @@ interface InitAutorunOptions<T> {
26
26
  */
27
27
  ready: () => boolean;
28
28
  /**
29
- * Whether the view has materialized — the same line each view's
30
- * postProcessSnapshot draws for persistence (dotplot: assemblyNames set;
31
- * synteny: rows built). Decides the failure policy, see below.
29
+ * Whether the view has materialized — the line `withLaunchInput`'s
30
+ * `materialized` draws for persistence, read from the live node (dotplot:
31
+ * assemblyNames set; synteny: rows built). Decides the failure policy, see
32
+ * below.
32
33
  */
33
34
  materialized: () => boolean;
34
35
  /** Apply one init blob. Owns the ordered steps; never clears `init`. */
@@ -40,8 +41,8 @@ interface InitAutorunOptions<T> {
40
41
  * the readiness gate, the serialized drain, the identity-checked clear, the
41
42
  * isAlive guards, and one failure policy.
42
43
  *
43
- * The failure policy keys off `materialized`, the same line each view's
44
- * postProcessSnapshot already draws for persistence:
44
+ * The failure policy keys off `materialized`, the same line `withLaunchInput`
45
+ * draws for persistence:
45
46
  *
46
47
  * - Not materialized — nothing is on screen and `launch` is still persisted, so
47
48
  * keep it for a reload retry and `setError`. That flips the view onto its
@@ -58,8 +58,8 @@ async function drainInit(self, opts) {
58
58
  * the readiness gate, the serialized drain, the identity-checked clear, the
59
59
  * isAlive guards, and one failure policy.
60
60
  *
61
- * The failure policy keys off `materialized`, the same line each view's
62
- * postProcessSnapshot already draws for persistence:
61
+ * The failure policy keys off `materialized`, the same line `withLaunchInput`
62
+ * draws for persistence:
63
63
  *
64
64
  * - Not materialized — nothing is on screen and `launch` is still persisted, so
65
65
  * keep it for a reload retry and `setError`. That flips the view onto its
@@ -0,0 +1,86 @@
1
+ import type { StatusReporter } from './createStopTokenRotation.ts';
2
+ import type { FetchContext } from './fetchContext.ts';
3
+ import type { FetchSkeletonHost } from './installFetch.ts';
4
+ /**
5
+ * What a prerequisite read needs of the display it runs on, beside the
6
+ * skeleton's own three. Duck-typed rather than a foundation's `Instance` type,
7
+ * because the hosts compose different foundations — one per fetch family, and
8
+ * the comparative displays compose none of them — and this is the only thing
9
+ * they have in common.
10
+ */
11
+ export interface PrerequisiteFetchHost extends FetchSkeletonHost {
12
+ /**
13
+ * Read in `prepare`, so it is **tracked**: an adapter edited in the config
14
+ * editor has to re-read, and `run`'s own reads are untracked by contract.
15
+ */
16
+ adapterConfig: Record<string, unknown>;
17
+ isMinimized: boolean;
18
+ }
19
+ /**
20
+ * A **prerequisite read**: one RPC about the adapter itself, beside the
21
+ * display's primary fetch. Three in the tree — HiC's `CoreGetInfo` header read,
22
+ * whose `resolutions` every contacts fetch waits on; the multi-sample sample
23
+ * list, which `fetchNeeded` declines until; and the tiered alignment file's
24
+ * `CoreGetInfo` header, which decides the LOD tier a synteny fetch asks for —
25
+ * and they sit on three different fetch foundations, which is why this sits in
26
+ * core beside the skeleton and not beside any of them.
27
+ *
28
+ * They had the shape below hand-copied, comment for comment, and each term is a
29
+ * rule rather than a preference:
30
+ *
31
+ * - **the adapter config is the whole trigger and the whole key.** Tracked in
32
+ * `prepare` so a config-editor edit re-reads; keyed on the same value so an
33
+ * un-minimize over the same file re-reads nothing. Getting one without the
34
+ * other gives either a stale header or a walk of a `.hic` norm-vector index on
35
+ * every expand.
36
+ * - **minimized is the gate**, and a display with a second condition of its own
37
+ * passes `gate` — the sample-list read waits for the LGV to be measured as
38
+ * well, so a full-file scan does not start ahead of the display's own first
39
+ * fetch, and the tier read waits on the track declaring a tier threshold at
40
+ * all.
41
+ * - **no `contract`.** This is the second fetch on a display whose foundation
42
+ * installed both checks already: `assertDisplayContract` would report the
43
+ * double-attach it exists to catch, and a second retry check would consume the
44
+ * same `reloadCounter` bumps as the first.
45
+ * - **where the status goes is the caller's** (`report`). The two LGV reads
46
+ * lend the display's own status window, so the read takes a slot beside the
47
+ * primary fetch rather than opening a second writer over the one status field
48
+ * (ADR-081) — and it matters more here than for most fetches: a prerequisite
49
+ * runs inside the pre-first-paint window, where the scrim is up because
50
+ * nothing is drawn rather than because `isLoading` is, so `statusMessage` is
51
+ * the only thing that can say what is happening. The tier read narrates
52
+ * nothing; a header is not a load.
53
+ *
54
+ * `createAdapterMetadataFetch` keys on the same adapter config and is
55
+ * deliberately NOT one of these: no trigger, no stop token and no status,
56
+ * because it is fetched lazily when a details widget opens and the widget opens
57
+ * on the result. A prerequisite read is the one a display's own fetch waits on.
58
+ *
59
+ * **A declaration, not the skeleton this name used to be.** There was an
60
+ * `installPrerequisiteFetch` until 2026-08-23, and `3c5aa7fce2` deleted it for
61
+ * a good reason: it carried a `runOne` of its own — a fifth copy of begin →
62
+ * clear → run → commit-if-current → `handleFetchError` → end — and once
63
+ * `installFetch` owned that sequence, a second one was pure drift surface. This
64
+ * one adds no sequence, no rotation and no error rule; it is terms handed to
65
+ * `installFetch`, the same shape `installGlobalFetchAutorun` and
66
+ * `installComparativeFetchAutorun` are. Add nothing here that a family could
67
+ * not state as an option to the skeleton.
68
+ *
69
+ * Everything the skeleton gives it is the point of going through the skeleton:
70
+ * the latest-wins rotation (so a superseding read aborts the one it replaced,
71
+ * and only a superseding read does — a user cancel of the primary fetch cannot
72
+ * strand the display the way sharing its token would), the clear at the start,
73
+ * the currency-guarded error rule, the unconditional `reloadCounter` read that
74
+ * makes the chrome's Retry re-run this, and the retired status slot that keeps a
75
+ * failed read from leaving a progress chip up for good.
76
+ */
77
+ export declare function installPrerequisiteFetch<TResult>(self: PrerequisiteFetchHost, { name, delay, report, gate, run, commit, setError, }: {
78
+ name: string;
79
+ delay: number;
80
+ report: StatusReporter;
81
+ /** an extra term of the display's own, ANDed under `!isMinimized` */
82
+ gate?: () => boolean;
83
+ run: (adapterConfig: Record<string, unknown>, ctx: FetchContext) => Promise<TResult | undefined>;
84
+ commit: (result: TResult) => void;
85
+ setError: (error?: unknown) => void;
86
+ }): void;
@@ -0,0 +1,73 @@
1
+ import { adapterConfigKey } from './adapterConfigKey.js';
2
+ import { installFetch } from './installFetch.js';
3
+ /**
4
+ * A **prerequisite read**: one RPC about the adapter itself, beside the
5
+ * display's primary fetch. Three in the tree — HiC's `CoreGetInfo` header read,
6
+ * whose `resolutions` every contacts fetch waits on; the multi-sample sample
7
+ * list, which `fetchNeeded` declines until; and the tiered alignment file's
8
+ * `CoreGetInfo` header, which decides the LOD tier a synteny fetch asks for —
9
+ * and they sit on three different fetch foundations, which is why this sits in
10
+ * core beside the skeleton and not beside any of them.
11
+ *
12
+ * They had the shape below hand-copied, comment for comment, and each term is a
13
+ * rule rather than a preference:
14
+ *
15
+ * - **the adapter config is the whole trigger and the whole key.** Tracked in
16
+ * `prepare` so a config-editor edit re-reads; keyed on the same value so an
17
+ * un-minimize over the same file re-reads nothing. Getting one without the
18
+ * other gives either a stale header or a walk of a `.hic` norm-vector index on
19
+ * every expand.
20
+ * - **minimized is the gate**, and a display with a second condition of its own
21
+ * passes `gate` — the sample-list read waits for the LGV to be measured as
22
+ * well, so a full-file scan does not start ahead of the display's own first
23
+ * fetch, and the tier read waits on the track declaring a tier threshold at
24
+ * all.
25
+ * - **no `contract`.** This is the second fetch on a display whose foundation
26
+ * installed both checks already: `assertDisplayContract` would report the
27
+ * double-attach it exists to catch, and a second retry check would consume the
28
+ * same `reloadCounter` bumps as the first.
29
+ * - **where the status goes is the caller's** (`report`). The two LGV reads
30
+ * lend the display's own status window, so the read takes a slot beside the
31
+ * primary fetch rather than opening a second writer over the one status field
32
+ * (ADR-081) — and it matters more here than for most fetches: a prerequisite
33
+ * runs inside the pre-first-paint window, where the scrim is up because
34
+ * nothing is drawn rather than because `isLoading` is, so `statusMessage` is
35
+ * the only thing that can say what is happening. The tier read narrates
36
+ * nothing; a header is not a load.
37
+ *
38
+ * `createAdapterMetadataFetch` keys on the same adapter config and is
39
+ * deliberately NOT one of these: no trigger, no stop token and no status,
40
+ * because it is fetched lazily when a details widget opens and the widget opens
41
+ * on the result. A prerequisite read is the one a display's own fetch waits on.
42
+ *
43
+ * **A declaration, not the skeleton this name used to be.** There was an
44
+ * `installPrerequisiteFetch` until 2026-08-23, and `3c5aa7fce2` deleted it for
45
+ * a good reason: it carried a `runOne` of its own — a fifth copy of begin →
46
+ * clear → run → commit-if-current → `handleFetchError` → end — and once
47
+ * `installFetch` owned that sequence, a second one was pure drift surface. This
48
+ * one adds no sequence, no rotation and no error rule; it is terms handed to
49
+ * `installFetch`, the same shape `installGlobalFetchAutorun` and
50
+ * `installComparativeFetchAutorun` are. Add nothing here that a family could
51
+ * not state as an option to the skeleton.
52
+ *
53
+ * Everything the skeleton gives it is the point of going through the skeleton:
54
+ * the latest-wins rotation (so a superseding read aborts the one it replaced,
55
+ * and only a superseding read does — a user cancel of the primary fetch cannot
56
+ * strand the display the way sharing its token would), the clear at the start,
57
+ * the currency-guarded error rule, the unconditional `reloadCounter` read that
58
+ * makes the chrome's Retry re-run this, and the retired status slot that keeps a
59
+ * failed read from leaving a progress chip up for good.
60
+ */
61
+ export function installPrerequisiteFetch(self, { name, delay, report, gate = () => true, run, commit, setError, }) {
62
+ installFetch(self, {
63
+ name,
64
+ delay,
65
+ report,
66
+ gate: () => !self.isMinimized && gate(),
67
+ prepare: () => ({ adapterConfig: self.adapterConfig }),
68
+ fetchKey: ({ adapterConfig }) => adapterConfigKey(adapterConfig),
69
+ run: ({ adapterConfig }, ctx) => run(adapterConfig, ctx),
70
+ commit,
71
+ setError,
72
+ });
73
+ }
@@ -5,10 +5,15 @@ export interface FeatureWidgetTypeRef {
5
5
  type: string;
6
6
  id: string;
7
7
  }
8
+ export interface ParentFeatureSummary {
9
+ name: string;
10
+ type?: string;
11
+ }
8
12
  export declare function openFeatureWidget(node: IAnyStateTreeNode, featureData: SimpleFeatureSerialized, opts?: {
9
13
  widget?: FeatureWidgetTypeRef;
10
14
  extra?: Record<string, unknown>;
11
15
  feature?: Feature;
16
+ parentFeature?: ParentFeatureSummary;
12
17
  }): Widget | undefined;
13
18
  /**
14
19
  * The other half of the flow above: the details lookup came back with nothing,
@@ -32,6 +32,7 @@ export function openFeatureWidget(node, featureData, opts = {}) {
32
32
  const { type, id } = opts.widget ?? DEFAULT_FEATURE_WIDGET;
33
33
  const widget = session.addWidget(type, id, {
34
34
  featureData,
35
+ parentFeature: opts.parentFeature,
35
36
  view: getContainingView(node),
36
37
  track: getContainingTrack(node),
37
38
  ...opts.extra,
@@ -0,0 +1,16 @@
1
+ import type { AbstractSessionModel, AbstractTrackModel, AbstractViewModel } from './types/index.ts';
2
+ /**
3
+ * "What is open" — the reduction four consumers wanted and each used to walk
4
+ * for itself (AppReadyMarker, jbApi, and capture's session gate and busy
5
+ * check), on different and drifting spellings of the view nesting.
6
+ *
7
+ * The recursion lives here, once. What each view contributes lives on the view,
8
+ * once, as `ownViews`/`ownTracks`. Neither half guesses at the other: the
9
+ * census is declared intent, not a shape that can be discovered, because the
10
+ * two things that look enumerable are not — the dotplot's `views` prop holds
11
+ * view-shaped axis models the user never opened, and react-msaview's `tracks`
12
+ * getter holds annotation rows that are not tracks.
13
+ */
14
+ export declare function openViews(session: AbstractSessionModel): AbstractViewModel[];
15
+ /** Every track on every open view. */
16
+ export declare function openTracks(session: AbstractSessionModel): AbstractTrackModel[];
@@ -0,0 +1,22 @@
1
+ /**
2
+ * "What is open" — the reduction four consumers wanted and each used to walk
3
+ * for itself (AppReadyMarker, jbApi, and capture's session gate and busy
4
+ * check), on different and drifting spellings of the view nesting.
5
+ *
6
+ * The recursion lives here, once. What each view contributes lives on the view,
7
+ * once, as `ownViews`/`ownTracks`. Neither half guesses at the other: the
8
+ * census is declared intent, not a shape that can be discovered, because the
9
+ * two things that look enumerable are not — the dotplot's `views` prop holds
10
+ * view-shaped axis models the user never opened, and react-msaview's `tracks`
11
+ * getter holds annotation rows that are not tracks.
12
+ */
13
+ export function openViews(session) {
14
+ return session.views.flatMap(withNested);
15
+ }
16
+ /** Every track on every open view. */
17
+ export function openTracks(session) {
18
+ return openViews(session).flatMap(v => v.ownTracks ?? []);
19
+ }
20
+ function withNested(view) {
21
+ return [view, ...(view.ownViews ?? []).flatMap(withNested)];
22
+ }
@@ -14,7 +14,7 @@ export declare function findParentThatIs<T extends (a: IAnyStateTreeNode) => boo
14
14
  * Keying on the node is safe because nothing re-parents one — both `detach`
15
15
  * call sites hand the node straight to `scheduleDetachedDestroy` (ADR-069), so
16
16
  * a cached ancestor can only go stale by dying, which the `isAlive` check
17
- * catches. That is the difference from the three memos REJECTED_IDEAS records
17
+ * catches. That is the difference from the three memos agent-docs/architecture-decision-records/ records
18
18
  * removing: each keyed on something its caller had just allocated.
19
19
  */
20
20
  export declare function cachedParent<T>(cache: WeakMap<IAnyStateTreeNode, T>, node: IAnyStateTreeNode, finder: () => T, errorMsg: string): T;
@@ -39,7 +39,7 @@ export function findParentThatIs(node, predicate) {
39
39
  * Keying on the node is safe because nothing re-parents one — both `detach`
40
40
  * call sites hand the node straight to `scheduleDetachedDestroy` (ADR-069), so
41
41
  * a cached ancestor can only go stale by dying, which the `isAlive` check
42
- * catches. That is the difference from the three memos REJECTED_IDEAS records
42
+ * catches. That is the difference from the three memos agent-docs/architecture-decision-records/ records
43
43
  * removing: each keyed on something its caller had just allocated.
44
44
  */
45
45
  export function cachedParent(cache, node, finder, errorMsg) {