Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,14 @@ repos:
rev: "v3.6.2"
hooks:
- id: prettier
exclude_types: [markdown]
exclude: ^pixi\.lock$

- repo: https://github.com/rvben/rumdl-pre-commit
rev: "v0.2.73"
hooks:
- id: rumdl-fmt

- repo: https://github.com/codespell-project/codespell
rev: "v2.4.1"
hooks:
Expand Down
5 changes: 0 additions & 5 deletions .prettierrc.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
proseWrap = "always"
printWidth = 80

[[overrides]]
files = "slides/*.md"
options.proseWrap = "never"
31 changes: 31 additions & 0 deletions .rumdl.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Markdown linting and formatting; replaces prettier for *.md.

[global]
flavor = "myst"
# rumdl refuses to format any file with conflict markers, even inside a code
# block, and the rule cannot be disabled.
exclude = ["content/week01_git/advanced_steps.md"]
disable = [
"MD014", # `$ ` prefixes are required by the `console` lexer
"MD024", # repeated headings are normal across course sections
"MD025", # heading levels are a content decision
"MD026", # headings keep their "!" and ":"
"MD028", # separate blockquotes are intentional
"MD033", # inline HTML is used in some chapters
"MD041", # chapters can start with frontmatter or a directive
"MD045", # some images are decorative
"MD053", # link definitions are shared between chapters
"MD059", # "this page" link text is fine in prose
]

[per-file-flavor]
"slides/*.md" = "standard"

[per-file-ignores]
# Marp decks keep one line per paragraph, as prettier's proseWrap = "never" did.
"slides/*.md" = ["MD013"]

[MD013]
line-length = 80
reflow = true
code-blocks = false
11 changes: 7 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,16 @@ MyST MD course site for _Software Engineering for Scientific Computing_.
## Lint / format / pre-commit

- Always use `prek -a --quiet` instead of `pre-commit run -a`.
- Hooks include: ruff-format, blacken-docs, nbstripout, prettier, codespell,
blocklint, plus a **custom `disallow-caps` hook** that rejects
- Hooks include: ruff-format, blacken-docs, nbstripout, rumdl, prettier,
codespell, blocklint, plus a **custom `disallow-caps` hook** that rejects
miscapitalizations of names like pybind11, NumPy, CMake, ccache, GitHub, and
pytest — always use the canonical spelling (the hook also applies to this
file).
- Prettier config (`.prettierrc.toml`): prose wraps at 80 chars by default,
**but never for `slides/*.md`**.
- `rumdl` formats all Markdown; config is `.rumdl.toml`. Prose wraps at 80
chars, **but `slides/*.md` keep one line per paragraph**. The MyST flavor is
on, so `` ```{directive} `` fences are understood.
- Prettier (`.prettierrc.toml`) now covers only the non-Markdown files: YAML,
JSON, CSS, and JavaScript.

## CI / deploy

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ too.

Tuesday/Thursday variation (fall 2026 dates):

```
```text
┌──────────┬──────────────────────────┬─────────────┐
│ Week │ Topic │ Date │
├──────────┼──────────────────────────┼─────────────┤
Expand Down
2 changes: 1 addition & 1 deletion content/week00_intro/practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ Notice the style:
A function's signature should be a contract between the function implementer
(you) and the function user (might also be you). Something like this:

```
```text
output1, output2, ... = function(input1, input2, ...)
```

Expand Down
14 changes: 7 additions & 7 deletions content/week01_git/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@ Things to keep in mind during our exercise

Your git branching sandbox

Open a browser to this URL: https://learngitbranching.js.org/?NODEMO
Open a browser to this URL: <https://learngitbranching.js.org/?NODEMO>

Other resources for git:

- https://gitimmersion.com/
- https://think-like-a-git.net/
- http://ndpsoftware.com/git-cheatsheet.html
- https://ohshitgit.com/
- https://gitready.com/
- https://explainshell.com/
- <https://gitimmersion.com/>
- <https://think-like-a-git.net/>
- <http://ndpsoftware.com/git-cheatsheet.html>
- <https://ohshitgit.com/>
- <https://gitready.com/>
- <https://explainshell.com/>
7 changes: 6 additions & 1 deletion content/week02_agents/agents_md.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ works on files in that directory. This is useful for a monorepo, where each
package has its own conventions.

```{attention} Claude Code
Claude Code does not read this standard file, so you need to either `ln -s AGENTS.md CLAUDE.md` or make a `CLAUDE.md` that has `@AGENTS.md` mentioned in it somewhere. Other {term}`harnesses <harness>` also have custom files too, but they do read AGENTS.md automatically. You can gitignore `CLAUDE.md` or commit the symlink (also `.claude/`, Claude puts local stuff there).
Claude Code does not read this standard file, so you need to either
`ln -s AGENTS.md CLAUDE.md` or make a `CLAUDE.md` that has `@AGENTS.md`
mentioned in it somewhere. Other {term}`harnesses <harness>` also have custom
files too, but they do read AGENTS.md automatically. You can gitignore
`CLAUDE.md` or commit the symlink (also `.claude/`, Claude puts local stuff
there).
```

## To commit or not to commit
Expand Down
7 changes: 4 additions & 3 deletions content/week02_agents/ci_and_bugfixes.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ mean it's correct or the best fix. Great tests and lints become more important
with AI; the harder it is to produce an incorrect fix, the better.

```{tip}
Add regression tests first, then fix. High end models and {term}`harnesses <harness>` might do
this for you; you can always request this in your user AGENTS.md or project
AGENTS.md files, see [](./agents_md.md) and [](./writing_tests.md).
Add regression tests first, then fix. High end models and
{term}`harnesses <harness>` might do this for you; you can always request this
in your user AGENTS.md or project AGENTS.md files, see [](./agents_md.md) and
[](./writing_tests.md).
```

## Exercise
Expand Down
3 changes: 2 additions & 1 deletion content/week02_agents/inspection.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ history and trace through to find answers.
You can ask it to record artifacts instead of just answering.

```{tip}
Harnesses have a way to copy the last response in markdown. Usually `/copy` or a similar shortcut.
Harnesses have a way to copy the last response in markdown. Usually `/copy` or a
similar shortcut.
```

## Watch it work
Expand Down
11 changes: 7 additions & 4 deletions content/week02_agents/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ converging on the same repos and even identical features. The OpenClaw
repository itself became the most famous victim: it went from about 2 PRs per
week in December 2025 to about 3,400 per week by February 2026, and the merge
rate fell from roughly 48% to under 10%. One contributor opened 106 PRs in a
single day, with a median gap of _three seconds_ between submissions
single day, with a median gap of *three seconds* between submissions
([Greptile's statistical study](https://www.greptile.com/blog/prs-on-openclaw)).
Security maintainers report the same pattern with AI-generated vulnerability
reports whose submitters cannot answer follow-up questions
Expand Down Expand Up @@ -238,8 +238,9 @@ it cannot be traced back to an AI company at all, but most are happy with the
Linux kernel trailer. Knowing the model helps when reviewing.

```{tip} Claude Code
Claude Code adds itself as a coauthor by default. You can turn it off in settings, then
you are free to add the Linux style trailer in via `~/.claude/CLAUDE.md` (below).
Claude Code adds itself as a coauthor by default. You can turn it off in
settings, then you are free to add the Linux style trailer in via
`~/.claude/CLAUDE.md` (below).
```

````{tip} User configuration
Expand All @@ -261,7 +262,9 @@ Linux kernel trailer or have the AI text below marker somewhere in the
description.

```{tip} User configuration
Prefix PR descriptions and comments on PRs with the line ":robot: *AI text below* :robot:" to indicate you are an agent speaking on a user's behalf.
Prefix PR descriptions and comments on PRs with the line ":robot:
*AI text below* :robot:" to indicate you are an agent speaking on a user's
behalf.
```

Follow the golden rule (LLVM/curl): a contribution should be worth more than the
Expand Down
10 changes: 8 additions & 2 deletions content/week02_agents/new_features.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,11 @@ alternatives:
[cibuildwheel#2946](https://github.com/pypa/cibuildwheel/pull/2946)

```{note} Model choice matters when building features
This is the place to use the best model you have available. You are asking for novel code rather than a mechanical transformation, so you want the highest chance that what comes back is usable. A weak model here produces plausible-looking code that costs you far more time in review than it saved in writing.
This is the place to use the best model you have available. You are asking for
novel code rather than a mechanical transformation, so you want the highest
chance that what comes back is usable. A weak model here produces
plausible-looking code that costs you far more time in review than it saved in
writing.
```

## Validate beyond your own repo
Expand Down Expand Up @@ -176,5 +180,7 @@ not merge it from a human contributor, do not merge it from the agent.
## Exercise

```{exercise}
Take a small written spec, plan it out in plan mode, implement it in `agentic-ai-example`, and review the result. Ideas: a scatter plot artist, a log-scale axis, or axis labels/titles.
Take a small written spec, plan it out in plan mode, implement it in
`agentic-ai-example`, and review the result. Ideas: a scatter plot artist, a
log-scale axis, or axis labels/titles.
```
3 changes: 2 additions & 1 deletion content/week02_agents/profiling.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,6 @@ measurements into a suite you already have:
## Exercise

```{exercise}
Profile a slow function in `agentic-ai-example`, test two optimization ideas, and report the numbers.
Profile a slow function in `agentic-ai-example`, test two optimization ideas,
and report the numbers.
```
3 changes: 1 addition & 2 deletions content/week02_agents/reviewing.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ above. This is called Rubber Duck, and it is built into GitHub Copilot CLI;
GitHub reports that Claude Sonnet 4.6 reviewed by GPT-5.4 closed 74.7% of the
gap to Claude Opus 4.6 running alone.[^rubber-duck]

[^rubber-duck]:
[GitHub Copilot CLI combines model families for a second opinion](https://github.blog/ai-and-ml/github-copilot/github-copilot-cli-combines-model-families-for-a-second-opinion/),
[^rubber-duck]: [GitHub Copilot CLI combines model families for a second opinion](https://github.blog/ai-and-ml/github-copilot/github-copilot-cli-combines-model-families-for-a-second-opinion/),
Nick McKenna and Bartek Perz, 2026-04-06.

If you try this with matching models, they will generally just praise the work.
Expand Down
6 changes: 5 additions & 1 deletion content/week02_agents/writing_tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ This process can occur in two different contexts:
in this case, even with small models.

```{note} Model choice matters when writing tests
Writing a good test requires a model that understands the codebase and the requirements. Small models may be able to write simple tests, but often they will not be able to write a meaningful test, in the sense that it checks for the right things. Larger models are also much better at identifying edge cases and weak points, and at writing tests to check them.
Writing a good test requires a model that understands the codebase and the
requirements. Small models may be able to write simple tests, but often they
will not be able to write a meaningful test, in the sense that it checks for the
right things. Larger models are also much better at identifying edge cases and
weak points, and at writing tests to check them.
```

## Improving the test suite
Expand Down
18 changes: 11 additions & 7 deletions content/week03_testing/pytest.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,11 @@ operations on floating point numbers, and you can customize it via keyword
arguments.

```{admonition} Correct calculations
If this bothers you, there are two libraries in the standard library
that help with exact calculations: `decimal.Decimal` and `fraction.Fraction`. These
do exact arithmetic, but are many times slower and bulkier than normal floating point calculations.
99% of the time, you just learn to work around floating point limitations.
If this bothers you, there are two libraries in the standard library that help
with exact calculations: `decimal.Decimal` and `fraction.Fraction`. These do
exact arithmetic, but are many times slower and bulkier than normal floating
point calculations. 99% of the time, you just learn to work around floating
point limitations.
```

## Fixtures
Expand Down Expand Up @@ -493,9 +494,12 @@ more running tips.

```{admonition} Further reading and useful links
* [Scikit-HEP Developer Pages](https://scikit-hep.org/developer/pytest)
* [Test and Code](https://testandcode.com): a podcast on testing and related topics
* [The Good Research Code Handbook](https://goodresearch.dev): General resource with a strong focus on testing
* [Research Software Engineering with Python](https://merely-useful.tech/py-rse/): Also has a testing section.
* [Test and Code](https://testandcode.com): a podcast on testing and related
topics
* [The Good Research Code Handbook](https://goodresearch.dev): General resource
with a strong focus on testing
* [Research Software Engineering with Python](https://merely-useful.tech/py-rse/):
Also has a testing section.
```

[hypothesis]: https://hypothesis.readthedocs.io
Expand Down
1 change: 0 additions & 1 deletion content/week03_testing/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ Here's a non-exhaustive list of some types of testing:
- Static "testing" (**static checking** is the more common term) will be covered
later. With this, you do not need to run the code. Dynamic testing (often just
called **testing**) runs your code.

- **Black box**: You can't "see inside" the unit you are testing, and have to
just test input/output.
- **White box** (really a bright box or clear box, IMO): You can "see inside",
Expand Down
4 changes: 2 additions & 2 deletions content/week04_package/using_packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ packages (often but not always with matching names).

All systems have an environment specification, something like this:

```
```text
requests
rich >=9.8
```
Expand Down Expand Up @@ -223,7 +223,7 @@ happened to me with `IPython` and `jedi`, by the way). How do you recover a
working version without going back to your computer? With a lock file! This
would look something like this:

```
```text
requests ==2.25.1
rich ==9.8.0
typing-extensions ==3.7.4
Expand Down
2 changes: 1 addition & 1 deletion content/week05_ci/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ $ sphinx-quickstart docs
You can answer the questions, and it will set up a docs folder. A classic
starting docs folder looks like this:

```
```text
- docs
- make.bat
- Makefile
Expand Down
15 changes: 8 additions & 7 deletions content/week06_compiled/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ When a code crashes it usually writes out a cryptic error message
- log of a number less or equal to zero

- Does not always crash your code! (depends on compilation and system settings)

- The code can keep going for a long time with `NaN` or `inf` values

- `SIGSEGV`: segmentation violation (see “man 7 signal”)
Expand Down Expand Up @@ -79,7 +80,7 @@ x[345] = 0.0; // panics at run-time
- No space left on disk
- `checkquota` will check for memory and inodes overflow

```
```text
$ checkquota
Storage/size quota filesystem report for user: rt3504
Filesystem Mount Used Limit MaxLim Comment
Expand Down Expand Up @@ -237,7 +238,7 @@ All compilers accept the `-g` option.
- where
- info stack

```
```text
$ apropos debug
__after_morecore_hook (3) - malloc debugging variables
__free_hook (3) - malloc debugging variables
Expand Down Expand Up @@ -581,7 +582,7 @@ pdb.set_trace()

- Use `help` to see the commands

```
```text
(base) ➜ ~ ./map2deb.py Work/tom/velx_00001.map
Reading Work/tom/velx_00001.map
> /Users/rt3504/map2deb.py(21)<module>()
Expand All @@ -605,7 +606,7 @@ exec pdb

Let's see another example

```
```text
(base) ➜ ~ ./map2deb.py Work/tom/velx_00001.map
Reading Work/tom/velx_00001.map
> /Users/rt3504/map2deb.py(21)<module>()
Expand Down Expand Up @@ -727,7 +728,7 @@ int main() {
We can compile this code using the `-g` option but nothing will be detected both
at compilation time and at run time.

```
```text
$ g++ -g ml.cpp -o ml
$ ./ml
```
Expand All @@ -736,7 +737,7 @@ Using the `top` command at several times, one can see the virtual memory (`VIRT`
below) slowly increasing from slightly less than 0.,5GB to more than 14GB and
counting. With more than 200 loops, the code would have crashed.

```
```text
$ top -n 1 | grep -B1 ml
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3092916 rt3504 20 0 4316088 81436 2232 R 94.4 0.0 0:02.29 ml
Expand Down Expand Up @@ -847,7 +848,7 @@ The `ddt` debugger is a good option for C/C++. See web page

Just type:

```
```text
$ ddt a.out
```

Expand Down
2 changes: 1 addition & 1 deletion content/week06_compiled/rust_example/compiled.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ warning: `foo` (bin "foo" test) generated 1 warning (run `cargo clippy --fix --b
```

> Note: you might not have `cargo-clippy` if you installed Rust minimally. See
> https://doc.rust-lang.org/stable/clippy/installation.html for info if so.
> <https://doc.rust-lang.org/stable/clippy/installation.html> for info if so.

This will run the checker (clippy) on all targets (including the test target).
However, not much is enabled by default. Add the following to your `Cargo.toml`:
Expand Down
4 changes: 3 additions & 1 deletion content/week07_parallel/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ these exist for `put` as well. And, like locks, you can end up with deadlocks if
you are not careful.

```{admonition} Error checking
This example will swallow errors if you play with it and make a mistake. To fix that, you need to save the returned values from the `.submit(...)`'s, and then call `.result()` on them; that will reraise the exception in the current thread.
This example will swallow errors if you play with it and make a mistake. To fix
that, you need to save the returned values from the `.submit(...)`'s, and then
call `.result()` on them; that will reraise the exception in the current thread.
```

## Barrier
Expand Down
Loading