From 0a904cb88bb8626a801070dce10782f870aafabd Mon Sep 17 00:00:00 2001 From: Spencer Bryngelson Date: Sat, 10 Oct 2026 22:38:37 -0400 Subject: [PATCH] Check staged docs for date footers; say what precheck skips A local docs build writes 'Page last updated' into every page in the source tree, generated ones included, so the footer check failed precheck after any docs build. Read the index of tracked pages instead: only a staged footer freezes a date. precheck skips the rendering and Fortran-compile unit tests that CI's toolchain lint runs, so it is not the same gate. Say so in the index and contributing.md. --- .claude/CLAUDE.md | 2 +- docs/documentation/contributing.md | 2 +- toolchain/mfc/lint_docs.py | 21 +++++++++++++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index b1321dcbc..5523423f4 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -12,7 +12,7 @@ It holds policy and pointers only; facts live in the linked docs, and `./mfc.sh * Load a compiler and MPI before building. On a supported cluster, `source ./mfc.sh load -c -m ` loads a known-working module set. Pass both flags; omitting either waits for interactive input. Computer slugs are the first column of `toolchain/modules`; elsewhere, `module load` the equivalents * Agent shell tools run each command in a fresh shell, so a one-off `module load` or `source ./mfc.sh load` is gone by the next command. Chain it (`source ./mfc.sh load -c p -m g && ./mfc.sh build -j 8`) or put the steps in a script * Running mfc.sh commands can create a lock file in build/ that is sticky, be careful (`toolchain/mfc/lock.py`) - * Run `./mfc.sh precheck` before pushing; it runs the same lint gate as CI + * Run `./mfc.sh precheck` before pushing; it runs the CI lint gate except the slow rendering and Fortran-compile unit tests * Iterate small: `./mfc.sh build -t simulation` builds one target; `./mfc.sh test --only ` runs one test; `./mfc.sh test --select-enforce` runs only the tests whose coverage touches your changed files * Programming and Design: * New code should follow the DRY principle and also make side-effect code DRY as well diff --git a/docs/documentation/contributing.md b/docs/documentation/contributing.md index 5230abe94..d86d61fef 100644 --- a/docs/documentation/contributing.md +++ b/docs/documentation/contributing.md @@ -802,7 +802,7 @@ Every push to a PR triggers CI. Understanding the pipeline helps you fix failure ### Lint Gate (runs first, blocks the build and test jobs) -All six checks must pass before any builds start (`./mfc.sh precheck` runs them locally, plus example-case validation): +All six checks must pass before any builds start. `./mfc.sh precheck` runs them locally, plus example-case validation, but skips the slow rendering and Fortran-compile unit tests in the toolchain lint: 1. **Formatting** — `./mfc.sh format` must leave no diff 2. **Spelling** — `./mfc.sh spelling` diff --git a/toolchain/mfc/lint_docs.py b/toolchain/mfc/lint_docs.py index 56c598281..e86b24d1d 100644 --- a/toolchain/mfc/lint_docs.py +++ b/toolchain/mfc/lint_docs.py @@ -847,13 +847,22 @@ def check_module_categories(repo_root: Path) -> list[str]: def check_page_date_footers(repo_root: Path) -> list[str]: - """Check that no doc carries a committed last-updated footer (docs/inject-dates.py adds it at build time).""" - doc_dir = repo_root / "docs" / "documentation" + """Check that no tracked doc is staged with a last-updated footer (docs/inject-dates.py adds it at build time). + + Reads the index, not the working tree: a local docs build writes footers into every page, and only a staged one + would freeze its date. + """ + import subprocess + + try: + tracked = subprocess.run(["git", "ls-files", "docs/documentation/*.md"], capture_output=True, text=True, cwd=repo_root, check=True).stdout.split() + except (FileNotFoundError, subprocess.CalledProcessError): + return [] errors = [] - for md_file in sorted(doc_dir.glob("*.md")): - if "Page last updated:" in md_file.read_text(encoding="utf-8"): - rel = md_file.relative_to(repo_root) - errors.append(f" {rel} contains a 'Page last updated' footer, which freezes its date. Fix: remove it (the docs build adds it from git history)") + for rel in tracked: + staged = subprocess.run(["git", "show", f":{rel}"], capture_output=True, text=True, cwd=repo_root, check=False).stdout + if "Page last updated:" in staged: + errors.append(f" {rel} is staged with a 'Page last updated' footer, which freezes its date. Fix: drop the footer (the docs build adds it from git history)") return errors