Skip to content

Add VS Code command to generate sprint report PDFs - #97

Merged
VeryComplexAndLongName merged 1 commit into
mainfrom
feat/sprint-report-vscode-command
Aug 27, 2026
Merged

VeryComplexAndLongName merged 1 commit into
mainfrom
feat/sprint-report-vscode-command

Conversation

@VeryComplexAndLongName

Copy link
Copy Markdown
Owner

Summary

  • Second half of the sprint-report feature (add-sprint-report-pdf, PR Add sprint summary PDF report (standalone) #96, shipped the standalone-only half). New Command Palette command "OpenSpec UI: Generate Sprint Report (PDF)": reuses pickChangesForTimeline unchanged, prompts for a validated YYYY-MM-DD start/end date (no native VS Code date picker; this command needs a real user-specified range, unlike the comparison timeline's auto-derived one), calls buildSprintReport/renderSprintReportPdf from @openspec-ui/core directly (per ADR-0001 — no server/REST round-trip), then showSaveDialog -> workspace.fs.writeFile -> a confirmation message offering to open the PDF.
  • Caught and fixed a real regression before it shipped: this is the first code path that actually executes renderSprintReportPdf from inside the bundled extension. That re-exposed the pdfkit/esbuild bundling hazard PR Add sprint summary PDF report (standalone) #96's CI caught — the createRequire-based workaround from that PR fixed extension activation, but silently stopped esbuild from inlining pdfkit into the bundle at all (confirmed: dist/extension.js dropped from 2.8MB to 635KB and left a real runtime require("pdfkit") call). Since vsce package --no-dependencies ships no node_modules, the command would have failed at runtime with "Cannot find module 'pdfkit'" the first time a real user ran it.
  • Fix: reverted sprint-report-pdf.ts to a plain import PDFDocument from "pdfkit" (correct as-is for every plain-Node/ESM consumer — server, core's own tests) and instead fixed the bundling problem where it actually lives — the extension's own esbuild config — via an alias mapping "pdfkit" to its real CommonJS build file at bundle time (build-options.mjs), which genuinely inlines it and reads __filename instead of import.meta.url.

Verification

Rebuilt dist/extension.js and loaded it in plain Node with a stubbed vscode module: activation succeeds, and the bundle contains pdfkit's real CommonJS build inline (confirmed via ICC_PROFILE_PATH's pathToFileURL(__filename) form, not the broken import_meta2.url form from before the fix).

Test plan

  • New tests in commands.test.ts for generateSprintReport: builds+saves+offers to open the PDF; no-op when no changes picked; no-op when either date prompt is dismissed; date validator rejects malformed input; no file written when the save dialog is dismissed; PDF not opened when the confirmation is dismissed; error surfaced when report generation fails
  • showSaveDialog/workspace.fs.writeFile/env.openExternal stubs added to test-utils/vscode-mock.ts
  • npm run typecheck, npm run lint (including lint:english), npm run test workspace-wide
  • Rebuilt dist/extension.js and verified real pdfkit-CJS inlining + successful activation in plain Node (see above)
  • openspec change validate --strict add-sprint-report-vscode-command

🤖 Generated with Claude Code

Second half of the sprint-report feature (add-sprint-report-pdf, PR
#96, shipped the standalone-only half). New Command Palette command
"OpenSpec UI: Generate Sprint Report (PDF)": reuses
pickChangesForTimeline unchanged, adds two validated YYYY-MM-DD date
prompts (VS Code has no native date picker, and this needs a real
user-specified range, not an auto-derived one), calls
buildSprintReport/renderSprintReportPdf from @openspec-ui/core
directly (per ADR-0001 -- no server/REST round-trip), then
showSaveDialog -> workspace.fs.writeFile -> a confirmation message
with an "Open" action.

This is also the first code path that actually executes
renderSprintReportPdf from inside the bundled extension -- which
re-exposed the pdfkit/esbuild bundling hazard PR #96's CI caught
(esbuild's CJS bundle can't shim pdfkit's ESM build's
import.meta.url). The createRequire-based workaround from that PR
fixed activation but silently stopped esbuild from inlining pdfkit at
all (a local variable named `require`, however constructed, isn't
recognized as a bundleable require once esbuild renames it during
bundling -- confirmed by inspecting the built dist/extension.js, which
dropped from 2.8MB to 635KB and left a real runtime
`require("pdfkit")` call). Since `vsce package --no-dependencies`
ships no node_modules, that would have failed at runtime with "Cannot
find module 'pdfkit'" the first time this command actually ran.

Reverted sprint-report-pdf.ts to a plain `import PDFDocument from
"pdfkit"` (correct as-is for every plain-Node/ESM consumer -- server,
core's own tests) and instead fixed the extension-only bundling
problem in the extension's own esbuild config: an `alias` mapping
"pdfkit" to its real CommonJS build file at bundle time
(build-options.mjs), which genuinely inlines it and reads __filename
instead of import.meta.url.

Verified: rebuilt dist/extension.js and loaded it in plain Node with a
stubbed vscode module -- activation succeeds, and the bundle contains
pdfkit's real CommonJS build inline (grep for ICC_PROFILE_PATH's
pathToFileURL(__filename) form, not import_meta2.url).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@VeryComplexAndLongName
VeryComplexAndLongName merged commit 89602a9 into main Aug 27, 2026
6 checks passed
@VeryComplexAndLongName
VeryComplexAndLongName deleted the feat/sprint-report-vscode-command branch August 27, 2026 04:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant