trellis 3.1.35 → 3.2.2

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 (287) hide show
  1. package/CHANGELOG.md +23 -5
  2. package/README.md +63 -156
  3. package/bin/trellis.mjs +2 -75
  4. package/dist/{better-sqlite-backend-ahx5p0br.js → better-sqlite-backend-2P4F6AOJ.js} +91 -29
  5. package/dist/boot-middleware-MHLHFCUC.js +9 -0
  6. package/dist/browser/index.d.ts +18 -0
  7. package/dist/browser/index.d.ts.map +1 -0
  8. package/dist/browser/index.js +95 -0
  9. package/dist/{index-53f3b8p8.js → chunk-2W3MHTMG.js} +552 -213
  10. package/dist/chunk-44FFQKQX.js +142 -0
  11. package/dist/chunk-4HYPLFJD.js +150 -0
  12. package/dist/chunk-4XIVMVHC.js +361 -0
  13. package/dist/{index-yp88he8n.js → chunk-6CTA6MCE.js} +88 -64
  14. package/dist/chunk-6GEZ6DN5.js +394 -0
  15. package/dist/chunk-7ZFRVCUE.js +211 -0
  16. package/dist/chunk-CAG4FULI.js +121 -0
  17. package/dist/chunk-FF36CQHZ.js +61 -0
  18. package/dist/{index-h32txmxe.js → chunk-FKQO5A3H.js} +6 -13
  19. package/dist/{index-nq520y6k.js → chunk-FWRS4CSC.js} +46 -32
  20. package/dist/chunk-GFZCJ4EH.js +108 -0
  21. package/dist/chunk-GLM4HGN4.js +55 -0
  22. package/dist/{index-4cdr7x2x.js → chunk-GU374KWZ.js} +182 -111
  23. package/dist/chunk-H6JB3PZ3.js +45 -0
  24. package/dist/chunk-IZX2PLIB.js +1240 -0
  25. package/dist/chunk-J2TXUFCZ.js +289 -0
  26. package/dist/chunk-J3WYZO3Q.js +211 -0
  27. package/dist/{index-xzym9w0m.js → chunk-JA7AIHRK.js} +12 -7
  28. package/dist/chunk-JHHEXEDM.js +162 -0
  29. package/dist/chunk-JUEMDWLU.js +233 -0
  30. package/dist/chunk-KFQGP6VL.js +33 -0
  31. package/dist/chunk-KIJITUZB.js +419 -0
  32. package/dist/{index-4wxa8xz4.js → chunk-KQ4A2D2P.js} +162 -23
  33. package/dist/chunk-KSU2GW22.js +958 -0
  34. package/dist/{index-rv1p47gp.js → chunk-L5N5PR2S.js} +3015 -2480
  35. package/dist/{index-h9e2efx4.js → chunk-LNUIGRDZ.js} +71 -55
  36. package/dist/{index-skhn0agf.js → chunk-MLC5BUYO.js} +19 -20
  37. package/dist/chunk-MPXUVGT3.js +104 -0
  38. package/dist/chunk-N6MYZT4O.js +68 -0
  39. package/dist/chunk-O2AV5WMN.js +48 -0
  40. package/dist/chunk-PZ4XYZ4J.js +143 -0
  41. package/dist/chunk-QB5ISE47.js +419 -0
  42. package/dist/chunk-RSWUFTO2.js +857 -0
  43. package/dist/chunk-S3XLFZ27.js +1095 -0
  44. package/dist/{index-w5wccer3.js → chunk-S6GBJ2ZB.js} +28 -12
  45. package/dist/{index-7pjz3tsy.js → chunk-SGMDTWJJ.js} +57 -15
  46. package/dist/chunk-SPSPV5BC.js +390 -0
  47. package/dist/chunk-TCKXSOBP.js +123 -0
  48. package/dist/chunk-UBGUDMUV.js +59 -0
  49. package/dist/{index-wt8rz4gn.js → chunk-UQISRW6T.js} +97 -26
  50. package/dist/chunk-USEINYUL.js +12 -0
  51. package/dist/{index-bmyt7k8n.js → chunk-UZRUP7QW.js} +12 -4
  52. package/dist/{index-xhcp6xrn.js → chunk-VBYUTRXX.js} +695 -514
  53. package/dist/{index-vkpkfwhq.js → chunk-VDAKEOML.js} +234 -194
  54. package/dist/chunk-WXSWA3MV.js +0 -0
  55. package/dist/{index-n9f2qyh5.js → chunk-X5FLTRUB.js} +55 -33
  56. package/dist/{index-h7zxhhhh.js → chunk-XMQ7G77X.js} +46 -38
  57. package/dist/{index-w7ng765c.js → chunk-YCM7ZYEZ.js} +102 -49
  58. package/dist/cli/deploy-cli.d.ts +18 -0
  59. package/dist/cli/deploy-cli.d.ts.map +1 -0
  60. package/dist/cli/errors.d.ts +6 -0
  61. package/dist/cli/errors.d.ts.map +1 -0
  62. package/dist/cli/examples.d.ts +23 -0
  63. package/dist/cli/examples.d.ts.map +1 -0
  64. package/dist/cli/index.d.ts +1 -1
  65. package/dist/cli/index.d.ts.map +1 -1
  66. package/dist/cli/index.js +2426 -6225
  67. package/dist/client/index.browser.d.ts +29 -0
  68. package/dist/client/index.browser.d.ts.map +1 -0
  69. package/dist/client/index.browser.js +64 -0
  70. package/dist/client/index.d.ts +6 -1
  71. package/dist/client/index.d.ts.map +1 -1
  72. package/dist/client/index.js +41 -21
  73. package/dist/client/live.d.ts +67 -0
  74. package/dist/client/live.d.ts.map +1 -0
  75. package/dist/client/reactive.d.ts +31 -0
  76. package/dist/client/reactive.d.ts.map +1 -0
  77. package/dist/client/sdk.browser.d.ts +104 -0
  78. package/dist/client/sdk.browser.d.ts.map +1 -0
  79. package/dist/client/sdk.browser.js +9 -0
  80. package/dist/client/sdk.d.ts +26 -2
  81. package/dist/client/sdk.d.ts.map +1 -1
  82. package/dist/client/sdk.js +9 -0
  83. package/dist/client/vcs-client.d.ts +129 -0
  84. package/dist/client/vcs-client.d.ts.map +1 -0
  85. package/dist/cms/index.js +171 -163
  86. package/dist/{config-8hczw0rs.js → config-PFTP67TR.js} +8 -9
  87. package/dist/core/computation/index.d.ts +5 -0
  88. package/dist/core/computation/index.d.ts.map +1 -0
  89. package/dist/core/computation/rollup.d.ts +18 -0
  90. package/dist/core/computation/rollup.d.ts.map +1 -0
  91. package/dist/core/index.d.ts +5 -0
  92. package/dist/core/index.d.ts.map +1 -1
  93. package/dist/core/index.js +171 -104
  94. package/dist/core/kernel/boot-middleware.d.ts +10 -0
  95. package/dist/core/kernel/boot-middleware.d.ts.map +1 -0
  96. package/dist/core/kernel/logic-middleware.d.ts +7 -1
  97. package/dist/core/kernel/logic-middleware.d.ts.map +1 -1
  98. package/dist/core/kernel/trellis-kernel.d.ts.map +1 -1
  99. package/dist/core/ontology/types.d.ts +5 -0
  100. package/dist/core/ontology/types.d.ts.map +1 -1
  101. package/dist/core/persist/better-sqlite-backend.d.ts +9 -2
  102. package/dist/core/persist/better-sqlite-backend.d.ts.map +1 -1
  103. package/dist/core/persist/factory.d.ts +6 -7
  104. package/dist/core/persist/factory.d.ts.map +1 -1
  105. package/dist/core/persist/factory.js +2 -3
  106. package/dist/core/persist/sqljs-backend.js +2 -3
  107. package/dist/db/index.d.ts +4 -1
  108. package/dist/db/index.d.ts.map +1 -1
  109. package/dist/db/index.js +67 -54
  110. package/dist/db/inspector.js +11 -19
  111. package/dist/db/trellis.css +1 -1
  112. package/dist/decisions/index.js +9 -10
  113. package/dist/deploy-LQ7GUGJ5.js +9 -0
  114. package/dist/deploy-YNVG5E4E.js +9 -0
  115. package/dist/deploy-cli-24BCHAXY.js +67 -0
  116. package/dist/deploy-cli-C35HTITO.js +67 -0
  117. package/dist/embeddings/auto-embed.d.ts +2 -2
  118. package/dist/embeddings/auto-embed.d.ts.map +1 -1
  119. package/dist/embeddings/index.js +20 -22
  120. package/dist/embeddings/search.d.ts +2 -1
  121. package/dist/embeddings/search.d.ts.map +1 -1
  122. package/dist/embeddings/store.d.ts +25 -4
  123. package/dist/embeddings/store.d.ts.map +1 -1
  124. package/dist/engine.d.ts +59 -19
  125. package/dist/engine.d.ts.map +1 -1
  126. package/dist/import-UZEKXU3B.js +10 -0
  127. package/dist/index.js +102 -93
  128. package/dist/launch-explorer-HZ4ZJA4X.js +95 -0
  129. package/dist/links/index.js +24 -26
  130. package/dist/mcp/server.d.ts.map +1 -1
  131. package/dist/plugins/agent-memory/index.js +316 -0
  132. package/dist/plugins/idea-garden/index.js +165 -0
  133. package/dist/plugins/plan-approval/index.js +579 -0
  134. package/dist/plugins/proactive-watcher/index.js +194 -0
  135. package/dist/{index-2r4jxwnb.js → query-XYLTJYSA.js} +14 -15
  136. package/dist/react/index.js +39 -70
  137. package/dist/react/realtime.js +11 -0
  138. package/dist/react/schema-hooks.js +87 -0
  139. package/dist/realtime/broadcast-channel-transport.d.ts +43 -0
  140. package/dist/realtime/broadcast-channel-transport.d.ts.map +1 -0
  141. package/dist/realtime/durable-object-relay-transport.d.ts +96 -0
  142. package/dist/realtime/durable-object-relay-transport.d.ts.map +1 -0
  143. package/dist/realtime/index.d.ts +44 -0
  144. package/dist/realtime/index.d.ts.map +1 -0
  145. package/dist/realtime/index.js +40 -0
  146. package/dist/realtime/memory-hub.d.ts +32 -0
  147. package/dist/realtime/memory-hub.d.ts.map +1 -0
  148. package/dist/realtime/persistent-channel.d.ts +105 -0
  149. package/dist/realtime/persistent-channel.d.ts.map +1 -0
  150. package/dist/realtime/presence.d.ts +73 -0
  151. package/dist/realtime/presence.d.ts.map +1 -0
  152. package/dist/realtime/relay-persistence.d.ts +37 -0
  153. package/dist/realtime/relay-persistence.d.ts.map +1 -0
  154. package/dist/realtime/relay-persistence.js +107 -0
  155. package/dist/realtime/relay-server.d.ts +103 -0
  156. package/dist/realtime/relay-server.d.ts.map +1 -0
  157. package/dist/realtime/room.d.ts +98 -0
  158. package/dist/realtime/room.d.ts.map +1 -0
  159. package/dist/realtime/text.d.ts +73 -0
  160. package/dist/realtime/text.d.ts.map +1 -0
  161. package/dist/realtime/types.d.ts +89 -0
  162. package/dist/realtime/types.d.ts.map +1 -0
  163. package/dist/realtime/websocket-relay-transport.d.ts +28 -0
  164. package/dist/realtime/websocket-relay-transport.d.ts.map +1 -0
  165. package/dist/realtime.bundle.js +1100 -0
  166. package/dist/{remote-manager-xvbg4230.js → remote-manager-ODE3T2KR.js} +25 -15
  167. package/dist/scaffold/seed.d.ts.map +1 -1
  168. package/dist/scaffold/write.d.ts +1 -1
  169. package/dist/scaffold/write.d.ts.map +1 -1
  170. package/dist/schema/define.d.ts +137 -0
  171. package/dist/schema/define.d.ts.map +1 -0
  172. package/dist/schema/entity-projection.d.ts +34 -0
  173. package/dist/schema/entity-projection.d.ts.map +1 -0
  174. package/dist/schema/eql.d.ts +46 -0
  175. package/dist/schema/eql.d.ts.map +1 -0
  176. package/dist/schema/index.d.ts +21 -0
  177. package/dist/schema/index.d.ts.map +1 -0
  178. package/dist/schema/index.js +46 -0
  179. package/dist/schema/kernel-resolve.d.ts +21 -0
  180. package/dist/schema/kernel-resolve.d.ts.map +1 -0
  181. package/dist/schema/mutations.d.ts +20 -0
  182. package/dist/schema/mutations.d.ts.map +1 -0
  183. package/dist/schema/resolve.d.ts +21 -0
  184. package/dist/schema/resolve.d.ts.map +1 -0
  185. package/dist/server/deploy-meta.d.ts +25 -0
  186. package/dist/server/deploy-meta.d.ts.map +1 -0
  187. package/dist/server/deploy.d.ts +7 -2
  188. package/dist/server/deploy.d.ts.map +1 -1
  189. package/dist/server/index.d.ts +7 -2
  190. package/dist/server/index.d.ts.map +1 -1
  191. package/dist/server/index.js +100 -58
  192. package/dist/server/node-adapter.js +5 -104
  193. package/dist/server/realtime.d.ts +14 -3
  194. package/dist/server/realtime.d.ts.map +1 -1
  195. package/dist/server/server.d.ts +8 -16
  196. package/dist/server/server.d.ts.map +1 -1
  197. package/dist/server/sprites.d.ts +18 -1
  198. package/dist/server/sprites.d.ts.map +1 -1
  199. package/dist/server/tenancy.d.ts +4 -0
  200. package/dist/server/tenancy.d.ts.map +1 -1
  201. package/dist/server/usage-meter.d.ts +53 -0
  202. package/dist/server/usage-meter.d.ts.map +1 -0
  203. package/dist/server-MB3OPSPI.js +18 -0
  204. package/dist/server-ZVWGLLRF.js +18 -0
  205. package/dist/sprites-KQGTGM6W.js +27 -0
  206. package/dist/{sprites-vc4qbrp1.js → sprites-RU3E4XQN.js} +6 -7
  207. package/dist/svelte/index.d.ts +17 -0
  208. package/dist/svelte/index.d.ts.map +1 -0
  209. package/dist/svelte/index.js +51 -0
  210. package/dist/svelte/schema-hooks.d.ts +45 -0
  211. package/dist/svelte/schema-hooks.d.ts.map +1 -0
  212. package/dist/svelte/schema-hooks.js +71 -0
  213. package/dist/svelte/stores.d.ts +78 -0
  214. package/dist/svelte/stores.d.ts.map +1 -0
  215. package/dist/sync/http-transport.d.ts +3 -3
  216. package/dist/sync/http-transport.d.ts.map +1 -1
  217. package/dist/sync/index.d.ts +15 -1
  218. package/dist/sync/index.d.ts.map +1 -1
  219. package/dist/sync/index.js +617 -0
  220. package/dist/sync/memory-room.d.ts +37 -0
  221. package/dist/sync/memory-room.d.ts.map +1 -0
  222. package/dist/sync/memory-transport.d.ts +3 -3
  223. package/dist/sync/memory-transport.d.ts.map +1 -1
  224. package/dist/sync/partykit-room.d.ts +40 -0
  225. package/dist/sync/partykit-room.d.ts.map +1 -0
  226. package/dist/sync/partykit-transport.d.ts +84 -0
  227. package/dist/sync/partykit-transport.d.ts.map +1 -0
  228. package/dist/sync/room-core.d.ts +53 -0
  229. package/dist/sync/room-core.d.ts.map +1 -0
  230. package/dist/sync/sync-engine.d.ts +40 -2
  231. package/dist/sync/sync-engine.d.ts.map +1 -1
  232. package/dist/sync/sync-room-server.d.ts +39 -0
  233. package/dist/sync/sync-room-server.d.ts.map +1 -0
  234. package/dist/sync/types.d.ts +70 -3
  235. package/dist/sync/types.d.ts.map +1 -1
  236. package/dist/sync/vcs-sync-peer.d.ts +63 -0
  237. package/dist/sync/vcs-sync-peer.d.ts.map +1 -0
  238. package/dist/sync/ws-transport.d.ts +2 -2
  239. package/dist/sync/ws-transport.d.ts.map +1 -1
  240. package/dist/tenancy-NBLLGCNJ.js +14 -0
  241. package/dist/tenancy-POMWQP6M.js +16 -0
  242. package/dist/ui/client.html +355 -67
  243. package/dist/ui/launch-explorer.d.ts +22 -0
  244. package/dist/ui/launch-explorer.d.ts.map +1 -0
  245. package/dist/ui/server.d.ts +1 -1
  246. package/dist/ui/server.d.ts.map +1 -1
  247. package/dist/vcs/blob-store.d.ts.map +1 -1
  248. package/dist/vcs/idb-op-log.d.ts +67 -0
  249. package/dist/vcs/idb-op-log.d.ts.map +1 -0
  250. package/dist/vcs/index.d.ts +1 -0
  251. package/dist/vcs/index.d.ts.map +1 -1
  252. package/dist/vcs/index.js +81 -72
  253. package/dist/vcs/issue.d.ts +22 -5
  254. package/dist/vcs/issue.d.ts.map +1 -1
  255. package/dist/vcs/lane-materialize.d.ts +5 -0
  256. package/dist/vcs/lane-materialize.d.ts.map +1 -1
  257. package/dist/vcs/op-log.d.ts +28 -2
  258. package/dist/vcs/op-log.d.ts.map +1 -1
  259. package/dist/vcs/ops.d.ts +10 -0
  260. package/dist/vcs/ops.d.ts.map +1 -1
  261. package/dist/vcs/types.d.ts +2 -0
  262. package/dist/vcs/types.d.ts.map +1 -1
  263. package/dist/{vm-config-6xhsj6b3.js → vm-config-JI4OXKDQ.js} +9 -10
  264. package/dist/vue/hooks.d.ts +64 -0
  265. package/dist/vue/hooks.d.ts.map +1 -0
  266. package/dist/vue/index.d.ts +19 -0
  267. package/dist/vue/index.d.ts.map +1 -0
  268. package/dist/vue/index.js +59 -0
  269. package/dist/vue/schema-hooks.d.ts +41 -0
  270. package/dist/vue/schema-hooks.d.ts.map +1 -0
  271. package/dist/vue/schema-hooks.js +64 -0
  272. package/package.json +130 -17
  273. package/dist/deploy-999q207z.js +0 -10
  274. package/dist/engine-y0724kjq.js +0 -8
  275. package/dist/import-s2b8e0ft.js +0 -11
  276. package/dist/index-a76rekgs.js +0 -67
  277. package/dist/index-c9h37r6h.js +0 -1
  278. package/dist/index-hr9qvv77.js +0 -860
  279. package/dist/index-k5b0xskw.js +0 -1
  280. package/dist/index-nzb3am4f.js +0 -80
  281. package/dist/index-wncptktd.js +0 -292
  282. package/dist/index-y6a4kj0p.js +0 -43
  283. package/dist/index-yhwjgfvj.js +0 -342
  284. package/dist/sdk-bepky0xs.js +0 -16
  285. package/dist/server-szdjx0nt.js +0 -13
  286. package/dist/sqlite-backend-0vsmc6qj.js +0 -8
  287. package/dist/tenancy-pjm32b4v.js +0 -14
@@ -80,14 +80,44 @@ body{font-family:var(--font);background:var(--bg);color:var(--text);overflow:hid
80
80
  .cmd-item .ci-type{font:500 9px var(--mono);color:var(--text3);text-transform:uppercase;width:48px;flex-shrink:0}
81
81
  .cmd-item .ci-label{font:400 13px var(--font);color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
82
82
 
83
- /* ─── Graph Panel ─── */
84
- #graph-panel svg{width:100%;height:100%}
85
- .graph-controls{position:absolute;bottom:16px;right:16px;display:flex;flex-direction:column;gap:4px}
86
- .graph-controls button{width:32px;height:32px;background:var(--surface);border:1px solid var(--border);border-radius:6px;color:var(--text2);font-size:14px;cursor:pointer;display:flex;align-items:center;justify-content:center}
87
- .graph-controls button:hover{background:var(--surface2);color:var(--text)}
88
- .graph-legend{position:absolute;bottom:16px;left:16px;display:flex;gap:12px;font:400 11px var(--font);color:var(--text3)}
89
- .legend-item{display:flex;align-items:center;gap:5px}
90
- .legend-dot{width:7px;height:7px;border-radius:50%}
83
+ /* ─── Graph Panel (Studio GraphView parity) ─── */
84
+ #graph-panel.panel.active{display:flex;flex-direction:column;padding:0;overflow:hidden}
85
+ .graph-layout{display:flex;flex:1;min-height:0;overflow:hidden}
86
+ .graph-sidebar{width:200px;flex-shrink:0;border-right:1px solid var(--border);background:var(--surface);display:flex;flex-direction:column;overflow:hidden}
87
+ .graph-sidebar-head{padding:10px 12px;border-bottom:1px solid var(--border);font:600 10px var(--font);letter-spacing:.08em;text-transform:uppercase;color:var(--text3)}
88
+ .graph-sidebar-meta{padding:8px 12px;font:400 11px var(--mono);color:var(--text3);border-bottom:1px solid var(--border)}
89
+ .graph-filter-list{flex:1;overflow-y:auto;padding:8px;display:flex;flex-direction:column;gap:4px}
90
+ .graph-type-pill{display:flex;align-items:center;gap:8px;width:100%;padding:6px 8px;border:1px solid transparent;border-radius:8px;background:transparent;color:var(--text2);font:500 11px var(--font);cursor:pointer;text-align:left;transition:background .12s,border-color .12s,opacity .12s}
91
+ .graph-type-pill:hover{background:var(--surface2)}
92
+ .graph-type-pill.active{background:var(--accent-glow);border-color:rgba(109,91,250,.35);color:var(--text)}
93
+ .graph-type-pill.dimmed{opacity:.35}
94
+ .graph-type-pill .dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
95
+ .graph-type-pill .name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
96
+ .graph-type-pill .count{font:500 10px var(--mono);color:var(--text3)}
97
+ .graph-canvas-wrap{position:relative;flex:1;min-width:0;min-height:0;background:var(--bg2)}
98
+ .graph-canvas-wrap svg{width:100%;height:100%;display:block;touch-action:none}
99
+ .graph-tooltip{position:absolute;pointer-events:none;z-index:20;display:none;padding:8px 10px;border-radius:8px;font:400 11px/1.4 var(--font);background:color-mix(in srgb,var(--surface) 88%,transparent);backdrop-filter:blur(8px);border:1px solid var(--border2);color:var(--text);box-shadow:0 6px 20px rgba(0,0,0,.4);max-width:min(360px,90vw);opacity:0;transform:translateY(2px);transition:opacity 80ms ease-out,transform 80ms ease-out}
100
+ .graph-tooltip.visible{display:block;opacity:1;transform:translateY(0)}
101
+ .graph-tooltip .gt-type{font:600 9px var(--mono);text-transform:uppercase;letter-spacing:.06em;color:var(--text3);margin-bottom:2px}
102
+ .graph-tooltip .gt-label{font-weight:500}
103
+ .graph-minimap{position:absolute;left:12px;bottom:12px;z-index:15;border:1px solid var(--border);border-radius:6px;background:color-mix(in srgb,var(--surface) 90%,transparent);box-shadow:0 2px 10px rgba(0,0,0,.35);cursor:pointer;transition:opacity .18s}
104
+ .graph-chrome{position:absolute;left:12px;bottom:144px;z-index:16;width:180px;border:1px solid var(--border);border-radius:8px;background:color-mix(in srgb,var(--surface) 90%,transparent);backdrop-filter:blur(10px);box-shadow:0 4px 16px rgba(0,0,0,.35);overflow:hidden;transition:opacity .18s}
105
+ .graph-chrome.dimmed,.graph-minimap.dimmed{opacity:.12;pointer-events:none}
106
+ .graph-chrome-head{display:flex;align-items:center;justify-content:space-between;padding:6px 8px;border-bottom:1px solid var(--border);font:600 10px var(--font);letter-spacing:.06em;text-transform:uppercase;color:var(--text3)}
107
+ .graph-chrome-head button{background:none;border:none;color:var(--text3);font:500 10px var(--font);cursor:pointer;padding:2px 6px;border-radius:4px}
108
+ .graph-chrome-head button:hover{color:var(--text);background:var(--surface2)}
109
+ .graph-chrome-body{padding:6px 8px 8px;display:flex;flex-direction:column;gap:6px}
110
+ .graph-chrome-body button{width:100%;padding:6px 8px;border-radius:6px;border:1px solid var(--border);background:var(--bg);color:var(--text2);font:500 11px var(--font);cursor:pointer}
111
+ .graph-chrome-body button:hover{border-color:var(--accent);color:var(--accent2)}
112
+ .graph-beacon{position:absolute;z-index:25;display:none;align-items:center;justify-content:center;width:40px;height:40px;padding:0;border-radius:999px;border:1px solid var(--border2);background:color-mix(in srgb,var(--surface) 92%,transparent);color:var(--text);box-shadow:0 4px 16px rgba(0,0,0,.4);cursor:pointer;transform:translate(-50%,-50%);transition:opacity .12s}
113
+ .graph-beacon.visible{display:flex}
114
+ .graph-controls{position:absolute;bottom:12px;right:12px;z-index:14;display:flex;flex-direction:column;gap:4px}
115
+ .graph-controls button{width:32px;height:32px;background:color-mix(in srgb,var(--surface) 92%,transparent);backdrop-filter:blur(8px);border:1px solid var(--border);border-radius:6px;color:var(--text2);font-size:14px;cursor:pointer;display:flex;align-items:center;justify-content:center}
116
+ .graph-controls button:hover{background:var(--surface2);color:var(--text);border-color:var(--border2)}
117
+ .graph-links line{stroke-linecap:round}
118
+ .graph-edge-labels text{font-family:var(--font);pointer-events:none}
119
+ @keyframes edgeFlow{to{stroke-dashoffset:-16}}
120
+ .graph-links line.edge-flow{animation:edgeFlow .5s linear infinite}
91
121
 
92
122
  /* ─── Timeline Panel ─── */
93
123
  #timeline-panel{padding:0}
@@ -194,8 +224,13 @@ body{font-family:var(--font);background:var(--bg);color:var(--text);overflow:hid
194
224
  // ─── State ───
195
225
  const S = { panel: 'graph', graph: null, timeline: null, store: null, system: null, cmdOpen: false, drawerOpen: false };
196
226
  const $ = id => document.getElementById(id);
197
- const TYPE_COLORS = { file:'#60a5fa', milestone:'#34d399', issue:'#fbbf24', branch:'#a78bfa', default:'#63637a' };
198
- const TYPE_RADIUS = { file:4, milestone:8, issue:7, branch:6, default:4 };
227
+ // Aligned with turtlecode/ide entity-theme (GraphView)
228
+ const ENTITY_COLORS = { file:'#14b8a6', milestone:'#3b82f6', issue:'#e879f9', branch:'#fde047', default:'#94a3b8' };
229
+ const GRAPH_LABEL_MIN_ZOOM = 0.65;
230
+ const GRAPH_MINIMAP_W = 180, GRAPH_MINIMAP_H = 120, GRAPH_MINIMAP_PAD = 6;
231
+ const EDGE_LABELS = { milestone_file:'includes', issue_branch:'branch', wikilink:'wikilink', causal:'causal' };
232
+ function nodeRadius(d){ if(d.type==='issue')return 12; if(d.type==='milestone')return 11; if(d.type==='branch')return 8; if(d.type==='file')return 7; return 6; }
233
+ function nodeColor(d){ return ENTITY_COLORS[d.type]||ENTITY_COLORS.default; }
199
234
 
200
235
  // ─── Panel Switching ───
201
236
  const tabs = document.querySelectorAll('.tab');
@@ -260,7 +295,7 @@ body{font-family:var(--font);background:var(--bg);color:var(--text);overflow:hid
260
295
  try{
261
296
  const res = await fetch('/api/node/'+encodeURIComponent(nodeId));
262
297
  const d = await res.json();
263
- let h = `<div class="d-section"><span class="d-badge" style="background:${TYPE_COLORS[d.type]||TYPE_COLORS.default}22;color:${TYPE_COLORS[d.type]||TYPE_COLORS.default}">${d.type}</span></div>`;
298
+ let h = `<div class="d-section"><span class="d-badge" style="background:${ENTITY_COLORS[d.type]||ENTITY_COLORS.default}22;color:${ENTITY_COLORS[d.type]||ENTITY_COLORS.default}">${d.type}</span></div>`;
264
299
  if(d.type==='file'){
265
300
  h += `<div class="d-section"><h4>Path</h4><div class="d-meta"><strong>${esc(d.path)}</strong></div></div>`;
266
301
  if(d.contentHash) h += `<div class="d-section"><h4>Hash</h4><div style="font:11px var(--mono);color:var(--text3);word-break:break-all">${d.contentHash}</div></div>`;
@@ -298,9 +333,120 @@ body{font-family:var(--font);background:var(--bg);color:var(--text);overflow:hid
298
333
  }
299
334
 
300
335
  // ═══════════════════════════════════════════════════════════════════════════
301
- // GRAPH PANEL
336
+ // GRAPH PANEL (Studio GraphView-style)
302
337
  // ═══════════════════════════════════════════════════════════════════════════
303
- let graphSim, graphZoom, graphSvg, graphG, graphNodes, graphLinks, graphLabels, graphNodeMap;
338
+ let graphSim, graphZoom, graphSvg, graphG, graphNodeGroups, graphLinks, graphLabels, graphEdgeLabels, graphNodeMap;
339
+ let graphCanvasWrap, graphZoomState = { k: 1, x: 0, y: 0 }, graphActiveFilters = null, graphMinimap, graphMinimapCtx, graphBeacon;
340
+
341
+ function buildGraphSidebar(nodes){
342
+ const counts = {};
343
+ nodes.forEach(n => { counts[n.type] = (counts[n.type]||0)+1; });
344
+ const types = Object.keys(counts).sort();
345
+ graphActiveFilters = new Set(types);
346
+ const sidebar = document.createElement('aside');
347
+ sidebar.className = 'graph-sidebar';
348
+ sidebar.innerHTML = `<div class="graph-sidebar-head">Entity types</div><div class="graph-sidebar-meta" id="graph-sidebar-meta"></div><div class="graph-filter-list" id="graph-filter-list"></div>`;
349
+ const list = sidebar.querySelector('#graph-filter-list');
350
+ const meta = sidebar.querySelector('#graph-sidebar-meta');
351
+ function refreshMeta(visible){
352
+ meta.textContent = visible + ' / ' + nodes.length + ' nodes';
353
+ }
354
+ function applyFilters(){
355
+ const on = graphActiveFilters;
356
+ let visible = 0;
357
+ graphNodeGroups?.attr('display', n => { const show = on.has(n.type); if(show) visible++; return show ? null : 'none'; });
358
+ graphLinks?.attr('stroke-opacity', l => {
359
+ const sid = typeof l.source==='object'?l.source.id:l.source;
360
+ const tid = typeof l.target==='object'?l.target.id:l.target;
361
+ const st = graphNodeMap?.get(sid)?.type;
362
+ const tt = graphNodeMap?.get(tid)?.type;
363
+ return (st && tt && on.has(st) && on.has(tt)) ? 0.18 : 0.02;
364
+ });
365
+ list.querySelectorAll('.graph-type-pill').forEach(p => p.classList.toggle('dimmed', !on.has(p.dataset.type)));
366
+ refreshMeta(visible);
367
+ }
368
+ types.forEach(t => {
369
+ const btn = document.createElement('button');
370
+ btn.type = 'button';
371
+ btn.className = 'graph-type-pill active';
372
+ btn.dataset.type = t;
373
+ btn.innerHTML = `<span class="dot" style="background:${ENTITY_COLORS[t]||ENTITY_COLORS.default}"></span><span class="name">${t}</span><span class="count">${counts[t]}</span>`;
374
+ btn.onclick = () => {
375
+ if(on.has(t) && on.size>1) on.delete(t); else on.add(t);
376
+ btn.classList.toggle('active', on.has(t));
377
+ applyFilters();
378
+ };
379
+ list.append(btn);
380
+ });
381
+ refreshMeta(nodes.length);
382
+ return { sidebar, applyFilters };
383
+ }
384
+
385
+ function paintGraphMinimap(simNodes){
386
+ if(!graphMinimapCtx) return;
387
+ const MAP_W = GRAPH_MINIMAP_W, MAP_H = GRAPH_MINIMAP_H, PAD = GRAPH_MINIMAP_PAD;
388
+ const mctx = graphMinimapCtx;
389
+ const wrap = graphCanvasWrap;
390
+ const w = wrap.clientWidth, h = wrap.clientHeight;
391
+ const zoom = graphZoomState;
392
+ mctx.clearRect(0, 0, MAP_W, MAP_H);
393
+ let minX=Infinity,minY=Infinity,maxX=-Infinity,maxY=-Infinity;
394
+ simNodes.forEach(n => {
395
+ const x=n.x??0,y=n.y??0;
396
+ if(x<minX)minX=x; if(y<minY)minY=y; if(x>maxX)maxX=x; if(y>maxY)maxY=y;
397
+ });
398
+ const vx0=-zoom.x/zoom.k, vy0=-zoom.y/zoom.k, vx1=(w-zoom.x)/zoom.k, vy1=(h-zoom.y)/zoom.k;
399
+ minX=Math.min(minX,vx0); minY=Math.min(minY,vy0); maxX=Math.max(maxX,vx1); maxY=Math.max(maxY,vy1);
400
+ if(!Number.isFinite(minX)){ minX=0;minY=0;maxX=w;maxY=h; }
401
+ const dx=maxX-minX||1, dy=maxY-minY||1;
402
+ const scale=Math.min((MAP_W-PAD*2)/dx,(MAP_H-PAD*2)/dy);
403
+ const toMap=(x,y)=>[PAD+(x-minX)*scale,PAD+(y-minY)*scale];
404
+ mctx.globalAlpha=.75;
405
+ simNodes.forEach(n => {
406
+ if(graphActiveFilters && !graphActiveFilters.has(n.type)) return;
407
+ const [mx,my]=toMap(n.x??0,n.y??0);
408
+ mctx.fillStyle=nodeColor(n);
409
+ mctx.beginPath(); mctx.arc(mx,my,1.2,0,Math.PI*2); mctx.fill();
410
+ });
411
+ mctx.globalAlpha=1;
412
+ const [rx,ry]=toMap(vx0,vy0), rw=(vx1-vx0)*scale, rh=(vy1-vy0)*scale;
413
+ mctx.fillStyle='rgba(0,0,0,.45)';
414
+ const mask=new Path2D();
415
+ mask.rect(0,0,MAP_W,MAP_H); mask.rect(rx,ry,rw,rh);
416
+ mctx.fill(mask,'evenodd');
417
+ mctx.strokeStyle='rgba(255,255,255,.85)'; mctx.lineWidth=1;
418
+ mctx.strokeRect(rx+.5,ry+.5,rw-1,rh-1);
419
+ updateGraphBeacon(simNodes, w, h);
420
+ }
421
+
422
+ function updateGraphBeacon(simNodes, w, h){
423
+ if(!graphBeacon) return;
424
+ const zoom=graphZoomState;
425
+ let minX=Infinity,minY=Infinity,maxX=-Infinity,maxY=-Infinity,cx=0,cy=0,n=0;
426
+ simNodes.forEach(nd => {
427
+ if(graphActiveFilters && !graphActiveFilters.has(nd.type)) return;
428
+ const x=nd.x??0,y=nd.y??0; cx+=x; cy+=y; n++;
429
+ if(x<minX)minX=x; if(y<minY)minY=y; if(x>maxX)maxX=x; if(y>maxY)maxY=y;
430
+ });
431
+ if(!n){ graphBeacon.classList.remove('visible'); return; }
432
+ cx/=n; cy/=n;
433
+ const vx0=-zoom.x/zoom.k, vy0=-zoom.y/zoom.k, vx1=(w-zoom.x)/zoom.k, vy1=(h-zoom.y)/zoom.k;
434
+ const offscreen = maxX<vx0||minX>vx1||maxY<vy0||minY>vy1;
435
+ if(!offscreen){ graphBeacon.classList.remove('visible'); return; }
436
+ const sx=cx*zoom.k+zoom.x, sy=cy*zoom.k+zoom.y;
437
+ const pad=56, hw=Math.max(24,w/2-pad), hh=Math.max(24,h/2-pad);
438
+ const dx=sx-w/2, dy=sy-h/2;
439
+ const sc=Math.min(Math.abs(hw/(dx||1e-6)),Math.abs(hh/(dy||1e-6)));
440
+ graphBeacon.style.left=(w/2+dx*sc)+'px';
441
+ graphBeacon.style.top=(h/2+dy*sc)+'px';
442
+ graphBeacon.classList.add('visible');
443
+ }
444
+
445
+ function updateLabelVisibility(){
446
+ const show = graphZoomState.k >= GRAPH_LABEL_MIN_ZOOM;
447
+ graphLabels?.attr('opacity', show ? 0.85 : 0);
448
+ graphEdgeLabels?.attr('opacity', show ? 0.35 : 0);
449
+ }
304
450
 
305
451
  async function initGraph(){
306
452
  try{ const r = await fetch('/api/graph'); S.graph = await r.json(); }
@@ -310,75 +456,217 @@ body{font-family:var(--font);background:var(--bg);color:var(--text);overflow:hid
310
456
  buildCmdItems();
311
457
 
312
458
  const container = $('graph-panel');
313
- const w = container.clientWidth, h = container.clientHeight;
314
-
315
- const svg = d3.select('#graph-panel').append('svg').attr('width', w).attr('height', h);
459
+ container.innerHTML = '';
460
+ const layout = document.createElement('div');
461
+ layout.className = 'graph-layout';
462
+ const { sidebar, applyFilters } = buildGraphSidebar(nodes);
463
+ graphCanvasWrap = document.createElement('div');
464
+ graphCanvasWrap.className = 'graph-canvas-wrap';
465
+ graphCanvasWrap.id = 'graph-canvas-wrap';
466
+ layout.append(sidebar, graphCanvasWrap);
467
+ container.append(layout);
468
+
469
+ const w = graphCanvasWrap.clientWidth || 800, h = graphCanvasWrap.clientHeight || 600;
470
+ const svg = d3.select(graphCanvasWrap).append('svg').attr('width', w).attr('height', h);
316
471
  graphSvg = svg;
317
472
  const g = svg.append('g');
318
473
  graphG = g;
319
- graphZoom = d3.zoom().scaleExtent([0.1,8]).on('zoom', e => g.attr('transform', e.transform));
474
+ graphZoom = d3.zoom().scaleExtent([0.05, 4]).on('zoom', e => {
475
+ g.attr('transform', e.transform);
476
+ graphZoomState = { k: e.transform.k, x: e.transform.x, y: e.transform.y };
477
+ updateLabelVisibility();
478
+ paintGraphMinimap(simNodes);
479
+ });
320
480
  svg.call(graphZoom);
481
+ svg.on('click', () => { clearGraphHighlight(); drawer.classList.remove('open'); });
321
482
 
322
483
  const simLinks = edges.map(e => ({...e}));
323
484
  const simNodes = nodes.map(n => ({...n}));
324
485
  graphNodeMap = new Map(); simNodes.forEach(n => graphNodeMap.set(n.id, n));
325
486
 
487
+ const size = simNodes.length;
488
+ const dist = size > 800 ? 45 : size > 300 ? 60 : 90;
489
+ const charge = size > 800 ? -90 : size > 300 ? -130 : -220;
490
+
326
491
  graphSim = d3.forceSimulation(simNodes)
327
- .force('link', d3.forceLink(simLinks).id(d=>d.id).distance(55).strength(0.3))
328
- .force('charge', d3.forceManyBody().strength(-70).distanceMax(280))
492
+ .force('link', d3.forceLink(simLinks).id(d=>d.id).distance(dist).strength(0.35))
493
+ .force('charge', d3.forceManyBody().strength(charge).distanceMax(400))
329
494
  .force('center', d3.forceCenter(w/2, h/2))
330
- .force('collision', d3.forceCollide().radius(d=>(TYPE_RADIUS[d.type]||4)+2))
331
- .force('x', d3.forceX(w/2).strength(0.03))
332
- .force('y', d3.forceY(h/2).strength(0.03));
495
+ .force('collision', d3.forceCollide().radius(d => nodeRadius(d) + 4))
496
+ .alphaDecay(0.04).alphaMin(0.02);
497
+
498
+ graphLinks = g.append('g').attr('class','graph-links').selectAll('line').data(simLinks).join('line')
499
+ .attr('stroke', 'var(--text3)')
500
+ .attr('stroke-width', 1)
501
+ .attr('stroke-opacity', 0.18)
502
+ .attr('stroke-dasharray', d => d.type==='wikilink' ? '3,3' : null);
503
+
504
+ graphEdgeLabels = g.append('g').attr('class','graph-edge-labels').selectAll('text').data(simLinks).join('text')
505
+ .text(d => EDGE_LABELS[d.type] || d.type)
506
+ .attr('font-size', 9).attr('font-weight', 500).attr('fill', 'var(--text2)')
507
+ .attr('stroke', 'var(--bg)').attr('stroke-width', 3).attr('paint-order', 'stroke')
508
+ .attr('text-anchor', 'middle').attr('dy', '0.35em').attr('opacity', 0);
509
+
510
+ graphNodeGroups = g.append('g').attr('class','graph-nodes').selectAll('g').data(simNodes).join('g')
511
+ .attr('cursor', 'pointer')
512
+ .call(d3.drag().on('start',(e,d)=>{if(!e.active)graphSim.alphaTarget(.25).restart();d.fx=d.x;d.fy=d.y})
513
+ .on('drag',(e,d)=>{d.fx=e.x;d.fy=e.y})
514
+ .on('end',(e,d)=>{if(!e.active)graphSim.alphaTarget(0);d.fx=null;d.fy=null}));
515
+
516
+ graphNodeGroups.append('circle')
517
+ .attr('r', d => nodeRadius(d))
518
+ .attr('fill', d => nodeColor(d))
519
+ .attr('stroke', 'transparent').attr('stroke-width', 2);
520
+
521
+ graphLabels = graphNodeGroups.append('text')
522
+ .text(d => d.label.length > 24 ? d.label.slice(0, 24) + '…' : d.label)
523
+ .attr('font-size', 10).attr('fill', 'var(--text2)')
524
+ .attr('x', d => nodeRadius(d) + 5).attr('dy', 4)
525
+ .attr('pointer-events', 'none').attr('opacity', 0)
526
+ .attr('font-family', 'Inter,sans-serif');
527
+
528
+ const graphTip = document.createElement('div');
529
+ graphTip.className = 'graph-tooltip';
530
+ graphCanvasWrap.appendChild(graphTip);
531
+
532
+ graphNodeGroups.on('mouseenter', (e, d) => {
533
+ graphTip.innerHTML = `<div class="gt-type">${d.type}</div><div class="gt-label">${esc(d.label)}</div>`;
534
+ graphTip.classList.add('visible');
535
+ graphTip.style.left = (e.offsetX + 14) + 'px';
536
+ graphTip.style.top = (e.offsetY + 10) + 'px';
537
+ $('tooltip').style.display = 'none';
538
+ }).on('mousemove', (e) => {
539
+ graphTip.style.left = (e.offsetX + 14) + 'px';
540
+ graphTip.style.top = (e.offsetY + 10) + 'px';
541
+ }).on('mouseleave', () => graphTip.classList.remove('visible'))
542
+ .on('click', (e, d) => { e.stopPropagation(); highlightGraphNode(d); loadNodeDetail(d.id); });
333
543
 
334
- graphLinks = g.append('g').selectAll('line').data(simLinks).join('line')
335
- .attr('stroke', d => d.type==='wikilink'?'#60a5fa33':d.type==='milestone_file'?'#34d39933':d.type==='issue_branch'?'#fbbf2433':'#25262e')
336
- .attr('stroke-width', d => d.type==='wikilink'?1.2:0.7);
544
+ graphSim.on('tick', () => {
545
+ graphLinks
546
+ .attr('x1', d => d.source.x).attr('y1', d => d.source.y)
547
+ .attr('x2', d => d.target.x).attr('y2', d => d.target.y);
548
+ graphNodeGroups.attr('transform', d => `translate(${d.x},${d.y})`);
549
+ graphEdgeLabels
550
+ .attr('x', d => (d.source.x + d.target.x) / 2)
551
+ .attr('y', d => (d.source.y + d.target.y) / 2);
552
+ paintGraphMinimap(simNodes);
553
+ });
337
554
 
338
- graphNodes = g.append('g').selectAll('circle').data(simNodes).join('circle')
339
- .attr('r', d => TYPE_RADIUS[d.type]||4)
340
- .attr('fill', d => TYPE_COLORS[d.type]||TYPE_COLORS.default)
341
- .attr('cursor','pointer')
342
- .call(d3.drag().on('start',(e,d)=>{if(!e.active)graphSim.alphaTarget(.3).restart();d.fx=d.x;d.fy=d.y}).on('drag',(e,d)=>{d.fx=e.x;d.fy=e.y}).on('end',(e,d)=>{if(!e.active)graphSim.alphaTarget(0);d.fx=null;d.fy=null}));
555
+ // Minimap
556
+ graphMinimap = document.createElement('canvas');
557
+ graphMinimap.className = 'graph-minimap';
558
+ graphMinimap.width = GRAPH_MINIMAP_W * (devicePixelRatio||1);
559
+ graphMinimap.height = GRAPH_MINIMAP_H * (devicePixelRatio||1);
560
+ graphMinimap.style.width = GRAPH_MINIMAP_W + 'px';
561
+ graphMinimap.style.height = GRAPH_MINIMAP_H + 'px';
562
+ graphMinimapCtx = graphMinimap.getContext('2d');
563
+ graphMinimapCtx.scale(devicePixelRatio||1, devicePixelRatio||1);
564
+ graphCanvasWrap.appendChild(graphMinimap);
565
+
566
+ function panToWorld(wx, wy){
567
+ const k = graphZoomState.k;
568
+ svg.transition().duration(280).call(graphZoom.transform, d3.zoomIdentity.translate(w/2 - wx*k, h/2 - wy*k).scale(k));
569
+ }
570
+ function minimapPoint(evt){
571
+ const rect = graphMinimap.getBoundingClientRect();
572
+ const mx = evt.clientX - rect.left, my = evt.clientY - rect.top;
573
+ let minX=Infinity,minY=Infinity,maxX=-Infinity,maxY=-Infinity;
574
+ simNodes.forEach(n => { const x=n.x??0,y=n.y??0; if(x<minX)minX=x; if(y<minY)minY=y; if(x>maxX)maxX=x; if(y>maxY)maxY=y; });
575
+ const dx=maxX-minX||1, dy=maxY-minY||1;
576
+ const scale=Math.min((GRAPH_MINIMAP_W-GRAPH_MINIMAP_PAD*2)/dx,(GRAPH_MINIMAP_H-GRAPH_MINIMAP_PAD*2)/dy);
577
+ return [(mx-GRAPH_MINIMAP_PAD)/scale+minX, (my-GRAPH_MINIMAP_PAD)/scale+minY];
578
+ }
579
+ graphMinimap.addEventListener('mousedown', e => { e.preventDefault(); panToWorld(...minimapPoint(e)); });
580
+ graphMinimap.addEventListener('mousemove', e => { if(e.buttons===1) panToWorld(...minimapPoint(e)); });
581
+
582
+ // Return-to-graph beacon
583
+ graphBeacon = document.createElement('button');
584
+ graphBeacon.type = 'button';
585
+ graphBeacon.className = 'graph-beacon';
586
+ graphBeacon.setAttribute('aria-label', 'Return to graph');
587
+ graphBeacon.innerHTML = '<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>';
588
+ graphBeacon.onclick = e => { e.stopPropagation(); fitGraph(); };
589
+ graphCanvasWrap.appendChild(graphBeacon);
590
+
591
+ // Graph chrome (fit / reset)
592
+ const chrome = document.createElement('div');
593
+ chrome.className = 'graph-chrome';
594
+ chrome.innerHTML = '<div class="graph-chrome-head"><span>Graph</span><button type="button" id="graph-chrome-reset">Reset</button></div><div class="graph-chrome-body"><button type="button" id="graph-chrome-fit">Fit to view</button></div>';
595
+ graphCanvasWrap.appendChild(chrome);
596
+ chrome.querySelector('#graph-chrome-fit').onclick = () => fitGraph();
597
+ chrome.querySelector('#graph-chrome-reset').onclick = () => { simNodes.forEach(n => { n.fx=null; n.fy=null; }); graphSim.alpha(0.6).restart(); };
598
+
599
+ const ctrlDiv = document.createElement('div');
600
+ ctrlDiv.className = 'graph-controls';
601
+ ctrlDiv.innerHTML = '<button id="gz-in" title="Zoom in">+</button><button id="gz-out" title="Zoom out">−</button><button id="gz-fit" title="Fit">⊙</button>';
602
+ graphCanvasWrap.appendChild(ctrlDiv);
603
+ $('gz-in').onclick = () => svg.transition().duration(200).call(graphZoom.scaleBy, 1.4);
604
+ $('gz-out').onclick = () => svg.transition().duration(200).call(graphZoom.scaleBy, 0.72);
605
+ $('gz-fit').onclick = () => fitGraph();
606
+
607
+ applyFilters();
608
+ graphSim.on('end', () => { fitGraph(); updateLabelVisibility(); });
609
+
610
+ const onResize = () => {
611
+ const nw = graphCanvasWrap.clientWidth, nh = graphCanvasWrap.clientHeight;
612
+ svg.attr('width', nw).attr('height', nh);
613
+ graphSim.force('center', d3.forceCenter(nw/2, nh/2));
614
+ paintGraphMinimap(simNodes);
615
+ };
616
+ window.addEventListener('resize', onResize);
617
+ }
343
618
 
344
- graphLabels = g.append('g').selectAll('text').data(simNodes.filter(d=>d.type!=='file')).join('text')
345
- .text(d => d.label.length>22?d.label.slice(0,22)+'…':d.label)
346
- .attr('font-size',10).attr('fill',d=>TYPE_COLORS[d.type]||'#63637a').attr('dx',d=>(TYPE_RADIUS[d.type]||4)+4).attr('dy',3).attr('pointer-events','none').attr('opacity',.8).attr('font-family','Inter,sans-serif');
619
+ function fitGraph(){
620
+ if(!graphG?.node()) return;
621
+ const b = graphG.node().getBBox();
622
+ if(!b.width) return;
623
+ const w = graphCanvasWrap?.clientWidth || 800, h = graphCanvasWrap?.clientHeight || 600, p = 80;
624
+ const s = Math.min((w - p*2)/b.width, (h - p*2)/b.height, 2);
625
+ graphSvg.transition().duration(500).call(graphZoom.transform,
626
+ d3.zoomIdentity.translate(w/2, h/2).scale(s).translate(-b.x - b.width/2, -b.y - b.height/2));
627
+ }
347
628
 
348
- graphSim.on('tick', () => {
349
- graphLinks.attr('x1',d=>d.source.x).attr('y1',d=>d.source.y).attr('x2',d=>d.target.x).attr('y2',d=>d.target.y);
350
- graphNodes.attr('cx',d=>d.x).attr('cy',d=>d.y);
351
- graphLabels.attr('x',d=>d.x).attr('y',d=>d.y);
629
+ function highlightGraphNode(d){
630
+ const c = new Set([d.id]);
631
+ graphLinks.each(function(l){
632
+ const s = typeof l.source==='object'?l.source.id:l.source;
633
+ const t = typeof l.target==='object'?l.target.id:l.target;
634
+ if(s===d.id) c.add(t); if(t===d.id) c.add(s);
635
+ });
636
+ graphNodeGroups.attr('opacity', n => c.has(n.id) ? 1 : 0.15);
637
+ graphNodeGroups.select('circle').attr('stroke', n => c.has(n.id) ? '#fff' : 'transparent').attr('stroke-width', n => c.has(n.id) ? 2.5 : 0);
638
+ graphLinks.each(function(l){
639
+ const s = typeof l.source==='object'?l.source.id:l.source;
640
+ const t = typeof l.target==='object'?l.target.id:l.target;
641
+ const on = (s===d.id||t===d.id);
642
+ d3.select(this).classed('edge-flow', on).attr('stroke-opacity', on ? 0.75 : 0.04);
643
+ });
644
+ graphLabels.attr('opacity', n => c.has(n.id) ? 1 : 0.1);
645
+ graphEdgeLabels.attr('opacity', l => {
646
+ const s = typeof l.source==='object'?l.source.id:l.source;
647
+ const t = typeof l.target==='object'?l.target.id:l.target;
648
+ return (s===d.id||t===d.id) && graphZoomState.k >= GRAPH_LABEL_MIN_ZOOM ? 0.9 : 0;
352
649
  });
650
+ }
651
+
652
+ function clearGraphHighlight(){
653
+ graphNodeGroups?.attr('opacity', 1);
654
+ graphNodeGroups?.select('circle').attr('stroke', 'transparent');
655
+ graphLinks?.attr('stroke-opacity', 0.18).classed('edge-flow', false);
656
+ graphLabels?.attr('opacity', graphZoomState.k >= GRAPH_LABEL_MIN_ZOOM ? 0.85 : 0);
657
+ graphEdgeLabels?.attr('opacity', graphZoomState.k >= GRAPH_LABEL_MIN_ZOOM ? 0.35 : 0);
658
+ }
353
659
 
354
- // Tooltip
355
- const tip = $('tooltip');
356
- graphNodes.on('mouseover',(e,d)=>{tip.textContent=d.label;tip.style.display='block';tip.style.left=(e.clientX+12)+'px';tip.style.top=(e.clientY-8)+'px'})
357
- .on('mousemove',e=>{tip.style.left=(e.clientX+12)+'px';tip.style.top=(e.clientY-8)+'px'})
358
- .on('mouseout',()=>{tip.style.display='none'});
359
-
360
- // Click detail
361
- graphNodes.on('click',(e,d)=>{e.stopPropagation();highlightGraphNode(d);loadNodeDetail(d.id)});
362
- svg.on('click',()=>{clearGraphHighlight();drawer.classList.remove('open')});
363
-
364
- // Legend
365
- const legendHtml = Object.entries(TYPE_COLORS).filter(([k])=>k!=='default').map(([k,c])=>`<div class="legend-item"><div class="legend-dot" style="background:${c}"></div>${k}</div>`).join('');
366
- const legendDiv = document.createElement('div'); legendDiv.className='graph-legend'; legendDiv.innerHTML=legendHtml; container.appendChild(legendDiv);
367
-
368
- // Zoom controls
369
- const ctrlDiv = document.createElement('div'); ctrlDiv.className='graph-controls';
370
- ctrlDiv.innerHTML='<button id="gz-in">+</button><button id="gz-out">−</button><button id="gz-fit">⊙</button>';
371
- container.appendChild(ctrlDiv);
372
- $('gz-in').onclick=()=>svg.transition().duration(300).call(graphZoom.scaleBy,1.5);
373
- $('gz-out').onclick=()=>svg.transition().duration(300).call(graphZoom.scaleBy,0.67);
374
- $('gz-fit').onclick=()=>fitGraph();
375
-
376
- graphSim.on('end', fitGraph);
660
+ function focusGraphNode(id){
661
+ const n = graphNodeMap?.get(id);
662
+ if(!n) return;
663
+ switchPanel('graph');
664
+ highlightGraphNode(n);
665
+ loadNodeDetail(id);
666
+ const w = graphCanvasWrap?.clientWidth || 800, h = graphCanvasWrap?.clientHeight || 600;
667
+ graphSvg.transition().duration(450).call(graphZoom.transform,
668
+ d3.zoomIdentity.translate(w/2, h/2).scale(Math.max(graphZoomState.k, 1)).translate(-n.x, -n.y));
377
669
  }
378
- function fitGraph(){ const b=graphG.node().getBBox();if(!b.width)return;const w=$('graph-panel').clientWidth,h=$('graph-panel').clientHeight,p=50;const s=Math.min((w-p*2)/b.width,(h-p*2)/b.height,2);graphSvg.transition().duration(600).call(graphZoom.transform,d3.zoomIdentity.translate(w/2,h/2).scale(s).translate(-b.x-b.width/2,-b.y-b.height/2)); }
379
- function highlightGraphNode(d){ const c=new Set([d.id]);graphLinks.each(function(l){const s=typeof l.source==='object'?l.source.id:l.source;const t=typeof l.target==='object'?l.target.id:l.target;if(s===d.id)c.add(t);if(t===d.id)c.add(s)});graphNodes.attr('opacity',n=>c.has(n.id)?1:.12);graphLinks.attr('opacity',l=>{const s=typeof l.source==='object'?l.source.id:l.source;const t=typeof l.target==='object'?l.target.id:l.target;return(s===d.id||t===d.id)?1:.04});graphLabels.attr('opacity',n=>c.has(n.id)?1:.08); }
380
- function clearGraphHighlight(){ graphNodes?.attr('opacity',1); graphLinks?.attr('opacity',1); graphLabels?.attr('opacity',.8); }
381
- function focusGraphNode(id){ const n=graphNodeMap?.get(id);if(!n)return;highlightGraphNode(n);loadNodeDetail(id);graphSvg.transition().duration(500).call(graphZoom.translateTo,n.x,n.y); }
382
670
 
383
671
  // ═══════════════════════════════════════════════════════════════════════════
384
672
  // TIMELINE PANEL
@@ -394,7 +682,7 @@ body{font-family:var(--font);background:var(--bg);color:var(--text);overflow:hid
394
682
  if(!ops.length){ $('tl-body').innerHTML='<div class="tl-empty">No operations yet</div>'; return; }
395
683
  const body = $('tl-body');
396
684
  const W = Math.max(body.clientWidth, ops.length*14+120), H = body.clientHeight-20;
397
- const KIND_COLORS = {'vcs:fileAdd':TYPE_COLORS.file,'vcs:fileModify':'#38bdf8','vcs:fileDelete':TYPE_COLORS.issue,'vcs:fileRename':'#fb923c','vcs:branchCreate':TYPE_COLORS.branch,'vcs:branchDelete':'#f472b6','vcs:milestoneCreate':TYPE_COLORS.milestone,'vcs:checkpointCreate':'#6b7280'};
685
+ const KIND_COLORS = {'vcs:fileAdd':ENTITY_COLORS.file,'vcs:fileModify':'#38bdf8','vcs:fileDelete':ENTITY_COLORS.issue,'vcs:fileRename':'#fb923c','vcs:branchCreate':ENTITY_COLORS.branch,'vcs:branchDelete':'#f472b6','vcs:milestoneCreate':ENTITY_COLORS.milestone,'vcs:checkpointCreate':'#6b7280'};
398
686
  const svg = d3.select('#tl-body').append('svg').attr('width',W).attr('height',H);
399
687
  const x = d3.scaleLinear().domain([0,ops.length-1||1]).range([40,W-40]);
400
688
  const laneY = H/2;
@@ -412,9 +700,9 @@ body{font-family:var(--font);background:var(--bg);color:var(--text);overflow:hid
412
700
  .on('click',(e,d)=>{e.stopPropagation();openDrawer('Op: '+d.kind,`<div class="d-section"><div class="d-kv"><span class="k">kind</span><span class="v">${d.kind}</span><span class="k">hash</span><span class="v">${d.hash}</span><span class="k">time</span><span class="v">${d.timestamp||''}</span><span class="k">agent</span><span class="v">${d.agentId||''}</span>${d.filePath?'<span class="k">file</span><span class="v">'+esc(d.filePath)+'</span>':''}${d.branchName?'<span class="k">branch</span><span class="v">'+esc(d.branchName)+'</span>':''}</div></div>`)});
413
701
 
414
702
  // Milestone markers
415
- milestones.forEach(m=>{const mx=x(m.atOpIndex);svg.append('polygon').attr('points',`${mx},${laneY-18} ${mx+6},${laneY-10} ${mx},${laneY-2} ${mx-6},${laneY-10}`).attr('fill',TYPE_COLORS.milestone).attr('opacity',.85).attr('cursor','pointer')
703
+ milestones.forEach(m=>{const mx=x(m.atOpIndex);svg.append('polygon').attr('points',`${mx},${laneY-18} ${mx+6},${laneY-10} ${mx},${laneY-2} ${mx-6},${laneY-10}`).attr('fill',ENTITY_COLORS.milestone).attr('opacity',.85).attr('cursor','pointer')
416
704
  .on('click',()=>openDrawer('Milestone',`<div class="d-section"><h4>Message</h4><div class="d-meta"><strong>${esc(m.message||'')}</strong></div></div><div class="d-section"><div class="d-kv"><span class="k">ID</span><span class="v">${m.id}</span><span class="k">at op</span><span class="v">#${m.atOpIndex}</span><span class="k">files</span><span class="v">${m.affectedFiles}</span></div></div>`));
417
- svg.append('text').attr('x',mx).attr('y',laneY-22).attr('text-anchor','middle').attr('font-size',9).attr('fill',TYPE_COLORS.milestone).attr('font-family','Inter').text(m.message?.slice(0,20)||m.id)});
705
+ svg.append('text').attr('x',mx).attr('y',laneY-22).attr('text-anchor','middle').attr('font-size',9).attr('fill',ENTITY_COLORS.milestone).attr('font-family','Inter').text(m.message?.slice(0,20)||m.id)});
418
706
 
419
707
  // Checkpoint ticks
420
708
  checkpoints.forEach(c=>{const cx=x(c.atOpIndex);svg.append('line').attr('x1',cx).attr('y1',laneY+8).attr('x2',cx).attr('y2',laneY+18).attr('stroke','#6b7280').attr('stroke-width',1).attr('opacity',.5)});
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Launch the SvelteKit realtime explorer (demo/realtime-app).
3
+ * Replaces the legacy client.html System Visualizer for `trellis ui`.
4
+ */
5
+ export type LaunchExplorerOptions = {
6
+ /** Repo root — ensures .trellis exists; explorer DB lives in demo/realtime-app */
7
+ rootPath: string;
8
+ /** SvelteKit dev port (default 4000) */
9
+ appPort?: number;
10
+ /** Trellis graph sidecar port (default 3920) */
11
+ trellisPort?: number;
12
+ };
13
+ export type LaunchExplorerHandle = {
14
+ appPort: number;
15
+ trellisPort: number;
16
+ appUrl: string;
17
+ trellisUrl: string;
18
+ stop: () => void;
19
+ };
20
+ export declare function resolveExplorerAppDir(): string;
21
+ export declare function launchRealtimeExplorer(opts: LaunchExplorerOptions): Promise<LaunchExplorerHandle>;
22
+ //# sourceMappingURL=launch-explorer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch-explorer.d.ts","sourceRoot":"","sources":["../../src/ui/launch-explorer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,MAAM,qBAAqB,GAAG;IAClC,kFAAkF;IAClF,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAIF,wBAAgB,qBAAqB,IAAI,MAAM,CAY9C;AAMD,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,oBAAoB,CAAC,CA0D/B"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Trellis UI Server
3
3
  *
4
- * Lightweight Bun HTTP server that exposes the TrellisVCS engine
4
+ * Lightweight HTTP server that exposes the TrellisVCS engine
5
5
  * as a JSON API and serves the System Visualizer client.
6
6
  *
7
7
  * Endpoints:
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAiBH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,gBAAgB,GAAG,cAAc,GAAG,UAAU,GAAG,QAAQ,CAAC;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAqZD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC,CAyLD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAmBH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,gBAAgB,GAAG,cAAc,GAAG,UAAU,GAAG,QAAQ,CAAC;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAqZD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC,CAsOD"}
@@ -1 +1 @@
1
- {"version":3,"file":"blob-store.d.ts","sourceRoot":"","sources":["../../src/vcs/blob-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAS;gBAEZ,UAAU,EAAE,MAAM;IAO9B;;;OAGG;IACG,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IASxD;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM;IAS7C;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQhC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAQzD;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM;IAW9C;;OAEG;IACH,KAAK,IAAI,MAAM;IASf;;OAEG;IACH,SAAS,IAAI,MAAM;IAgBnB,OAAO,CAAC,aAAa;CAKtB"}
1
+ {"version":3,"file":"blob-store.d.ts","sourceRoot":"","sources":["../../src/vcs/blob-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAS;gBAEZ,UAAU,EAAE,MAAM;IAO9B;;;OAGG;IACG,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IASxD;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM;IAS7C;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQhC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAQzD;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM;IAK9C;;OAEG;IACH,KAAK,IAAI,MAAM;IASf;;OAEG;IACH,SAAS,IAAI,MAAM;IAgBnB,OAAO,CAAC,aAAa;CAKtB"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * IndexedDB-backed op log.
3
+ *
4
+ * Browser-side companion to {@link JsonOpLog}. Designed to satisfy the
5
+ * {@link OpLog} contract while accommodating IndexedDB's async nature:
6
+ *
7
+ * - `load()` opens the database and pulls every persisted op into an
8
+ * in-memory cache. All subsequent reads serve from cache, so the engine
9
+ * can continue using synchronous `readAll`/`getLastOp`/`count`.
10
+ * - `append()` is synchronous from the caller's perspective: it updates the
11
+ * in-memory cache immediately and enqueues a durable IDB write. The
12
+ * returned promise from `flush()` resolves once every queued write has
13
+ * committed.
14
+ * - Hash dedup happens against the cache before the write is enqueued, so
15
+ * replayed sync batches never insert the same op twice.
16
+ *
17
+ * Default store layout: one database per repo, one object store keyed by
18
+ * `hash`, with a monotonically-increasing `seq` index so we can replay in
19
+ * append order on load. Callers may override the IDB factory in tests by
20
+ * passing `indexedDB` in the constructor options.
21
+ */
22
+ import type { VcsOp } from './types.js';
23
+ import type { OpLog } from './op-log.js';
24
+ /**
25
+ * Subset of the IndexedDB Factory we use. Matches both `globalThis.indexedDB`
26
+ * and `fake-indexeddb`'s `IDBFactory`. Allows test injection without pulling
27
+ * in the full DOM typings.
28
+ */
29
+ export interface IdbFactoryLike {
30
+ open(name: string, version?: number): IDBOpenDBRequest;
31
+ }
32
+ export interface IdbOpLogOptions {
33
+ /** Database name. One Trellis repo per database. */
34
+ dbName: string;
35
+ /**
36
+ * Object store name. Defaults to `ops`. Override if multiple op logs share
37
+ * a database (e.g. integration journal vs. lane journals).
38
+ */
39
+ storeName?: string;
40
+ /**
41
+ * Injected IndexedDB factory. Defaults to `globalThis.indexedDB`. Tests
42
+ * pass `fake-indexeddb`'s factory directly.
43
+ */
44
+ indexedDB?: IdbFactoryLike;
45
+ }
46
+ export declare class IdbOpLog implements OpLog {
47
+ private ops;
48
+ private hashes;
49
+ private db;
50
+ private nextSeq;
51
+ private pendingWrites;
52
+ private readonly dbName;
53
+ private readonly storeName;
54
+ private readonly factory;
55
+ constructor(opts: IdbOpLogOptions);
56
+ load(): Promise<void>;
57
+ append(op: VcsOp): void;
58
+ readAll(): VcsOp[];
59
+ getLastOp(): VcsOp | undefined;
60
+ count(): number;
61
+ flush(): Promise<void>;
62
+ close(): Promise<void>;
63
+ private openDb;
64
+ private readAllRecords;
65
+ private putRecord;
66
+ }
67
+ //# sourceMappingURL=idb-op-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idb-op-log.d.ts","sourceRoot":"","sources":["../../src/vcs/idb-op-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;CACxD;AAED,MAAM,WAAW,eAAe;IAC9B,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AAQD,qBAAa,QAAS,YAAW,KAAK;IACpC,OAAO,CAAC,GAAG,CAAe;IAC1B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,EAAE,CAA4B;IACtC,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,aAAa,CAAoC;IAEzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;gBAE7B,IAAI,EAAE,eAAe;IAc3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,MAAM,CAAC,EAAE,EAAE,KAAK,GAAG,IAAI;IAevB,OAAO,IAAI,KAAK,EAAE;IAIlB,SAAS,IAAI,KAAK,GAAG,SAAS;IAI9B,KAAK,IAAI,MAAM;IAIT,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,OAAO,CAAC,MAAM;IAkBd,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,SAAS;CAclB"}
@@ -21,5 +21,6 @@ export * from './diff.js';
21
21
  export * from './merge.js';
22
22
  export * from './issue.js';
23
23
  export * from './op-log.js';
24
+ export * from './idb-op-log.js';
24
25
  export * from './lane.js';
25
26
  //# sourceMappingURL=index.d.ts.map