design.md was stored in a global Zustand store + per-file-key localStorage
in apps/web, and in a module-level cache in pen-mcp. Both leaked across
files: a newly-created document could pick up the previous file's dark
palette (async clearForNewDocument raced with AI chat reads; hydrate()
could rehydrate the last file's designMd on refresh; shared .pen files
lost the spec entirely because it wasn't inside the document).
Fix:
- Add `designMd?: DesignMdSpec` to PenDocument (pen-types). It now
serializes with .pen/.op and travels across sessions/users.
- Add `setDesignMd` action to document-store.
- Rewrite design-md-store as a thin mirror over document-store so the
legacy hook API still works. On document load it migrates any legacy
localStorage entry into the opened document and deletes the localStorage
key; hydrate() wipes the orphan `openpencil-design-md-current-key`.
- MCP handleGetDesignMd / handleSetDesignMd / handleExportDesignMd read
`doc.designMd` directly and persist via saveDocument. Removed the
process-level `_mcpDesignMd` cache.
Verified via MCP live round-trip: set on file A → persists to A's .op on
disk → new file B returns hasDesignMd:false (no leak).