Skip to content

Commit 249d1cb

Browse files
Update CLAUDE.md with selective soul conventions
Filter by applies_when frontmatter. Only include conventions relevant to this repo. Frontmatter stripped from output. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ffe81e0 commit 249d1cb

1 file changed

Lines changed: 8 additions & 291 deletions

File tree

CLAUDE.md

Lines changed: 8 additions & 291 deletions
Original file line numberDiff line numberDiff line change
@@ -30,296 +30,6 @@ geometry column may be named `geom` not `geometry`
3030

3131
<\!-- BEGIN SOUL CONVENTIONS — DO NOT EDIT BELOW THIS LINE -->
3232

33-
# Bookdown Conventions
34-
35-
Standards for bookdown report projects across New Graph Environment.
36-
37-
## Template Repos
38-
39-
These are the canonical references. Child repos inherit their structure and patterns.
40-
41-
- [mybookdown-template](https://github.com/NewGraphEnvironment/mybookdown-template) — General-purpose bookdown starter
42-
- [fish_passage_template_reporting](https://github.com/NewGraphEnvironment/fish_passage_template_reporting) — Fish passage reporting template
43-
44-
When in doubt, match what the template does. When the template and production repos disagree, production wins — update the template.
45-
46-
## Project Structure
47-
48-
```
49-
project/
50-
├── index.Rmd # Master config, YAML params, setup chunks
51-
├── _bookdown.yml # book_filename, output_dir: "docs"
52-
├── _output.yml # Gitbook, pagedown, pdf_book config
53-
├── 0100-intro.Rmd # Chapter numbering: 4-digit, 100s increment
54-
├── 0200-background.Rmd
55-
├── 0300-methods.Rmd
56-
├── 0400-results.Rmd
57-
├── 0500-*.Rmd # Discussion/recommendations
58-
├── 0800-appendix-*.Rmd # Appendices (site-specific in fish passage)
59-
├── 2000-references.Rmd # Auto-generated from .bib
60-
├── 2090-report-change-log.Rmd # Auto-generated from NEWS.md
61-
├── 2100-session-info.Rmd # Reproducibility
62-
├── NEWS.md # Changelog (semantic versioning)
63-
├── scripts/
64-
│ ├── packages.R # Package loading (renv-managed)
65-
│ ├── functions.R # Project-specific functions
66-
│ ├── staticimports.R # Auto-generated from staticimports pkg
67-
│ ├── setup_docs.R # Build helper
68-
│ └── run.R # Local build (gitbook + PDF)
69-
├── fig/ # Figures (organized by chapter or type)
70-
├── data/ # Project data
71-
├── docs/ # Rendered output (GitHub Pages)
72-
├── renv.lock # Locked dependencies
73-
└── .Rprofile # Activates renv
74-
```
75-
76-
## Setup Chunk Pattern
77-
78-
Every `index.Rmd` follows this setup sequence. Order matters.
79-
80-
```r
81-
# 1. Gitbook vs PDF switch
82-
gitbook_on <- TRUE
83-
84-
# 2. Knitr options
85-
knitr::opts_chunk$set(
86-
echo = identical(gitbook_on, TRUE), # Show code only in gitbook
87-
message = FALSE, warning = FALSE,
88-
dpi = 60, out.width = "100%"
89-
)
90-
options(scipen = 999)
91-
options(knitr.kable.NA = '--')
92-
options(knitr.kable.NAN = '--')
93-
94-
# 3. Source in order: packages → static imports → functions → data
95-
source('scripts/packages.R')
96-
source('scripts/staticimports.R')
97-
source('scripts/functions.R')
98-
```
99-
100-
Responsive settings by output format:
101-
102-
```r
103-
# Gitbook
104-
photo_width <- "100%"; font_set <- 11
105-
106-
# PDF (paged.js)
107-
photo_width <- "80%"; font_set <- 9
108-
```
109-
110-
## YAML Parameters
111-
112-
Parameters live in `index.Rmd` frontmatter (not a separate file). Child repos override by editing these values.
113-
114-
```yaml
115-
params:
116-
repo_url: 'https://github.com/NewGraphEnvironment/repo_name'
117-
report_url: 'https://www.newgraphenvironment.com/repo_name/'
118-
update_packages: FALSE
119-
update_bib: TRUE
120-
gitbook_on: TRUE
121-
```
122-
123-
Fish passage repos add project-specific params (`project_region`, `model_species`, `wsg_code`, update flags for forms). These are project-specific — don't add them to the general template.
124-
125-
## Chunk Naming
126-
127-
Embed context and purpose in chunk names. The principle is universal; the codes are project-specific.
128-
129-
**Pattern:** `{type}-{system}-{description}`
130-
131-
| Type | Examples |
132-
|------|---------|
133-
| Tables | `tab-kln-load-int-yr`, `tab-sites-sum`, `tab-wshd-196332` |
134-
| Figures | `plot-wq-kln-quadratic`, `map-interactive`, `map-196332` |
135-
| Photos | `photo-196332-01`, `photo-196332-d01` (dual layout) |
136-
137-
## Cross-References
138-
139-
Bookdown auto-prepends `fig:` or `tab:` to chunk names.
140-
141-
- **Tables:** `Table \@ref(tab:chunk-name)`
142-
- **Figures:** `Figure \@ref(fig:chunk-name)`
143-
144-
No `fig:` or `tab:` prefix in the chunk label itself — bookdown adds it.
145-
146-
## Table Caption Workaround
147-
148-
Interactive tables (DT) can't use standard bookdown captions. Use the `my_tab_caption()` function from `staticimports.R`.
149-
150-
**Pattern:** Separate `-cap` chunk from table chunk.
151-
152-
```r
153-
# Caption chunk — must use results="asis"
154-
{r tab-sites-sum-cap, results="asis"}
155-
my_caption <- "Summary of fish passage assessment procedures."
156-
my_tab_caption()
157-
```
158-
159-
```r
160-
# Table chunk — renders the DT
161-
{r tab-sites-sum}
162-
data |> my_dt_table(page_length = 20, cols_freeze_left = 0)
163-
```
164-
165-
`my_tab_caption()` auto-grabs the chunk label via `knitr::opts_current$get()$label` and wraps it in HTML caption tags that bookdown can cross-reference.
166-
167-
## Photo Layout
168-
169-
Separate prep chunk (find the file) from display chunk (render it).
170-
171-
```r
172-
# Prep — find the photo
173-
{r photo-196332-01-prep}
174-
my_photo1 <- fpr::fpr_photo_pull_by_str(str_to_pull = 'ds_typical_1_')
175-
my_caption1 <- paste0('Typical habitat downstream of PSCIS crossing ', my_site, '.')
176-
```
177-
178-
```r
179-
# Gitbook — full width
180-
{r photo-196332-01, fig.cap=my_caption1, out.width=photo_width, eval=gitbook_on}
181-
knitr::include_graphics(my_photo1)
182-
```
183-
184-
```r
185-
# PDF — side by side with 1% spacer
186-
{r photo-196332-d01, fig.show="hold", out.width=c("49.5%","1%","49.5%"), eval=identical(gitbook_on, FALSE)}
187-
knitr::include_graphics(my_photo1)
188-
knitr::include_graphics("fig/pixel.png")
189-
knitr::include_graphics(my_photo2)
190-
```
191-
192-
## Bibliography
193-
194-
**`references.bib` is auto-generated — never edit it manually.** On each build, `rbbt::bbt_write_bib()` scans all `.Rmd` files for `@citekey` references, pulls the BibTeX from Zotero's Better BibTeX, and overwrites `references.bib`. Any manual additions will be lost on the next build.
195-
196-
To add a reference: add it to the shared Zotero group library, use its BBT citation key (`@key`) in the `.Rmd` text, and build. rbbt handles the rest.
197-
198-
```yaml
199-
bibliography: "`r rbbt::bbt_write_bib('references.bib', overwrite = TRUE)`"
200-
biblio-style: apalike
201-
link-citations: no
202-
```
203-
204-
When `update_bib: FALSE` in params, the build uses the existing `references.bib` without regenerating — useful for offline builds or CI where Zotero isn't running.
205-
206-
Auto-generate package citations:
207-
208-
```r
209-
knitr::write_bib(c(.packages(), 'bookdown', 'knitr', 'rmarkdown'), 'packages.bib')
210-
```
211-
212-
Use `nocite:` in YAML to include references not cited in text.
213-
214-
## Acknowledgement & AI Disclosure
215-
216-
`index.Rmd` contains two separate front-matter sections after the setup chunks:
217-
218-
### Acknowledgement {.front-matter .unnumbered}
219-
220-
Three parts, in order:
221-
222-
1. **Personal connection to land** (template-level, same across all reports):
223-
> At New Graph Environment, we understand our well-being as inseparable from the health of the land and waters we work within. When we care for ecosystems, we care for ourselves and for the communities connected to them. This relationship is not metaphorical — it is the foundation of our practice.
224-
225-
2. **Colonial acknowledgement** (template-level):
226-
> Modern civilization has a long journey ahead to acknowledge and address the historic and ongoing impacts of colonialism...
227-
228-
3. **Territorial acknowledgement** (project-specific, must be edited per report): Name the Nations, governance systems, watersheds, and species relevant to the project. Do not use a generic office-location acknowledgement — tie it to the territory where the work happens. See the Wedzin Kwa chinook example for the pattern.
229-
230-
4. **Funding and partners** (project-specific).
231-
232-
### AI Disclosure
233-
234-
Do not use a `#` heading for the disclosure — this creates a separate chapter page in gitbook. Instead, add it to the YAML `date:` field so it renders in the title block:
235-
236-
```yaml
237-
date: |
238-
|
239-
| Version X.X.X DRAFT `r format(Sys.Date(), "%Y-%m-%d")`
240-
|
241-
| *Claude Sonnet 4.6 (Anthropic) assisted with literature synthesis, drafting, and technical writing. All scientific interpretation, data analysis, and conclusions are the responsibility of the authors.*
242-
```
243-
244-
**Wording principle:** Be accurate about what the LLM did. It assisted with drafting and synthesis — it did not make scientific interpretations or conclusions. Do not say "independently verified by the authors" (redundant) or attribute "ecological assessments" to the LLM.
245-
246-
For regulatory/EGBC-stamped work, use the extended disclaimer from `soul/research/20260212_ai_disclosure_research.md`. See NewGraphEnvironment/mybookdown-template#89.
247-
248-
## Conditional Rendering (Gitbook vs PDF)
249-
250-
A single boolean `gitbook_on` controls output format throughout.
251-
252-
```r
253-
# Show only in gitbook
254-
{r map-interactive, eval=gitbook_on}
255-
256-
# Show only in PDF
257-
{r fig-print-only, eval=identical(gitbook_on, FALSE)}
258-
259-
# Conditional inline content
260-
`r if(identical(gitbook_on, FALSE)) knitr::asis_output("This report is available online...")`
261-
262-
# Page breaks for PDF only
263-
`r if(gitbook_on){knitr::asis_output("")} else knitr::asis_output("\\pagebreak")`
264-
```
265-
266-
## Versioning and Changelog
267-
268-
Reports use MAJOR.MINOR.PATCH versioning with a `NEWS.md` changelog.
269-
270-
**Version in `index.Rmd` YAML:**
271-
```yaml
272-
date: |
273-
|
274-
| Version 1.1.0 DRAFT `r format(Sys.Date(), "%Y-%m-%d")`
275-
```
276-
277-
**NEWS.md format:**
278-
```markdown
279-
## 1.1.0 (2026-02-17)
280-
281-
- Add feature X
282-
- Fix issue Y ([Issue #N](https://github.com/Org/repo/issues/N))
283-
```
284-
285-
**Auto-append as appendix** via `my_news_to_appendix()` in `staticimports.R`:
286-
```r
287-
news_to_appendix(md_name = "NEWS.md", rmd_name = "2090-report-change-log.Rmd")
288-
```
289-
290-
**Convention:**
291-
- Bump version in `index.Rmd` and add NEWS entry for every commit to main that changes report content
292-
- Tag releases: `git tag -a v1.1.0 -m "v1.1.0: Brief description"`
293-
- MAJOR: structural changes, new chapters, methodology changes
294-
- MINOR: new content, figures, tables, discussion sections
295-
- PATCH: prose fixes, corrections, formatting
296-
297-
## COG Viewer Embedding
298-
299-
Always use `ngr::ngr_str_viewer_cog()` — never hardcode viewer iframes.
300-
301-
```r
302-
knitr::asis_output(ngr::ngr_str_viewer_cog("https://bucket.s3.us-west-2.amazonaws.com/ortho.tif"))
303-
```
304-
305-
The function includes a cache-busting `?v=` parameter. Bump `v` in the function default when `viewer.html` has breaking changes.
306-
307-
## Dependency Management
308-
309-
Use `renv` for reproducible package management:
310-
- `.Rprofile` activates renv on startup
311-
- `renv::restore()` installs from lockfile
312-
- `renv::snapshot()` updates lockfile after adding packages
313-
- Use `pak::pak("pkg")` to install (not `install.packages`)
314-
315-
## Known Drift
316-
317-
Production repos (2024-2025) have drifted from templates in these areas. When working in a child repo, match what that repo does, not the template:
318-
319-
- **Script naming in `02_reporting/`** — older repos use `tables.R`, `0165-read-sqlite.R`; newer repos use numbered `0130-tables.R`. Follow the repo you're in.
320-
- **Removed packages** — `elevatr`, `rayshader`, `arrow` removed from production but still in template.
321-
- **`staticimports::import()` call** — some repos skip it and source `staticimports.R` directly.
322-
- **Hardcoded vs parameterized years** — older repos hardcode years in file paths; newer repos use `params$project_year`. Prefer parameterized.
32333

32434
# Cartography
32535

@@ -409,6 +119,7 @@ drift::dft_map_interactive(classified, aoi = aoi)
409119
- For production COGs on S3, `dft_map_interactive()` serves tiles via titiler — set `options(drift.titiler_url = "...")`
410120
- See the [drift vignette](https://www.newgraphenvironment.com/drift/articles/neexdzii-kwa.html) for a worked example (Neexdzii Kwa floodplain, 2017-2023)
411121

122+
412123
# Code Check Conventions
413124

414125
Structured checklist for reviewing diffs before commit. Used by `/code-check`.
@@ -497,6 +208,7 @@ Add new checks here when a bug class is discovered — they compound over time.
497208
- New variables: update .tfvars.example
498209
- New workflows: update relevant README
499210

211+
500212
# Communications Conventions
501213

502214
Standards for external communications across New Graph Environment.
@@ -558,6 +270,7 @@ Website: www.newgraphenvironment.com
558270

559271
In HTML emails, use `<br>` tags between lines.
560272

273+
561274
# LLM Behavioral Guidelines
562275

563276
<!-- Source: https://github.com/forrestchang/andrej-karpathy-skills/main/CLAUDE.md -->
@@ -625,10 +338,10 @@ For multi-step tasks, state a brief plan:
625338

626339
Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
627340

628-
---
629341

630342
**These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.
631343

344+
632345
# New Graph Environment Conventions
633346

634347
Core patterns for professional, efficient workflows across New Graph Environment repositories.
@@ -773,6 +486,7 @@ Scripts and logs live together: `scripts/<module>/logs/`
773486
| Restoration planning | **Aquatic Restoration Planning (#5)** |
774487
| QGIS, Mergin, field forms | **Collaborative GIS (#3)** |
775488

489+
776490
# Planning Conventions
777491

778492
How Claude manages structured planning for complex tasks using planning-with-files (PWF).
@@ -869,6 +583,7 @@ If `planning/` doesn't exist in the repo, run `/planning-init` first.
869583
| `/planning-update` | Mid-session — sync checkboxes and progress |
870584
| `/planning-archive` | Issue complete — archive and create fresh active/ |
871585

586+
872587
# R Package Development Conventions
873588

874589
Standards for R package development across New Graph Environment repositories.
@@ -1102,6 +817,7 @@ When an LLM assistant modifies R package code:
1102817
Rscript -e 'devtools::check()' 2>&1 | grep -E "(ERROR|WARNING|NOTE|errors|warnings|notes)" | tail -10
1103818
```
1104819

820+
1105821
# Reference Management Conventions
1106822

1107823
How references flow between Claude Code, Zotero, and technical writing at New Graph Environment.
@@ -1227,6 +943,7 @@ Always verify downloads: `file paper.pdf` should say "PDF document", not HTML.
1227943
- NEVER cite specific numbers without verifying from the source PDF via ragnar search
1228944
- NEVER paraphrase equations — copy exact notation and cite page/section
1229945

946+
1230947
# SRED Conventions
1231948

1232949
How SR&ED tracking integrates with New Graph Environment's development workflows.

0 commit comments

Comments
 (0)