@yahoo/uds-create-config 2.44.0 → 3.0.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 (376) hide show
  1. package/README.md +129 -0
  2. package/dist/ai-lanes.d.ts +23 -0
  3. package/dist/ai-lanes.js +34 -0
  4. package/dist/authoring/define-component.d.ts +85 -0
  5. package/dist/configs/CanvasConfig.d.ts +3237 -0
  6. package/dist/configs/CanvasConfig.js +332 -0
  7. package/dist/configs/build-options.d.ts +10 -0
  8. package/dist/configs/build-options.js +68 -0
  9. package/dist/configs/platform.d.ts +15 -0
  10. package/dist/configs/platform.js +17 -0
  11. package/dist/configs/react-native-system.d.ts +3026 -0
  12. package/dist/configs/react-native-system.js +64 -0
  13. package/dist/configs/system.d.ts +2771 -0
  14. package/dist/configs/system.js +74 -0
  15. package/dist/css/properties.generated.d.ts +14 -0
  16. package/dist/css/properties.generated.js +6260 -0
  17. package/dist/css/value-type.d.ts +48 -0
  18. package/dist/css/value-type.js +131 -0
  19. package/dist/css/values.d.ts +33 -0
  20. package/dist/css/values.js +116 -0
  21. package/dist/entities/native/NativeModifier.d.ts +25 -0
  22. package/dist/entities/native/NativeModifier.js +41 -0
  23. package/dist/entities/native/NativeSettings.d.ts +44 -0
  24. package/dist/entities/native/NativeSettings.js +39 -0
  25. package/dist/entities/native/NativeStyleProperty.d.ts +355 -0
  26. package/dist/entities/native/NativeStyleProperty.js +28 -0
  27. package/dist/entities/native/NativeToken.d.ts +31 -0
  28. package/dist/entities/native/NativeToken.js +49 -0
  29. package/dist/entities/system/CanvasRole.d.ts +34 -0
  30. package/dist/entities/system/CanvasRole.js +45 -0
  31. package/dist/entities/system/Component.d.ts +1287 -0
  32. package/dist/entities/system/Component.js +1840 -0
  33. package/dist/entities/system/Composite.d.ts +12 -0
  34. package/dist/entities/system/Composite.js +26 -0
  35. package/dist/entities/system/Device.d.ts +11 -0
  36. package/dist/entities/system/Device.js +18 -0
  37. package/dist/entities/system/File.d.ts +72 -0
  38. package/dist/entities/system/File.js +136 -0
  39. package/dist/entities/system/Font.d.ts +48 -0
  40. package/dist/entities/system/Font.js +56 -0
  41. package/dist/entities/system/GlobalStyle.d.ts +26 -0
  42. package/dist/entities/system/GlobalStyle.js +54 -0
  43. package/dist/entities/system/Guidance.d.ts +85 -0
  44. package/dist/entities/system/Guidance.js +59 -0
  45. package/dist/entities/system/GuidanceStyle.d.ts +14 -0
  46. package/dist/entities/system/GuidanceStyle.js +8 -0
  47. package/dist/entities/system/Icon.d.ts +46 -0
  48. package/dist/entities/system/Icon.js +46 -0
  49. package/dist/entities/system/LinkedSystem.d.ts +504 -0
  50. package/dist/entities/system/LinkedSystem.js +814 -0
  51. package/dist/entities/system/Modifier.d.ts +92 -0
  52. package/dist/entities/system/Modifier.js +120 -0
  53. package/dist/entities/system/Motion.d.ts +28 -0
  54. package/dist/entities/system/Motion.js +48 -0
  55. package/dist/entities/system/Operation.d.ts +100 -0
  56. package/dist/entities/system/Operation.js +236 -0
  57. package/dist/entities/system/Package.d.ts +42 -0
  58. package/dist/entities/system/Package.js +75 -0
  59. package/dist/entities/system/Settings.d.ts +94 -0
  60. package/dist/entities/system/Settings.js +166 -0
  61. package/dist/entities/system/StyleProperty.d.ts +135 -0
  62. package/dist/entities/system/StyleProperty.js +438 -0
  63. package/dist/entities/system/Token.d.ts +67 -0
  64. package/dist/entities/system/Token.js +129 -0
  65. package/dist/entities/system/Tool.d.ts +134 -0
  66. package/dist/entities/system/Tool.js +124 -0
  67. package/dist/entities/system/color.d.ts +64 -0
  68. package/dist/entities/system/color.js +123 -0
  69. package/dist/entities/system/component-module.d.ts +63 -0
  70. package/dist/entities/system/component-module.js +258 -0
  71. package/dist/entities/system/copy-plan.d.ts +98 -0
  72. package/dist/entities/system/copy-plan.js +451 -0
  73. package/dist/entities/system/defineComponent.d.ts +428 -0
  74. package/dist/entities/system/defineComponent.js +337 -0
  75. package/dist/entities/system/element.d.ts +101 -0
  76. package/dist/entities/system/element.js +171 -0
  77. package/dist/entities/system/icon-library.d.ts +64 -0
  78. package/dist/entities/system/icon-library.js +112 -0
  79. package/dist/entities/system/icon-metadata.d.ts +72 -0
  80. package/dist/entities/system/icon-metadata.js +111 -0
  81. package/dist/entities/system/link-declaration.d.ts +27 -0
  82. package/dist/entities/system/link-declaration.js +64 -0
  83. package/dist/entities/system/link-plan.d.ts +160 -0
  84. package/dist/entities/system/link-plan.js +770 -0
  85. package/dist/entities/system/runtime-modules.d.ts +25 -0
  86. package/dist/entities/system/runtime-modules.js +38 -0
  87. package/dist/entities/system/style-bag.d.ts +20 -0
  88. package/dist/entities/system/style-bag.js +246 -0
  89. package/dist/entities/system/token-index.d.ts +89 -0
  90. package/dist/entities/system/token-index.js +112 -0
  91. package/dist/framework/Config.d.ts +2472 -0
  92. package/dist/framework/Config.js +5023 -0
  93. package/dist/framework/Entity.d.ts +127 -0
  94. package/dist/framework/Entity.js +125 -0
  95. package/dist/framework/authoring.d.ts +24 -0
  96. package/dist/framework/authoring.js +7 -0
  97. package/dist/framework/change-hooks.d.ts +119 -0
  98. package/dist/framework/change-hooks.js +131 -0
  99. package/dist/framework/changes.d.ts +88 -0
  100. package/dist/framework/changes.js +246 -0
  101. package/dist/framework/class-names.d.ts +260 -0
  102. package/dist/framework/class-names.js +630 -0
  103. package/dist/framework/coalesce.d.ts +25 -0
  104. package/dist/framework/coalesce.js +60 -0
  105. package/dist/framework/config-op.d.ts +76 -0
  106. package/dist/framework/config-op.js +43 -0
  107. package/dist/framework/config-operation-kind.d.ts +14 -0
  108. package/dist/framework/config-operation-kind.js +14 -0
  109. package/dist/framework/config-ops.d.ts +34 -0
  110. package/dist/framework/config-ops.js +187 -0
  111. package/dist/framework/defineConfig.d.ts +196 -0
  112. package/dist/framework/defineConfig.js +100 -0
  113. package/dist/framework/defineDerivedEntity.d.ts +74 -0
  114. package/dist/framework/defineDerivedEntity.js +83 -0
  115. package/dist/framework/defineEntity.d.ts +318 -0
  116. package/dist/framework/defineEntity.js +183 -0
  117. package/dist/framework/defineSubEntity.d.ts +148 -0
  118. package/dist/framework/defineSubEntity.js +121 -0
  119. package/dist/framework/derived-mutations.d.ts +20 -0
  120. package/dist/framework/derived-mutations.js +38 -0
  121. package/dist/framework/entity-search.d.ts +29 -0
  122. package/dist/framework/entity-search.js +117 -0
  123. package/dist/framework/inline-sources.d.ts +49 -0
  124. package/dist/framework/inline-sources.js +388 -0
  125. package/dist/framework/layer-styles.d.ts +25 -0
  126. package/dist/framework/layer-styles.js +49 -0
  127. package/dist/framework/memo.d.ts +48 -0
  128. package/dist/framework/memo.js +84 -0
  129. package/dist/framework/overlay.d.ts +49 -0
  130. package/dist/framework/overlay.js +17 -0
  131. package/dist/framework/plan.d.ts +49 -0
  132. package/dist/framework/plan.js +73 -0
  133. package/dist/framework/projections.d.ts +480 -0
  134. package/dist/framework/projections.js +974 -0
  135. package/dist/framework/prop-surface.d.ts +132 -0
  136. package/dist/framework/prop-surface.js +278 -0
  137. package/dist/framework/ref-graph.d.ts +71 -0
  138. package/dist/framework/ref-graph.js +158 -0
  139. package/dist/framework/ref-integrity.d.ts +55 -0
  140. package/dist/framework/ref-integrity.js +171 -0
  141. package/dist/framework/registered.d.ts +95 -0
  142. package/dist/framework/registry-dir.d.ts +42 -0
  143. package/dist/framework/registry-dir.js +48 -0
  144. package/dist/framework/registry.d.ts +300 -0
  145. package/dist/framework/registry.js +104 -0
  146. package/dist/framework/rejection.d.ts +58 -0
  147. package/dist/framework/rejection.js +111 -0
  148. package/dist/framework/rename-inference.d.ts +26 -0
  149. package/dist/framework/rename-inference.js +50 -0
  150. package/dist/framework/render-spec.d.ts +296 -0
  151. package/dist/framework/render-spec.js +809 -0
  152. package/dist/framework/schema-version.d.ts +140 -0
  153. package/dist/framework/schema-version.js +214 -0
  154. package/dist/framework/schemas.d.ts +109 -0
  155. package/dist/framework/schemas.js +615 -0
  156. package/dist/framework/session.d.ts +196 -0
  157. package/dist/framework/session.js +367 -0
  158. package/dist/framework/signature.d.ts +15 -0
  159. package/dist/framework/signature.js +83 -0
  160. package/dist/framework/snapshot.d.ts +115 -0
  161. package/dist/framework/snapshot.js +277 -0
  162. package/dist/framework/source-integrity.d.ts +226 -0
  163. package/dist/framework/source-integrity.js +478 -0
  164. package/dist/framework/sources.d.ts +211 -0
  165. package/dist/framework/sources.js +89 -0
  166. package/dist/framework/utils/compiled-schema.d.ts +23 -0
  167. package/dist/framework/utils/compiled-schema.js +46 -0
  168. package/dist/framework/utils/content-key.d.ts +15 -0
  169. package/dist/framework/utils/content-key.js +33 -0
  170. package/dist/framework/utils/enumerated.d.ts +13 -0
  171. package/dist/framework/utils/enumerated.js +19 -0
  172. package/dist/framework/utils/field-path.d.ts +95 -0
  173. package/dist/framework/utils/field-path.js +136 -0
  174. package/dist/framework/utils/field-schema.d.ts +55 -0
  175. package/dist/framework/utils/field-schema.js +183 -0
  176. package/dist/framework/utils/group.d.ts +37 -0
  177. package/dist/framework/utils/group.js +13 -0
  178. package/dist/framework/utils/package-path.d.ts +37 -0
  179. package/dist/framework/utils/package-path.js +61 -0
  180. package/dist/framework/utils/refs.d.ts +194 -0
  181. package/dist/framework/utils/refs.js +403 -0
  182. package/dist/framework/validate-spec.d.ts +27 -0
  183. package/dist/framework/validate-spec.js +45 -0
  184. package/dist/framework/value-domain.d.ts +26 -0
  185. package/dist/framework/value-domain.js +202 -0
  186. package/dist/framework/views-facade.d.ts +15 -0
  187. package/dist/framework/views-facade.js +19 -0
  188. package/dist/index.d.ts +90 -42
  189. package/dist/index.js +86 -37
  190. package/dist/migrations/2.0.0/raw-css.d.ts +11 -0
  191. package/dist/migrations/2.0.0/raw-css.js +72 -0
  192. package/dist/migrations/2.0.0/v1-artifact.d.ts +1559 -0
  193. package/dist/migrations/2.0.0/v1-artifact.js +1018 -0
  194. package/dist/migrations/20260908171448_settings_as_kind.d.ts +22 -0
  195. package/dist/migrations/20260908171448_settings_as_kind.js +89 -0
  196. package/dist/migrations/20260908194245_visible_state_pointer.d.ts +19 -0
  197. package/dist/migrations/20260908194245_visible_state_pointer.js +115 -0
  198. package/dist/migrations/20260909183001_icon_knockout_variants.d.ts +18 -0
  199. package/dist/migrations/20260909183001_icon_knockout_variants.js +8 -0
  200. package/dist/migrations/20260910212453_linked_system_link_ops.d.ts +13 -0
  201. package/dist/migrations/20260910212453_linked_system_link_ops.js +8 -0
  202. package/dist/migrations/index.d.ts +2 -0
  203. package/dist/migrations/index.js +2 -0
  204. package/dist/react-native/style-keys.generated.d.ts +10 -0
  205. package/dist/react-native/style-keys.generated.js +167 -0
  206. package/dist/renderer/RendererErrorBoundary.d.ts +32 -5
  207. package/dist/renderer/RendererErrorBoundary.js +59 -10
  208. package/dist/renderer/UdsRenderer.d.ts +11 -10
  209. package/dist/renderer/UdsRenderer.js +1 -1
  210. package/dist/renderer/assetEntries.d.ts +37 -0
  211. package/dist/renderer/assetEntries.js +39 -0
  212. package/dist/renderer/assetRenderable.d.ts +14 -6
  213. package/dist/renderer/assetRenderable.js +8 -2
  214. package/dist/renderer/componentEntry.d.ts +58 -0
  215. package/dist/renderer/componentEntry.js +71 -0
  216. package/dist/renderer/icon-library.d.ts +20 -0
  217. package/dist/renderer/index.d.ts +7 -7
  218. package/dist/renderer/index.js +5 -5
  219. package/dist/renderer/primitives/SlotRenderer.d.ts +1 -1
  220. package/dist/renderer/primitives/SlotRenderer.js +1 -1
  221. package/dist/renderer/runtimeComponent.d.ts +33 -0
  222. package/dist/renderer/runtimeComponent.js +113 -0
  223. package/dist/renderer/spec-content.d.ts +43 -0
  224. package/dist/renderer/spec-content.js +95 -0
  225. package/dist/renderer/wrapRegistry.d.ts +22 -37
  226. package/dist/renderer/wrapRegistry.js +10 -20
  227. package/dist/renderer/wrappers/event-bridge.js +6 -5
  228. package/dist/renderer/wrappers/hex-normalize.js +6 -5
  229. package/dist/renderer/wrappers/html-aliases.d.ts +7 -2
  230. package/dist/renderer/wrappers/html-aliases.js +36 -19
  231. package/dist/renderer/wrappers/inline-styles.js +7 -6
  232. package/dist/spec/asset-jsx.d.ts +18 -5
  233. package/dist/spec/asset-jsx.js +27 -16
  234. package/dist/spec/collapse-text-labels.d.ts +5 -15
  235. package/dist/spec/collapse-text-labels.js +26 -19
  236. package/dist/spec/empty-node-slots.d.ts +56 -34
  237. package/dist/spec/empty-node-slots.js +87 -47
  238. package/dist/spec/index.d.ts +21 -10
  239. package/dist/spec/index.js +21 -10
  240. package/dist/spec/jsxToSpec.d.ts +14 -9
  241. package/dist/spec/jsxToSpec.js +20 -3
  242. package/dist/spec/preview-elements.d.ts +63 -0
  243. package/dist/spec/preview-elements.js +89 -0
  244. package/dist/spec/rewrite-refs.d.ts +58 -0
  245. package/dist/spec/rewrite-refs.js +250 -0
  246. package/dist/spec/specToJsx.js +18 -29
  247. package/dist/tsconfig.tsbuildinfo +1 -1
  248. package/package.json +39 -52
  249. package/dist/AssetGroup.d.ts +0 -77
  250. package/dist/AssetGroup.js +0 -125
  251. package/dist/Component.d.ts +0 -333
  252. package/dist/Component.js +0 -1061
  253. package/dist/ComponentGroup.d.ts +0 -22
  254. package/dist/ComponentGroup.js +0 -51
  255. package/dist/CompositeStyle.d.ts +0 -30
  256. package/dist/CompositeStyle.js +0 -59
  257. package/dist/Config.d.ts +0 -528
  258. package/dist/Config.js +0 -1712
  259. package/dist/Mode.d.ts +0 -41
  260. package/dist/Mode.js +0 -81
  261. package/dist/Modifier.d.ts +0 -51
  262. package/dist/Modifier.js +0 -97
  263. package/dist/MotionDef.d.ts +0 -81
  264. package/dist/MotionDef.js +0 -212
  265. package/dist/Props.d.ts +0 -332
  266. package/dist/Props.js +0 -35
  267. package/dist/Provider.d.ts +0 -20
  268. package/dist/Provider.js +0 -14
  269. package/dist/StyleProp.d.ts +0 -145
  270. package/dist/StyleProp.js +0 -239
  271. package/dist/Token.d.ts +0 -76
  272. package/dist/Token.js +0 -133
  273. package/dist/TokenGroup.d.ts +0 -33
  274. package/dist/TokenGroup.js +0 -69
  275. package/dist/asset-kind.d.ts +0 -55
  276. package/dist/asset-kind.js +0 -29
  277. package/dist/asset-value.d.ts +0 -23
  278. package/dist/asset-value.js +0 -40
  279. package/dist/brands.d.ts +0 -30
  280. package/dist/brands.js +0 -20
  281. package/dist/captureCallerPath.d.ts +0 -48
  282. package/dist/captureCallerPath.js +0 -95
  283. package/dist/colorExpressions.d.ts +0 -131
  284. package/dist/colorExpressions.js +0 -148
  285. package/dist/component-referrers.d.ts +0 -30
  286. package/dist/component-referrers.js +0 -40
  287. package/dist/config-diagnostics.d.ts +0 -21
  288. package/dist/config-diagnostics.js +0 -12
  289. package/dist/defineAssetGroup.d.ts +0 -200
  290. package/dist/defineAssetGroup.js +0 -323
  291. package/dist/defineProvider.d.ts +0 -29
  292. package/dist/defineProvider.js +0 -60
  293. package/dist/element-marker.d.ts +0 -63
  294. package/dist/element-marker.js +0 -113
  295. package/dist/entity-utils.d.ts +0 -56
  296. package/dist/entity-utils.js +0 -105
  297. package/dist/extension.d.ts +0 -55
  298. package/dist/extension.js +0 -214
  299. package/dist/factories.d.ts +0 -863
  300. package/dist/factories.js +0 -475
  301. package/dist/font-face.d.ts +0 -25
  302. package/dist/font-face.js +0 -72
  303. package/dist/foreign-component-name.d.ts +0 -21
  304. package/dist/foreign-component-name.js +0 -42
  305. package/dist/interpolate.d.ts +0 -20
  306. package/dist/interpolate.js +0 -10
  307. package/dist/jsx/__fixtures__/cross-component-preview.d.ts +0 -3
  308. package/dist/jsx/__fixtures__/cross-component-preview.js +0 -15
  309. package/dist/jsx/jsx-dev-runtime.d.ts +0 -15
  310. package/dist/jsx/jsx-dev-runtime.js +0 -11
  311. package/dist/jsx/jsx-runtime.d.ts +0 -48
  312. package/dist/jsx/jsx-runtime.js +0 -305
  313. package/dist/linked-system-pins.d.ts +0 -30
  314. package/dist/linked-system-pins.js +0 -45
  315. package/dist/linkedNodePrefixes.d.ts +0 -73
  316. package/dist/linkedNodePrefixes.js +0 -99
  317. package/dist/markers.d.ts +0 -235
  318. package/dist/markers.js +0 -70
  319. package/dist/motion-constants.d.ts +0 -37
  320. package/dist/motion-constants.js +0 -61
  321. package/dist/native/NativeConfig.d.ts +0 -56
  322. package/dist/native/NativeConfig.js +0 -162
  323. package/dist/native/assets.d.ts +0 -20
  324. package/dist/native/assets.js +0 -17
  325. package/dist/native/components.d.ts +0 -139
  326. package/dist/native/components.js +0 -67
  327. package/dist/native/index.d.ts +0 -18
  328. package/dist/native/index.js +0 -17
  329. package/dist/native/modes.d.ts +0 -10
  330. package/dist/native/modes.js +0 -11
  331. package/dist/native/types.d.ts +0 -95
  332. package/dist/native/types.js +0 -0
  333. package/dist/native/validation.d.ts +0 -8
  334. package/dist/native/validation.js +0 -885
  335. package/dist/native/values.d.ts +0 -7
  336. package/dist/native/values.js +0 -15
  337. package/dist/native.d.ts +0 -12
  338. package/dist/native.js +0 -10
  339. package/dist/refs.d.ts +0 -204
  340. package/dist/refs.js +0 -129
  341. package/dist/registry-aliases.d.ts +0 -33
  342. package/dist/registry-aliases.js +0 -35
  343. package/dist/registry-dir.d.ts +0 -22
  344. package/dist/registry-dir.js +0 -10
  345. package/dist/renderer/makeRegistry.d.ts +0 -34
  346. package/dist/renderer/makeRegistry.js +0 -52
  347. package/dist/renderer/makeUdsRenderer.d.ts +0 -13
  348. package/dist/renderer/makeUdsRenderer.js +0 -51
  349. package/dist/renderer/wrappers/component-slots.d.ts +0 -41
  350. package/dist/renderer/wrappers/component-slots.js +0 -66
  351. package/dist/renderer/wrappers/slot-resolution.d.ts +0 -25
  352. package/dist/renderer/wrappers/slot-resolution.js +0 -68
  353. package/dist/renderer/wrappers/void-elements.d.ts +0 -37
  354. package/dist/renderer/wrappers/void-elements.js +0 -40
  355. package/dist/spec/layer-props.d.ts +0 -52
  356. package/dist/spec/layer-props.js +0 -149
  357. package/dist/spec/preview-controls.d.ts +0 -44
  358. package/dist/spec/preview-controls.js +0 -139
  359. package/dist/spec/slot-refs.d.ts +0 -39
  360. package/dist/spec/slot-refs.js +0 -56
  361. package/dist/token-override-rows.d.ts +0 -68
  362. package/dist/token-override-rows.js +0 -233
  363. package/dist/tokenValueType.d.ts +0 -34
  364. package/dist/tokenValueType.js +0 -138
  365. package/dist/types/css-properties.d.ts +0 -233
  366. package/dist/types/css-properties.js +0 -14
  367. package/dist/types/css-property-keywords.d.ts +0 -156
  368. package/dist/types/css-property-keywords.js +0 -616
  369. package/dist/types/css-values.d.ts +0 -63
  370. package/dist/types/css-values.js +0 -16
  371. package/dist/types.d.ts +0 -1138
  372. package/dist/types.js +0 -12
  373. package/dist/units.d.ts +0 -14
  374. package/dist/units.js +0 -16
  375. package/dist/utils/index.d.ts +0 -4
  376. package/dist/utils/index.js +0 -4
@@ -0,0 +1,2472 @@
1
+ import { CopyPlan } from "../entities/system/copy-plan.js";
2
+ import { ConfigEdit, ConfigOp } from "./config-op.js";
3
+ import { RebaseResult, StampedPatch } from "./overlay.js";
4
+ import { DeletePlan, Plan, PlanOp, RenamePlan } from "./plan.js";
5
+ import { Entity } from "./Entity.js";
6
+ import { Ref } from "./utils/refs.js";
7
+ import { RefGraph, TraverseOptions } from "./ref-graph.js";
8
+ import { FieldsSchema } from "./utils/field-schema.js";
9
+ import { SubEntityClass } from "./defineSubEntity.js";
10
+ import { LocalOverlay, SourceAnswer, SourceOverlay, SourceResolver, SourceState } from "./sources.js";
11
+ import { AuthoredEntry } from "./utils/group.js";
12
+ import { EntityClass } from "./defineEntity.js";
13
+ import { BreakPlan, LinkPlan, SourceRowState, UnlinkPlan } from "../entities/system/link-plan.js";
14
+ import { InlineOptions } from "./inline-sources.js";
15
+ import { Snapshot } from "./snapshot.js";
16
+ import { EntityKind } from "./registry.js";
17
+
18
+ //#region src/framework/Config.d.ts
19
+ /**
20
+ * One source this config recorded — the closure it reaches through a link, as an ordinary artifact.
21
+ *
22
+ * Recorded because only a build ever has a source attached, and every reader afterwards wanted the
23
+ * twelve entities a system uses rather than the four hundred it can see. Stored as a config rather
24
+ * than as a bag of values so nothing about reading it is special: entity bodies validate against their
25
+ * own kinds' schemas, group nodes and settings ride along, and `sourceFor` hands back something the
26
+ * ordinary chase already knows how to walk.
27
+ */
28
+ interface RecordedSource {
29
+ /**
30
+ * What the source resolved to when this was recorded — concrete, and an immutable snapshot. Absent
31
+ * when nothing resolved it: a config assembled by `registerSources` rather than loaded has attached
32
+ * sources and no answer about where they came from, which is the same third state
33
+ * {@link Config.sources} reports.
34
+ *
35
+ * `unknown`, because the shape is the source kind's. It is written straight from the `attached`
36
+ * state's `resolved`, already validated against that kind's own `sourceResolution.resolved` schema at
37
+ * the resolver seam — so a reader that knows the kind reads it as that kind's type
38
+ * (`ResolvedSource` for a linked system) and nothing here restates it. Naming
39
+ * `{ systemId, version }` was the framework naming a kind, and a repo-local source could not fill it
40
+ * anyway: identity on one is its `configPath`.
41
+ */
42
+ readonly resolved?: unknown;
43
+ /** The reached closure. Recursive by nature: a source is a config. */
44
+ readonly config: SerializedConfig;
45
+ }
46
+ /**
47
+ * A config's wire form.
48
+ *
49
+ * Declared rather than inferred off `toJSON`. Inference is the nicer shape — a field added to the
50
+ * writer is in the type for free — and it is not available here: the wire form contains itself
51
+ * ({@link RecordedSource} holds a `SerializedConfig`), so reading the type off a writer that
52
+ * references the type is circular and TypeScript answers `any`.
53
+ *
54
+ * Most of the guarantee the inference bought is kept by annotating `toJSON` with this type: a required
55
+ * field declared here and not emitted is a compile error, and a field added to the literal outside a
56
+ * spread is an excess-property error.
57
+ *
58
+ * What is genuinely weaker: an optional field added as a conditional spread
59
+ * (`...(cond ? { k } : {})`) is not excess-checked, so it can be emitted without being declared here
60
+ * and nothing complains. Every optional field below arrives that way. There is no type-level fix that
61
+ * keeps the recursion, so this is the cost of the wire form containing itself — when adding an
62
+ * optional field to `toJSON`, add it here too.
63
+ */
64
+ /**
65
+ * The version of {@link SerializedConfig} this build writes and reads — an alias for
66
+ * `CURRENT_SCHEMA_VERSION` (`schema-version.ts`), kept under the name the wire-form constructors
67
+ * across the repo already spell. The version is a mint timestamp and moves with every schema change;
68
+ * an artifact written under an older one comes up through the registered migration chain on
69
+ * hydrate, and one written under a newer one is refused with the remedy named.
70
+ *
71
+ * An artifact with no version at all is the corpus written before versioning existed — version 1.
72
+ * The dense-counter `2` a short-lived scheme stamped before the chain existed reads as the mint
73
+ * that replaced it (see `detectedWireVersion`).
74
+ */
75
+ declare const SERIALIZED_CONFIG_VERSION = 20260910212453;
76
+ interface SerializedConfig {
77
+ /** See {@link SERIALIZED_CONFIG_VERSION}. Always written; a stored artifact may lack it. */
78
+ readonly version: number;
79
+ /** The config's namespace name — preserved so a round-tripped config keeps its tool prefix. */
80
+ readonly name?: string;
81
+ /** The kinds this config owns — preserved so a kind registered without items (an AI sandbox that
82
+ * may create the first one) survives the round-trip and still exposes its ops. */
83
+ readonly ownedKinds: string[];
84
+ readonly items: Record<string, Record<string, unknown>>;
85
+ readonly groups: Record<string, Record<string, unknown>>;
86
+ /** Every source this config reaches into, by slug — see {@link RecordedSource}. Absent when
87
+ * nothing is borrowed. */
88
+ readonly sources?: Record<string, RecordedSource>;
89
+ /** Self-sourced derived kinds, re-attached (source = the loaded config) on `fromJSON`. An
90
+ * externally-sourced one re-attaches via `rederiveFrom`, not through the wire. */
91
+ readonly derivedKinds?: string[];
92
+ /** Sparse per-member overrides of a derived kind's fields. The base always re-derives. */
93
+ readonly overrides?: Record<string, Record<string, Record<string, unknown>>>;
94
+ }
95
+ /**
96
+ * A stored artifact as read, before this build has checked its version: written under some version or
97
+ * none, and possibly carrying the `options` slot a pre-version artifact kept its config type's settings
98
+ * in. What `hydrateFrom` takes in and what a migration's `up` reads and answers.
99
+ */
100
+ type StoredConfig = Omit<SerializedConfig, 'version' | 'sources'> & {
101
+ readonly version?: number;
102
+ readonly options?: unknown; /** The recorded closures, each an artifact of the same age as the one holding it. */
103
+ readonly sources?: Record<string, {
104
+ readonly resolved?: unknown;
105
+ readonly config: StoredConfig;
106
+ }>;
107
+ };
108
+ /** A CRUD mutation — the patch shape the pipeline speaks. `data` is validated against the
109
+ * kind's schema-derived create/update shape. */
110
+ /** An op a tolerant batch left out: where it sat in the batch, and the refusal it got. */
111
+ interface SkippedOp {
112
+ readonly opIndex: number;
113
+ readonly message: string;
114
+ }
115
+ type Patch = {
116
+ kind: string;
117
+ operation: 'create';
118
+ path: string;
119
+ data: unknown;
120
+ }
121
+ /**
122
+ * A partial over the item body, addressed by field path — `{ 'layers.root.bg': 'hover' }`. The value
123
+ * replaces whatever the key names and `null` removes it, so one verb writes at every depth
124
+ * ({@link applyPathDelta}).
125
+ *
126
+ * Depth is the caller's to state, which is what makes this one op rather than two. It also composes:
127
+ * two entries against one target apply in order rather than clobbering, so a batch needs no grouping
128
+ * by target and no caller does read-merge-write to set a nested value.
129
+ */
130
+ | {
131
+ kind: string;
132
+ operation: 'update';
133
+ path: string;
134
+ data: unknown;
135
+ }
136
+ /**
137
+ * Replace an occupied path's whole stored body — the write a partial can't express.
138
+ *
139
+ * `update` is a merge, and on a borrowed item it merges into the envelope by design: `{ value: … }`
140
+ * over `Token.ref('x@ds').extend({ … })` records a local override, which is what makes an extension
141
+ * useful and why `update` can never remove one. `create` refuses an occupied path, and
142
+ * `delete`-then-`create` is refused by any referrer and drops the item to the end of its collection,
143
+ * because order is key order.
144
+ *
145
+ * So dissolving a borrow into a body of this config's own has no other spelling. Writing the snapshot
146
+ * directly produces no patch, which is invisible to replay: an undo or a rebase re-applies the
147
+ * flattening `update` onto the envelope it was meant to remove, puts the value back inside `extend`,
148
+ * then refuses to drop the pin because the extension still references it. Both directions of the
149
+ * borrow boundary — a `copy` landing on a pointer row, and a pointer written over a local body — are
150
+ * ordinary recorded edits through this verb.
151
+ *
152
+ * It writes in place, so the item keeps its position. `data` is a complete body, the same shape
153
+ * `create` takes, including the two shorthands: a bare ref lands in the kind's primary field, and an
154
+ * `{ __ref, extend }` body is stored as an extension.
155
+ */
156
+ | {
157
+ kind: string;
158
+ operation: 'replace';
159
+ path: string;
160
+ data: unknown;
161
+ } | {
162
+ kind: string;
163
+ operation: 'delete';
164
+ path: string;
165
+ } | {
166
+ kind: string;
167
+ operation: 'rename';
168
+ path: string;
169
+ to: string;
170
+ }
171
+ /** A group node's own body (`path` = the group prefix) — its kind's `groupFields` plus the
172
+ * universal label/description. Separate from item CRUD because a group isn't an item: it lives in
173
+ * its own store, and a folder can be rendered with no node behind it. */
174
+ | {
175
+ kind: string;
176
+ operation: 'group-update';
177
+ path: string;
178
+ data: unknown;
179
+ }
180
+ /**
181
+ * Move a whole group — its stored body and every member whose path extends it.
182
+ *
183
+ * Its own operation rather than a fan-out of member renames, because a group is two things at once:
184
+ * membership is emergent from paths, but the body (label, icon) is stored under the group path. A
185
+ * caller renaming the members would move half of it, orphaning the body under the old name and
186
+ * leaving the new name unlabelled. It is also one patch — one draft row, one undo step, one line in
187
+ * the changes panel — where the fan-out was one per member.
188
+ */
189
+ | {
190
+ kind: string;
191
+ operation: 'group-rename';
192
+ path: string;
193
+ to: string;
194
+ } /** Delete a group: its body and its members. Nothing is left for a group to be derived from. */ | {
195
+ kind: string;
196
+ operation: 'group-delete';
197
+ path: string;
198
+ }
199
+ /**
200
+ * Rearrange a kind's items — and, separately below, its group nodes.
201
+ *
202
+ * Order is key order — the order of the authored object literal, of the serialized artifact, and of
203
+ * the emitted stylesheet — so this rewrites that rather than writing a rank or an index anywhere. An
204
+ * authored config therefore says nothing about ordering; it just has its keys in an order.
205
+ *
206
+ * `order` is the full intended sequence rather than a relative move, so replay never depends on a
207
+ * neighbour still existing.
208
+ *
209
+ * Two operations rather than one carrying `target: 'item' | 'group'`, for the same reason a sub-op
210
+ * spells its collection (`sub-create/layers`): what is being ordered is part of which operation this
211
+ * is, not an argument to a shared one. Every other group operation is already its own verb
212
+ * (`group-update`, `group-rename`, `group-delete`), ordering was the one that wasn't, and the cost
213
+ * showed up downstream — one op can't be both `scope: 'collection'` and `scope: 'group'`, so its
214
+ * derived tool advertised a single overloaded call where every other group edit has its own.
215
+ */
216
+ | {
217
+ kind: string;
218
+ operation: 'reorder';
219
+ order: readonly string[];
220
+ } /** Rearrange a kind's group nodes — the folders, not the items inside them. */ | {
221
+ kind: string;
222
+ operation: 'group-reorder';
223
+ order: readonly string[];
224
+ } | SubPatch;
225
+ /**
226
+ * A mutation on a member inside an item's keyed collection field (a component's `layers`/`props`) —
227
+ * `field` names the collection, `key` the member.
228
+ *
229
+ * A nested collection is addressed by the same two plus `owner`: `field` is the declared path
230
+ * (`props/value`, a variant prop's values) and `owner` is the member of the outer collection it
231
+ * sits in (`variant`). The field stays the declaration rather than absorbing the owner key, so the
232
+ * verb it produces (`sub-create/props/value`) is the same string the op catalog declares.
233
+ */
234
+ type SubPatch = {
235
+ kind: string;
236
+ operation: 'sub-create';
237
+ path: string;
238
+ field: string;
239
+ owner?: string; /** Left out on a collection that derives its members' keys. */
240
+ key?: string;
241
+ data: unknown;
242
+ }
243
+ /**
244
+ * Write one member's whole value, whether or not it is already there.
245
+ *
246
+ * Deliberately not `sub-create` relaxed into an upsert. A create's `ALREADY_EXISTS` refusal is
247
+ * load-bearing: the draft is a replayed list, so a create landing on a base that already holds the
248
+ * member is a collision someone has to be told about, and an "add" tool that silently clobbered a
249
+ * member a collaborator just added would make that invisible. Those are two different intents, so
250
+ * they are two operations — `sub-create` still means "this is new", and a surface that only knows
251
+ * what the member should be says so instead of reading the collection first to find out which
252
+ * verb it is allowed to use.
253
+ */
254
+ | {
255
+ kind: string;
256
+ operation: 'sub-upsert';
257
+ path: string;
258
+ field: string;
259
+ owner?: string; /** Left out on a collection that derives its members' keys — an override's, a style rule's. */
260
+ key?: string;
261
+ data: unknown;
262
+ }
263
+ /**
264
+ * A partial over one member, addressed by field path — `{ 'layers.root.bg': 'hover' }` changes one
265
+ * leaf of a style rule's bag and leaves every sibling alone, where `sub-upsert` would replace the
266
+ * member whole. `null` at an address removes what is there.
267
+ *
268
+ * **Upserting on purpose**: a missing member is written from `{}` rather than refused. Two reasons,
269
+ * and they point the same way. A derived key (`defineSubEntity({ key })`) is a function of the
270
+ * content, so "the rule at this condition" names the same thing whether or not it is stored yet —
271
+ * refusing would mean a component could only be styled where it already was. And a member whose key
272
+ * is the caller's may still be a part the config only projects until someone edits it: a node inside
273
+ * an inserted instance has no stored anatomy entry until its first prop is written, and that write is
274
+ * what stores it. `sub-create` stays the strict form for a caller that means "this must be new".
275
+ *
276
+ * The result is validated against the field's create schema, never the delta against a derived
277
+ * partial — so `null` never reaches a stored value type, per-owner strictness still applies, and
278
+ * every declared coercion and `.default()` still runs.
279
+ */
280
+ | {
281
+ kind: string;
282
+ operation: 'sub-update';
283
+ path: string;
284
+ field: string;
285
+ owner?: string;
286
+ key: string;
287
+ data: unknown;
288
+ } | {
289
+ kind: string;
290
+ operation: 'sub-delete';
291
+ path: string;
292
+ field: string;
293
+ owner?: string;
294
+ key: string;
295
+ } | {
296
+ kind: string;
297
+ operation: 'sub-rename';
298
+ path: string;
299
+ field: string;
300
+ owner?: string;
301
+ key: string;
302
+ to: string;
303
+ } | {
304
+ kind: string;
305
+ operation: 'sub-reorder';
306
+ path: string;
307
+ field: string;
308
+ owner?: string;
309
+ order: string[];
310
+ };
311
+ /** A node in a kind's folder/file tree — a `folder` (an emergent group prefix, with its
312
+ * optional metadata) or an `item` (a leaf entity). */
313
+ interface TreeNode {
314
+ name: string;
315
+ path: string;
316
+ type: 'folder' | 'item';
317
+ meta?: Record<string, unknown>;
318
+ item?: Entity;
319
+ children: TreeNode[];
320
+ }
321
+ /**
322
+ * Somewhere a current config can be read from — what a link points at.
323
+ *
324
+ * Two immutable values can't be "live" with respect to each other: once a link captures a `Config`,
325
+ * that config never changes again, and `sys = sys.apply(…)` produces a value the link has never
326
+ * heard of. So a link stores this instead, and reads resolve through it every time.
327
+ *
328
+ * `ConfigSession` is the real implementation — a mutable handle whose `config` advances as edits
329
+ * land. A plain config supplies {@link Config.liveSource}, which resolves to itself: correct for the
330
+ * build-time case, where the source is authored once and never edited.
331
+ */
332
+ interface LiveConfig {
333
+ readonly config: Config;
334
+ }
335
+ /**
336
+ * One source kind's loaded sources, by the slug every ref through them spells — a live `Config`, or
337
+ * the serialized form straight off the wire.
338
+ *
339
+ * Accepting the serialized form is what keeps `fromJSON` the only hydration API. A caller holding a
340
+ * payload would otherwise need somewhere to turn each source into a `Config` first, and "somewhere"
341
+ * becomes a helper, a name for the argument, and a second vocabulary sitting next to `fromJSON` — with
342
+ * every call site remembering to use it. There is nothing to remember if the option takes what the
343
+ * caller has.
344
+ */
345
+ type SourcesBySlug = Record<string, Config | LiveConfig | SerializedConfig>;
346
+ /**
347
+ * Loaded sources ready to attach, keyed by the source kind's accessor name and then by the item's
348
+ * slug — `{ linkedSystems: { yos: yahooOs } }`.
349
+ *
350
+ * The same two levels the declaration uses (`register({ linkedSystems: { yos: LinkedSystem.item(…) } })`),
351
+ * so declaring a source and handing over what it resolved to are spelled the same way. See
352
+ * {@link Config.registerSources}.
353
+ */
354
+ type AttachedSources = Readonly<Record<string, SourcesBySlug>>;
355
+ /**
356
+ * What a serialized config needs from outside itself in order to hydrate whole.
357
+ *
358
+ * `sources` attaches each source under the slug every ref through it spells, and is not required: an
359
+ * artifact whose sources are absent is a legitimate, readable config whose borrowed values simply do not
360
+ * resolve, which is what Create shows as "linked, unresolved".
361
+ *
362
+ * Attaching at hydration rather than after it is the point. `fromJSON(json)` followed by
363
+ * `.registerSources(…)` leaves a window in which every sourced ref dangles, and anything that reads in that
364
+ * window — an emitter, an integrity check, a memo that caches — gets a wrong answer that looks like data.
365
+ */
366
+ interface HydrationOptions {
367
+ /**
368
+ * The loaded sources to attach — {@link AttachedSources}, so `{ linkedSystems: { yos: … } }`.
369
+ *
370
+ * Nested under its own key rather than spread across this interface, because the accessor names are
371
+ * the config type's to choose. A `linkedSystems?:` field here would be the framework naming a kind
372
+ * (see `.claude/rules/config-framework-kind-agnostic.md`), and a config declaring `linkedPackages`
373
+ * would have no way to hydrate at all. `patches` shares this level, which is why the sources cannot
374
+ * simply be this interface.
375
+ */
376
+ readonly sources?: AttachedSources;
377
+ /**
378
+ * What those sources resolved to, by slug — the receipt beside the attachment.
379
+ *
380
+ * `sources` and this are two halves of one answer, and {@link Config.load} sets both: attaching says
381
+ * a source is readable, and the state says how that turned out and, for one that couldn't be met,
382
+ * why. A surface reads the second through {@link Config.sourceStatus}, so hydrating with sources but
383
+ * no states leaves the linked-system rail unable to tell "nobody looked" from "looked and could not".
384
+ *
385
+ * Here rather than only inside `load`, because resolving is what makes `load` async and attaching is
386
+ * not. A client handed pre-resolved answers — the editor, whose server resolved them at page load —
387
+ * has nothing to await, and going through `load` would mean an async hydrate for a synchronous fact.
388
+ *
389
+ * Keyed by slug alone, like every other source lookup: a ref spells `@ds` with no room for a
390
+ * collection. The payloads inside are the kind's own, so this names no kind.
391
+ */
392
+ readonly sourceStates?: ReadonlyMap<string, SourceState>;
393
+ /**
394
+ * The draft this snapshot already includes, recorded rather than replayed — see
395
+ * {@link Config.withResolvedDraft}.
396
+ *
397
+ * Here because a client's hydration is one step conceptually and was two in practice: the server sends
398
+ * base-plus-draft applied, so the browser must record the log without performing it, and a `fromJSON`
399
+ * that couldn't do that left every caller to remember a second call. `config.patches` empty on mount is
400
+ * not a smaller version of the truth — it is a config that cannot answer "is this new in this draft".
401
+ *
402
+ * **Pass the ID with a patch that has one.** A stored patch is already known by an id, and that id is
403
+ * what the changes panel deletes by, what `drop` takes, and what an optimistic caller staged under; a
404
+ * fresh one would name nothing on either side. So an entry may be a bare `Patch` — stamped with a new id,
405
+ * which is right for a draft assembled locally — or `{ id, patch }` when the id already exists.
406
+ *
407
+ * Its twin, {@link Config.withDraft}, stays a method: it replays, and reports which patches would not
408
+ * apply, so it answers with more than a config.
409
+ */
410
+ readonly patches?: readonly (Patch | StampedPatch)[];
411
+ }
412
+ /** How a derived kind gets its members. `source: undefined` means self, resolved at read time
413
+ * rather than captured in a closure — so a derived config rebinds for free instead of having to
414
+ * rebuild every forward. */
415
+ interface DerivedBinding {
416
+ readonly deriveMembers: (source: Config) => Record<string, Record<string, unknown>>;
417
+ /** `undefined` = self. An external source is a {@link LiveConfig} for the same reason a link is:
418
+ * a derived kind computed from another config has to track it, not a frozen copy of it. */
419
+ readonly source: LiveConfig | undefined;
420
+ }
421
+ /**
422
+ * A config's whole state, in one object — so deriving a config is a single property write and the
423
+ * clone stays O(1) however many kinds are registered.
424
+ *
425
+ * The metadata half (`entities` / `ownedKinds` / `links` / `derived`) is shared by
426
+ * reference across every config `apply` produces, and copied only by the authoring methods, which
427
+ * run once at build time.
428
+ */
429
+ /**
430
+ * What a config has written: its base and its pending list.
431
+ *
432
+ * One `Edition` value is shared by every config derived from the same edits, so two configs with the
433
+ * same `edition` differ only in what was read into them — an attached source, derived rows, an owner.
434
+ * A holder deciding whether someone else wrote compares editions; comparing configs would count every
435
+ * late read as a write.
436
+ */
437
+ interface Edition {
438
+ readonly base: Snapshot;
439
+ readonly pending: readonly StampedPatch[];
440
+ }
441
+ /**
442
+ * A judgement about CSS text the config can't make on its own: whether `value` is one the CSS
443
+ * `property` takes, against the property's real grammar. `true` and `false` are verdicts; `undefined`
444
+ * is no verdict, for a property or a value the grammar can't judge (a custom property, a `var()`).
445
+ *
446
+ * The generated CSS table answers keywords and single-class literals itself and puts to this only what
447
+ * it can't judge (a shorthand, a function). A write lane supplies one through
448
+ * {@link Config.withCssGrammar}; the package never loads a grammar itself, since it is bundled into
449
+ * the Studio client.
450
+ */
451
+ type CssGrammar = (input: {
452
+ readonly property: string;
453
+ readonly value: string;
454
+ }) => boolean | undefined;
455
+ interface ConfigState {
456
+ readonly name: string;
457
+ /** What this config type holds and how one is authored — prose the config type declares. */
458
+ readonly description?: string;
459
+ /** The grammar a write lane armed this config with — see {@link CssGrammar}. */
460
+ readonly cssGrammar?: CssGrammar;
461
+ /** What reads see: the base with every pending patch applied. */
462
+ readonly snapshot: Snapshot;
463
+ /** The last state seen from the source — what `rebase` replays the pending patches onto. */
464
+ readonly base: Snapshot;
465
+ /** Local edits the source hasn't confirmed yet. */
466
+ readonly pending: readonly StampedPatch[];
467
+ /** Shared by every config holding the same `base` and `pending` — see {@link Edition}. */
468
+ readonly edition: Edition;
469
+ /** Bumps on every derivation — the coarse cache key kept for compatibility. New code keys on
470
+ * Snapshot slice identity instead (see `memo.ts`), which doesn't over-invalidate. */
471
+ readonly generation: number;
472
+ readonly entities: ReadonlyMap<string, EntityKind>;
473
+ readonly ownedKinds: ReadonlySet<string>;
474
+ /**
475
+ * The loaded linked systems, keyed by the link's local slug — what a `@source` ref resolves
476
+ * through.
477
+ *
478
+ * Distinct from `links`, which is keyed by kind and borrows one kind wholesale (a design file's
479
+ * view of its system's components). This borrows nothing: a source sits here so refs into it can
480
+ * be followed, and using none of it is the normal case. A {@link LiveConfig} for the same reason a
481
+ * link is — a source that advances has to be seen advancing.
482
+ */
483
+ readonly sources: ReadonlyMap<string, LiveConfig>;
484
+ /**
485
+ * The resolved values of the borrowed entities this config actually reaches, keyed by the qualified ref
486
+ * that reaches them — computed as the config serializes, which is the only moment they matter.
487
+ *
488
+ * Why record what the sources could compute: a source is a whole config, and only the build ever has one
489
+ * attached. Every reader afterwards — Create painting a swatch, the server regenerating a stylesheet —
490
+ * wanted the twelve values a system uses, not the four hundred it can see, and was being handed the
491
+ * problem of fetching and materializing entire artifacts to get them. Recording them where they are
492
+ * already computed (the CSS emitter walks exactly this set) makes every later read a lookup.
493
+ *
494
+ * Sound because a pin is exact: a published `{systemId, version}` is immutable, so its values cannot
495
+ * drift, and a repo-local pin is recomputed on every local build. Stale values would need a source to
496
+ * change under a fixed pin, which is the one thing a pin prevents.
497
+ */
498
+ /**
499
+ * Sources this config recorded, by slug — the closure it reaches, each as an ordinary artifact.
500
+ *
501
+ * Distinct from {@link sources} above, which holds what is attached right now. A reader asking "can
502
+ * I read this value" wants either ({@link Config.sourceFor}); a reader asking "is a real source
503
+ * attached" wants only the first ({@link Config.liveSourceFor}), and four of them do.
504
+ *
505
+ * Carried by reference through `derive`, which is load-bearing: the reconstructed configs are
506
+ * memoized on this map's identity, and rebuilding it per `apply` would rebuild them too — throwing
507
+ * away every memo keyed on a source (`memo.ts`) on every keystroke, with nothing failing.
508
+ */
509
+ readonly recorded: ReadonlyMap<string, RecordedSource>;
510
+ /**
511
+ * What each declared source resolved to, recorded per slug by {@link Config.load} — the same
512
+ * tagged value the resolver answered with, so nothing translates between them.
513
+ *
514
+ * Absent is a third state, and a meaningful one: a config hydrated by plain `fromJSON` asked nobody,
515
+ * which is different from a resolver that looked and could not. Those two plus `attached` are the
516
+ * three cases that are all the same `undefined` without this.
517
+ *
518
+ * Carried by reference through `derive` like {@link recorded} — an edit does not change what a
519
+ * source resolved to.
520
+ */
521
+ readonly sourceStates: ReadonlyMap<string, SourceState>;
522
+ readonly derived: ReadonlyMap<string, DerivedBinding>;
523
+ /** The mutable handle that owns this config's lineage, when one does (a `ConfigSession`). A link
524
+ * taken off this config reads through it, so the window stays live as the session advances.
525
+ * `undefined` for a standalone value, which links as itself. */
526
+ readonly owner: LiveConfig | undefined;
527
+ }
528
+ /**
529
+ * Everything a config derives from its snapshot and its live linked sources, in one bucket.
530
+ *
531
+ * Reference stability for a resolved extension, a kind's list and a group's members all want the
532
+ * same key, and none of them can be keyed on the snapshot alone: an extended linked item takes its
533
+ * base from the current source, so a config that swapped one — hydrating with `{ sources }`,
534
+ * re-attaching after a republish — has the same slices and different data. `list` inlines those
535
+ * resolved entities into an array, so a slug-only key would keep handing back the pre-republish ones
536
+ * even though `resolveExtension` would now build new ones.
537
+ *
538
+ * Keyed by the current source Config identities, a live source edit invalidates naturally without
539
+ * serializing or hashing either config.
540
+ */
541
+ /** What a collection read may leave out. `retired: false` drops every entity {@link Config.retired}
542
+ * answers true for; anything else is the total list. */
543
+ type ListOptions = {
544
+ readonly retired?: boolean;
545
+ };
546
+ declare class Config {
547
+ #private;
548
+ /** All of this config's state. `protected`, not a `#private` field, so a derived config can be
549
+ * built with `Object.create` — JS private fields are installed by a constructor, and an O(1)
550
+ * clone is precisely the thing that skips the constructor. */
551
+ protected state: ConfigState;
552
+ /** A config's name is its namespace (`'system-config'`, `'design-file'`) — the segment tool names
553
+ * carry (`uds_<name>_<verb>_<kind>`) so two configs' tools are distinct. Defaults to
554
+ * `'system-config'` for a bare `new Config()`; a config type (`defineConfig({ name })`) passes its
555
+ * own. */
556
+ constructor(name?: string, description?: string);
557
+ get name(): string;
558
+ /** What this config type holds and how one is authored, when the type says. */
559
+ get description(): string | undefined;
560
+ /** The stored state this config reads through — the value the view caches key on (`memo.ts`). */
561
+ get snapshot(): Snapshot;
562
+ /** The last state seen from the source, without the local pending patches. */
563
+ get base(): Snapshot;
564
+ /** Local edits the source hasn't confirmed yet, oldest first. */
565
+ get patches(): readonly Patch[];
566
+ /** This config as A link source — what another config's `registerLinked` should point at.
567
+ * Resolves through the owning session when there is one, so the link tracks it; otherwise it
568
+ * resolves to this exact value, which is what a build-time link wants. */
569
+ get liveSource(): LiveConfig;
570
+ /** Bind this config's lineage to the handle that owns it — called by `ConfigSession`, so links
571
+ * taken off any config it produces resolve through the session rather than freezing. */
572
+ withOwner(owner: LiveConfig): this;
573
+ /** The pending edits with their ids — what a sink persists and `merge` names. */
574
+ get pending(): readonly StampedPatch[];
575
+ /**
576
+ * What this config has written, as one value shared with every config derived from the same edits.
577
+ *
578
+ * A write — `apply`, `rebase`, `withDraft`, `merge`, `drop` — produces a new edition. A read that
579
+ * arrives late — a source attaching, rows deriving, an owner binding — produces a new config over
580
+ * the same one. A holder asking "did someone else write while my edit was out" compares this.
581
+ */
582
+ get edition(): Edition;
583
+ /**
584
+ * The members of one collection that the unmerged draft created — "which of these elements are new
585
+ * in this draft?"
586
+ *
587
+ * The one class of question a snapshot cannot answer. A component's anatomy says an element is
588
+ * there, not who put it there, and an editor that routes a dropped instance to a different panel
589
+ * than a baked one has to know which it is. It is asked of the config because the config is what
590
+ * holds the draft; the alternative every surface reached for was scanning stored rows, which sees
591
+ * only what has been persisted — an edit still in flight is invisible to it, and one that has
592
+ * settled is invisible in the other direction, because the row a client stages and the rows a
593
+ * commit writes are not the same shape.
594
+ *
595
+ * Looks for the create, not for the op that produced it. A custom op decomposes into several
596
+ * patches and replay never records that one ran, so `element-insert` leaves a `sub-create` on the
597
+ * collection its element landed in and nothing that names the insert. That also means a subtree
598
+ * insert answers with every node it grafted, not just the root: each one is equally new, and a
599
+ * caller that wants only the root has a containment question to ask of the anatomy, not of the
600
+ * draft.
601
+ */
602
+ draftCreatedKeys(kind: string, path: string, field: string): ReadonlySet<string>;
603
+ /**
604
+ * This config's bucket in {@link cachesFor}, resolved once.
605
+ *
606
+ * `cachesFor` allocates a sorted `[slug, Config]` list and scans the snapshot's buckets for a match,
607
+ * and its callers include `withComputed`, which the value-domain expansion behind one CSS emit reaches
608
+ * hundreds of thousands of times. The pair it keys on — this config's snapshot and its attached
609
+ * sources — is fixed for the instance's lifetime, because every change goes through {@link derive} and
610
+ * produces a new one, so holding the answer here is a memo that can't go stale.
611
+ *
612
+ * Safe on a derived config for the same reason: `derive` builds the clone with `Object.create` and
613
+ * assigns only `state`, so an instance field is never carried across.
614
+ */
615
+ private get caches();
616
+ private buckets?;
617
+ /**
618
+ * The next config: same identity and metadata, new state. One `Object.create` plus one property
619
+ * write — no re-registration, no rehydration, and the receiver is untouched.
620
+ */
621
+ private derive;
622
+ /**
623
+ * This config over another snapshot — what a guard inside {@link computeApply} reads.
624
+ *
625
+ * `computeApply` is pure in its `snapshot` and reads metadata off `this`, and during a replay those
626
+ * are two different states: `this` is the stale local config, while the patch has to be judged against
627
+ * the base it is landing on. So a guard whose question is about stored rows — a pin's `link` field,
628
+ * a folder's pointer — must not ask `this`. The reads that answer it are `Config` methods rather than
629
+ * `Snapshot` ones, because they cross kinds and consult the entity registry, and this is the view they
630
+ * take instead.
631
+ *
632
+ * One `Object.create` (see {@link derive}), and every snapshot-keyed cache is shared with the
633
+ * receiver, so a guard pays nothing for asking the right config.
634
+ */
635
+ private at;
636
+ /** A mutable copy of the metadata half — taken by the authoring methods, which are pure but rare.
637
+ * `apply` shares the metadata by reference and never pays for this. */
638
+ private metaDraft;
639
+ /** The state a completed registration produces. Build content is confirmed by definition, so the
640
+ * base advances with it — nothing authored is ever "pending". */
641
+ private registered;
642
+ /** This config's metadata for a kind — the `EntityKind` copied off the entity class when the kind
643
+ * was registered into this instance. `undefined` for a kind this config doesn't know. The single
644
+ * accessor every internal read routes through. */
645
+ entityOf(kind: string): EntityKind | undefined;
646
+ /**
647
+ * Run one of a kind's operations — the input parsed through the op's own schema, then handed to
648
+ * its handler.
649
+ *
650
+ * The parse is the point. An op declares what it takes, and that declaration is what the AI tools
651
+ * advertise, what the docs print, and what an example is filled from — but a caller reaching
652
+ * `schemas[verb].handler` directly skipped every word of it, so a missing field arrived as
653
+ * `undefined` and a declared `.default()` never applied at all. Callers were left supplying the
654
+ * defaults themselves, which put a fact about the op (an unstated parent means `root`) in whichever
655
+ * consumer happened to need it, spelled slightly differently each time.
656
+ *
657
+ * Throws the same rejection any other refused write throws, so a bad tool call and a bad patch
658
+ * report identically.
659
+ *
660
+ * The single-op half of {@link run}, which is the door a caller uses.
661
+ */
662
+ private dispatch;
663
+ /**
664
+ * A whole-body op's input with a bare ref put in the kind's primary field, so an op takes the same
665
+ * shorthand `apply` does (`wholeBodyChange`): `Token.ref('x@ds')` is a token body at either door.
666
+ * Anything else is handed back as it came.
667
+ */
668
+ private wholeBodyShorthand;
669
+ /**
670
+ * Run an operation: one op, or a list as one changeset.
671
+ *
672
+ * One op is looked up and run, read or write alike, and typed by its verb where the framework
673
+ * declares the verb: a standard write (`create`, `update`, `rename`, `sub-update`, …) produces a
674
+ * config, and a standard read (`list`, `get`, `delete-plan`, …) produces its answer. A custom op is
675
+ * declared by a kind, which the type system cannot enumerate, so it comes back as `unknown`; a caller
676
+ * that wants the config from a custom op runs it as a one-item list.
677
+ *
678
+ * `id` on the single form names the first patch the op produces, for the same reason `apply` takes
679
+ * one — see {@link named}. A custom op applies several patches internally, and the caller cannot hand
680
+ * any of them over, so this is the only place its own id can reach them.
681
+ */
682
+ run(op: ConfigOp & {
683
+ readonly operation: Patch['operation'];
684
+ }, id?: string): this;
685
+ run(op: ConfigOp & {
686
+ readonly operation: 'list';
687
+ }): Entity[];
688
+ run(op: ConfigOp & {
689
+ readonly operation: 'get';
690
+ }): Entity | undefined;
691
+ run(op: ConfigOp & {
692
+ readonly operation: 'dependents';
693
+ }): string[];
694
+ run(op: ConfigOp & {
695
+ readonly operation: 'rename-plan';
696
+ }): RenamePlan;
697
+ run(op: ConfigOp & {
698
+ readonly operation: 'delete-plan';
699
+ }): DeletePlan;
700
+ run(op: ConfigOp & {
701
+ readonly operation: 'copy-plan';
702
+ }): Omit<CopyPlan, 'patches'>;
703
+ run(op: ConfigOp & {
704
+ readonly operation: 'link-plan';
705
+ }): Omit<LinkPlan, 'patches'>;
706
+ run(op: ConfigOp & {
707
+ readonly operation: 'unlink-plan';
708
+ }): Omit<UnlinkPlan, 'patches'>;
709
+ run(op: ConfigOp & {
710
+ readonly operation: 'break-plan';
711
+ }): Omit<BreakPlan, 'patches'>;
712
+ run(op: ConfigOp & {
713
+ readonly operation: 'rows';
714
+ }): SourceRowState[];
715
+ run(op: ConfigOp & {
716
+ readonly operation: 'group-list';
717
+ }): ReturnType<Config['groups']>;
718
+ run(op: ConfigOp & {
719
+ readonly operation: 'group-get';
720
+ }): {
721
+ path: string;
722
+ meta: Record<string, unknown> | undefined;
723
+ members: string[];
724
+ };
725
+ run(op: ConfigOp, id?: string): unknown;
726
+ run(ops: readonly ConfigEdit[], changeset?: {
727
+ id?: string;
728
+ }): this;
729
+ /**
730
+ * Several ops as one changeset.
731
+ *
732
+ * Each runs against the config the previous one produced, so a refused op refuses the call and
733
+ * nothing lands, and every patch they wrote is stamped with the call's changeset — one undo step and one
734
+ * line in a changes list for what a caller did once. An op that stamped a changeset of its own is
735
+ * folded into the call's: a changeset is flat, and the call is the gesture.
736
+ *
737
+ * An item may name the id its first patch lands under ({@link IdentifiedOp}); the rest are minted.
738
+ *
739
+ * A refusal is the op's own `ConfigRejection` with `opIndex` set to the position of the op that
740
+ * was refused, so a caller reporting on a batch can name the item without running them one by one.
741
+ */
742
+ private runBatch;
743
+ /**
744
+ * The batch {@link run} would apply, keeping every op this config takes and naming the ones it
745
+ * refuses, by position and reason. An op that depended on a refused one is refused in turn and
746
+ * named the same way. What landed shares one changeset, as a run does; nothing lands when
747
+ * everything was refused.
748
+ */
749
+ runSkippingRefused(ops: readonly ConfigEdit[], changeset?: {
750
+ id?: string;
751
+ }): {
752
+ config: Config;
753
+ skipped: readonly SkippedOp[];
754
+ };
755
+ /**
756
+ * What running `ops` would do, without doing it.
757
+ *
758
+ * Every op is config in, config out, so the ops run against this config as {@link run} would run a list of
759
+ * them, and the patches they appended are read off the result and returned with it dropped. Nothing
760
+ * is stored and nothing reaches a sink; the receiver is untouched. Refuses exactly what the ops
761
+ * refuse, since it runs them, and refuses a read, since a read writes nothing to plan.
762
+ *
763
+ * A patch list cannot show everything an op does. A rename is one patch whose cascade rewrites every
764
+ * referrer; a delete is refused by dependents; a link break resolves every borrowed ref. A kind says
765
+ * so by declaring a `<verb>-plan` read beside the op, and the plan runs that read for each op, against
766
+ * the config as it stands when the op would run, so one plan is the whole account.
767
+ */
768
+ plan(ops: PlanOp | readonly PlanOp[]): Plan;
769
+ /** This config carrying a CSS grammar for what the generated table leaves unjudged, and every config
770
+ * derived from it carries it too. `undefined` disarms. */
771
+ withCssGrammar(grammar: CssGrammar | undefined): this;
772
+ /** The grammar a write lane armed this config with, if any — see {@link CssGrammar}. */
773
+ get cssGrammar(): CssGrammar | undefined;
774
+ /**
775
+ * The pending patches from `since` onward, as one changeset — the call's, over whatever the ops that
776
+ * produced them stamped, since a changeset is flat and the call is the gesture.
777
+ *
778
+ * What {@link run} on a list ends with, and what a caller that applied a batch entry by entry (to report
779
+ * which entry failed) calls afterwards. The first patch takes `id` when given, and that id is the
780
+ * changeset's; a tail of one patch carries no changeset.
781
+ */
782
+ withChangeset({
783
+ since,
784
+ id
785
+ }: {
786
+ since: number;
787
+ id?: string;
788
+ }): this;
789
+ /**
790
+ * The patches an op produced, as one changeset.
791
+ *
792
+ * A custom op is one changeset that decomposes into several patches, and the handler mints an id for
793
+ * each — so an optimistic caller, which staged a row under an id of its own before the op ran, gets
794
+ * back a pending log naming patches it has never heard of and can never settle its row. The first
795
+ * patch takes the caller's id, exactly as passing an id to `apply` does for the single-patch case,
796
+ * and that id is also the changeset's, so what the caller staged, what undo drops and what a list groups
797
+ * under are one identifier.
798
+ *
799
+ * A single patch carries no changeset. Several carry one, and a caller whose call is the gesture
800
+ * stamps over what the ops stamped with {@link withChangeset}.
801
+ *
802
+ * Anything that isn't a config passes straight through — a read op (`info`, `api`) returns a value,
803
+ * and there is no patch to name.
804
+ */
805
+ private named;
806
+ /** The sub-entity a kind's collection field is declared with (`component`/`layers` → `Layer`), or
807
+ * `undefined` when the field isn't a collection. Takes a field path, so a nested collection
808
+ * (`props/value`) resolves too. The accessor a consumer asks for a member's labels or its own
809
+ * `list`/`get`, so nothing has to reach into `subEntities` or fall back to title-casing the key. */
810
+ subEntityOf(kind: string, field: string): SubEntityClass | undefined;
811
+ /** The human label for one item of a kind — the registered `label`, or a title-cased fallback for
812
+ * a kind this config doesn't know (e.g. a synthetic UI group). */
813
+ entityLabel(kind: string): string;
814
+ /** The human label for a collection of a kind — the registered `labelPlural`, or a naive `<Label>s`
815
+ * fallback. */
816
+ entityLabelPlural(kind: string): string;
817
+ /** Spin up a read-view facade for this config — `config.views.components()`,
818
+ * `config.views.token(path)`, `config.views.render(spec)`. */
819
+ get views(): {
820
+ token: (path: string) => string | number | undefined;
821
+ componentProps: (path: string) => Record<string, unknown>;
822
+ stylePropValues: (path: string) => string[];
823
+ styleValue: (value: unknown) => string;
824
+ styleDeclarations: (bag: Record<string, unknown>) => Record<string, string>;
825
+ cssVar: (kind: string, path: string) => string;
826
+ cssVarRef: (kind: string, path: string) => string;
827
+ className: (kind: string, path: string) => string;
828
+ };
829
+ /** Every ref in this config, indexed both ways — `config.refs.dependents(ref)`,
830
+ * `.dependencies(ref)` (each with `{ transitive }`), and `.path(from, to)` for the chain
831
+ * between two entities. Carried on the snapshot and updated per mutation for the entities that
832
+ * actually changed, so a delete-safety check or an impact panel is a lookup, not a re-scan. */
833
+ get refs(): RefGraph;
834
+ /** Bumps on every derivation — the coarse cache key a display layer memoizes against. Includes
835
+ * linked sources' versions, so a change in a linked config bumps this too. Prefer keying on
836
+ * Snapshot slice identity (`memo.ts`), which doesn't invalidate unrelated kinds. */
837
+ get version(): number;
838
+ /** The low-level registration primitive — seed a kind's metadata into a new config (from the
839
+ * Entity class's `kindDef`) and wire its membership: Derive (members computed from a source —
840
+ * self by default), link (a read-only window onto a source's items), or own (load the items in
841
+ * `record`). `protected`: authoring goes through a config type (`defineConfig`), whose typed
842
+ * `register`/`registerLinked` call this per entry — there is no public single-entity register.
843
+ *
844
+ * A value in `record` is a group node (`Token.group(...)`), a raw item (`Token.item(...)` / bare
845
+ * shorthand), or a typed authoring handle (`defineComponent` → any `Authored`, which adopts its
846
+ * path and normalizes via `toStored()`). Entries register in order, so one may reference another. */
847
+ protected registerEntity<F extends FieldsSchema, G extends FieldsSchema>(entityClass: EntityClass<F, G> | {
848
+ readonly kind: string;
849
+ readonly isDerived: true;
850
+ readonly kindDef: EntityKind;
851
+ }, record?: Record<string, AuthoredEntry<F, G>>): this;
852
+ /**
853
+ * Every item of `kind`, with its factory sub-entity members coerced — what makes an authored
854
+ * collection store what the same write through a sub-op would have stored.
855
+ *
856
+ * Without it a component authored with its `styles` inline holds a condition exactly as typed
857
+ * while one edited through `sub-create` holds the ref its schema transforms it into, and every
858
+ * reader has to accept both forever. A no-op for a kind with no factory members, which is most.
859
+ */
860
+ /**
861
+ * Re-coerce every owned kind — run after a `register` call has loaded all of its records.
862
+ *
863
+ * A member's schema is built from the config, so a value that names another kind's item can only
864
+ * bind once that item exists. `registerEntity` coerces the kind it just wrote, which makes forward
865
+ * depend on the order the keys happen to appear in one `register({ … })` literal: a component listed
866
+ * before the motion presets it defaults to saw no presets yet and stored a bare name, silently, with
867
+ * the reference missing from the graph. A second pass over everything removes the ordering from the
868
+ * answer.
869
+ *
870
+ * Idempotent, which is what makes a second pass safe: forward turns a leaf into a ref, and a ref is
871
+ * not a leaf, so re-coercing already-bound data is a no-op that allocates nothing.
872
+ */
873
+ protected coerceOwned(): this;
874
+ /**
875
+ * Refuse two source kinds claiming one slug.
876
+ *
877
+ * A ref spells `@ds` and nothing more, so a slug resolves against the config rather than against a
878
+ * collection: {@link sourceFor}, the attached sources, the recorded closures and the resolved states
879
+ * are every one of them keyed by slug alone. Two kinds declaring `ds` therefore cannot both be
880
+ * reachable — one silently wins every read, and which one depends on the order they were registered
881
+ * in.
882
+ *
883
+ * Checked rather than assumed. "The slug namespace is flat" is a property of the ref grammar, and
884
+ * nothing was making the data honour it: a config declaring `linkedSystems: { ds }` and
885
+ * `linkedPackages: { ds }` registered clean, `sourceSlugs()` answered `['ds', 'ds']`, and every read
886
+ * through `@ds` picked a winner. Unreachable while a config declares one source kind, and the first
887
+ * thing to go wrong the day it declares two — which is exactly what `sources` exists to allow.
888
+ *
889
+ * A slug equal to this config's own {@link name} is refused for the same reason: {@link configFor}
890
+ * answers a ref qualified with the name locally, so a source declared under it would shadow this
891
+ * config's own entities for every reader holding such a ref.
892
+ *
893
+ * The cross-kind check is free for a config with fewer than two source kinds, which is every config
894
+ * today.
895
+ */
896
+ private assertDistinctSourceSlugs;
897
+ private coerceKind;
898
+ /**
899
+ * Seed a kind in place — legal only from a constructor, where the object being built isn't
900
+ * observable to anyone yet, so this isn't mutation in the sense the rest of the class avoids.
901
+ * `defineConfig` uses it to install a config type's manifest without a clone per kind.
902
+ */
903
+ protected seedEntityInPlace(entityClass: {
904
+ readonly kind: string;
905
+ readonly kindDef: EntityKind;
906
+ }): void;
907
+ /** Apply one patch — the recorded unit of change, in the shape a draft stores and replays.
908
+ *
909
+ * `apply` and {@link run} are two doors on one wall. A {@link Patch} is one of the framework's own
910
+ * verbs (`create`, `update`, `rename`, `sub-update`, …) with its body already in stored shape, and
911
+ * `apply` performs exactly that one and records it. A {@link ConfigOp} is anything the catalog
912
+ * addresses — those same verbs, and custom ops such as `linked-system/copy` that decompose into
913
+ * several patches — and `run` parses its input against the op's own schema and hands it to the op's
914
+ * handler, which for a standard verb is a call to `apply`. So `apply` is what a handler and a
915
+ * replay call, and `run` is what a caller calls: a tool, an editor gesture, a commit. A caller
916
+ * reaching for `apply` directly skips the op's input parse (its defaults, its refinements) and
917
+ * cannot spell a custom op at all.
918
+ *
919
+ * `create`/`update` bodies are validated against the schema-derived shapes; `update`/`delete`
920
+ * require an existing target. Throws on an invalid body or missing target.
921
+ *
922
+ * Returns a new config; the receiver is unchanged. A caller that drops the return has applied
923
+ * nothing.
924
+ *
925
+ * `id` lets a caller name the patch it just made. A client that paints optimistically stages a row
926
+ * under an id of its own and has to settle that row when the write lands, so it needs the pending
927
+ * entry and its own staging to agree — and an id minted here would be a second source that
928
+ * silently disagrees with it. Omitted, one is minted, which is what every non-optimistic caller
929
+ * wants. */
930
+ apply(patch: Patch, id?: string): this;
931
+ /**
932
+ * Several patches as one step: each validates against the state the previous one produced, as
933
+ * {@link apply} would, and the config is derived once at the end rather than once per patch.
934
+ *
935
+ * What a handler that writes a row per entity uses. Deriving is the larger share of an apply, so
936
+ * a copy of 2,600 entities takes a third of the time it would one patch at a time, and every
937
+ * patch still lands in `pending` with its own stamp, so the sink and a replay see the same list.
938
+ *
939
+ * A patch on a source kind goes through {@link apply} on its own, since that is where a pin that
940
+ * moves retires what was held under its slug, and where the rows its declaration mints re-derive.
941
+ *
942
+ * Several patches are one gesture, so they share one changeset; a single patch carries none.
943
+ */
944
+ applyAll(patches: readonly Patch[]): this;
945
+ /**
946
+ * Replay the pending patches onto a new base — what a remote change calls.
947
+ *
948
+ * Each patch re-validates against the state the previous one produced, so a patch whose target
949
+ * the remote change removed (or whose derived member key it re-keyed) fails exactly as a fresh
950
+ * apply would. Those are dropped and reported rather than silently skipped: the local edit really
951
+ * is gone, and the surface that made it needs to be able to say so.
952
+ *
953
+ * A replayed pin patch does not re-derive rows the way {@link apply} does. A draft stored before
954
+ * pin patches re-derived carries a `delete` per minted row after its `link: null`, and those have
955
+ * to replay whole; the session derives once after the replay instead.
956
+ */
957
+ rebase(base: Snapshot): RebaseResult<this>;
958
+ /**
959
+ * One patch of a changeset onto a scratch snapshot, with the same second try a lone patch gets: a
960
+ * patch may fail because the rows it needs had not been derived yet (the pin it depends on is in
961
+ * this draft), so the replay derives against what it has built so far and goes once more.
962
+ */
963
+ private replayOne;
964
+ /**
965
+ * Attach the draft log to a snapshot that already includes it.
966
+ *
967
+ * The client's counterpart to {@link withDraft}, and deliberately not the same thing. A browser
968
+ * receives the config the server already resolved — base plus draft, applied — so replaying the
969
+ * draft over it would apply every edit twice. But `fromJSON` seeds `pending: []`, so what arrives
970
+ * is a config that cannot say which patches compose it: `config.patches` is empty on mount and
971
+ * after every true-up, and every question of the form "is this element new in this draft" has to
972
+ * be re-derived by scanning stored rows instead.
973
+ *
974
+ * So the patches are recorded, not performed. The snapshot is untouched.
975
+ *
976
+ * The consequence to know: `base` stays where it is, which for a client is the resolved state —
977
+ * so this config knows its draft but cannot rewind it. {@link rebase} and {@link merge} are
978
+ * therefore not meaningful on one built this way, and a client doesn't call them: it re-hydrates
979
+ * wholesale from the server instead.
980
+ */
981
+ withResolvedDraft(patches: readonly StampedPatch[]): this;
982
+ /**
983
+ * Drop patches the base now contains — what a merge produces.
984
+ *
985
+ * Merging a branch's draft publishes a new artifact that already includes these edits, so keeping
986
+ * them pending would apply them twice. Note this is not about persistence: a patch written to
987
+ * `draft_patches` is durable but still part of the draft, and still belongs here.
988
+ *
989
+ * Unknown ids are ignored, since a merge may be observed more than once.
990
+ */
991
+ merge(patchIds: readonly string[]): this;
992
+ /**
993
+ * Adopt a shared draft — take `patches` as the pending list and replay them onto the current base.
994
+ *
995
+ * The collaborative case. A branch's draft is one list every client can see, so a client takes it
996
+ * whole rather than reconciling it entry by entry. Replacing rather than appending is what makes
997
+ * a client's own echo harmless: its patch comes back inside a list it is already part of, so it
998
+ * is replayed exactly once.
999
+ *
1000
+ * The base does not move here — only the draft over it does. A patch the current base can no
1001
+ * longer take is dropped and reported, exactly as in `rebase`.
1002
+ */
1003
+ withDraft(patches: readonly StampedPatch[]): RebaseResult<this>;
1004
+ /**
1005
+ * One complete item body as a change — the shared half of `create` and `replace`, which differ only
1006
+ * in whether the path has to be free or has to be taken.
1007
+ *
1008
+ * Three body shapes, all of which a config file already authors, which is why they're accepted here
1009
+ * rather than only by `register`:
1010
+ *
1011
+ * • a field bag — the ordinary case, validated against the kind's create schema.
1012
+ * • a bare ref — `{ __ref: 'token:color/brand@ds' }` borrows through a source, and `primaryField`
1013
+ * is the field the kind puts it in. That is why `Token.ref(…)` reads as a token in a config file.
1014
+ * `itemChange` does the wrap, but it runs after the parse, so without this a patch would be the
1015
+ * one door refusing a shorthand every other door takes.
1016
+ * • an extension — `{ __ref, extend }`, stored as framework data rather than parsed as a body,
1017
+ * because its delta is sparse and a complete-body schema would refuse it.
1018
+ */
1019
+ private wholeBodyChange;
1020
+ /** The next snapshot for one patch, validated. Pure in `snapshot`; reads metadata off `this`. */
1021
+ private computeApply;
1022
+ /**
1023
+ * This config's reads over another snapshot, for a check that wants nothing else: a plain clone
1024
+ * with the snapshot swapped in. Unlike {@link at}, it records no parent link for the snapshot, so a
1025
+ * batch or a replay that checks every intermediate step keeps none of them alive.
1026
+ */
1027
+ private viewOf;
1028
+ /**
1029
+ * Refuse a state the kind's {@link EntityKind.invariants} reject, or one where a kind declaring
1030
+ * {@link EntityKind.uniqueLeaves} holds a leaf twice. One kind when a patch names it, every kind
1031
+ * after a registration. Never called on hydration.
1032
+ */
1033
+ private assertInvariants;
1034
+ /** One sentence per leaf that two items of `kind` hold, since a leaf has to name one item. */
1035
+ private duplicateLeaves;
1036
+ /** `patch` with a bare leaf resolved to the path it names — see {@link leafPath}. */
1037
+ private leafAddressed;
1038
+ private computeApplyPatch;
1039
+ /** Apply a mutation to a derived kind — only `update`, which merges a sparse override of the
1040
+ * `overridable` fields (the base always re-derives). Create/delete/rename don't exist. */
1041
+ private applyDerived;
1042
+ /** Sub-entity CRUD — mutate one member inside an item's keyed collection field
1043
+ * (`layers`/`props`): create/update/delete/rename a member, or reorder the collection.
1044
+ * The item re-hydrates so refs inside the member flow into the dependency graph. */
1045
+ private applySub;
1046
+ /** Which names a member's delta may address as fields — read off the collection's own member
1047
+ * schema, resolved for this owner, so a per-owner shape (a style rule's `layers`, keyed by the
1048
+ * Component's own layers) answers for the member actually being written. */
1049
+ private memberFields;
1050
+ /**
1051
+ * The key a member of `field` on `kind` is stored under when the collection derives it from the
1052
+ * member itself — an override's from its `on`. `undefined` where the caller's key stands, and for a
1053
+ * member the derivation cannot read.
1054
+ */
1055
+ memberKeyOf({
1056
+ kind,
1057
+ field,
1058
+ member
1059
+ }: {
1060
+ kind: string;
1061
+ field: string;
1062
+ member: unknown;
1063
+ }): string | undefined;
1064
+ /** A member's derived key, when its collection declares that members are identified by their
1065
+ * value (`defineSubEntity({ key })`). `undefined` = the caller's key stands. */
1066
+ private memberKey;
1067
+ /** Validate a sub-entity member body against the field's sub-op data schema (`sub-create/<field>`
1068
+ * or `sub-update/<field>` in `schemas`), returning the parsed (coerced) output. A field with no
1069
+ * derived member schema stores as-is. */
1070
+ private validateMember;
1071
+ /**
1072
+ * One member through its per-owner schema, for its coercions only — whatever doesn't fit is
1073
+ * returned exactly as authored, field by field ({@link coerceFieldwise}).
1074
+ *
1075
+ * Lenient on purpose. This runs on paths that never validated factory members at all (an authored
1076
+ * Config's inline collections, an item create), so rejecting here would turn a coercion into a new
1077
+ * gate and fail configs that load today. Validation stays where it already is: the sub-ops, which
1078
+ * refuse through {@link validateMember}.
1079
+ */
1080
+ private coerceMember;
1081
+ /**
1082
+ * Run every member of every sub-entity collection through its own member schema.
1083
+ *
1084
+ * An authored config never meets that schema otherwise: `register` stores the body as written, so
1085
+ * a component authored with its `styles` inline stored a condition exactly as typed while the same
1086
+ * rule written through `sub-create` stored the ref its schema transforms it into. Two storage
1087
+ * forms for one statement, decided by which door the write came through — and every reader
1088
+ * downstream then has to accept both forever.
1089
+ *
1090
+ * Running it here is what makes the authored path and the op path agree, which is why it covers
1091
+ * static members too and not only the per-owner factories: a variant prop's values are a keyed
1092
+ * collection whichever way they were authored, and the list an author writes is coerced by the
1093
+ * member's own schema. Members are re-keyed afterwards for the same reason `cascadeRename` does
1094
+ * it: a coercion can change a derived key.
1095
+ *
1096
+ * `written` scopes it to the fields a write actually carried. Coercion belongs to the write that
1097
+ * stores a value, and a collection the patch didn't touch was coerced by the write that did store
1098
+ * it — so an update setting one field has no reason to re-derive the per-owner schema of every
1099
+ * other collection on the item. Omitted (create, registration) means the whole body was written.
1100
+ *
1101
+ * `strict` is a whole new body — a create or a replace — which refuses a member its per-owner
1102
+ * schema refuses, exactly as the member's own sub-op would; otherwise a component created whole
1103
+ * could carry a style rule no `sub-create/styles` takes, and the first later edit of that rule,
1104
+ * which re-validates it merged, would be refused for a key the create let in. An update stays
1105
+ * lenient, as registration and hydration do ({@link coerceMember}): the build records the anatomy
1106
+ * a render actually has through `update`, and a stored body has to load so it can be fixed.
1107
+ */
1108
+ private normalizeMembers;
1109
+ /**
1110
+ * A body's refs to a kind with unique leaves, spelled by path. An author writes
1111
+ * `Modifier.ref('dark')`; the graph holds `modifier:colorMode/dark`, so one spelling is what the
1112
+ * index sees and what a rename cascade finds. A ref that already spells a path, or that reaches
1113
+ * through a source, is left alone.
1114
+ */
1115
+ private canonicalLeafRefs;
1116
+ /**
1117
+ * Every reference to `from` rewritten to name `to` — the entities at either address untouched.
1118
+ *
1119
+ * The third answer to a link collision, and the one that makes a design spec portable: a spec stores
1120
+ * paths, so a system that repoints its refs at the source's qualified address starts speaking the
1121
+ * source's vocabulary and its specs travel. Re-aliasing is the other answer — keep your path, point
1122
+ * its body at theirs — and the two are not reversible into one another for free, which is why the
1123
+ * `link` op asks rather than defaulting.
1124
+ *
1125
+ * Only the dependents the ref index names are visited, the same as a rename.
1126
+ *
1127
+ * **A name held as a key is not moved, and this refuses rather than half-moving it.** A style
1128
+ * property and a modifier appear in a styles bag as keys rather than refs, and `to` here is a
1129
+ * qualified address (`style-property:bg@ds`), which is not a thing a bag key can be. So after the
1130
+ * refs are rewritten anything still depending on `from` is depending by name, and the caller is told
1131
+ * which — a repoint that silently left those keys naming a row it had just deleted would break the
1132
+ * styles that use them with nothing to read.
1133
+ */
1134
+ repointRefs({
1135
+ from,
1136
+ to
1137
+ }: {
1138
+ from: string;
1139
+ to: string;
1140
+ }): this;
1141
+ /**
1142
+ * Rewrite every ref `from` → `to`, across items and group nodes alike.
1143
+ *
1144
+ * Only the entities the ref index says actually point at `from` are visited. The previous version
1145
+ * re-serialized every item of every kind to find the few that matched, which made a rename cost
1146
+ * the whole config; the index already knows the answer.
1147
+ */
1148
+ private cascadeRename;
1149
+ /**
1150
+ * Rename one key inside every record that is keyed by the renamed collection — a style rule's
1151
+ * `when`, which names the props it conditions on.
1152
+ *
1153
+ * The counterpart to a ref rewrite, for the one place a rename can't be expressed as one. Refs
1154
+ * carry identity in a value, where {@link rewriteRefs} can find them; a record carries it in a
1155
+ * key, where nothing generic can — so the sub-entity declares which of its fields work that way
1156
+ * (`namesMembersOf`) and this walks exactly those.
1157
+ *
1158
+ * Key order is preserved: `when`'s order feeds `canonicalWhen`, and a rebuilt record that reorders
1159
+ * would change the derived key of a rule nothing asked to move.
1160
+ */
1161
+ private rekeyRecords;
1162
+ /** Re-derive every derived member key in `def`. The key function is the single source of a
1163
+ * member's identity (`memberKey` already runs it on sub-create/sub-update), so re-running it
1164
+ * after any change to the member's data keeps key and value from drifting. Collections with
1165
+ * caller-chosen keys (layers, props) have no key function and pass through untouched. */
1166
+ private rekeyMembers;
1167
+ /** Merge a partial over a group node's body, creating the node when the folder is emergent — a
1168
+ * group exists as soon as an item path implies it, so requiring a node first would make a folder
1169
+ * the UI already renders uneditable. `null` clears an optional field, as on an item update. */
1170
+ private applyGroupUpdate;
1171
+ /**
1172
+ * A group's members — every item whose path extends the prefix.
1173
+ *
1174
+ * The separator is part of the match, so `color/` never catches `colorScheme/fg`, and a member in a
1175
+ * subgroup (`color/brand/primary`) belongs to `color` too. Getting either wrong is silent: one drags
1176
+ * an unrelated group along, the other skips half of what the user sees under the heading.
1177
+ */
1178
+ private groupMembers;
1179
+ /**
1180
+ * The declared group nodes nested under `group`, at any depth. Sub-groups are stored apart from a
1181
+ * group's items, so a group op has to move or remove them explicitly. Emergent sub-groups exist
1182
+ * because an item is named into them and follow the items by construction.
1183
+ */
1184
+ private descendantGroups;
1185
+ private applyGroupRename;
1186
+ private applyGroupDelete;
1187
+ /** A derived kind's members, memoized against the source's snapshot (recompute only on change). */
1188
+ private derivedMembers;
1189
+ /** Resolve one derived member — base ⊕ sparse override, with `computed` fields evaluated on read
1190
+ * (never stored). Returns `undefined` for a path that doesn't derive. */
1191
+ private resolveDerived;
1192
+ resolve(kind: string, path: string): Entity | undefined;
1193
+ /**
1194
+ * Whether this config holds `target`'s entity, at the path the source spells it, through `slug`.
1195
+ *
1196
+ * The narrow question, and the narrowness is the point. A row merely occupying that path is not
1197
+ * enough — a borrower with its own `primitives/Box` has a different entity that happens to share a
1198
+ * name, and reading the source's render against it would swap what the render was written for
1199
+ * without anything looking broken. This asks whether the row is a pointer at the same entity, so
1200
+ * that answering yes means the two spellings cannot disagree.
1201
+ *
1202
+ * Entity-level pointers only. A value borrow leaves the entity the borrower's own, holding what
1203
+ * theirs is worth, so it is the first case rather than this one.
1204
+ */
1205
+ private borrowsExactly;
1206
+ /**
1207
+ * The body a linked extension resolves to before this config's kind parses it — the pinned source's
1208
+ * own fields, qualified into this namespace, with the locally authored delta laid over them.
1209
+ *
1210
+ * Split out of {@link resolveExtension} so {@link canBorrow} can ask whether a borrow would parse
1211
+ * here against the same merge a resolve performs. Two merges would disagree about the one case either
1212
+ * exists for, the record-valued fields that merge a level deep, and the disagreement would surface
1213
+ * only as a borrow the picker offered and the read then refused.
1214
+ */
1215
+ private extensionBody;
1216
+ /**
1217
+ * Resolve one locally extended linked item: the pinned source body, shallowly overlaid by the fields
1218
+ * authored here, then parsed through this config's kind. Parsing on this side is what lets a React
1219
+ * Native kind transform or reject a web value rather than trusting the source kind's rules.
1220
+ *
1221
+ * `strict` says what to do when the kind refuses it, and the two callers want different things:
1222
+ *
1223
+ * `true` a write is going through this body — a sub-op editing the inherited bag, or `materialize`
1224
+ * sealing it into a local item. A body the kind refuses can't be written, so it throws and
1225
+ * names the field.
1226
+ * `false` a read. A borrow whose body this kind refuses is one this config can't show, which is the
1227
+ * same answer as a source that never resolved: nothing. It must not throw, because the row is
1228
+ * stored, so `list`, `sourceClosure` and `toJSON` all reach it on their way past, and a throw
1229
+ * from inside serialization has no caller in a position to catch it.
1230
+ *
1231
+ * {@link canBorrow} is the door that keeps such a row from being written; this is what a config
1232
+ */
1233
+ private resolveExtension;
1234
+ /**
1235
+ * Whether an entity in the catalogue of the source `slug` names can be borrowed into this config —
1236
+ * asked before the ref is written, which is the only moment anything can be done about the answer.
1237
+ *
1238
+ * Two ways it can be no, and they're different failures:
1239
+ *
1240
+ * - **This config has no such kind.** Two config types need not declare the same ones — a native
1241
+ * System declares no `motion` or `global-style` — so a source offering them is offering something
1242
+ * with nowhere to land.
1243
+ * - **The kind exists and the body doesn't fit it.** Same kind string, different value domain: a
1244
+ * Native modifier's `{ state: 'pressed' }` selector has no arm in the web `Modifier`'s union.
1245
+ * Writing that borrow leaves a row nothing here can read.
1246
+ *
1247
+ * Judged by the merge a resolve would perform ({@link extensionBody}), so what a surface offers and
1248
+ * what the read produces can't drift. A slug with nothing resolved is `ok` rather than refused: the
1249
+ * catalogue is what this judges against, and "not loaded here" isn't a verdict about the entity.
1250
+ */
1251
+ canBorrow({
1252
+ kind,
1253
+ path,
1254
+ slug,
1255
+ extend
1256
+ }: {
1257
+ kind: string;
1258
+ path: string;
1259
+ slug: string;
1260
+ /** The delta the borrow would carry, if any — a local answer is exactly how a body that would not
1261
+ * otherwise fit is brought into range, so judging without it would refuse a legal borrow. */
1262
+ extend?: Record<string, unknown>;
1263
+ }): {
1264
+ ok: true;
1265
+ } | {
1266
+ ok: false;
1267
+ error: string;
1268
+ };
1269
+ /**
1270
+ * The kinds this config could take from `slug` at all — what the source declares, narrowed to what
1271
+ * this config also declares.
1272
+ *
1273
+ * The intersection is the whole content, and it's a real question because the two sides need not
1274
+ * share a platform: a native system declares no `motion` or `global-style`, and a web source offering
1275
+ * both is offering kinds with nowhere to land. A surface enumerating the source's kinds instead would
1276
+ * send an op per kind for things this config can't hold.
1277
+ *
1278
+ * Capability only. Whether a kind is one a person should take wholesale — their pins, their editor
1279
+ * configuration, their sealed files — is a judgement about what the kind means, and belongs to the
1280
+ * surface offering the gesture.
1281
+ */
1282
+ borrowableKinds(slug: string): string[];
1283
+ /**
1284
+ * Which config answers for `kind`/`path` — this one, or the source of a linked kind.
1285
+ *
1286
+ * Provenance, resolved per item rather than per kind, and that is the whole point. A borrowed
1287
+ * Entity's own fields were written in its source's namespace: its unqualified `token:color/brand`
1288
+ * means the source's `color/brand`, and its var name carries the source's `cssPrefix`. Interpreting
1289
+ * it against the borrowing config names a custom property nothing sets, and the borrowed component
1290
+ * paints its default with nothing thrown.
1291
+ *
1292
+ * Asking per item is also what makes two links bringing the same kind unambiguous: the answer is the
1293
+ * Config that has the item, so there is no precedence to define and no first-match to depend on.
1294
+ *
1295
+ * Routing only — no entity is built. Every ref rendered into a stylesheet goes through here
1296
+ * ({@link configFor} → `renderStyleValue`), so it walks the snapshot and the declared links and
1297
+ * stops; {@link resolvedIn} is the pair for a caller that wants the item too.
1298
+ *
1299
+ * Recursive, because a source may itself link.
1300
+ */
1301
+ ownerOf(kind: string, path: string): Config | undefined;
1302
+ /**
1303
+ * The item at `kind`/`path` and the config that answered for it.
1304
+ *
1305
+ * Every read that cares where an item came from goes through here, because the two halves must not be
1306
+ * chosen separately: a caller that resolved the item here and then interpreted it against a config of
1307
+ * its own choosing gets a plausible wrong answer whenever those differ — a borrowed token carries the
1308
+ * source's `cssPrefix`, and a borrowed entity's unqualified refs name the source's vocabulary.
1309
+ *
1310
+ * {@link ownerOf} picks the config; this builds the item there. Split so the routing can be asked for
1311
+ * on its own, and so the two can never disagree about who answers.
1312
+ */
1313
+ private resolvedIn;
1314
+ /**
1315
+ * The path a bare leaf names, for a kind that declares {@link EntityKind.uniqueLeaves}. `undefined`
1316
+ * for any other kind, for a leaf nothing holds, or for a name that already carries a slash.
1317
+ */
1318
+ leafPath(kind: string, leaf: string): string | undefined;
1319
+ /**
1320
+ * Every spelling an edge to `kind:path` may carry: the path itself, and for a kind with unique
1321
+ * leaves the bare leaf, since a name-borne edge (`modifier:dark`) is minted from a bag key that
1322
+ * cannot spell the path. Read wherever the index is asked who points at an entity.
1323
+ */
1324
+ private refAliases;
1325
+ /** Who points at `kind:path`, under every spelling {@link refAliases} admits. */
1326
+ private referrersOf;
1327
+ /** The path an item read addresses. A singleton has one item, at the kind's own name, so any path
1328
+ * a ref spells is a path INTO it and the item is what resolves; {@link valueAt} reads the rest. */
1329
+ private itemPath;
1330
+ /**
1331
+ * The value a ref addresses, member path included: an item's whole body, one member of a keyed
1332
+ * collection (`component:Button#props/gap`), or a field of a singleton's one item spelled as the path
1333
+ * (`settings:css/prefix`, `settings:css`). A qualified ref reads through its source. `undefined` when
1334
+ * nothing is there.
1335
+ */
1336
+ valueAt(target: string | Ref): unknown;
1337
+ /** The item this config stores or derives at `kind`/`path`, with no routing — {@link ownerOf} has
1338
+ * already chosen who answers, so this must not delegate or the two would recurse into each other. */
1339
+ private storedEntity;
1340
+ /**
1341
+ * A stored entity, with its kind's {@link ComputedFields} evaluated against this config.
1342
+ *
1343
+ * A stored `Entity` is built when the snapshot changes, so it holds no config and can't compute
1344
+ * anything itself. The config it lives in is only known at read time, which is here.
1345
+ *
1346
+ * **Memoized, because entity reads are reference-stable and code depends on it.** `Component.get`
1347
+ * returning a fresh instance per call would put a new value in every dep array that holds one, which
1348
+ * is the same failure a derivation inside a zustand selector causes, arriving from the other
1349
+ * direction. Keyed on the snapshot rather than the config instance: a config is a value, so a cache
1350
+ * living on one would be discarded by the next `apply`, where a snapshot survives every derivation
1351
+ * that didn't change the data.
1352
+ *
1353
+ * The snapshot alone isn't the whole key, because two configs can share one and still disagree on a
1354
+ * computed — attaching a linked source derives a new config over the same data, which is what flips a
1355
+ * Token's `link` from unresolved to resolved. So it shares {@link cachesFor}'s bucket, which adds the
1356
+ * attached sources by identity. Keyed on slug names, re-pointing a slug at a newer source under the
1357
+ * same name would look like nothing changed, and a computed reading through that source would serve
1358
+ * the pre-swap answer for the rest of the session.
1359
+ *
1360
+ * A kind that declares no computeds is handed straight back, so the common path allocates nothing.
1361
+ */
1362
+ private withComputed;
1363
+ /**
1364
+ * Attach loaded sources, in the shape everything else names them in — keyed by the source kind's
1365
+ * accessor name, then by the item's slug:
1366
+ *
1367
+ * ```ts
1368
+ * Config.registerSources({ linkedSystems: { yos: yahooOs } })
1369
+ * ```
1370
+ *
1371
+ * The same two levels `register` takes (`{ linkedSystems: { yos: LinkedSystem.item(…) } }`) and the
1372
+ * same two `fromJSON(json, { sources })` takes, so one gesture — declare a source, then hand
1373
+ * over what it resolved to — reads identically at all three. A flat `{ yos }` said nothing about
1374
+ * which collection `yos` came from, which is fine while `linked-system` is the only source kind and
1375
+ * wrong the day there is a second.
1376
+ *
1377
+ * Immutable like every other authoring step: the sources ride on the derived config, and every later
1378
+ * `apply` carries them along.
1379
+ *
1380
+ * Prefer `fromJSON(json, { sources })` when hydrating: attaching after hydration leaves a window
1381
+ * in which every sourced ref dangles, and the emitters and integrity checks read exactly there.
1382
+ */
1383
+ registerSources(sources: AttachedSources): this;
1384
+ private assertSlugIsNotOwnName;
1385
+ /**
1386
+ * Every attached source, ordered by slug — the memo key for any derivation that can reach a borrowed
1387
+ * value (`memo.ts`). A source's entities are in the source's snapshot, so nothing about swapping one
1388
+ * shows up in this config's slices.
1389
+ */
1390
+ attachedSources(): readonly Config[];
1391
+ /**
1392
+ * The source behind a link slug — attached if one is, otherwise the closure this config recorded.
1393
+ *
1394
+ * What a reader asking "can I read this value" wants, and it should not have to care which it got:
1395
+ * a recorded closure is a config, so the ordinary chase walks it and a borrowed alias resolves
1396
+ * inside it exactly as it would inside the live source.
1397
+ *
1398
+ * A reader asking "is a real source attached right now" wants {@link liveSourceFor} instead, and
1399
+ * four do — the incremental CSS delta (which compares by reference), the emitted path unions (which
1400
+ * must not narrow to paths already used), the dangling-ref check (whose whole subject is the seam
1401
+ * where the other side can change without us), and the Create badges.
1402
+ */
1403
+ sourceFor(slug: string): Config | undefined;
1404
+ /** This config's own answer for a slug — attached, else the closure it recorded. No hop, which is
1405
+ * what makes it the base case {@link sourceThrough} recurses over. */
1406
+ private ownSourceFor;
1407
+ /**
1408
+ * A slug this config doesn't declare, answered by a source that does.
1409
+ *
1410
+ * It exists for a published chain two deep. Materializing keeps a ref whose target has no value to
1411
+ * collapse into — a `style-property`, a component's `file` — so a component borrowed from `mid`
1412
+ * arrives in `top` still spelling `style-property:bg@base`, where `base` is a pin only `mid` declared.
1413
+ * `top` has no way to name it, because the slug belongs to the system that wrote the ref. Answering
1414
+ * `undefined` makes the ref unresolvable, which surfaces as `Cannot inline "style-property:bg@base"`
1415
+ * and takes the whole publish down. Depth one works only because there the slug is the consumer's own.
1416
+ *
1417
+ * Read the way {@link configFor} already describes resolution: it hops configs, each answering for
1418
+ * the links it declares. This is the same hop for the source address rather than the entity.
1419
+ *
1420
+ * Local first, always. {@link sourceFor} tries {@link ownSourceFor} before reaching here, so a config
1421
+ * that declares `base` itself keeps meaning its own, and a diamond resolves through the pin its owner
1422
+ * wrote.
1423
+ *
1424
+ * Memoized per instance including the misses: a dangling sourced ref is read repeatedly, since
1425
+ * `list`, `sourceClosure` and `toJSON` all pass over it, and each miss would otherwise re-walk every
1426
+ * source.
1427
+ */
1428
+ private sourceThrough;
1429
+ private throughCache?;
1430
+ /**
1431
+ * One level of {@link sourceThrough}'s search, then the same again through whatever answered.
1432
+ *
1433
+ * `seen` guards against a walk that never terminates: a derived kind can be sourced from the config
1434
+ * that owns it, so a Config is reachable from itself. It carries configs rather than slugs, because
1435
+ * one slug legitimately names different sources at different depths.
1436
+ *
1437
+ * Keyed off the attachment maps rather than `sourceSlugs()` — a recorded closure holds the entities
1438
+ * its refs reached and no pin items at all, so asking it what it declares answers nothing while its
1439
+ * own recorded closures are right there.
1440
+ */
1441
+ private hopFor;
1442
+ /**
1443
+ * Record what each source resolved to. Immutable like every other authoring step, and carried by
1444
+ * reference through `derive` — an edit does not change what a source resolved to.
1445
+ *
1446
+ * Internal to {@link Config.load}: a state is an answer a resolver gave, so there is no legitimate
1447
+ * reason for a caller to assert one without having resolved it.
1448
+ */
1449
+ protected withSourceStates(states: ReadonlyMap<string, SourceState>): this;
1450
+ /**
1451
+ * What every resolved source resolved to, by slug.
1452
+ *
1453
+ * Empty for a config hydrated by plain `fromJSON`, which asked nobody — and that is a real third
1454
+ * answer rather than a gap. "Nothing resolved this" is not "a resolver looked and could not", and the
1455
+ * two being the same `undefined` is why one rail says a value "isn't loaded here" when it is loaded
1456
+ * and the ref is simply broken.
1457
+ *
1458
+ * Distinct from the config type's `sources` declaration, which says what it draws on; this says how
1459
+ * that turned out. Distinct again from {@link attachedSources}, which hands back the configs
1460
+ * themselves and answers nothing about the ones that failed to resolve.
1461
+ */
1462
+ sourceStates(): readonly SourceState[];
1463
+ /**
1464
+ * One source's state — the same tagged value its resolver answered with, so nothing maps between
1465
+ * what a resolver said and what a surface reads.
1466
+ *
1467
+ * By slug alone, like {@link sourceFor} and {@link liveSourceFor}, even though the state itself
1468
+ * carries which declared source it came from. A ref spells `@ds` with no room for a collection, so a
1469
+ * second address level here would be a key nothing that resolves a ref could supply — and
1470
+ * {@link assertDistinctSourceSlugs} is what makes one level sufficient rather than merely usual.
1471
+ *
1472
+ * `undefined` means nothing has resolved this slug. See {@link sources} for why that is a third
1473
+ * state and not a missing one.
1474
+ */
1475
+ sourceStatus(slug: string): SourceState | undefined;
1476
+ /**
1477
+ * The one source slug every member of a group draws through — `undefined` when they disagree, and
1478
+ * `undefined` for an empty group.
1479
+ *
1480
+ * The same rule {@link Entity.source} applies across an item's fields, applied across a group's
1481
+ * members: a group is a display convenience over member paths, not a thing that can itself be
1482
+ * borrowed, so "this group is borrowed" can only mean "all of it is". One local member makes it
1483
+ * mixed, and a mixed group answers `undefined` — its editor stays editable, because one of its rows
1484
+ * is. Members split across two sources answer `undefined` too, because naming either would label the
1485
+ * other's rows wrongly.
1486
+ *
1487
+ * Answers the slug, which is the kind-agnostic half and therefore the half that belongs here. Turning
1488
+ * a slug into the typed pin behind it is the source kind's own business (`sourceOfGroup` beside
1489
+ * `LinkedSystem`) — a `Config` method could only hand back a bare `Entity`, and the rule above would
1490
+ * then be stated once per source kind instead of once.
1491
+ */
1492
+ groupSource({
1493
+ kind,
1494
+ groupPath
1495
+ }: {
1496
+ kind: string;
1497
+ groupPath: string;
1498
+ }): string | undefined;
1499
+ /**
1500
+ * The one source every member of a group is borrowed from — `undefined` when they disagree, when any
1501
+ * member is this config's own, and for an empty group.
1502
+ *
1503
+ * {@link groupSource} applied to the other provenance question, so the agreement rule is stated once
1504
+ * for both. The pair splits the way `Entity.source` and `Entity.borrowedFrom` do: a folder whose
1505
+ * members all point at another system is worth adorning, while a folder whose members all are another
1506
+ * System's is the one where adding, renaming and reordering belong to somebody else.
1507
+ */
1508
+ groupBorrowedFrom({
1509
+ kind,
1510
+ groupPath
1511
+ }: {
1512
+ kind: string;
1513
+ groupPath: string;
1514
+ }): string | undefined;
1515
+ /** The slug a linked folder records on its own body (`ref`), or `undefined` for a folder of this
1516
+ * config's own. */
1517
+ private recordedGroupSource;
1518
+ /** The rule both group-level provenance reads follow — one dissenting or local member and there is
1519
+ * no answer. Private because the two public readers above are the questions worth asking. */
1520
+ private agreedAcrossMembers;
1521
+ /**
1522
+ * Every item this config stores for a kind, as authored — the body before resolution.
1523
+ *
1524
+ * The counterpart to {@link list}, and the right subject for anything asking what this config claims
1525
+ * rather than what it currently reads as. Resolution is lossy in both directions for that question:
1526
+ * an extension whose base cannot be found resolves to nothing and drops out of `list` entirely, while
1527
+ * one that can be found resolves to its source's fields merged in — so a resolved body carries refs
1528
+ * this config never wrote, through slugs it never declared.
1529
+ *
1530
+ * Groups are not included. A group node holds metadata, not values, and every caller here is asking
1531
+ * about the things that point somewhere.
1532
+ */
1533
+ authoredItems(kind: string): {
1534
+ path: string;
1535
+ body: Record<string, unknown>;
1536
+ }[];
1537
+ /**
1538
+ * The slug whose bulk-take declaration still covers this path — `undefined` when none does.
1539
+ *
1540
+ * Two questions, and both have to answer yes. The entity has to be a borrow, stored as a pointer into
1541
+ * a source ({@link borrowedFrom}): a declaration says what was taken from someone else and reaches
1542
+ * nothing this config authored, so gating on the kind alone would refuse you your own tokens the
1543
+ * moment you took that kind wholesale. And the source's pin has to still cover the path the pointer
1544
+ * names, which only the pin's kind can say — where it records a take, how it keys it, and which kinds
1545
+ * a whole-source take doesn't extend to are all facts about that kind
1546
+ * ({@link EntityKind.bulkAdopts}).
1547
+ *
1548
+ * Matched on the path the source spells rather than the local one, because that's what a declaration
1549
+ * names: `to` lets a borrow sit under a name of your own, and a list matched against the local name
1550
+ * would cover nothing for exactly those.
1551
+ *
1552
+ * A pointer is the only borrow shape this can see. A `scope: 'value'` borrow stores the source's ref
1553
+ * in the primary field, which is byte-for-byte what a local entity pointing at a borrowed value
1554
+ * stores, so refusing on that shape would lock a pointer we declared. See `borrowedSlug`.
1555
+ */
1556
+ /**
1557
+ * The pin whose `link` declaration covers `kind:path` and whose source has a row there, so the build
1558
+ * mints the source's row at the path on its next pass. `undefined` when no declaration covers the
1559
+ * path, or the declaring source is attached and lacks it. A source that isn't attached is taken at
1560
+ * its declaration's word.
1561
+ */
1562
+ private declaringSource;
1563
+ /** Whether the pin at `slug` declares the source's `kind:path`, read off the stored pin alone. */
1564
+ private declarationAdopts;
1565
+ private adoptingSource;
1566
+ /**
1567
+ * What the declared source at `slug` lays over one of its entities, or `undefined` where it says
1568
+ * nothing about that path. The narrow half of {@link Config.sourceDirective}, for the readers whose
1569
+ * subject is the overlay rather than whether a row is minted at all.
1570
+ */
1571
+ sourceOverlay(slug: string, kind: string, path: string): SourceOverlay | undefined;
1572
+ /**
1573
+ * The field-path delta that records `overlay` as the pin's directive for one path, or `null` when
1574
+ * there is nothing to write.
1575
+ *
1576
+ * An overlay with nothing in it is cleared rather than written: the pin refuses an empty entry, and
1577
+ * a path it says nothing about is the plain adopted row this edit has just made it again. Clearing
1578
+ * the last entry the pin holds removes `options` altogether, so the pin reads as it was authored,
1579
+ * and clearing an entry that was never there is a no-op rather than a recorded patch.
1580
+ */
1581
+ private directiveWrite;
1582
+ /**
1583
+ * Every path a declared source's declaration says something about, with the accessor resolved to the
1584
+ * kind it addresses — `kind: undefined` where this config has no kind under that accessor.
1585
+ *
1586
+ * The inverse of every other read here. Those answer for a path you already hold, so they are asked
1587
+ * while walking something that exists; this enumerates what was written, which is the only direction
1588
+ * that can see an entry aimed at a path or an accessor that is not there. Asked of the kind
1589
+ * ({@link EntityKind.bulkDirectives}), for the reason the rest are: the field is the kind's.
1590
+ */
1591
+ sourceDirectives(slug: string): {
1592
+ kind: string | undefined;
1593
+ accessor: string;
1594
+ path: string;
1595
+ }[];
1596
+ /**
1597
+ * Whether one of a declared source's paths is adopted here — covered by the pin's `link`.
1598
+ *
1599
+ * The question a spelling turns on: an adopted path is addressed bare, because the build mints a
1600
+ * row for it at the path the source spells, and everything else is addressed qualified. The two are
1601
+ * exclusive, which is what keeps one entity from having two names.
1602
+ */
1603
+ sourceStance(slug: string, kind: string, path: string): {
1604
+ adopted: boolean;
1605
+ };
1606
+ /**
1607
+ * Whether the entity at `path` — an item or a group node — is kept but no longer offered.
1608
+ *
1609
+ * An authoring question, not a resolution one. The entity is still here and still resolves, because
1610
+ * references already going through it have to keep working — so nothing that emits a *value* reads
1611
+ * this. What does: a surface that lists paths for someone to pick from, and the emitted type union,
1612
+ * which is exactly such a list.
1613
+ *
1614
+ * True when the entity's own body says `hidden`, when any folder above it does, or when the pin a
1615
+ * borrowed row came through hides its path. A folder's flag reaches every member without the members
1616
+ * being rewritten, so un-hiding the folder is one write. Asked by local path, which for an inherited
1617
+ * row is the path the source spells.
1618
+ */
1619
+ hidden(kind: string, path: string): boolean;
1620
+ /**
1621
+ * Whether the entity at `path` — an item or a group node — is withdrawn from new work.
1622
+ *
1623
+ * Everything {@link hidden} is, and then every existing use is something to flag: a value bound to a
1624
+ * deprecated token, an instance of a deprecated component, a build warning per reference. Same shape
1625
+ * as `hidden` — the body, or any folder above it — minus the pin case, since deprecation is a fact
1626
+ * about the entity rather than about a borrow. A borrowed row reads its source's flag through its
1627
+ * resolved body.
1628
+ */
1629
+ deprecated(kind: string, path: string): boolean;
1630
+ /**
1631
+ * Whether the entity at `path` is retired short of deletion — {@link hidden} or {@link deprecated}.
1632
+ * The one read a surface choosing a NEW value filters on: a picker, an autocomplete, a prompt
1633
+ * catalogue. A surface showing an EXISTING value does not ask, since a value already bound keeps
1634
+ * rendering whatever its entity's state.
1635
+ */
1636
+ retired(kind: string, path: string): boolean;
1637
+ /** {@link hidden} and {@link deprecated} share one walk: the node at the path, then each folder
1638
+ * above it, nearest first. */
1639
+ private flagged;
1640
+ /**
1641
+ * One node's own answer, with no walk: its resolved body, and for `hidden` the directive the pin lays
1642
+ * over a borrowed row or a borrowed group. A path that is both an item and a folder (a component
1643
+ * holding its parts) answers as the item; its group node has no body of its own.
1644
+ */
1645
+ private flagAt;
1646
+ /** {@link groups} keyed by path, cached beside it. */
1647
+ private groupIndex;
1648
+ /**
1649
+ * What the declared source at `slug` says about one of the source's paths: whether its `link` claims
1650
+ * it, and what it lays over the entity.
1651
+ *
1652
+ * Asked of the kind ({@link EntityKind.bulkAdopts} / {@link EntityKind.bulkOverlay}) rather than read
1653
+ * off a field here: the framework does not know the pin's vocabulary, and a second reader of the
1654
+ * same field is a second thing to keep in step.
1655
+ */
1656
+ private sourceDirective;
1657
+ /**
1658
+ * One of a source's entity bodies as it reads from here — their fields with their refs qualified
1659
+ * into this namespace, and `undefined` for a path they have nothing at.
1660
+ *
1661
+ * Qualified for the reason {@link extensionBody} qualifies: their body spells its refs the way they
1662
+ * do, locally, and a value spliced into a row of ours without that would name whatever this config
1663
+ * happens to have at the same path. The overlay merge splices exactly one thing — the entries an
1664
+ * `extend` unions onto their array.
1665
+ */
1666
+ private theirBody;
1667
+ /**
1668
+ * The source's entity at `kind:path`, as a body this config could author — what a copy stores.
1669
+ *
1670
+ * Refs into the source are qualified `@slug`, except a target this config names bare: one it
1671
+ * already borrows at the source's own path, or one `alongside` says will be here once the edit
1672
+ * lands — arriving with it, or held already. So a copied token that points at a sibling copied
1673
+ * with it points at the local copy, and one that points at something not taken keeps drawing
1674
+ * through the pin.
1675
+ *
1676
+ * `extend` is the delta a pointer at the path carried, laid over the source's body by the same rule
1677
+ * a derived row's `options` are — so copying a linked row keeps what was written over it here.
1678
+ *
1679
+ * `undefined` when nothing has resolved the slug, or the source has no such entity.
1680
+ */
1681
+ copyOf({
1682
+ slug,
1683
+ kind,
1684
+ path,
1685
+ alongside,
1686
+ extend
1687
+ }: {
1688
+ slug: string;
1689
+ kind: string;
1690
+ path: string; /** `kind:path` targets landing as this config's own in the same edit. */
1691
+ alongside?: ReadonlySet<string>;
1692
+ extend?: Record<string, unknown>;
1693
+ }): Record<string, unknown> | undefined;
1694
+ /**
1695
+ * Whether a copied row no longer matches what its source offers at the path it was copied from.
1696
+ *
1697
+ * `undefined` when the row is not a copy, or its source is not attached — there is nothing to compare
1698
+ * against, which is not the same as matching. `true` when the source has moved on since the copy, or
1699
+ * no longer has the path; also `true` when the copy was edited here, since the row itself cannot say
1700
+ * which side moved. A surface phrases it as "differs from the source" for that reason.
1701
+ */
1702
+ copyDiffers({
1703
+ kind,
1704
+ path
1705
+ }: {
1706
+ kind: string;
1707
+ path: string;
1708
+ }): boolean | undefined;
1709
+ /**
1710
+ * Whether what this config shows at `path` reads the same as what `slug` offers there — what a
1711
+ * source page asks about a row that is yours, or another pin's, before it calls the two a conflict.
1712
+ *
1713
+ * The whole of what shows, not the one body: a component reads through its style properties and
1714
+ * tokens, so every entity the source's row reaches by ref is compared on both sides too, a ref at a
1715
+ * folder by that folder's members. Taking theirs would bring those along, and a match here means
1716
+ * nothing that renders would change.
1717
+ *
1718
+ * `undefined` when nothing is held at the path, the source has no such path, or the source is not
1719
+ * attached. Compares resolved bodies, so a row minted through another pin is read as the values it
1720
+ * shows rather than as the pointer it stores. Refs are compared bare: `token:color/brand@f` and
1721
+ * `token:color/brand@ds` name one path through two pins. A copy's `copiedFrom` mark is provenance,
1722
+ * not a value, and is left out. A dependency this config doesn't hold is a difference: what shows
1723
+ * here can't read the same without it.
1724
+ */
1725
+ matchesSource({
1726
+ slug,
1727
+ kind,
1728
+ path
1729
+ }: {
1730
+ slug: string;
1731
+ kind: string;
1732
+ path: string;
1733
+ }): boolean | undefined;
1734
+ /** The source attached for a slug — `undefined` for one that was only recorded. The narrow question,
1735
+ * for the readers whose subject is the live link rather than the value behind it. */
1736
+ liveSourceFor(slug: string): Config | undefined;
1737
+ /**
1738
+ * The source an item is borrowed from — set only when this config stores it as a pointer into one,
1739
+ * and `undefined` for an item it authored, however far that item's own fields point.
1740
+ *
1741
+ * Backs the `borrowedFrom` computed the framework installs on every kind, which is how callers read
1742
+ * it (`config.resolve(kind, path)?.borrowedFrom`). A method here because the answer is in the
1743
+ * snapshot rather than in the resolved entity — resolving an extension merges its source's fields in
1744
+ * over the pointer, so by the time a computed sees `member` there is nothing left to read.
1745
+ */
1746
+ borrowedFrom(kind: string, path: string): string | undefined;
1747
+ /**
1748
+ * What this config lays over a borrowed item, beside the source's own body it lays it on —
1749
+ * `undefined` for an item this config authored.
1750
+ *
1751
+ * One answer for both ways an item is borrowed. A row the build minted from a `link` carries the
1752
+ * pin's directive folded into its `extend`, and a row extended by hand carries the delta the author
1753
+ * wrote there; either way the stored body is the pointer plus our fields. The source body is theirs
1754
+ * as it reads from here, refs qualified into this namespace, and `undefined` while the source is
1755
+ * unavailable — every field is then an extension, since nothing says otherwise.
1756
+ */
1757
+ localOverlay(kind: string, path: string): LocalOverlay | undefined;
1758
+ /**
1759
+ * One item's body as stored — the pointer still visible, nothing merged in, and `undefined` for a path
1760
+ * this config doesn't hold.
1761
+ *
1762
+ * The pair to {@link resolve}, and the difference is why both exist. `resolve` answers what the item
1763
+ * is, so an extension comes back as the source's fields under ours, which is what a renderer wants
1764
+ * and is the merge that erases the pointer. This answers what this config wrote, which is what a
1765
+ * caller deciding whether an item is a borrow, and of which shape, has to read. {@link borrowedFrom}
1766
+ * is the narrow question over the same body; this is for a caller that needs the rest of it.
1767
+ *
1768
+ * `groupMeta` is the group half. Named for the stored form rather than "raw", because the distinction
1769
+ * is about the merge and not about parsing: the body has been through the kind's schema.
1770
+ */
1771
+ storedBody(kind: string, path: string): Record<string, unknown> | undefined;
1772
+ /**
1773
+ * This config with every cross-source ref replaced by the value it points at — self-contained, so it
1774
+ * loads with no sources attached.
1775
+ *
1776
+ * What the materialize route runs before handing a published version to a consumer: their artifact may
1777
+ * draw on systems the consumer never pinned and cannot see, and resolving here (with the publisher's
1778
+ * sources) is what makes one entry answer for itself. A chained link resolves all the way to a literal,
1779
+ * and a ref that cannot resolve throws rather than leaving a hole — a partial artifact breaks builds
1780
+ * confusingly later.
1781
+ *
1782
+ * The pins stay. They are not values that inline, and a consumer's tooling still wants them for
1783
+ * attribution and upgrade detection. Breaking a link is deleting the pin, once nothing refers
1784
+ * through it.
1785
+ *
1786
+ * Local refs are untouched — the point is to remove dependence on other systems, not to flatten this
1787
+ * one into literals.
1788
+ */
1789
+ withInlinedSources(options?: InlineOptions): this;
1790
+ /** @internal Turn extensions through the selected source into ordinary complete local items.
1791
+ *
1792
+ * Used by source materialization before it walks nested refs. A component cannot
1793
+ * collapse to one scalar value the way a token ref can, so its extension is flattened as the
1794
+ * complete resolved entity instead. That makes a published B→A component extension self-contained
1795
+ * when C installs B: C receives B's component and render source, and never needs permission to A.
1796
+ *
1797
+ * `only` narrows to one item. It has to come through here rather than being done by the caller,
1798
+ * because the enumeration is over stored bodies — an extension is only visible before it resolves,
1799
+ * and `list` hands back the merge.
1800
+ *
1801
+ * Each one goes through `apply` as a `replace`. Writing the snapshot directly would produce no
1802
+ * patch, so the dissolve would be invisible to replay: an undo or a rebase would re-apply a
1803
+ * flattening `update` onto the envelope it was supposed to have removed, put the value back inside
1804
+ * `extend`, and then refuse to drop the pin because the extension still referenced it. `replace`
1805
+ * makes a dissolve an ordinary recorded edit, so it survives being replayed. */
1806
+ withMaterializedExtensions({
1807
+ slug,
1808
+ only
1809
+ }?: {
1810
+ slug?: string;
1811
+ only?: {
1812
+ kind: string;
1813
+ path: string;
1814
+ };
1815
+ }): this;
1816
+ /**
1817
+ * The config a ref resolves in — this one for a local ref or a ref qualified with this config's own
1818
+ * {@link name}, the linked source for any other qualified one.
1819
+ *
1820
+ * `undefined` means the ref names a source this config can't reach: either the link isn't declared
1821
+ * or it was declared and never loaded. That is deliberately not the same as falling back to
1822
+ * ourselves. Resolving `token:color/brand@yahoo-os` against our own `color/brand` would hand back
1823
+ * a plausible wrong value with nothing to signal it — the exact confusion between your key and
1824
+ * their key that qualified refs exist to prevent.
1825
+ *
1826
+ * The own-name case is the one exception, because it is not a fallback: a canvas attaches the one
1827
+ * system it draws from under that system's `name`, so the refs it mints
1828
+ * (`component:actions/Button@system-config`) are addressed to whichever system is attached. The
1829
+ * name is the config type's, shared by every `System`, which is why "the attached one" is all it
1830
+ * can mean. Handed to the system itself, such a ref resolves there. A source that was hydrated
1831
+ * under that slug still answers first, so an artifact written before the name was reserved keeps
1832
+ * its meaning; {@link assertDistinctSourceSlugs} refuses authoring a new one.
1833
+ */
1834
+ configFor(target: string | Ref): Config | undefined;
1835
+ /** One ref, resolved wherever it points — the source hop plus an ordinary `resolve`, so a caller
1836
+ * following a ref never splits one apart or decides which config to ask. */
1837
+ resolveRef(target: string | Ref): Entity | undefined;
1838
+ /**
1839
+ * What a person calls whatever `target` names: the resolved entity's
1840
+ * {@link Entity.displayLabel} (its authored `label`, else its leaf). A
1841
+ * `#member` reads as the member's own leaf (`gap` for `props/gap`), and a
1842
+ * name that resolves to nothing — a bare intrinsic tag, a glyph the config
1843
+ * never registered, a deleted component — as the leaf of its path. Never a
1844
+ * `kind:` marker, which no person should read.
1845
+ */
1846
+ displayLabelOf(target: string | Ref): string;
1847
+ /**
1848
+ * The `data` schema for a mutation `verb`, narrowed to one target entity — the same per-owner
1849
+ * schema `apply` validates against (a factory input like a style rule's `when`/`layers` builds
1850
+ * itself from the resolved parent), emitted as JSON Schema for a form to render. A tool's
1851
+ * advertised input stays owner-agnostic (no `path` chosen yet); this is for a form that already
1852
+ * knows its target. `undefined` when the verb carries no `data`, or the target doesn't resolve.
1853
+ */
1854
+ contextualDataSchema(kind: string, path: string, verb: string): Record<string, unknown> | undefined;
1855
+ /**
1856
+ * Validate a `data` payload against that same per-owner schema — the write-time check `apply`
1857
+ * runs, minus the mutation. `[]` = valid; otherwise `path: message` lines. Lets a preview form
1858
+ * flag exactly what `apply` would reject, before anything is sent.
1859
+ */
1860
+ validateData(kind: string, path: string, verb: string, data: unknown): string[];
1861
+ /** What a body's collection members would be refused for, as `field.key.path: message` lines —
1862
+ * the per-owner check a strict {@link normalizeMembers} throws, collected instead. */
1863
+ private memberIssues;
1864
+ /** Emergent membership: the items whose path sits under a group prefix. Never stored. Reads
1865
+ * through `list`, so a linked kind's members come from its source. */
1866
+ members(kind: string, groupPath: string): Entity[];
1867
+ /**
1868
+ * A kind's groups — the union of the two ways one can exist.
1869
+ *
1870
+ * A group's membership is emergent: `spacing/sm` puts `spacing` on this list whether or not anything
1871
+ * wrote a body for it. A group's body is stored, so a group someone just made and hasn't filled is on
1872
+ * this list too. Listing only the stored bodies hides every group nobody has labelled, including —
1873
+ * after a rename moved its members — the group they moved to.
1874
+ *
1875
+ * Every prefix level with members counts, so `spectrum/brand` is a group in its own right next to
1876
+ * `spectrum`, **unless there is an item at that path**. That exception keeps a component's parts from
1877
+ * turning their owner into a folder: `Select/Trigger` is a part of `Select` because it is named that
1878
+ * way, and `Select` is a component rather than a group containing one. A prefix is a group only when
1879
+ * nothing occupies it.
1880
+ *
1881
+ * **The stored record is the authority for order.** Bodied groups come first, in its key order, which
1882
+ * is what `reorder` rewrites, and body-less ones follow, positioned by where their first member sits
1883
+ * in the item record. So a body-less group can't be reordered until something gives it a body, which
1884
+ * is a gap rather than an intended rule.
1885
+ */
1886
+ /**
1887
+ * A group's metadata, with what the source says about the group inherited from it and any
1888
+ * directive the pin lays over this path folded in.
1889
+ *
1890
+ * The source's group node arrives whole, minus the fields the kind declares as its own
1891
+ * ({@link EntityKind.localGroupFields}). The split is what a field is ABOUT: `variants` and `sizes`
1892
+ * describe the icon library, so a consumer that borrows it needs them — `primitives/Icon` declares
1893
+ * its `variant` prop's domain as `icon:<slug>#variants`, which is read off this node, and without
1894
+ * it the ref resolves to nothing and the build refuses. `cssPrefix` describes how a config emits,
1895
+ * and a borrowed component's classes carry the consumer's prefix, so inheriting the source's would
1896
+ * name classes this stylesheet doesn't contain.
1897
+ *
1898
+ * Asked of the kind rather than named here, so a kind whose group node carries facts about the
1899
+ * group is described by this rather than flattened to the two fields every kind happens to share.
1900
+ *
1901
+ * A directive at this path — from `options`, or from `applyGroupUpdate`'s redirect off a minted
1902
+ * body — lays over what inherits, the same order an item's `extend` lays over its source fields.
1903
+ * Anything the stored body itself still sets wins over both: a hand-linked group (no `link`
1904
+ * declaration behind it) keeps writing its own body, and this is where that read wins.
1905
+ */
1906
+ private withInheritedGroupMeta;
1907
+ /** Every group node of a kind, total by default; `{ retired: false }` leaves out retired folders,
1908
+ * the same way {@link list} leaves out retired items. */
1909
+ groups(kind: string, opts?: ListOptions): {
1910
+ path: string;
1911
+ meta: Record<string, unknown>;
1912
+ }[];
1913
+ /** The total list behind {@link groups}. */
1914
+ private allGroupsOf;
1915
+ /**
1916
+ * The walk behind {@link groups}. Per call it reads every stored group's inherited meta through its
1917
+ * source and splits every item's path for emergent folders, so a consumer with borrowed groups pays
1918
+ * the source's own walk once per group — which is why the answer is cached per snapshot above.
1919
+ */
1920
+ private computeGroups;
1921
+ groupMeta(kind: string, groupPath: string): Record<string, unknown> | undefined;
1922
+ /** The kinds this config surfaces for reading — its own kinds with items, plus its derived ones.
1923
+ * The top level of a UI tree. A source's kinds are not here: they are read through a qualified
1924
+ * ref, so they belong to the config that answers for them. */
1925
+ kinds(): string[];
1926
+ /** The kinds this config derives (computed, read-only) via `defineDerivedEntity`. */
1927
+ derivedKinds(): string[];
1928
+ /** Re-attach `other`'s derived kinds onto this config — the derived twin of `relinkFrom`. A
1929
+ * self-sourced kind rebinds to this config (so a clone's members reflect the clone); an
1930
+ * externally-sourced one keeps pointing at its original source. Used after `fromJSON` on a clone. */
1931
+ rederiveFrom(other: Config): this;
1932
+ /**
1933
+ * The accessor each kind is registered under (`tokens` → the Token kind) — the one mapping a write
1934
+ * back into authored source needs, because a patch names the kind while the source names the
1935
+ * accessor.
1936
+ *
1937
+ * Read off the config type's own `entities` manifest, which `defineConfig` installs as a static.
1938
+ * Here rather than at each call site: every writer needs it, and reaching for the constructor is a
1939
+ * cast each of them would otherwise repeat.
1940
+ */
1941
+ accessors(): Record<string, {
1942
+ kind: string;
1943
+ }>;
1944
+ /** The kinds registered into this config — what it owns, whether or not they hold items yet.
1945
+ * Tool derivation (reads + mutations) scopes to these so a config only exposes its own kinds
1946
+ * (a source's kinds are read through their own config, so they derive none). */
1947
+ ownedKinds(): string[];
1948
+ /**
1949
+ * What this config reaches inside `slug`'s source, transitively — as qualified `kind:path` targets.
1950
+ *
1951
+ * Seeded two ways, and both are floors rather than filters. From the sourced refs this config
1952
+ * spells, then closed over each target's own refs inside the source, because their entity may alias
1953
+ * another of theirs. And from what the pin declares it took ({@link adoptedFrom}) — a surface
1954
+ * saying "every token" is describing entities no ref has landed on yet, and a closure that carried
1955
+ * only the reached ones would leave those rows absent from the artifact. Reachability stays the
1956
+ * floor either way, so a ref always brings its target whether or not a declaration claims it.
1957
+ *
1958
+ * Shared rather than computed per caller: the CSS emitter needs it to know what to declare, and the
1959
+ * build's validation needs the same set to know what to check — two answers to that question would
1960
+ * drift, and the drift would look like a token that emits but isn't validated.
1961
+ *
1962
+ * `kind` narrows it for a caller that emits or validates one kind, which is the caller's business
1963
+ * to name; the walk itself follows refs wherever they go, so borrowing something other than a token
1964
+ * is reached rather than silently dropped.
1965
+ *
1966
+ * Sorted, so anything built from it is deterministic.
1967
+ */
1968
+ sourceClosure(slug: string, kind?: string): string[];
1969
+ /**
1970
+ * The walk behind {@link sourceClosure}, run once per snapshot and source set.
1971
+ *
1972
+ * Memoized because it is asked repeatedly of one config and is O(every entity): the CSS emit asks
1973
+ * per kind, the artifact walk asks per slug, and the row derivation asks again — three full passes
1974
+ * over a config that is routinely megabytes, for one answer that cannot change while the snapshot
1975
+ * and its sources are fixed.
1976
+ */
1977
+ private computeSourceClosure;
1978
+ /**
1979
+ * A refusal for a pin patch whose derive pass would retire a minted row that something authored
1980
+ * here still points at. A minted row has no body of its own, so once it goes the referrer dangles;
1981
+ * copying what is used, or breaking the link with `keep`, is how the value stays.
1982
+ */
1983
+ private assertDerivedDropsUnreferenced;
1984
+ /**
1985
+ * This config with a row for every entity it inherits — the build's output. A pin patch runs this
1986
+ * inside {@link apply}; a source attaching runs it through the session.
1987
+ *
1988
+ * A link declares a source and what it took from it; everything that arrives is derived here, one
1989
+ * pointer per entity at the path the source spells it, marked ({@link minted}). So authored source
1990
+ * carries a declaration rather than a copy — linking one system into another would otherwise write
1991
+ * 2,674 rows by hand — while everything downstream still reads a stored row: `list`, the pickers, the
1992
+ * rename gate, `inlineAllSources` and the emitters are untouched, because a derived row is a stored
1993
+ * row by the time any of them run.
1994
+ *
1995
+ * The set is {@link adoptedFrom} — what the pin adopts. Not
1996
+ * {@link sourceClosure}, which is that plus whatever this config's refs happen to reach: a ref
1997
+ * already resolves qualified, so minting a bare row for it gives one entity two spellings, and which
1998
+ * one you get depends on what some unrelated file happened to reference. Adoption is a declaration,
1999
+ * and the rows follow it.
2000
+ *
2001
+ * The folders standing above a derived item come with it — a var name carries its group's
2002
+ * `cssPrefix`, so a leaf without its folder emits a custom property nothing declares.
2003
+ *
2004
+ * **A path this config already holds is left alone, silently.** Local shadows a source, whether the
2005
+ * local row is authored, borrowed by hand, or derived by an earlier pass — which is what makes this
2006
+ * idempotent and makes re-running it after a source grows additive.
2007
+ *
2008
+ * Only slugs this config pins derive rows. A slug reached through a borrowed entity names a third
2009
+ * system's namespace, which this config has no `@slug` for and no claim on.
2010
+ */
2011
+ withDerivedRows(): this;
2012
+ /**
2013
+ * Whether the snapshot already stores exactly the row a derive pass would write at this path.
2014
+ *
2015
+ * A minted row is recomputed on every pass, so the plan names every inherited entity whether or not
2016
+ * anything about it moved. Writing an unchanged row would still mint a new config, and a session
2017
+ * derives on every publish — so on a linked branch every edit, and every holder keyed on the
2018
+ * config's identity, would see a fresh value for a snapshot that says the same thing.
2019
+ */
2020
+ private holdsDerivedRow;
2021
+ /**
2022
+ * The paths two or more sources both offer and this config has not settled — `kind:path` with the
2023
+ * slugs that wanted it.
2024
+ *
2025
+ * Local shadows a source silently, and that is what makes re-deriving additive: a row you authored
2026
+ * wins and nothing is lost, because you said what you meant. Two *sources* offering one path is a
2027
+ * different question with no such answer — deciding it by pin order would make which vendor's
2028
+ * `actions/Button` you got depend on the order links happen to sit in, and nothing would look wrong.
2029
+ *
2030
+ * So neither derives, and this names them. The way out is an authored row at that path extending the
2031
+ * one you meant, which settles it as an ordinary local shadow and is reviewable in a diff.
2032
+ */
2033
+ collidingSources(): {
2034
+ kind: string;
2035
+ path: string;
2036
+ slugs: string[];
2037
+ }[];
2038
+ /**
2039
+ * The derivation made for the snapshot this one came from, when this edit could not have changed
2040
+ * it: the same sources, no change to a pin or to which paths exist, and every row that did change
2041
+ * is authored on both sides with the same source-qualified refs and the same style-bag keys —
2042
+ * which is all {@link groupRefMembers} reads off an authored body. A value edit on an authored row
2043
+ * is the common case and passes.
2044
+ *
2045
+ * A session derives on every publish, so on a linked branch every keystroke redoes the walk
2046
+ * otherwise.
2047
+ */
2048
+ private inheritedDerivation;
2049
+ /**
2050
+ * Same paths in the same order, and every row that changed is authored on both sides and reaches
2051
+ * the same sources the same way — see {@link inheritedDerivation}. Order counts because the walk
2052
+ * visits rows in stored order and mints in the order it reaches them, and key order is meaning
2053
+ * downstream.
2054
+ */
2055
+ private sameRowsForDerivation;
2056
+ /**
2057
+ * What the row derivation reads off an authored body, as one comparable string: the refs that
2058
+ * name a source, and the style-bag keys (a bag's keys name style properties a source may declare).
2059
+ */
2060
+ private derivationFacts;
2061
+ /**
2062
+ * The derivation, run once per snapshot and source set — {@link withDerivedRows} takes the changes
2063
+ * and {@link collidingSources} takes what it refused to decide.
2064
+ *
2065
+ * One walk rather than two, because the two answers come from the same pass and a second walk is a
2066
+ * second chance to disagree about which source claimed a path.
2067
+ */
2068
+ private rowDerivation;
2069
+ /**
2070
+ * The targets inside `slug` this config already RE-aliases — `kind:path` in the source's namespace,
2071
+ * under a local name of its own rather than the source's.
2072
+ *
2073
+ * Entity-level pointers only, which is the borrow that moves an entity here. A value borrow leaves
2074
+ * the entity theirs and points a row of ours at what it is worth, so their path is still free and a
2075
+ * derived row there is the ordinary inheritance rather than a duplicate.
2076
+ *
2077
+ * A row this same declaration derived is never a re-alias — {@link derivedItemChange} always points
2078
+ * a target at its own path, so excluding it here is what lets {@link rowDerivation} re-derive one
2079
+ * rather than reading its presence as somebody's chosen alias.
2080
+ *
2081
+ * Also what the emitted types qualify: `Token.ref('x@ds')` is spelled in authored source to extend
2082
+ * an entity you hold, so the qualified name is worth typing for exactly these and not for the rest
2083
+ * of a source's catalogue.
2084
+ */
2085
+ borrowedTargets(slug: string): Set<string>;
2086
+ /**
2087
+ * Everything `slug`'s pin declares this system took, as `kind:path` targets in the source's own
2088
+ * namespace — the second seed {@link sourceClosure} closes over.
2089
+ *
2090
+ * The declaration lives on the pin and only that kind knows how to read it, so this asks per
2091
+ * candidate ({@link EntityKind.bulkAdopts}) rather than interpreting the field here. Candidates are
2092
+ * what the source offers and this config could hold ({@link borrowableKinds}), which is what keeps a
2093
+ * whole-source take to design entities instead of reaching the source's own pins and sealed files.
2094
+ *
2095
+ * Empty for a pin that declares nothing, which is the ordinary case — so a config that borrowed by
2096
+ * hand enumerates no catalogue.
2097
+ *
2098
+ * Public because it is the half of {@link sourceClosure} that stands on its own: a row the pin
2099
+ * declares is there whatever this config's refs do, where a row seeded by reachability exists
2100
+ * because of the very ref asking about it. {@link redundantQualifiers} needs that distinction.
2101
+ */
2102
+ /**
2103
+ * What the rows drawn through `slug` depend on: the members of a source GROUP something here names,
2104
+ * and every entity a LINKED row points at, walked to a fixpoint.
2105
+ *
2106
+ * A linked row's dependencies land as rows of their own, so everything a link needs has a path in
2107
+ * this system, the way a copy writes every one of them. A ref this config wrote by hand at the
2108
+ * source (`Token.ref('x@ds')`) brings a folder's members but not an item: the ref already reaches
2109
+ * the value, and a row minted for it would be that value under a second spelling.
2110
+ *
2111
+ * A ref may name a folder rather than an entity: `primitives/Text` binds its `variant` prop to
2112
+ * `composite:textVariant`, and a style property's `values: [Token.ref(ramp)]` does the same. A
2113
+ * folder has no stored row to borrow, so reachability — which brings what a ref NAMES — brings
2114
+ * nothing, and a config that borrowed one component ended up with a component whose prop domain is
2115
+ * empty and whose emitted module imports a lookup table that was never emitted.
2116
+ *
2117
+ * Taking every member is what makes the two spellings one set: the members land as ordinary rows at
2118
+ * their own paths, so this config emits their rules under ITS prefix and the borrowed module's
2119
+ * import resolves against its own table. A wholesale link already has them, so this adds nothing
2120
+ * there — it is the narrow borrow, which adopts no kinds at all, that has the hole.
2121
+ *
2122
+ * Walked to a fixpoint, because a member may name a folder of its own. That is also what keeps
2123
+ * {@link withDerivedRows} idempotent: a second pass finds every member already held and plans no
2124
+ * change.
2125
+ *
2126
+ * Every guard the adopted targets pass through applies to these too — a name this config already
2127
+ * holds wins, an entry it cannot express is left behind — because
2128
+ * they join the same loop rather than being written directly.
2129
+ */
2130
+ private groupRefMembers;
2131
+ adoptedFrom(slug: string): string[];
2132
+ /**
2133
+ * One source item's identity, from the fields its own kind declares as `sourceIdentity` — what a walk
2134
+ * that must stay kind-blind keys a cache and a cycle check on.
2135
+ *
2136
+ * `undefined` when the kind declares none, or nothing is stored at that path. A declared field the
2137
+ * item does not set contributes an empty segment rather than being skipped: two items differing only
2138
+ * in which fields they set are different sources, and collapsing them would share one cache entry.
2139
+ *
2140
+ * Derived rather than spelled, which is what makes it right for kinds nobody has written — it covers
2141
+ * whatever fields a kind actually declares instead of the three `linked-system` happens to have. The
2142
+ * key it replaces was `${systemId}@${version}`, which a repo-local source cannot state at all;
2143
+ * that is the case the walk using it had to pre-skip.
2144
+ */
2145
+ sourceIdentityKey(kind: string, path: string): string | undefined;
2146
+ private sourceKey;
2147
+ /**
2148
+ * Where what this config shows at `path` originates: the system it was first authored in, followed
2149
+ * through however many pins it took to get here. `undefined` for a row this config authored itself.
2150
+ *
2151
+ * A row borrowed or copied through a pin is asked of that pin's source in turn, so a system linked
2152
+ * to a system linked to a foundation answers with the foundation. A row a materialized artifact
2153
+ * flattened to a literal has no pointer left, so the pin whose `link` declaration covers the path
2154
+ * stands in, provided the row still reads as the source's ({@link matchesSource}); one the
2155
+ * publisher changed is its own. Two answers with one `key` are one entity reached by two routes,
2156
+ * whatever versions the pins name: the key is the pin kind's `sourceOrigin`, not its identity.
2157
+ *
2158
+ * `pin` is the pin entity at the hop where the answer was found, for a surface that names the
2159
+ * origin the way it names any source.
2160
+ */
2161
+ originOf({
2162
+ kind,
2163
+ path
2164
+ }: {
2165
+ kind: string;
2166
+ path: string;
2167
+ }): {
2168
+ key: string;
2169
+ pin: Entity;
2170
+ } | undefined;
2171
+ /**
2172
+ * The pin whose `link` declaration covers `kind:path` while the row there still reads as that
2173
+ * source's: how a row a materialized artifact flattened to a literal is traced back to the pin it
2174
+ * came through. `undefined` when no declaration covers it, or the row differs from the source's.
2175
+ */
2176
+ private declaredThrough;
2177
+ /**
2178
+ * The identity of the source behind a slug — {@link sourceIdentityKey} for a caller holding the
2179
+ * address every source lookup uses.
2180
+ *
2181
+ * A slug is unique across source kinds ({@link assertDistinctSourceSlugs}), so the first kind holding
2182
+ * it is the only one that can, and nothing here has to say which kind that was.
2183
+ *
2184
+ * A client that fetched a catalogue needs to know whether the pin it fetched under is still the same
2185
+ * pin. Comparing slugs alone can't tell a retarget from a no-op, and comparing `systemId`/`version`
2186
+ * names fields one kind happens to declare. `undefined` for a slug this config doesn't pin.
2187
+ */
2188
+ sourceIdentityOf(slug: string): string | undefined;
2189
+ /**
2190
+ * Every slug this config draws a source under — the item paths of every kind declaring
2191
+ * {@link EntityKind.sourceIdentity}, whatever those kinds are called.
2192
+ *
2193
+ * One declaration site is the point: a source's value says both which source and where from, so
2194
+ * nothing has to reconcile two lists.
2195
+ *
2196
+ * Across all source kinds, and that is the right answer rather than a convenience: a ref spells `@ds`
2197
+ * with no room for a collection, so a slug is taken if any source kind has it. Two kinds claiming one
2198
+ * is refused outright ({@link assertDistinctSourceSlugs}), so this never reports a duplicate.
2199
+ */
2200
+ sourceSlugs(): string[];
2201
+ /**
2202
+ * The kinds whose items name an external source — the ones declaring
2203
+ * {@link EntityKind.sourceIdentity}.
2204
+ *
2205
+ * The framework knows borrowing as a mechanism and asks which kind implements it rather than testing
2206
+ * for one by name. A config registering no such kind borrows nothing, and every reader below returns
2207
+ * empty without a special case.
2208
+ */
2209
+ sourceKinds(): string[];
2210
+ /**
2211
+ * The source kind whose declared item is `slug` — asked rather than named, the same reason
2212
+ * {@link sourceKinds} is a list rather than a single kind the framework assumes.
2213
+ *
2214
+ * At most one: a config's slugs are flat and unique across every source kind
2215
+ * ({@link assertDistinctSourceSlugs}), because a ref spells `@ds` with no room for which
2216
+ * collection `ds` came from.
2217
+ */
2218
+ private sourceKindFor;
2219
+ /**
2220
+ * Every source kind by the accessor name its config type declares it under — `linkedSystems` →
2221
+ * `linked-system`.
2222
+ *
2223
+ * The accessor name is what every source-shaped argument is keyed by ({@link AttachedSources},
2224
+ * `register`, `Config.load`'s resolvers), because it's the name an author writes, where the kind is
2225
+ * what the framework indexes items under. Something has to hold the pair, and this is the only place
2226
+ * it needs holding.
2227
+ *
2228
+ * Read structurally off the config type's own manifest, so it names no kind and needs nothing added
2229
+ * per kind. A `Config` built outside `defineConfig` has no manifest, so its source kinds answer under
2230
+ * their kind name, which is the only key such a config has.
2231
+ */
2232
+ /**
2233
+ * The accessor a kind is registered under — `token` → `tokens` — or `undefined` for a config with no
2234
+ * manifest, and for a kind it does not declare.
2235
+ *
2236
+ * Config files are keyed by accessor (`register({ tokens, components })`) while ops and refs are
2237
+ * keyed by kind (`token:color/brand`). Anything stored that a person will read in a config file
2238
+ * therefore wants the accessor, and something has to be able to say which — this is that, read
2239
+ * structurally off the config type's own manifest exactly as {@link sourceAccessors} does, so it
2240
+ * names no kind and needs nothing added per kind.
2241
+ */
2242
+ accessorOf(kind: string): string | undefined;
2243
+ sourceAccessors(): ReadonlyMap<string, string>;
2244
+ /**
2245
+ * Every source this config reaches into, captured as an ordinary artifact — what `toJSON` stores.
2246
+ *
2247
+ * Membership is reachability and nothing else: follow the refs and keep what they land on, whatever
2248
+ * kind it is. No kind opts in and no field is required, which is why a modifier reached through a
2249
+ * Token's condition and a font reached through a typography token both survive. A value-map shape
2250
+ * drops both, and the font is native borrowing's blocker.
2251
+ *
2252
+ * Stored as a config rather than a bag of values, so nothing about reading it is special. Bodies are
2253
+ * verbatim, so each validates against its own kind's schema on the way back in, and groups and
2254
+ * settings ride along so `cssVar` recomputes from the source's own `cssPrefix` instead of being
2255
+ * frozen per entity.
2256
+ *
2257
+ * Away from a build there is nothing attached, so this carries through what was hydrated rather than
2258
+ * blanking it.
2259
+ *
2260
+ * That is sound because a pin is exact: a published version is immutable, and a repo-local pin is
2261
+ * recomputed on every local build. A stale closure would need a source to change under a fixed pin,
2262
+ * which is what a pin prevents.
2263
+ */
2264
+ /**
2265
+ * The closures this config would embed if it were serialized, without serializing it.
2266
+ *
2267
+ * {@link toJSON} already carries them, which is how an artifact keeps its borrowed values readable
2268
+ * when nothing is attached. A caller that wants only the closures — Create's load path, adding a
2269
+ * draft-aware closure to the base artifact a client hydrates — would otherwise pay a full walk over
2270
+ * every entity in a config that is routinely megabytes, to read a few kilobytes off the end.
2271
+ *
2272
+ * The same map `toJSON` embeds, from the same private walk, so the two can't describe a borrow
2273
+ * differently.
2274
+ */
2275
+ recordedSources(): Record<string, RecordedSource>;
2276
+ private recordSources;
2277
+ /**
2278
+ * Every slug this config's refs name, declared here or not — what {@link recordSources} owes a
2279
+ * closure for.
2280
+ *
2281
+ * Declared slugs are only half of it. Materializing a published chain keeps a ref whose target has no
2282
+ * value to collapse into, so a component borrowed from `mid` arrives holding `style-property:bg@base`,
2283
+ * a slug only `mid` declares. Recording only what this config pins leaves that ref with nothing behind
2284
+ * it, and a consumer holding the artifact alone reads a borrowed component whose style property
2285
+ * resolves to nothing.
2286
+ *
2287
+ * Reachability is already what a closure means; this applies the same rule to the source address
2288
+ * rather than the target. {@link sourceThrough} is what answers for such a slug, and the pair is why
2289
+ * the recorded artifact is self-contained.
2290
+ *
2291
+ * Skipped entirely for a config that borrows nothing, so the common serialize walks nothing extra.
2292
+ */
2293
+ private reachedSlugs;
2294
+ /**
2295
+ * Every item of a kind, in authored order — the flat list to map over in a UI. This config's own
2296
+ * kinds only: a source's items are read through a qualified ref, in the config that answers.
2297
+ *
2298
+ * **Memoized on the snapshot, like {@link Config.withComputed}, and for a sharper reason than
2299
+ * convenience.** A value domain is expanded per read (`stylePropEntries` → `members` → here), so
2300
+ * one CSS emit over this system's own artifact asked for the token list 23,895 times and paid 673
2301
+ * `withComputed` lookups each — 16M of them, 1.7s, on the browser's main thread. The list a
2302
+ * Snapshot has of a kind cannot change without the snapshot changing, so there is nothing to
2303
+ * expire.
2304
+ *
2305
+ * The array is shared with every other caller at this snapshot: consume it, don't mutate it. Sort
2306
+ * or splice a projection of it (`list(k).map(…).sort()`), never the list itself.
2307
+ */
2308
+ /**
2309
+ * Every item of a kind. Total by default: the stylesheet, the type union, ref resolution and the rail
2310
+ * all read it, and each has to keep seeing a hidden or deprecated entity. `{ retired: false }` is the
2311
+ * offer surface's read — a picker, an autocomplete, a prompt catalogue — and leaves out every entity
2312
+ * {@link retired} answers true for. Both answers are cached per snapshot, so either is safe in a dep
2313
+ * array.
2314
+ */
2315
+ list(kind: string, opts?: ListOptions): Entity[];
2316
+ /** The total list behind {@link list}. */
2317
+ private allOf;
2318
+ /** A kind's items as a nested folder/file tree, built from the qualified paths at any
2319
+ * depth (`color/spectrum/purple-60` → folder `color` → folder `color/spectrum` → item). A
2320
+ * folder carries its group metadata when a node exists at that prefix, else `undefined`
2321
+ * — folders come from the paths, so they render whether or not they were augmented. */
2322
+ tree(kind: string): TreeNode[];
2323
+ /** Every `kind:path` whose definition references the given entity — the reverse
2324
+ * dependency graph, harvested generically from refs in each item's data. */
2325
+ dependentsOf(kind: string, path: string, opts?: TraverseOptions): string[];
2326
+ /** The inverse: what `kind:path` needs in order to resolve. `{ transitive: true }` returns the
2327
+ * whole closure — what a sealed/exported copy would have to carry along with it. */
2328
+ dependenciesOf(kind: string, path: string, opts?: TraverseOptions): string[];
2329
+ /** Validate a create body against the kind's schema — derived from its fields. */
2330
+ validateCreate(kind: string, data: unknown): {
2331
+ ok: true;
2332
+ } | {
2333
+ ok: false;
2334
+ error: string;
2335
+ };
2336
+ /**
2337
+ * The wire form. Annotated with {@link SerializedConfig} rather than defining it by inference —
2338
+ * see that type for why the direction flipped, and why both drift directions still fail to compile.
2339
+ *
2340
+ * Every optional field stays a conditional spread rather than a later assignment: a
2341
+ * `{...(cond ? { k } : {})}` is checked against the annotation as one literal, where assigning to a
2342
+ * mutable object would defeat the excess-property check that replaces the old inference.
2343
+ */
2344
+ toJSON(): SerializedConfig;
2345
+ /** `defineConfig` registers its class here so `Config.fromJSON(json)` can construct the right type
2346
+ * from `json.name`. */
2347
+ static registerConfigType(name: string, ctor: new () => Config): void;
2348
+ /** Rehydrate a config from its wire form. Untyped escape hatch for generic code that only holds a
2349
+ * plain `Config` (the ~100 studio patch appliers — all link-less system configs, so they call it
2350
+ * one-arg). Dispatches on `json.name` to the registered config type, then hydrates. Typed callers
2351
+ * use the config type's own `fromJSON` static (strict `LinkedSources`). `sources` values
2352
+ * self-describe their linked kind, so keys are irrelevant here. */
2353
+ static fromJSON(json: StoredConfig, options?: HydrationOptions): Config;
2354
+ /**
2355
+ * Hydrate an artifact with its sources resolved — the async counterpart to {@link fromJSON}.
2356
+ *
2357
+ * `fromJSON` is sync and every environment's fetch is not, which is the whole reason this exists.
2358
+ * Attaching at hydration rather than after is load-bearing: `registerSources` leaves a window in which
2359
+ * every sourced ref dangles, and emitters, integrity checks and memos all read exactly there.
2360
+ *
2361
+ * `sources` is keyed the way every other source-shaped argument is — by the source kind's accessor
2362
+ * name, `{ linkedSystems: resolver }` — so the resolver set, the declaration, and
2363
+ * {@link registerSources} all spell the same key. Each resolver is the kind's own
2364
+ * (`LinkedSystemResolver`), and its answer is validated against the schemas that kind declares.
2365
+ *
2366
+ * Reads the source entities off a throwaway bare parse, resolves them all, then hydrates once with
2367
+ * whatever came back attached. The bare parse is cheap and is what lets a resolver be handed the
2368
+ * Entity — `entity.path` is the slug and every other field is its kind's own, so a config declaring
2369
+ * some other source kind needs nothing added here.
2370
+ *
2371
+ * **Two levels of totality, failing differently.** The resolver map must cover every declared source
2372
+ * kind — a missing key is a programming error, and answering nothing for a kind reads identically to
2373
+ * "this config borrows nothing". Each resolver must then answer for every item of its kind;
2374
+ * `unavailable` is a legal answer, no answer is not.
2375
+ *
2376
+ * Refusing on `unavailable` is the caller's policy, not this method's: a build refuses, an editor
2377
+ * records it and paints it. So this attaches what it got, records every state, and returns.
2378
+ */
2379
+ static load(json: SerializedConfig, options: {
2380
+ readonly sources: Record<string, SourceResolver<never>>;
2381
+ }): Promise<Config>;
2382
+ /**
2383
+ * This config with its declared sources resolved — the authoring-side counterpart to {@link load}.
2384
+ *
2385
+ * `load` is for an artifact, where attaching at hydration is load-bearing: between a bare `fromJSON`
2386
+ * and a later attach every sourced ref dangles, and the emitters and integrity checks read exactly
2387
+ * there. A config that was authored has no such window — it already exists, its sourced refs already
2388
+ * dangle, and the only question is what its pins resolve to. That is the build's shape, and forcing it
2389
+ * through `load` would mean serializing a config the caller is holding just to hydrate it again.
2390
+ *
2391
+ * Same resolvers, same validation, same recorded states, so the two paths cannot disagree about what a
2392
+ * source resolved to.
2393
+ */
2394
+ resolveSources(options: {
2395
+ readonly sources: Record<string, SourceResolver<never>>;
2396
+ }): Promise<this>;
2397
+ /**
2398
+ * Attach one source and record what it resolved to — the incremental counterpart to
2399
+ * {@link resolveSources}.
2400
+ *
2401
+ * A walk answers for every declared pin at once, which is what a build and a page load want. A
2402
+ * surface that fetched a source because someone opened a panel holds one answer about one slug, and
2403
+ * putting that through the walk would mean inventing answers for the others: "as before" for the ones
2404
+ * already attached, and something for the ones nobody has looked at, which turns the third state
2405
+ * ({@link sources}: nobody resolved this) into a verdict. So the incremental case gets its own door.
2406
+ */
2407
+ attachResolved({
2408
+ source,
2409
+ slug,
2410
+ answer
2411
+ }: {
2412
+ readonly source: string;
2413
+ readonly slug: string; /** What a resolver — or the server action standing in for one — answered about this slug. */
2414
+ readonly answer: SourceAnswer;
2415
+ }): this;
2416
+ /**
2417
+ * This config with another's live attachments and receipts carried across — minus any whose pin moved.
2418
+ *
2419
+ * **A rebuild from bytes loses every attachment.** A payload is bytes and an attached source isn't in
2420
+ * them, so `fromJSON` hands back a config with nothing attached, and every holder that rehydrates — a
2421
+ * realtime echo, a draft sync, a tab-switch true-up, a rebase — wipes a catalogue someone just
2422
+ * fetched. It looks like this: link a system, watch its catalogue fill in, then watch the panel revert
2423
+ * to "their values aren't loaded here yet" with no interaction. Nothing errors and the pin is still
2424
+ * there; only the attachment is gone, and with it every borrowed read.
2425
+ *
2426
+ * The receipts ride along for the same reason. They are what a rail reads to say why a pin is unmet,
2427
+ * and rebuilding without them turns "we looked and it failed" back into "nobody looked".
2428
+ *
2429
+ * Carried per slug, and only where the pin still names the same source, judged by the fields the kind
2430
+ * declares as its identity ({@link sourceIdentityOf}). A pin retargeted to another version is a
2431
+ * different source, and carrying its catalogue would have the picker offering the old version's
2432
+ * Entities under the new pin's name.
2433
+ *
2434
+ * It never overwrites — a caller that hydrated with sources of its own keeps them — and returns the
2435
+ * receiver unchanged when there is nothing to carry, so the ordinary path allocates nothing and
2436
+ * callers can compare by reference.
2437
+ */
2438
+ withAttachmentsFrom(previous: Config): this;
2439
+ /**
2440
+ * Retire the attachment for every slug a walk answered `unavailable` for.
2441
+ *
2442
+ * A resolve walk is total over the declared items of a source kind — `unavailable` is a legal answer
2443
+ * and silence is not — so what it reports is the whole truth about those slugs rather than an
2444
+ * amendment to what was attached before. {@link registerSources} only ever sets, which is right for
2445
+ * the incremental case, attaching one source someone just fetched, and wrong for an answer that
2446
+ */
2447
+ private detachUnresolved;
2448
+ /**
2449
+ * The resolve walk {@link load} and {@link resolveSources} share — declared sources in, the states
2450
+ * they answered with and the configs to attach out.
2451
+ *
2452
+ * Static and taking its config, because `load` runs it against a throwaway bare parse while
2453
+ * `resolveSources` runs it against the config the caller already holds.
2454
+ */
2455
+ private static resolveDeclared;
2456
+ /**
2457
+ * One source kind's resolution schema, from what the kind declared — the framework's `status` tag over
2458
+ * its own `{ resolved, unavailable }`.
2459
+ *
2460
+ * A separate step so the refusal reads as a declaration problem rather than as a validation failure on
2461
+ * whatever the first resolver happened to answer. `defineConfig` already refuses a `sources` entry whose
2462
+ * kind declares none, so reaching this throw means a kind was resolved through some other route.
2463
+ */
2464
+ private static resolutionSchemaOf;
2465
+ /** The shared hydration path both the untyped dispatcher and a config type's typed `fromJSON` funnel
2466
+ * through. The instance is freshly constructed by a config type, so its entity metadata is already
2467
+ * seeded (owned + derived); this loads the data (items, groups, sparse overrides) and wires
2468
+ * links from the provided sources. A declared `linkedKind` with no provided source throws. */
2469
+ protected hydrateFrom(stored: StoredConfig, options?: HydrationOptions): this;
2470
+ }
2471
+ //#endregion
2472
+ export { AttachedSources, Config, CssGrammar, Edition, HydrationOptions, ListOptions, LiveConfig, Patch, RecordedSource, SERIALIZED_CONFIG_VERSION, SerializedConfig, SkippedOp, SourcesBySlug, StoredConfig, SubPatch, TreeNode };