wiki-viewer 1.4.2 → 1.5.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 (280) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +5 -0
  3. package/.next/standalone/.next/build-manifest.json +3 -3
  4. package/.next/standalone/.next/prerender-manifest.json +3 -27
  5. package/.next/standalone/.next/routes-manifest.json +34 -0
  6. package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
  7. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page.js +4 -4
  16. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  18. package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  21. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  22. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  23. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  24. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  25. package/.next/standalone/.next/server/app/api/agent/activity/route.js +5 -5
  26. package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/agent/admin/agents/[agentId]/revoke/route.js +6 -6
  28. package/.next/standalone/.next/server/app/api/agent/admin/agents/[agentId]/revoke/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/agent/admin/agents/route.js +6 -6
  30. package/.next/standalone/.next/server/app/api/agent/admin/agents/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/approve/route.js +6 -6
  32. package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/approve/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/deny/route.js +4 -4
  34. package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/deny/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/agent/admin/registrations/route.js +4 -4
  36. package/.next/standalone/.next/server/app/api/agent/admin/registrations/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js +5 -5
  38. package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js +11 -10
  40. package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route/app-paths-manifest.json +3 -0
  42. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route/build-manifest.json +9 -0
  43. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route/server-reference-manifest.json +4 -0
  44. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js +17 -0
  45. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.map +5 -0
  46. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -0
  47. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route_client-reference-manifest.js +3 -0
  48. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route/app-paths-manifest.json +3 -0
  49. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route/build-manifest.json +9 -0
  50. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route/server-reference-manifest.json +4 -0
  51. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js +15 -0
  52. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.map +5 -0
  53. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -0
  54. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route_client-reference-manifest.js +3 -0
  55. package/.next/standalone/.next/server/app/api/agent/fs/move/route/app-paths-manifest.json +3 -0
  56. package/.next/standalone/.next/server/app/api/agent/fs/move/route/build-manifest.json +9 -0
  57. package/.next/standalone/.next/server/app/api/agent/fs/move/route/server-reference-manifest.json +4 -0
  58. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js +15 -0
  59. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.map +5 -0
  60. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -0
  61. package/.next/standalone/.next/server/app/api/agent/fs/move/route_client-reference-manifest.js +3 -0
  62. package/.next/standalone/.next/server/app/api/agent/fs/search/route/app-paths-manifest.json +3 -0
  63. package/.next/standalone/.next/server/app/api/agent/fs/search/route/build-manifest.json +9 -0
  64. package/.next/standalone/.next/server/app/api/agent/fs/search/route/server-reference-manifest.json +4 -0
  65. package/.next/standalone/.next/server/app/api/agent/fs/search/route.js +15 -0
  66. package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.map +5 -0
  67. package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -0
  68. package/.next/standalone/.next/server/app/api/agent/fs/search/route_client-reference-manifest.js +3 -0
  69. package/.next/standalone/.next/server/app/api/agent/internal/span/route.js +8 -8
  70. package/.next/standalone/.next/server/app/api/agent/internal/span/route.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/api/agent/settings/route.js +8 -8
  72. package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
  73. package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js +7 -7
  74. package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js.nft.json +1 -1
  75. package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js +1 -1
  76. package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js.nft.json +1 -1
  77. package/.next/standalone/.next/server/app/api/assets/[...path]/route.js.nft.json +1 -1
  78. package/.next/standalone/.next/server/app/api/auth/[...all]/route.js +3 -3
  79. package/.next/standalone/.next/server/app/api/auth/[...all]/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/system/auth-config/route.js +5 -5
  81. package/.next/standalone/.next/server/app/api/system/auth-config/route.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/api/system/auth-settings/route.js +4 -4
  83. package/.next/standalone/.next/server/app/api/system/auth-settings/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/system/browse/route.js +6 -6
  85. package/.next/standalone/.next/server/app/api/system/browse/route.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/api/system/clear-root/route.js +5 -5
  87. package/.next/standalone/.next/server/app/api/system/clear-root/route.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/api/system/config/route.js +5 -5
  89. package/.next/standalone/.next/server/app/api/system/config/route.js.nft.json +1 -1
  90. package/.next/standalone/.next/server/app/api/system/pins/route.js +4 -4
  91. package/.next/standalone/.next/server/app/api/system/pins/route.js.nft.json +1 -1
  92. package/.next/standalone/.next/server/app/api/system/reveal/route.js +4 -4
  93. package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/api/system/root-status/route.js +4 -4
  95. package/.next/standalone/.next/server/app/api/system/root-status/route.js.nft.json +1 -1
  96. package/.next/standalone/.next/server/app/api/system/set-root/route.js +5 -5
  97. package/.next/standalone/.next/server/app/api/system/set-root/route.js.nft.json +1 -1
  98. package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/api/wiki/app/route.js +6 -6
  100. package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/wiki/content/route.js +6 -6
  102. package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/wiki/file/route.js.nft.json +1 -1
  104. package/.next/standalone/.next/server/app/api/wiki/folder/route.js +5 -5
  105. package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
  106. package/.next/standalone/.next/server/app/api/wiki/move/route.js +6 -6
  107. package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
  108. package/.next/standalone/.next/server/app/api/wiki/new-file/route.js +5 -5
  109. package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
  110. package/.next/standalone/.next/server/app/api/wiki/page/route.js +5 -5
  111. package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
  112. package/.next/standalone/.next/server/app/api/wiki/presence/route/app-paths-manifest.json +3 -0
  113. package/.next/standalone/.next/server/app/api/wiki/presence/route/build-manifest.json +9 -0
  114. package/.next/standalone/.next/server/app/api/wiki/presence/route/server-reference-manifest.json +4 -0
  115. package/.next/standalone/.next/server/app/api/wiki/presence/route.js +14 -0
  116. package/.next/standalone/.next/server/app/api/wiki/presence/route.js.map +5 -0
  117. package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -0
  118. package/.next/standalone/.next/server/app/api/wiki/presence/route_client-reference-manifest.js +3 -0
  119. package/.next/standalone/.next/server/app/api/wiki/route.js +5 -5
  120. package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
  121. package/.next/standalone/.next/server/app/api/wiki/slugs/route.js +5 -5
  122. package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
  123. package/.next/standalone/.next/server/app/api/wiki/upload/route.js +5 -5
  124. package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
  125. package/.next/standalone/.next/server/app/api/wiki/watch/route.js +6 -6
  126. package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
  127. package/.next/standalone/.next/server/app/index.html +1 -1
  128. package/.next/standalone/.next/server/app/index.rsc +2 -2
  129. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  130. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  131. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  132. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  133. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  134. package/.next/standalone/.next/server/app/page.js +4 -4
  135. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  136. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  137. package/.next/standalone/.next/server/app/signin/page.js +9 -4
  138. package/.next/standalone/.next/server/app/signin/page.js.nft.json +1 -1
  139. package/.next/standalone/.next/server/app/signin/page_client-reference-manifest.js +1 -1
  140. package/.next/standalone/.next/server/app-paths-manifest.json +5 -0
  141. package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0d2jbo5.js +3 -0
  142. package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0ytral2.js +3 -0
  143. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0269d2e._.js +1 -1
  144. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__03h3~3e._.js → [root-of-the-server]__04udrya._.js} +2 -2
  145. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05f6x0i._.js +3 -0
  146. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06-dtd0._.js +3 -0
  147. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06sek6_._.js +1 -1
  148. package/.next/standalone/.next/server/chunks/[root-of-the-server]__09s9qkd._.js +1 -1
  149. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d75a5q._.js +1 -1
  150. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d_da6q._.js +3 -0
  151. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e7si9p._.js +1 -1
  152. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0hhhvm7._.js +1 -1
  153. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__04g0j8i._.js → [root-of-the-server]__0kdn1le._.js} +2 -2
  154. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kk26wc._.js +3 -0
  155. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kur4ro._.js +15 -0
  156. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0p12-6~._.js +1 -1
  157. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qc2~6l._.js +15 -0
  158. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0s~i040._.js +3 -0
  159. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0w47wil._.js +1 -1
  160. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xq124z._.js +3 -0
  161. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0l..bxz._.js → [root-of-the-server]__0xz-_0v._.js} +2 -2
  162. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10w2q~o._.js +1 -1
  163. package/.next/standalone/.next/server/chunks/_079xuln._.js +3 -0
  164. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_file_[___path]_route_actions_0gb11t~.js +3 -0
  165. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_ls_[[___path]]_route_actions_0wfg4nl.js +3 -0
  166. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_move_route_actions_0z34mqq.js +3 -0
  167. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_search_route_actions_0ut_ug..js +3 -0
  168. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_wiki_presence_route_actions_0x9d7f4.js +3 -0
  169. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0d89o98._.js → src_lib_auth_server_ts_00f4e0h._.js} +2 -2
  170. package/.next/standalone/.next/server/chunks/ssr/0biy_@better-auth_core_dist_121m_lh._.js +5 -0
  171. package/.next/standalone/.next/server/chunks/ssr/0dhv_better-auth_dist_adapters_kysely-adapter_index_mjs_08ymlcb._.js +3 -0
  172. package/.next/standalone/.next/server/chunks/ssr/0dti_kysely_dist_esm_0-t3o9q._.js +3 -0
  173. package/.next/standalone/.next/server/chunks/ssr/0dti_kysely_dist_esm_01._58q._.js +3 -0
  174. package/.next/standalone/.next/server/chunks/ssr/0p91_next_0f40gy0._.js +6 -0
  175. package/.next/standalone/.next/server/chunks/ssr/{0p91_next_dist_0~2d1tl._.js → 0p91_next_dist_10ud_sa._.js} +2 -2
  176. package/.next/standalone/.next/server/chunks/ssr/0sag_@better-auth_memory-adapter_dist_index_mjs_07-_ka6._.js +3 -0
  177. package/.next/standalone/.next/server/chunks/ssr/0ugq_@better-auth_kysely-adapter_dist_bun-sqlite-dialect-DzNwOpKv_mjs_0lruvb8._.js +3 -0
  178. package/.next/standalone/.next/server/chunks/ssr/0ugq_@better-auth_kysely-adapter_dist_d1-sqlite-dialect-C2B7YsIT_mjs_03n6~tc._.js +3 -0
  179. package/.next/standalone/.next/server/chunks/ssr/0ugq_@better-auth_kysely-adapter_dist_index_mjs_0gi5w.w._.js +4 -0
  180. package/.next/standalone/.next/server/chunks/ssr/0ugq_@better-auth_kysely-adapter_dist_node-sqlite-dialect_mjs_0l4.y~0._.js +3 -0
  181. package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_diagram-OG6HWLK6_mjs_0t5sus6._.js +1 -1
  182. package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_sankeyDiagram-5OEKKPKP_mjs_11ifrnu._.js +1 -1
  183. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__026s8~z._.js +3 -0
  184. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06mzg2t._.js +3 -0
  185. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0btcd4o._.js +12 -0
  186. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0c~og-9._.js +3 -0
  187. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__134_q7l._.js +1 -1
  188. package/.next/standalone/.next/server/chunks/ssr/_0pqaawz._.js +3 -3
  189. package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_051tcva._.js +3 -0
  190. package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_0o~d81.._.js +1 -1
  191. package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_0y9k6h~._.js +1 -1
  192. package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_0znncy9._.js +1 -1
  193. package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_12-ni1n._.js +1 -1
  194. package/.next/standalone/.next/server/chunks/ssr/src_app_signin_00yk0vm._.js +452 -0
  195. package/.next/standalone/.next/server/chunks/ssr/src_app_signin_signin-form_tsx_0eznlbd._.js +3 -0
  196. package/.next/standalone/.next/server/functions-config-manifest.json +5 -0
  197. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  198. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  199. package/.next/standalone/.next/server/pages/404.html +1 -1
  200. package/.next/standalone/.next/server/pages/500.html +1 -1
  201. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  202. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  203. package/.next/standalone/.next/static/chunks/09-jtayuhrq~b.js +1 -0
  204. package/.next/standalone/.next/static/chunks/0uv7ozzpiyp2_.js +1 -0
  205. package/.next/standalone/.next/static/chunks/135c~rq_ux73w.js +1 -0
  206. package/.next/standalone/.next/static/chunks/{11s9zwr7edrs7.js → 14luv~jq7e6-n.js} +12 -12
  207. package/.next/standalone/README.md +79 -16
  208. package/.next/standalone/agents/bootstrap-prompt.md +12 -1
  209. package/.next/standalone/agents/wiki-viewer-skill/SKILL.md +199 -6
  210. package/.next/standalone/docs/agent-fs-plan.md +65 -7
  211. package/.next/standalone/docs/file-vs-collab-authority.md +124 -0
  212. package/.next/standalone/package.json +1 -1
  213. package/.next/standalone/packages/wiki-viewer-mcp/README.md +194 -0
  214. package/.next/standalone/packages/wiki-viewer-mcp/dist/http-client.js +220 -0
  215. package/.next/standalone/packages/wiki-viewer-mcp/dist/index.js +472 -0
  216. package/.next/standalone/packages/wiki-viewer-mcp/dist/register.js +94 -0
  217. package/.next/standalone/packages/wiki-viewer-mcp/dist/state-cache.js +26 -0
  218. package/.next/standalone/packages/wiki-viewer-mcp/package-lock.json +1716 -0
  219. package/.next/standalone/packages/wiki-viewer-mcp/package.json +41 -0
  220. package/.next/standalone/packages/wiki-viewer-mcp/src/http-client.ts +344 -0
  221. package/.next/standalone/packages/wiki-viewer-mcp/src/index.ts +575 -0
  222. package/.next/standalone/packages/wiki-viewer-mcp/src/register.ts +144 -0
  223. package/.next/standalone/packages/wiki-viewer-mcp/src/state-cache.ts +45 -0
  224. package/.next/standalone/packages/wiki-viewer-mcp/tsconfig.json +19 -0
  225. package/.next/standalone/pnpm-lock.yaml +9 -9
  226. package/.next/standalone/src/app/api/agent/files/[...path]/route.ts +11 -1
  227. package/.next/standalone/src/app/api/agent/fs/file/[...path]/route.ts +344 -0
  228. package/.next/standalone/src/app/api/agent/fs/ls/[[...path]]/route.ts +147 -0
  229. package/.next/standalone/src/app/api/agent/fs/move/route.ts +125 -0
  230. package/.next/standalone/src/app/api/agent/fs/search/route.ts +236 -0
  231. package/.next/standalone/src/app/api/agent/register/route.ts +3 -3
  232. package/.next/standalone/src/app/api/agents/install/route.ts +44 -2
  233. package/.next/standalone/src/app/api/wiki/move/route.ts +10 -1
  234. package/.next/standalone/src/app/api/wiki/presence/route.ts +55 -0
  235. package/.next/standalone/src/app/signin/page.tsx +10 -225
  236. package/.next/standalone/src/app/signin/signin-form.tsx +238 -0
  237. package/.next/standalone/src/components/ai-panel/ai-panel.tsx +49 -0
  238. package/.next/standalone/src/components/editor/editor.tsx +38 -0
  239. package/.next/standalone/src/lib/proof/audit.ts +79 -0
  240. package/.next/standalone/src/lib/proof/auth.ts +2 -2
  241. package/.next/standalone/src/lib/proof/collab-state.ts +79 -0
  242. package/.next/standalone/src/lib/proof/lease.ts +104 -0
  243. package/.next/standalone/src/lib/proof/ops-applier.ts +74 -25
  244. package/.next/standalone/src/lib/proof/raw-fs.ts +198 -0
  245. package/.next/standalone/src/lib/proof/registry.ts +1 -1
  246. package/.next/standalone/src/lib/proof/sidecar.ts +38 -1
  247. package/.next/standalone/src/lib/proof/types.ts +13 -1
  248. package/.next/standalone/src/tests/proof/agent-fs.test.ts +824 -0
  249. package/.next/standalone/src/tests/proof/agents-install.test.ts +53 -0
  250. package/.next/standalone/src/tests/proof/collab-state.test.ts +499 -0
  251. package/.next/standalone/src/tests/proof/reconcile-sidecar.test.ts +195 -0
  252. package/.next/standalone/src/tests/proof/sidecar-lifecycle.test.ts +177 -0
  253. package/.next/standalone/tsconfig.tsbuildinfo +1 -1
  254. package/README.md +79 -16
  255. package/package.json +1 -1
  256. package/.next/standalone/.next/server/app/signin.html +0 -1
  257. package/.next/standalone/.next/server/app/signin.meta +0 -15
  258. package/.next/standalone/.next/server/app/signin.rsc +0 -23
  259. package/.next/standalone/.next/server/app/signin.segments/_full.segment.rsc +0 -23
  260. package/.next/standalone/.next/server/app/signin.segments/_head.segment.rsc +0 -6
  261. package/.next/standalone/.next/server/app/signin.segments/_index.segment.rsc +0 -7
  262. package/.next/standalone/.next/server/app/signin.segments/_tree.segment.rsc +0 -3
  263. package/.next/standalone/.next/server/app/signin.segments/signin/__PAGE__.segment.rsc +0 -9
  264. package/.next/standalone/.next/server/app/signin.segments/signin.segment.rsc +0 -5
  265. package/.next/standalone/.next/server/chunks/[root-of-the-server]__09~~-nd._.js +0 -3
  266. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0w87kiz._.js +0 -3
  267. package/.next/standalone/.next/server/chunks/[root-of-the-server]__12ssbhv._.js +0 -3
  268. package/.next/standalone/.next/server/chunks/node_modules__pnpm_0g0fhfk._.js +0 -3
  269. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__088hqzy._.js +0 -3
  270. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0c147fo._.js +0 -3
  271. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0z.1v1z._.js +0 -3
  272. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12zp2dm._.js +0 -3
  273. package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_0exqvyf._.js +0 -3
  274. package/.next/standalone/.next/server/chunks/ssr/src_app_signin_page_tsx_1143y49._.js +0 -3
  275. package/.next/standalone/.next/static/chunks/0-_39e4awbk8y.js +0 -1
  276. package/.next/standalone/.next/static/chunks/02bxx~2cg~s6~.js +0 -1
  277. package/.next/standalone/.next/static/chunks/0mj_f8ncf2tks.js +0 -1
  278. /package/.next/standalone/.next/static/{OwXjVuoXDC_gda_BKji1J → 19j4-_brJLoulXAMekpM2}/_buildManifest.js +0 -0
  279. /package/.next/standalone/.next/static/{OwXjVuoXDC_gda_BKji1J → 19j4-_brJLoulXAMekpM2}/_clientMiddlewareManifest.js +0 -0
  280. /package/.next/standalone/.next/static/{OwXjVuoXDC_gda_BKji1J → 19j4-_brJLoulXAMekpM2}/_ssgManifest.js +0 -0
@@ -22,8 +22,10 @@
22
22
  Originally a zero-config single-user tool, it now supports:
23
23
 
24
24
  - Multi-user sign-in (Google OAuth or email + password) for teams of 3 to 10 sharing a VPS.
25
- - An HTTP collaboration API that lets AI agents read and edit Markdown files alongside you, with provenance marks, comments, suggestions, and revision-checked mutations.
25
+ - An HTTP API for AI agents with **two tiers**: a raw filesystem (read/write/edit/list/search/move/delete for **all file types**) for fast filework, and a Markdown collaboration layer with provenance marks, comments, suggestions, and revision-checked mutations.
26
+ - A **working-vs-collaborating** safety model: when you have a Markdown doc open, agents automatically defer to the reviewable collab path instead of overwriting it.
26
27
  - Per-agent registration and scoped tokens. No shared bearer secret.
28
+ - An optional `npx wiki-viewer-mcp` adapter so MCP-capable agents (Claude Code, Cursor, Codex) get native file tools against a remote instance.
27
29
 
28
30
  Single-user, no-auth mode still works. Auth turns on automatically once anyone signs up.
29
31
 
@@ -279,7 +281,23 @@ The Markdown editor now sends a `baseRevision` with every save. If another user
279
281
 
280
282
  ## Working with AI agents
281
283
 
282
- wiki-viewer exposes an HTTP collaboration protocol so agents (Claude, Cursor, ChatGPT desktop, custom scripts) can read and edit Markdown files. Every AI-authored insert is wrapped in an inline `<proof-span>` mark so the human reviewer can see, accept, or revert each change.
284
+ wiki-viewer exposes an HTTP API so agents (Claude, Cursor, ChatGPT desktop, custom scripts) can work with files in a running instance locally or remotely almost as if they were on their own filesystem. There are **two tiers**, sharing one auth/scope/lock spine:
285
+
286
+ - **Tier 1 — Raw filesystem** (`/api/agent/fs/*`): `read`, `write`, `edit`, `list`, `search`, `move`, `delete` for **every file type** (code, configs, PDFs, notebooks, Markdown — anything). Fast, boring, byte-accurate. Mutations are audited.
287
+ - **Tier 2 — Markdown collaboration** (`/api/agent/files/*`): structured block-ops where every AI-authored insert is wrapped in an inline `<proof-span>` mark so the human reviewer can see, accept, or revert each change, plus comments and suggestions. Tier-2 is API-compatible in spirit with [Proof SDK](https://github.com/EveryInc/proof-sdk).
288
+
289
+ ### Which tier? Working mode vs collaborating mode
290
+
291
+ Before editing a Markdown file, an agent reads it and checks the **`X-Collab-State`** response header:
292
+
293
+ | `X-Collab-State` | Meaning | Agent uses |
294
+ | ---------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------- |
295
+ | `active` | A human has the doc open, or it has pending suggestions/comments | **Tier-2 block-ops** (reviewable). A raw write is rejected `409 COLLAB_ACTIVE`. |
296
+ | `tracked` | Has a collab sidecar, nobody editing now | Prefer Tier-2 for prose; raw OK for mechanical edits |
297
+ | `untracked` | Plain Markdown, never collaborated on | Either tier |
298
+ | `not-markdown` | Any non-`.md` file | **Tier-1 raw only** |
299
+
300
+ This is enforced, not advisory: the collab state is re-checked atomically inside the write lock, so an agent can never silently clobber a doc you just opened. The browser editor sends a presence heartbeat to drive the `active` state. See [`docs/file-vs-collab-authority.md`](docs/file-vs-collab-authority.md) for the full authority model.
283
301
 
284
302
  The protocol is intentionally API-compatible in spirit with [Proof SDK](https://github.com/EveryInc/proof-sdk).
285
303
 
@@ -306,7 +324,42 @@ npx skills add anh-chu/wiki-viewer/agents/wiki-viewer-skill
306
324
 
307
325
  For any chat agent, paste the bootstrap prompt from `<your-server>/agents/install` (also visible in the AI Panel). The agent fetches `/api/agents/install` and learns the full op vocabulary at runtime.
308
326
 
309
- ### Op vocabulary
327
+ ### Tier 1 — raw filesystem
328
+
329
+ Work with any file type. All routes take `Authorization: Bearer <token>` + `X-Agent-Id`, are scope-checked, and reject path traversal, symlink escapes, and anything under `.proof/`.
330
+
331
+ ```bash
332
+ # Read (bytes; ETag is the sha256, supports Range, returns X-Collab-State)
333
+ curl -sD- -H "Authorization: Bearer $TOKEN" -H "X-Agent-Id: ai:claude" \
334
+ https://wiki.team.com/api/agent/fs/file/src/util.ts
335
+
336
+ # Write/overwrite (atomic). If-Match: <sha256> is required to overwrite;
337
+ # omit it to create. ?mkdirs=true creates parent dirs. ?force=true overrides (audited).
338
+ curl -s -X PUT -H "Authorization: Bearer $TOKEN" -H "X-Agent-Id: ai:claude" \
339
+ -H "If-Match: <sha256-from-read>" --data-binary @util.ts \
340
+ https://wiki.team.com/api/agent/fs/file/src/util.ts
341
+
342
+ # List a directory (scope-filtered)
343
+ curl -s -H "Authorization: Bearer $TOKEN" -H "X-Agent-Id: ai:claude" \
344
+ "https://wiki.team.com/api/agent/fs/ls/src?recursive=true&limit=500"
345
+
346
+ # Search (server-side; kills round-trips)
347
+ curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "X-Agent-Id: ai:claude" \
348
+ -H "Content-Type: application/json" \
349
+ -d '{"kind":"grep","query":"TODO","glob":"**/*.ts"}' \
350
+ https://wiki.team.com/api/agent/fs/search
351
+
352
+ # Move and delete (delete needs the `delete` scope + If-Match)
353
+ curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "X-Agent-Id: ai:claude" \
354
+ -H "Content-Type: application/json" -d '{"from":"a.md","to":"b.md"}' \
355
+ https://wiki.team.com/api/agent/fs/move
356
+ curl -s -X DELETE -H "Authorization: Bearer $TOKEN" -H "X-Agent-Id: ai:claude" \
357
+ -H "If-Match: <sha256>" https://wiki.team.com/api/agent/fs/file/old.md
358
+ ```
359
+
360
+ Mutating a Markdown file via raw write emits a `file.rawWritten` event and re-binds the collab sidecar; if the doc is `active` it is rejected `409 COLLAB_ACTIVE` (use Tier-2 instead). Use the **`npx wiki-viewer-mcp`** adapter to get all of this as standard MCP file tools — it handles `If-Match`, mode-awareness, and edit-via-read-then-write for you.
361
+
362
+ ### Tier 2 — op vocabulary (Markdown)
310
363
 
311
364
  Block-level edits (revision-checked, idempotent):
312
365
 
@@ -356,15 +409,23 @@ Owner-only (session cookie):
356
409
 
357
410
  Agent routes (bearer + `X-Agent-Id`, scope-checked):
358
411
 
359
- | Method | Path | Required scope |
360
- | ------ | ---------------------------------------- | --------------------- |
361
- | `GET` | `/api/agent/files/<path.md>` | `read` + path match |
362
- | `POST` | `/api/agent/files/<path.md>` | `mutate` + path match |
363
- | `GET` | `/api/agent/events/<path.md>?after=<id>` | `read` + path match |
364
- | `POST` | `/api/agent/events/<path.md>` | `read` + path match |
365
- | `GET` | `/api/agent/sidecar/<path.md>` | `read` + path match |
366
- | `GET` | `/api/agent/settings` | `read` |
367
- | `GET` | `/api/agent/activity` | `read` |
412
+ | Method | Path | Required scope | Tier |
413
+ | -------- | ---------------------------------------- | --------------------- | ---- |
414
+ | `GET` | `/api/agent/fs/file/<path>` | `read` + path match | 1 |
415
+ | `PUT` | `/api/agent/fs/file/<path>` | `mutate` + path match | 1 |
416
+ | `DELETE` | `/api/agent/fs/file/<path>` | `delete` + path match | 1 |
417
+ | `GET` | `/api/agent/fs/ls/<path>` | `read` + path match | 1 |
418
+ | `POST` | `/api/agent/fs/move` | `mutate` (src+dest) | 1 |
419
+ | `POST` | `/api/agent/fs/search` | `read` (per match) | 1 |
420
+ | `GET` | `/api/agent/files/<path.md>` | `read` + path match | 2 |
421
+ | `POST` | `/api/agent/files/<path.md>` | `mutate` + path match | 2 |
422
+ | `GET` | `/api/agent/events/<path.md>?after=<id>` | `read` + path match | 2 |
423
+ | `POST` | `/api/agent/events/<path.md>` | `read` + path match | 2 |
424
+ | `GET` | `/api/agent/sidecar/<path.md>` | `read` + path match | 2 |
425
+ | `GET` | `/api/agent/settings` | `read` | — |
426
+ | `GET` | `/api/agent/activity` | `read` | — |
427
+
428
+ Scopes: `paths` is a glob list (directories work natively, e.g. `notes/**`); `ops` is any of `read`, `mutate` (create/overwrite/move), `delete` (remove). Grant `["read","mutate"]` for edit-but-never-delete.
368
429
 
369
430
  ### Full curl trace
370
431
 
@@ -373,7 +434,7 @@ Agent routes (bearer + `X-Agent-Id`, scope-checked):
373
434
  curl -s -X POST https://wiki.team.com/api/agent/register \
374
435
  -H "Content-Type: application/json" \
375
436
  -d '{"id":"ai:claude","displayName":"Claude",
376
- "scope":{"paths":["**/*"],"ops":["read","mutate"]}}'
437
+ "scope":{"paths":["**/*"],"ops":["read","mutate","delete"]}}'
377
438
  # -> { "registrationId":"reg_abc","pollUrl":"/api/agent/register/reg_abc","status":"pending" }
378
439
 
379
440
  # 2. Owner approves in the AI Panel.
@@ -406,9 +467,11 @@ Response codes to handle:
406
467
 
407
468
  - `401 UNAUTHORIZED` — bad token or `X-Agent-Id`.
408
469
  - `403 FORBIDDEN` — out of scope or `by` mismatches identity.
409
- - `409 STALE_REVISION` — refetch and retry. Response includes a fresh snapshot.
410
- - `409 BLOCK_NOT_FOUND` — the ref no longer exists.
411
- - `409 IDEMPOTENCY_KEY_REUSED` — same key, different body.
470
+ - `409 STALE_REVISION` — refetch and retry. Response includes a fresh snapshot. (Tier 2)
471
+ - `409 BLOCK_NOT_FOUND` — the ref no longer exists. (Tier 2)
472
+ - `409 IDEMPOTENCY_KEY_REUSED` — same key, different body. (Tier 2)
473
+ - `409 COLLAB_ACTIVE` — raw write to a Markdown doc a human is editing; use Tier-2 block-ops (response includes the snapshot URL) or `?force=true`. (Tier 1)
474
+ - `412 PRECONDITION_FAILED` — `If-Match` sha mismatch (file changed); re-read and retry. (Tier 1)
412
475
  - `429 RATE_LIMITED` — honor `Retry-After`. Default 60 ops/minute per agent.
413
476
 
414
477
  ### Agent rate limit override
@@ -1 +1,12 @@
1
- You are connecting to a running wiki-viewer instance at $WIKI_URL (e.g. `http://localhost:3000`). Fetch `$WIKI_URL/api/agents/install`and follow the instructions there to register, wait for human approval, then read and edit markdown files via its HTTP API. Set`basis`and`basisDetail`on every content op so the human can see where your changes came from. Prefer`suggestion.add` over direct block ops unless told otherwise.
1
+ You are connecting to a running wiki-viewer instance at $WIKI_URL (e.g. `http://localhost:3000`). Fetch `$WIKI_URL/api/agents/install` and follow the instructions there to register, wait for human approval, then work with files via its HTTP API.
2
+
3
+ **Two tiers — pick by `X-Collab-State`:**
4
+
5
+ - **Tier 1 Raw FS** (`/api/agent/fs/*`) — all file types, fast read/write/ls/search. Use for code, binaries, and markdown that isn't being actively co-edited.
6
+ - **Tier 2 Collab** (`/api/agent/files/*.md`) — markdown only, reviewable proof-spans. Use when `X-Collab-State: active` (human has the doc open or it has pending suggestions).
7
+
8
+ **Mode rule:** Every file read returns `X-Collab-State`. If `active` → use Tier-2 block-ops so the human can review. Otherwise → use Tier-1 raw fs. A raw write to an `active` .md is rejected 409 `COLLAB_ACTIVE` with the Tier-2 URL.
9
+
10
+ Set `basis` and `basisDetail` on every Tier-2 content op so the human can see where your changes came from. Prefer `suggestion.add` over direct block ops unless told otherwise.
11
+
12
+ MCP-capable agents: `npx wiki-viewer-mcp` (set `WIKI_VIEWER_URL`, `WIKI_VIEWER_TOKEN`, `WIKI_VIEWER_AGENT_ID`) handles tier routing automatically.
@@ -8,6 +8,17 @@ license: MIT
8
8
 
9
9
  You are working with **wiki-viewer**, a local-first markdown viewer that exposes a Proof-SDK-compatible HTTP API for agents. Files on disk are the source of truth. Every AI-authored edit is wrapped in an inline `<proof-span>` mark so the human can see, accept, or revert your contribution.
10
10
 
11
+ ## Quick orientation: two tiers
12
+
13
+ | Tier | Routes | File types | When to use |
14
+ | ------------------- | ----------------------- | ----------------------------------- | --------------------------------------------------------------------------------- |
15
+ | **Tier 1 — Raw FS** | `/api/agent/fs/*` | All types (markdown, code, binary…) | Fast filework. Read, write, list, move, delete, search. Audited but no review UI. |
16
+ | **Tier 2 — Collab** | `/api/agent/files/*.md` | Markdown only | Reviewable prose. Edits become proof-spans the human can accept/revert. |
17
+
18
+ Both tiers use the same auth (TOFU token). Pick the tier based on `X-Collab-State` (see [Which tier do I use?](#which-tier-do-i-use)).
19
+
20
+ ---
21
+
11
22
  ## Discovery
12
23
 
13
24
  The server publishes everything you need at one URL:
@@ -214,6 +225,180 @@ Acks are advisory; events are never deleted.
214
225
  | 422 | INVALID_MARKDOWN | op's markdown failed to parse |
215
226
  | 429 | RATE_LIMITED | bucket exhausted, honor `Retry-After` header |
216
227
 
228
+ ---
229
+
230
+ ## Working with files (raw filesystem — Tier 1)
231
+
232
+ All Tier-1 routes require `Authorization: Bearer <token>` + `X-Agent-Id: ai:<name>` (same as Tier 2). The agent's `scope.paths` glob applies to every surface (reads, ls results, search results, move, delete).
233
+
234
+ ### Scope ops
235
+
236
+ When registering, `scope.ops` can include:
237
+
238
+ - `read` — read files + list + search
239
+ - `mutate` — create / overwrite / move
240
+ - `delete` — remove files/dirs (separate from mutate so a human can grant edit-but-never-delete)
241
+
242
+ Example registration with full access:
243
+
244
+ ```json
245
+ {
246
+ "id": "ai:claude",
247
+ "scope": { "paths": ["**/*"], "ops": ["read", "mutate", "delete"] }
248
+ }
249
+ ```
250
+
251
+ ### Read a file
252
+
253
+ ```
254
+ GET /api/agent/fs/file/<path>
255
+ ```
256
+
257
+ Returns raw bytes. Metadata in response headers:
258
+
259
+ ```
260
+ ETag: "<sha256>"
261
+ X-File-Size: <bytes>
262
+ X-File-Mtime: <ISO-8601>
263
+ Content-Type: <mime>
264
+ X-Collab-State: active | tracked | untracked | not-markdown
265
+ X-Collab-Revision: <n>
266
+ X-Collab-Snapshot: /api/agent/files/<path>.md # when applicable
267
+ ```
268
+
269
+ Supports `Range` header for large/binary files.
270
+
271
+ ### Write a file
272
+
273
+ ```
274
+ PUT /api/agent/fs/file/<path>
275
+ If-Match: "<sha256>" # required for overwrites; omit for creates
276
+ Content-Type: <mime>
277
+ <raw bytes body>
278
+ ```
279
+
280
+ - **Create** (file doesn't exist): omit `If-Match`. Creating a file that already exists without `If-Match` → 412 (no blind clobber).
281
+ - **Overwrite** (file exists): send `If-Match` with the sha256 you read. Mismatch → 412.
282
+ - `?mkdirs=true` — create parent directories.
283
+ - `?force=true` — bypass `If-Match` check (audited; use sparingly).
284
+
285
+ For `.md` files, also send:
286
+
287
+ ```
288
+ If-Collab-Match: <X-Collab-Revision> # prevents writing into a live collab session
289
+ ```
290
+
291
+ (See [Which tier do I use?](#which-tier-do-i-use).)
292
+
293
+ Response:
294
+
295
+ ```json
296
+ {
297
+ "path": "...",
298
+ "sha256": "...",
299
+ "size": 1234,
300
+ "mtime": "...",
301
+ "created": false
302
+ }
303
+ ```
304
+
305
+ ### Delete a file
306
+
307
+ ```
308
+ DELETE /api/agent/fs/file/<path>
309
+ If-Match: "<sha256>" # required — you must have read the file first
310
+ ```
311
+
312
+ Requires `delete` in `scope.ops`. Deletes the `.proof/` sidecar too for `.md` files. For directories: `?recursive=true`.
313
+
314
+ ### List a directory
315
+
316
+ ```
317
+ GET /api/agent/fs/ls/<path>?recursive=true&limit=500&depth=3
318
+ ```
319
+
320
+ Returns `{ entries: [{name, type, path, size, mtime}] }`. Unauthorized paths silently omitted. Excludes `.proof/`.
321
+
322
+ ### Move / rename
323
+
324
+ ```
325
+ POST /api/agent/fs/move
326
+ Content-Type: application/json
327
+
328
+ { "from": "notes/old.md", "to": "notes/new.md", "ifMatch": "<sha256>" }
329
+ ```
330
+
331
+ Moves the `.proof/` sidecar for `.md` files automatically.
332
+
333
+ ### Search (grep / glob)
334
+
335
+ ```
336
+ POST /api/agent/fs/search
337
+ Content-Type: application/json
338
+
339
+ { "kind": "grep", "query": "TODO", "path": "src", "glob": "*.ts", "limit": 100 }
340
+ ```
341
+
342
+ ```
343
+ POST /api/agent/fs/search
344
+ Content-Type: application/json
345
+
346
+ { "kind": "glob", "query": "**/*.test.ts" }
347
+ ```
348
+
349
+ Server-side: one call replaces dozens of `ls`+`read` round-trips. Results are scope-filtered. Glob dialect: `**`, `*`, `?` only (no braces/negation in v1).
350
+
351
+ ### Error codes (Tier 1)
352
+
353
+ | Status | Code | Meaning |
354
+ | ------ | ------------------- | --------------------------------------------------------------------------- |
355
+ | 400 | BAD_REQUEST | Invalid path or body |
356
+ | 401 | UNAUTHORIZED | Bad/missing token or X-Agent-Id |
357
+ | 403 | FORBIDDEN | Scope mismatch or missing `delete` op |
358
+ | 404 | NOT_FOUND | Path doesn't exist |
359
+ | 409 | COLLAB_ACTIVE | Raw PUT rejected — doc is active-collab; use Tier-2 or send If-Collab-Match |
360
+ | 412 | PRECONDITION_FAILED | If-Match sha mismatch (concurrent modification) |
361
+ | 413 | PAYLOAD_TOO_LARGE | File exceeds 50 MB limit |
362
+ | 429 | RATE_LIMITED | Honor `Retry-After` |
363
+
364
+ ---
365
+
366
+ ## Which tier do I use?
367
+
368
+ Every `GET /api/agent/fs/file/<path>` (and every Tier-2 snapshot read) returns `X-Collab-State`.
369
+
370
+ | `X-Collab-State` | Meaning | Use |
371
+ | ---------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
372
+ | `active` | Human has this `.md` open in the editor, OR it has pending suggestions / unresolved comments. | **Tier 2 block-ops only.** A raw `PUT` returns `409 COLLAB_ACTIVE`. |
373
+ | `tracked` | `.md` has a sidecar (prior collab history), no active session. | Prefer Tier-2 for prose/semantic edits. Raw ok for mechanical/whole-file ops (reformat, regenerate). |
374
+ | `untracked` | `.md`, no sidecar yet. | Raw is fine. Tier-2 creates a sidecar (starts provenance tracking). |
375
+ | `not-markdown` | Any non-`.md` file. | **Tier-1 raw only.** Tier 2 does not apply. |
376
+
377
+ **Rule (one sentence):** Read the file, check `X-Collab-State`, use Tier-2 if `active`, else use Tier-1. For non-markdown, always Tier-1.
378
+
379
+ **Editing a `.md` safely:**
380
+
381
+ ```
382
+ 1. GET /api/agent/fs/file/<path>.md
383
+ → note ETag (sha256) and X-Collab-Revision + X-Collab-State
384
+
385
+ 2a. If X-Collab-State == "active":
386
+ → POST /api/agent/files/<path>.md (block-ops, Tier-2)
387
+ Use the X-Collab-Snapshot URL. See "Mutating" section below.
388
+
389
+ 2b. Otherwise (tracked / untracked):
390
+ → PUT /api/agent/fs/file/<path>.md (raw Tier-1)
391
+ If-Match: "<ETag from step 1>"
392
+ If-Collab-Match: <X-Collab-Revision from step 1>
393
+
394
+ 3. If you get 409 COLLAB_ACTIVE: the doc became active after your read.
395
+ Switch to Tier-2 (block-ops) using the URL in the response body.
396
+ ```
397
+
398
+ **MCP-capable agents:** run `npx wiki-viewer-mcp` — it reads `X-Collab-State` automatically and routes to the correct tier. Set env vars `WIKI_VIEWER_URL`, `WIKI_VIEWER_TOKEN`, `WIKI_VIEWER_AGENT_ID`.
399
+
400
+ ---
401
+
217
402
  ## Working style
218
403
 
219
404
  - Read before write. Always GET a fresh snapshot to capture current `revision` and block `ref`s.
@@ -226,11 +411,19 @@ Acks are advisory; events are never deleted.
226
411
  ## Sample first interaction
227
412
 
228
413
  ```
229
- 1. GET /api/agents/install # discovery
230
- 2. POST /api/agent/register # register
414
+ 1. GET /api/agents/install # discovery
415
+ 2. POST /api/agent/register # register (include "delete" in ops if needed)
231
416
  3. tell human: "approve me in the AI Panel"
232
- 4. GET /api/agent/register/<regId> # poll until approved
233
- 5. GET /api/agent/files/<path>.md # read
234
- 6. POST /api/agent/files/<path>.md # suggest or mutate
235
- 7. GET /api/agent/events/<path>.md?after=<id> # listen for replies
417
+ 4. GET /api/agent/register/<regId> # poll until approved
418
+
419
+ # Working mode (Tier-1, e.g. code files or untracked .md)
420
+ 5. GET /api/agent/fs/ls/src?recursive=true # list
421
+ 6. GET /api/agent/fs/file/src/main.ts # read -> capture ETag
422
+ 7. PUT /api/agent/fs/file/src/main.ts (If-Match: <sha>) # write
423
+
424
+ # Collaborating mode (Tier-2, active .md)
425
+ 5. GET /api/agent/fs/file/notes/plan.md # read -> X-Collab-State: active
426
+ 6. GET /api/agent/files/notes/plan.md # read snapshot (Tier-2)
427
+ 7. POST /api/agent/files/notes/plan.md # suggest or mutate (Tier-2)
428
+ 8. GET /api/agent/events/notes/plan.md?after=<id> # listen for replies
236
429
  ```
@@ -62,9 +62,10 @@ All routes reuse `checkAuth` + `enforceScope` + `withFileMutex` + `safeRootPath`
62
62
  ### 2.2 Write (`PUT .../file/<path>`)
63
63
 
64
64
  - Atomic: write temp in **same dir** → `fsync` → `rename`. (`fsync` dir optional but documented.)
65
- - Preserve mode of existing file. Do **not** create parent dirs unless body/flag explicitly opts in.
66
- - `If-Match: <sha256>` 412 on mismatch. **Required by default for all writes** (see R4); explicit `?force=true` bypasses and is audited.
67
- - Response: `{path, sha256, size, mtime}`.
65
+ - Preserve mode of existing file. Do **not** create parent dirs unless `?mkdirs=true`.
66
+ - **Create = implicit.** `PUT` to a non-existent path creates the file (write-with-no-prior). Omit `If-Match` for a create; send `If-Match: <sha256>` only when overwriting. A create where the file already exists (no `If-Match`) 412, so creates can't silently clobber.
67
+ - `If-Match: <sha256>` → 412 on mismatch. **Required by default for overwrites** (see R4); explicit `?force=true` bypasses and is audited.
68
+ - Response: `{path, sha256, size, mtime, created: bool}`.
68
69
 
69
70
  ### 2.3 Listing (`GET .../ls`)
70
71
 
@@ -82,6 +83,12 @@ All routes reuse `checkAuth` + `enforceScope` + `withFileMutex` + `safeRootPath`
82
83
  - Checks: source `read`+`mutate`, dest `mutate`.
83
84
  - For `.md`: moves the `.proof/<path>.json` sidecar too. Lock ordering: single operation lock, or lock source+dest in **sorted key order** to avoid deadlock.
84
85
 
86
+ ### 2.6 Delete (`DELETE .../file/<path>`)
87
+
88
+ - Requires the `delete` scope op (see §3.5) and `If-Match: <sha256>` — the agent must have read the current file first, so it cannot blind-delete. This `If-Match` requirement **is** the confirmation for v1.
89
+ - `.md`: also deletes the sidecar (R3).
90
+ - Directory delete is opt-in and explicit: `?recursive=true`; without it, deleting a non-empty dir is refused. (No human approval queue in v1 — deferred.)
91
+
85
92
  ---
86
93
 
87
94
  ## 3. Tier 2 — Collab (unchanged)
@@ -90,14 +97,61 @@ Markdown block-ops (`block.replace/insertAfter/insertBefore/delete/append/prepen
90
97
 
91
98
  ---
92
99
 
100
+ ## 3.5 Working mode vs Collaborating mode (THE central distinction)
101
+
102
+ The whole design hinges on the agent knowing **when a file is being actively co-edited by a human** (use the reviewable Tier-2 path) versus **when it's just a file to work on** (use fast raw Tier-1). Today nothing tells the agent this; a wrong guess clobbers a human's pending suggestions. We make the mode **discoverable, documented, and enforced** — three layers so the agent cannot miss it.
103
+
104
+ ### The signal: `X-Collab-State` header (on every read, both tiers)
105
+
106
+ Every `GET fs/file/<path>` and every Tier-2 snapshot read returns:
107
+
108
+ ```
109
+ X-Collab-State: active | tracked | untracked | not-markdown
110
+ X-Collab-Snapshot: /api/agent/files/<path>.md # present when state != not-markdown
111
+ ```
112
+
113
+ | State | Meaning | Agent should… |
114
+ | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
115
+ | `active` | `.md` that is **live**: either has review artifacts (pending suggestions / unresolved comments / unreverted proof-spans) **OR has a current human edit lease** (someone has the doc open in the editor). A human is collaborating right now. | **Use Tier-2 block-ops.** Your edits become reviewable suggestions. A raw `PUT` is rejected unless `If-Collab-Match` matches (see R6). |
116
+ | `tracked` | `.md` with a sidecar, no artifacts, no lease. | **Prefer Tier-2 for any semantic/prose edit** so provenance accrues. Raw only for mechanical/whole-file ops (e.g. reformat, regenerate). Not a free pass. |
117
+ | `untracked` | `.md`, no sidecar, no lease — nobody has collaborated. | Raw ok. A reviewable (Tier-2) edit creates a sidecar so future edits are tracked. |
118
+ | `not-markdown` | Any non-`.md` file. | **Tier-1 raw only** (Tier-2 doesn't apply). |
119
+
120
+ **Definition of `active` (two sources, OR'd):**
121
+
122
+ 1. **Artifacts:** `pendingSuggestions > 0` OR `unresolvedComments > 0` OR `proofSpanCount > 0` (from sidecar — cheap, already in memory on read).
123
+ 2. **Human edit lease:** a short-TTL presence marker (default 90s, heartbeat ~30s) set when a human opens the doc in the editor and refreshed while it stays open. **This closes the false-negative GPT-5.5 caught:** a human who opens a doc but hasn't typed a suggestion yet still reads `active`, so the agent won't blind-write into a live session. Lease lives in-memory (or the existing SQLite), keyed by `(path)`, set by a lightweight `POST /api/wiki/presence` ping the editor already can issue alongside its chokidar SSE connection. No lease + no artifacts → not active.
124
+
125
+ ### Layer 2 — documented (manifest + skill)
126
+
127
+ The `/api/agents/install` manifest and the skill state the rule in one sentence:
128
+
129
+ > _"Before editing a `.md`, read it and check `X-Collab-State`. If `active`, use block-ops (Tier 2) so a human can review. Otherwise use raw fs (Tier 1). For non-markdown, always use raw fs."_
130
+
131
+ ### Layer 3 — enforced (R4 + R6 backstop)
132
+
133
+ Even a confused or racing agent cannot silently clobber a live session: a raw `PUT` to an `active` `.md` is **rejected with 409 `COLLAB_ACTIVE`** unless it carries a matching `If-Collab-Match` (R6) — and the state is re-checked atomically inside the write mutex, so a session that goes active mid-flight still wins. Any genuinely orphaned suggestion/comment is marked `stale` by reconciliation (R2), never dropped. The 409 returns the Tier-2 snapshot URL, re-teaching the mode.
134
+
135
+ ### What the human sees
136
+
137
+ - Agent works in Tier-2 on an `active` doc → normal reviewable suggestions (existing UX).
138
+ - Agent raw-writes an `active` doc anyway → `file.rawWritten by ai:<id>` in the AI Panel feed + any unbindable anchors flagged `stale` (not vanished).
139
+ - Agent works on `untracked`/non-md → silent, fast, audited. No collab noise.
140
+
141
+ ---
142
+
93
143
  ## 4. Integration rules (load-bearing)
94
144
 
95
145
  - **R1 — Shared lock.** A raw write/move/delete on a `.md` acquires the **same** `withFileMutex` key the ops-applier uses. No interleaving with block-ops mid-proof-span.
96
146
  - **R2 — No fake provenance.** Raw writes never author proof-spans. After a raw write to a tracked `.md`, emit `file.rawWritten` (writer known) and **reconcile the sidecar synchronously, inside the same mutex** (rebuild `refMap`, set fingerprint to `newSha`, mark affected proof refs stale). Raw edits are unmarked by definition; human sees _who_ via the event, not as an accept/revert suggestion.
97
147
  - **GOTCHA (do not regress):** do NOT just "bump fingerprint to newSha and let existing reconciliation fire later." The existing reconciliation triggers on `sidecar.fingerprint != file sha256`; if the raw write sets fingerprint current, the mismatch is gone and rebuild never runs. Because the writer is known, reconcile **eagerly within the write**, not lazily on next read.
98
- - **R3 — Sidecar lifecycle.** Raw `mv`/`rm` of a `.md` moves/deletes its sidecar (reuse human `wiki/move` logic).
148
+ - **R3 — Sidecar lifecycle.** Raw `mv`/`rm` of a `.md` moves/deletes its sidecar. **NOTE:** the human `wiki/move` route currently does a bare `rename` and does NOT move the sidecar — a latent bug that orphans `.proof/` JSON today. Build a shared `moveSidecar`/`deleteSidecar` helper in `sidecar.ts` and wire **both** the raw-fs path and `wiki/move` to it (fixes the existing bug for free).
99
149
  - **R4 — Write guard (If-Match by default).** **All** mutating raw ops (`PUT`/`DELETE`/`move`) REQUIRE `If-Match: <sha256>` by default; 412 on mismatch. An explicit `?force=true` bypasses it and is recorded in the audit row. Rationale: agents edit code/config just as much as `.md`; optional concurrency = silent lost updates, and a format-based safety boundary is arbitrary. Cheap because the agent already has the sha from `GET`.
100
- - **R5 — Scope unification.** Registration `scope.paths` glob + `scope.ops:[read,mutate]` already exist; raw-fs honors the same. No new scope concepts in v1.
150
+ - **R5 — Scope unification + `delete` op.** Registration `scope.paths` glob already covers **directories natively** (e.g. `notes/**` grants the whole subtree — no file lists). Raw-fs honors the same glob, on every surface (read/ls/search/move/delete results all re-checked). **One addition:** split `delete` out of `mutate`, so `scope.ops` becomes `[read, mutate, delete]`. This lets a human grant "edit but never delete." `mutate` = create/overwrite/move; `delete` = remove. Back-compat: existing `[read, mutate]` agents simply can't delete until re-scoped. Glob dialect (v1): `**`, `*`, `?` only — no braces/negation; advertise this in the manifest.
151
+ - **R6 — Collab-state precondition on raw `.md` writes (closes the TOCTOU race).** `If-Match` protects _bytes_, not _collaboration intent_: a human could create a sidecar/lease after the agent's read but before its raw `PUT`, leaving bytes unchanged so `If-Match` still passes. To prevent silently writing into a session that went `active` mid-flight:
152
+ - Every `.md` read also returns `X-Collab-Revision: <n>` (bumped on any sidecar/lease state change).
153
+ - A raw `PUT` to a `.md` must, **inside the same mutex, re-read collab state immediately before writing**: if the doc is now `active` and the request did not supply a matching `If-Collab-Match: <n>`, **reject with 409 `COLLAB_ACTIVE`** + the Tier-2 snapshot URL. The agent then switches to block-ops. `?force=true` still bypasses (audited) for deliberate overrides.
154
+ - This makes the mode check atomic with the write, not advisory.
101
155
 
102
156
  ### Event taxonomy (don't overload)
103
157
 
@@ -120,7 +174,8 @@ A full-file `PUT` to a `.md` can strip `<proof-span>` marks and shift block boun
120
174
  Extend `/api/agents/install` manifest:
121
175
 
122
176
  - Advertise the new `fs/*` routes.
123
- - Add a `capabilities` block: `{ maxFileBytes, supportsRange, ifMatchRequired:true, forceBypass:true, search:["grep","glob"] }`.
177
+ - Add a `capabilities` block: `{ maxFileBytes, supportsRange, ifMatchRequired:true, forceBypass:true, search:["grep","glob"], globDialect:"**,*,?", scopeOps:["read","mutate","delete"], collabStates:["active","tracked","untracked","not-markdown"], collabPrecondition:"If-Collab-Match" }`.
178
+ - State the **working-vs-collaborating rule** (§3.5) in prose so the agent self-configures its tier choice.
124
179
  - Advertise the optional MCP adapter package + version.
125
180
  One manifest; agent self-configures. HTTP routes are the canonical contract.
126
181
 
@@ -135,6 +190,8 @@ Extend `/api/agents/install` manifest:
135
190
  - `edit_file` (str-replace) → **client-side**: read → transform → `PUT If-Match`. (Server stays dumb; edit footguns live in the adapter.)
136
191
  - `list_directory` → `GET fs/ls`
137
192
  - `search` → `POST fs/search`
193
+ - `delete_file` → `DELETE fs/file` (requires `delete` scope + `If-Match`)
194
+ - The shim reads `X-Collab-State` and, when `active`, **warns or routes the edit through the Tier-2 block-op tools** instead of a blind raw write — so even off-the-shelf MCP clients respect collaborating mode.
138
195
  - Do **not** make the core app MCP-native first. The app already has HTTP auth/discovery; the shim adapts to Claude Code / Cursor / Codex without poisoning the core.
139
196
 
140
197
  ---
@@ -165,7 +222,8 @@ Extend `/api/agents/install` manifest:
165
222
  5. `fs/search` (grep/glob, limits).
166
223
  6. Extend `/api/agents/install` manifest + capabilities.
167
224
  7. `wiki-viewer-mcp` adapter (read/write/edit/list/search).
168
- 8. Tests: traversal, symlink escape, If-Match 412, sidecar move, scope filtering on ls/search, big-file Range, binary skip in grep.
225
+ 8. **Mode plumbing:** human edit-lease (`POST /api/wiki/presence` + TTL, editor heartbeat), `X-Collab-State` + `X-Collab-Revision` headers on both read paths, R6 atomic re-check + 409 `COLLAB_ACTIVE` on raw `.md` writes. Plus `delete` scope op + create/`?mkdirs`/`?recursive` semantics.
226
+ 9. Tests: traversal, symlink escape, If-Match 412, create-collision 412, sidecar move (incl. `wiki/move` bug fix), scope filtering on ls/search, big-file Range, binary skip in grep, **`X-Collab-State` matrix incl. lease-only `active`**, **R6 TOCTOU: doc goes active between read and raw PUT → 409**, stale-anchor after raw `.md` overwrite, `delete` op gating, lease expiry flips active→tracked.
169
227
 
170
228
  ```
171
229
 
@@ -0,0 +1,124 @@
1
+ # File vs Collab Authority Model
2
+
3
+ **TL;DR:** File on disk is truth. Tier-1 raw edits are fast + audited but unmarked. Tier-2 block-ops are slower but reviewable. The `X-Collab-State` header tells an agent which tier to use; the server enforces it atomically.
4
+
5
+ ---
6
+
7
+ ## Source of truth
8
+
9
+ The `.md` file on disk is the canonical document. The `.proof/<path>.json` sidecar holds provenance metadata (comments, suggestions, proof-span refs, fingerprint) but is never the source of truth for content. If the sidecar is lost the document is intact; if the document is lost the sidecar is orphaned.
10
+
11
+ ---
12
+
13
+ ## Two tiers
14
+
15
+ ### Tier 1 — Raw FS
16
+
17
+ - Routes: `GET/PUT/DELETE /api/agent/fs/file/<path>`, `GET /api/agent/fs/ls/...`, `POST /api/agent/fs/move`, `POST /api/agent/fs/search`.
18
+ - All file types. Raw bytes in, raw bytes out.
19
+ - Writes are **atomic** (temp-file + rename in same directory).
20
+ - **Audit:** every mutation records a row in the `agent_fs_audit` SQLite table (`path`, `op`, `agentId`, `oldSha`, `newSha`, `forced`, `at`).
21
+ - **Event:** `file.rawWritten` emitted with `{ by: "ai:<id>", path, oldSha, newSha }`. Distinct from `file.externallyEdited` (chokidar, writer unknown).
22
+ - No `<proof-span>` marks. No accept/revert UI. Audit log is the paper trail.
23
+
24
+ ### Tier 2 — Collab
25
+
26
+ - Routes: `GET/POST /api/agent/files/<path>.md`, `GET/POST /api/agent/events/<path>.md`.
27
+ - Markdown only.
28
+ - Edits are wrapped in `<proof-span>` marks inline in the `.md` file.
29
+ - Provenance (suggestions, comments, block refs) stored in `.proof/<path>.json` sidecar.
30
+ - Human can accept or revert individual spans in the editor UI.
31
+ - Mandatory `baseRevision` optimistic concurrency + `Idempotency-Key` per request.
32
+
33
+ ---
34
+
35
+ ## The `X-Collab-State` header
36
+
37
+ Every `GET /api/agent/fs/file/<path>` (Tier-1 read) and every Tier-2 snapshot read returns:
38
+
39
+ ```
40
+ X-Collab-State: active | tracked | untracked | not-markdown
41
+ X-Collab-Revision: <n>
42
+ X-Collab-Snapshot: /api/agent/files/<path>.md # present when not not-markdown
43
+ ```
44
+
45
+ ### State machine
46
+
47
+ ```
48
+ [file created]
49
+
50
+
51
+ untracked ──── first Tier-2 op ────► tracked
52
+ │ │
53
+ │ (Tier-1 writes stay untracked) │ human opens editor
54
+ │ ▼
55
+ │ active
56
+ │ │
57
+ │ editor closes +
58
+ │ no artifacts
59
+ │ │
60
+ │ ▼
61
+ └────────────────────────────────── tracked
62
+ ```
63
+
64
+ **`active`** is set by two independent sources (OR'd):
65
+
66
+ 1. **Artifacts** — sidecar has `pendingSuggestions > 0` OR `unresolvedComments > 0` OR `proofSpanCount > 0`. Cheap: always in memory when sidecar is loaded.
67
+ 2. **Human edit lease** — a short-TTL presence marker (default 90 s, heartbeat ~30 s) set via `POST /api/wiki/presence { path, action: "open" | "heartbeat" | "close" }`. Closes the false-negative: a human who opens a doc but hasn't typed a suggestion yet still reads `active`.
68
+
69
+ `X-Collab-Revision` bumps on any sidecar write OR lease open/close. Used by R6.
70
+
71
+ ---
72
+
73
+ ## R6 — atomic TOCTOU race fix
74
+
75
+ `If-Match` (sha256) protects _bytes_. But a human could open the doc between the agent's read and its raw `PUT`, making it `active` while bytes are unchanged — so `If-Match` passes but the write clobbers a live session.
76
+
77
+ **Fix:** a raw `PUT` to any `.md` re-checks `collabState` **inside the same `withFileMutex` call, immediately before writing**. If the state is now `active` and the request did not supply a matching `If-Collab-Match: <revision>`, the write is **rejected 409 `COLLAB_ACTIVE`** with the Tier-2 URL. This check is atomic with the write — not advisory.
78
+
79
+ `?force=true` bypasses both `If-Match` and `If-Collab-Match` and is recorded in the audit row as `forced: true`.
80
+
81
+ ---
82
+
83
+ ## R2 — eager sidecar reconciliation
84
+
85
+ After a raw `PUT` to a tracked/active `.md`, the sidecar must be reconciled **synchronously, inside the same mutex**, before the lock is released:
86
+
87
+ 1. Re-scan the new file bytes for surviving `<proof-span>` marks.
88
+ 2. Re-bind each proof ref to its new block offset; mark unresolvable refs `stale: true`.
89
+ 3. Set `sidecar.fingerprint = newSha` (so the lazy mismatch-trigger in `readSnapshot` does NOT re-fire — the reconcile already ran).
90
+ 4. Emit `file.rawWritten` event.
91
+
92
+ **Do not** just bump the fingerprint and let reconciliation fire lazily on the next read. The lazy trigger fires only when `sidecar.fingerprint != file sha256`; once the raw write sets fingerprint current, the mismatch is gone and rebuild never runs. Eager reconciliation is the correct invariant.
93
+
94
+ ---
95
+
96
+ ## Known v1 limitations
97
+
98
+ ### (a) Editor does not call `/api/wiki/presence` yet
99
+
100
+ The front-end editor does **not** currently issue `POST /api/wiki/presence` on open/heartbeat/close. Consequence: lease-based `active` never fires. Only artifact-based `active` works (pending suggestions, unresolved comments, proof-spans in sidecar).
101
+
102
+ **Impact:** a human who opens a doc but has no pending review artifacts will see `X-Collab-State: tracked` (or `untracked`), not `active`. An agent raw-writing that doc won't be blocked. This is a safety gap — not a correctness bug (no data loss), but the intended "lock out while human is live-editing" experience is incomplete until the editor heartbeat is wired.
103
+
104
+ **Fix:** call `POST /api/wiki/presence { path, action: "open" }` when the editor mounts the doc and `{ action: "close" }` on unmount. Heartbeat every ~30 s. Tracked as a follow-up task.
105
+
106
+ ### (b) Lease store is in-memory (single-process only)
107
+
108
+ The presence lease map lives in the Node.js process memory. In a multi-process deployment (PM2 cluster mode, multiple Next.js instances behind a load balancer) each process has its own lease state and processes do not share it.
109
+
110
+ **Impact:** a human's open lease set by process A is invisible to process B. A raw write handled by process B may not see the `active` state and proceed when it should block.
111
+
112
+ **Fix:** move the lease store to the shared SQLite (`~/.wiki-viewer/auth.db`) with a TTL column and a periodic cleanup job. The table is already shared across the process boundary. Tracked as a follow-up task.
113
+
114
+ ---
115
+
116
+ ## Sidecar lifecycle rules
117
+
118
+ | Raw-fs op | On non-`.md` | On `.md` |
119
+ | ------------------------ | ------------ | ------------------------------------------------------------------ |
120
+ | `PUT` (create/overwrite) | plain write | acquire mutex → write → reconcile sidecar → emit `file.rawWritten` |
121
+ | `DELETE` | plain delete | delete file + delete `.proof/<path>.json` sidecar |
122
+ | `POST /fs/move` | plain rename | rename file + rename `.proof/<old>.json` → `.proof/<new>.json` |
123
+
124
+ The human `wiki/move` route was previously a bare `rename` that orphaned sidecars. It now uses the same shared `moveSidecar` helper (fixed in Phase 1).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-viewer",
3
- "version": "1.4.2",
3
+ "version": "1.5.0",
4
4
  "description": "Local file viewer and wiki — view markdown, HTML, PDFs, notebooks, office docs, and more from any directory",
5
5
  "license": "MIT",
6
6
  "type": "module",