Generated by the improve skill on 2026-07-10, planned against commit
c63cb120 (Slidev v52.16.0). Each plan is a self-contained handoff for an
executor with zero prior context: read the plan fully before starting, run its
verification commands, honor its STOP conditions, and update your row below when
done.
Advisor constraint: these plans were produced read-only. No source code was
modified. The audit that produced them is summarized in each plan's "Why this
matters" / "Current state". Verification baseline for the whole repo:
pnpm install && pnpm build && pnpm typecheck && pnpm lint && pnpm test
(tests require a prior pnpm build; plan 003 adds a verify aggregate).
Ordered by leverage and dependencies: cheap/low-risk wins first, then high-confidence security + correctness, then larger refactors. You may cherry-pick — only the edges in "Dependency notes" are hard requirements.
| Plan | Title | Priority | Effort | Risk | Depends on | Status |
|---|---|---|---|---|---|---|
| 001 | CI type-checks on every PR | P1 | S | LOW | — | DONE (plan file removed) |
| 002 | Cache the pnpm store in CI | P2 | S | LOW | — | DONE (plan file removed) |
| 003 | Aggregate verify script + document build-before-test |
P2 | S | LOW | — | DONE (plan file removed) |
| 004 | Fix catalog drift (runtime deps on catalog:dev) |
P2 | S | LOW | — | DONE (plan file removed) |
| 005 | Add contributor AGENTS.md |
P3 | S | LOW | — | TODO |
| 006 | Replace exec shell-string with execFile (edit shortcut) |
P2 | S | LOW | — | DONE (plan file removed) |
| 007 | Guarantee Chromium teardown on export failure | P1 | S | LOW | — | DONE (plan file removed) |
| 008 | Guard against circular src: slide imports |
P1 | S | LOW | — | DONE (plan file removed) |
| 009 | parseRangeString lower-bound / NaN validation |
P2 | S | LOW | — | TODO |
| 010 | Harden getSlidePath against unknown slide |
P2 | S | LOW-MED | — | TODO |
| 011 | 404 on out-of-range slide-patch request | P3 | S | LOW | — | TODO |
| 012 | Fix no-op HMR utils refresh (missing await) |
P2 | S | LOW | — | TODO |
| 013 | Free port + cleanup for build's temp servers | P2 | S-M | MED | — | TODO |
| 014 | Confine deck-controlled file reads (snippets + src:) |
P1 | M | MED | — | DONE (plan file removed) |
| 015 | Validate paths in dev-server write sinks | P1 | S-M | MED | — | DONE (plan file removed) |
| 016 | Confine export output path from deck exportFilename |
P2 | S | LOW | — | TODO |
| 017 | Validate WebSocket Origin on privileged ws handlers | P2 | M | MED | — | TODO |
| 018 | Enforce --remote auth server-side (not just client) |
P3 | M-L | MED | — | TODO |
| 019 | Key getRoots() cache by entry (multi-entry build/export) |
P2 | M | MED | — | TODO |
| 020 | O(1) slide lookup Map (fix O(n²) TOC) | P2 | S | LOW | — | TODO |
| 021 | Consolidate divergent addToTree TOC builders |
P2 | M | MED | — | TODO |
| 022 | Test the export pipeline (characterization tests) | P1 | M | LOW | — | TODO |
| 023 | Decompose god functions in export.ts/cli.ts |
P3 | L | MED | 022 | TODO |
| 024 | Incremental HMR parse cache | P3 | L | MED | — | TODO |
| 025 | Guard skills/-vs-docs/ drift in CI |
P3 | S-M | LOW | — | TODO |
Status values: TODO | IN PROGRESS | DONE | BLOCKED (one-line reason) |
REJECTED (one-line rationale).
If you don't run them all, start with the low-risk, high-confidence set (all clean verification stories): 001, 002, 003, 004, 006, 007, 008, 014, 015 — plus 022 early, because it unblocks the export refactor and de-risks 007/016/023.
- 023 requires 022: do not refactor
exportSlides/serve handler until the export characterization tests exist (023's only safety net; there are no serve tests, so its Step 3 is manual + STOP-gated). - 021 ↔ 022: 021 moves
addToTreeinto@slidev/parserasbuildTocTree; 022 tests the export TOC path. If 021 lands first, 022 tests the shared builder; if 022 lands first, 021 keeps its test green. Land either order, but re-run the other's tests. - 018 subsumes the network-exposure parts of 015 and 017; still land 015 (path validation) and 017 (origin) as defense-in-depth regardless.
- 012 ↔ 024: 012 makes the per-HMR
utilsrefresh actually run (awaited); 024 reduces the parse cost that makes such per-HMR work expensive. If 012's cost proves high before 024 lands, see 012's STOP condition. - 010 ↔ 020: both touch
packages/client/logic/slides.ts(getSlide/getSlidePath). Whichever lands second must preserve the other's change (010 = undefined guard, 020 = lookup Map). Small merge; not a hard edge. - 001, 002, 003 are the CI/DX cluster — independent but naturally reviewed together.
014, 015, 016, 017, 018 all harden the dev-server + parser trust boundary that
Slidev's existing vite/importGuard.ts began. 014 (arbitrary file read via
snippets/src:) and 015 (traversal writes) are the highest-confidence,
most-actionable; 018 is the larger architectural lift (real server-side auth).
Frame all of them as defensive maintenance for the "untrusted deck" and
"exposed dev server" threat models — consistent with the maintainers' own
hardening intent.
export.ts:630-655"empty catches" — NOT a bug: a deliberate 4-location Playwright-resolution fallback chain ending in a helpfulthrow.importGuard.tsskipping dynamic imports with${template specifiers — accepted limitation; defense-in-depth atop Vite'sserver.fs.strict, does not itself widenfs.allow.resolver.tscatch {}blocks (:116/148/157/162) — deliberate best-effort resolution fallbacks; not load-bearing error swallowing.- prettier v2 (vscode) vs v3 (root) — documented decision (
taze.config.ts:10). - PlantUML default egress to
plantuml.com(parser/src/config.ts:37) — by-design/documented; a docs note at most, not a code change. DEPS-02minor version drift (@types/katex0.16 vs katex 0.17; the@hedgedocpatch;@lillallol/outline-pdfbus-factor) — low leverage; monitor, no dedicated plan.- Global-install E2E disabled in
smoke.yml— a documented pnpm-v11 limitation, not a defect.
Surfaced during the audit but out of the "fix" set; each is grounded in repo evidence and would be a design/spike plan if pursued:
- D1 Agent deck-authoring LM tools (write side of the read-only
packages/vscode/src/lmTools.ts, over@slidev/parser's existingstringify/parseSlide). - D2 A
skills/generator (scripts/gen-skills.ts) — the automation behind plan 025's drift guard. - D3 Backend-agnostic deck introspection (extract
lmTools.tsinto CLI subcommands / an MCP server). - D4 Finish per-image snapshot export (
integrations/snapshots.ts:25TODO).