wiki-viewer 1.14.1 → 1.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) 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/server/app/_global-error.html +1 -1
  4. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  5. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  6. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  11. package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  18. package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
  20. package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/agent/internal/span/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/agent/sidecar/[...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/share/[token]/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/share/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/system/set-root/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/refresh/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/system/workspaces/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/wiki/backlinks/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/api/wiki/download/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/wiki/file/route.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/wiki/git-branches/route.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/api/wiki/git-checkout/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/wiki/git-diff/route.js.nft.json +1 -1
  47. package/.next/standalone/.next/server/app/api/wiki/git-file-info/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/wiki/git-history/route.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/api/wiki/git-pull/route.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/api/wiki/outlinks/route.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
  54. package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/api/wiki/search/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
  58. package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/index.html +1 -1
  61. package/.next/standalone/.next/server/app/index.rsc +1 -1
  62. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  63. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  64. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  65. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  66. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  67. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  68. package/.next/standalone/.next/server/middleware-manifest.json +1 -1
  69. package/.next/standalone/.next/server/pages/404.html +1 -1
  70. package/.next/standalone/.next/server/pages/500.html +1 -1
  71. package/.next/standalone/package.json +1 -1
  72. package/bin/postbuild.js +21 -0
  73. package/package.json +1 -1
  74. package/.next/standalone/.github/workflows/publish.yml +0 -37
  75. package/.next/standalone/.handoffs/archive/handoff-20260612-113332.md +0 -98
  76. package/.next/standalone/.handoffs/archive/handoff-20260612-141032.md +0 -73
  77. package/.next/standalone/.pi/ownership.json +0 -3
  78. package/.next/standalone/AGENTS.md +0 -114
  79. package/.next/standalone/DESIGN.md +0 -521
  80. package/.next/standalone/README.md +0 -821
  81. package/.next/standalone/TODO.md +0 -20
  82. package/.next/standalone/agents/bootstrap-prompt.md +0 -14
  83. package/.next/standalone/agents/wiki-viewer-skill/SKILL.md +0 -456
  84. package/.next/standalone/bin/postbuild.js +0 -78
  85. package/.next/standalone/bin/wiki-viewer.js +0 -922
  86. package/.next/standalone/certificates/localhost-key.pem +0 -28
  87. package/.next/standalone/certificates/localhost.pem +0 -24
  88. package/.next/standalone/docs/agent-collab-plan.md +0 -1615
  89. package/.next/standalone/docs/agent-collab-v2-plan.md +0 -771
  90. package/.next/standalone/docs/agent-fs-plan.md +0 -232
  91. package/.next/standalone/docs/editorial-skin-spec.md +0 -242
  92. package/.next/standalone/docs/file-vs-collab-authority.md +0 -124
  93. package/.next/standalone/docs/mobile-readiness-spec.md +0 -229
  94. package/.next/standalone/docs/workspacing-plan.md +0 -364
  95. package/.next/standalone/packages/wiki-viewer-mcp/README.md +0 -195
  96. package/.next/standalone/packages/wiki-viewer-mcp/bench-e2e.mjs +0 -166
  97. package/.next/standalone/packages/wiki-viewer-mcp/bench-latency.mjs +0 -87
  98. package/.next/standalone/packages/wiki-viewer-mcp/bench-payload.mjs +0 -45
  99. package/.next/standalone/packages/wiki-viewer-mcp/dist/http-client.js +0 -331
  100. package/.next/standalone/packages/wiki-viewer-mcp/dist/index.js +0 -531
  101. package/.next/standalone/packages/wiki-viewer-mcp/dist/register.js +0 -94
  102. package/.next/standalone/packages/wiki-viewer-mcp/dist/state-cache.js +0 -28
  103. package/.next/standalone/packages/wiki-viewer-mcp/package-lock.json +0 -1716
  104. package/.next/standalone/packages/wiki-viewer-mcp/package.json +0 -41
  105. package/.next/standalone/packages/wiki-viewer-mcp/src/http-client.ts +0 -459
  106. package/.next/standalone/packages/wiki-viewer-mcp/src/index.ts +0 -638
  107. package/.next/standalone/packages/wiki-viewer-mcp/src/register.ts +0 -144
  108. package/.next/standalone/packages/wiki-viewer-mcp/src/state-cache.ts +0 -55
  109. package/.next/standalone/packages/wiki-viewer-mcp/tsconfig.json +0 -19
  110. package/.next/standalone/pnpm-lock.yaml +0 -6697
  111. package/.next/standalone/pnpm-workspace.yaml +0 -8
  112. package/.next/standalone/postcss.config.mjs +0 -2
  113. package/.next/standalone/src/app/api/agent/activity/route.ts +0 -59
  114. package/.next/standalone/src/app/api/agent/admin/agents/[agentId]/revoke/route.ts +0 -40
  115. package/.next/standalone/src/app/api/agent/admin/agents/route.ts +0 -33
  116. package/.next/standalone/src/app/api/agent/admin/registrations/[regId]/approve/route.ts +0 -83
  117. package/.next/standalone/src/app/api/agent/admin/registrations/[regId]/deny/route.ts +0 -36
  118. package/.next/standalone/src/app/api/agent/admin/registrations/route.ts +0 -27
  119. package/.next/standalone/src/app/api/agent/events/[...path]/route.ts +0 -148
  120. package/.next/standalone/src/app/api/agent/files/[...path]/route.ts +0 -219
  121. package/.next/standalone/src/app/api/agent/fs/file/[...path]/route.ts +0 -446
  122. package/.next/standalone/src/app/api/agent/fs/ls/[[...path]]/route.ts +0 -152
  123. package/.next/standalone/src/app/api/agent/fs/move/route.ts +0 -130
  124. package/.next/standalone/src/app/api/agent/fs/search/route.ts +0 -272
  125. package/.next/standalone/src/app/api/agent/internal/span/route.ts +0 -121
  126. package/.next/standalone/src/app/api/agent/register/[regId]/route.ts +0 -50
  127. package/.next/standalone/src/app/api/agent/register/route.ts +0 -118
  128. package/.next/standalone/src/app/api/agent/settings/route.ts +0 -34
  129. package/.next/standalone/src/app/api/agent/settings/token/regenerate/route.ts +0 -20
  130. package/.next/standalone/src/app/api/agent/sidecar/[...path]/route.ts +0 -53
  131. package/.next/standalone/src/app/api/agents/install/route.ts +0 -143
  132. package/.next/standalone/src/app/api/agents/skill/route.ts +0 -20
  133. package/.next/standalone/src/app/api/agents/skill.tar.gz/route.ts +0 -87
  134. package/.next/standalone/src/app/api/app-proxy/[...path]/route.ts +0 -247
  135. package/.next/standalone/src/app/api/assets/[...path]/route.ts +0 -75
  136. package/.next/standalone/src/app/api/auth/[...all]/route.ts +0 -7
  137. package/.next/standalone/src/app/api/owner/init/route.ts +0 -14
  138. package/.next/standalone/src/app/api/share/[token]/route.ts +0 -269
  139. package/.next/standalone/src/app/api/share/route.ts +0 -127
  140. package/.next/standalone/src/app/api/system/admins/route.ts +0 -103
  141. package/.next/standalone/src/app/api/system/auth-config/route.ts +0 -22
  142. package/.next/standalone/src/app/api/system/auth-settings/route.ts +0 -86
  143. package/.next/standalone/src/app/api/system/browse/route.ts +0 -82
  144. package/.next/standalone/src/app/api/system/clear-root/route.ts +0 -16
  145. package/.next/standalone/src/app/api/system/config/route.ts +0 -14
  146. package/.next/standalone/src/app/api/system/pins/route.ts +0 -38
  147. package/.next/standalone/src/app/api/system/reveal/route.ts +0 -36
  148. package/.next/standalone/src/app/api/system/root-status/route.ts +0 -13
  149. package/.next/standalone/src/app/api/system/set-root/route.ts +0 -53
  150. package/.next/standalone/src/app/api/system/users/route.ts +0 -120
  151. package/.next/standalone/src/app/api/system/workspaces/[id]/open/route.ts +0 -34
  152. package/.next/standalone/src/app/api/system/workspaces/[id]/refresh/route.ts +0 -32
  153. package/.next/standalone/src/app/api/system/workspaces/[id]/route.ts +0 -78
  154. package/.next/standalone/src/app/api/system/workspaces/route.ts +0 -128
  155. package/.next/standalone/src/app/api/upload/[...path]/route.ts +0 -85
  156. package/.next/standalone/src/app/api/wiki/app/route.ts +0 -60
  157. package/.next/standalone/src/app/api/wiki/backlinks/route.ts +0 -29
  158. package/.next/standalone/src/app/api/wiki/content/route.ts +0 -159
  159. package/.next/standalone/src/app/api/wiki/download/route.ts +0 -100
  160. package/.next/standalone/src/app/api/wiki/file/route.ts +0 -57
  161. package/.next/standalone/src/app/api/wiki/folder/route.ts +0 -34
  162. package/.next/standalone/src/app/api/wiki/git-branches/route.ts +0 -32
  163. package/.next/standalone/src/app/api/wiki/git-checkout/route.ts +0 -45
  164. package/.next/standalone/src/app/api/wiki/git-diff/route.ts +0 -33
  165. package/.next/standalone/src/app/api/wiki/git-file-info/route.ts +0 -27
  166. package/.next/standalone/src/app/api/wiki/git-history/route.ts +0 -27
  167. package/.next/standalone/src/app/api/wiki/git-pull/route.ts +0 -48
  168. package/.next/standalone/src/app/api/wiki/move/route.ts +0 -61
  169. package/.next/standalone/src/app/api/wiki/new-file/route.ts +0 -56
  170. package/.next/standalone/src/app/api/wiki/outlinks/route.ts +0 -76
  171. package/.next/standalone/src/app/api/wiki/page/route.ts +0 -92
  172. package/.next/standalone/src/app/api/wiki/presence/route.ts +0 -56
  173. package/.next/standalone/src/app/api/wiki/route.ts +0 -116
  174. package/.next/standalone/src/app/api/wiki/search/route.ts +0 -44
  175. package/.next/standalone/src/app/api/wiki/slugs/route.ts +0 -54
  176. package/.next/standalone/src/app/api/wiki/upload/route.ts +0 -95
  177. package/.next/standalone/src/app/api/wiki/watch/route.ts +0 -67
  178. package/.next/standalone/src/app/globals.css +0 -1249
  179. package/.next/standalone/src/app/icon.svg +0 -11
  180. package/.next/standalone/src/app/layout.tsx +0 -78
  181. package/.next/standalone/src/app/manifest.ts +0 -30
  182. package/.next/standalone/src/app/page.tsx +0 -3260
  183. package/.next/standalone/src/app/s/[token]/page.tsx +0 -357
  184. package/.next/standalone/src/app/signin/page.tsx +0 -16
  185. package/.next/standalone/src/app/signin/signin-form.tsx +0 -238
  186. package/.next/standalone/src/components/ai-panel/activity-row.tsx +0 -284
  187. package/.next/standalone/src/components/ai-panel/ai-panel.tsx +0 -311
  188. package/.next/standalone/src/components/ai-panel/token-section.tsx +0 -313
  189. package/.next/standalone/src/components/auth-settings-sheet.tsx +0 -474
  190. package/.next/standalone/src/components/confirm-dialog.tsx +0 -56
  191. package/.next/standalone/src/components/dir-picker.tsx +0 -606
  192. package/.next/standalone/src/components/editor/backlinks-panel.tsx +0 -139
  193. package/.next/standalone/src/components/editor/bubble-menu.tsx +0 -346
  194. package/.next/standalone/src/components/editor/callout-extension.ts +0 -36
  195. package/.next/standalone/src/components/editor/comment-pip.tsx +0 -56
  196. package/.next/standalone/src/components/editor/comment-thread.tsx +0 -254
  197. package/.next/standalone/src/components/editor/csv-viewer.tsx +0 -379
  198. package/.next/standalone/src/components/editor/document-outline.tsx +0 -230
  199. package/.next/standalone/src/components/editor/editor-toolbar.tsx +0 -564
  200. package/.next/standalone/src/components/editor/editor.tsx +0 -1327
  201. package/.next/standalone/src/components/editor/extensions/drag-handle.ts +0 -325
  202. package/.next/standalone/src/components/editor/extensions/heading-anchors.ts +0 -55
  203. package/.next/standalone/src/components/editor/extensions/proof-span.ts +0 -60
  204. package/.next/standalone/src/components/editor/extensions/resizable-image.tsx +0 -159
  205. package/.next/standalone/src/components/editor/extensions.ts +0 -150
  206. package/.next/standalone/src/components/editor/file-fallback-viewer.tsx +0 -75
  207. package/.next/standalone/src/components/editor/folder-index.tsx +0 -236
  208. package/.next/standalone/src/components/editor/google-doc-viewer.tsx +0 -73
  209. package/.next/standalone/src/components/editor/image-viewer.tsx +0 -57
  210. package/.next/standalone/src/components/editor/large-file-gate.tsx +0 -108
  211. package/.next/standalone/src/components/editor/link-popover.tsx +0 -111
  212. package/.next/standalone/src/components/editor/media-popover.tsx +0 -212
  213. package/.next/standalone/src/components/editor/media-viewer.tsx +0 -70
  214. package/.next/standalone/src/components/editor/mermaid-viewer.tsx +0 -286
  215. package/.next/standalone/src/components/editor/node-app-viewer.tsx +0 -328
  216. package/.next/standalone/src/components/editor/notebook-viewer.tsx +0 -371
  217. package/.next/standalone/src/components/editor/office/docx-viewer.tsx +0 -93
  218. package/.next/standalone/src/components/editor/office/office-chrome.tsx +0 -83
  219. package/.next/standalone/src/components/editor/office/pptx-viewer.tsx +0 -104
  220. package/.next/standalone/src/components/editor/office/xlsx-viewer.tsx +0 -192
  221. package/.next/standalone/src/components/editor/pdf-viewer.tsx +0 -32
  222. package/.next/standalone/src/components/editor/proof-span-popover.tsx +0 -162
  223. package/.next/standalone/src/components/editor/slash-commands.tsx +0 -629
  224. package/.next/standalone/src/components/editor/source-viewer.tsx +0 -289
  225. package/.next/standalone/src/components/editor/suggest-edit-popover.tsx +0 -229
  226. package/.next/standalone/src/components/editor/suggestion-card.tsx +0 -206
  227. package/.next/standalone/src/components/editor/table-menu.tsx +0 -232
  228. package/.next/standalone/src/components/editor/view-mode-comment-button.tsx +0 -77
  229. package/.next/standalone/src/components/editor/website-viewer.tsx +0 -75
  230. package/.next/standalone/src/components/editor/wiki-link-create-dialog.tsx +0 -189
  231. package/.next/standalone/src/components/editor/wiki-link-decorator.ts +0 -79
  232. package/.next/standalone/src/components/editor/wiki-link-extension.ts +0 -120
  233. package/.next/standalone/src/components/editor/wiki-link-picker.tsx +0 -250
  234. package/.next/standalone/src/components/layout/viewer-toolbar.tsx +0 -54
  235. package/.next/standalone/src/components/search/search-command-dialog.tsx +0 -246
  236. package/.next/standalone/src/components/search/sidebar-search-box.tsx +0 -121
  237. package/.next/standalone/src/components/search/snippet-text.tsx +0 -48
  238. package/.next/standalone/src/components/share-dialog.tsx +0 -307
  239. package/.next/standalone/src/components/theme-provider.tsx +0 -16
  240. package/.next/standalone/src/components/theme-toggle.tsx +0 -24
  241. package/.next/standalone/src/components/ui/badge.tsx +0 -35
  242. package/.next/standalone/src/components/ui/button.tsx +0 -56
  243. package/.next/standalone/src/components/ui/card.tsx +0 -63
  244. package/.next/standalone/src/components/ui/collapsible.tsx +0 -9
  245. package/.next/standalone/src/components/ui/command.tsx +0 -151
  246. package/.next/standalone/src/components/ui/context-menu.tsx +0 -191
  247. package/.next/standalone/src/components/ui/dialog.tsx +0 -119
  248. package/.next/standalone/src/components/ui/dropdown-menu.tsx +0 -194
  249. package/.next/standalone/src/components/ui/input.tsx +0 -22
  250. package/.next/standalone/src/components/ui/label.tsx +0 -25
  251. package/.next/standalone/src/components/ui/popover.tsx +0 -33
  252. package/.next/standalone/src/components/ui/scroll-area.tsx +0 -47
  253. package/.next/standalone/src/components/ui/select.tsx +0 -156
  254. package/.next/standalone/src/components/ui/separator.tsx +0 -30
  255. package/.next/standalone/src/components/ui/sheet.tsx +0 -140
  256. package/.next/standalone/src/components/ui/skeleton.tsx +0 -15
  257. package/.next/standalone/src/components/ui/switch.tsx +0 -28
  258. package/.next/standalone/src/components/ui/tabs.tsx +0 -54
  259. package/.next/standalone/src/components/ui/textarea.tsx +0 -21
  260. package/.next/standalone/src/components/ui/tip.tsx +0 -23
  261. package/.next/standalone/src/components/ui/toggle-group.tsx +0 -41
  262. package/.next/standalone/src/components/ui/tooltip.tsx +0 -27
  263. package/.next/standalone/src/components/view-width-toggle.tsx +0 -70
  264. package/.next/standalone/src/components/wiki/frontmatter-header.tsx +0 -164
  265. package/.next/standalone/src/hooks/use-is-mobile.ts +0 -14
  266. package/.next/standalone/src/lib/app-runner.ts +0 -272
  267. package/.next/standalone/src/lib/auth/admin.ts +0 -120
  268. package/.next/standalone/src/lib/auth/allowlist.ts +0 -50
  269. package/.next/standalone/src/lib/auth/client.ts +0 -4
  270. package/.next/standalone/src/lib/auth/csrf.ts +0 -68
  271. package/.next/standalone/src/lib/auth/server.ts +0 -215
  272. package/.next/standalone/src/lib/cabinets/tree.ts +0 -75
  273. package/.next/standalone/src/lib/config.ts +0 -114
  274. package/.next/standalone/src/lib/embeds/detect.ts +0 -142
  275. package/.next/standalone/src/lib/git-secrets.ts +0 -65
  276. package/.next/standalone/src/lib/git.ts +0 -503
  277. package/.next/standalone/src/lib/google/detect.ts +0 -107
  278. package/.next/standalone/src/lib/markdown/parse-frontmatter.ts +0 -104
  279. package/.next/standalone/src/lib/markdown/remark-wikilinks.ts +0 -100
  280. package/.next/standalone/src/lib/markdown/sanitize-schema.ts +0 -106
  281. package/.next/standalone/src/lib/markdown/to-html.ts +0 -282
  282. package/.next/standalone/src/lib/markdown/to-markdown.ts +0 -252
  283. package/.next/standalone/src/lib/proof/activity-shared.ts +0 -31
  284. package/.next/standalone/src/lib/proof/activity.ts +0 -74
  285. package/.next/standalone/src/lib/proof/audit.ts +0 -88
  286. package/.next/standalone/src/lib/proof/auth.ts +0 -143
  287. package/.next/standalone/src/lib/proof/block-refs.ts +0 -133
  288. package/.next/standalone/src/lib/proof/blocks.ts +0 -73
  289. package/.next/standalone/src/lib/proof/client-auth.ts +0 -23
  290. package/.next/standalone/src/lib/proof/collab-state.ts +0 -81
  291. package/.next/standalone/src/lib/proof/event-bus.ts +0 -47
  292. package/.next/standalone/src/lib/proof/file-lock.ts +0 -43
  293. package/.next/standalone/src/lib/proof/glob.ts +0 -51
  294. package/.next/standalone/src/lib/proof/idempotency.ts +0 -37
  295. package/.next/standalone/src/lib/proof/lease.ts +0 -117
  296. package/.next/standalone/src/lib/proof/mutex.ts +0 -36
  297. package/.next/standalone/src/lib/proof/ops-applier.ts +0 -727
  298. package/.next/standalone/src/lib/proof/owner-auth.ts +0 -2
  299. package/.next/standalone/src/lib/proof/pending.ts +0 -97
  300. package/.next/standalone/src/lib/proof/proof-span.ts +0 -141
  301. package/.next/standalone/src/lib/proof/rate-limit.ts +0 -53
  302. package/.next/standalone/src/lib/proof/raw-fs.ts +0 -197
  303. package/.next/standalone/src/lib/proof/register-rate-limit.ts +0 -53
  304. package/.next/standalone/src/lib/proof/registry.ts +0 -195
  305. package/.next/standalone/src/lib/proof/sidecar.ts +0 -103
  306. package/.next/standalone/src/lib/proof/suggest-capture.ts +0 -69
  307. package/.next/standalone/src/lib/proof/types.ts +0 -182
  308. package/.next/standalone/src/lib/proof-config.ts +0 -14
  309. package/.next/standalone/src/lib/root-dir.ts +0 -35
  310. package/.next/standalone/src/lib/search/indexable-exts.ts +0 -25
  311. package/.next/standalone/src/lib/search/indexer.ts +0 -634
  312. package/.next/standalone/src/lib/search/sanitize.ts +0 -35
  313. package/.next/standalone/src/lib/search/search-db.ts +0 -57
  314. package/.next/standalone/src/lib/search/watcher-pool.ts +0 -79
  315. package/.next/standalone/src/lib/shared-docs/db.ts +0 -177
  316. package/.next/standalone/src/lib/toast.ts +0 -9
  317. package/.next/standalone/src/lib/utils.ts +0 -6
  318. package/.next/standalone/src/lib/wiki-helpers.ts +0 -36
  319. package/.next/standalone/src/lib/workspace-client.ts +0 -82
  320. package/.next/standalone/src/lib/workspace-context.ts +0 -173
  321. package/.next/standalone/src/lib/workspaces.ts +0 -400
  322. package/.next/standalone/src/middleware.ts +0 -44
  323. package/.next/standalone/src/stores/ai-panel-store.ts +0 -79
  324. package/.next/standalone/src/stores/editor-store.ts +0 -439
  325. package/.next/standalone/src/stores/pin-store.ts +0 -56
  326. package/.next/standalone/src/stores/proof-store.ts +0 -124
  327. package/.next/standalone/src/stores/recent-store.ts +0 -51
  328. package/.next/standalone/src/stores/search-store.ts +0 -104
  329. package/.next/standalone/src/stores/show-hidden-store.ts +0 -26
  330. package/.next/standalone/src/stores/sidebar-width-store.ts +0 -39
  331. package/.next/standalone/src/stores/skin-store.ts +0 -42
  332. package/.next/standalone/src/stores/tree-store.ts +0 -52
  333. package/.next/standalone/src/stores/view-width-store.ts +0 -101
  334. package/.next/standalone/src/stores/wiki-slugs-store.ts +0 -75
  335. package/.next/standalone/src/tests/proof/activity-aggregator.test.ts +0 -146
  336. package/.next/standalone/src/tests/proof/admin-create-user.test.ts +0 -43
  337. package/.next/standalone/src/tests/proof/agent-fs.test.ts +0 -973
  338. package/.next/standalone/src/tests/proof/agent-ownership.test.ts +0 -140
  339. package/.next/standalone/src/tests/proof/agent-workspace-scope.test.ts +0 -134
  340. package/.next/standalone/src/tests/proof/agents-install.test.ts +0 -110
  341. package/.next/standalone/src/tests/proof/bench-write.ts +0 -179
  342. package/.next/standalone/src/tests/proof/better-auth.test.ts +0 -68
  343. package/.next/standalone/src/tests/proof/block-refs.test.ts +0 -108
  344. package/.next/standalone/src/tests/proof/blocks.test.ts +0 -92
  345. package/.next/standalone/src/tests/proof/collab-state.test.ts +0 -501
  346. package/.next/standalone/src/tests/proof/comments-ops.test.ts +0 -177
  347. package/.next/standalone/src/tests/proof/editor-roundtrip.test.ts +0 -85
  348. package/.next/standalone/src/tests/proof/external-edit.test.ts +0 -58
  349. package/.next/standalone/src/tests/proof/file-lock.test.ts +0 -80
  350. package/.next/standalone/src/tests/proof/git-branches-checkout.test.ts +0 -136
  351. package/.next/standalone/src/tests/proof/git-read-features.test.ts +0 -473
  352. package/.next/standalone/src/tests/proof/git-secrets.test.ts +0 -138
  353. package/.next/standalone/src/tests/proof/git-sparse.test.ts +0 -257
  354. package/.next/standalone/src/tests/proof/git-workspace.test.ts +0 -135
  355. package/.next/standalone/src/tests/proof/git.test.ts +0 -243
  356. package/.next/standalone/src/tests/proof/glob.test.ts +0 -82
  357. package/.next/standalone/src/tests/proof/helpers/auth-session.ts +0 -27
  358. package/.next/standalone/src/tests/proof/markdown-to-html.test.ts +0 -46
  359. package/.next/standalone/src/tests/proof/ops-applier.test.ts +0 -368
  360. package/.next/standalone/src/tests/proof/owner-init.test.ts +0 -2
  361. package/.next/standalone/src/tests/proof/parse-frontmatter.test.ts +0 -60
  362. package/.next/standalone/src/tests/proof/preload.ts +0 -21
  363. package/.next/standalone/src/tests/proof/proof-span.test.ts +0 -98
  364. package/.next/standalone/src/tests/proof/rate-limit.test.ts +0 -54
  365. package/.next/standalone/src/tests/proof/readonly-enforcement.test.ts +0 -161
  366. package/.next/standalone/src/tests/proof/reconcile-sidecar.test.ts +0 -195
  367. package/.next/standalone/src/tests/proof/registration-flow.test.ts +0 -330
  368. package/.next/standalone/src/tests/proof/registry.test.ts +0 -169
  369. package/.next/standalone/src/tests/proof/routes.test.ts +0 -516
  370. package/.next/standalone/src/tests/proof/search-index.test.ts +0 -376
  371. package/.next/standalone/src/tests/proof/sidecar-lifecycle.test.ts +0 -177
  372. package/.next/standalone/src/tests/proof/sidecar-trim.test.ts +0 -58
  373. package/.next/standalone/src/tests/proof/suggestion-ops.test.ts +0 -280
  374. package/.next/standalone/src/tests/proof/wiki-content-put.test.ts +0 -140
  375. package/.next/standalone/src/tests/proof/wiki-routes-auth.test.ts +0 -208
  376. package/.next/standalone/src/tests/proof/workspace-isolation.test.ts +0 -87
  377. package/.next/standalone/src/tests/proof/workspaces-api.test.ts +0 -227
  378. package/.next/standalone/src/types/index.ts +0 -47
  379. package/.next/standalone/tailwind.config.ts +0 -191
  380. package/.next/standalone/tsconfig.json +0 -41
  381. package/.next/standalone/tsconfig.tsbuildinfo +0 -1
  382. /package/.next/standalone/.next/static/{WMOTgfV82apmdovxzgbMx → rRyvFORvJoc5OWbCR2A_P}/_buildManifest.js +0 -0
  383. /package/.next/standalone/.next/static/{WMOTgfV82apmdovxzgbMx → rRyvFORvJoc5OWbCR2A_P}/_clientMiddlewareManifest.js +0 -0
  384. /package/.next/standalone/.next/static/{WMOTgfV82apmdovxzgbMx → rRyvFORvJoc5OWbCR2A_P}/_ssgManifest.js +0 -0
@@ -1,771 +0,0 @@
1
- # Agent Collaboration Protocol — v2 Implementation Plan
2
-
3
- **Status:** Draft for review. Do not implement until user signs off.
4
- **Target:** Pivot wiki-viewer from single-user local-first to multi-user remote-server with realtime CRDT collab.
5
- **Audience:** Implementing agent, with no prior context, who has read `docs/agent-collab-plan.md` (v1) for reference.
6
- **Relationship to v1:** v1 stays as historical reference. v2 supersedes §0 prohibition on Yjs and §0 single-user constraint. The HTTP agent surface, op vocabulary, sidecar shape, and provenance marks survive in modified form. The file-on-disk-is-truth rule is loosened (see §1.3).
7
-
8
- ---
9
-
10
- ## 0. What changed since v1
11
-
12
- | v1 axiom | v2 status |
13
- | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
14
- | Single-user, local-first | **REVERSED** — multi-user, remote-server first |
15
- | File on disk is source of truth, always | **REFINED** — Y.Doc is source of truth during live session; markdown is durable export + cold-start seed |
16
- | No Yjs, no WebSockets, no realtime CRDT | **REVERSED** — Yjs + Hocuspocus realtime, y-prosemirror binding |
17
- | Bearer token + owner cookie | **REPLACED** — OAuth (GitHub primary, Google secondary), session in DB, per-user identity |
18
- | Single ROOT_DIR | **REPLACED** — workspace entity with member ACL |
19
- | Agent registry in `~/.wiki-viewer/agents.json` | **REPLACED** — per-workspace agent rows in DB |
20
- | In-process mutex serializes mutations | **KEPT for cold path** — Y.Doc handles concurrent edits, server applies agent ops as Y transactions; mutex still guards persistence-flush and external-edit reconciliation |
21
- | `PUT /api/wiki/content` bypasses ops-applier | **FIXED** — editor never writes raw markdown; saves go through Y.Doc |
22
- | Pending registrations in-memory | **REPLACED** — DB-backed |
23
- | No HTTPS / no CSRF | **FIXED** — enforce HTTPS in prod, CSRF on owner-cookie POSTs (now session-cookie POSTs), Origin check on WS upgrade |
24
- | No presence, no live cursors | **ADDED** — Yjs awareness |
25
-
26
- What stays:
27
-
28
- - TipTap editor (no Milkdown swap)
29
- - proof-span mark (now lives inside Y.XmlFragment)
30
- - Block-ref + idempotency semantics on the HTTP surface (agents see no API break for their core ops, only auth/scope)
31
- - Sidecar concept (comments, suggestions, events, blockProvenance) — migrates from JSON files to DB rows
32
- - 160-test suite via `node --test` / `tsx --test` — augmented, not replaced
33
-
34
- ---
35
-
36
- ## 1. Architecture sketch
37
-
38
- ### 1.1 Block diagram (post-pivot)
39
-
40
- ```
41
- ┌────────────────────────────────────────────────────────────────────────────┐
42
- │ Browser (User) │
43
- │ │
44
- │ ┌────────────────────────────────────────────────────────────────────┐ │
45
- │ │ Next.js app │ │
46
- │ │ ┌──────────────────────┐ ┌──────────────────────────────────┐ │ │
47
- │ │ │ TipTap editor │◄──►│ y-prosemirror binding │ │ │
48
- │ │ │ + ProofSpan mark │ │ + @tiptap/extension-collab │ │ │
49
- │ │ │ + suggestion cards │ │ + Y.Doc (per file, in-memory) │ │ │
50
- │ │ │ + comment pips │ └────────────────┬─────────────────┘ │ │
51
- │ │ │ + presence cursors │ │ │ │
52
- │ │ └──────────────────────┘ │ │ │
53
- │ │ ┌──────────────────────┐ │ │ │
54
- │ │ │ Sidecar REST client │◄────────────────────┼───── y-protocol │ │
55
- │ │ │ (comments, sugg., │ │ messages │ │
56
- │ │ │ events polling) │ │ │ │
57
- │ │ └──────────────────────┘ │ │ │
58
- │ └────────────────────────────────────────────────┼───────────────────┘ │
59
- │ HTTPS │ session cookie WSS │ session cookie │
60
- └──────────────────────────┼───────────────────────────┼───────────────────┘
61
- │ │
62
- ┌──────────────────────────▼───────────────────────────▼───────────────────┐
63
- │ Node process (custom server.ts) │
64
- │ │
65
- │ ┌─────────────────────────────────┐ ┌───────────────────────────────┐ │
66
- │ │ Next.js HTTP handler │ │ Hocuspocus (mounted on /yjs) │ │
67
- │ │ - /api/auth/* (OAuth) │ │ onAuthenticate → session │ │
68
- │ │ - /api/workspaces/* │ │ onLoadDocument → seed Y.Doc │ │
69
- │ │ - /api/agent/* (HTTP bridge) │ │ from markdown OR DB blob │ │
70
- │ │ - /api/wiki/* (read-only file │ │ onChange → debounced flush │ │
71
- │ │ tree, content GET) │ │ → markdown + commit to │ │
72
- │ │ - /api/sidecar/* │ │ workspace store + DB blob │ │
73
- │ └────────────────┬────────────────┘ │ onDisconnect → presence rm │ │
74
- │ │ └────────────┬──────────────────┘ │
75
- │ │ │ │
76
- │ ┌────────────────▼─────────────────────────────────▼──────────────────┐ │
77
- │ │ Server-side proof core (refactored) │ │
78
- │ │ - ops-applier-yjs.ts (translates Op → Y.Doc transaction) │ │
79
- │ │ - block-refs.ts (now reads block list from Y.Doc snapshot) │ │
80
- │ │ - sidecar-store.ts (DB-backed; legacy JSON read for migration) │ │
81
- │ │ - mutex.ts (per-doc serial for flush + agent ops batch)│ │
82
- │ └─────────────┬──────────────────────────────┬────────────────────────┘ │
83
- │ │ │ │
84
- │ ┌─────────────▼──────────┐ ┌──────────────▼──────────────────────┐ │
85
- │ │ Postgres (or SQLite) │ │ File-system store (per workspace) │ │
86
- │ │ users │ │ <workspace_root>/<path>.md │ │
87
- │ │ sessions │ │ (debounced flush from Y.Doc, │ │
88
- │ │ workspaces │ │ chokidar watches for external) │ │
89
- │ │ workspace_members │ └──────────────────────────────────────┘ │
90
- │ │ agent_registrations │ │
91
- │ │ agent_records │ │
92
- │ │ comments │ │
93
- │ │ suggestions │ │
94
- │ │ events │ │
95
- │ │ ydoc_snapshots │ ← optional: persisted Yjs state vectors │
96
- │ └────────────────────────┘ │
97
- └──────────────────────────────────────────────────────────────────────────┘
98
-
99
- │ HTTPS (Authorization: Bearer <agent-token>)
100
-
101
- ┌──────────┴──────────┐
102
- │ Remote AI agent │ (Claude, Cursor, ChatGPT desktop, etc.)
103
- │ uses /api/agent/* │ Sees blocks + revision, NOT raw Yjs protocol.
104
- └─────────────────────┘
105
- ```
106
-
107
- ### 1.2 Yjs provider choice
108
-
109
- Pick: **Hocuspocus**.
110
-
111
- | Option | Why not / why yes |
112
- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
113
- | Raw `y-protocols` + `ws` | Too low-level. Need to reimplement onAuthenticate, onLoadDocument, onStore, debounced persistence, awareness routing, hooks. Reinventing Hocuspocus. |
114
- | `y-websocket` server | Good enough for happy path, but auth hook is `gc`-only, no built-in onLoadDocument/onStore hooks tuned for our flush model, no extension API. Adopted then abandoned by many teams. |
115
- | **Hocuspocus** | Built for this. First-class hooks: `onAuthenticate`, `onConnect`, `onLoadDocument`, `onChange`, `onStoreDocument`, `onDisconnect`. Cleanly mountable inside a custom Next.js server. MIT, actively maintained. Extension ecosystem (`@hocuspocus/extension-database`, `@hocuspocus/extension-throttle`, `@hocuspocus/extension-logger`) overlaps with our needs. Cost: ships a chunky server bundle and ties our persistence to its hook lifecycle, but the lifecycle matches our model. |
116
-
117
- Trade-off accepted: Hocuspocus binds us to a specific Yjs server vendor. Escape hatch: ops-applier-yjs and persistence sink live in our code; Hocuspocus is a thin transport layer. We can swap to a custom y-protocols server later without rewriting business logic.
118
-
119
- ### 1.3 Where does the markdown file fit?
120
-
121
- **Rule (explicit):**
122
-
123
- 1. **Y.Doc is the live truth** during any active editing session for a given file. All edits (human, agent) land in the Y.Doc first.
124
- 2. **Markdown on disk is durable export + cold seed.** When a Y.Doc has no awareness connections for `IDLE_FLUSH_MS` (default 30s), or on graceful shutdown, server serializes Y.Doc to markdown and writes the file. File commit is also debounced during the live session (`LIVE_FLUSH_MS`, default 5s) so external tools see fresh content.
125
- 3. **DB stores the canonical Yjs state vector** + a debounced markdown snapshot blob in `ydoc_snapshots`. The file system markdown is regenerated from DB on every flush. The on-disk file is for: git, chokidar consumers, command-line tools, downloads.
126
- 4. **On document open with no live session:** if `ydoc_snapshots` has rows, load latest snapshot's Y.Doc state and continue. If not, parse markdown from disk → seed Y.Doc → write snapshot. (This is the migration path from v1 sidecars.)
127
- 5. **External edit (vim) while doc is live:** chokidar fires. Server's `onExternalFileChange` handler computes diff between current Y.Doc serialization and new file content. If different, **the external edit wins** by being applied as a Yjs transaction (using `applyMarkdownAsYjsTransaction`, which diffs at block granularity to minimize churn). This emits a `file.externallyEdited` event and shows a toast in the editor. Rationale: vim user explicitly typed those bytes; refusing them would be confusing.
128
- 6. **External edit while doc is NOT live:** trivial. Next open seeds from disk, which is now newer than the last `ydoc_snapshots` row.
129
-
130
- This is the **single hardest design decision** in v2. Document it in `docs/file-vs-yjs-authority.md` with examples before phase F.
131
-
132
- ---
133
-
134
- ## 2. Persistence model
135
-
136
- ### 2.1 Y.Doc lifecycle per file
137
-
138
- | Phase | Action |
139
- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
140
- | First open ever | `parseBlocks(md)` → for each block, create a Y.XmlElement with attributes `data-ref=<ref>` and content. Wrap into the doc's primary Y.XmlFragment named `default`. Write initial snapshot to `ydoc_snapshots`. |
141
- | Reopen with snapshot | `Y.applyUpdate(doc, snapshot.update)`. Skip markdown parse. |
142
- | Live edits | Editor's y-prosemirror binding applies Y.Doc updates. Awareness updates broadcast cursors / users. |
143
- | Debounced live flush | Every `LIVE_FLUSH_MS` or on quiet window of `IDLE_FLUSH_MS`: serialize Y.Doc → markdown via `yDocToMarkdown()`, write `<workspace_root>/<path>.md`, upsert `ydoc_snapshots` row with `Y.encodeStateAsUpdate(doc)`. |
144
- | External edit detected | Reconcile (§1.3.5). |
145
- | All clients disconnect | Schedule full flush + idle eviction after `IDLE_EVICT_MS` (default 5 min). After eviction, Y.Doc unloaded from memory; next open reseeds. |
146
-
147
- ### 2.2 Sidecar migration
148
-
149
- v1 stored comments / suggestions / events / refMap / blockProvenance in `<root>/.proof/<path>.json`. v2:
150
-
151
- - **Comments, suggestions, events, blockProvenance** → DB rows keyed by `(workspace_id, path)`. See §5.2 schema.
152
- - **refMap, refAliases** → no longer stored. Refs are derived from current Y.Doc state: each block-level Y.XmlElement carries `data-ref` attribute, stable across edits to its content (the ref is set at insertion time and survives content edits because we attach it to the element node, not its text).
153
- - **lastAck** → DB column on `agent_records` keyed by `(agent_id, workspace_id, path)`.
154
-
155
- Recommendation: **drop sidecar JSON entirely.** Migrate existing files at first read: if `.proof/<path>.json` exists, import into DB, then leave the file in place (read-only, ignored) for safety. After 2 weeks of green prod, delete migration code.
156
-
157
- ### 2.3 Agent block-ref + revision model under Yjs
158
-
159
- This is the second hardest design decision. Two truths to reconcile:
160
-
161
- - Agents send `baseRevision: N` and expect 409 STALE_REVISION if the doc moved.
162
- - Yjs has no monotonic per-doc revision; it has a state vector (a `Map<clientId, clock>`) representing the latest seen update per peer.
163
-
164
- **Approach (Proof-SDK-inspired): mutationBaseToken**
165
-
166
- When an agent calls `GET /api/agent/files/<workspace>/<path>`, the response includes:
167
-
168
- ```json
169
- {
170
- "revision": 47,
171
- "mutationBaseToken": "<base64-state-vector>",
172
- "blocks": [ { "ref": "b7f2c1", ... }, ... ]
173
- }
174
- ```
175
-
176
- - `revision` is still a monotonic integer maintained per (workspace, path) in DB. Bumped only when ops-applier-yjs commits an agent ops batch. Human edits do NOT bump this counter (they're CRDT; no agent should care).
177
- - `mutationBaseToken` is `Y.encodeStateVector(doc)` base64-encoded. Carries far more information than `revision`; tells us exactly what the agent saw.
178
-
179
- When agent POSTs ops with `baseRevision: 47` and (optionally) `mutationBaseToken`:
180
-
181
- 1. Check `revision === 47` — if not, return STALE_REVISION with fresh snapshot.
182
- 2. Optionally validate `mutationBaseToken` matches current state vector. If matches: pure forward agent op, no human edits since. If doesn't match: humans typed since the snapshot. Apply the agent ops anyway — Yjs CRDT will merge — but include a warning header `X-Concurrent-Human-Edits: true` so agent SDKs can log it.
183
- 3. Each block ref in the ops is resolved against current Y.Doc state (the `data-ref` attribute on element nodes). If missing, return BLOCK_NOT_FOUND with fresh snapshot.
184
-
185
- **Implication for agents:** v1's block-ref-not-found error becomes much rarer because content edits don't invalidate refs. Only deletions do.
186
-
187
- ---
188
-
189
- ## 3. Multi-user identity
190
-
191
- ### 3.1 Auth library choice
192
-
193
- Pick: **NextAuth.js v5 (Auth.js)**.
194
-
195
- | Option | Verdict |
196
- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
197
- | **NextAuth v5** | Mature, OAuth providers are config-only, supports DB sessions with Drizzle adapter, integrates with App Router middleware cleanly, has been battle-tested on Next 14/15/16. Cost: opinionated session shape, bundle weight. |
198
- | lucia-auth | Smaller, more flexible, but author paused active development and recommended migrating away. Don't bet on it. |
199
- | Hand-rolled OAuth | We'd reimplement: provider URL builders, state cookie, PKCE, JWT signing, refresh rotation. Each is a security landmine. Reject. |
200
-
201
- **Session storage:** **DB sessions, not JWT.** Reasons:
202
-
203
- - Logout-anywhere is a real requirement
204
- - Session revocation on permission change
205
- - Token refresh rotation easier with DB
206
- - JWT cookies become large; DB sessions remain a short opaque ID
207
-
208
- **Cookie:** `__Host-session` in prod, `next-auth.session-token` semantics. HttpOnly, SameSite=Lax, Secure in prod.
209
-
210
- ### 3.2 User record schema (Drizzle pseudo)
211
-
212
- ```
213
- users
214
- id uuid primary key
215
- email text not null unique
216
- display_name text not null
217
- avatar_url text
218
- created_at timestamptz default now()
219
-
220
- oauth_accounts
221
- id uuid primary key
222
- user_id uuid references users on delete cascade
223
- provider text not null -- "github" | "google"
224
- provider_sub text not null -- subject id from provider
225
- access_token text -- encrypted at rest (later phase)
226
- refresh_token text -- encrypted at rest
227
- expires_at timestamptz
228
- unique (provider, provider_sub)
229
-
230
- sessions
231
- id text primary key -- random 32 bytes b64u
232
- user_id uuid references users on delete cascade
233
- expires_at timestamptz not null
234
- created_at timestamptz default now()
235
- last_seen timestamptz default now()
236
- ```
237
-
238
- ### 3.3 Identity threading
239
-
240
- | Surface | How identity flows |
241
- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
242
- | HTTP request | Session cookie → middleware → `req.user` (uid, email, displayName) |
243
- | Yjs WebSocket | `onAuthenticate({ token })` token is the session cookie value; server validates same way → resolves user; injected into `context.user`. Awareness sets `{ user: { id, name, color } }`. |
244
- | proof-span `by` attribute | Now `"user:<uuid>"` for humans (was `"human"`), `"ai:<agent-id>"` for agents. v1 `"human"` value preserved during read for back-compat in old files (mapped to `"user:legacy"`). |
245
- | Agent HTTP `by` field | Must equal authenticated agent's id (already enforced by `verifyBy`). Browser-driven mutations (suggestion accept, span accept) use `by: "user:<uuid>"`. |
246
- | Agent registration approval | Whoever owns the workspace approves. Workspace admins can approve. Pending registrations carry the requested workspace_id. |
247
- | Agent registry ownership | Each agent record is `(workspace_id, agent_id)` keyed. Tokens are workspace-scoped. |
248
-
249
- ---
250
-
251
- ## 4. Workspace model
252
-
253
- ### 4.1 Workspaces as first-class entity
254
-
255
- ```
256
- workspaces
257
- id uuid primary key
258
- name text not null
259
- root_path text not null -- absolute on server
260
- created_by uuid references users
261
- created_at timestamptz default now()
262
- visibility enum('private', 'invite_only') default 'invite_only'
263
-
264
- workspace_members
265
- workspace_id uuid references workspaces on delete cascade
266
- user_id uuid references users on delete cascade
267
- role enum('admin', 'editor', 'viewer') not null
268
- added_at timestamptz default now()
269
- primary key (workspace_id, user_id)
270
- ```
271
-
272
- - All files live under `<workspaces.root_path>/`. Server enforces traversal protection (current `safeRootPath` generalizes to `safeWorkspacePath(workspace_id, rel)`).
273
- - A user with no membership row gets 404 on the workspace (do not leak existence via 403).
274
- - `admin` can: invite/remove members, register agents, change visibility, delete workspace.
275
- - `editor` can: read + write files, manage comments/suggestions, mention agents.
276
- - `viewer` can: read only. Read-only Y.Doc connection (Hocuspocus supports `readOnly: true` in onAuthenticate).
277
-
278
- ### 4.2 Path namespacing
279
-
280
- URLs become `/w/<workspace_slug>/<file-path>`. API:
281
-
282
- - `/api/workspaces/<workspace_id>/files/<path>` (catch-all)
283
- - `/api/workspaces/<workspace_id>/agent/files/<path>` (agent HTTP surface, see §7)
284
- - WS: `wss://<host>/yjs/<workspace_id>/<path>`
285
-
286
- Slug or UUID in URL? Use **slug** for human URLs (`/w/team-notes/plan.md`), **UUID** under the hood (resolved server-side in middleware). Keeps URLs nice without leaking enumerable IDs.
287
-
288
- ### 4.3 Agent registry under workspace
289
-
290
- ```
291
- agent_records
292
- id text primary key -- agent slug, e.g. "claude-1"
293
- workspace_id uuid references workspaces on delete cascade
294
- display_name text not null
295
- token_hash text not null -- sha256 of plaintext
296
- scope_paths jsonb not null -- string[] glob
297
- scope_ops jsonb not null -- ('read'|'mutate')[]
298
- created_by uuid references users
299
- created_at timestamptz default now()
300
- last_seen timestamptz
301
- unique (workspace_id, id)
302
- ```
303
-
304
- Token check becomes: lookup by hash → find row → check workspace + match `X-Agent-Id` to row id.
305
-
306
- `agent_registrations` table mirrors `pending.ts` but DB-backed (rows pruned after TTL).
307
-
308
- ---
309
-
310
- ## 5. Database
311
-
312
- ### 5.1 Engine choice
313
-
314
- Pick: **Postgres** (managed; e.g., Neon, Supabase, or Railway).
315
-
316
- Rationale:
317
-
318
- - User says "remote server, multi-user". SQLite single-writer model becomes a bottleneck under realtime workloads where Hocuspocus may write `ydoc_snapshots` every 5s per active file.
319
- - WS server may run as multiple replicas; SQLite + multiple writers = pain. Postgres handles concurrent writes natively.
320
- - LISTEN/NOTIFY useful for fan-out of events to non-WS subscribers (later).
321
- - Drizzle ORM has identical TS API for both, so swap cost is low if user prefers SQLite later.
322
-
323
- **Fallback for small deploys:** keep SQLite as an option via drizzle's dialect switch. Migrations written to both. Defaulted off; documented.
324
-
325
- ### 5.2 Full schema (concise)
326
-
327
- ```
328
- users (§3.2)
329
- oauth_accounts (§3.2)
330
- sessions (§3.2)
331
- workspaces (§4.1)
332
- workspace_members (§4.1)
333
- agent_records (§4.3)
334
-
335
- agent_registrations
336
- id text primary key -- registration code
337
- workspace_id uuid references workspaces on delete cascade
338
- payload jsonb -- display_name, requested scope
339
- status enum('pending','approved','rejected','expired') default 'pending'
340
- approved_by uuid references users
341
- approved_at timestamptz
342
- expires_at timestamptz
343
- created_at timestamptz default now()
344
-
345
- comments
346
- id text primary key -- "c" + hex
347
- workspace_id uuid references workspaces on delete cascade
348
- path text not null
349
- block_ref text not null
350
- resolved boolean default false
351
- created_at timestamptz default now()
352
- unique (workspace_id, path, id)
353
-
354
- comment_turns
355
- id bigserial primary key
356
- comment_id text references comments on delete cascade
357
- by text not null
358
- text text not null
359
- at timestamptz default now()
360
-
361
- suggestions
362
- id text primary key
363
- workspace_id uuid references workspaces on delete cascade
364
- path text not null
365
- block_ref text not null
366
- kind text not null
367
- status text not null
368
- by text not null
369
- markdown text
370
- basis text
371
- basis_detail text
372
- created_at timestamptz default now()
373
- resolved_at timestamptz
374
- resolved_by text
375
- unique (workspace_id, path, id)
376
-
377
- events
378
- id bigserial primary key
379
- workspace_id uuid references workspaces on delete cascade
380
- path text not null
381
- seq bigint not null -- monotonic per (workspace, path)
382
- type text not null
383
- by text not null
384
- at timestamptz default now()
385
- payload jsonb
386
- unique (workspace_id, path, seq)
387
-
388
- ack_cursors
389
- workspace_id uuid
390
- path text
391
- by text -- agent id
392
- up_to bigint -- event seq
393
- primary key (workspace_id, path, by)
394
-
395
- ydoc_snapshots
396
- workspace_id uuid
397
- path text
398
- taken_at timestamptz default now()
399
- state_update bytea -- Y.encodeStateAsUpdate
400
- primary key (workspace_id, path)
401
-
402
- block_provenance
403
- workspace_id uuid
404
- path text
405
- block_ref text
406
- attrs jsonb -- SpanAttrs for non-wrappable blocks
407
- primary key (workspace_id, path, block_ref)
408
- ```
409
-
410
- Files (the markdown bytes) stay on disk. No `files` table needed; the file tree under each workspace root is the source of fileness.
411
-
412
- ### 5.3 Migrations: Drizzle
413
-
414
- Pick: **Drizzle ORM + drizzle-kit**.
415
-
416
- | Option | Verdict |
417
- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
418
- | **Drizzle** | TS-first schemas, lightweight, no runtime overhead, generates SQL migrations as files, works with both Postgres and SQLite. NextAuth has a Drizzle adapter. Recommended for greenfield TS projects. |
419
- | Prisma | Heavier, slower start, opinionated client generation, less control. Reject. |
420
- | Kysely | Beautiful query builder, no migration story (drizzle's `drizzle-kit` is the closest equivalent and tighter). |
421
- | Raw SQL + a runner | Tempting but reintroduces bugs we already get for free. Reject. |
422
-
423
- Migration command in `package.json`: `db:generate`, `db:push`, `db:migrate`. Add to `scripts`.
424
-
425
- ---
426
-
427
- ## 6. Realtime transport
428
-
429
- ### 6.1 Co-location vs separate process
430
-
431
- **Pick co-location** via custom `server.ts`:
432
-
433
- ```ts
434
- // server.ts (sketch)
435
- const httpServer = http.createServer(nextHandler);
436
- const hocuspocus = Hocuspocus.configure({
437
- extensions: [database, throttle, logger],
438
- onAuthenticate,
439
- onLoadDocument,
440
- onChange,
441
- onStoreDocument,
442
- onDisconnect,
443
- });
444
- hocuspocus.attachWebSocketServer(httpServer, { path: "/yjs" });
445
- httpServer.listen(PORT);
446
- ```
447
-
448
- Reasons for co-location:
449
-
450
- - One process = one session model = one deploy unit
451
- - WS upgrade and HTTP go through the same TLS cert / domain (no CORS, no cross-origin cookies)
452
- - Hocuspocus's API is designed for this mounting style
453
-
454
- Cost: lose Next.js' built-in `next start` ergonomics. We replace with `node server.ts`. Document this.
455
-
456
- Alternative if WS scaling becomes a problem: factor Hocuspocus into a separate process behind the same reverse proxy, use Postgres or Redis as the cross-replica sync layer (`@hocuspocus/extension-database` supports this). Not in v2 scope.
457
-
458
- ### 6.2 Auth gate on WS upgrade
459
-
460
- ```ts
461
- async onAuthenticate({ token, documentName, request }) {
462
- const session = await verifySessionCookie(token);
463
- if (!session) throw new Error('UNAUTHORIZED');
464
-
465
- const [workspaceId, ...pathParts] = documentName.split('/');
466
- const role = await getMemberRole(workspaceId, session.user.id);
467
- if (!role) throw new Error('FORBIDDEN');
468
-
469
- const origin = request.headers.origin;
470
- if (!isAllowedOrigin(origin)) throw new Error('FORBIDDEN_ORIGIN');
471
-
472
- return {
473
- user: { id: session.user.id, name: session.user.displayName, color: hashColor(session.user.id) },
474
- workspaceId,
475
- path: pathParts.join('/'),
476
- readOnly: role === 'viewer'
477
- };
478
- }
479
- ```
480
-
481
- Browser side: y-hocuspocus provider's `token` param holds session cookie. Or, simpler — since same-origin WS auto-sends cookies, parse the cookie server-side in `onAuthenticate({ request })`. Pick whichever Hocuspocus's API exposes cleanly; document the choice in `server.ts`.
482
-
483
- ### 6.3 Awareness contract
484
-
485
- Each connection's awareness state:
486
-
487
- ```ts
488
- {
489
- user: { id: string, name: string, color: string },
490
- cursor?: { anchor: number, head: number },
491
- typing?: boolean
492
- }
493
- ```
494
-
495
- - Color: deterministic from user id (`hashColor`), 12-color palette tuned for the editor's dark + light themes. Same user same color across reconnects.
496
- - Display name: from session.
497
- - Cursors render via `y-prosemirror`'s built-in `yCursorPlugin`. Configure to render small caret bar + tag with name on hover.
498
- - Typing indicator (optional polish): set true on input, debounce-clear after 1s. Not strictly necessary v2.
499
-
500
- ---
501
-
502
- ## 7. Agent bridge changes
503
-
504
- ### 7.1 Two architectural options
505
-
506
- **Option A: HTTP-only agent surface, server compiles ops to Y.Doc transactions.** (chosen)
507
-
508
- ```
509
- Agent ─HTTP POST /api/agent/files─► route
510
-
511
- ├─ verify auth + scope + by
512
- ├─ open Y.Doc (load from in-memory pool or rehydrate from snapshot)
513
- ├─ check baseRevision
514
- ├─ ops-applier-yjs.applyOps(ops, ydoc, { actor })
515
- │ - for each block.* op: mutate Y.XmlFragment within doc.transact()
516
- │ - for each comment.* / suggestion.* op: DB row update
517
- │ - emit events
518
- │ - wrap proof-spans inline as Y nodes
519
- ├─ bump revision counter (DB)
520
- ├─ schedule flush (markdown serialize + ydoc_snapshot upsert)
521
- └─ return new Snapshot
522
- ```
523
-
524
- The transact's awareness identity is set to a synthetic clientId reserved for the agent (e.g. negative integers per agent id, deterministic). Browser sees the edit live via Hocuspocus broadcast; cursors show "claude is editing" via awareness if the agent also pushes presence.
525
-
526
- **Option B: Agent has its own Yjs client connection.** (rejected)
527
-
528
- | Pro | Con |
529
- | ------------------------ | -------------------------------------------------------------------------------------------------------------------- |
530
- | Agent gets realtime echo | Agent SDK becomes 10x more complex (must speak y-protocols) |
531
- | | Agent can no longer be "just curl" |
532
- | | Breaks v1 skill / bootstrap-prompt entirely |
533
- | | No clear win — agents don't need to see human keystrokes in real time; polling events catches comment additions etc. |
534
-
535
- **Decision: Option A.** Existing skill/bootstrap-prompt survives unchanged in shape; only the workspace prefix on URLs is new and the bearer token replaces env-token semantics.
536
-
537
- ### 7.2 baseRevision becomes mutationBaseToken (or stays revision)
538
-
539
- Both are returned. Agents that send only `baseRevision` still work. Newer agents may send `mutationBaseToken` for finer-grained concurrency awareness (§2.3).
540
-
541
- ### 7.3 proof-span behavior
542
-
543
- Unchanged in shape. Wrapping logic moves: ops-applier-yjs constructs the proof-span as a Y.XmlElement (or as inline HTML inside a paragraph's Y.XmlText, depending on how y-prosemirror serializes ProofSpan marks).
544
-
545
- **Important integration test (Phase 6):** insert a paragraph via agent → verify y-prosemirror renders the proof-span mark on the right text → verify markdown serialization emits the right HTML.
546
-
547
- ### 7.4 New agent endpoints
548
-
549
- - `POST /api/workspaces/<wid>/agent/files/<path>` — same op vocab
550
- - `GET /api/workspaces/<wid>/agent/files/<path>` — snapshot
551
- - `GET /api/workspaces/<wid>/agent/events/<path>` — events
552
- - `POST /api/workspaces/<wid>/agent/events/<path>` — ack
553
- - `GET /api/workspaces/<wid>/agent/sidecar/<path>` — comments + suggestions JSON (now built from DB)
554
-
555
- Backward compat shim: `GET /api/agent/files/<path>` redirects to `/api/workspaces/<default>/agent/files/<path>` for single-workspace deployments. Document deprecation.
556
-
557
- ---
558
-
559
- ## 8. Editor changes
560
-
561
- ### 8.1 Remove the htmlToMarkdown save loop
562
-
563
- Current path: editor change → debounce → `htmlToMarkdown` → `PUT /api/wiki/content`. This bypasses the ops-applier and the revision counter — v1 known bug.
564
-
565
- v2:
566
-
567
- - Editor binds to Y.Doc via `@tiptap/extension-collaboration` + `y-prosemirror`.
568
- - All edits land in Y.Doc → Hocuspocus broadcasts.
569
- - Server's `onChange` debounces flush (§2.1).
570
- - `PUT /api/wiki/content` becomes **read-only-or-removed**. Optionally keep for non-markdown files (json, ts, etc. that the editor still saves directly). For markdown files: return 410 Gone with message "use Yjs editor".
571
-
572
- Editor's `editor-store.ts` simplifies: no debounced save side, just open/close Y.Doc connections.
573
-
574
- ### 8.2 ProofSpan mark stays
575
-
576
- Definition unchanged. Y-prosemirror serializes marks fine. Verify with a Y.Doc round-trip test (§9 Phase 4).
577
-
578
- ### 8.3 Suggestion cards + comment pips read from DB
579
-
580
- Currently they read from `useProofStore` populated by `GET /api/agent/sidecar/<path>`. v2: same store, same component code; underlying API now reads from DB rows. Almost zero React component change.
581
-
582
- When a comment is added (by anyone), server emits an event AND pushes to a per-workspace SSE channel that the editor subscribes to → store updates → pip appears. (Could route via Hocuspocus message channel too, but SSE keeps comment state out of the Y.Doc, which is intentional.)
583
-
584
- ### 8.4 Markdown export
585
-
586
- Server-side function `yDocToMarkdown(doc, { workspaceId, path })`:
587
-
588
- 1. Walk Y.XmlFragment → convert each block element to mdast node (reverse of v1's parse, with provenance attrs preserved on text marks).
589
- 2. Stringify via remark-stringify (same options as v1's `blocks.ts`).
590
- 3. Augment with block_provenance rows for non-wrappable blocks.
591
-
592
- Used by:
593
-
594
- - Debounced disk flush (§2.1)
595
- - `GET /api/workspaces/<wid>/files/<path>?format=markdown` (read-only API)
596
- - Git friendly view, downloads, mobile read-only mode if it ever ships
597
-
598
- ---
599
-
600
- ## 9. Concrete phase plan
601
-
602
- Each phase ends with a green-test gate.
603
-
604
- ### Phase 1 — Auth: OAuth + sessions
605
-
606
- - Add Drizzle + Postgres. Schema for users, oauth_accounts, sessions.
607
- - Add NextAuth v5 with GitHub + Google providers. Drizzle adapter.
608
- - Middleware that populates `req.user` from session cookie.
609
- - Replace `wv_owner` cookie reads in routes with session reads.
610
- - `/signin` page.
611
- - **Tests:** session round-trip, OAuth mock callback creates user.
612
- - **LoC ~700. Time ~1-2d.**
613
- - **Gate:** sign in via GitHub, see name in header, sign out.
614
-
615
- ### Phase 2 — Workspaces + DB migration of registry
616
-
617
- - Schema: workspaces, workspace_members, agent_records, agent_registrations.
618
- - Migration script: read `~/.wiki-viewer/agents.json` → seed default workspace + agents.
619
- - `/api/workspaces` CRUD.
620
- - `safeRootPath` → `safeWorkspacePath(workspaceId, rel)`. Update consumers.
621
- - DB-backed registry.
622
- - **Tests:** workspaces.test, registry-db.test (ports of v1 registry tests).
623
- - **LoC ~900. Time ~2d.**
624
- - **Gate:** existing 160 + new tests green.
625
-
626
- ### Phase 3 — DB-backed sidecar
627
-
628
- - Schema: comments, comment_turns, suggestions, events, ack_cursors, block_provenance.
629
- - `lib/proof/sidecar-store.ts` DB-backed; same API as v1.
630
- - ops-applier writes DB rows.
631
- - Migration: import `.proof/*.json` into DB on first read.
632
- - **Tests:** all v1 ops-applier/comments/suggestion/trim tests via in-mem DB.
633
- - **LoC ~700. Time ~2d.**
634
- - **Gate:** 160+ tests green.
635
-
636
- ### Phase 4 — Yjs server + flush sink (no editor binding yet)
637
-
638
- - Add yjs, @hocuspocus/server, y-prosemirror, @tiptap/extension-collaboration.
639
- - `server.ts` mounts Hocuspocus on `/yjs`.
640
- - `lib/proof/yjs-store.ts`: loadDoc / flushDoc / closeDoc.
641
- - `lib/proof/yjs-markdown.ts`: markdownToYjs, yDocToMarkdown.
642
- - Chokidar reconciler (§1.3.5).
643
- - WS auth (§6.2).
644
- - **Tests:** yjs-roundtrip, yjs-external-edit, yjs-flush.
645
- - **LoC ~1300. Time ~3d.**
646
- - **Gate:** Y.Doc lifecycle tests green.
647
-
648
- ### Phase 5 — Editor binding + presence
649
-
650
- - Replace save loop with y-prosemirror collab binding.
651
- - Hocuspocus provider client.
652
- - Cursor caret + name tag (yCursorPlugin).
653
- - Presence avatar bar.
654
- - Remove `PUT /api/wiki/content` for `.md`.
655
- - **Tests:** editor-roundtrip via Y.Doc; manual two-tab test.
656
- - **LoC ~600. Time ~2d.**
657
- - **Gate:** two-tab live edit works.
658
-
659
- ### Phase 6 — Agent bridge port to Yjs
660
-
661
- - `ops-applier.ts` → `ops-applier-yjs.ts`. `doc.transact()` for block ops.
662
- - proof-span wrap via Y nodes.
663
- - mutationBaseToken in snapshot.
664
- - Routes under `/api/workspaces/<wid>/agent/*`; back-compat redirect.
665
- - Update skill bootstrap-prompt for workspace prefix.
666
- - **Tests:** rewrite ops-applier assertions to Y.Doc state; new concurrent-edits.test.
667
- - **LoC ~1100. Time ~3d.**
668
- - **Gate:** all proof tests green + concurrency test.
669
-
670
- ### Phase 7 — Realtime UI polish
671
-
672
- - Per-block selection indicators.
673
- - Comment SSE push for instant pip appearance.
674
- - Suggestion live push.
675
- - HTTPS enforcement, CSRF token, Origin check.
676
- - **LoC ~500. Time ~2d.**
677
-
678
- ### Phase 8 — Hardening
679
-
680
- - Rate limit WS connections per user.
681
- - WS message size cap.
682
- - Idle eviction tests.
683
- - Snapshot pruning.
684
- - Docs: README "running multi-user", `docs/file-vs-yjs-authority.md`.
685
- - **LoC ~400. Time ~1-2d.**
686
-
687
- **Total: ~6200 LoC, 16-18 working days.**
688
-
689
- ---
690
-
691
- ## 10. Risks + open questions
692
-
693
- ### 10.1 File vs Y.Doc authority
694
-
695
- External edit during live session: external wins, applied as Yjs transaction. Risk: silent loss of unflushed Y.Doc edits. Mitigation: aggressive flush during active session.
696
-
697
- ### 10.2 Git commits during live editing
698
-
699
- Commit captures whatever was flushed. Sample pre-commit hook calls `/api/flush`. Document, don't auto-install.
700
-
701
- ### 10.3 Bandwidth
702
-
703
- Idle: few KB/s keepalive. Active edit: ~1-10 KB/s. 100 users ≈ 1 MB/s peak. Acceptable.
704
-
705
- ### 10.4 Suggestion lifecycle in CRDT
706
-
707
- Accept applies Y.Doc transaction. If target block was deleted by human edit: BLOCK_NOT_FOUND, suggestion auto-archived "block_deleted".
708
-
709
- ### 10.5 Undo for AI-marked content
710
-
711
- proof-span removal via Y.Doc transaction. Edge case: undo after human typed in span may restore mark over human content. Document and accept.
712
-
713
- ### 10.6 Open questions for user (before Phase 1)
714
-
715
- 1. Postgres OK, or insist on SQLite for solo deploys? (Recommend Postgres + SQLite-as-option.)
716
- 2. Managed Postgres (Neon/Supabase) or self-host?
717
- 3. GitHub + Google confirmed. Microsoft later? (No for v2.)
718
- 4. Workspace creation: anyone or admin-only? (Recommend: anyone creates their own; admins invite to existing.)
719
- 5. Editor for non-markdown files: keep `PUT /api/wiki/content`? (Yes.)
720
- 6. Browser localStorage Y.Doc persistence for offline read? (Not v2.)
721
-
722
- ---
723
-
724
- ## 11. Out of scope
725
-
726
- - Mobile native app
727
- - Offline editing without sync
728
- - E2E encryption
729
- - Plugin marketplace
730
- - Search (full-text), tags
731
- - Real-time voice/video
732
- - File create/rename/delete via agent
733
- - Multi-file agent ops
734
- - Cross-workspace links
735
- - Snapshot history browsing
736
- - Audit log UI beyond event stream
737
-
738
- ---
739
-
740
- ## 12. Constraint compliance
741
-
742
- | Constraint | v2 |
743
- | --------------------------------------- | ----------------------------------------------------------------------------------------- |
744
- | Preserve agent HTTP contract | Op vocab unchanged. URL gains `/workspaces/<wid>`. Skill ships with one-line path update. |
745
- | Tests keep running | `node --test` / `tsx --test`. New tests follow pattern. |
746
- | 160 tests mostly survive | Phases 1-3 port them. Phase 6 rewrites assertions, preserves cases. ≥150 survive. |
747
- | No big-bang | 8 phases each shippable. User can pause after Phase 3. |
748
- | Tabs, TS strict, no `any`, no em-dashes | Continued. |
749
-
750
- ---
751
-
752
- ## 13. Definition of done
753
-
754
- - Phases 1-8 merged
755
- - All tests green incl. Phase 6 rewrites
756
- - Two-tab live edit smoke passes
757
- - External edit reconciliation smoke passes
758
- - Agent skill updated + re-tested end-to-end
759
- - `docs/file-vs-yjs-authority.md` reviewed
760
- - README "running multi-user" section
761
- - v1 plan (`docs/agent-collab-plan.md`) untouched
762
-
763
- ---
764
-
765
- ## 14. Critical files for implementation
766
-
767
- - `src/lib/proof/ops-applier.ts` → becomes `ops-applier-yjs.ts`; biggest refactor
768
- - `src/components/editor/editor.tsx` → replace save loop with y-prosemirror collab binding
769
- - `src/lib/proof/registry.ts` → DB-backed per-workspace agent records
770
- - `src/lib/proof/auth.ts` → session+OAuth gate, plus WS onAuthenticate
771
- - `src/app/api/wiki/content/route.ts` → remove markdown PUT path that bypasses pipeline