wiki-viewer 1.4.3 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) 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 -3
  5. package/.next/standalone/.next/routes-manifest.json +34 -0
  6. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  14. package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  18. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  21. package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js +8 -7
  24. package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route/app-paths-manifest.json +3 -0
  26. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route/build-manifest.json +9 -0
  27. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route/server-reference-manifest.json +4 -0
  28. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js +17 -0
  29. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.map +5 -0
  30. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -0
  31. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route_client-reference-manifest.js +3 -0
  32. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route/app-paths-manifest.json +3 -0
  33. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route/build-manifest.json +9 -0
  34. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route/server-reference-manifest.json +4 -0
  35. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js +15 -0
  36. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.map +5 -0
  37. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -0
  38. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route_client-reference-manifest.js +3 -0
  39. package/.next/standalone/.next/server/app/api/agent/fs/move/route/app-paths-manifest.json +3 -0
  40. package/.next/standalone/.next/server/app/api/agent/fs/move/route/build-manifest.json +9 -0
  41. package/.next/standalone/.next/server/app/api/agent/fs/move/route/server-reference-manifest.json +4 -0
  42. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js +15 -0
  43. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.map +5 -0
  44. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -0
  45. package/.next/standalone/.next/server/app/api/agent/fs/move/route_client-reference-manifest.js +3 -0
  46. package/.next/standalone/.next/server/app/api/agent/fs/search/route/app-paths-manifest.json +3 -0
  47. package/.next/standalone/.next/server/app/api/agent/fs/search/route/build-manifest.json +9 -0
  48. package/.next/standalone/.next/server/app/api/agent/fs/search/route/server-reference-manifest.json +4 -0
  49. package/.next/standalone/.next/server/app/api/agent/fs/search/route.js +15 -0
  50. package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.map +5 -0
  51. package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -0
  52. package/.next/standalone/.next/server/app/api/agent/fs/search/route_client-reference-manifest.js +3 -0
  53. package/.next/standalone/.next/server/app/api/agent/internal/span/route.js.nft.json +1 -1
  54. package/.next/standalone/.next/server/app/api/agent/settings/route.js +1 -1
  55. package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js +1 -1
  58. package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/api/assets/[...path]/route.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/api/system/browse/route.js.nft.json +1 -1
  61. package/.next/standalone/.next/server/app/api/system/clear-root/route.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
  63. package/.next/standalone/.next/server/app/api/system/root-status/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/api/system/set-root/route.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
  67. package/.next/standalone/.next/server/app/api/wiki/content/route.js +2 -2
  68. package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
  69. package/.next/standalone/.next/server/app/api/wiki/file/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/api/wiki/move/route.js +3 -3
  72. package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
  73. package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
  74. package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
  75. package/.next/standalone/.next/server/app/api/wiki/presence/route/app-paths-manifest.json +3 -0
  76. package/.next/standalone/.next/server/app/api/wiki/presence/route/build-manifest.json +9 -0
  77. package/.next/standalone/.next/server/app/api/wiki/presence/route/server-reference-manifest.json +4 -0
  78. package/.next/standalone/.next/server/app/api/wiki/presence/route.js +14 -0
  79. package/.next/standalone/.next/server/app/api/wiki/presence/route.js.map +5 -0
  80. package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -0
  81. package/.next/standalone/.next/server/app/api/wiki/presence/route_client-reference-manifest.js +3 -0
  82. package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
  83. package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
  85. package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/index.html +1 -1
  87. package/.next/standalone/.next/server/app/index.rsc +2 -2
  88. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  89. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  90. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  91. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  92. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  93. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  95. package/.next/standalone/.next/server/app-paths-manifest.json +5 -0
  96. package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0d2jbo5.js +3 -0
  97. package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0ytral2.js +3 -0
  98. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-ao6a_._.js +1 -1
  99. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0269d2e._.js +1 -1
  100. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05f6x0i._.js +3 -0
  101. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06-dtd0._.js +3 -0
  102. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06sek6_._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/[root-of-the-server]__09s9qkd._.js +1 -1
  104. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d75a5q._.js +1 -1
  105. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d_da6q._.js +3 -0
  106. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e7si9p._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0hhhvm7._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kk26wc._.js +3 -0
  109. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kur4ro._.js +15 -0
  110. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0p12-6~._.js +1 -1
  111. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qc2~6l._.js +15 -0
  112. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0s~i040._.js +3 -0
  113. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0w47wil._.js +1 -1
  114. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xq124z._.js +3 -0
  115. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0l..bxz._.js → [root-of-the-server]__0xz-_0v._.js} +2 -2
  116. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10w2q~o._.js +1 -1
  117. package/.next/standalone/.next/server/chunks/_079xuln._.js +3 -0
  118. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_file_[___path]_route_actions_0gb11t~.js +3 -0
  119. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_ls_[[___path]]_route_actions_0wfg4nl.js +3 -0
  120. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_move_route_actions_0z34mqq.js +3 -0
  121. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_search_route_actions_0ut_ug..js +3 -0
  122. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_wiki_presence_route_actions_0x9d7f4.js +3 -0
  123. package/.next/standalone/.next/server/chunks/ssr/{0~w0_katex_dist_katex_mjs_055boxx._.js → 0~w0_katex_dist_katex_mjs_00650~e._.js} +1 -1
  124. package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_diagram-OG6HWLK6_mjs_0t5sus6._.js +1 -1
  125. package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_sankeyDiagram-5OEKKPKP_mjs_11ifrnu._.js +1 -1
  126. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__134_q7l._.js → [root-of-the-server]__12ahxbl._.js} +2 -2
  127. package/.next/standalone/.next/server/chunks/ssr/_0pqaawz._.js +3 -3
  128. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0rc1vh5._.js → node_modules__pnpm_02gx8km._.js} +1 -1
  129. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0t4unpg._.js → node_modules__pnpm_02mew~s._.js} +2 -2
  130. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_12-ni1n._.js → node_modules__pnpm_03ij5.g._.js} +2 -2
  131. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_12~a4c_._.js → node_modules__pnpm_03v21p-._.js} +2 -2
  132. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0f~_mm3._.js → node_modules__pnpm_05qsply._.js} +2 -2
  133. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0alwr5e._.js → node_modules__pnpm_06pgebo._.js} +2 -2
  134. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_02zxe7o._.js → node_modules__pnpm_08ibh0w._.js} +2 -2
  135. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0hr027i._.js → node_modules__pnpm_099cv.b._.js} +1 -1
  136. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0znncy9._.js → node_modules__pnpm_0cwpt9p._.js} +2 -2
  137. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0-pisfi._.js → node_modules__pnpm_0f9fpy5._.js} +1 -1
  138. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0zhbnni._.js → node_modules__pnpm_0f_uzgy._.js} +1 -1
  139. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0-w-d-.._.js → node_modules__pnpm_0fixtms._.js} +1 -1
  140. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_03z0vkh._.js → node_modules__pnpm_0gofu~q._.js} +1 -1
  141. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_10i6lh6._.js → node_modules__pnpm_0iojvye._.js} +2 -2
  142. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0-hfev1._.js → node_modules__pnpm_0li2vzs._.js} +1 -1
  143. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_13kfy_z._.js → node_modules__pnpm_0m5-azh._.js} +1 -1
  144. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_071f6vl._.js → node_modules__pnpm_0n1kfcp._.js} +1 -1
  145. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_07uh2kc._.js → node_modules__pnpm_0rebktf._.js} +1 -1
  146. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0okw1r.._.js → node_modules__pnpm_0tkiej3._.js} +2 -2
  147. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0xuz.8f._.js → node_modules__pnpm_0v_nwsz._.js} +1 -1
  148. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0zb6573._.js → node_modules__pnpm_0wffzo0._.js} +1 -1
  149. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0d7jxsf._.js → node_modules__pnpm_0wouz19._.js} +1 -1
  150. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0egenev._.js → node_modules__pnpm_0xxwmv2._.js} +1 -1
  151. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0j9bq9s._.js → node_modules__pnpm_0zzzsrj._.js} +1 -1
  152. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0irsd.b._.js → node_modules__pnpm_0~.6dgb._.js} +1 -1
  153. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0erwv_m._.js → node_modules__pnpm_0~2~c30._.js} +1 -1
  154. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0y9k6h~._.js → node_modules__pnpm_10413dq._.js} +2 -2
  155. package/.next/standalone/.next/server/functions-config-manifest.json +5 -0
  156. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  157. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  158. package/.next/standalone/.next/server/pages/404.html +1 -1
  159. package/.next/standalone/.next/server/pages/500.html +1 -1
  160. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  161. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  162. package/.next/standalone/.next/static/chunks/{11s9zwr7edrs7.js → 17~r3.8awh3qg.js} +12 -12
  163. package/.next/standalone/README.md +79 -16
  164. package/.next/standalone/agents/bootstrap-prompt.md +12 -1
  165. package/.next/standalone/agents/wiki-viewer-skill/SKILL.md +199 -6
  166. package/.next/standalone/docs/file-vs-collab-authority.md +124 -0
  167. package/.next/standalone/package.json +1 -1
  168. package/.next/standalone/packages/wiki-viewer-mcp/README.md +194 -0
  169. package/.next/standalone/packages/wiki-viewer-mcp/dist/http-client.js +220 -0
  170. package/.next/standalone/packages/wiki-viewer-mcp/dist/index.js +472 -0
  171. package/.next/standalone/packages/wiki-viewer-mcp/dist/register.js +94 -0
  172. package/.next/standalone/packages/wiki-viewer-mcp/dist/state-cache.js +26 -0
  173. package/.next/standalone/packages/wiki-viewer-mcp/package-lock.json +1716 -0
  174. package/.next/standalone/packages/wiki-viewer-mcp/package.json +41 -0
  175. package/.next/standalone/packages/wiki-viewer-mcp/src/http-client.ts +344 -0
  176. package/.next/standalone/packages/wiki-viewer-mcp/src/index.ts +575 -0
  177. package/.next/standalone/packages/wiki-viewer-mcp/src/register.ts +144 -0
  178. package/.next/standalone/packages/wiki-viewer-mcp/src/state-cache.ts +45 -0
  179. package/.next/standalone/packages/wiki-viewer-mcp/tsconfig.json +19 -0
  180. package/.next/standalone/pnpm-lock.yaml +9 -9
  181. package/.next/standalone/src/app/api/agent/files/[...path]/route.ts +11 -1
  182. package/.next/standalone/src/app/api/agent/fs/file/[...path]/route.ts +344 -0
  183. package/.next/standalone/src/app/api/agent/fs/ls/[[...path]]/route.ts +147 -0
  184. package/.next/standalone/src/app/api/agent/fs/move/route.ts +125 -0
  185. package/.next/standalone/src/app/api/agent/fs/search/route.ts +236 -0
  186. package/.next/standalone/src/app/api/agent/register/route.ts +3 -3
  187. package/.next/standalone/src/app/api/agents/install/route.ts +44 -2
  188. package/.next/standalone/src/app/api/system/auth-settings/route.ts +1 -0
  189. package/.next/standalone/src/app/api/wiki/move/route.ts +10 -1
  190. package/.next/standalone/src/app/api/wiki/presence/route.ts +55 -0
  191. package/.next/standalone/src/components/ai-panel/ai-panel.tsx +98 -103
  192. package/.next/standalone/src/components/ai-panel/token-section.tsx +8 -7
  193. package/.next/standalone/src/components/auth-settings-sheet.tsx +81 -22
  194. package/.next/standalone/src/components/editor/editor.tsx +38 -0
  195. package/.next/standalone/src/lib/proof/audit.ts +79 -0
  196. package/.next/standalone/src/lib/proof/auth.ts +2 -2
  197. package/.next/standalone/src/lib/proof/collab-state.ts +79 -0
  198. package/.next/standalone/src/lib/proof/lease.ts +104 -0
  199. package/.next/standalone/src/lib/proof/ops-applier.ts +74 -25
  200. package/.next/standalone/src/lib/proof/raw-fs.ts +198 -0
  201. package/.next/standalone/src/lib/proof/registry.ts +1 -1
  202. package/.next/standalone/src/lib/proof/sidecar.ts +38 -1
  203. package/.next/standalone/src/lib/proof/types.ts +13 -1
  204. package/.next/standalone/src/tests/proof/agent-fs.test.ts +824 -0
  205. package/.next/standalone/src/tests/proof/agents-install.test.ts +53 -0
  206. package/.next/standalone/src/tests/proof/collab-state.test.ts +499 -0
  207. package/.next/standalone/src/tests/proof/reconcile-sidecar.test.ts +195 -0
  208. package/.next/standalone/src/tests/proof/sidecar-lifecycle.test.ts +177 -0
  209. package/.next/standalone/tsconfig.tsbuildinfo +1 -1
  210. package/README.md +79 -16
  211. package/package.json +1 -1
  212. package/.next/standalone/.next/server/chunks/[root-of-the-server]__09~~-nd._.js +0 -3
  213. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0w87kiz._.js +0 -3
  214. package/.next/standalone/.next/server/chunks/[root-of-the-server]__12ssbhv._.js +0 -3
  215. package/.next/standalone/.next/server/chunks/node_modules__pnpm_0g0fhfk._.js +0 -3
  216. /package/.next/standalone/.next/static/{kzOuSAQArtvD7uiAJ6ZLh → 3G_3qm2a9nOX7oi5k0mPV}/_buildManifest.js +0 -0
  217. /package/.next/standalone/.next/static/{kzOuSAQArtvD7uiAJ6ZLh → 3G_3qm2a9nOX7oi5k0mPV}/_clientMiddlewareManifest.js +0 -0
  218. /package/.next/standalone/.next/static/{kzOuSAQArtvD7uiAJ6ZLh → 3G_3qm2a9nOX7oi5k0mPV}/_ssgManifest.js +0 -0
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Tests for the extracted reconcileSidecar function.
3
+ * Verifies: refMap rebuild, revision bump, fingerprint update, event emission,
4
+ * stale-anchor marking on orphaned refs.
5
+ */
6
+ import { test, before, after } from "node:test";
7
+ import assert from "node:assert/strict";
8
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
9
+ import { tmpdir } from "node:os";
10
+ import { createHash } from "node:crypto";
11
+ import path from "node:path";
12
+
13
+ import { reconcileSidecar } from "../../lib/proof/ops-applier.js";
14
+ import { emptySidecar, writeSidecar, readSidecar } from "../../lib/proof/sidecar.js";
15
+
16
+ function sha256(content: string): string {
17
+ return "sha256:" + createHash("sha256").update(content, "utf8").digest("hex");
18
+ }
19
+
20
+ let tmpRoot: string;
21
+
22
+ before(async () => {
23
+ tmpRoot = await mkdtemp(path.join(tmpdir(), "wiki-reconcile-test-"));
24
+ });
25
+
26
+ after(async () => {
27
+ await rm(tmpRoot, { recursive: true, force: true });
28
+ });
29
+
30
+ test("reconcileSidecar: bumps revision, sets fingerprint, emits file.externallyEdited, writes sidecar", async () => {
31
+ const mdPath = "notes.md";
32
+ const absPath = path.join(tmpRoot, mdPath);
33
+ const content = "# Hello\n\nWorld paragraph.\n";
34
+ await writeFile(absPath, content, "utf-8");
35
+
36
+ const sidecar = emptySidecar(mdPath);
37
+ sidecar.fingerprint = sha256("old content that changed");
38
+ const oldRevision = sidecar.revision;
39
+
40
+ const fingerprint = sha256(content);
41
+ const { snapshot, blocks } = await reconcileSidecar({
42
+ rootDir: tmpRoot,
43
+ mdPath,
44
+ content,
45
+ sidecar,
46
+ by: "system",
47
+ eventType: "file.externallyEdited",
48
+ fingerprint,
49
+ });
50
+
51
+ // Revision bumped
52
+ assert.equal(sidecar.revision, oldRevision + 1);
53
+ // Fingerprint updated
54
+ assert.equal(sidecar.fingerprint, fingerprint);
55
+ // refMap has entries for the blocks
56
+ assert.ok(Object.keys(sidecar.refMap).length > 0, "refMap should be non-empty");
57
+ // Event emitted
58
+ assert.equal(sidecar.events.length, 1);
59
+ assert.equal(sidecar.events[0].type, "file.externallyEdited");
60
+ assert.equal(sidecar.events[0].by, "system");
61
+ // Sidecar written to disk
62
+ const onDisk = await readSidecar(tmpRoot, mdPath);
63
+ assert.ok(onDisk, "sidecar should be written to disk");
64
+ assert.equal(onDisk!.revision, oldRevision + 1);
65
+ // Snapshot returned
66
+ assert.equal(snapshot.path, mdPath);
67
+ assert.equal(snapshot.revision, oldRevision + 1);
68
+ assert.equal(snapshot.fingerprint, fingerprint);
69
+ // Blocks returned
70
+ assert.ok(blocks.length > 0, "blocks should be non-empty");
71
+ });
72
+
73
+ test("reconcileSidecar: emits file.rawWritten with oldSha + newSha when eventType is rawWritten", async () => {
74
+ const mdPath = "raw-notes.md";
75
+ const absPath = path.join(tmpRoot, mdPath);
76
+ const content = "# Raw write\n\nNew content.\n";
77
+ await writeFile(absPath, content, "utf-8");
78
+
79
+ const sidecar = emptySidecar(mdPath);
80
+ const oldSha = sha256("old content");
81
+ sidecar.fingerprint = oldSha;
82
+
83
+ const newSha = sha256(content);
84
+ await reconcileSidecar({
85
+ rootDir: tmpRoot,
86
+ mdPath,
87
+ content,
88
+ sidecar,
89
+ by: "ai:test-agent",
90
+ eventType: "file.rawWritten",
91
+ fingerprint: newSha,
92
+ });
93
+
94
+ assert.equal(sidecar.events.length, 1);
95
+ const ev = sidecar.events[0];
96
+ assert.equal(ev.type, "file.rawWritten");
97
+ assert.equal(ev.by, "ai:test-agent");
98
+ assert.equal(ev.oldSha, oldSha);
99
+ assert.equal(ev.newSha, newSha);
100
+ });
101
+
102
+ test("reconcileSidecar: marks pending suggestions stale when ref no longer in new refMap", async () => {
103
+ const mdPath = "stale-anchors.md";
104
+ const absPath = path.join(tmpRoot, mdPath);
105
+
106
+ // Original content with two paragraphs
107
+ const original = "# Doc\n\nParagraph one.\n\nParagraph two.\n";
108
+ await writeFile(absPath, original, "utf-8");
109
+
110
+ const sidecar = emptySidecar(mdPath);
111
+ // Add a pending suggestion referencing a fictional ref that won't exist after reparse
112
+ sidecar.suggestions.push({
113
+ id: "s0001",
114
+ ref: "b_orphan_ref",
115
+ kind: "replace",
116
+ status: "pending",
117
+ by: "ai:test",
118
+ markdown: "replacement",
119
+ createdAt: new Date().toISOString(),
120
+ });
121
+ // Add a comment referencing a valid ref — will be assigned after reconcile
122
+ // For simplicity, leave it pointing at another ghost ref too
123
+ sidecar.comments.push({
124
+ id: "c0001",
125
+ ref: "b_also_orphaned",
126
+ resolved: false,
127
+ createdAt: new Date().toISOString(),
128
+ turns: [{ by: "human", text: "comment", at: new Date().toISOString() }],
129
+ });
130
+
131
+ const newContent = "# Doc\n\nTotally new content only.\n";
132
+ await writeFile(absPath, newContent, "utf-8");
133
+ const fingerprint = sha256(newContent);
134
+
135
+ await reconcileSidecar({
136
+ rootDir: tmpRoot,
137
+ mdPath,
138
+ content: newContent,
139
+ sidecar,
140
+ by: "ai:agent",
141
+ eventType: "file.rawWritten",
142
+ fingerprint,
143
+ });
144
+
145
+ // Both orphaned anchors should be marked stale
146
+ const staleSuggestion = sidecar.suggestions.find((s) => s.id === "s0001");
147
+ assert.equal(staleSuggestion?.stale, true, "suggestion with orphaned ref should be stale");
148
+
149
+ const staleComment = sidecar.comments.find((c) => c.id === "c0001");
150
+ assert.equal(staleComment?.stale, true, "comment with orphaned ref should be stale");
151
+ });
152
+
153
+ test("reconcileSidecar: does NOT mark resolved comments or non-pending suggestions stale", async () => {
154
+ const mdPath = "not-stale.md";
155
+ const absPath = path.join(tmpRoot, mdPath);
156
+ const content = "# Head\n\nPara.\n";
157
+ await writeFile(absPath, content, "utf-8");
158
+
159
+ const sidecar = emptySidecar(mdPath);
160
+ // Resolved comment with orphaned ref — should NOT be marked stale
161
+ sidecar.comments.push({
162
+ id: "c_resolved",
163
+ ref: "b_orphan",
164
+ resolved: true,
165
+ createdAt: new Date().toISOString(),
166
+ turns: [],
167
+ });
168
+ // Accepted suggestion with orphaned ref — should NOT be marked stale
169
+ sidecar.archivedSuggestions.push({
170
+ id: "s_accepted",
171
+ ref: "b_orphan",
172
+ kind: "replace",
173
+ status: "accepted",
174
+ by: "ai:test",
175
+ createdAt: new Date().toISOString(),
176
+ });
177
+
178
+ const fingerprint = sha256(content);
179
+ await reconcileSidecar({
180
+ rootDir: tmpRoot,
181
+ mdPath,
182
+ content,
183
+ sidecar,
184
+ by: "system",
185
+ eventType: "file.externallyEdited",
186
+ fingerprint,
187
+ });
188
+
189
+ const comment = sidecar.comments.find((c) => c.id === "c_resolved");
190
+ assert.equal(comment?.stale, undefined, "resolved comment should not be marked stale");
191
+
192
+ // archivedSuggestions are not checked by markOrphanedRefsStale
193
+ const suggestion = sidecar.archivedSuggestions.find((s) => s.id === "s_accepted");
194
+ assert.equal(suggestion?.stale, undefined, "accepted suggestion should not be marked stale");
195
+ });
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Tests for moveSidecar, deleteSidecar, and wiki/move sidecar bug fix (R3).
3
+ */
4
+ import { test, before, after } from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { mkdtemp, rm, writeFile, mkdir, stat, access } from "node:fs/promises";
7
+ import { tmpdir } from "node:os";
8
+ import path from "node:path";
9
+
10
+ import {
11
+ moveSidecar,
12
+ deleteSidecar,
13
+ writeSidecar,
14
+ readSidecar,
15
+ emptySidecar,
16
+ sidecarPath,
17
+ } from "../../lib/proof/sidecar.js";
18
+
19
+ let tmpRoot: string;
20
+
21
+ before(async () => {
22
+ tmpRoot = await mkdtemp(path.join(tmpdir(), "wiki-sidecar-lifecycle-"));
23
+ });
24
+
25
+ after(async () => {
26
+ await rm(tmpRoot, { recursive: true, force: true });
27
+ });
28
+
29
+ // --- moveSidecar ---
30
+
31
+ test("moveSidecar: moves sidecar file to new path", async () => {
32
+ const from = "alpha.md";
33
+ const to = "renamed/alpha.md";
34
+
35
+ const sc = emptySidecar(from);
36
+ sc.revision = 42;
37
+ await writeSidecar(tmpRoot, from, sc);
38
+
39
+ const srcPath = sidecarPath(tmpRoot, from);
40
+ const destPath = sidecarPath(tmpRoot, to);
41
+
42
+ await moveSidecar(tmpRoot, from, to);
43
+
44
+ // Source gone
45
+ await assert.rejects(() => access(srcPath), "source sidecar should be gone");
46
+ // Dest present and correct
47
+ const moved = await readSidecar(tmpRoot, to);
48
+ assert.ok(moved, "destination sidecar should exist");
49
+ assert.equal(moved!.revision, 42);
50
+ });
51
+
52
+ test("moveSidecar: no-op when sidecar does not exist", async () => {
53
+ // Should not throw
54
+ await moveSidecar(tmpRoot, "nonexistent.md", "also-nonexistent.md");
55
+ });
56
+
57
+ test("moveSidecar: creates intermediate dirs for destination", async () => {
58
+ const from = "flat.md";
59
+ const to = "deep/nested/dir/flat.md";
60
+
61
+ const sc = emptySidecar(from);
62
+ await writeSidecar(tmpRoot, from, sc);
63
+
64
+ await moveSidecar(tmpRoot, from, to);
65
+
66
+ const moved = await readSidecar(tmpRoot, to);
67
+ assert.ok(moved, "destination sidecar should exist even in deep dir");
68
+ });
69
+
70
+ // --- deleteSidecar ---
71
+
72
+ test("deleteSidecar: deletes sidecar file", async () => {
73
+ const mdPath = "to-delete.md";
74
+ const sc = emptySidecar(mdPath);
75
+ await writeSidecar(tmpRoot, mdPath, sc);
76
+
77
+ const filePath = sidecarPath(tmpRoot, mdPath);
78
+ // Verify it exists first
79
+ await access(filePath); // throws if missing
80
+
81
+ await deleteSidecar(tmpRoot, mdPath);
82
+
83
+ await assert.rejects(() => access(filePath), "sidecar should be deleted");
84
+ });
85
+
86
+ test("deleteSidecar: no-op when sidecar does not exist", async () => {
87
+ // Should not throw
88
+ await deleteSidecar(tmpRoot, "never-existed.md");
89
+ });
90
+
91
+ // --- wiki/move route sidecar fix ---
92
+
93
+ test("wiki/move: moves sidecar alongside .md file rename", async () => {
94
+ // Set up isolated tmp env
95
+ const home = await mkdtemp(path.join(tmpdir(), "wiki-move-home-"));
96
+ const root = await mkdtemp(path.join(tmpdir(), "wiki-move-root-"));
97
+
98
+ try {
99
+ process.env.HOME = home;
100
+ process.env.ROOT_DIR = root;
101
+ const { setRootDir } = await import("../../lib/root-dir.js");
102
+ setRootDir(root);
103
+
104
+ const { makeUserSession } = await import("./helpers/auth-session.js");
105
+ const { POST } = await import("../../app/api/wiki/move/route.js");
106
+
107
+ // Create a .md file + sidecar
108
+ const fromRel = "moveme.md";
109
+ const toRel = "moved-target.md";
110
+ await writeFile(path.join(root, fromRel), "# Hello\n", "utf-8");
111
+
112
+ const sc = emptySidecar(fromRel);
113
+ sc.revision = 7;
114
+ await writeSidecar(root, fromRel, sc);
115
+
116
+ // Make an authenticated request
117
+ const cookie = await makeUserSession();
118
+ const req = new Request("http://localhost/api/wiki/move", {
119
+ method: "POST",
120
+ headers: {
121
+ "Content-Type": "application/json",
122
+ Cookie: cookie,
123
+ Origin: "http://localhost",
124
+ },
125
+ body: JSON.stringify({ from: fromRel, to: toRel }),
126
+ });
127
+
128
+ const res = await POST(req);
129
+ assert.equal(res.status, 200, "move should succeed");
130
+
131
+ // Source sidecar gone
132
+ const srcSidecarPath = sidecarPath(root, fromRel);
133
+ await assert.rejects(() => access(srcSidecarPath), "source sidecar should be gone after move");
134
+
135
+ // Destination sidecar present
136
+ const destSidecar = await readSidecar(root, toRel);
137
+ assert.ok(destSidecar, "destination sidecar should exist after move");
138
+ assert.equal(destSidecar!.revision, 7, "sidecar data should be preserved");
139
+ } finally {
140
+ await rm(home, { recursive: true, force: true });
141
+ await rm(root, { recursive: true, force: true });
142
+ }
143
+ });
144
+
145
+ test("wiki/move: non-.md moves don't call moveSidecar (no error)", async () => {
146
+ const home = await mkdtemp(path.join(tmpdir(), "wiki-move-nm-home-"));
147
+ const root = await mkdtemp(path.join(tmpdir(), "wiki-move-nm-root-"));
148
+
149
+ try {
150
+ process.env.HOME = home;
151
+ process.env.ROOT_DIR = root;
152
+ const { setRootDir } = await import("../../lib/root-dir.js");
153
+ setRootDir(root);
154
+
155
+ const { makeUserSession } = await import("./helpers/auth-session.js");
156
+ const { POST } = await import("../../app/api/wiki/move/route.js");
157
+
158
+ await writeFile(path.join(root, "data.json"), '{"x":1}', "utf-8");
159
+
160
+ const cookie = await makeUserSession();
161
+ const req = new Request("http://localhost/api/wiki/move", {
162
+ method: "POST",
163
+ headers: {
164
+ "Content-Type": "application/json",
165
+ Cookie: cookie,
166
+ Origin: "http://localhost",
167
+ },
168
+ body: JSON.stringify({ from: "data.json", to: "data-renamed.json" }),
169
+ });
170
+
171
+ const res = await POST(req);
172
+ assert.equal(res.status, 200, "non-.md move should succeed without error");
173
+ } finally {
174
+ await rm(home, { recursive: true, force: true });
175
+ await rm(root, { recursive: true, force: true });
176
+ }
177
+ });