Skip to content

Latest commit

 

History

History
136 lines (113 loc) · 12.3 KB

CLAUDE.md

File metadata and controls

136 lines (113 loc) · 12.3 KB

Claude Code Instructions

Project guidance for Claude Code (CLI, IDE, and the GitHub Action). The same conventions apply to GitHub Copilot --- see .github/copilot-instructions.md, which is the source of truth for style.

Project context

mds holds the mathematics that the Morrison-Lab data science courses assume: notation, algebra, calculus, linear algebra and vector calculus, as Quarto fragments. It renders on its own as a website, and course sites such as mlds link to its pages by URL, so a page's path and its #id anchors are an interface: renaming either breaks those links. The scaffolding came from the UCD-SERG qwt template.

Authoritative style guide: UCD-SERG Lab Manual (source: https://github.com/UCD-SERG/lab-manual).

Repository layout

  • index.qmd, chapters/, appendix-*.qmd --- Quarto source pages
  • references.qmd --- standalone reference page; excluded from the default website render (!references.qmd in _quarto-website.yml), so it isn't part of the normal site build
  • _quarto.yml, _quarto-website.yml --- Quarto project + website config
  • _extensions/ --- vendored Quarto extensions
  • latex-macros/ --- git submodule for shortcode/macro definitions (see .gitmodules)
  • R/, man/, DESCRIPTION, NAMESPACE --- the project is also a small R package
  • references.bib --- BibTeX bibliography
  • page-navigation.html --- HTML include (format.html.include-after-body) that adds floating previous/next arrows in the page margins and highlights the navbar link for the current page; vendored from Morrison-Lab/lbt via Morrison-Lab/qwt. The previous/next order comes from website.sidebar in _quarto-website.yml, so add each new page to both the navbar and the sidebar, in the same position.
  • offwhite.scss, theme-picker.html --- the website's Light / Off-white / Parchment / Dark theme dropdown (saved under mln-theme, shared with the slides and the other sites on this origin)
  • styles.css --- website styling; styles-reveal.scss, qwt-reveal-toggle.html (the same dropdown for slides), and the revealjs-*.lua filters drive the reveal.js slide output
  • math-xrefs.lua --- resolves @id cross-references written inside math (for example a \text{(@thm-spectral)} derivation annotation), which Quarto leaves as literal text; it numbers theorem-type divs and labelled equations the way Quarto does and writes the label ("Theorem 59"), linked in HTML
  • assets/, images/ --- static image and asset files (site pages, docs, CI/PR screenshots)
  • .github/workflows/ --- CI workflow definitions
  • .github/scripts/ --- helper scripts used by workflows
  • .github/instructions/ --- path-scoped Copilot rules that attach by file glob (see .github/copilot-instructions.md)
  • CONTRIBUTING.md --- contributor guide
  • _site/, _freeze/, .quarto/ --- build artifacts (do not edit by hand)

Style conventions

Mirrors .github/copilot-instructions.md. Key points:

  • Lists of 3+ items: use bullet lists rather than comma-separated prose. Always leave a blank line before a markdown bullet list (especially in .qmd files).
  • Code chunks: HTML output folds code by default: _quarto-website.yml sets code-fold: true (with code-tools: true, so readers can show all code at once), as rme does. Keep the default when the output (plot, table) is the point and the code is incidental. Set #| code-fold: false on tutorial code, short examples, code that is the main focus, and chunks where the console output is the main content.
  • R style: respect .lintr.R. Run lintr::lint_dir() before declaring R changes done.
  • No nested calls in R: lint-changed-lines.yaml lints the R code and R chunks that a PR adds or edits, with lms::default_linters(nested_calls = TRUE). Its nested_calls = TRUE setting enforces the lab's no-nested-calls rule. The linters also flag base R functions that have tidyverse replacements. Run the same linters on a file before pushing with lintr::lint("file.qmd", linters = lms::default_linters(nested_calls = TRUE)).
  • Quarto chunks: prefer chunk options as YAML-style #| directives, not as inline r, opt = val arguments.
  • Useful resources: a course, book or video that covers a topic mds teaches goes in the Further reading section of the matching page, even when lds already lists it in a directory (Ezra, 2026-10-15). Link the resource, and adapt it with attribution only when its license allows adapting. See track-useful-resources.
  • Page, section and subsection files nest by heading level (Ezra, 2026-11-03): a page's top-level .qmd holds the YAML header, the macros include, every first-level heading, and an include of each first-level section's body. A section body holds its second-level headings and an include of each subsection's body, and so on down. Only the file for the level above holds a heading, so no file is a wrapper that adds one heading and one include. Apply it to a page when you touch it, not as a sweep. The rule is in psw's Writing for code review and software.
  • One term per #def- div: define a single term in each definition div, and give each further term its own div and id, placed right after the first (or before it, if the first uses it) and linking to it. Aliases of one term ("also called ...") stay in the same div, in bold and in the div title. Put commentary in a separate #rem- div and each example in an #exm- div after the definition it illustrates. A theorem-type div states one result. Keep the old id on the original term (Ezra, 2026-10-12); see psw's Writing for teaching.

Working in this repo

  • Don't edit generated files: README.md is built from README.Rmd; _site/ and _freeze/ are build outputs.
  • Local preview: quarto preview (live reload). Full build: quarto render. When verifying a single edited page, render just that page (quarto render <file>.qmd --to html) rather than the whole site --- the /render command is for the full build.
  • Submodules: latex-macros/ is the only git submodule (see .gitmodules). Run git submodule update --init --recursive after cloning.
  • Spell check: words go in inst/WORDLIST (see .github/workflows/check-spelling.yaml). Update the wordlist instead of disabling the check.
  • Link check: tuned in lychee.toml; prefer fixing broken links over adding exceptions.
  • Other CI checks: workflows also verify bibliography DOIs (check-bibliography-dois.yml) and flag non-standard characters (check-non-standard-chars.yaml). Fix the flagged source rather than relaxing the check.
  • A book with no DOI: add its key to exclude-keys in .github/workflows/check-bibliography-dois.yml in the same PR as its references.bib entry and citations (mds#635). A separate exemption PR is flagged for a key no entry uses, and the entry's PR fails the check without it.
  • Previews skip the PDFs and Word files: on a pull request, tools/skip_pdf_in_previews.py (a pre-render script) removes the pdf and docx formats unless the PR carries the label preview:pdf or preview:docx. The publish on main builds both. With only the PDFs skipped, a preview took 89 of its 90 minutes, so the preview cap is 120 minutes (decided 2026-10-22, mds#447).
  • The Quarto freeze cache is kept across runs, and a changed subfile invalidates it (checked 2026-11-05 against Morrison-Lab/gha v3, mds#631). Both publish.yml (freeze-cache: true) and the preview workflow restore _freeze with actions/cache, from the newest cache whose key matches. freeze: auto hashes only a page's own file, so a changed subfile would otherwise keep serving stale results. gha's preview/prune-stale-freeze.py runs after the restore in both workflows. It reads the commit SHA out of the restored key and diffs that commit against HEAD. It deletes the frozen results of every page that changed, that includes a changed file through any chain of {{< include >}}, or that mentions the file name of a changed non-page file (a data file, script or the latex-macros pin). It resolves every path with Path.resolve(), so an include written mds/_subfiles/... reaches _subfiles/... through the mds -> . symlink and counts as a dependency. If the key names no commit, or the commit cannot be fetched, it deletes the whole freeze. Before relying on it for a new include style (a {{< include >}} with a shortcode or variable in the path), check that INCLUDE_RE in that script matches it. The clear freezer label discards the cache; a subfile edit no longer needs it.
  • Dependencies: Dependabot auto-updates the latex-macros submodule and GitHub Actions (see .github/dependabot.yml); don't bump those by hand unless a PR needs it.

Pull request expectations

  • Keep PRs scoped --- bug fixes shouldn't smuggle in refactors.
  • Write commit messages and PR descriptions explaining the why, not just the what.
  • Don't bypass CI failures (spell check, link check, lint, bibliography DOIs, non-standard chars) --- fix the underlying issue.
  • Don't commit _site/ or _freeze/ changes unless that is genuinely the intent of the PR.

Shared lab rules

The lab's cross-repository rules live in Morrison-Lab/ai-config, which .claude/settings.json enables as the ai-config@Morrison-Lab plugin. Enabling is not installing: a local session needs claude plugin install ai-config@Morrison-Lab once. When the plugin is not loaded (for example, in a session rooted above this checkout), read the rules from a clone of ai-config before content work, in particular:

  • shared/writing/ --- definitions, derivation steps, fact-checking, cross-references, plain prose
  • shared/coding/ --- R style, ASCII punctuation in source
  • skills/quarto-authoring/references/divs-and-spans.md --- no theorem-type div nested inside another

Relationship to rme

This repository is the canonical home for the math prerequisites that Morrison-Lab/rme carries as appendices (math-prereqs.qmd, algebra.qmd, calc-derivatives.qmd, calc-integrals.qmd and notation.qmd). rme will drop those appendices and point readers here (rme#1204).

  • rme is a good first place to look for content, not an authority on content or style: much of it predates the lab's style rules. Check what you port, fix what is wrong, and bring it up to the current rules.
  • Keep rme's #ids, so rme's links can be repointed by changing only the path.

Things to avoid

  • Reformatting unrelated files.
  • Inventing URLs or citations --- only use sources actually present in references.bib or explicitly provided.
  • Showing readers source information when content comes from our own lab (e.g. "Source: new for Fall 2026", "written for Midterm 1", "from our lab"). Only external reference sources (textbooks, papers, external software) should be cited; internal lab provenance is unnecessary clutter for readers.
  • Asking a person to check a citation you can check yourself. The lab's reference books (for example Billingsley, Probability and Measure, 3rd ed.) are PDFs in the private Morrison-Lab/mlr repository under books/; verify section, theorem, and page numbers against them before citing or reporting a citation as unchecked.

Cross-project agent rules (ai-config)

This repository follows the maintainer's cross-project agent rules in Morrison-Lab/ai-config. If your harness has not already loaded them (Claude Code loads them through the ai-config plugin), read AGENTS.md before starting work, and follow it alongside this file. This file's own instructions add to those rules, and win only where they are more specific.