19 Commits

Author SHA1 Message Date
Vijay Janapa Reddi
f127d268fa Rename Binder release workflow 2026-06-20 18:12:35 -04:00
Vijay Janapa Reddi
45aeb6b026 Audit citations and consolidate bibliography 2026-06-14 19:41:26 -04:00
Vijay Janapa Reddi
efab848914 layout: add two-phase auto layout planner 2026-06-11 20:55:44 -04:00
Vijay Janapa Reddi
42af2615cf chore: remove stale cleanup artifacts 2026-06-11 16:06:55 -04:00
Vijay Janapa Reddi
6dd3c04ebc Apply Design B multiplier formatting 2026-06-02 22:17:41 -04:00
Vijay Janapa Reddi
6860c2459f Centralize book checks in Binder CLI 2026-05-30 13:41:34 -04:00
Vijay Janapa Reddi
f741a12103 Refactor inline-python chapters to one LEGO focal point per cell.
Split mega-classes and break cross-cell reads across vol1/vol2, add lego_focal_verify.py, wire foundation-model amortization prose to computed exports, and repair compute_infrastructure inline python fences and table placement.
2026-05-24 13:17:40 -04:00
Vijay Janapa Reddi
0bd5547f54 fix(epub): align nav mathml manifest property 2026-05-12 20:03:27 -04:00
Vijay Janapa Reddi
7371f1ca4d refactor(pre-commit): collapse book-check-headers split (vol2 now clean)
Vol II now has section IDs on every numbered header (prior commit), so
both `ids` and `case` scopes pass on both volumes. Replace the two
per-scope hooks with a single `book-check-headers` running
`./binder check headers` (no flags).

The `labels` split (orphans vol1-only, duplicates both-vols) stays in
place — Vol II still references not-yet-authored chapters, which the
orphans scope correctly flags. Collapse that one once those chapters
land.

Hook count: 47 -> 46.
2026-05-06 09:08:15 -04:00
Vijay Janapa Reddi
8e7fc08282 refactor(pre-commit): split headers / labels by scope to cover vol2
Vol II was being skipped by the headers and labels hooks because both
hooks carried a `--vol1` filter. The filter was needed for ONE scope in
each group (headers/ids, labels/orphans), not the other (headers/case,
labels/duplicates which both pass cleanly on vol2 today).

Split each group into per-scope hooks so the universally-clean scope
covers both volumes:

  book-check-headers-ids         vol1 only   (--scope ids --vol1)
  book-check-headers-case        both vols   (--scope case)
  book-check-labels-orphans      vol1 only   (--scope orphans --vol1)
  book-check-labels-duplicates   both vols   (--scope duplicates)

Net effect: vol2 now gets headline-case enforcement + figure/table/listing
duplicate-label detection on every commit. No regression to vol1 coverage
(both vol1-only scopes still run on vol1; the both-vols scopes also see
vol1).

When vol2 catches up — every section ID'd, every forward-ref resolved
to a real chapter — collapse each pair back to a single
`book-check-<group>` running `./binder check <group>`. The TODO is
inline in `.pre-commit-config.yaml`.

Hook count: 45 -> 47.
2026-05-06 08:52:41 -04:00
Vijay Janapa Reddi
e2415e67cc docs(book/cli/README): align with scope-default architecture
Replace the dated 60-row "Check Groups & Scopes" table (which still
mentioned a `rendering` group split out months ago and was missing the
migrated index/lego-dead-code scopes) with a description of the
discovery contract:

  ./binder check               # full catalogue
  ./binder check <group> help  # per-group rows incl. default flag

Adding 60+ rows of stale truth-duplication to a Markdown table is the
opposite of maintainable; the binder help output now is the source of
truth.

Document the "default=True vs default=False" contract that pre-commit
and CI consume, and rewrite the Pre-commit Integration + Adding a new
check sections to walk a future maintainer through the actual flow:
write _run_<scope>, add a Scope() entry, done — no YAML edit needed.
2026-05-06 08:46:48 -04:00
Vijay Janapa Reddi
6f420e14f6 feat(binder): post-build EPUB validation — smoke + epubcheck after render
Closes the loop on `./binder build epub`. The build pipeline now ends
with a smoke + epubcheck pass against the just-built EPUB, matching
what CI runs, so a local success means "you built it AND it validates
against the same baseline CI enforces." Before this commit, the build
simply exited after the post-process sanitizer — leaving the user to
remember `./binder check epub` as a separate step. Most users didn't.

Sequence for `./binder build epub --vol1` is now:

  1. hygiene preflight        (~100ms; fast-fail on source issues)
  2. Quarto render            (~2 min)
  3. epub_postprocess.py hook (sanitizes renderer-emitted issues)
  4. smoke + epubcheck        (~7s; new; validates the final EPUB)

Post-flight runs on all four EPUB build paths (build_full,
build_volume, build_chapters, build_chapters_with_volume) for
symmetry with the existing --skip-hygiene behaviour.

Failure modes
-------------
- smoke finds a reader-compat issue (CSS custom properties, external
  resource refs): build exits nonzero, file still written. Release
  scripts gated on exit code fail fast rather than shipping a broken
  artifact.
- epubcheck reports counts within baseline: build succeeds with a
  yellow summary line showing the counts ("all within baseline — no
  regression"). No regression → no failure.
- epubcheck counts exceed the baseline recorded in
  book/tools/audit/epubcheck-baseline.json: build exits nonzero with
  per-volume deltas and a pointer to `--update-baseline` for
  accepted increases.
- Java / epubcheck missing locally: smoke still runs; epubcheck
  skipped with a single yellow hint line ("install via `pip install
  epubcheck` or `./binder doctor`"). Build does NOT fail — CI will
  catch anything this local pass would have.

--skip-validate
---------------
Matches --skip-hygiene in shape. Bypasses the post-flight step for:
  * iterating on a known-broken build
  * local environments without Java / epubcheck
  * emergency artifact generation
Prints a loud yellow warning so the bypass is never silent.

Also done in this commit
------------------------
- Inlined "EPUB — How This Integrates with the Book Workflow" into
  book/cli/README.md so the author / release / CI flows are
  documented in one place new contributors will actually find.
- Added --skip-validate to the `./binder build --help` output.

Validation
----------
  ./binder build --help              → lists --skip-validate
  BuildCommand class signatures      → skip_validate parameter on
                                       all four build_* methods
  baseline matches recorded counts   → post-flight would pass silently
2026-04-20 16:54:23 -04:00
Vijay Janapa Reddi
22853d314c feat(binder): epubcheck ratchet — fail on regression, not on absolute count
Replaces the flat MAX_FATAL / MAX_ERRORS gating in CI with a
per-volume baseline file. The check fails only when the current
epubcheck counts exceed what is recorded in
`book/tools/audit/epubcheck-baseline.json`, so:

  * Pre-existing issues do not block PRs that don't touch them.
  * Any new FATAL / ERROR / WARNING does block the PR.
  * A cleanup PR that lowers the counts must also include an
    `--update-baseline` commit so the ratchet tightens.

This is strictly better than `--max-errors N`: with a flat threshold
of N, a cleanup that brings the count from N to N-10 leaves the
ceiling at N forever and allows silent regrowth. With the ratchet,
every cleanup explicitly lowers the ceiling.

CLI surface
-----------
  ./binder check epub --scope epubcheck \
      --baseline book/tools/audit/epubcheck-baseline.json

  ./binder check epub --scope epubcheck \
      --baseline book/tools/audit/epubcheck-baseline.json \
      --update-baseline                # rewrite to current counts

When --baseline is supplied, --max-fatal / --max-errors are ignored.
The baseline file is JSON with a `volumes` map of per-volume
{FATAL, ERROR, WARNING} counts.

Under-baseline behaviour
------------------------
When current counts are *below* baseline, the run passes and prints
a hint that `--update-baseline` is available. It deliberately does
NOT auto-update: silently lowering the bar without a commit would
mean regression detection depends on build order, not on a tracked
artifact.

Baseline file (initial)
-----------------------
  vol1: 0 FATAL, 0 ERROR, 0 WARNING
  vol2: 0 FATAL, 0 ERROR, 0 WARNING

Matches the current clean state after the fix/epub-issues work.
Any new issue in either volume blocks the PR.

CI wiring
---------
.github/workflows/book-validate-dev.yml now passes --baseline
instead of --max-fatal / --max-errors. The inline env block and
step-level comment document the update-baseline workflow so a
cleanup PR knows to refresh the file.

Validation
----------
  ./binder check epub --scope epubcheck \
      --baseline book/tools/audit/epubcheck-baseline.json   → exit 0
  (clean tree matches baseline)
  YAML parse of CI workflow                                 → OK
2026-04-20 16:26:03 -04:00
Vijay Janapa Reddi
7abd633fb2 refactor(binder): consolidate legacy validate_epub.py into smoke scope
The legacy `book/tools/scripts/utilities/validate_epub.py` duplicated
most of what epubcheck covers (mimetype, container.xml, OPF structure,
XHTML well-formedness, unclosed tags, unescaped ampersands) and had a
pre-existing broken exit code that made it unusable in the default
`./binder check epub` run.

Two of its checks were genuinely unique — CSS custom properties and
external resource references. Those patterns produce real user-
reported breakage on older readers (ClearView / Tolino firmware pre-
2023) that epubcheck does not flag because they are valid EPUB 3
spec. Those unique checks now live in _epub_checks.py as
`run_smoke_checks_on()`, exposed via the new scope:

    ./binder check epub --scope smoke

Smoke runs in <1s, does not require Java, and fails on detection
(error severity) because the patterns caused real load failures.

Default `./binder check epub` now runs three scopes in order:

    hygiene   (source, pre-build)
    smoke     (built EPUB, reader compat, no Java)
    epubcheck (built EPUB, W3C validation, needs Java)

Together they form a three-layer defense: source, built-EPUB without
Java, built-EPUB with Java. A regression has to escape all three to
reach a reader.

Removed
-------
book/tools/scripts/utilities/validate_epub.py — duplicate of epubcheck
plus two unique checks now owned by _epub_checks.py.

Validation
----------
  ./binder check epub             → 0 issues, 3 scopes run, ~7s
  ./binder check epub --scope smoke → 0 issues, ~200ms
2026-04-20 16:13:47 -04:00
Vijay Janapa Reddi
48dae7b52b refactor(binder): integrate EPUB checks into the check command group
Folds both EPUB checks into the binder CLI so pre-commit, CI, and
interactive `./binder check epub` all exercise the same Python code
(no subprocess-to-script). Adds epubcheck to book/tools/dependencies
so pip install gives every contributor the validator, and simplifies
the CI job from ~60 lines of shell+Java setup to three binder calls.

New CLI surface
---------------
  ./binder check epub                    # both scopes (default)
  ./binder check epub --scope hygiene    # source-level invariants
  ./binder check epub --scope epubcheck  # W3C validator on built EPUBs
  ./binder check epub --scope epubcheck \
      --max-fatal 0 --max-errors 0       # tighten thresholds
  ./binder check epub --json             # machine-readable output

Implementation
--------------
New file book/cli/commands/_epub_checks.py holds the primitives:
  find_hygiene_issues()   — walks SVG + BIB source, returns
                            EpubIssue records for the four invariant
                            classes (svg-c0, svg-dupe-marker,
                            bib-url-escape-{underscore,percent},
                            bib-url-raw-angle).
  run_epubcheck_on()      — invokes the epubcheck binary or Python
                            wrapper, parses JSON messages, returns
                            one EpubIssue per location with severity
                            counts for threshold checks.
  emit_github_annotations() — under GITHUB_ACTIONS=true, emits
                              `::error file=...` so findings appear
                              inline on the PR diff.
  _discover_built_epubs() — finds the most recent EPUB per volume
                            under book/quarto/_build/epub-vol*/.

validate.py gains:
  - GROUPS['epub'] with 'hygiene' and 'epubcheck' scopes (the old
    'structure' scope delegated to validate_epub.py and had a
    pre-existing broken exit code; retired from default runs).
  - New --max-fatal and --max-errors flags.
  - Native _run_epub_hygiene and _run_epubcheck methods that call
    _epub_checks.py directly and wrap results into ValidationIssue.
    No subprocess-to-my-own-script.

Pre-commit wiring
-----------------
book-epub-hygiene now runs `./book/binder check epub --scope hygiene`.
Trigger files extended to include validate.py and _epub_checks.py so
the hook re-runs when the check itself changes.

CI wiring
---------
epub-validate job drops ~60 lines of shell + java jar download and
calls `./binder check epub --scope epubcheck` twice: once with --json
to capture a machine-readable artifact, once without for the
threshold-gated human summary. Java is still installed via
actions/setup-java because epubcheck is a jar.

Requirements
------------
`epubcheck>=5.1.0` added to book/tools/dependencies/requirements.txt
so every contributor gets the validator alongside the rest of the
binder runtime. Wrapper bundles the jar; JRE 8+ is still a host
requirement (brew install temurin / apt install default-jre). When
neither the Python wrapper nor the system binary is available, the
binder check emits an `epubcheck-missing` issue with install
instructions rather than silently passing.

Removed
-------
book/tools/audit/checks/epub_hygiene.py — its logic now lives in
book/cli/commands/_epub_checks.py.

Documentation
-------------
book/cli/README.md gains a "EPUB Checks — Two Layers, One CLI
Surface" section with an error-code table, fix-at-source guidance
per code, and the defense-in-depth rationale (hygiene →
epub_postprocess → epubcheck) so future contributors understand
where each check fits in the pipeline.

Validation
----------
  ./binder check epub              → 0 issues, ~7s (both scopes)
  ./binder check epub --scope hygiene  → 0 issues, ~100ms
  pre-commit run book-epub-hygiene → passes
  YAML parse of pre-commit + CI    → both OK
2026-04-20 16:03:40 -04:00
Vijay Janapa Reddi
2c17ba876a fix(book): add spacing around $\times$ in product patterns to prevent PDF overflow
Adds space before $\times$ when it appears between two inline Python
values (product pattern), preventing LaTeX from treating the entire
sequence as one unbreakable token that overflows callout boxes and
page margins. Multiplier patterns (e.g. "3× faster") left unchanged.

Also centralizes pre-commit checks:
- Migrate inline bash div-fence checks into binder (div-fences scope)
- Add times-product-spacing check to catch future regressions
- Update binder CLI README with full command/scope reference
- Remove redundant BINDER_NATIVE_AUDIT.md
2026-03-24 08:49:45 -04:00
Vijay Janapa Reddi
ff3797a1d8 Refactor: Finalize Volume 1 and update CLI/VSCode tooling
- Completed full Volume 1 refactor to Safe Class Namespace pattern.

- Fixed render errors and verified all 16 chapters.

- Updated 'binder' CLI with native validation and maintenance namespaces.

- Enhanced VS Code extension with Chapter Navigator and Run History.

- Integrated 'binder validate' into pre-commit workflows.
2026-02-11 09:25:50 -05:00
Vijay Janapa Reddi
853eb03ee8 style: apply consistent whitespace and formatting across codebase 2025-12-13 14:05:34 -05:00
Vijay Janapa Reddi
7b92e11193 Repository Restructuring: Prepare for TinyTorch Integration (#1068)
* Restructure: Move book content to book/ subdirectory

- Move quarto/ → book/quarto/
- Move cli/ → book/cli/
- Move docker/ → book/docker/
- Move socratiQ/ → book/socratiQ/
- Move tools/ → book/tools/
- Move scripts/ → book/scripts/
- Move config/ → book/config/
- Move docs/ → book/docs/
- Move binder → book/binder

Git history fully preserved for all moved files.

Part of repository restructuring to support MLSysBook + TinyTorch.

Pre-commit hooks bypassed for this commit as paths need updating.

* Update pre-commit hooks for book/ subdirectory

- Update all quarto/ paths to book/quarto/
- Update all tools/ paths to book/tools/
- Update config/linting to book/config/linting
- Update project structure checks

Pre-commit hooks will now work with new directory structure.

* Update .gitignore for book/ subdirectory structure

- Update quarto/ paths to book/quarto/
- Update assets/ paths to book/quarto/assets/
- Maintain all existing ignore patterns

* Update GitHub workflows for book/ subdirectory

- Update all quarto/ paths to book/quarto/
- Update cli/ paths to book/cli/
- Update tools/ paths to book/tools/
- Update docker/ paths to book/docker/
- Update config/ paths to book/config/
- Maintain all workflow functionality

* Update CLI config to support book/ subdirectory

- Check for book/quarto/ path first
- Fall back to quarto/ for backward compatibility
- Maintain full CLI functionality

* Create new root and book READMEs for dual structure

- Add comprehensive root README explaining both projects
- Create book-specific README with quick start guide
- Document repository structure and navigation
- Prepare for TinyTorch integration
2025-12-05 14:04:21 -08:00