From 53f7be94537446a44ae27663799d17463b2785c7 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" Date: Thu, 15 Oct 2026 09:50:10 +0100 Subject: [PATCH] docs(repo): AGENTS.md, recording the traps that are invisible until they bite Instructions for coding agents, loaded at startup by the agents.md convention. Two things this session measured the hard way: - renv.lock and ci.yml's two hardcoded R-package verification lists are coupled: removing a package from the lock fails CI at install verification, nowhere near the code that stopped using it (JoshuaJewell/MetaManifold-WebUI#57). Any lock change must grep .github/workflows/ci.yml for the package name and update both lists in the same commit. And tibble cannot leave the lock while dada2 is in it: dada2 -> ggplot2 -> tibble is dada2's own chain, and the lock's Requirements arrays are not evidence against it. - commit signing needs the SSH agent (the fixed socket at /tmp/lcb-ssh-agent.sock, exported by ~/.profile when it exists); a non-interactive shell cannot prompt for the passphrase, and disabling signing to work around it is how unsigned commits happen. The root-shape allowlist gains AGENTS.md: the convention only loads it from the root, so it cannot live under .github/ with the other health files. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- AGENTS.md | 35 ++++++++++++++++++++++++++++++++++ test/unit/test_install_pins.jl | 5 +++++ 2 files changed, 40 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..d4164769 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,35 @@ +# AGENTS.md + +Instructions for coding agents working in this repository. Read the contribution +rules in `.github/CONTRIBUTING.md` first; this file records only the traps that +are invisible until they bite. + +## renv.lock and CI's hardcoded R-package lists are coupled + +CI installs R from `renv.lock` (`renv::restore()`), but `.github/workflows/ci.yml` +names the expected packages in TWO hardcoded verification lists: + +- the `Install R packages` step's `require()` check ("failed to install"), and +- the `Verify R packages visible from RCall` step. + +Removing a package from `renv.lock` therefore fails the run at install +verification, nowhere near the code that stopped using it. MEASURED on +JoshuaJewell/MetaManifold-WebUI#57 (2026-10-15): dplyr left the lock and both +checks failed until the lists were updated in the same PR. Whenever a change +touches `renv.lock`, grep `.github/workflows/ci.yml` for every added or removed +package name and update both lists in the same commit. + +Corollary, measured the same way: `tibble` cannot leave the lock while dada2 is +in it. `dada2 -> ggplot2 -> tibble` is dada2's own dependency chain, independent +of anything this project's code does; the lock's `Requirements` arrays are not +evidence (only a handful of records carry one). + +## Commit signing needs the SSH agent, not a passphrase prompt + +`commit.gpgsign` is on, with a passphrase-protected SSH key. A non-interactive +shell has no askpass and no terminal for a prompt, so signing fails with a +misleading "failed to write commit object" unless the agent is reachable: +`SSH_AUTH_SOCK=/tmp/lcb-ssh-agent.sock` (the fixed socket; `~/.profile` exports +it when the socket exists). Never work around this with +`commit.gpgsign=false` — check the agent first with +`SSH_AUTH_SOCK=/tmp/lcb-ssh-agent.sock ssh-add -l`. diff --git a/test/unit/test_install_pins.jl b/test/unit/test_install_pins.jl index abf9e6df..93f63624 100644 --- a/test/unit/test_install_pins.jl +++ b/test/unit/test_install_pins.jl @@ -333,6 +333,11 @@ end # configs (codecov.yml) live under .github/. ".github", "bench", "config", "data", "docs", "frontend", "proofs", "scripts", "src", "test", + # Agent instructions (the agents.md convention): coding agents load + # this at startup, and it only works from the root, which is why it + # is listed here rather than living under .github/ with the other + # health files. + "AGENTS.md", # VCS housekeeping. ".gitignore", ]