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.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +5 -0
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/routes-manifest.json +34 -0
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js +8 -7
- package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js +17 -0
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js +15 -0
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/agent/fs/move/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/agent/fs/move/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/agent/fs/move/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/agent/fs/move/route.js +15 -0
- package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/agent/fs/move/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/agent/fs/search/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/agent/fs/search/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/agent/fs/search/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/agent/fs/search/route.js +15 -0
- package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/agent/fs/search/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/agent/internal/span/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/settings/route.js +1 -1
- package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/assets/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/browse/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/clear-root/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/root-status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/set-root/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/content/route.js +2 -2
- package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/file/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/move/route.js +3 -3
- package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/presence/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/wiki/presence/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/wiki/presence/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/wiki/presence/route.js +14 -0
- package/.next/standalone/.next/server/app/api/wiki/presence/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/wiki/presence/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +5 -0
- package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0d2jbo5.js +3 -0
- package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0ytral2.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-ao6a_._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0269d2e._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__05f6x0i._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06-dtd0._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06sek6_._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__09s9qkd._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d75a5q._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d_da6q._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e7si9p._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0hhhvm7._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kk26wc._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kur4ro._.js +15 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0p12-6~._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qc2~6l._.js +15 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0s~i040._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0w47wil._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xq124z._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0l..bxz._.js → [root-of-the-server]__0xz-_0v._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__10w2q~o._.js +1 -1
- package/.next/standalone/.next/server/chunks/_079xuln._.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_file_[___path]_route_actions_0gb11t~.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_ls_[[___path]]_route_actions_0wfg4nl.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_move_route_actions_0z34mqq.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_agent_fs_search_route_actions_0ut_ug..js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_wiki_presence_route_actions_0x9d7f4.js +3 -0
- 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
- package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_diagram-OG6HWLK6_mjs_0t5sus6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_sankeyDiagram-5OEKKPKP_mjs_11ifrnu._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__134_q7l._.js → [root-of-the-server]__12ahxbl._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_0pqaawz._.js +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0rc1vh5._.js → node_modules__pnpm_02gx8km._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0t4unpg._.js → node_modules__pnpm_02mew~s._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_12-ni1n._.js → node_modules__pnpm_03ij5.g._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_12~a4c_._.js → node_modules__pnpm_03v21p-._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0f~_mm3._.js → node_modules__pnpm_05qsply._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0alwr5e._.js → node_modules__pnpm_06pgebo._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_02zxe7o._.js → node_modules__pnpm_08ibh0w._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0hr027i._.js → node_modules__pnpm_099cv.b._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0znncy9._.js → node_modules__pnpm_0cwpt9p._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0-pisfi._.js → node_modules__pnpm_0f9fpy5._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0zhbnni._.js → node_modules__pnpm_0f_uzgy._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0-w-d-.._.js → node_modules__pnpm_0fixtms._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_03z0vkh._.js → node_modules__pnpm_0gofu~q._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_10i6lh6._.js → node_modules__pnpm_0iojvye._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0-hfev1._.js → node_modules__pnpm_0li2vzs._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_13kfy_z._.js → node_modules__pnpm_0m5-azh._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_071f6vl._.js → node_modules__pnpm_0n1kfcp._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_07uh2kc._.js → node_modules__pnpm_0rebktf._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0okw1r.._.js → node_modules__pnpm_0tkiej3._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0xuz.8f._.js → node_modules__pnpm_0v_nwsz._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0zb6573._.js → node_modules__pnpm_0wffzo0._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0d7jxsf._.js → node_modules__pnpm_0wouz19._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0egenev._.js → node_modules__pnpm_0xxwmv2._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0j9bq9s._.js → node_modules__pnpm_0zzzsrj._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0irsd.b._.js → node_modules__pnpm_0~.6dgb._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0erwv_m._.js → node_modules__pnpm_0~2~c30._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0y9k6h~._.js → node_modules__pnpm_10413dq._.js} +2 -2
- package/.next/standalone/.next/server/functions-config-manifest.json +5 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/middleware-manifest.json +5 -5
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/{11s9zwr7edrs7.js → 17~r3.8awh3qg.js} +12 -12
- package/.next/standalone/README.md +79 -16
- package/.next/standalone/agents/bootstrap-prompt.md +12 -1
- package/.next/standalone/agents/wiki-viewer-skill/SKILL.md +199 -6
- package/.next/standalone/docs/file-vs-collab-authority.md +124 -0
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/packages/wiki-viewer-mcp/README.md +194 -0
- package/.next/standalone/packages/wiki-viewer-mcp/dist/http-client.js +220 -0
- package/.next/standalone/packages/wiki-viewer-mcp/dist/index.js +472 -0
- package/.next/standalone/packages/wiki-viewer-mcp/dist/register.js +94 -0
- package/.next/standalone/packages/wiki-viewer-mcp/dist/state-cache.js +26 -0
- package/.next/standalone/packages/wiki-viewer-mcp/package-lock.json +1716 -0
- package/.next/standalone/packages/wiki-viewer-mcp/package.json +41 -0
- package/.next/standalone/packages/wiki-viewer-mcp/src/http-client.ts +344 -0
- package/.next/standalone/packages/wiki-viewer-mcp/src/index.ts +575 -0
- package/.next/standalone/packages/wiki-viewer-mcp/src/register.ts +144 -0
- package/.next/standalone/packages/wiki-viewer-mcp/src/state-cache.ts +45 -0
- package/.next/standalone/packages/wiki-viewer-mcp/tsconfig.json +19 -0
- package/.next/standalone/pnpm-lock.yaml +9 -9
- package/.next/standalone/src/app/api/agent/files/[...path]/route.ts +11 -1
- package/.next/standalone/src/app/api/agent/fs/file/[...path]/route.ts +344 -0
- package/.next/standalone/src/app/api/agent/fs/ls/[[...path]]/route.ts +147 -0
- package/.next/standalone/src/app/api/agent/fs/move/route.ts +125 -0
- package/.next/standalone/src/app/api/agent/fs/search/route.ts +236 -0
- package/.next/standalone/src/app/api/agent/register/route.ts +3 -3
- package/.next/standalone/src/app/api/agents/install/route.ts +44 -2
- package/.next/standalone/src/app/api/system/auth-settings/route.ts +1 -0
- package/.next/standalone/src/app/api/wiki/move/route.ts +10 -1
- package/.next/standalone/src/app/api/wiki/presence/route.ts +55 -0
- package/.next/standalone/src/components/ai-panel/ai-panel.tsx +98 -103
- package/.next/standalone/src/components/ai-panel/token-section.tsx +8 -7
- package/.next/standalone/src/components/auth-settings-sheet.tsx +81 -22
- package/.next/standalone/src/components/editor/editor.tsx +38 -0
- package/.next/standalone/src/lib/proof/audit.ts +79 -0
- package/.next/standalone/src/lib/proof/auth.ts +2 -2
- package/.next/standalone/src/lib/proof/collab-state.ts +79 -0
- package/.next/standalone/src/lib/proof/lease.ts +104 -0
- package/.next/standalone/src/lib/proof/ops-applier.ts +74 -25
- package/.next/standalone/src/lib/proof/raw-fs.ts +198 -0
- package/.next/standalone/src/lib/proof/registry.ts +1 -1
- package/.next/standalone/src/lib/proof/sidecar.ts +38 -1
- package/.next/standalone/src/lib/proof/types.ts +13 -1
- package/.next/standalone/src/tests/proof/agent-fs.test.ts +824 -0
- package/.next/standalone/src/tests/proof/agents-install.test.ts +53 -0
- package/.next/standalone/src/tests/proof/collab-state.test.ts +499 -0
- package/.next/standalone/src/tests/proof/reconcile-sidecar.test.ts +195 -0
- package/.next/standalone/src/tests/proof/sidecar-lifecycle.test.ts +177 -0
- package/.next/standalone/tsconfig.tsbuildinfo +1 -1
- package/README.md +79 -16
- package/package.json +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__09~~-nd._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0w87kiz._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__12ssbhv._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules__pnpm_0g0fhfk._.js +0 -3
- /package/.next/standalone/.next/static/{kzOuSAQArtvD7uiAJ6ZLh → 3G_3qm2a9nOX7oi5k0mPV}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{kzOuSAQArtvD7uiAJ6ZLh → 3G_3qm2a9nOX7oi5k0mPV}/_clientMiddlewareManifest.js +0 -0
- /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
|
+
});
|