wiki-viewer 2.20.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  6. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
  14. package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js +4 -4
  15. package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
  16. package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js +8 -8
  17. package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js +8 -8
  19. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -1
  20. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js +5 -5
  22. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js +4 -4
  26. package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/assets/[...path]/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/pdf/save/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/share/[token]/asset/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/share/[token]/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/share/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/system/browse/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/branch/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/refresh/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/system/workspaces/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/wiki/backlinks/route.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/api/wiki/content/route.js +7 -6
  44. package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/api/wiki/download/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
  47. package/.next/standalone/.next/server/app/api/wiki/git-branches/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/wiki/git-checkout/route.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/api/wiki/git-diff/route.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/api/wiki/git-file-info/route.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/api/wiki/git-history/route.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/api/wiki/git-pull/route.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/api/wiki/hosted-apps/[slug]/route.js.nft.json +1 -1
  54. package/.next/standalone/.next/server/app/api/wiki/hosted-apps/route.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/api/wiki/move/route.js +4 -4
  56. package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
  58. package/.next/standalone/.next/server/app/api/wiki/outlinks/route.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -1
  61. package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/api/wiki/scratch/route.js.nft.json +1 -1
  63. package/.next/standalone/.next/server/app/api/wiki/search/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
  67. package/.next/standalone/.next/server/app/app/[slug]/[[...rest]]/route.js +1 -1
  68. package/.next/standalone/.next/server/app/app/[slug]/[[...rest]]/route.js.nft.json +1 -1
  69. package/.next/standalone/.next/server/app/page/react-loadable-manifest.json +1 -1
  70. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/s/[token]/page.js.nft.json +1 -1
  73. package/.next/standalone/.next/server/app/s/[token]/page_client-reference-manifest.js +1 -1
  74. package/.next/standalone/.next/server/app/signin/page_client-reference-manifest.js +1 -1
  75. package/.next/standalone/.next/server/chunks/0.u4_next_dist_esm_build_templates_app-route_0.4w~2_.js +1 -1
  76. package/.next/standalone/.next/server/chunks/0.u4_next_dist_esm_build_templates_app-route_024r~hj.js +1 -1
  77. package/.next/standalone/.next/server/chunks/[root-of-the-server]__014dhj5._.js +3 -0
  78. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__09vw_yd._.js → [root-of-the-server]__07757zz._.js} +2 -2
  79. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_2j7pq._.js +3 -0
  80. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0dya7sd._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ivbizg._.js +16 -0
  82. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0k2nouu._.js +3 -0
  83. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ul.gyt._.js +3 -0
  84. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0w2ba2x._.js +3 -0
  85. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wcg8qs._.js +16 -0
  86. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0yzumg-._.js +1 -1
  87. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0~a6cyg._.js +1 -1
  88. package/.next/standalone/.next/server/chunks/_079xuln._.js +1 -1
  89. package/.next/standalone/.next/server/chunks/ssr/{0~w0_katex_dist_katex_mjs_02b4pv0._.js → 0~w0_katex_dist_katex_mjs_01swx_l._.js} +1 -1
  90. package/.next/standalone/.next/server/chunks/ssr/{0~w0_katex_dist_katex_mjs_03x.-bb._.js → 0~w0_katex_dist_katex_mjs_10cht08._.js} +1 -1
  91. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0fh-02e._.js → [root-of-the-server]__0d89mrm._.js} +2 -2
  92. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__05fw4nf._.js → [root-of-the-server]__0xl7e3h._.js} +2 -2
  93. package/.next/standalone/.next/server/chunks/ssr/_0d28.zp._.js +1 -1
  94. package/.next/standalone/.next/server/chunks/ssr/_0e1uo~z._.js +1 -1
  95. package/.next/standalone/.next/server/chunks/ssr/_0k6g8yo._.js +22 -20
  96. package/.next/standalone/.next/server/chunks/ssr/_0sr4wj.._.js +1 -1
  97. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0ho8oyj._.js → node_modules__pnpm_0-xbi6q._.js} +2 -2
  98. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0.lls2f._.js → node_modules__pnpm_0045hhh._.js} +2 -2
  99. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0p_qmx3._.js → node_modules__pnpm_00b2ftc._.js} +2 -2
  100. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_06xedp9._.js → node_modules__pnpm_01mrx7s._.js} +2 -2
  101. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0.b-q-g._.js → node_modules__pnpm_029sanw._.js} +2 -2
  102. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0dm-.3s._.js → node_modules__pnpm_034eonm._.js} +1 -1
  103. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0gdk9ii._.js → node_modules__pnpm_03cxqnc._.js} +2 -2
  104. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_131~6_2._.js → node_modules__pnpm_03~9v2y._.js} +1 -1
  105. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0eo2ac8._.js → node_modules__pnpm_047iyar._.js} +1 -1
  106. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0f.-l_i._.js → node_modules__pnpm_04qoa_.._.js} +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_02j29jd._.js → node_modules__pnpm_05jxr.d._.js} +2 -2
  108. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0u~ng-b._.js → node_modules__pnpm_05m3zxe._.js} +1 -1
  109. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_03m~yp-._.js → node_modules__pnpm_05s3rp_._.js} +1 -1
  110. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0owi.t~._.js → node_modules__pnpm_06ti8hd._.js} +2 -2
  111. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0frtimc._.js → node_modules__pnpm_06xoojz._.js} +1 -1
  112. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0zhmzqf._.js → node_modules__pnpm_085kv-l._.js} +1 -1
  113. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0b9mrd-._.js → node_modules__pnpm_08wjj_6._.js} +2 -2
  114. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_004esp.._.js → node_modules__pnpm_098q_0q._.js} +1 -1
  115. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_035f6c2._.js → node_modules__pnpm_0_rahb~._.js} +1 -1
  116. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_00d_ihj._.js → node_modules__pnpm_0a2ww-4._.js} +1 -1
  117. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0dnud63._.js → node_modules__pnpm_0aca6hd._.js} +1 -1
  118. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0laq3ah._.js → node_modules__pnpm_0btk5kj._.js} +2 -2
  119. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0lwio3d._.js → node_modules__pnpm_0deg.gs._.js} +1 -1
  120. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_029eo0j._.js → node_modules__pnpm_0dir6h3._.js} +1 -1
  121. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_13i2f82._.js → node_modules__pnpm_0fk6r5-._.js} +1 -1
  122. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_04e8oap._.js → node_modules__pnpm_0g.7k_n._.js} +1 -1
  123. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0wpana9._.js → node_modules__pnpm_0gguvd4._.js} +1 -1
  124. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0.cggg3._.js → node_modules__pnpm_0gy4l1q._.js} +1 -1
  125. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0jn81p-._.js → node_modules__pnpm_0hajaki._.js} +1 -1
  126. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0oqqt~3._.js → node_modules__pnpm_0hvnqml._.js} +2 -2
  127. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0qq915e._.js → node_modules__pnpm_0hy39av._.js} +1 -1
  128. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0va2k-t._.js → node_modules__pnpm_0j_.d8m._.js} +1 -1
  129. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0w6417f._.js → node_modules__pnpm_0jq2ef9._.js} +2 -2
  130. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0t_97nv._.js → node_modules__pnpm_0mtv_af._.js} +1 -1
  131. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_09-tnjc._.js → node_modules__pnpm_0mus7ah._.js} +1 -1
  132. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0_39rjg._.js → node_modules__pnpm_0oexapu._.js} +1 -1
  133. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0d.7f.v._.js → node_modules__pnpm_0oqzhc1._.js} +1 -1
  134. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0-q76.t._.js → node_modules__pnpm_0o~vvgs._.js} +1 -1
  135. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_08aserg._.js → node_modules__pnpm_0ptozb4._.js} +1 -1
  136. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_018bmrp._.js → node_modules__pnpm_0rqsp1j._.js} +1 -1
  137. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0ye5zu~._.js → node_modules__pnpm_0rs15iz._.js} +2 -2
  138. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0pq-m-w._.js → node_modules__pnpm_0ryy9ik._.js} +1 -1
  139. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0ew~_em._.js → node_modules__pnpm_0t9_wi1._.js} +1 -1
  140. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0.eafd4._.js → node_modules__pnpm_0tnriso._.js} +2 -2
  141. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0awp-lz._.js → node_modules__pnpm_0tz8-2x._.js} +1 -1
  142. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_08ly65-._.js → node_modules__pnpm_0uap1~z._.js} +1 -1
  143. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0-9pgc-._.js → node_modules__pnpm_0wyvqp7._.js} +1 -1
  144. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0a0xb30._.js → node_modules__pnpm_0yect_i._.js} +1 -1
  145. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0gk3zd4._.js → node_modules__pnpm_0yyt.qr._.js} +1 -1
  146. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_13dh01l._.js → node_modules__pnpm_0z7wvui._.js} +1 -1
  147. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_11ge450._.js → node_modules__pnpm_1032cax._.js} +1 -1
  148. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_10tma_q._.js → node_modules__pnpm_107~rhn._.js} +1 -1
  149. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_09cnu2l._.js → node_modules__pnpm_124jh7j._.js} +1 -1
  150. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0ibh1jm._.js → node_modules__pnpm_12v9693._.js} +1 -1
  151. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  152. package/.next/standalone/.next/server/pages/500.html +1 -1
  153. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  154. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  155. package/.next/standalone/.next/static/chunks/0_6~i5v43qpgh.js +1 -0
  156. package/.next/standalone/.next/static/chunks/{16xauntup4146.js → 0drn9l.ihdwh-.js} +1 -1
  157. package/.next/standalone/.next/static/chunks/{0j7kp7w2oum68.js → 0ftz-0jz~tk6i.js} +1 -1
  158. package/.next/standalone/.next/static/chunks/0kml2.eor4-mh.js +190 -0
  159. package/.next/standalone/.next/static/chunks/{09dn.__2m_69y.js → 0rows7ykoflq3.js} +1 -1
  160. package/.next/standalone/.next/static/chunks/{0j_n58.7iw6~6.js → 0ujpqxim7iqme.js} +1 -1
  161. package/.next/standalone/.next/static/chunks/136jk6_h2z_jw.js +1 -0
  162. package/.next/standalone/.next/static/chunks/17khi18hxwx5d.css +1 -0
  163. package/.next/standalone/.test-floor +1 -1
  164. package/.next/standalone/package.json +22 -21
  165. package/.next/standalone/server.js +1 -1
  166. package/package.json +22 -21
  167. package/.next/standalone/.next/server/chunks/[root-of-the-server]__041fu_k._.js +0 -3
  168. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_6mful._.js +0 -3
  169. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0b7h2ot._.js +0 -16
  170. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0bs~4kr._.js +0 -3
  171. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0bzyv11._.js +0 -3
  172. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ian9~8._.js +0 -16
  173. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wgd88e._.js +0 -3
  174. package/.next/standalone/.next/static/chunks/0gl24pgjp37cr.js +0 -1
  175. package/.next/standalone/.next/static/chunks/0o.-s7.m.hhct.css +0 -1
  176. package/.next/standalone/.next/static/chunks/0x082gn2hhbex.js +0 -188
  177. package/.next/standalone/.next/static/chunks/13s~dhi5itm5t.js +0 -1
  178. package/.next/standalone/isometric-codebase-map.html +0 -1506
  179. package/.next/standalone/isometric-codebase-map.json +0 -169
  180. package/.next/standalone/wp-test-6mm5qr/burst-0.txt +0 -1
  181. package/.next/standalone/wp-test-6mm5qr/burst-1.txt +0 -1
  182. package/.next/standalone/wp-test-6mm5qr/burst-10.txt +0 -1
  183. package/.next/standalone/wp-test-6mm5qr/burst-11.txt +0 -1
  184. package/.next/standalone/wp-test-6mm5qr/burst-12.txt +0 -1
  185. package/.next/standalone/wp-test-6mm5qr/burst-13.txt +0 -1
  186. package/.next/standalone/wp-test-6mm5qr/burst-14.txt +0 -1
  187. package/.next/standalone/wp-test-6mm5qr/burst-15.txt +0 -1
  188. package/.next/standalone/wp-test-6mm5qr/burst-16.txt +0 -1
  189. package/.next/standalone/wp-test-6mm5qr/burst-17.txt +0 -1
  190. package/.next/standalone/wp-test-6mm5qr/burst-18.txt +0 -1
  191. package/.next/standalone/wp-test-6mm5qr/burst-19.txt +0 -1
  192. package/.next/standalone/wp-test-6mm5qr/burst-2.txt +0 -1
  193. package/.next/standalone/wp-test-6mm5qr/burst-20.txt +0 -1
  194. package/.next/standalone/wp-test-6mm5qr/burst-21.txt +0 -1
  195. package/.next/standalone/wp-test-6mm5qr/burst-22.txt +0 -1
  196. package/.next/standalone/wp-test-6mm5qr/burst-23.txt +0 -1
  197. package/.next/standalone/wp-test-6mm5qr/burst-24.txt +0 -1
  198. package/.next/standalone/wp-test-6mm5qr/burst-25.txt +0 -1
  199. package/.next/standalone/wp-test-6mm5qr/burst-26.txt +0 -1
  200. package/.next/standalone/wp-test-6mm5qr/burst-27.txt +0 -1
  201. package/.next/standalone/wp-test-6mm5qr/burst-28.txt +0 -1
  202. package/.next/standalone/wp-test-6mm5qr/burst-29.txt +0 -1
  203. package/.next/standalone/wp-test-6mm5qr/burst-3.txt +0 -1
  204. package/.next/standalone/wp-test-6mm5qr/burst-30.txt +0 -1
  205. package/.next/standalone/wp-test-6mm5qr/burst-31.txt +0 -1
  206. package/.next/standalone/wp-test-6mm5qr/burst-32.txt +0 -1
  207. package/.next/standalone/wp-test-6mm5qr/burst-33.txt +0 -1
  208. package/.next/standalone/wp-test-6mm5qr/burst-34.txt +0 -1
  209. package/.next/standalone/wp-test-6mm5qr/burst-35.txt +0 -1
  210. package/.next/standalone/wp-test-6mm5qr/burst-36.txt +0 -1
  211. package/.next/standalone/wp-test-6mm5qr/burst-37.txt +0 -1
  212. package/.next/standalone/wp-test-6mm5qr/burst-38.txt +0 -1
  213. package/.next/standalone/wp-test-6mm5qr/burst-39.txt +0 -1
  214. package/.next/standalone/wp-test-6mm5qr/burst-4.txt +0 -1
  215. package/.next/standalone/wp-test-6mm5qr/burst-40.txt +0 -1
  216. package/.next/standalone/wp-test-6mm5qr/burst-41.txt +0 -1
  217. package/.next/standalone/wp-test-6mm5qr/burst-42.txt +0 -1
  218. package/.next/standalone/wp-test-6mm5qr/burst-43.txt +0 -1
  219. package/.next/standalone/wp-test-6mm5qr/burst-44.txt +0 -1
  220. package/.next/standalone/wp-test-6mm5qr/burst-45.txt +0 -1
  221. package/.next/standalone/wp-test-6mm5qr/burst-46.txt +0 -1
  222. package/.next/standalone/wp-test-6mm5qr/burst-47.txt +0 -1
  223. package/.next/standalone/wp-test-6mm5qr/burst-48.txt +0 -1
  224. package/.next/standalone/wp-test-6mm5qr/burst-49.txt +0 -1
  225. package/.next/standalone/wp-test-6mm5qr/burst-5.txt +0 -1
  226. package/.next/standalone/wp-test-6mm5qr/burst-6.txt +0 -1
  227. package/.next/standalone/wp-test-6mm5qr/burst-7.txt +0 -1
  228. package/.next/standalone/wp-test-6mm5qr/burst-8.txt +0 -1
  229. package/.next/standalone/wp-test-6mm5qr/burst-9.txt +0 -1
  230. package/.next/standalone/wp-test-SiMBLk/child/nested.txt +0 -1
  231. package/.next/standalone/wp-test-SiMBLk/rootfile.txt +0 -1
  232. package/.next/standalone/wp-test-bFyuuZ/child/nested.txt +0 -1
  233. package/.next/standalone/wp-test-bFyuuZ/rootfile.txt +0 -1
  234. package/.next/standalone/wp-test-dn9shN/after-reset.txt +0 -1
  235. package/.next/standalone/wp-test-gL64l2/shared.txt +0 -1
  236. package/.next/standalone/wp-test-mlyQ7q/test.txt +0 -1
  237. package/.next/standalone/wp-test-o3g2XI/shared.txt +0 -1
  238. package/.next/standalone/wp-test-oHeYCM/subA/a.txt +0 -1
  239. package/.next/standalone/wp-test-oHeYCM/subB/b.txt +0 -1
  240. /package/.next/standalone/.next/static/{ch24XdB6w4ERJnCBxzvzW → fJ3GtWg-nxX07oIencv35}/_buildManifest.js +0 -0
  241. /package/.next/standalone/.next/static/{ch24XdB6w4ERJnCBxzvzW → fJ3GtWg-nxX07oIencv35}/_clientMiddlewareManifest.js +0 -0
  242. /package/.next/standalone/.next/static/{ch24XdB6w4ERJnCBxzvzW → fJ3GtWg-nxX07oIencv35}/_ssgManifest.js +0 -0
@@ -1,1506 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width,initial-scale=1">
6
- <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src data:; style-src 'unsafe-inline'; script-src 'unsafe-inline'; font-src data:">
7
- <title>Isometric Codebase Map</title>
8
- <link rel="icon" href="data:image/svg+xml,%3Csvg viewBox='0 0 64 64'%3E%3Ctext y='52' font-size='52'%3E%F0%9F%97%BA%EF%B8%8F%3C/text%3E%3C/svg%3E">
9
- <style>
10
- :root {
11
- --paper: #f3efe3;
12
- --paper-2: #e9e2d1;
13
- --ink: #242b2a;
14
- --muted: #69706d;
15
- --line: #9b9a8d;
16
- --accent: #d24d35;
17
- --panel: rgba(249, 246, 237, 0.94);
18
- --shadow: rgba(47, 42, 31, 0.16);
19
- }
20
-
21
- * { box-sizing: border-box; }
22
-
23
- html, body {
24
- width: 100%;
25
- height: 100%;
26
- margin: 0;
27
- overflow: hidden;
28
- background: var(--paper);
29
- color: var(--ink);
30
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
31
- }
32
-
33
- button { font: inherit; }
34
-
35
- .shell {
36
- min-width: 1180px;
37
- height: 100vh;
38
- padding-top: 72px;
39
- background:
40
- linear-gradient(rgba(69, 77, 71, 0.035) 1px, transparent 1px),
41
- linear-gradient(90deg, rgba(69, 77, 71, 0.035) 1px, transparent 1px),
42
- var(--paper);
43
- background-size: 18px 18px;
44
- }
45
-
46
- .topbar {
47
- position: fixed;
48
- top: 0;
49
- right: 0;
50
- left: 0;
51
- height: 72px;
52
- display: grid;
53
- grid-template-columns: minmax(320px, 1fr) auto auto;
54
- align-items: center;
55
- gap: 22px;
56
- padding: 0 20px;
57
- border-bottom: 1px solid rgba(63, 69, 66, 0.34);
58
- background: rgba(246, 242, 232, 0.96);
59
- box-shadow: 0 4px 18px rgba(51, 48, 39, 0.07);
60
- z-index: 10;
61
- }
62
-
63
- .brand {
64
- min-width: 0;
65
- display: flex;
66
- align-items: center;
67
- gap: 13px;
68
- }
69
-
70
- .brand-mark {
71
- width: 40px;
72
- height: 40px;
73
- display: grid;
74
- place-items: center;
75
- flex: 0 0 auto;
76
- border: 1px solid var(--ink);
77
- background:
78
- repeating-linear-gradient(135deg, transparent 0 4px, rgba(36, 43, 42, 0.15) 4px 5px),
79
- #dfd7c2;
80
- box-shadow: 3px 3px 0 rgba(36, 43, 42, 0.16);
81
- font-size: 20px;
82
- }
83
-
84
- .brand-copy { min-width: 0; }
85
-
86
- .brand h1 {
87
- margin: 0;
88
- overflow: hidden;
89
- text-overflow: ellipsis;
90
- white-space: nowrap;
91
- font-family: Georgia, "Times New Roman", serif;
92
- font-size: 22px;
93
- font-weight: 700;
94
- letter-spacing: -0.02em;
95
- }
96
-
97
- .brand p {
98
- margin: 3px 0 0;
99
- overflow: hidden;
100
- text-overflow: ellipsis;
101
- white-space: nowrap;
102
- color: var(--muted);
103
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
104
- font-size: 10px;
105
- letter-spacing: 0.08em;
106
- text-transform: uppercase;
107
- }
108
-
109
- .stats {
110
- display: flex;
111
- align-items: stretch;
112
- border-left: 1px solid rgba(63, 69, 66, 0.25);
113
- }
114
-
115
- .stat {
116
- min-width: 80px;
117
- padding: 3px 14px;
118
- border-right: 1px solid rgba(63, 69, 66, 0.25);
119
- text-align: center;
120
- }
121
-
122
- .stat strong {
123
- display: block;
124
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
125
- font-size: 15px;
126
- line-height: 1.1;
127
- }
128
-
129
- .stat span {
130
- display: block;
131
- margin-top: 4px;
132
- color: var(--muted);
133
- font-size: 9px;
134
- letter-spacing: 0.1em;
135
- text-transform: uppercase;
136
- }
137
-
138
- .top-actions {
139
- display: flex;
140
- align-items: center;
141
- gap: 7px;
142
- }
143
-
144
- .control {
145
- min-height: 34px;
146
- padding: 0 12px;
147
- border: 1px solid rgba(36, 43, 42, 0.5);
148
- border-radius: 2px;
149
- background: transparent;
150
- color: var(--ink);
151
- cursor: pointer;
152
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
153
- font-size: 10px;
154
- font-weight: 700;
155
- letter-spacing: 0.08em;
156
- text-transform: uppercase;
157
- }
158
-
159
- .control:hover,
160
- .control:focus-visible {
161
- outline: none;
162
- background: var(--ink);
163
- color: var(--paper);
164
- }
165
-
166
- .control.primary {
167
- border-color: var(--accent);
168
- background: var(--accent);
169
- color: #fffaf0;
170
- }
171
-
172
- .app {
173
- height: calc(100vh - 72px);
174
- min-height: 0;
175
- display: grid;
176
- grid-template-columns: 258px minmax(560px, 1fr) 342px;
177
- }
178
-
179
- .rail,
180
- .detail {
181
- min-height: 0;
182
- overflow: auto;
183
- background: var(--panel);
184
- backdrop-filter: blur(7px);
185
- scrollbar-width: thin;
186
- scrollbar-color: rgba(36, 43, 42, 0.28) transparent;
187
- }
188
-
189
- .rail {
190
- border-right: 1px solid rgba(63, 69, 66, 0.34);
191
- padding: 20px 14px 30px;
192
- }
193
-
194
- .detail {
195
- border-left: 1px solid rgba(63, 69, 66, 0.34);
196
- padding: 24px 24px 38px;
197
- }
198
-
199
- .rail-heading,
200
- .eyebrow {
201
- margin: 0 0 15px;
202
- color: var(--muted);
203
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
204
- font-size: 10px;
205
- font-weight: 800;
206
- letter-spacing: 0.14em;
207
- text-transform: uppercase;
208
- }
209
-
210
- .group { margin-bottom: 19px; }
211
-
212
- .group-title {
213
- display: flex;
214
- align-items: center;
215
- gap: 8px;
216
- margin: 0 7px 7px;
217
- color: var(--muted);
218
- font-size: 10px;
219
- font-weight: 800;
220
- letter-spacing: 0.11em;
221
- text-transform: uppercase;
222
- }
223
-
224
- .swatch {
225
- width: 9px;
226
- height: 9px;
227
- border: 1px solid rgba(36, 43, 42, 0.46);
228
- transform: rotate(45deg);
229
- }
230
-
231
- .structure-link {
232
- width: 100%;
233
- display: grid;
234
- grid-template-columns: 31px minmax(0, 1fr) auto;
235
- align-items: center;
236
- gap: 8px;
237
- min-height: 37px;
238
- margin: 2px 0;
239
- padding: 4px 6px;
240
- border: 1px solid transparent;
241
- border-radius: 2px;
242
- background: transparent;
243
- color: var(--ink);
244
- text-align: left;
245
- cursor: pointer;
246
- }
247
-
248
- .structure-link:hover,
249
- .structure-link:focus-visible,
250
- .structure-link.active {
251
- outline: none;
252
- border-color: rgba(36, 43, 42, 0.35);
253
- background: rgba(255, 252, 244, 0.8);
254
- box-shadow: 2px 2px 0 rgba(36, 43, 42, 0.09);
255
- }
256
-
257
- .structure-link.active { border-left: 3px solid var(--accent); }
258
-
259
- .code-chip {
260
- width: 28px;
261
- height: 25px;
262
- display: grid;
263
- place-items: center;
264
- border: 1px solid rgba(36, 43, 42, 0.5);
265
- background: var(--chip, #ddd4bf);
266
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
267
- font-size: 10px;
268
- font-weight: 900;
269
- }
270
-
271
- .structure-link .name {
272
- overflow: hidden;
273
- text-overflow: ellipsis;
274
- white-space: nowrap;
275
- font-size: 12px;
276
- font-weight: 700;
277
- }
278
-
279
- .structure-link .loc {
280
- color: var(--muted);
281
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
282
- font-size: 9px;
283
- }
284
-
285
- .stage {
286
- position: relative;
287
- min-width: 0;
288
- min-height: 0;
289
- overflow: hidden;
290
- background:
291
- repeating-linear-gradient(30deg, transparent 0 12px, rgba(65, 75, 69, 0.035) 12px 13px),
292
- repeating-linear-gradient(150deg, transparent 0 12px, rgba(65, 75, 69, 0.028) 12px 13px),
293
- radial-gradient(circle at 50% 42%, rgba(255, 255, 255, 0.78), rgba(230, 223, 207, 0.52));
294
- }
295
-
296
- #map {
297
- width: 100%;
298
- height: 100%;
299
- display: block;
300
- overflow: visible;
301
- }
302
-
303
- .ground-line {
304
- fill: none;
305
- stroke: rgba(66, 73, 69, 0.11);
306
- stroke-width: 1;
307
- }
308
-
309
- .zone-label {
310
- fill: rgba(52, 61, 57, 0.28);
311
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
312
- font-size: 10px;
313
- font-weight: 800;
314
- letter-spacing: 0.18em;
315
- }
316
-
317
- .edge-line {
318
- fill: none;
319
- stroke: rgba(54, 64, 59, 0.43);
320
- stroke-width: 1.5;
321
- vector-effect: non-scaling-stroke;
322
- }
323
-
324
- .edge-line.flow { stroke: rgba(56, 72, 65, 0.68); }
325
- .edge-line.dashed { stroke-dasharray: 5 5; stroke: rgba(83, 81, 70, 0.5); }
326
- .edge-line.active { stroke: var(--accent); stroke-width: 3; }
327
- .edge-line.trace-complete { stroke: #aa6d32; stroke-width: 2.2; opacity: 0.9; }
328
- .edge-line.trace-current { stroke: var(--accent); stroke-width: 4; opacity: 1; }
329
-
330
- .edge-hit {
331
- fill: none;
332
- stroke: transparent;
333
- stroke-width: 12;
334
- pointer-events: stroke;
335
- cursor: help;
336
- }
337
-
338
- .flow-dot {
339
- fill: #c54831;
340
- stroke: #fff8e8;
341
- stroke-width: 1.2;
342
- pointer-events: all;
343
- }
344
-
345
- .structure {
346
- cursor: pointer;
347
- transition: opacity 140ms ease;
348
- }
349
-
350
- .structure:focus-visible { outline: none; }
351
- .structure .face { stroke: rgba(31, 39, 36, 0.62); stroke-width: 1; vector-effect: non-scaling-stroke; }
352
- .structure .top { filter: url(#paper-shadow); }
353
-
354
- .structure:hover .face,
355
- .structure.active .face,
356
- .structure:focus-visible .face {
357
- stroke: var(--accent);
358
- stroke-width: 2.4;
359
- }
360
-
361
- .structure.dimmed { opacity: 0.28; }
362
-
363
- .structure.trace-complete .face {
364
- stroke: #aa6d32;
365
- stroke-width: 2.1;
366
- }
367
-
368
- .structure.trace-current {
369
- filter: drop-shadow(0 0 6px rgba(210, 77, 53, 0.5));
370
- }
371
-
372
- .structure.trace-current .face {
373
- stroke: var(--accent);
374
- stroke-width: 3.2;
375
- }
376
-
377
- .block-code {
378
- fill: #28302d;
379
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
380
- font-size: 13px;
381
- font-weight: 900;
382
- text-anchor: middle;
383
- pointer-events: none;
384
- }
385
-
386
- .block-loc {
387
- fill: rgba(40, 48, 45, 0.67);
388
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
389
- font-size: 8px;
390
- font-weight: 700;
391
- text-anchor: middle;
392
- pointer-events: none;
393
- }
394
-
395
- .external-line {
396
- fill: none;
397
- stroke: rgba(78, 79, 70, 0.53);
398
- stroke-width: 1.2;
399
- stroke-dasharray: 4 5;
400
- }
401
-
402
- .external-card {
403
- fill: rgba(249, 246, 237, 0.96);
404
- stroke: rgba(58, 64, 61, 0.58);
405
- stroke-width: 1;
406
- }
407
-
408
- .external-name {
409
- fill: var(--ink);
410
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
411
- font-size: 9px;
412
- font-weight: 800;
413
- letter-spacing: 0.04em;
414
- }
415
-
416
- .external-pay {
417
- fill: var(--muted);
418
- font-size: 8px;
419
- }
420
-
421
- .tooltip {
422
- position: fixed;
423
- z-index: 30;
424
- width: 240px;
425
- padding: 12px 13px;
426
- border: 1px solid var(--ink);
427
- background: #fffaf0;
428
- box-shadow: 5px 5px 0 rgba(36, 43, 42, 0.14);
429
- pointer-events: none;
430
- opacity: 0;
431
- transform: translate(10px, 10px);
432
- }
433
-
434
- .tooltip.show { opacity: 1; }
435
-
436
- .tooltip strong {
437
- display: block;
438
- margin-bottom: 5px;
439
- font-size: 12px;
440
- }
441
-
442
- .tooltip span {
443
- color: var(--muted);
444
- font-size: 10px;
445
- line-height: 1.45;
446
- }
447
-
448
- .detail h2 {
449
- margin: 0 0 10px;
450
- font-family: Georgia, "Times New Roman", serif;
451
- font-size: 28px;
452
- line-height: 1.05;
453
- letter-spacing: -0.025em;
454
- }
455
-
456
- .detail-meta {
457
- display: flex;
458
- gap: 7px;
459
- flex-wrap: wrap;
460
- margin-bottom: 25px;
461
- }
462
-
463
- .detail-meta span {
464
- padding: 4px 7px;
465
- border: 1px solid rgba(36, 43, 42, 0.32);
466
- background: rgba(255, 252, 244, 0.65);
467
- color: var(--muted);
468
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
469
- font-size: 9px;
470
- font-weight: 700;
471
- text-transform: uppercase;
472
- }
473
-
474
- .detail-section {
475
- padding: 18px 0;
476
- border-top: 1px solid rgba(63, 69, 66, 0.24);
477
- }
478
-
479
- .detail-section h3 {
480
- margin: 0 0 9px;
481
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
482
- font-size: 10px;
483
- letter-spacing: 0.14em;
484
- text-transform: uppercase;
485
- }
486
-
487
- .detail-section p,
488
- .detail-section li {
489
- margin: 0;
490
- color: #4f5753;
491
- font-size: 12px;
492
- line-height: 1.65;
493
- }
494
-
495
- .detail-section ul {
496
- margin: 0;
497
- padding-left: 18px;
498
- }
499
-
500
- .inside-button {
501
- width: 100%;
502
- min-height: 44px;
503
- margin-top: 17px;
504
- border: 1px solid var(--ink);
505
- background:
506
- repeating-linear-gradient(135deg, transparent 0 6px, rgba(255, 255, 255, 0.15) 6px 7px),
507
- var(--ink);
508
- color: #fffaf0;
509
- cursor: pointer;
510
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
511
- font-size: 10px;
512
- font-weight: 900;
513
- letter-spacing: 0.1em;
514
- text-transform: uppercase;
515
- }
516
-
517
- .inside-button:hover,
518
- .inside-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
519
-
520
- .trace-card {
521
- position: absolute;
522
- left: 24px;
523
- right: 24px;
524
- bottom: 20px;
525
- z-index: 8;
526
- display: none;
527
- grid-template-columns: 130px minmax(0, 1fr) auto;
528
- align-items: center;
529
- gap: 12px 18px;
530
- min-height: 148px;
531
- padding: 14px 16px 12px;
532
- border: 1px solid var(--ink);
533
- background: rgba(255, 250, 240, 0.96);
534
- box-shadow: 6px 6px 0 rgba(36, 43, 42, 0.14);
535
- }
536
-
537
- .trace-card.show { display: grid; }
538
-
539
- .trace-count {
540
- min-width: 120px;
541
- color: var(--accent);
542
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
543
- font-weight: 900;
544
- }
545
-
546
- .trace-count small,
547
- .trace-count span {
548
- display: block;
549
- color: var(--muted);
550
- font-size: 8px;
551
- letter-spacing: 0.1em;
552
- text-transform: uppercase;
553
- }
554
-
555
- .trace-count b {
556
- display: block;
557
- margin: 2px 0 3px;
558
- font-size: 22px;
559
- }
560
-
561
- .trace-copy strong {
562
- display: block;
563
- margin-bottom: 4px;
564
- font-size: 15px;
565
- }
566
-
567
- .trace-copy span {
568
- display: block;
569
- color: var(--muted);
570
- font-size: 11px;
571
- line-height: 1.35;
572
- }
573
-
574
- .trace-actions { display: flex; gap: 7px; }
575
-
576
- .trace-actions button {
577
- min-width: 72px;
578
- height: 34px;
579
- padding: 0 9px;
580
- border: 1px solid rgba(36, 43, 42, 0.48);
581
- background: transparent;
582
- cursor: pointer;
583
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
584
- font-size: 9px;
585
- font-weight: 900;
586
- letter-spacing: 0.05em;
587
- text-transform: uppercase;
588
- }
589
-
590
- .trace-actions button:hover,
591
- .trace-actions button:focus-visible { outline: none; background: var(--ink); color: var(--paper); }
592
-
593
- .trace-actions button:disabled { cursor: default; opacity: 0.3; }
594
-
595
- .trace-timeline {
596
- position: relative;
597
- grid-column: 1 / -1;
598
- display: grid;
599
- grid-template-columns: repeat(var(--trace-count), minmax(42px, 1fr));
600
- gap: 5px;
601
- padding-top: 13px;
602
- border-top: 1px solid rgba(63, 69, 66, 0.24);
603
- }
604
-
605
- .trace-timeline::before {
606
- position: absolute;
607
- top: 27px;
608
- right: 22px;
609
- left: 22px;
610
- height: 2px;
611
- background: rgba(36, 43, 42, 0.18);
612
- content: "";
613
- }
614
-
615
- .trace-step {
616
- position: relative;
617
- z-index: 1;
618
- display: grid;
619
- justify-items: center;
620
- gap: 4px;
621
- min-width: 0;
622
- padding: 0;
623
- border: 0;
624
- background: transparent;
625
- color: var(--muted);
626
- cursor: pointer;
627
- }
628
-
629
- .trace-dot {
630
- width: 29px;
631
- height: 29px;
632
- display: grid;
633
- place-items: center;
634
- border: 2px solid rgba(36, 43, 42, 0.35);
635
- border-radius: 50%;
636
- background: #fffaf0;
637
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
638
- font-size: 9px;
639
- font-weight: 900;
640
- }
641
-
642
- .trace-step.complete .trace-dot { border-color: #aa6d32; background: #aa6d32; color: #fffaf0; }
643
- .trace-step.current .trace-dot { border-color: var(--accent); background: var(--accent); color: #fffaf0; box-shadow: 0 0 0 4px rgba(210, 77, 53, 0.16); }
644
-
645
- .trace-step-label {
646
- max-width: 100%;
647
- overflow: hidden;
648
- text-overflow: ellipsis;
649
- white-space: nowrap;
650
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
651
- font-size: 8px;
652
- font-weight: 800;
653
- }
654
-
655
- .trace-step.current .trace-step-label { color: var(--accent); }
656
- .trace-step:hover .trace-step-label,
657
- .trace-step:focus-visible .trace-step-label { color: var(--ink); }
658
- .trace-step:focus-visible { outline: 1px solid var(--ink); outline-offset: 3px; }
659
-
660
- .inside-title {
661
- fill: var(--ink);
662
- font-family: Georgia, "Times New Roman", serif;
663
- font-size: 28px;
664
- font-weight: 700;
665
- }
666
-
667
- .inside-note {
668
- fill: var(--muted);
669
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
670
- font-size: 10px;
671
- letter-spacing: 0.08em;
672
- }
673
-
674
- .inside-boundary {
675
- fill: rgba(255, 252, 244, 0.3);
676
- stroke: rgba(56, 64, 60, 0.36);
677
- stroke-width: 1.2;
678
- stroke-dasharray: 8 6;
679
- }
680
-
681
- .inside-back {
682
- position: absolute;
683
- top: 18px;
684
- left: 18px;
685
- z-index: 9;
686
- display: none;
687
- }
688
-
689
- .inside-back.show { display: block; }
690
-
691
- .legend {
692
- position: absolute;
693
- right: 16px;
694
- top: 15px;
695
- display: flex;
696
- gap: 13px;
697
- padding: 7px 9px;
698
- border: 1px solid rgba(36, 43, 42, 0.22);
699
- background: rgba(249, 246, 237, 0.72);
700
- color: var(--muted);
701
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
702
- font-size: 8px;
703
- letter-spacing: 0.07em;
704
- text-transform: uppercase;
705
- }
706
-
707
- .legend i {
708
- width: 18px;
709
- height: 2px;
710
- display: inline-block;
711
- margin-right: 5px;
712
- vertical-align: middle;
713
- background: rgba(56, 72, 65, 0.68);
714
- }
715
-
716
- .legend i.dashed {
717
- background: repeating-linear-gradient(90deg, rgba(83, 81, 70, 0.7) 0 4px, transparent 4px 7px);
718
- }
719
- </style>
720
- </head>
721
- <body>
722
- <div class="shell">
723
- <header class="topbar">
724
- <div class="brand">
725
- <div class="brand-mark" aria-hidden="true">🗺️</div>
726
- <div class="brand-copy">
727
- <h1 id="page-title"></h1>
728
- <p id="page-subtitle"></p>
729
- </div>
730
- </div>
731
- <div class="stats" id="stats" aria-label="Repository statistics"></div>
732
- <div class="top-actions">
733
- <button class="control" id="overview-button" type="button">Overview</button>
734
- <button class="control primary" id="trace-button" type="button">Request trace</button>
735
- </div>
736
- </header>
737
-
738
- <div class="app">
739
- <aside class="rail" aria-label="Repository structures">
740
- <p class="rail-heading">Structure index</p>
741
- <nav id="structure-nav"></nav>
742
- </aside>
743
-
744
- <main class="stage" id="stage">
745
- <svg id="map" viewBox="0 0 1000 790" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Interactive isometric architecture map">
746
- <defs>
747
- <filter id="paper-shadow" x="-20%" y="-20%" width="150%" height="160%">
748
- <feDropShadow dx="3" dy="5" stdDeviation="3" flood-color="#3b392f" flood-opacity="0.16"></feDropShadow>
749
- </filter>
750
- <pattern id="fine-hatch" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(35)">
751
- <line x1="0" y1="0" x2="0" y2="7" stroke="#27302d" stroke-opacity="0.09" stroke-width="1"></line>
752
- </pattern>
753
- </defs>
754
- </svg>
755
- <button class="control inside-back" id="inside-back" type="button">← Back to system</button>
756
- <div class="legend" aria-hidden="true"><span><i></i>runtime flow</span><span><i class="dashed"></i>advisory</span></div>
757
- <div class="trace-card" id="trace-card" aria-live="polite"></div>
758
- </main>
759
-
760
- <aside class="detail" id="detail" aria-live="polite"></aside>
761
- </div>
762
- </div>
763
-
764
- <div class="tooltip" id="tooltip" role="tooltip"></div>
765
-
766
- <script>
767
- "use strict";
768
-
769
- /* ========================================================================
770
- DATA — REPLACE ONLY THIS SECTION FOR A NEW REPOSITORY
771
-
772
- STRUCTURES fields:
773
- id, code, name, group, loc, gx, gy, w, d, h, what, how, talks
774
- optional slab:true
775
- optional children:[{code,name,h,what,how}]
776
-
777
- EDGES fields:
778
- f, t, pay
779
- optional flow:1, dashed:1, via:[[gx,gy], ...]
780
-
781
- EXTERNALS fields:
782
- id, name, target, gx, gy, pay
783
-
784
- TRACE contains 10-14 [structureId, sentence] entries.
785
- Keep structure footprints disjoint and all IDs stable across updates.
786
- ======================================================================== */
787
-
788
- const SAMPLE_DATA = false;
789
-
790
- const TITLE = "Wiki Viewer Architecture";
791
- const SUBTITLE = "Measured map of one Next.js server, its browser clients, agent API, and local stores";
792
-
793
- const STATS = [
794
- { value: "60,395", label: "source LOC" },
795
- { value: "79", label: "API routes" },
796
- { value: "71", label: "test files" },
797
- { value: "1", label: "deployed service" }
798
- ];
799
-
800
- const GROUPS = [
801
- { id: "surface", name: "Browser surfaces", color: "#d8a14a", labelGX: 5, labelGY: -1 },
802
- { id: "entry", name: "Entry and access", color: "#c86a52", labelGX: 4, labelGY: 4 },
803
- { id: "domain", name: "Core capabilities", color: "#6f9d83", labelGX: -1, labelGY: 10 },
804
- { id: "compute", name: "Runtime roles", color: "#6689a6", labelGX: 13, labelGY: 9 },
805
- { id: "data", name: "Durable stores", color: "#9a8eb4", labelGX: 8, labelGY: 19 },
806
- { id: "delivery", name: "Delivery", color: "#8b9272", labelGX: 1, labelGY: 14 }
807
- ];
808
-
809
- const STRUCTURES = [
810
- { id: "web-shell", code: "WS", name: "Web shell", group: "surface", loc: "5,443 LOC", gx: 1, gy: 0, w: 3, d: 2, h: 8, what: "The browser workbench where people browse folders, open files, and review changes.", how: "App routes, layout, wiki shell, viewer toolbar, and shared UI compose the protected workbench.", talks: ["hooks", "wiki-api", "share-api"], children: [
811
- { code: "AP", name: "App routes", h: 6, what: "Load the protected shell and route-level page surfaces.", how: "Next.js pages in src/app compose the sign-in, share, and main workbench surfaces behind the middleware gate." },
812
- { code: "WL", name: "Wiki layout", h: 7, what: "Compose navigation, directory tree, tabs, and the main canvas.", how: "layout.tsx plus the wiki sidebar and shell components assemble the directory tree, tabs, and viewer canvas into one protected frame." },
813
- { code: "UI", name: "Shared UI", h: 4, what: "Provide dialogs, menus, forms, and status primitives.", how: "Reusable components in src/components/ui centralize dialogs, menus, forms, and status elements used across surfaces." },
814
- { code: "TB", name: "Viewer toolbar", h: 3, what: "Expose file actions, history, sharing, and view controls.", how: "The editor toolbar and file actions menu wire view controls, history, sharing, and view-mode buttons to hooks and API calls." }
815
- ] },
816
- { id: "editor", code: "ED", name: "Editor and viewers", group: "surface", loc: "12,224 LOC", gx: 5, gy: 0, w: 4, d: 3, h: 13, what: "Shows many file types and lets people edit Markdown with rich interactions.", how: "TipTap extensions and viewer components handle Markdown, documents, media, notebooks, and websites.", talks: ["wiki-api", "proof", "state"], children: [
817
- { code: "TP", name: "TipTap editor", h: 8, what: "Turns Markdown blocks into an editable document.", how: "editor.tsx and extensions.ts register TipTap nodes and marks that map Markdown blocks to an editable ProseMirror document." },
818
- { code: "VW", name: "File viewers", h: 6, what: "Chooses a safe renderer for each supported file kind.", how: "A viewer registry dispatches per-type renderers for images, PDFs, media, notebooks, CSVs, Mermaid, websites, and MDX; the MDX viewer compiles .mdx in-browser via the mdx-js compiler and executes its JSX inside a null-origin allow-scripts iframe (React loaded from esm.sh) behind a default-off scripts consent." },
819
- { code: "CV", name: "Canvas viewer", h: 5, what: "Renders and edits .excalidraw scene JSON in an Excalidraw surface.", how: "The canvas viewer lazy-loads Excalidraw, debounces scene autosaves, embeds files, and reloads on sha256 conflicts; it renders read-only (viewModeEnabled) in git read-only workspaces and public share links." }
820
- ] },
821
- { id: "hooks", code: "HK", name: "Page-shell hooks", group: "surface", loc: "1,688 LOC", gx: 10, gy: 0, w: 2, d: 2, h: 5, what: "Connects page actions to workspaces, file trees, uploads, scratchpad, and navigation.", how: "Client hooks coordinate URL state, prefetching, workspace selection, and server calls.", talks: ["wiki-api", "workspace", "state"], children: [
822
- { code: "FT", name: "File tree", h: 6, what: "Load directories and preserve expanded navigation state.", how: "use-file-tree.ts fetches directory listings and keeps expanded nodes in sync with the active path." },
823
- { code: "OF", name: "Open file", h: 5, what: "Resolve selected files into editor or viewer content.", how: "use-open-file.ts maps selected paths to editor content or the correct file viewer." },
824
- { code: "WS", name: "Workspace switcher", h: 4, what: "Change roots without losing the current page intent.", how: "use-workspaces.ts lists roots and swaps the active workspace while preserving the current page." },
825
- { code: "UP", name: "Upload flow", h: 3, what: "Coordinate drops, progress, and post-upload refreshes.", how: "use-upload.ts stages dropped files, tracks progress, and refreshes the tree after uploads land." }
826
- ] },
827
- { id: "state", code: "ST", name: "Client state", group: "surface", loc: "1,453 LOC", gx: 13, gy: 0, w: 2, d: 2, h: 4, what: "Keeps open pages, editor status, search, favorites, and agent activity responsive.", how: "Zustand stores combine page caching, autosave state, revision recovery, and browser preferences.", talks: ["editor", "web-shell", "wiki-api"], children: [
828
- { code: "PG", name: "Page state", h: 6, what: "Track open paths, active tabs, and route transitions.", how: "Zustand stores hold open paths, active tabs, and route transition state shared across the shell." },
829
- { code: "ED", name: "Editor state", h: 7, what: "Track dirty content, save status, and revision recovery.", how: "editor-store.ts tracks dirty content, save status, and revision recovery for the active document." },
830
- { code: "SR", name: "Search state", h: 4, what: "Keep query, result scope, and selected matches stable.", how: "search-store.ts keeps query, scope, and selected matches stable across navigation." },
831
- { code: "AC", name: "Activity state", h: 3, what: "Surface agent events, presence, and collaboration status.", how: "ai-panel-store.ts and proof-store.ts hold agent events, presence, and collaboration status." }
832
- ] },
833
- { id: "ai-panel", code: "AI", name: "Agent panel", group: "surface", loc: "934 LOC", gx: 16, gy: 0, w: 2, d: 2, h: 3, what: "Lets people register agents, inspect activity, and follow collaboration status.", how: "A small client surface polls activity and calls registration, approval, and presence APIs.", talks: ["agent-api", "state"] },
834
-
835
- { id: "middleware", code: "MW", name: "Middleware gate", group: "entry", loc: "70 LOC", gx: 0, gy: 4, w: 2, d: 2, h: 3, what: "Stops protected pages before the app shell loads when no session cookie exists.", how: "src/middleware.ts applies the cookie gate, lite-mode deny list, and pass-through rules.", talks: ["web-shell", "auth"] },
836
- { id: "auth", code: "AU", name: "Human access", group: "entry", loc: "618 LOC", gx: 3, gy: 4, w: 2, d: 2, h: 5, what: "Authenticates people and checks whether state-changing browser requests are allowed.", how: "Better Auth, session checks, CSRF origin checks, admin rules, and embed-key checks share one boundary.", talks: ["middleware", "wiki-api", "system-api", "share-api"], children: [
837
- { code: "BA", name: "Better Auth", h: 7, what: "Create accounts, sessions, and sign-in responses.", how: "The Better Auth server instance issues accounts, sessions, and sign-in responses from the database adapter." },
838
- { code: "SS", name: "Session boundary", h: 6, what: "Resolve the current person before protected handlers run.", how: "Session checks resolve the current person before protected route handlers execute." },
839
- { code: "CS", name: "Origin checks", h: 4, what: "Reject cross-origin cookie mutations.", how: "CSRF origin checks reject state-changing requests that lack the expected origin." },
840
- { code: "AD", name: "Admin policy", h: 3, what: "Gate system settings and privileged app controls.", how: "Admin rules gate system settings and privileged controls behind a role check." }
841
- ] },
842
- { id: "workspace", code: "WS", name: "Workspace registry", group: "entry", loc: "918 LOC", gx: 6, gy: 4, w: 3, d: 2, h: 6, what: "Selects one of the server's registered roots for each request.", how: "workspaces.ts, config.ts, and workspace-context.ts resolve workspace headers, access, git roots, and remote mounts.", talks: ["path", "wiki-api", "system-api", "agent-api"], children: [
843
- { code: "RG", name: "Root registry", h: 6, what: "Stores and lists named workspace roots.", how: "config.ts and workspaces.ts store and list the named roots registered for the server." },
844
- { code: "CX", name: "Request context", h: 7, what: "Resolves workspace identity and access for each request.", how: "workspace-context.ts resolves the active workspace and access policy for each request." },
845
- { code: "GI", name: "Git roots", h: 4, what: "Recognizes repository-backed workspaces and branches.", how: "Git root detection recognizes repository-backed workspaces and exposes their branches." },
846
- { code: "RM", name: "Remote mounts", h: 3, what: "Connects registered roots to remote folder mounts.", how: "Remote mount config connects registered roots to SSHFS-backed folder mounts." }
847
- ] },
848
- { id: "path", code: "PT", name: "Path containment", group: "entry", loc: "343 LOC", gx: 10, gy: 4, w: 2, d: 2, h: 4, what: "Keeps file operations inside the selected workspace.", how: "resolveWorkspacePath realpaths roots, rejects traversal and denied segments, and checks symlink-safe ancestors.", talks: ["workspace", "wiki-api", "agent-api", "git"] },
849
- { id: "wiki-api", code: "WK", name: "Browser wiki API", group: "entry", loc: "2,701 LOC", gx: 13, gy: 4, w: 3, d: 2, h: 8, what: "Serves folder listings, file content, search, history, uploads, and watches.", how: "31 route handlers resolve user workspaces, validate origins, call domain libraries, and serialize responses.", talks: ["auth", "workspace", "path", "proof", "watch", "search", "git", "scratch"], children: [
850
- { code: "FI", name: "File operations", h: 8, what: "List, read, write, move, upload, and delete workspace files.", how: "Route handlers validate origins and call the filesystem library for list, read, write, move, upload, and delete; .excalidraw writes require a sha256 precondition." },
851
- { code: "GI", name: "Git views", h: 5, what: "Expose history, diffs, branches, and repository actions.", how: "Git routes wrap the git integration to expose history, diffs, branches, and repository actions." },
852
- { code: "SR", name: "Search and links", h: 5, what: "Serve content search, backlinks, and slug lookups.", how: "Search routes invoke the search engine for content matches, backlinks, and slug lookups." },
853
- { code: "WS", name: "Watch stream", h: 4, what: "Connect browser directories to file events.", how: "Watch routes subscribe request scopes to the watcher pool for file events." }
854
- ] },
855
- { id: "agent-api", code: "AG", name: "Agent HTTP API", group: "entry", loc: "2,612 LOC", gx: 17, gy: 4, w: 3, d: 2, h: 8, what: "Gives approved automation agents scoped file and collaboration operations.", how: "22 route handlers enforce bearer identity, workspace scope, path globs, revision checks, and operation permissions.", talks: ["auth", "workspace", "path", "proof", "search"], children: [
856
- { code: "FS", name: "Raw filesystem", h: 8, what: "Read, write, search, move, and delete arbitrary file bytes.", how: "Raw filesystem routes enforce bearer identity, workspace scope, and path globs before byte-level operations." },
857
- { code: "MD", name: "Markdown collab", h: 8, what: "Read snapshots and apply revision-checked block operations.", how: "Markdown routes read snapshots and apply revision-checked block operations through the proof core." },
858
- { code: "EV", name: "Events and activity", h: 4, what: "Stream document changes and provenance to agents.", how: "Event routes stream document changes and provenance to approved agents." },
859
- { code: "RG", name: "Registration", h: 4, what: "Register agents via TOFU approval or service-token bootstrap, and expose approved scopes.", how: "Registration routes record agents; a valid X-Service-Token header auto-approves and mints the bearer token inline; otherwise the owner approves and the agent polls a one-shot pickup." }
860
- ] },
861
-
862
- { id: "cli", code: "CL", name: "CLI launcher", group: "compute", loc: "1,862 LOC", gx: 0, gy: 7, w: 2, d: 2, h: 5, what: "Starts the packaged server and manages local service or remote-mount setup.", how: "bin/ parses options, applies environment precedence, starts the standalone server, and exposes service helpers.", talks: ["ci", "web-shell", "workspace", "sshfs"] },
863
- { id: "system-api", code: "SY", name: "System config API", group: "entry", loc: "902 LOC", gx: 3, gy: 7, w: 2, d: 2, h: 4, what: "Changes workspaces, users, administrators, pins, and local settings.", how: "14 route handlers use session and origin checks before mutating persisted configuration.", talks: ["auth", "workspace", "auth-store"] },
864
- { id: "share-api", code: "SH", name: "Shared documents", group: "entry", loc: "817 LOC", gx: 6, gy: 7, w: 3, d: 2, h: 4, what: "Publishes read-only document links with optional unlock and expiry controls.", how: "Share routes and shared-docs modules create opaque grants, validate unlocks, and render sanitized content.", talks: ["auth", "share-store", "markdown"] },
865
- { id: "mcp", code: "MC", name: "MCP adapter", group: "compute", loc: "2,911 LOC", gx: 10, gy: 7, w: 3, d: 2, h: 6, what: "Lets MCP clients use the agent contract through a separate npm package.", how: "packages/wiki-viewer-mcp defines 13 Zod-backed tools and a typed HTTP client with revision and scope errors; its register command auto-approves via the server service token when present.", talks: ["agent-api", "proof"] },
866
- { id: "app-runner", code: "AR", name: "Node app runner", group: "compute", loc: "738 LOC", gx: 14, gy: 7, w: 3, d: 2, h: 5, what: "Runs trusted node-app folders and proxies their local web surface.", how: "app-runner.ts manages child processes, readiness probes, ports, logs, access-checked forwarding (a workspace-root app has relPath '' and is proxied via the reserved ~root sentinel), pinned boot restore, crash caps, and file-change supervision.", talks: ["wiki-api", "path", "web-shell"] },
867
- { id: "git", code: "GT", name: "Git integration", group: "domain", loc: "871 LOC", gx: 18, gy: 7, w: 2, d: 2, h: 5, what: "Shows repository history and supports safe branch-oriented workspace actions.", how: "git.ts wraps the system binary, scans for leaked credentials, and backs history, diff, branch, and clone routes.", talks: ["wiki-api", "path", "workspace"] },
868
- { id: "sshfs", code: "SF", name: "SSHFS remotes", group: "domain", loc: "464 LOC", gx: 21, gy: 7, w: 2, d: 2, h: 4, what: "Makes remote folders appear as workspaces through a local mount boundary.", how: "sshfs.ts and mount helpers manage remote lifecycle, reconnects, and mount hazards.", talks: ["workspace", "path", "cli"] },
869
- { id: "hosted-apps", code: "HA", name: "Hosted apps", group: "compute", loc: "560 LOC", gx: 24, gy: 7, w: 2, d: 2, h: 4, what: "Maps short user-chosen slugs to HTML directories or running node apps reachable at /app/<slug>.", how: "hosted-apps.ts persists the slug registry (~/.wiki-viewer/hosted-apps.json); /api/wiki/hosted-apps manages entries, pinning, and derived node status; the sidebar sorts pinned apps first and exposes status/error popovers with restart-now; app-proxy-core.ts forwards existing and slug-routed node traffic while the /app/<slug> route serves HTML dirs dir-aware or proxies each request to the live child port.", talks: ["wiki-api", "path", "workspace", "app-runner", "web-shell"] },
870
-
871
- { id: "proof", code: "PR", name: "Proof core", group: "domain", loc: "1,397 LOC", gx: 1, gy: 10, w: 4, d: 3, h: 10, what: "Applies structured Markdown edits while preserving revisions, references, comments, and suggestions.", how: "ops-applier.ts parses blocks, checks base revisions, applies operations, writes atomically, and updates sidecar metadata.", talks: ["safety", "markdown", "auth-store", "audit-store"], children: [
872
- { code: "OP", name: "Block operations", h: 9, what: "Apply insert, replace, delete, and annotation operations.", how: "ops-applier.ts applies insert, replace, delete, and annotation operations against parsed blocks." },
873
- { code: "RF", name: "Reference map", h: 5, what: "Keeps stable block references across edits.", how: "block-refs.ts keeps stable block references valid across edits." },
874
- { code: "SC", name: "Sidecar state", h: 6, what: "Stores revisions, activity, comments, and suggestions beside files.", how: "sidecar.ts and activity.ts store revisions, activity, comments, and suggestions beside each file." },
875
- { code: "EV", name: "Event bus", h: 4, what: "Publishes document changes to watchers and agents.", how: "event-bus.ts publishes document changes to watchers and agent subscribers." }
876
- ] },
877
- { id: "safety", code: "LK", name: "Locking and audit", group: "domain", loc: "539 LOC", gx: 6, gy: 10, w: 3, d: 2, h: 7, what: "Prevents concurrent edits from silently overwriting one another.", how: "Mutexes, proper-lockfile, leases, collab state, idempotency, rate limits, and audit rows protect writes.", talks: ["proof", "audit-store"] },
878
- { id: "watch", code: "WT", name: "Watch and SSE", group: "compute", loc: "725 LOC", gx: 14, gy: 10, w: 2, d: 2, h: 5, what: "Notifies browser and agent clients when files change outside their current request.", how: "watcher-pool.ts uses chokidar subscriptions, ancestor merging, scope rebasing, deduplication, and heartbeats.", talks: ["wiki-api", "state", "proof"], children: [
879
- { code: "CH", name: "Chokidar pool", h: 7, what: "Share filesystem watchers across compatible scopes.", how: "watcher-pool.ts shares chokidar watchers across compatible scopes." },
880
- { code: "RB", name: "Scope rebasing", h: 5, what: "Map ancestor events back to subscribed workspace paths.", how: "Scope rebasing maps ancestor events back to subscribed workspace paths." },
881
- { code: "DD", name: "Deduplication", h: 4, what: "Collapse repeated changes into useful event payloads.", how: "Deduplication collapses repeated changes into one useful event payload." },
882
- { code: "HB", name: "Heartbeats", h: 3, what: "Keep long-lived browser and agent streams alive.", how: "Heartbeats keep long-lived browser and agent streams alive." }
883
- ] },
884
- { id: "search", code: "SE", name: "Search engine", group: "domain", loc: "1,845 LOC", gx: 17, gy: 10, w: 3, d: 2, h: 8, what: "Finds files and content without loading an entire workspace into memory.", how: "Ripgrep adapters stream bounded JSON results, retry advanced patterns, and verify backlinks through Markdown parsing.", talks: ["wiki-api", "agent-api", "markdown", "path"], children: [
885
- { code: "RG", name: "Ripgrep adapter", h: 7, what: "Stream bounded file and content matches.", how: "rg-search.ts and rg-snippet.ts stream bounded ripgrep matches as JSON; .excalidraw scene JSON is excluded from full-text content search while filename search still finds it." },
886
- { code: "FP", name: "File paths", h: 5, what: "Filter hidden, denied, and out-of-scope paths.", how: "rg-path.ts filters hidden, denied, and out-of-scope paths before searching." },
887
- { code: "BL", name: "Backlinks", h: 6, what: "Parse Markdown references and return incoming links.", how: "backlinks.ts parses Markdown references and returns incoming links." },
888
- { code: "RT", name: "Retry policy", h: 3, what: "Retry advanced queries when the fast path rejects them.", how: "The retry policy reruns advanced queries when the fast path rejects them." }
889
- ] },
890
-
891
- { id: "markdown", code: "MD", name: "Markdown pipeline", group: "domain", loc: "1,023 LOC", gx: 0, gy: 13, w: 3, d: 2, h: 6, what: "Converts Markdown into safe HTML and understands links, embeds, tasks, and frontmatter.", how: "Unified remark and rehype plugins parse, sanitize, rewrite relative assets, detect embeds, and cache output.", talks: ["proof", "search", "share-api", "editor"], children: [
892
- { code: "PA", name: "Parser", h: 7, what: "Build an AST from Markdown and GitHub-flavored syntax.", how: "Unified remark plugins parse Markdown and GitHub-flavored syntax into an AST." },
893
- { code: "HT", name: "HTML renderer", h: 6, what: "Convert parsed content into safe display HTML.", how: "to-html.ts runs rehype plugins and the sanitize schema to emit safe HTML." },
894
- { code: "WL", name: "Wiki links", h: 4, what: "Resolve internal links and relative asset references.", how: "wikilink.ts resolves internal links and relative asset references." },
895
- { code: "EM", name: "Embeds", h: 4, what: "Detect supported external media and document embeds.", how: "lib/embeds detects supported external media and document embeds." }
896
- ] },
897
- { id: "scratch", code: "SC", name: "Scratchpad", group: "domain", loc: "355 LOC", gx: 8, gy: 13, w: 2, d: 2, h: 4, what: "Captures quick snippets before they become normal workspace files.", how: "Scratch config and detection modules create, sweep, and promote temporary captures.", talks: ["wiki-api", "path", "state"] },
898
- { id: "tests", code: "TS", name: "Proof test suite", group: "delivery", loc: "14,849 LOC", gx: 12, gy: 13, w: 2, d: 2, h: 5, what: "Exercises the filesystem, auth, collaboration, and agent safety contracts.", how: "71 proof test files run through scripts/test-floor.mjs, which enforces a 673-test minimum.", talks: ["proof", "agent-api", "wiki-api", "ci"] },
899
- { id: "ci", code: "CI", name: "Build and publish", group: "delivery", loc: "3 workflow files", gx: 15, gy: 13, w: 3, d: 2, h: 3, what: "Checks changes and prepares the standalone package for release.", how: "Versioned workflows run formatting, tests, builds, and npm publishing around the one server artifact.", talks: ["cli", "editor", "agent-api", "tests"] },
900
-
901
- { id: "auth-store", code: "DB", name: "Auth store", group: "data", loc: "role", gx: 0, gy: 16, w: 3, d: 2, h: 1, slab: true, what: "Durable users, sessions, and account records.", how: "Better Auth uses a local SQLite store through the project database adapter.", talks: ["auth", "system-api", "proof"] },
902
- { id: "share-store", code: "DB", name: "Share store", group: "data", loc: "role", gx: 4, gy: 16, w: 3, d: 2, h: 1, slab: true, what: "Durable public-share grants, expiry data, and view counts.", how: "shared-docs/db.ts persists opaque share metadata in SQLite.", talks: ["share-api"] },
903
- { id: "audit-store", code: "DB", name: "Audit store", group: "data", loc: "role", gx: 12, gy: 16, w: 3, d: 2, h: 1, slab: true, what: "Append-only records of scoped agent filesystem operations.", how: "proof/audit.ts writes operation, path, revision, and hash metadata to SQLite.", talks: ["safety", "agent-api"] }
904
- ];
905
-
906
- const EDGES = [
907
- { f: "middleware", t: "web-shell", flow: 1, pay: "Session gate" },
908
- { f: "web-shell", t: "hooks", flow: 1, pay: "Page actions" },
909
- { f: "hooks", t: "wiki-api", flow: 1, pay: "Workspace request" },
910
- { f: "wiki-api", t: "auth", flow: 1, pay: "Session context" },
911
- { f: "wiki-api", t: "workspace", flow: 1, pay: "Workspace choice" },
912
- { f: "workspace", t: "path", flow: 1, pay: "Root and relative path" },
913
- { f: "wiki-api", t: "proof", flow: 1, pay: "Markdown command" },
914
- { f: "editor", t: "wiki-api", flow: 1, pay: "Read or save" },
915
- { f: "wiki-api", t: "watch", flow: 1, pay: "Watch scope" },
916
- { f: "watch", t: "state", flow: 1, pay: "File event" },
917
- { f: "agent-api", t: "proof", flow: 1, pay: "Scoped block ops" },
918
- { f: "proof", t: "safety", flow: 1, pay: "Locked mutation" },
919
- { f: "safety", t: "audit-store", flow: 1, pay: "Audit row" },
920
- { f: "proof", t: "auth-store", flow: 1, pay: "Access-linked state" },
921
- { f: "share-api", t: "share-store", flow: 1, pay: "Share grant" },
922
- { f: "share-api", t: "markdown", flow: 1, pay: "Safe rendering" },
923
- { f: "proof", t: "markdown", flow: 1, pay: "Parsed document" },
924
- { f: "search", t: "markdown", flow: 1, pay: "Parsed backlink" },
925
- { f: "wiki-api", t: "search", flow: 1, pay: "Query" },
926
- { f: "wiki-api", t: "git", flow: 1, pay: "Repository action" },
927
- { f: "workspace", t: "sshfs", flow: 1, pay: "Remote workspace" },
928
- { f: "wiki-api", t: "scratch", flow: 1, pay: "Quick capture" },
929
- { f: "wiki-api", t: "app-runner", flow: 1, pay: "Trusted app launch" },
930
- { f: "app-runner", t: "web-shell", flow: 1, pay: "Proxied preview" },
931
- { f: "wiki-api", t: "hosted-apps", flow: 1, pay: "Hosted app registry" },
932
- { f: "hosted-apps", t: "web-shell", flow: 1, pay: "Slug-served app" },
933
- { f: "mcp", t: "agent-api", flow: 1, pay: "MCP tool call" },
934
- { f: "ai-panel", t: "agent-api", flow: 1, pay: "Agent management" },
935
- { f: "state", t: "editor", flow: 1, pay: "Page state" },
936
- { f: "cli", t: "web-shell", dashed: 1, pay: "Server startup" },
937
- { f: "ci", t: "cli", dashed: 1, pay: "Package output" },
938
- { f: "ci", t: "tests", dashed: 1, pay: "Quality checks" },
939
- { f: "tests", t: "proof", dashed: 1, pay: "Contract coverage" }
940
- ];
941
-
942
- const EXTERNALS = [
943
- { id: "browser", name: "Browser", target: "web-shell", gx: 4, gy: -3, pay: "User interaction" },
944
- { id: "identity-service", name: "Identity service", target: "auth", gx: -3, gy: 5, pay: "Optional identity" },
945
- { id: "git-host", name: "Git host", target: "git", gx: 23, gy: 6, pay: "Repository data" },
946
- ];
947
-
948
- const TRACE = [
949
- ["web-shell", "A person opens the browser workbench."],
950
- ["middleware", "Middleware checks for the session gate before protected pages render."],
951
- ["web-shell", "The app shell mounts its workspace and file-tree controls."],
952
- ["hooks", "Page hooks request available workspaces and the current directory listing."],
953
- ["wiki-api", "The wiki API validates the request and selects the content handler."],
954
- ["workspace", "Workspace context resolves the selected root and access policy."],
955
- ["path", "Path containment resolves the relative file without crossing the root."],
956
- ["editor", "The editor renders the Markdown snapshot and starts its watch stream."],
957
- ["proof", "A debounced save applies the new blocks and advances the revision atomically."],
958
- ["agent-api", "An approved agent receives the request and returns scoped operations."],
959
- ["state", "Client state records the revision and refreshes the visible page."],
960
- ["web-shell", "The browser presents the saved document and current activity." ]
961
- ];
962
-
963
- const OVERVIEW_WHAT = "Wiki Viewer is one local-first web server for browsing and editing many file types. Its browser workbench, scoped agent API, and MCP adapter all meet at workspace-aware filesystem operations, with Markdown collaboration adding revisions and provenance around ordinary files.";
964
- const OVERVIEW_HOW = "The standalone Next.js server owns request routing, auth, workspace selection, path containment, rendering, git and remote adapters, app launching, and three SQLite-backed roles. Human saves and agent block operations share locks and revision checks. Chokidar watchers, SSE streams, and timers provide asynchronous behavior inside the same deployed service; no separate queue or worker service is present.";
965
-
966
- /* ============================== END DATA ============================== */
967
-
968
- (function () {
969
- const NS = "http:" + "//www.w3.org/2000/svg";
970
- const VIEW_W = 1000;
971
- const VIEW_H = 790;
972
- const ORIGIN_X = 493;
973
- const ORIGIN_Y = 175;
974
- const ISO_X = 26;
975
- const ISO_Y = 14.3;
976
- const ISO_H = 16;
977
-
978
- const svg = document.getElementById("map");
979
- const nav = document.getElementById("structure-nav");
980
- const detail = document.getElementById("detail");
981
- const tooltip = document.getElementById("tooltip");
982
- const traceCard = document.getElementById("trace-card");
983
- const insideBack = document.getElementById("inside-back");
984
- const groupById = new Map(GROUPS.map((group) => [group.id, group]));
985
- const structureById = new Map(STRUCTURES.map((structure) => [structure.id, structure]));
986
- let selectedId = null;
987
- let insideId = null;
988
- let traceIndex = null;
989
-
990
- function esc(value) {
991
- return String(value)
992
- .replaceAll("&", "&amp;")
993
- .replaceAll("<", "&lt;")
994
- .replaceAll(">", "&gt;")
995
- .replaceAll('"', "&quot;")
996
- .replaceAll("'", "&#39;");
997
- }
998
-
999
- function svgEl(name, attrs, text) {
1000
- const node = document.createElementNS(NS, name);
1001
- Object.entries(attrs || {}).forEach(([key, value]) => node.setAttribute(key, String(value)));
1002
- if (text !== undefined) node.textContent = String(text);
1003
- return node;
1004
- }
1005
-
1006
- function project(gx, gy, h) {
1007
- return [ORIGIN_X + (gx - gy) * ISO_X, ORIGIN_Y + (gx + gy) * ISO_Y - h * ISO_H];
1008
- }
1009
-
1010
- function points(values) {
1011
- return values.map((point) => point.join(",")).join(" ");
1012
- }
1013
-
1014
- function shade(hex, amount) {
1015
- const raw = hex.replace("#", "");
1016
- const value = parseInt(raw, 16);
1017
- const r = Math.max(0, Math.min(255, (value >> 16) + amount));
1018
- const g = Math.max(0, Math.min(255, ((value >> 8) & 255) + amount));
1019
- const b = Math.max(0, Math.min(255, (value & 255) + amount));
1020
- return `rgb(${r},${g},${b})`;
1021
- }
1022
-
1023
- function structureCenter(structure) {
1024
- return {
1025
- gx: structure.gx + structure.w / 2,
1026
- gy: structure.gy + structure.d / 2
1027
- };
1028
- }
1029
-
1030
- function clearDrawing() {
1031
- svg.querySelectorAll(".drawing-layer").forEach((node) => node.remove());
1032
- }
1033
-
1034
- function makeLayer(name) {
1035
- const layer = svgEl("g", { class: `drawing-layer ${name}` });
1036
- svg.appendChild(layer);
1037
- return layer;
1038
- }
1039
-
1040
- function drawGround(layer) {
1041
- for (let i = -5; i <= 24; i += 2) {
1042
- const a = project(i, -4, 0);
1043
- const b = project(i, 23, 0);
1044
- layer.appendChild(svgEl("line", { class: "ground-line", x1: a[0], y1: a[1], x2: b[0], y2: b[1] }));
1045
- }
1046
- for (let i = -4; i <= 23; i += 2) {
1047
- const a = project(-5, i, 0);
1048
- const b = project(24, i, 0);
1049
- layer.appendChild(svgEl("line", { class: "ground-line", x1: a[0], y1: a[1], x2: b[0], y2: b[1] }));
1050
- }
1051
- }
1052
-
1053
- function routeFor(edge) {
1054
- const from = structureById.get(edge.f);
1055
- const to = structureById.get(edge.t);
1056
- if (!from || !to) return null;
1057
- const start = structureCenter(from);
1058
- const end = structureCenter(to);
1059
- const logical = [
1060
- [start.gx, start.gy],
1061
- ...(edge.via || [[end.gx, start.gy]]),
1062
- [end.gx, end.gy]
1063
- ];
1064
- const projected = logical.map(([gx, gy]) => project(gx, gy, 0.08));
1065
- return `M ${projected.map((point) => `${point[0]} ${point[1]}`).join(" L ")}`;
1066
- }
1067
-
1068
- function showTooltip(event, title, body) {
1069
- tooltip.innerHTML = `<strong>${esc(title)}</strong><span>${esc(body)}</span>`;
1070
- const left = Math.min(window.innerWidth - 270, event.clientX + 12);
1071
- const top = Math.min(window.innerHeight - 120, event.clientY + 12);
1072
- tooltip.style.left = `${Math.max(10, left)}px`;
1073
- tooltip.style.top = `${Math.max(10, top)}px`;
1074
- tooltip.classList.add("show");
1075
- }
1076
-
1077
- function hideTooltip() {
1078
- tooltip.classList.remove("show");
1079
- }
1080
-
1081
- function drawEdges(layer) {
1082
- EDGES.forEach((edge, index) => {
1083
- const d = routeFor(edge);
1084
- if (!d) return;
1085
- const path = svgEl("path", {
1086
- id: `flow-path-${index}`,
1087
- class: `edge-line${edge.flow ? " flow" : ""}${edge.dashed ? " dashed" : ""}`,
1088
- d,
1089
- "data-from": edge.f,
1090
- "data-to": edge.t
1091
- });
1092
- const hit = svgEl("path", { class: "edge-hit", d, tabindex: "0" });
1093
- const describe = (event) => showTooltip(event, `${structureById.get(edge.f).name} → ${structureById.get(edge.t).name}`, edge.pay);
1094
- hit.addEventListener("pointermove", describe);
1095
- hit.addEventListener("pointerleave", hideTooltip);
1096
- hit.addEventListener("focus", (event) => showTooltip({ clientX: window.innerWidth / 2, clientY: 120 }, "Data flow", edge.pay));
1097
- hit.addEventListener("blur", hideTooltip);
1098
- layer.appendChild(path);
1099
- layer.appendChild(hit);
1100
-
1101
- if (edge.flow) {
1102
- [0, 1].forEach((dotIndex) => {
1103
- const circle = svgEl("circle", { class: "flow-dot", r: 3.5, "data-pay": edge.pay });
1104
- const motion = svgEl("animateMotion", {
1105
- path: d,
1106
- dur: `${5.5 + (index % 4) * 0.8}s`,
1107
- begin: `${dotIndex * -2.7}s`,
1108
- repeatCount: "indefinite"
1109
- });
1110
- circle.appendChild(motion);
1111
- circle.addEventListener("pointermove", (event) => showTooltip(event, "In transit", edge.pay));
1112
- circle.addEventListener("pointerleave", hideTooltip);
1113
- layer.appendChild(circle);
1114
- });
1115
- }
1116
- });
1117
- }
1118
-
1119
- function blockGeometry(structure) {
1120
- const height = structure.slab ? Math.max(0.55, structure.h) : structure.h;
1121
- const topA = project(structure.gx, structure.gy, height);
1122
- const topB = project(structure.gx + structure.w, structure.gy, height);
1123
- const topC = project(structure.gx + structure.w, structure.gy + structure.d, height);
1124
- const topD = project(structure.gx, structure.gy + structure.d, height);
1125
- const baseB = project(structure.gx + structure.w, structure.gy, 0);
1126
- const baseC = project(structure.gx + structure.w, structure.gy + structure.d, 0);
1127
- const baseD = project(structure.gx, structure.gy + structure.d, 0);
1128
- return { height, topA, topB, topC, topD, baseB, baseC, baseD };
1129
- }
1130
-
1131
- function drawBlock(layer, structure, options) {
1132
- const settings = options || {};
1133
- const group = groupById.get(structure.group) || { color: "#a69d88" };
1134
- const color = settings.color || group.color;
1135
- const geometry = blockGeometry(structure);
1136
- const node = svgEl("g", {
1137
- class: "structure",
1138
- tabindex: "0",
1139
- role: "button",
1140
- "aria-label": `${structure.name}, ${structure.loc || "internal structure"}`,
1141
- "data-id": structure.id
1142
- });
1143
-
1144
- node.appendChild(svgEl("polygon", {
1145
- class: "face right",
1146
- points: points([geometry.topB, geometry.topC, geometry.baseC, geometry.baseB]),
1147
- fill: shade(color, -36)
1148
- }));
1149
- node.appendChild(svgEl("polygon", {
1150
- class: "face left",
1151
- points: points([geometry.topC, geometry.topD, geometry.baseD, geometry.baseC]),
1152
- fill: shade(color, -18)
1153
- }));
1154
- node.appendChild(svgEl("polygon", {
1155
- class: "face top",
1156
- points: points([geometry.topA, geometry.topB, geometry.topC, geometry.topD]),
1157
- fill: color
1158
- }));
1159
- node.appendChild(svgEl("polygon", {
1160
- points: points([geometry.topA, geometry.topB, geometry.topC, geometry.topD]),
1161
- fill: "url(#fine-hatch)",
1162
- "pointer-events": "none"
1163
- }));
1164
-
1165
- const topCenter = project(structure.gx + structure.w / 2, structure.gy + structure.d / 2, geometry.height);
1166
- node.appendChild(svgEl("text", { class: "block-code", x: topCenter[0], y: topCenter[1] - 2 }, structure.code));
1167
- node.appendChild(svgEl("text", { class: "block-loc", x: topCenter[0], y: topCenter[1] + 11 }, structure.loc || ""));
1168
-
1169
- const activate = () => settings.onSelect ? settings.onSelect(structure) : selectStructure(structure.id);
1170
- node.addEventListener("click", activate);
1171
- node.addEventListener("keydown", (event) => {
1172
- if (event.key === "Enter" || event.key === " ") {
1173
- event.preventDefault();
1174
- activate();
1175
- }
1176
- });
1177
- node.addEventListener("pointermove", (event) => {
1178
- showTooltip(event, `${structure.name} · ${structure.loc || ""}`, structure.what);
1179
- if (!settings.noNeighbors) highlightNeighborhood(structure.id);
1180
- });
1181
- node.addEventListener("pointerleave", () => {
1182
- hideTooltip();
1183
- if (!settings.noNeighbors) applyHighlightState();
1184
- });
1185
- node.addEventListener("focus", () => {
1186
- if (!settings.noNeighbors) highlightNeighborhood(structure.id);
1187
- });
1188
- node.addEventListener("blur", () => {
1189
- if (!settings.noNeighbors) applyHighlightState();
1190
- });
1191
- layer.appendChild(node);
1192
- return node;
1193
- }
1194
-
1195
- function drawExternals(layer) {
1196
- EXTERNALS.forEach((external) => {
1197
- const target = structureById.get(external.target);
1198
- if (!target) return;
1199
- const targetCenter = structureCenter(target);
1200
- const start = project(external.gx, external.gy, 0.1);
1201
- const end = project(targetCenter.gx, targetCenter.gy, 0.1);
1202
- const width = Math.max(118, external.name.length * 7.2);
1203
- const group = svgEl("g", { tabindex: "0", role: "note" });
1204
- group.appendChild(svgEl("path", { class: "external-line", d: `M ${start[0]} ${start[1]} L ${end[0]} ${end[1]}` }));
1205
- group.appendChild(svgEl("rect", { class: "external-card", x: start[0] - width / 2, y: start[1] - 18, width, height: 35, rx: 2 }));
1206
- group.appendChild(svgEl("text", { class: "external-name", x: start[0], y: start[1] - 3, "text-anchor": "middle" }, external.name));
1207
- group.appendChild(svgEl("text", { class: "external-pay", x: start[0], y: start[1] + 10, "text-anchor": "middle" }, external.pay));
1208
- group.addEventListener("pointermove", (event) => showTooltip(event, external.name, external.pay));
1209
- group.addEventListener("pointerleave", hideTooltip);
1210
- layer.appendChild(group);
1211
- });
1212
- }
1213
-
1214
- function drawZoneLabels(layer) {
1215
- const labels = GROUPS
1216
- .filter(
1217
- (group) =>
1218
- Number.isFinite(group.labelGX)
1219
- && Number.isFinite(group.labelGY)
1220
- )
1221
- .map((group) => [group.name.toUpperCase(), group.labelGX, group.labelGY]);
1222
-
1223
- labels.forEach(([label, gx, gy]) => {
1224
- const at = project(gx, gy, 0);
1225
- layer.appendChild(svgEl("text", { class: "zone-label", x: at[0], y: at[1], "text-anchor": "middle" }, label));
1226
- });
1227
- }
1228
-
1229
- function renderCity() {
1230
- insideId = null;
1231
- insideBack.classList.remove("show");
1232
- clearDrawing();
1233
- const ground = makeLayer("ground-layer");
1234
- const edges = makeLayer("edge-layer");
1235
- const blocks = makeLayer("block-layer");
1236
- const externals = makeLayer("external-layer");
1237
- drawGround(ground);
1238
- drawZoneLabels(ground);
1239
- drawEdges(edges);
1240
- STRUCTURES
1241
- .slice()
1242
- .sort((a, b) => (a.gx + a.gy) - (b.gx + b.gy))
1243
- .forEach((structure) => drawBlock(blocks, structure));
1244
- drawExternals(externals);
1245
- applyHighlightState();
1246
- }
1247
-
1248
- function renderInside(parent) {
1249
- insideId = parent.id;
1250
- selectedId = parent.id;
1251
- traceIndex = null;
1252
- traceCard.classList.remove("show");
1253
- insideBack.classList.add("show");
1254
- clearDrawing();
1255
- const ground = makeLayer("ground-layer");
1256
- const blocks = makeLayer("block-layer");
1257
- drawGround(ground);
1258
-
1259
- ground.appendChild(svgEl("rect", { class: "inside-boundary", x: 130, y: 130, width: 740, height: 520, rx: 8 }));
1260
- ground.appendChild(svgEl("text", { class: "inside-title", x: 165, y: 184 }, `Inside ${parent.name}`));
1261
- ground.appendChild(svgEl("text", { class: "inside-note", x: 166, y: 207 }, "COMPONENT RESPONSIBILITIES · HEIGHTS FOLLOW RELATIVE SIZE"));
1262
-
1263
- const children = parent.children || [];
1264
- children.forEach((child, index) => {
1265
- const column = index % 3;
1266
- const row = Math.floor(index / 3);
1267
- const structure = {
1268
- id: `${parent.id}-child-${index}`,
1269
- code: child.code,
1270
- name: child.name,
1271
- group: parent.group,
1272
- loc: child.loc || "internal",
1273
- gx: 5 + column * 5,
1274
- gy: 8 + row * 6,
1275
- w: 3,
1276
- d: 2.4,
1277
- h: child.h,
1278
- what: child.what,
1279
- how: parent.how,
1280
- talks: []
1281
- };
1282
- drawBlock(blocks, structure, {
1283
- color: (groupById.get(parent.group) || { color: "#9d9480" }).color,
1284
- noNeighbors: true,
1285
- onSelect: () => renderChildDetail(parent, child)
1286
- });
1287
- });
1288
- renderStructureDetail(parent);
1289
- syncNav();
1290
- }
1291
-
1292
- function highlightNeighborhood(id) {
1293
- const neighbors = new Set([id]);
1294
- EDGES.forEach((edge) => {
1295
- if (edge.f === id) neighbors.add(edge.t);
1296
- if (edge.t === id) neighbors.add(edge.f);
1297
- });
1298
- svg.querySelectorAll(".structure").forEach((node) => {
1299
- node.classList.toggle("dimmed", !neighbors.has(node.dataset.id));
1300
- });
1301
- svg.querySelectorAll(".edge-line").forEach((node) => {
1302
- node.classList.toggle("active", node.dataset.from === id || node.dataset.to === id);
1303
- });
1304
- }
1305
-
1306
- function applyHighlightState() {
1307
- const active = traceIndex !== null ? TRACE[traceIndex][0] : selectedId;
1308
- const completedIds = traceIndex !== null
1309
- ? new Set(TRACE.slice(0, traceIndex + 1).map(([id]) => id))
1310
- : new Set();
1311
- const transitions = traceIndex !== null
1312
- ? TRACE.slice(1, traceIndex + 1).map(([to], index) => [TRACE[index][0], to])
1313
- : [];
1314
- svg.querySelectorAll(".structure").forEach((node) => {
1315
- const isCurrent = traceIndex !== null && node.dataset.id === active;
1316
- const isComplete = traceIndex !== null && completedIds.has(node.dataset.id) && !isCurrent;
1317
- node.classList.toggle("dimmed", traceIndex !== null && !completedIds.has(node.dataset.id));
1318
- node.classList.toggle("active", traceIndex === null && node.dataset.id === active);
1319
- node.classList.toggle("trace-complete", isComplete);
1320
- node.classList.toggle("trace-current", isCurrent);
1321
- });
1322
- svg.querySelectorAll(".edge-line").forEach((node) => {
1323
- let lastMatch = -1;
1324
- transitions.forEach(([from, to], index) => {
1325
- const matches = (node.dataset.from === from && node.dataset.to === to)
1326
- || (node.dataset.from === to && node.dataset.to === from);
1327
- if (matches) lastMatch = index;
1328
- });
1329
- node.classList.toggle("active", false);
1330
- node.classList.toggle("trace-complete", lastMatch >= 0 && lastMatch < transitions.length - 1);
1331
- node.classList.toggle("trace-current", lastMatch >= 0 && lastMatch === transitions.length - 1);
1332
- });
1333
- syncNav();
1334
- }
1335
-
1336
- function syncNav() {
1337
- nav.querySelectorAll(".structure-link").forEach((button) => {
1338
- button.classList.toggle("active", button.dataset.id === selectedId);
1339
- });
1340
- }
1341
-
1342
- function renderNav() {
1343
- nav.textContent = "";
1344
- GROUPS.forEach((group) => {
1345
- const members = STRUCTURES.filter((structure) => structure.group === group.id);
1346
- if (!members.length) return;
1347
- const section = document.createElement("section");
1348
- section.className = "group";
1349
- const title = document.createElement("p");
1350
- title.className = "group-title";
1351
- title.innerHTML = `<span class="swatch" style="background:${esc(group.color)}"></span>${esc(group.name)}`;
1352
- section.appendChild(title);
1353
- members.forEach((structure) => {
1354
- const button = document.createElement("button");
1355
- button.type = "button";
1356
- button.className = "structure-link";
1357
- button.dataset.id = structure.id;
1358
- button.style.setProperty("--chip", group.color);
1359
- button.innerHTML = `<span class="code-chip">${esc(structure.code)}</span><span class="name">${esc(structure.name)}</span><span class="loc">${esc(structure.loc)}</span>`;
1360
- button.addEventListener("click", () => {
1361
- if (location.hash) history.replaceState(null, "", location.pathname + location.search);
1362
- if (insideId) renderCity();
1363
- traceIndex = null;
1364
- traceCard.classList.remove("show");
1365
- selectStructure(structure.id);
1366
- });
1367
- section.appendChild(button);
1368
- });
1369
- nav.appendChild(section);
1370
- });
1371
- }
1372
-
1373
- function renderOverview() {
1374
- selectedId = null;
1375
- detail.innerHTML = `
1376
- <p class="eyebrow">System overview</p>
1377
- <h2>${esc(TITLE)}</h2>
1378
- <div class="detail-meta"><span>${STRUCTURES.length} structures</span><span>${EDGES.length} connections</span></div>
1379
- <section class="detail-section"><h3>What it does</h3><p>${esc(OVERVIEW_WHAT)}</p></section>
1380
- <section class="detail-section"><h3>How it's built</h3><p>${esc(OVERVIEW_HOW)}</p></section>
1381
- <section class="detail-section"><h3>How to explore</h3><p>Hover blocks and moving dots for context. Select a structure for details. Request trace reveals a numbered path: orange marks completed steps and red marks the current step. Structures with internal components offer a go-inside view.</p></section>`;
1382
- syncNav();
1383
- }
1384
-
1385
- function renderStructureDetail(structure) {
1386
- const group = groupById.get(structure.group);
1387
- const connections = (structure.talks || [])
1388
- .map((id) => structureById.get(id))
1389
- .filter(Boolean);
1390
- const connectionsHtml = connections.length
1391
- ? `<ul>${connections.map((item) => `<li>${esc(item.name)}</li>`).join("")}</ul>`
1392
- : `<p>No outgoing runtime connection is shown.</p>`;
1393
- detail.innerHTML = `
1394
- <p class="eyebrow">${esc(group ? group.name : "Structure")}</p>
1395
- <h2>${esc(structure.name)}</h2>
1396
- <div class="detail-meta"><span>${esc(structure.code)}</span><span>${esc(structure.loc)}</span>${structure.slab ? "<span>storage slab</span>" : ""}</div>
1397
- <section class="detail-section"><h3>What it does</h3><p>${esc(structure.what)}</p></section>
1398
- <section class="detail-section"><h3>How it's built</h3><p>${esc(structure.how)}</p></section>
1399
- <section class="detail-section"><h3>Talks to</h3>${connectionsHtml}</section>
1400
- ${structure.children && structure.children.length ? `<button class="inside-button" id="go-inside" type="button">Go inside · ${structure.children.length} components</button>` : ""}`;
1401
- const insideButton = document.getElementById("go-inside");
1402
- if (insideButton) insideButton.addEventListener("click", () => { location.hash = `inside=${encodeURIComponent(structure.id)}`; });
1403
- }
1404
-
1405
- function renderChildDetail(parent, child) {
1406
- detail.innerHTML = `
1407
- <p class="eyebrow">Inside ${esc(parent.name)}</p>
1408
- <h2>${esc(child.name)}</h2>
1409
- <div class="detail-meta"><span>${esc(child.code)}</span><span>internal component</span></div>
1410
- <section class="detail-section"><h3>What it does</h3><p>${esc(child.what)}</p></section>
1411
- <section class="detail-section"><h3>How it works</h3><p>${esc(child.how)}</p></section>
1412
- <section class="detail-section"><h3>Parent implementation</h3><p>${esc(parent.how)}</p></section>`;
1413
- }
1414
-
1415
- function selectStructure(id) {
1416
- const structure = structureById.get(id);
1417
- if (!structure) return;
1418
- selectedId = id;
1419
- renderStructureDetail(structure);
1420
- applyHighlightState();
1421
- }
1422
-
1423
- function renderTrace(index) {
1424
- const safeIndex = Math.max(0, Math.min(TRACE.length - 1, index));
1425
- traceIndex = safeIndex;
1426
- const [id, sentence] = TRACE[safeIndex];
1427
- const structure = structureById.get(id);
1428
- const traceStepsHtml = TRACE.map(([stepId], stepIndex) => {
1429
- const stepStructure = structureById.get(stepId);
1430
- const state = stepIndex === safeIndex ? " current" : (stepIndex < safeIndex ? " complete" : "");
1431
- const label = stepStructure ? stepStructure.code : String(stepIndex + 1);
1432
- const name = stepStructure ? stepStructure.name : stepId;
1433
- return `<button class="trace-step${state}" type="button" data-trace-step="${stepIndex + 1}" aria-label="Go to trace step ${stepIndex + 1}: ${esc(name)}"><span class="trace-dot">${stepIndex + 1}</span><span class="trace-step-label">${esc(label)}</span></button>`;
1434
- }).join("");
1435
- selectedId = id;
1436
- if (insideId) renderCity();
1437
- traceCard.classList.add("show");
1438
- traceCard.innerHTML = `
1439
- <div class="trace-count"><small>Request trace</small><b>${String(safeIndex + 1).padStart(2, "0")} / ${String(TRACE.length).padStart(2, "0")}</b><span>Orange done · red current</span></div>
1440
- <div class="trace-copy"><strong>${esc(structure ? structure.name : id)}</strong><span>${esc(sentence)}</span></div>
1441
- <div class="trace-actions">
1442
- <button type="button" data-trace-action="previous"${safeIndex === 0 ? " disabled" : ""}>← Previous</button>
1443
- <button type="button" data-trace-action="next"${safeIndex === TRACE.length - 1 ? " disabled" : ""}>Next →</button>
1444
- <button type="button" data-trace-action="close">Close</button>
1445
- </div>
1446
- <div class="trace-timeline" style="--trace-count:${TRACE.length}">${traceStepsHtml}</div>`;
1447
- traceCard.querySelector('[data-trace-action="previous"]').addEventListener("click", () => setTrace(Math.max(1, safeIndex)));
1448
- traceCard.querySelector('[data-trace-action="next"]').addEventListener("click", () => setTrace(Math.min(TRACE.length, safeIndex + 2)));
1449
- traceCard.querySelector('[data-trace-action="close"]').addEventListener("click", () => { location.hash = ""; });
1450
- traceCard.querySelectorAll("[data-trace-step]").forEach((button) => {
1451
- button.addEventListener("click", () => setTrace(Number(button.dataset.traceStep)));
1452
- });
1453
- if (structure) renderStructureDetail(structure);
1454
- applyHighlightState();
1455
- }
1456
-
1457
- function setTrace(oneBasedIndex) {
1458
- location.hash = `trace=${oneBasedIndex}`;
1459
- }
1460
-
1461
- function applyHash() {
1462
- // Debug hooks: #inside=STRUCTURE_ID and #trace=7.
1463
- window.scrollTo(0, 0);
1464
- document.documentElement.scrollTop = 0;
1465
- document.body.scrollTop = 0;
1466
- const params = new URLSearchParams(location.hash.slice(1));
1467
- const inside = params.get("inside");
1468
- const trace = Number(params.get("trace"));
1469
- if (inside) {
1470
- const structure = structureById.get(inside);
1471
- if (structure && structure.children && structure.children.length) {
1472
- renderInside(structure);
1473
- return;
1474
- }
1475
- }
1476
- renderCity();
1477
- if (Number.isFinite(trace) && trace >= 1) {
1478
- renderTrace(trace - 1);
1479
- } else {
1480
- traceIndex = null;
1481
- traceCard.classList.remove("show");
1482
- renderOverview();
1483
- applyHighlightState();
1484
- }
1485
- }
1486
-
1487
- document.getElementById("page-title").textContent = TITLE;
1488
- document.getElementById("page-subtitle").textContent = SUBTITLE;
1489
- document.title = TITLE;
1490
- document.getElementById("stats").innerHTML = STATS.map((stat) => `<div class="stat"><strong>${esc(stat.value)}</strong><span>${esc(stat.label)}</span></div>`).join("");
1491
- document.getElementById("overview-button").addEventListener("click", () => { location.hash = ""; });
1492
- document.getElementById("trace-button").addEventListener("click", () => setTrace(1));
1493
- insideBack.addEventListener("click", () => { location.hash = ""; });
1494
- window.addEventListener("hashchange", applyHash);
1495
- window.addEventListener("pointerdown", (event) => {
1496
- if (!event.target.closest(".structure") && !event.target.closest(".structure-link") && !event.target.closest(".detail")) hideTooltip();
1497
- });
1498
-
1499
- if ("scrollRestoration" in history) history.scrollRestoration = "manual";
1500
- renderNav();
1501
- applyHash();
1502
- window.__isometricReady = true;
1503
- }());
1504
- </script>
1505
- </body>
1506
- </html>