@treenity/core 1.0.48 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (807) hide show
  1. package/README.md +72 -12
  2. package/dist/chain.d.ts +19 -0
  3. package/dist/chain.d.ts.map +1 -0
  4. package/dist/chain.js +59 -0
  5. package/dist/chain.js.map +1 -0
  6. package/dist/client/handle.d.ts +13 -0
  7. package/dist/client/handle.d.ts.map +1 -0
  8. package/dist/client/handle.js +46 -0
  9. package/dist/client/handle.js.map +1 -0
  10. package/dist/client/index.d.ts +21 -0
  11. package/dist/client/index.d.ts.map +1 -0
  12. package/dist/client/index.js +5 -0
  13. package/dist/client/index.js.map +1 -0
  14. package/dist/client/trpc.d.ts +13 -0
  15. package/dist/client/trpc.d.ts.map +1 -0
  16. package/dist/client/trpc.js +79 -0
  17. package/dist/client/trpc.js.map +1 -0
  18. package/dist/client.d.ts +2 -0
  19. package/dist/client.d.ts.map +1 -0
  20. package/dist/client.js +2 -0
  21. package/dist/client.js.map +1 -0
  22. package/dist/comp/handle.d.ts +14 -0
  23. package/dist/comp/handle.d.ts.map +1 -0
  24. package/dist/comp/handle.js +21 -0
  25. package/dist/comp/handle.js.map +1 -0
  26. package/dist/comp/index.d.ts +41 -0
  27. package/dist/comp/index.d.ts.map +1 -0
  28. package/dist/comp/index.js +127 -0
  29. package/dist/comp/index.js.map +1 -0
  30. package/dist/comp/needs.d.ts +26 -0
  31. package/dist/comp/needs.d.ts.map +1 -0
  32. package/dist/comp/needs.js +101 -0
  33. package/dist/comp/needs.js.map +1 -0
  34. package/dist/comp/validate.d.ts +13 -0
  35. package/dist/comp/validate.d.ts.map +1 -0
  36. package/dist/comp/validate.js +117 -0
  37. package/dist/comp/validate.js.map +1 -0
  38. package/dist/comp.d.ts +2 -0
  39. package/dist/comp.d.ts.map +1 -0
  40. package/dist/comp.js +2 -0
  41. package/dist/comp.js.map +1 -0
  42. package/dist/contexts/schema/index.d.ts +7 -0
  43. package/dist/contexts/schema/index.d.ts.map +1 -0
  44. package/dist/contexts/schema/index.js +2 -0
  45. package/dist/contexts/schema/index.js.map +1 -0
  46. package/dist/contexts/schema.d.ts +2 -0
  47. package/dist/contexts/schema.d.ts.map +1 -0
  48. package/dist/contexts/schema.js +2 -0
  49. package/dist/contexts/schema.js.map +1 -0
  50. package/dist/contexts/service/index.d.ts +31 -0
  51. package/dist/contexts/service/index.d.ts.map +1 -0
  52. package/dist/contexts/service/index.js +16 -0
  53. package/dist/contexts/service/index.js.map +1 -0
  54. package/dist/contexts/service.d.ts +1 -14
  55. package/dist/contexts/service.d.ts.map +1 -1
  56. package/dist/contexts/service.js +2 -0
  57. package/dist/contexts/service.js.map +1 -0
  58. package/dist/contexts/telegram/index.d.ts +19 -0
  59. package/dist/contexts/telegram/index.d.ts.map +1 -0
  60. package/dist/contexts/telegram/index.js +89 -0
  61. package/dist/contexts/telegram/index.js.map +1 -0
  62. package/dist/contexts/text/index.d.ts +7 -0
  63. package/dist/contexts/text/index.d.ts.map +1 -0
  64. package/dist/contexts/text/index.js +9 -0
  65. package/dist/contexts/text/index.js.map +1 -0
  66. package/dist/contexts/text.d.ts +2 -0
  67. package/dist/contexts/text.d.ts.map +1 -0
  68. package/dist/contexts/text.js +2 -0
  69. package/dist/contexts/text.js.map +1 -0
  70. package/dist/core/component.d.ts +43 -0
  71. package/dist/core/component.d.ts.map +1 -0
  72. package/dist/core/component.js +101 -0
  73. package/dist/core/component.js.map +1 -0
  74. package/dist/core/context.d.ts +5 -0
  75. package/dist/core/context.d.ts.map +1 -0
  76. package/dist/core/context.js +3 -0
  77. package/dist/core/context.js.map +1 -0
  78. package/dist/core/index.d.ts +5 -0
  79. package/dist/core/index.d.ts.map +1 -0
  80. package/dist/core/index.js +8 -0
  81. package/dist/core/index.js.map +1 -0
  82. package/dist/core/path.d.ts +7 -0
  83. package/dist/core/path.d.ts.map +1 -0
  84. package/dist/core/path.js +41 -0
  85. package/dist/core/path.js.map +1 -0
  86. package/dist/core/registry.d.ts +17 -0
  87. package/dist/core/registry.d.ts.map +1 -0
  88. package/dist/core/registry.js +100 -0
  89. package/dist/core/registry.js.map +1 -0
  90. package/dist/core.d.ts +2 -0
  91. package/dist/core.d.ts.map +1 -0
  92. package/dist/core.js +2 -0
  93. package/dist/core.js.map +1 -0
  94. package/dist/index.d.ts +1 -12
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +2 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/log.d.ts +38 -0
  99. package/dist/log.d.ts.map +1 -0
  100. package/dist/log.js +150 -0
  101. package/dist/log.js.map +1 -0
  102. package/dist/mod/discover.d.ts +4 -0
  103. package/dist/mod/discover.d.ts.map +1 -0
  104. package/dist/mod/discover.js +103 -0
  105. package/dist/mod/discover.js.map +1 -0
  106. package/dist/mod/examples/ticker/seed.d.ts +3 -0
  107. package/dist/mod/examples/ticker/seed.d.ts.map +1 -0
  108. package/dist/mod/examples/ticker/seed.js +16 -0
  109. package/dist/mod/examples/ticker/seed.js.map +1 -0
  110. package/dist/mod/examples/ticker/service.d.ts +2 -0
  111. package/dist/mod/examples/ticker/service.d.ts.map +1 -0
  112. package/dist/mod/examples/ticker/service.js +17 -0
  113. package/dist/mod/examples/ticker/service.js.map +1 -0
  114. package/dist/mod/examples/ticker/types.d.ts +16 -0
  115. package/dist/mod/examples/ticker/types.d.ts.map +1 -0
  116. package/dist/mod/examples/ticker/types.js +20 -0
  117. package/dist/mod/examples/ticker/types.js.map +1 -0
  118. package/dist/mod/examples/ticker/view.d.ts +2 -0
  119. package/dist/mod/examples/ticker/view.d.ts.map +1 -0
  120. package/dist/mod/examples/ticker/view.js +10 -0
  121. package/dist/mod/examples/ticker/view.js.map +1 -0
  122. package/dist/mod/index.d.ts +11 -0
  123. package/dist/mod/index.d.ts.map +1 -0
  124. package/dist/mod/index.js +8 -0
  125. package/dist/mod/index.js.map +1 -0
  126. package/dist/mod/loader.d.ts +19 -0
  127. package/dist/mod/loader.d.ts.map +1 -0
  128. package/dist/mod/loader.js +180 -0
  129. package/dist/mod/loader.js.map +1 -0
  130. package/dist/mod/optimistic.d.ts +34 -0
  131. package/dist/mod/optimistic.d.ts.map +1 -0
  132. package/dist/mod/optimistic.js +176 -0
  133. package/dist/mod/optimistic.js.map +1 -0
  134. package/dist/mod/prefab.d.ts +18 -0
  135. package/dist/mod/prefab.d.ts.map +1 -0
  136. package/dist/mod/prefab.js +42 -0
  137. package/dist/mod/prefab.js.map +1 -0
  138. package/dist/mod/tracking.d.ts +8 -0
  139. package/dist/mod/tracking.d.ts.map +1 -0
  140. package/dist/mod/tracking.js +44 -0
  141. package/dist/mod/tracking.js.map +1 -0
  142. package/dist/mod/types.d.ts +31 -0
  143. package/dist/mod/types.d.ts.map +1 -0
  144. package/dist/mod/types.js +5 -0
  145. package/dist/mod/types.js.map +1 -0
  146. package/dist/mod.d.ts +2 -0
  147. package/dist/mod.d.ts.map +1 -0
  148. package/dist/mod.js +2 -0
  149. package/dist/mod.js.map +1 -0
  150. package/dist/mods/autostart/server.d.ts +2 -0
  151. package/dist/mods/autostart/server.d.ts.map +1 -0
  152. package/dist/mods/autostart/server.js +2 -0
  153. package/dist/mods/autostart/server.js.map +1 -0
  154. package/dist/mods/autostart/service.d.ts +14 -0
  155. package/dist/mods/autostart/service.d.ts.map +1 -0
  156. package/dist/mods/autostart/service.js +88 -0
  157. package/dist/mods/autostart/service.js.map +1 -0
  158. package/dist/mods/clients.d.ts +2 -0
  159. package/dist/mods/clients.d.ts.map +1 -0
  160. package/dist/mods/clients.js +3 -0
  161. package/dist/mods/clients.js.map +1 -0
  162. package/dist/mods/llm/index.d.ts +13 -0
  163. package/dist/mods/llm/index.d.ts.map +1 -0
  164. package/dist/mods/llm/index.js +43 -0
  165. package/dist/mods/llm/index.js.map +1 -0
  166. package/dist/mods/llm/server.d.ts +2 -0
  167. package/dist/mods/llm/server.d.ts.map +1 -0
  168. package/dist/mods/llm/server.js +2 -0
  169. package/dist/mods/llm/server.js.map +1 -0
  170. package/dist/mods/mcp/server.d.ts +2 -0
  171. package/dist/mods/mcp/server.js +2 -0
  172. package/dist/mods/mcp/service.d.ts +1 -0
  173. package/dist/mods/mcp/service.js +16 -0
  174. package/dist/mods/mcp/types.d.ts +4 -0
  175. package/dist/mods/mcp/types.js +6 -0
  176. package/dist/mods/servers.d.ts +4 -0
  177. package/dist/mods/servers.d.ts.map +1 -0
  178. package/dist/mods/servers.js +5 -0
  179. package/dist/mods/servers.js.map +1 -0
  180. package/dist/mods/treenity/agent-port.d.ts +2 -0
  181. package/dist/mods/treenity/agent-port.d.ts.map +1 -0
  182. package/dist/mods/treenity/agent-port.js +76 -0
  183. package/dist/mods/treenity/agent-port.js.map +1 -0
  184. package/dist/mods/treenity/builtins.d.ts +2 -0
  185. package/dist/mods/treenity/builtins.d.ts.map +1 -0
  186. package/dist/mods/treenity/builtins.js +18 -0
  187. package/dist/mods/treenity/builtins.js.map +1 -0
  188. package/dist/mods/treenity/groups.d.ts +2 -0
  189. package/dist/mods/treenity/groups.d.ts.map +1 -0
  190. package/dist/mods/treenity/groups.js +18 -0
  191. package/dist/mods/treenity/groups.js.map +1 -0
  192. package/dist/mods/treenity/logs.d.ts +18 -0
  193. package/dist/mods/treenity/logs.d.ts.map +1 -0
  194. package/dist/mods/treenity/logs.js +17 -0
  195. package/dist/mods/treenity/logs.js.map +1 -0
  196. package/dist/mods/treenity/mod-type.d.ts +2 -0
  197. package/dist/mods/treenity/mod-type.d.ts.map +1 -0
  198. package/dist/mods/treenity/mod-type.js +9 -0
  199. package/dist/mods/treenity/mod-type.js.map +1 -0
  200. package/dist/mods/treenity/seed.d.ts +2 -0
  201. package/dist/mods/treenity/seed.d.ts.map +1 -0
  202. package/dist/mods/treenity/seed.js +55 -0
  203. package/dist/mods/treenity/seed.js.map +1 -0
  204. package/dist/mods/treenity/server.d.ts +7 -0
  205. package/dist/mods/treenity/server.d.ts.map +1 -0
  206. package/dist/mods/treenity/server.js +7 -0
  207. package/dist/mods/treenity/server.js.map +1 -0
  208. package/dist/mods/treenity/system.d.ts +36 -0
  209. package/dist/mods/treenity/system.d.ts.map +1 -0
  210. package/dist/mods/treenity/system.js +61 -0
  211. package/dist/mods/treenity/system.js.map +1 -0
  212. package/dist/mods/uix/client.d.ts +3 -0
  213. package/dist/mods/uix/client.d.ts.map +1 -0
  214. package/dist/mods/uix/client.js +96 -0
  215. package/dist/mods/uix/client.js.map +1 -0
  216. package/dist/mods/uix/compile.d.ts +7 -0
  217. package/dist/mods/uix/compile.d.ts.map +1 -0
  218. package/dist/mods/uix/compile.js +96 -0
  219. package/dist/mods/uix/compile.js.map +1 -0
  220. package/dist/mods/uix/jsx-parser.d.ts +2 -0
  221. package/dist/mods/uix/jsx-parser.d.ts.map +1 -0
  222. package/dist/mods/uix/jsx-parser.js +565 -0
  223. package/dist/mods/uix/jsx-parser.js.map +1 -0
  224. package/dist/mods/uix/verify.d.ts +7 -0
  225. package/dist/mods/uix/verify.d.ts.map +1 -0
  226. package/dist/mods/uix/verify.js +59 -0
  227. package/dist/mods/uix/verify.js.map +1 -0
  228. package/dist/schema/_test-fixture.d.ts +11 -0
  229. package/dist/schema/_test-fixture.d.ts.map +1 -0
  230. package/dist/schema/_test-fixture.js +8 -0
  231. package/dist/schema/_test-fixture.js.map +1 -0
  232. package/dist/schema/catalog.d.ts +23 -0
  233. package/dist/schema/catalog.d.ts.map +1 -0
  234. package/dist/schema/catalog.js +82 -0
  235. package/dist/schema/catalog.js.map +1 -0
  236. package/dist/schema/extract-schemas.d.ts +5 -0
  237. package/dist/schema/extract-schemas.d.ts.map +1 -0
  238. package/dist/schema/extract-schemas.js +444 -0
  239. package/dist/schema/extract-schemas.js.map +1 -0
  240. package/dist/schema/load.d.ts +2 -0
  241. package/dist/schema/load.d.ts.map +1 -0
  242. package/dist/schema/load.js +23 -0
  243. package/dist/schema/load.js.map +1 -0
  244. package/dist/schema/test-fixture.types.d.ts +2 -0
  245. package/dist/schema/test-fixture.types.d.ts.map +1 -0
  246. package/dist/schema/test-fixture.types.js +19 -0
  247. package/dist/schema/test-fixture.types.js.map +1 -0
  248. package/dist/schema/types.d.ts +38 -0
  249. package/dist/schema/types.d.ts.map +1 -0
  250. package/dist/schema/types.js +3 -0
  251. package/dist/schema/types.js.map +1 -0
  252. package/dist/server/actions.d.ts +35 -0
  253. package/dist/server/actions.d.ts.map +1 -0
  254. package/dist/server/actions.js +170 -0
  255. package/dist/server/actions.js.map +1 -0
  256. package/dist/server/agent.d.ts +6 -0
  257. package/dist/server/agent.d.ts.map +1 -0
  258. package/dist/server/agent.js +15 -0
  259. package/dist/server/agent.js.map +1 -0
  260. package/dist/server/auth.d.ts +39 -0
  261. package/dist/server/auth.d.ts.map +1 -0
  262. package/dist/server/auth.js +336 -0
  263. package/dist/server/auth.js.map +1 -0
  264. package/dist/server/client.d.ts +190 -0
  265. package/dist/server/client.d.ts.map +1 -0
  266. package/dist/server/client.js +22 -0
  267. package/dist/server/client.js.map +1 -0
  268. package/dist/server/cookies.d.ts +5 -0
  269. package/dist/server/cookies.d.ts.map +1 -0
  270. package/dist/server/cookies.js +24 -0
  271. package/dist/server/cookies.js.map +1 -0
  272. package/dist/server/doc-index.d.ts +38 -0
  273. package/dist/server/doc-index.d.ts.map +1 -0
  274. package/dist/server/doc-index.js +245 -0
  275. package/dist/server/doc-index.js.map +1 -0
  276. package/dist/server/errors.d.ts +7 -0
  277. package/dist/server/errors.d.ts.map +1 -0
  278. package/dist/server/errors.js +11 -0
  279. package/dist/server/errors.js.map +1 -0
  280. package/dist/server/factory.d.ts +29 -0
  281. package/dist/server/factory.d.ts.map +1 -0
  282. package/dist/server/factory.js +89 -0
  283. package/dist/server/factory.js.map +1 -0
  284. package/dist/server/main.d.ts +2 -0
  285. package/dist/server/main.d.ts.map +1 -0
  286. package/dist/server/main.js +19 -0
  287. package/dist/server/main.js.map +1 -0
  288. package/dist/server/mcp.d.ts +4 -0
  289. package/dist/server/mcp.js +279 -0
  290. package/dist/server/migrate.d.ts +3 -0
  291. package/dist/server/migrate.d.ts.map +1 -0
  292. package/dist/server/migrate.js +56 -0
  293. package/dist/server/migrate.js.map +1 -0
  294. package/dist/server/mod-catalog.d.ts +14 -0
  295. package/dist/server/mod-catalog.d.ts.map +1 -0
  296. package/dist/server/mod-catalog.js +40 -0
  297. package/dist/server/mod-catalog.js.map +1 -0
  298. package/dist/server/mods-mount.d.ts +3 -0
  299. package/dist/server/mods-mount.d.ts.map +1 -0
  300. package/dist/server/mods-mount.js +168 -0
  301. package/dist/server/mods-mount.js.map +1 -0
  302. package/dist/server/mount-adapters.d.ts +9 -0
  303. package/dist/server/mount-adapters.d.ts.map +1 -0
  304. package/dist/server/mount-adapters.js +80 -0
  305. package/dist/server/mount-adapters.js.map +1 -0
  306. package/dist/server/mount.d.ts +3 -0
  307. package/dist/server/mount.d.ts.map +1 -0
  308. package/dist/server/mount.js +195 -0
  309. package/dist/server/mount.js.map +1 -0
  310. package/dist/server/prefab.d.ts +18 -0
  311. package/dist/server/prefab.d.ts.map +1 -0
  312. package/dist/server/prefab.js +72 -0
  313. package/dist/server/prefab.js.map +1 -0
  314. package/dist/server/refs.d.ts +3 -0
  315. package/dist/server/refs.d.ts.map +1 -0
  316. package/dist/server/refs.js +59 -0
  317. package/dist/server/refs.js.map +1 -0
  318. package/dist/server/seed/index.d.ts +6 -0
  319. package/dist/server/seed/index.d.ts.map +1 -0
  320. package/dist/server/seed/index.js +16 -0
  321. package/dist/server/seed/index.js.map +1 -0
  322. package/dist/server/server.d.ts +28 -0
  323. package/dist/server/server.d.ts.map +1 -0
  324. package/dist/server/server.js +127 -0
  325. package/dist/server/server.js.map +1 -0
  326. package/dist/server/sub.d.ts +34 -0
  327. package/dist/server/sub.d.ts.map +1 -0
  328. package/dist/server/sub.js +174 -0
  329. package/dist/server/sub.js.map +1 -0
  330. package/dist/server/trpc.d.ts +199 -0
  331. package/dist/server/trpc.d.ts.map +1 -0
  332. package/dist/server/trpc.js +323 -0
  333. package/dist/server/trpc.js.map +1 -0
  334. package/dist/server/types-mount.d.ts +3 -0
  335. package/dist/server/types-mount.d.ts.map +1 -0
  336. package/dist/server/types-mount.js +144 -0
  337. package/dist/server/types-mount.js.map +1 -0
  338. package/dist/server/validate.d.ts +3 -0
  339. package/dist/server/validate.d.ts.map +1 -0
  340. package/dist/server/validate.js +20 -0
  341. package/dist/server/validate.js.map +1 -0
  342. package/dist/server/volatile.d.ts +11 -0
  343. package/dist/server/volatile.d.ts.map +1 -0
  344. package/dist/server/volatile.js +26 -0
  345. package/dist/server/volatile.js.map +1 -0
  346. package/dist/server/watch.d.ts +23 -0
  347. package/dist/server/watch.d.ts.map +1 -0
  348. package/dist/server/watch.js +178 -0
  349. package/dist/server/watch.js.map +1 -0
  350. package/dist/tree/cache.d.ts +3 -0
  351. package/dist/tree/cache.d.ts.map +1 -0
  352. package/dist/tree/cache.js +48 -0
  353. package/dist/tree/cache.js.map +1 -0
  354. package/dist/tree/fs.d.ts +3 -0
  355. package/dist/tree/fs.d.ts.map +1 -0
  356. package/dist/tree/fs.js +276 -0
  357. package/dist/tree/fs.js.map +1 -0
  358. package/dist/tree/index.d.ts +38 -0
  359. package/dist/tree/index.d.ts.map +1 -0
  360. package/dist/tree/index.js +183 -0
  361. package/dist/tree/index.js.map +1 -0
  362. package/dist/tree/inflight.d.ts +2 -0
  363. package/dist/tree/inflight.d.ts.map +1 -0
  364. package/dist/tree/inflight.js +15 -0
  365. package/dist/tree/inflight.js.map +1 -0
  366. package/dist/tree/json-codec.d.ts +2 -0
  367. package/dist/tree/json-codec.d.ts.map +1 -0
  368. package/dist/tree/json-codec.js +13 -0
  369. package/dist/tree/json-codec.js.map +1 -0
  370. package/dist/tree/mimefs.d.ts +13 -0
  371. package/dist/tree/mimefs.d.ts.map +1 -0
  372. package/dist/tree/mimefs.js +124 -0
  373. package/dist/tree/mimefs.js.map +1 -0
  374. package/dist/tree/mongo.d.ts +5 -0
  375. package/dist/tree/mongo.d.ts.map +1 -0
  376. package/dist/tree/mongo.js +110 -0
  377. package/dist/tree/mongo.js.map +1 -0
  378. package/dist/tree/patch.d.ts +30 -0
  379. package/dist/tree/patch.d.ts.map +1 -0
  380. package/dist/tree/patch.js +112 -0
  381. package/dist/tree/patch.js.map +1 -0
  382. package/dist/tree/query.d.ts +12 -0
  383. package/dist/tree/query.d.ts.map +1 -0
  384. package/dist/tree/query.js +61 -0
  385. package/dist/tree/query.js.map +1 -0
  386. package/dist/tree/repath.d.ts +3 -0
  387. package/dist/tree/repath.d.ts.map +1 -0
  388. package/dist/tree/repath.js +38 -0
  389. package/dist/tree/repath.js.map +1 -0
  390. package/dist/tree-chain.d.ts +19 -0
  391. package/dist/tree-chain.d.ts.map +1 -0
  392. package/dist/tree-chain.js +111 -0
  393. package/dist/tree-chain.js.map +1 -0
  394. package/dist/tree.d.ts +2 -0
  395. package/dist/tree.d.ts.map +1 -0
  396. package/dist/tree.js +2 -0
  397. package/dist/tree.js.map +1 -0
  398. package/dist/uri.d.ts +11 -0
  399. package/dist/uri.d.ts.map +1 -0
  400. package/dist/uri.js +84 -0
  401. package/dist/uri.js.map +1 -0
  402. package/package.json +78 -37
  403. package/src/chain.test.ts +190 -0
  404. package/src/chain.ts +84 -0
  405. package/src/client/client.test.ts +192 -0
  406. package/src/client/handle.ts +53 -0
  407. package/src/client/index.ts +18 -0
  408. package/src/client/trpc.ts +92 -0
  409. package/src/client.ts +1 -0
  410. package/src/comp/CLAUDE.md +14 -0
  411. package/src/comp/handle.ts +36 -0
  412. package/src/comp/index.test.ts +165 -0
  413. package/src/comp/index.ts +186 -0
  414. package/src/comp/needs.test.ts +499 -0
  415. package/src/comp/needs.ts +113 -0
  416. package/src/comp/validate.test.ts +304 -0
  417. package/src/comp/validate.ts +125 -0
  418. package/src/comp.ts +1 -0
  419. package/src/contexts/schema/index.ts +7 -0
  420. package/src/contexts/schema.ts +1 -0
  421. package/src/contexts/service/index.test.ts +323 -0
  422. package/src/contexts/service/index.ts +43 -0
  423. package/src/contexts/service.ts +1 -0
  424. package/src/contexts/telegram/index.ts +115 -0
  425. package/src/contexts/text/index.test.ts +31 -0
  426. package/src/contexts/text/index.ts +18 -0
  427. package/src/contexts/text.ts +1 -0
  428. package/src/core/component.ts +153 -0
  429. package/src/core/context.ts +14 -0
  430. package/src/core/index.test.ts +224 -0
  431. package/src/core/index.ts +9 -0
  432. package/src/core/path.ts +38 -0
  433. package/src/core/registry.ts +112 -0
  434. package/src/core.ts +1 -0
  435. package/src/index.ts +1 -0
  436. package/src/log.test.ts +70 -0
  437. package/src/log.ts +199 -0
  438. package/src/mod/discover.test.ts +133 -0
  439. package/src/mod/discover.ts +100 -0
  440. package/src/mod/docs/00-index.md +19 -0
  441. package/src/mod/docs/01-primitives.md +38 -0
  442. package/src/mod/docs/02-core-api.md +68 -0
  443. package/src/mod/docs/03-registry.md +30 -0
  444. package/src/mod/docs/04-store.md +62 -0
  445. package/src/mod/docs/05-comp.md +111 -0
  446. package/src/mod/docs/06-actions.md +193 -0
  447. package/src/mod/docs/07-realtime.md +108 -0
  448. package/src/mod/docs/08-services.md +35 -0
  449. package/src/mod/docs/09-mounts.md +43 -0
  450. package/src/mod/docs/10-acl.md +60 -0
  451. package/src/mod/docs/11-server.md +62 -0
  452. package/src/mod/docs/12-conventions.md +108 -0
  453. package/src/mod/docs/13-example.md +142 -0
  454. package/src/mod/docs/14-mod-format.md +377 -0
  455. package/src/mod/docs/15-documenting-types.md +156 -0
  456. package/src/mod/examples/ticker/seed.ts +19 -0
  457. package/src/mod/examples/ticker/service.ts +19 -0
  458. package/src/mod/examples/ticker/ticker.test.ts +18 -0
  459. package/src/mod/examples/ticker/types.ts +22 -0
  460. package/src/mod/examples/ticker/view.tsx +19 -0
  461. package/src/mod/index.ts +12 -0
  462. package/src/mod/loader.test.ts +220 -0
  463. package/src/mod/loader.ts +207 -0
  464. package/src/mod/optimistic.test.ts +446 -0
  465. package/src/mod/optimistic.ts +210 -0
  466. package/src/mod/prefab.ts +62 -0
  467. package/src/mod/tracking.test.ts +59 -0
  468. package/src/mod/tracking.ts +51 -0
  469. package/src/mod/types.ts +40 -0
  470. package/src/mod.ts +1 -0
  471. package/src/mods/autostart/CLAUDE.md +6 -0
  472. package/src/mods/autostart/autostart.test.ts +85 -0
  473. package/src/mods/autostart/server.ts +1 -0
  474. package/src/mods/autostart/service.ts +98 -0
  475. package/src/mods/clients.ts +2 -0
  476. package/src/mods/llm/CLAUDE.md +6 -0
  477. package/src/mods/llm/index.ts +57 -0
  478. package/src/mods/llm/llm.test.ts +109 -0
  479. package/src/mods/llm/server.ts +1 -0
  480. package/src/mods/servers.ts +4 -0
  481. package/src/mods/treenity/agent-port.ts +93 -0
  482. package/src/mods/treenity/builtins.ts +21 -0
  483. package/src/mods/treenity/groups.ts +19 -0
  484. package/src/mods/treenity/logs.ts +26 -0
  485. package/src/mods/treenity/mod-type.ts +10 -0
  486. package/src/mods/treenity/seed.ts +58 -0
  487. package/src/mods/treenity/server.ts +6 -0
  488. package/src/mods/treenity/system.ts +70 -0
  489. package/src/mods/uix/CLAUDE.md +7 -0
  490. package/src/mods/uix/client.ts +117 -0
  491. package/src/mods/uix/compile.test.ts +228 -0
  492. package/src/mods/uix/compile.ts +112 -0
  493. package/src/mods/uix/jsx-parser.test.ts +554 -0
  494. package/src/mods/uix/jsx-parser.ts +489 -0
  495. package/src/mods/uix/lazy-load.test.ts +261 -0
  496. package/src/mods/uix/uix-repomix.md +3509 -0
  497. package/src/mods/uix/verify.ts +68 -0
  498. package/src/schema/CLAUDE.md +13 -0
  499. package/src/schema/_test-fixture.ts +12 -0
  500. package/src/schema/catalog.ts +101 -0
  501. package/src/schema/extract-schemas.test.ts +84 -0
  502. package/src/schema/extract-schemas.ts +462 -0
  503. package/src/schema/generated/ai.agent.json +133 -0
  504. package/src/schema/generated/ai.approval.json +105 -0
  505. package/src/schema/generated/ai.approvals.json +24 -0
  506. package/src/schema/generated/ai.assignment.json +28 -0
  507. package/src/schema/generated/ai.plan.json +84 -0
  508. package/src/schema/generated/ai.policy.json +105 -0
  509. package/src/schema/generated/ai.pool.json +37 -0
  510. package/src/schema/generated/ai.thread.json +64 -0
  511. package/src/schema/generated/autostart.json +44 -0
  512. package/src/schema/generated/board.column.json +25 -0
  513. package/src/schema/generated/board.kanban.json +7 -0
  514. package/src/schema/generated/board.task.json +147 -0
  515. package/src/schema/generated/brahman.action.back.json +12 -0
  516. package/src/schema/generated/brahman.action.broadcast.json +31 -0
  517. package/src/schema/generated/brahman.action.call.json +57 -0
  518. package/src/schema/generated/brahman.action.emittext.json +23 -0
  519. package/src/schema/generated/brahman.action.eval.json +23 -0
  520. package/src/schema/generated/brahman.action.file.json +28 -0
  521. package/src/schema/generated/brahman.action.forward.json +29 -0
  522. package/src/schema/generated/brahman.action.getvalue.json +28 -0
  523. package/src/schema/generated/brahman.action.ifelse.json +42 -0
  524. package/src/schema/generated/brahman.action.keywordselect.json +46 -0
  525. package/src/schema/generated/brahman.action.message.json +127 -0
  526. package/src/schema/generated/brahman.action.onerror.json +29 -0
  527. package/src/schema/generated/brahman.action.page.json +22 -0
  528. package/src/schema/generated/brahman.action.params.json +36 -0
  529. package/src/schema/generated/brahman.action.question.json +43 -0
  530. package/src/schema/generated/brahman.action.remove.json +12 -0
  531. package/src/schema/generated/brahman.action.resethistory.json +12 -0
  532. package/src/schema/generated/brahman.action.resetsession.json +12 -0
  533. package/src/schema/generated/brahman.action.selectlang.json +20 -0
  534. package/src/schema/generated/brahman.action.setvalue.json +27 -0
  535. package/src/schema/generated/brahman.action.tag.json +27 -0
  536. package/src/schema/generated/brahman.bot.json +68 -0
  537. package/src/schema/generated/brahman.page.json +25 -0
  538. package/src/schema/generated/brahman.session.json +29 -0
  539. package/src/schema/generated/brahman.user.json +58 -0
  540. package/src/schema/generated/cafe.contact.json +56 -0
  541. package/src/schema/generated/cafe.mail.json +29 -0
  542. package/src/schema/generated/canary.item.json +40 -0
  543. package/src/schema/generated/claude-search.json +20 -0
  544. package/src/schema/generated/craft.product.json +47 -0
  545. package/src/schema/generated/craft.shop.json +94 -0
  546. package/src/schema/generated/craft.subscription.json +27 -0
  547. package/src/schema/generated/default.json +15 -0
  548. package/src/schema/generated/doc.page.json +23 -0
  549. package/src/schema/generated/examples.demo.generator.json +16 -0
  550. package/src/schema/generated/examples.demo.sensor.json +35 -0
  551. package/src/schema/generated/examples.demo.sensor.reading.json +25 -0
  552. package/src/schema/generated/flow.node.action.json +61 -0
  553. package/src/schema/generated/flow.node.code.json +43 -0
  554. package/src/schema/generated/flow.node.condition.json +37 -0
  555. package/src/schema/generated/flow.node.end.json +35 -0
  556. package/src/schema/generated/flow.node.http.json +65 -0
  557. package/src/schema/generated/flow.node.llm.json +67 -0
  558. package/src/schema/generated/flow.node.loop.json +49 -0
  559. package/src/schema/generated/flow.node.start.json +39 -0
  560. package/src/schema/generated/flow.scenario.json +118 -0
  561. package/src/schema/generated/groups.json +20 -0
  562. package/src/schema/generated/grove.attempt.json +199 -0
  563. package/src/schema/generated/grove.path.json +93 -0
  564. package/src/schema/generated/grove.review.json +27 -0
  565. package/src/schema/generated/grove.task.json +164 -0
  566. package/src/schema/generated/intel.scenario.json +58 -0
  567. package/src/schema/generated/intel.signal.json +113 -0
  568. package/src/schema/generated/intel.world.json +15 -0
  569. package/src/schema/generated/landing.block.json +201 -0
  570. package/src/schema/generated/landing.page.json +84 -0
  571. package/src/schema/generated/launcher.json +91 -0
  572. package/src/schema/generated/mcp.server.json +15 -0
  573. package/src/schema/generated/metatron.config.json +119 -0
  574. package/src/schema/generated/metatron.permission.json +36 -0
  575. package/src/schema/generated/metatron.skill.json +36 -0
  576. package/src/schema/generated/metatron.task.json +114 -0
  577. package/src/schema/generated/metatron.template.json +26 -0
  578. package/src/schema/generated/metatron.workspace.json +60 -0
  579. package/src/schema/generated/mindmap.map.json +22 -0
  580. package/src/schema/generated/order.status.json +21 -0
  581. package/src/schema/generated/polyhope.backtest.json +161 -0
  582. package/src/schema/generated/polyhope.feed.json +33 -0
  583. package/src/schema/generated/polyhope.run.json +94 -0
  584. package/src/schema/generated/polyhope.strategy.json +152 -0
  585. package/src/schema/generated/polymax.activity.json +65 -0
  586. package/src/schema/generated/polymax.aggr-feed.json +28 -0
  587. package/src/schema/generated/polymax.aggr.json +20 -0
  588. package/src/schema/generated/polymax.alert.json +56 -0
  589. package/src/schema/generated/polymax.bot-config.json +14 -0
  590. package/src/schema/generated/polymax.bot-status.json +35 -0
  591. package/src/schema/generated/polymax.classification.json +55 -0
  592. package/src/schema/generated/polymax.deposits.json +45 -0
  593. package/src/schema/generated/polymax.holding.json +55 -0
  594. package/src/schema/generated/polymax.identity.json +71 -0
  595. package/src/schema/generated/polymax.lb-entry.json +75 -0
  596. package/src/schema/generated/polymax.leaderboard.json +37 -0
  597. package/src/schema/generated/polymax.market-ref.json +25 -0
  598. package/src/schema/generated/polymax.performance.json +65 -0
  599. package/src/schema/generated/polymax.profile.json +16 -0
  600. package/src/schema/generated/polymax.scan-result.json +50 -0
  601. package/src/schema/generated/polymax.status.json +40 -0
  602. package/src/schema/generated/polymax.tags.json +53 -0
  603. package/src/schema/generated/polymax.trader.json +16 -0
  604. package/src/schema/generated/polymax.wallet-market.json +50 -0
  605. package/src/schema/generated/polymax.wallet-pnl.json +35 -0
  606. package/src/schema/generated/pult.concept.json +53 -0
  607. package/src/schema/generated/pult.config.json +227 -0
  608. package/src/schema/generated/pult.connector.json +72 -0
  609. package/src/schema/generated/pult.market.json +113 -0
  610. package/src/schema/generated/pult.order.json +113 -0
  611. package/src/schema/generated/pult.rete.json +68 -0
  612. package/src/schema/generated/pult.sensor.json +74 -0
  613. package/src/schema/generated/pult.signal.json +54 -0
  614. package/src/schema/generated/pult.synapse.json +93 -0
  615. package/src/schema/generated/pult.trade.json +93 -0
  616. package/src/schema/generated/resim.config.json +34 -0
  617. package/src/schema/generated/resim.function.json +62 -0
  618. package/src/schema/generated/resim.goal.json +22 -0
  619. package/src/schema/generated/resim.resource.json +40 -0
  620. package/src/schema/generated/resim.state.json +48 -0
  621. package/src/schema/generated/resim.world.json +40 -0
  622. package/src/schema/generated/saveme.action.save.json +29 -0
  623. package/src/schema/generated/saveme.message.json +36 -0
  624. package/src/schema/generated/saveme.router.json +31 -0
  625. package/src/schema/generated/sim.agent.json +24 -0
  626. package/src/schema/generated/sim.ai.json +24 -0
  627. package/src/schema/generated/sim.config.json +38 -0
  628. package/src/schema/generated/sim.descriptive.json +26 -0
  629. package/src/schema/generated/sim.events.json +47 -0
  630. package/src/schema/generated/sim.item.json +20 -0
  631. package/src/schema/generated/sim.memory.json +17 -0
  632. package/src/schema/generated/sim.nearby.json +17 -0
  633. package/src/schema/generated/sim.position.json +25 -0
  634. package/src/schema/generated/sim.round.json +64 -0
  635. package/src/schema/generated/sim.world.json +32 -0
  636. package/src/schema/generated/t.agent.port.json +74 -0
  637. package/src/schema/generated/t.coolify.json +50 -0
  638. package/src/schema/generated/t.event.json +46 -0
  639. package/src/schema/generated/t.llm.json +20 -0
  640. package/src/schema/generated/t.logs.json +155 -0
  641. package/src/schema/generated/t.mod.json +27 -0
  642. package/src/schema/generated/t.note.json +31 -0
  643. package/src/schema/generated/t.person.json +36 -0
  644. package/src/schema/generated/t.tenant.json +57 -0
  645. package/src/schema/generated/t.tenant.status.json +42 -0
  646. package/src/schema/generated/t3d.animator.json +46 -0
  647. package/src/schema/generated/t3d.audio.json +58 -0
  648. package/src/schema/generated/t3d.camera.json +50 -0
  649. package/src/schema/generated/t3d.collider.json +84 -0
  650. package/src/schema/generated/t3d.light.json +90 -0
  651. package/src/schema/generated/t3d.line.json +47 -0
  652. package/src/schema/generated/t3d.lod.json +28 -0
  653. package/src/schema/generated/t3d.material.json +131 -0
  654. package/src/schema/generated/t3d.mesh.json +65 -0
  655. package/src/schema/generated/t3d.object.json +64 -0
  656. package/src/schema/generated/t3d.particles.json +109 -0
  657. package/src/schema/generated/t3d.rigidbody.json +81 -0
  658. package/src/schema/generated/t3d.scene.json +7 -0
  659. package/src/schema/generated/t3d.script.json +23 -0
  660. package/src/schema/generated/t3d.text.json +86 -0
  661. package/src/schema/generated/t3d.trail.json +45 -0
  662. package/src/schema/generated/tagger.config.json +115 -0
  663. package/src/schema/generated/tagger.result.json +57 -0
  664. package/src/schema/generated/tagger.tree.json +36 -0
  665. package/src/schema/generated/task.json +96 -0
  666. package/src/schema/generated/test.fixture.json +43 -0
  667. package/src/schema/generated/ticker.config.json +43 -0
  668. package/src/schema/generated/ticker.price.json +20 -0
  669. package/src/schema/generated/todo.item.json +25 -0
  670. package/src/schema/generated/todo.list.json +33 -0
  671. package/src/schema/generated/treenity.system.json +259 -0
  672. package/src/schema/generated/ui.table.json +46 -0
  673. package/src/schema/generated/whisper.audio.json +25 -0
  674. package/src/schema/generated/whisper.checklist.json +17 -0
  675. package/src/schema/generated/whisper.config.json +30 -0
  676. package/src/schema/generated/whisper.inbox.json +24 -0
  677. package/src/schema/generated/whisper.meta.json +35 -0
  678. package/src/schema/generated/whisper.text.json +16 -0
  679. package/src/schema/load.ts +24 -0
  680. package/src/schema/schema.test.ts +86 -0
  681. package/src/schema/test-fixture.types.ts +21 -0
  682. package/src/schema/types.ts +34 -0
  683. package/src/server/CLAUDE.md +26 -0
  684. package/src/server/actions.test.ts +272 -0
  685. package/src/server/actions.ts +274 -0
  686. package/src/server/agent-sub.test.ts +90 -0
  687. package/src/server/agent.test.ts +305 -0
  688. package/src/server/agent.ts +17 -0
  689. package/src/server/api.test.ts +463 -0
  690. package/src/server/auth.test.ts +441 -0
  691. package/src/server/auth.ts +387 -0
  692. package/src/server/client.ts +24 -0
  693. package/src/server/conditions.test.ts +128 -0
  694. package/src/server/cookies.ts +25 -0
  695. package/src/server/coverage.test.ts +827 -0
  696. package/src/server/doc-index.ts +287 -0
  697. package/src/server/e2e.test.ts +967 -0
  698. package/src/server/errors.ts +11 -0
  699. package/src/server/factory.ts +121 -0
  700. package/src/server/main.ts +24 -0
  701. package/src/server/migrate.test.ts +123 -0
  702. package/src/server/migrate.ts +62 -0
  703. package/src/server/mod-catalog.ts +59 -0
  704. package/src/server/mods-mount.ts +177 -0
  705. package/src/server/mount-adapters.ts +87 -0
  706. package/src/server/mount.parametrized.test.ts +52 -0
  707. package/src/server/mount.query.test.ts +127 -0
  708. package/src/server/mount.test.ts +565 -0
  709. package/src/server/mount.ts +208 -0
  710. package/src/server/prefab.test.ts +415 -0
  711. package/src/server/prefab.ts +105 -0
  712. package/src/server/refs.test.ts +82 -0
  713. package/src/server/refs.ts +64 -0
  714. package/src/server/seed/index.ts +24 -0
  715. package/src/server/server.ts +164 -0
  716. package/src/server/stress.test.ts +844 -0
  717. package/src/server/sub.test.ts +55 -0
  718. package/src/server/sub.ts +224 -0
  719. package/src/server/trpc.ts +375 -0
  720. package/src/server/types-mount.ts +142 -0
  721. package/src/server/validate.test.ts +91 -0
  722. package/src/server/validate.ts +22 -0
  723. package/src/server/volatile.test.ts +140 -0
  724. package/src/server/volatile.ts +32 -0
  725. package/src/server/watch.test.ts +594 -0
  726. package/src/server/watch.ts +202 -0
  727. package/src/server/workflow.test.ts +82 -0
  728. package/src/tree/CLAUDE.md +13 -0
  729. package/src/tree/cache.test.ts +213 -0
  730. package/src/tree/cache.ts +51 -0
  731. package/src/tree/fs.test.ts +247 -0
  732. package/src/tree/fs.ts +257 -0
  733. package/src/tree/index.test.ts +190 -0
  734. package/src/tree/index.ts +217 -0
  735. package/src/tree/inflight.ts +15 -0
  736. package/src/tree/json-codec.ts +16 -0
  737. package/src/tree/mimefs.test.ts +289 -0
  738. package/src/tree/mimefs.ts +142 -0
  739. package/src/tree/mongo.ts +125 -0
  740. package/src/tree/patch.test.ts +192 -0
  741. package/src/tree/patch.ts +133 -0
  742. package/src/tree/query.test.ts +110 -0
  743. package/src/tree/query.ts +70 -0
  744. package/src/tree/repath.test.ts +86 -0
  745. package/src/tree/repath.ts +53 -0
  746. package/src/tree-chain.test.ts +716 -0
  747. package/src/tree-chain.ts +150 -0
  748. package/src/tree.ts +1 -0
  749. package/src/uri.test.ts +113 -0
  750. package/src/uri.ts +84 -0
  751. package/CHANGELOG.md +0 -314
  752. package/dist/context.d.ts +0 -41
  753. package/dist/context.d.ts.map +0 -1
  754. package/dist/context.mjs +0 -81
  755. package/dist/context.mjs.map +0 -1
  756. package/dist/contexts/node-engine.d.ts +0 -12
  757. package/dist/contexts/node-engine.d.ts.map +0 -1
  758. package/dist/contexts/node-engine.mjs +0 -7
  759. package/dist/contexts/node-engine.mjs.map +0 -1
  760. package/dist/contexts/noflo/types.d.ts +0 -20
  761. package/dist/contexts/noflo/types.d.ts.map +0 -1
  762. package/dist/contexts/object.d.ts +0 -11
  763. package/dist/contexts/object.d.ts.map +0 -1
  764. package/dist/contexts/object.mjs +0 -15
  765. package/dist/contexts/object.mjs.map +0 -1
  766. package/dist/contexts/proto.d.ts +0 -11
  767. package/dist/contexts/proto.d.ts.map +0 -1
  768. package/dist/contexts/proto.mjs +0 -7
  769. package/dist/contexts/proto.mjs.map +0 -1
  770. package/dist/contexts/react-context.d.ts +0 -21
  771. package/dist/contexts/react-context.d.ts.map +0 -1
  772. package/dist/contexts/react-context.mjs +0 -24
  773. package/dist/contexts/react-context.mjs.map +0 -1
  774. package/dist/contexts/service.mjs +0 -7
  775. package/dist/contexts/service.mjs.map +0 -1
  776. package/dist/get-type-cache.d.ts +0 -2
  777. package/dist/get-type-cache.d.ts.map +0 -1
  778. package/dist/get-type-cache.mjs +0 -7
  779. package/dist/get-type-cache.mjs.map +0 -1
  780. package/dist/index.mjs +0 -10
  781. package/dist/index.mjs.map +0 -1
  782. package/dist/link/link.d.ts +0 -25
  783. package/dist/link/link.d.ts.map +0 -1
  784. package/dist/link/link.mjs +0 -72
  785. package/dist/link/link.mjs.map +0 -1
  786. package/dist/link/link.test.d.ts +0 -2
  787. package/dist/link/link.test.d.ts.map +0 -1
  788. package/dist/loading.d.ts +0 -9
  789. package/dist/loading.d.ts.map +0 -1
  790. package/dist/meta-type.d.ts +0 -58
  791. package/dist/meta-type.d.ts.map +0 -1
  792. package/dist/meta-type.mjs +0 -104
  793. package/dist/meta-type.mjs.map +0 -1
  794. package/dist/meta.d.ts +0 -20
  795. package/dist/meta.d.ts.map +0 -1
  796. package/dist/meta.mjs +0 -16
  797. package/dist/meta.mjs.map +0 -1
  798. package/dist/node/index.d.ts +0 -2
  799. package/dist/node/index.d.ts.map +0 -1
  800. package/dist/node/types.d.ts +0 -37
  801. package/dist/node/types.d.ts.map +0 -1
  802. package/dist/test/context.test.d.ts +0 -2
  803. package/dist/test/context.test.d.ts.map +0 -1
  804. package/dist/types.d.ts +0 -14
  805. package/dist/types.d.ts.map +0 -1
  806. package/dist/types.mjs +0 -16
  807. package/dist/types.mjs.map +0 -1
@@ -0,0 +1,716 @@
1
+ import { refVal, type TypedRef } from '#chain';
2
+ import { registerType } from '#comp';
3
+ import { isRef } from '#core';
4
+ import type { Tree } from '#tree';
5
+ import { createMemoryTree } from '#tree';
6
+ import assert from 'node:assert/strict';
7
+ import { describe, test } from 'node:test';
8
+ import { treeChain } from './tree-chain';
9
+
10
+ // ── Test types ──
11
+
12
+ class Scanner {
13
+ static $type = 'tch.scanner'
14
+ intervalMs = 900_000
15
+ maxRetries = 3
16
+ livePrices: TypedRef<LivePrices> = refVal(LivePrices)
17
+ scan() { return { started: true } }
18
+ configure(data: { interval: number }) { return data }
19
+ }
20
+ registerType('tch.scanner', Scanner)
21
+
22
+ class LivePrices {
23
+ static $type = 'tch.live-prices'
24
+ feederUrl = 'ws://localhost:8090'
25
+ subscribe(data: { slugs: string[] }) {
26
+ return data.slugs.map((s: string) => ({ slug: s, bid: 0.6 }))
27
+ }
28
+ }
29
+ registerType('tch.live-prices', LivePrices)
30
+
31
+ class Profile {
32
+ static $type = 'tch.profile'
33
+ name = ''
34
+ balance = 0
35
+ }
36
+ registerType('tch.profile', Profile)
37
+
38
+ class Wallet {
39
+ static $type = 'tch.wallet'
40
+ address = ''
41
+ chain = ''
42
+ }
43
+ registerType('tch.wallet', Wallet)
44
+
45
+ // ── Seed ──
46
+
47
+ async function seed(): Promise<Tree> {
48
+ const tree = createMemoryTree()
49
+
50
+ await tree.set({ $path: '/services', $type: 'dir' })
51
+ await tree.set({
52
+ $path: '/services/scanner',
53
+ $type: 'tch.scanner',
54
+ intervalMs: 900_000,
55
+ maxRetries: 3,
56
+ livePrices: { $type: 'ref', $ref: '/services/live-prices' },
57
+ })
58
+ await tree.set({
59
+ $path: '/services/live-prices',
60
+ $type: 'tch.live-prices',
61
+ feederUrl: 'ws://localhost:8090',
62
+ })
63
+
64
+ // Children of scanner
65
+ await tree.set({ $path: '/services/scanner/s1', $type: 'tch.scan-result', ts: 1000 })
66
+ await tree.set({ $path: '/services/scanner/s2', $type: 'tch.scan-result', ts: 2000 })
67
+
68
+ // Node with named component
69
+ await tree.set({
70
+ $path: '/users/alice',
71
+ $type: 'tch.profile',
72
+ name: 'Alice',
73
+ balance: 100,
74
+ wallet: { $type: 'tch.wallet', address: '0xabc', chain: 'eth' },
75
+ })
76
+
77
+ return tree
78
+ }
79
+
80
+ describe('treeChain — path building', () => {
81
+ test('$path from dot navigation', () => {
82
+ const c = treeChain(null as any)
83
+ assert.equal(c.services.scanner.$path, '/services/scanner')
84
+ })
85
+
86
+ test('$path from root', () => {
87
+ const c = treeChain(null as any)
88
+ assert.equal(c.$path, '/')
89
+ })
90
+
91
+ test('$path with basePath', () => {
92
+ const c = treeChain(null as any, '/services')
93
+ assert.equal(c.scanner.$path, '/services/scanner')
94
+ })
95
+
96
+ test('$path with bracket access', () => {
97
+ const c = treeChain(null as any)
98
+ assert.equal(c.services.scanner['s1'].$path, '/services/scanner/s1')
99
+ })
100
+ })
101
+
102
+ describe('treeChain — node materialization (await)', () => {
103
+ test('await returns node data', async () => {
104
+ const tree = await seed()
105
+ const c = treeChain(tree)
106
+ const node = await c.services.scanner
107
+ assert.equal(node.$type, 'tch.scanner')
108
+ assert.equal(node.intervalMs, 900_000)
109
+ })
110
+
111
+ test('await deep path', async () => {
112
+ const tree = await seed()
113
+ const node = await treeChain(tree).services.scanner['s1']
114
+ assert.equal(node.ts, 1000)
115
+ })
116
+
117
+ test('await missing node throws', async () => {
118
+ const tree = await seed()
119
+ await assert.rejects(async () => { await treeChain(tree).nothing.here })
120
+ })
121
+ })
122
+
123
+ describe('treeChain — $get (typed component)', () => {
124
+ test('$get returns typed fields', async () => {
125
+ const tree = await seed()
126
+ const scanner: Scanner = await treeChain(tree).services.scanner.$get(Scanner)
127
+ assert.equal(scanner.intervalMs, 900_000)
128
+ assert.equal(scanner.maxRetries, 3)
129
+ })
130
+
131
+ test('$field with named component', async () => {
132
+ const tree = await seed()
133
+ const wallet = await treeChain(tree).users.alice.$field('wallet')
134
+ assert.equal(wallet.address, '0xabc')
135
+ })
136
+
137
+ test('$get wrong type throws', async () => {
138
+ const tree = await seed()
139
+ await assert.rejects(async () => { await treeChain(tree).services.scanner.$get(LivePrices) })
140
+ })
141
+ })
142
+
143
+ describe('treeChain — (Class) bracket access', () => {
144
+ test('(Class) returns typed fields', async () => {
145
+ const tree = await seed()
146
+ const scanner: Scanner = await treeChain(tree).services.scanner(Scanner)
147
+ assert.equal(scanner.intervalMs, 900_000)
148
+ assert.equal(scanner.maxRetries, 3)
149
+ })
150
+
151
+ test('(Class) finds named component by type scan', async () => {
152
+ const tree = await seed()
153
+ const wallet = await treeChain(tree).users.alice(Wallet)
154
+ assert.equal(wallet.address, '0xabc')
155
+ })
156
+
157
+ test('(Class) wrong type throws', async () => {
158
+ const tree = await seed()
159
+ await assert.rejects(async () => { await treeChain(tree).services.scanner(LivePrices) })
160
+ })
161
+
162
+ test('(Class) then ref follow', async () => {
163
+ const tree = await seed()
164
+ const lp = await treeChain(tree).services.scanner(Scanner).livePrices
165
+ assert.equal(lp.feederUrl, 'ws://localhost:8090')
166
+ })
167
+
168
+ test('(Class) → ref → action', async () => {
169
+ const tree = await seed()
170
+ const result = await treeChain(tree)
171
+ .services.scanner(Scanner).livePrices
172
+ .subscribe({ slugs: ['btc'] })
173
+ assert.deepEqual(result, [{ slug: 'btc', bid: 0.6 }])
174
+ })
175
+ })
176
+
177
+ describe('treeChain — ref auto-follow', () => {
178
+ test('TypedRef field resolves to target node', async () => {
179
+ const tree = await seed()
180
+ // scanner.livePrices is { $ref: '/services/live-prices' }
181
+ // chain follows ref automatically
182
+ const lp = await treeChain(tree).services.scanner.$get(Scanner).livePrices
183
+ assert.equal(lp.feederUrl, 'ws://localhost:8090')
184
+ })
185
+
186
+ test('ref field then field access', async () => {
187
+ const tree = await seed()
188
+ const url = await treeChain(tree).services.scanner.$get(Scanner).livePrices.feederUrl
189
+ assert.equal(url, 'ws://localhost:8090')
190
+ })
191
+
192
+ test('missing ref throws', async () => {
193
+ const tree = await seed()
194
+ // Set scanner with broken ref
195
+ await tree.set({
196
+ $path: '/broken',
197
+ $type: 'tch.scanner',
198
+ livePrices: { $type: 'ref', $ref: '/nonexistent' },
199
+ })
200
+ await assert.rejects(async () => { await treeChain(tree).broken.$get(Scanner).livePrices })
201
+ })
202
+ })
203
+
204
+ describe('treeChain — actions', () => {
205
+ test('action call returns result', async () => {
206
+ const tree = await seed()
207
+ const result = await treeChain(tree).services.scanner(Scanner).scan()
208
+ assert.deepEqual(result, { started: true })
209
+ })
210
+
211
+ test('action with data', async () => {
212
+ const tree = await seed()
213
+ const result = await treeChain(tree).services.scanner(Scanner).configure({ interval: 5000 })
214
+ assert.deepEqual(result, { interval: 5000 })
215
+ })
216
+
217
+ test('action on ref target', async () => {
218
+ const tree = await seed()
219
+ const result = await treeChain(tree)
220
+ .services.scanner
221
+ .$get(Scanner).livePrices
222
+ .subscribe({ slugs: ['btc'] })
223
+ assert.deepEqual(result, [{ slug: 'btc', bid: 0.6 }])
224
+ })
225
+ })
226
+
227
+ describe('treeChain — $children', () => {
228
+ test('returns child nodes', async () => {
229
+ const tree = await seed()
230
+ const kids = await treeChain(tree).services.scanner.$children()
231
+ assert.equal(kids.length, 2)
232
+ })
233
+
234
+ test('with query filter', async () => {
235
+ const tree = await seed()
236
+ const kids = await treeChain(tree).services.scanner.$children({ ts: 1000 })
237
+ assert.equal(kids.length, 1)
238
+ assert.equal(kids[0].ts, 1000)
239
+ })
240
+
241
+ test('empty children', async () => {
242
+ const tree = await seed()
243
+ const kids = await treeChain(tree).services['live-prices'].$children()
244
+ assert.equal(kids.length, 0)
245
+ })
246
+ })
247
+
248
+ describe('treeChain — composition', () => {
249
+ test('chain is reusable (no state mutation)', async () => {
250
+ const tree = await seed()
251
+ const services = treeChain(tree).services
252
+ const a = await services.scanner
253
+ const b = await services['live-prices']
254
+ assert.equal(a.$type, 'tch.scanner')
255
+ assert.equal(b.$type, 'tch.live-prices')
256
+ })
257
+
258
+ test('chain from basePath', async () => {
259
+ const tree = await seed()
260
+ const scanner = await treeChain(tree, '/services/scanner')
261
+ assert.equal(scanner.$type, 'tch.scanner')
262
+ })
263
+
264
+ test('full pipeline: navigate → type → ref → action', async () => {
265
+ const tree = await seed()
266
+ const result = await treeChain(tree)
267
+ .services // → /services (child nav)
268
+ .scanner // → /services/scanner (child nav)
269
+ .$get(Scanner) // → typed as Scanner
270
+ .livePrices // → follow ref → /services/live-prices
271
+ .subscribe({ slugs: ['eth', 'btc'] }) // → action on LivePrices
272
+
273
+ assert.equal(result.length, 2)
274
+ assert.equal(result[0].slug, 'eth')
275
+ assert.equal(result[1].slug, 'btc')
276
+ })
277
+ })
278
+
279
+ // ── Real-world usage examples ──
280
+ // These show how treeChain would be used on a real Treenity tree.
281
+ // Seed mimics actual /board, /cafe, /agent structure.
282
+
283
+ class BoardTask {
284
+ static $type = 'tch.board.task'
285
+ title = ''
286
+ status = 'backlog'
287
+ priority = 'normal'
288
+ move(data: { status: string }) { return { moved: data.status } }
289
+ assign(data: { to: string }) { return { assigned: data.to } }
290
+ }
291
+ registerType('tch.board.task', BoardTask)
292
+
293
+ class BoardKanban {
294
+ static $type = 'tch.board.kanban'
295
+ }
296
+ registerType('tch.board.kanban', BoardKanban)
297
+
298
+ class CafeContact {
299
+ static $type = 'tch.cafe.contact'
300
+ phone = ''
301
+ address = ''
302
+ }
303
+ registerType('tch.cafe.contact', CafeContact)
304
+
305
+ class AgentConfig {
306
+ static $type = 'tch.agent.config'
307
+ model = ''
308
+ bot: TypedRef<BrahmanBot> = refVal(BrahmanBot)
309
+ }
310
+ registerType('tch.agent.config', AgentConfig)
311
+
312
+ class BrahmanBot {
313
+ static $type = 'tch.brahman.bot'
314
+ alias = ''
315
+ running = false
316
+ restart() { return { restarted: true } }
317
+ }
318
+ registerType('tch.brahman.bot', BrahmanBot)
319
+
320
+ async function seedRealWorld(): Promise<Tree> {
321
+ const tree = createMemoryTree()
322
+
323
+ // /board — kanban with task children
324
+ await tree.set({ $path: '/board', $type: 'tch.board.kanban' })
325
+ await tree.set({
326
+ $path: '/board/landing',
327
+ $type: 'tch.board.task',
328
+ title: 'Landing treenity.land',
329
+ status: 'doing',
330
+ priority: 'urgent',
331
+ })
332
+ await tree.set({
333
+ $path: '/board/npm-split',
334
+ $type: 'tch.board.task',
335
+ title: 'npm monorepo split',
336
+ status: 'done',
337
+ priority: 'high',
338
+ })
339
+ await tree.set({
340
+ $path: '/board/agent-toolkit',
341
+ $type: 'tch.board.task',
342
+ title: 'Agent Toolkit — MCP tools',
343
+ status: 'backlog',
344
+ priority: 'urgent',
345
+ })
346
+
347
+ // /cafe — contact with nested component
348
+ await tree.set({
349
+ $path: '/cafe/contact',
350
+ $type: 'tch.cafe.contact',
351
+ phone: '+7-999-123-4567',
352
+ address: 'Moscow, Tverskaya 1',
353
+ })
354
+
355
+ // /agent — config with ref to bot
356
+ await tree.set({
357
+ $path: '/agent',
358
+ $type: 'tch.agent.config',
359
+ model: 'claude-opus-4-6',
360
+ bot: { $type: 'ref', $ref: '/brahman' },
361
+ })
362
+ await tree.set({
363
+ $path: '/brahman',
364
+ $type: 'tch.brahman.bot',
365
+ alias: '@treenitybot',
366
+ running: true,
367
+ })
368
+
369
+ return tree
370
+ }
371
+
372
+ describe('real-world: board tasks', () => {
373
+ test('read task title by path', async () => {
374
+ const tree = await seedRealWorld()
375
+ const task = await treeChain(tree).board.landing
376
+ assert.equal(task.title, 'Landing treenity.land')
377
+ assert.equal(task.status, 'doing')
378
+ })
379
+
380
+ test('list all board tasks', async () => {
381
+ const tree = await seedRealWorld()
382
+ const tasks = await treeChain(tree).board.$children()
383
+ assert.equal(tasks.length, 3)
384
+ })
385
+
386
+ test('filter tasks by status', async () => {
387
+ const tree = await seedRealWorld()
388
+ const doing = await treeChain(tree).board.$children({ status: 'doing' })
389
+ assert.equal(doing.length, 1)
390
+ assert.equal(doing[0].title, 'Landing treenity.land')
391
+ })
392
+
393
+ test('move task via action', async () => {
394
+ const tree = await seedRealWorld()
395
+ const result = await treeChain(tree).board.landing(BoardTask).move({ status: 'review' })
396
+ assert.deepEqual(result, { moved: 'review' })
397
+ })
398
+
399
+ test('assign task', async () => {
400
+ const tree = await seedRealWorld()
401
+ const result = await treeChain(tree).board['agent-toolkit'](BoardTask).assign({ to: 'agent' })
402
+ assert.deepEqual(result, { assigned: 'agent' })
403
+ })
404
+
405
+ test('save chain as bookmark, reuse', async () => {
406
+ const tree = await seedRealWorld()
407
+ const board = treeChain(tree).board
408
+
409
+ const t1 = await board.landing
410
+ const t2 = await board['npm-split']
411
+ assert.equal(t1.priority, 'urgent')
412
+ assert.equal(t2.status, 'done')
413
+ })
414
+ })
415
+
416
+ describe('real-world: cross-node refs', () => {
417
+ test('agent → bot ref auto-follow', async () => {
418
+ const tree = await seedRealWorld()
419
+ const bot = await treeChain(tree).agent.$get(AgentConfig).bot
420
+ assert.equal(bot.alias, '@treenitybot')
421
+ assert.equal(bot.running, true)
422
+ })
423
+
424
+ test('action through ref: restart bot via agent', async () => {
425
+ const tree = await seedRealWorld()
426
+ const result = await treeChain(tree)
427
+ .agent
428
+ .$get(AgentConfig).bot
429
+ .restart()
430
+ assert.deepEqual(result, { restarted: true })
431
+ })
432
+
433
+ test('read field through ref', async () => {
434
+ const tree = await seedRealWorld()
435
+ const alias = await treeChain(tree).agent.$get(AgentConfig).bot.alias
436
+ assert.equal(alias, '@treenitybot')
437
+ })
438
+ })
439
+
440
+ describe('real-world: (Class) bracket access', () => {
441
+ test('agent(AgentConfig).bot auto-follows ref', async () => {
442
+ const tree = await seedRealWorld()
443
+ const bot = await treeChain(tree).agent(AgentConfig).bot
444
+ assert.equal(bot.alias, '@treenitybot')
445
+ assert.equal(bot.running, true)
446
+ })
447
+
448
+ test('(Class) → ref → action', async () => {
449
+ const tree = await seedRealWorld()
450
+ const result = await treeChain(tree).agent(AgentConfig).bot.restart()
451
+ assert.deepEqual(result, { restarted: true })
452
+ })
453
+
454
+ test('(Class) → ref → field', async () => {
455
+ const tree = await seedRealWorld()
456
+ const alias = await treeChain(tree).agent(AgentConfig).bot.alias
457
+ assert.equal(alias, '@treenitybot')
458
+ })
459
+ })
460
+
461
+ describe('real-world: ergonomics comparison', () => {
462
+ // These tests show the same operation done via treeChain vs old API
463
+ // to demonstrate the ergonomics gain.
464
+
465
+ test('old way vs new way: read nested data', async () => {
466
+ const tree = await seedRealWorld()
467
+
468
+ // OLD: 3 lines, manual path construction, no types
469
+ const node = await tree.get('/board/landing')
470
+ assert.ok(node)
471
+ const title = node.title
472
+
473
+ // NEW: 1 expression, dot navigation
474
+ const title2 = (await treeChain(tree).board.landing).title
475
+
476
+ assert.equal(title, title2)
477
+ })
478
+
479
+ test('old way vs new way: follow ref + action', async () => {
480
+ const tree = await seedRealWorld()
481
+
482
+ // OLD: manual ref resolution, 4+ lines
483
+ const agentNode = await tree.get('/agent')
484
+ assert.ok(agentNode)
485
+ const botRef = (agentNode as any).bot
486
+ assert.ok(isRef(botRef))
487
+ // would need: const bot = await tree.get(botRef.$ref)
488
+ // then: executeAction(tree, botRef.$ref, ..., 'restart')
489
+
490
+ // NEW: one chain — navigate, follow ref, call action
491
+ const result = await treeChain(tree).agent.$get(AgentConfig).bot.restart()
492
+ assert.deepEqual(result, { restarted: true })
493
+ })
494
+ })
495
+
496
+ describe('treeChain — $set', () => {
497
+ test('creates node with type from class', async () => {
498
+ const tree = createMemoryTree()
499
+ await treeChain(tree).status.$set(LivePrices, { feederUrl: 'ws://example.com' })
500
+ const node = await tree.get('/status')
501
+ assert.ok(node)
502
+ assert.equal(node.$type, 'tch.live-prices')
503
+ assert.equal(node.feederUrl, 'ws://example.com')
504
+ })
505
+
506
+ test('overwrites existing node', async () => {
507
+ const tree = await seed()
508
+ await treeChain(tree).services.scanner.$set(Scanner, { intervalMs: 5000, maxRetries: 1 })
509
+ const node = await tree.get('/services/scanner')
510
+ assert.equal(node!.intervalMs, 5000)
511
+ assert.equal(node!.maxRetries, 1)
512
+ })
513
+
514
+ test('deep path via dot navigation', async () => {
515
+ const tree = createMemoryTree()
516
+ await treeChain(tree).a.b.c.$set(Profile, { name: 'Deep', balance: 42 })
517
+ const node = await tree.get('/a/b/c')
518
+ assert.ok(node)
519
+ assert.equal(node.$type, 'tch.profile')
520
+ assert.equal(node.name, 'Deep')
521
+ assert.equal(node.balance, 42)
522
+ })
523
+
524
+ test('no data — creates node with just type', async () => {
525
+ const tree = createMemoryTree()
526
+ await treeChain(tree).board.$set(BoardKanban)
527
+ const node = await tree.get('/board')
528
+ assert.ok(node)
529
+ assert.equal(node.$type, 'tch.board.kanban')
530
+ })
531
+
532
+ test('$set then read back via chain', async () => {
533
+ const tree = createMemoryTree()
534
+ const t = treeChain(tree)
535
+ await t.users.bob.$set(Profile, { name: 'Bob', balance: 250 })
536
+ const bob = await t.users.bob
537
+ assert.equal(bob.name, 'Bob')
538
+ assert.equal(bob.balance, 250)
539
+ })
540
+
541
+ test('$set with ref field', async () => {
542
+ const tree = createMemoryTree()
543
+ await treeChain(tree).brahman.$set(BrahmanBot, { alias: '@bot', running: true })
544
+ await treeChain(tree).agent.$set(AgentConfig, {
545
+ model: 'opus',
546
+ bot: { $type: 'ref', $ref: '/brahman' },
547
+ })
548
+ const bot = await treeChain(tree).agent(AgentConfig).bot
549
+ assert.equal(bot.alias, '@bot')
550
+ })
551
+ })
552
+
553
+ describe('treeChain — Symbol traps', () => {
554
+ test('Symbol.toPrimitive on root', () => {
555
+ assert.equal((treeChain(null as any) as any)[Symbol.toPrimitive], 'TreeChain(/)')
556
+ })
557
+
558
+ test('Symbol.toStringTag', () => {
559
+ const c = treeChain(null as any) as any
560
+ assert.equal(c.foo[Symbol.toStringTag], 'TreeChain(/foo)')
561
+ })
562
+
563
+ test('other symbols return undefined', () => {
564
+ const c = treeChain(null as any) as any
565
+ assert.equal(c[Symbol.iterator], undefined)
566
+ assert.equal(c[Symbol.asyncIterator], undefined)
567
+ })
568
+ })
569
+
570
+ describe('treeChain — basePath edge cases', () => {
571
+ test('basePath without leading slash', () => {
572
+ const c = treeChain(null as any, 'services/scanner')
573
+ assert.equal(c.$path, '/services/scanner')
574
+ })
575
+
576
+ test('basePath await resolves directly', async () => {
577
+ const tree = await seed()
578
+ const node = await treeChain(tree, '/services/scanner')
579
+ assert.equal(node.$type, 'tch.scanner')
580
+ assert.equal(node.intervalMs, 900_000)
581
+ })
582
+
583
+ test('basePath + child nav', async () => {
584
+ const tree = await seed()
585
+ const node = await treeChain(tree, '/services').scanner
586
+ assert.equal(node.$type, 'tch.scanner')
587
+ })
588
+ })
589
+
590
+ describe('treeChain — error paths', () => {
591
+ test('action without (Class) throws', async () => {
592
+ const tree = await seed()
593
+ const t = treeChain(tree) as any
594
+ await assert.rejects(
595
+ async () => { await t.services.scanner.scan() },
596
+ (e: Error) => e.message.includes('Class'),
597
+ )
598
+ })
599
+
600
+ test('unregistered action throws', async () => {
601
+ const tree = await seed()
602
+ const t = treeChain(tree) as any
603
+ await assert.rejects(
604
+ async () => { await t.services.scanner(Scanner).nonexistent() },
605
+ (e: Error) => e.message.includes('action'),
606
+ )
607
+ })
608
+
609
+ test('null field in ops throws', async () => {
610
+ const tree = await seed()
611
+ const t = treeChain(tree) as any
612
+ await assert.rejects(
613
+ async () => { await t.services.scanner.$get(Scanner).noSuchField },
614
+ (e: Error) => e.message.includes('null'),
615
+ )
616
+ })
617
+
618
+ test('$field with missing named component throws', async () => {
619
+ const tree = await seed()
620
+ await assert.rejects(
621
+ async () => { await treeChain(tree).services.scanner.$field('ghost') },
622
+ (e: Error) => e.message.includes('ghost'),
623
+ )
624
+ })
625
+
626
+ test('await root of empty tree throws', async () => {
627
+ const tree = createMemoryTree()
628
+ await assert.rejects(async () => { await treeChain(tree) })
629
+ })
630
+ })
631
+
632
+ describe('treeChain — (Class) where node.$type matches', () => {
633
+ test('getComponent returns node itself when $type matches', async () => {
634
+ const tree = await seed()
635
+ // scanner.$type === 'tch.scanner', Scanner.$type === 'tch.scanner'
636
+ // getComponent returns node itself — all fields at node level
637
+ const node = await treeChain(tree).services.scanner
638
+ assert.equal(node.$type, 'tch.scanner')
639
+ assert.equal(node.$path, '/services/scanner')
640
+ const scanner = await treeChain(tree).services.scanner(Scanner)
641
+ assert.equal(scanner.intervalMs, 900_000)
642
+ })
643
+ })
644
+
645
+ describe('treeChain — ref edge cases', () => {
646
+ test('ref without $type field is still followed', async () => {
647
+ const tree = createMemoryTree()
648
+ await tree.set({
649
+ $path: '/target',
650
+ $type: 'tch.live-prices',
651
+ feederUrl: 'ws://bare-ref',
652
+ })
653
+ await tree.set({
654
+ $path: '/source',
655
+ $type: 'tch.scanner',
656
+ intervalMs: 1,
657
+ maxRetries: 1,
658
+ // ref without $type — isRef accepts { $ref: string }
659
+ livePrices: { $ref: '/target' },
660
+ })
661
+ const lp = await treeChain(tree).source.$get(Scanner).livePrices
662
+ assert.equal(lp.feederUrl, 'ws://bare-ref')
663
+ })
664
+
665
+ test('ref field → then read field on resolved target', async () => {
666
+ const tree = await seed()
667
+ const url = await treeChain(tree).services.scanner(Scanner).livePrices.feederUrl
668
+ assert.equal(url, 'ws://localhost:8090')
669
+ })
670
+ })
671
+
672
+ describe('treeChain — multiple ops chain', () => {
673
+ test('field → field reads chain correctly', async () => {
674
+ const tree = createMemoryTree()
675
+ await tree.set({
676
+ $path: '/config',
677
+ $type: 'tch.scanner',
678
+ intervalMs: 1,
679
+ maxRetries: 1,
680
+ livePrices: { $type: 'ref', $ref: '/lp' },
681
+ nested: { $type: 'tch.wallet', address: '0x123', chain: 'polygon' },
682
+ })
683
+ await tree.set({ $path: '/lp', $type: 'tch.live-prices', feederUrl: 'ws://chain' })
684
+
685
+ // $get → field (nested component, not a ref) → field
686
+ const chain = await treeChain(tree).config.$field('nested').chain
687
+ assert.equal(chain, 'polygon')
688
+ })
689
+ })
690
+
691
+ describe('treeChain — chain isolation', () => {
692
+ test('two chains from same root are independent', async () => {
693
+ const tree = await seed()
694
+ const t = treeChain(tree)
695
+
696
+ const chain1 = t.services.scanner
697
+ const chain2 = t.services['live-prices']
698
+
699
+ const s = await chain1
700
+ const lp = await chain2
701
+ assert.equal(s.$type, 'tch.scanner')
702
+ assert.equal(lp.$type, 'tch.live-prices')
703
+ })
704
+
705
+ test('(Class) on one branch does not affect another', async () => {
706
+ const tree = await seed()
707
+ const services = treeChain(tree).services
708
+
709
+ const typed = await services.scanner(Scanner)
710
+ const raw = await services.scanner
711
+
712
+ assert.equal(typed.intervalMs, 900_000)
713
+ assert.equal(raw.intervalMs, 900_000)
714
+ assert.equal(raw.$type, 'tch.scanner')
715
+ })
716
+ })