Skip to content

Validation & Metrics

Copy page

Plan Desk ships a named validation suite aligned with the RFC validation section.

Assertion IDBehaviorTest location
test:canvas_roundtripPUT 3 nodes + 2 labeled edges; GET returns identical coords + labelspackages/plandesk-api/src/routes/canvas.test.ts
test:doc_linkCreate doc with linkedTaskId; GET /tasks/:id/document returns itpackages/plandesk-api/src/routes/documents.test.ts
test:sse_task_updateSSE client receives task_updated within 500 ms of PATCHpackages/plandesk-api/src/routes/events.test.ts
test:mcp_update_taskMCP update_task → REST reflects change → SSE firespackages/plandesk-mcp/src/server.test.ts
test:export_importExport → import → node/edge/doc counts + content matchpackages/plandesk-db/src/portability.test.ts
test:factory_adapter_smokeMCP client with token lists ≥1 project on live serverpackages/plandesk-mcp-client/src/client.test.ts

Discover any named assertion:

Terminal window
pnpm test 2>&1 | rg 'test:(canvas_roundtrip|doc_link|sse_task_update|mcp_update_task|export_import|factory_adapter_smoke)'
BehaviorTest location
Drizzle migration up/down on empty DBpackages/plandesk-db/src/migrate.test.ts
Drizzle migration up/down on seeded DBpackages/plandesk-db/src/migrate.test.ts
MCP token revoke → subsequent call returns 401packages/plandesk-api/src/routes/tokens.test.ts, packages/plandesk-mcp/src/server.test.ts

scripts/validate.sh boots plandesk serve on a temp data directory and ephemeral port, then runs:

Assertion IDCheck
cmd:api_healthGET /api/v1/health{ "ok": true }
cmd:plandesk_serveServer responds on the chosen loopback port
cmd:mcp_list_toolsMCP session lists ≥8 tools with a bearer token

The script traps EXIT/INT/TERM and reaps the server process plus temp directory. It never touches ~/.plandesk.

Terminal window
pnpm validate
# equivalent:
bash scripts/validate.sh

Run the full gate before shipping:

Terminal window
pnpm build && pnpm test && pnpm lint && pnpm validate

Performance targets are measured with pnpm metrics (node scripts/metrics.mjs).

Measured: 2026-06-07 — darwin arm64, Apple M1 Pro, Node v22.22.2

MetricTargetMeasuredStatus
Cold start (serve spawn → first POST /projects)< 5 s419.9 ms (0.42 s)PASS
MCP list_projects + get_project p502.6 ms
MCP list_projects + get_project p95< 2 s4.9 msPASS
SSE task_updated latency p50 (PATCH → event)1.3 ms
SSE task_updated latency p95< 500 ms1.9 msPASS
Export/import lossless (counts + links)losslesstrue (tasks=3, edges=2, docs=2)PASS
  • Isolated temp data dir + ephemeral loopback port; plandesk init before serve.
  • Cold start: fresh plandesk serve spawn until first successful POST /api/v1/projects.
  • MCP: Bearer token; 50 sequential list_projects + get_project pairs via Streamable HTTP MCP.
  • SSE: one /api/v1/events subscriber; 20 PATCH /api/v1/tasks/:id toggles; time to task_updated.
  • Export/import: REST fixture → CLI export → import → re-export; compare structure without IDs.