Validation & Metrics
Copy page
Validation contract
Section titled “Validation contract”Plan Desk ships a named validation suite aligned with the RFC validation section.
Fail-to-pass tests (pnpm test)
Section titled “Fail-to-pass tests (pnpm test)”| Assertion ID | Behavior | Test location |
|---|---|---|
test:canvas_roundtrip | PUT 3 nodes + 2 labeled edges; GET returns identical coords + labels | packages/plandesk-api/src/routes/canvas.test.ts |
test:doc_link | Create doc with linkedTaskId; GET /tasks/:id/document returns it | packages/plandesk-api/src/routes/documents.test.ts |
test:sse_task_update | SSE client receives task_updated within 500 ms of PATCH | packages/plandesk-api/src/routes/events.test.ts |
test:mcp_update_task | MCP update_task → REST reflects change → SSE fires | packages/plandesk-mcp/src/server.test.ts |
test:export_import | Export → import → node/edge/doc counts + content match | packages/plandesk-db/src/portability.test.ts |
test:factory_adapter_smoke | MCP client with token lists ≥1 project on live server | packages/plandesk-mcp-client/src/client.test.ts |
Discover any named assertion:
pnpm test 2>&1 | rg 'test:(canvas_roundtrip|doc_link|sse_task_update|mcp_update_task|export_import|factory_adapter_smoke)'Regression tests (pnpm test)
Section titled “Regression tests (pnpm test)”| Behavior | Test location |
|---|---|
| Drizzle migration up/down on empty DB | packages/plandesk-db/src/migrate.test.ts |
| Drizzle migration up/down on seeded DB | packages/plandesk-db/src/migrate.test.ts |
| MCP token revoke → subsequent call returns 401 | packages/plandesk-api/src/routes/tokens.test.ts, packages/plandesk-mcp/src/server.test.ts |
Live validation commands (pnpm validate)
Section titled “Live validation commands (pnpm validate)”scripts/validate.sh boots plandesk serve on a temp data directory and ephemeral port, then runs:
| Assertion ID | Check |
|---|---|
cmd:api_health | GET /api/v1/health → { "ok": true } |
cmd:plandesk_serve | Server responds on the chosen loopback port |
cmd:mcp_list_tools | MCP 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.
pnpm validate# equivalent:bash scripts/validate.shRun the full gate before shipping:
pnpm build && pnpm test && pnpm lint && pnpm validatev1 Metrics
Section titled “v1 Metrics”Performance targets are measured with pnpm metrics (node scripts/metrics.mjs).
Measured: 2026-06-07 — darwin arm64, Apple M1 Pro, Node v22.22.2
| Metric | Target | Measured | Status |
|---|---|---|---|
Cold start (serve spawn → first POST /projects) | < 5 s | 419.9 ms (0.42 s) | PASS |
MCP list_projects + get_project p50 | — | 2.6 ms | — |
MCP list_projects + get_project p95 | < 2 s | 4.9 ms | PASS |
SSE task_updated latency p50 (PATCH → event) | — | 1.3 ms | — |
SSE task_updated latency p95 | < 500 ms | 1.9 ms | PASS |
| Export/import lossless (counts + links) | lossless | true (tasks=3, edges=2, docs=2) | PASS |
Measurement rig
Section titled “Measurement rig”- Isolated temp data dir + ephemeral loopback port;
plandesk initbefore serve. - Cold start: fresh
plandesk servespawn until first successfulPOST /api/v1/projects. - MCP: Bearer token; 50 sequential
list_projects+get_projectpairs via Streamable HTTP MCP. - SSE: one
/api/v1/eventssubscriber; 20PATCH /api/v1/tasks/:idtoggles; time totask_updated. - Export/import: REST fixture → CLI export → import → re-export; compare structure without IDs.