From e6051001b1c2d119bcc893e8406dca8265bf3b9a Mon Sep 17 00:00:00 2001 From: Vijay Janapa Reddi Date: Sun, 15 Feb 2026 16:50:25 -0500 Subject: [PATCH] Parallel builds: track callout PDFs, fix extension errors, remove copy step - .gitignore: allow book/quarto/assets/images/icons/callouts/*.pdf - Add missing callout PDFs (takeaways, pitfall, fallacy) so worktrees have them - Extension: runtime repo-root check and clearer errors for parallel debug - Extension: remove copyCalloutPdfsToWorktree (PDFs now in repo by default) - README: document parallel build requirements; drop callout copy note --- .gitignore | 2 ++ .../icons/callouts/icon_callout_fallacy.pdf | Bin 0 -> 1146 bytes .../icons/callouts/icon_callout_pitfall.pdf | Bin 0 -> 1191 bytes .../icons/callouts/icon_callout_takeaways.pdf | Bin 0 -> 1152 bytes book/vscode-ext/README.md | 15 +++++++++++++++ book/vscode-ext/src/commands/debugCommands.ts | 12 ++++++++++-- book/vscode-ext/src/utils/parallelDebug.ts | 3 +++ 7 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 book/quarto/assets/images/icons/callouts/icon_callout_fallacy.pdf create mode 100644 book/quarto/assets/images/icons/callouts/icon_callout_pitfall.pdf create mode 100644 book/quarto/assets/images/icons/callouts/icon_callout_takeaways.pdf diff --git a/.gitignore b/.gitignore index 08772cfdc..30ad0db2c 100644 --- a/.gitignore +++ b/.gitignore @@ -120,6 +120,8 @@ book/tools/scripts/testing/logs/ *.lof *.lot *.pdf +# Callout icon PDFs needed for PDF builds (and parallel worktree builds) +!book/quarto/assets/images/icons/callouts/*.pdf # Database *.db diff --git a/book/quarto/assets/images/icons/callouts/icon_callout_fallacy.pdf b/book/quarto/assets/images/icons/callouts/icon_callout_fallacy.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e368c46ff71c817705fe86d88cb180cf5acfedd0 GIT binary patch literal 1146 zcmY!laBlj?Vxi^-5@&vWf(>}z~ym+g*M;E)UJf8-bz zaKu(e?oaLJo6{8*8Y>!4ZhN@ZY>fhIuDfkzc&MT$@B1B71TNo_DZdeC`z}8zd{qm7 z<(sdzFKYs)AMa&h|B?`Gy-06rgTjjiGK*KYrc1FN71KGlyz0g0HP0M#rmFR-ZL17R z{g|0`Hu}ZJnkpyfHR=CikKR<3DCt;}@?q0~`8T(m%=wa>_k#OiyL}v2YF-M|$v_s! zvmhUWXrLbr%`8CjAf7QiD8Qa~ttfF1E&+O6!Nvw800jDp20)I2zO$o(p@M#LB9H_I z2T%e?0uj_4bGSJQ`XQACsS5i3Nm;=qxnNVFVQc{pV?PB$u!LJ?QE`ca36zaL+>L_` z9&|nHddkGWX2BSX=|7O^aR0%aWl4my42_W71#=6?T}H-4IV^OdV|I&yKr~fo8@RkRTaVt2eyMomAg_qBr_SB_`Pj5 z>R|6d&)D!kT=)ETgqg0C`g4uz_F+2*FPVz&b3S1Uo6p|;?9zKm|Df#OgZm$5y?i?T zW&Y-izwf&#U(^pT$;-!#9B>#zW5>wc3>H0xh~x)LHW5LoX~>Dj)BuQ#--Y&)Ja2<-6U{7>36desx7nUQ>5vM25vK zQ0UUyrJ=LK?%z+<74~$f6CMNhYs^5}-X1HfUVl%hXalNYxvrbqXR#Kl)QQ7`?TfY5s{~K00Z!ZY{ zJ<4&ky{7-sy2>B(SIE0(B#C!)nw~wTn0>bI;Yp*UXF9hQdS72~@p*gL)120}wWqZ= z^S)d!D1Gk4(rM>ncA4e9p5-=W^;@&_+4~>c{m{;RDILlh^oT1pF9qs7APW>QpwIx( z!0<3KGy=(kc*gKx0|%6AMTvWG2{4cpY-~URK%k#!0OTm>J3A^ED(ELC0!d)d0VRMW z5JAl`hnu6IA5vM6s-W+mloec(3pN!R9~SWV@KZ1ZOSokg6_+TOK-u`?$T-;GLD#dc zr%ViN7L2i&{sWl~^`D^`%vqL1ILpuo$z3qFfZSzdOq9byCpu=g7znh!|JSv1%BzL5 zQnpTY{kDP2TeJ1(-RPH!M-K9eD0}MMt-s&7F51f}!S3FZy`B~uI*c_UR2sx>9?6*L zE3MKxaqhaHqV*}cSQdtxv){?oG%&E~)|^{mcKJc0`|i7U3b!nqEfUo+^~yB{|H_%q z1mgF|-!(g(b}QO4ZcEY1jkS|>u18FXo4s(NoMPU#rp|OX_S4;)1pL=jr07KY{!2Q@ z9NGSF@fL}qmK5WP<9?_2{#>}DCoHaQubZ4rr|gsRuLoykwyffET_N5+bKMJ=sxEYwy^o^-Onz)r}PiX{yn(=Vb;s1(_iLq zzWDpToAO2d@RGcI%*X+UF)a0&!=uL#k^ErECL$;`4LQ-6TH=fZP~r^EtV&fdgv467 zLbRcRk%CbySVvHPeu;viAv|t9^V0Ga3=P11)7tOIb;v-#^?PwwJ>z4aS!ypiTbjCG1;unU z1-)6cwU3?VVi-ho=g2#>KamH`ARp6vCs*wA6D z5uwr`Zu3aSOkZi0)`@f11r@DN$;GlT+?@SRrlx^`O}FOU3bV@(8r^r_y;Hbl*=&)h zj;U9!G5A-`d?paTNB*wa>9kwXmT_B(R&K1Fq;oxDO5E&)6Xg{1wl#I8yRo0{-X!3^ zrXocr()VA|LFUNze~Y(B6t$!nR~+{{z4zzB9X(-jZF}A1Y&vD1lz%-qE3;)4m+K1g z_L=KmxLi4Pu=k*6Z1^9pdwx5@Ojk<%xyE(-u$_aKOhxxOpRk3^XYYP?={==?Q1W7!)N5X&D$87=2*obkmz4Vcjv6Q7NvmNg4 UqLPXtp!+S2%(zrlUH#p-0N(edfdBvi literal 0 HcmV?d00001 diff --git a/book/vscode-ext/README.md b/book/vscode-ext/README.md index f03617354..61b8ad98d 100644 --- a/book/vscode-ext/README.md +++ b/book/vscode-ext/README.md @@ -49,6 +49,21 @@ This keeps daily actions focused while preserving easy access to tuning controls - Validate content: `./book/binder validate all` - Maintenance checks: `./book/binder maintain repo-health` +## Parallel builds (Test All Chapters) + +**Build All Chapters (Parallel)** in the Debug view runs each chapter in a separate git worktree so multiple PDF builds run at once. + +**Requirements:** + +1. **Open the repo root** — Open the folder that contains `book/` (e.g. `mlsysbook-vols`), not a subfolder like `book/` or `book/quarto/`. The extension needs `book/binder` to be present to register commands and run parallel jobs. +2. **Git in PATH** — Parallel mode uses `git worktree add --detach`; ensure `git` is available in the environment where the extension runs. +3. **Optional settings** (VS Code/Cursor → Settings → MLSysBook): + - `mlsysbook.parallelDebugWorkers` — number of concurrent builds (default: 4). + - `mlsysbook.parallelDebugRoot` — directory for worktrees under repo root (default: `.mlsysbook/worktrees`). + - `mlsysbook.keepFailedWorktrees` — keep worktrees for failed chapters for inspection (default: true). + +If worktree creation fails, check the **MLSysBook Parallel Debug** output channel; the first failure will include a tip about repo root and git. + ## Quarto Visual Customization The extension includes QMD-focused visual highlighting to improve scanability in long Quarto documents. diff --git a/book/vscode-ext/src/commands/debugCommands.ts b/book/vscode-ext/src/commands/debugCommands.ts index 8cbdc5153..ed04afb6b 100644 --- a/book/vscode-ext/src/commands/debugCommands.ts +++ b/book/vscode-ext/src/commands/debugCommands.ts @@ -18,11 +18,19 @@ const STATE_LAST_PARALLEL_VOLUME = 'mlsysbook.lastParallelVolume'; /** * Test All Chapters — prompts for volume only, then builds every chapter * in parallel using PDF format and the configured worker count. + * Requires workspace opened at repo root (folder containing book/) and git in PATH. */ async function runTestAllChapters( root: string, context: vscode.ExtensionContext, ): Promise { + const repoRoot = getRepoRoot(); + if (!repoRoot) { + vscode.window.showErrorMessage( + 'MLSysBook: Parallel build requires the workspace to be the repository root (the folder that contains book/). Open that folder and try again.', + ); + return; + } const defaultVolume = context.workspaceState.get(STATE_LAST_PARALLEL_VOLUME); const picks = [ { label: defaultVolume === 'vol1' ? 'Volume I (last used)' : 'Volume I', id: 'vol1' as VolumeId }, @@ -32,7 +40,7 @@ async function runTestAllChapters( if (!selection) { return; } const volumeId = selection.id; - const volumes = discoverChapters(root); + const volumes = discoverChapters(repoRoot); const volume = volumes.find(v => v.id === volumeId); if (!volume || volume.chapters.length === 0) { vscode.window.showWarningMessage(`No chapters found for ${volumeId}.`); @@ -51,7 +59,7 @@ async function runTestAllChapters( ); await runParallelChapterDebug({ - repoRoot: root, + repoRoot, volume: volumeId, format: 'pdf', chapters: allChapters, diff --git a/book/vscode-ext/src/utils/parallelDebug.ts b/book/vscode-ext/src/utils/parallelDebug.ts index 19ea59a43..2fc376aa3 100644 --- a/book/vscode-ext/src/utils/parallelDebug.ts +++ b/book/vscode-ext/src/utils/parallelDebug.ts @@ -442,6 +442,9 @@ async function runParallelDebugBatch(options: BatchRunOptions): Promise<{ result elapsedMs: Date.now() - start, }); channel.appendLine(`[${tag}] failed to create worktree (exit ${addCode})`); + if (index === 0) { + channel.appendLine('[session] Tip: ensure the workspace is the repo root and `git` is in PATH.'); + } continue; }