docs: dependency notes in the README

What a library ships and where, what a consumer's AGENTS.md gets and
when it is written, the section's format, and what cfg.dependencyNotes
selects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-10-31 03:18:26 +01:00
commit c2e8bf0a93
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB

View file

@ -94,6 +94,38 @@ import Crafter.LintRules;
#pragma crafter dependency "<source>" [branch "<name>" | commit "<sha>"] [project "<file>"]
```
### Dependency notes for agents
An agent working on a project reads its `AGENTS.md`, which says nothing about the libraries the project builds against unless someone copied that in by hand. A library ships it instead: an `AGENTS.consumer.md` beside its `project.cpp`, written for whoever uses the library rather than whoever works on it. When a consumer has an `AGENTS.md` beside its own `project.cpp`, `crafter-build` and `crafter-build test` keep its dependencies' notes in a section of it:
```markdown
<!-- crafter-build: dependency notes begin -->
<!-- Written by crafter-build from the AGENTS.consumer.md each dependency ships, and rewritten on every build. Edit those files, not this section; cfg.dependencyNotes in project.cpp picks which dependencies are included. -->
<!-- from https://forgejo.catcrafts.net/Catcrafts/Crafter.Math.git -->
## Crafter.Math
...
<!-- crafter-build: dependency notes end -->
```
- Each file goes in as written, under a line naming where it came from: the git URL, or for a `LocalProject` the file's path relative to the consumer. It lands among the consumer's own headings, so start it with a `##` heading that names the library.
- The section is appended the first time and rewritten in place after that, wherever it has been moved to. Edits inside it are lost on the next build; the rest of the file is never touched. The file is written only when the section changes, and an `AGENTS.md` is never created.
- The update runs after `project.cpp` loads and before anything compiles, so a build that fails still has the notes. `lint`, `format`, `run` and `clean` leave the file alone.
- An unpinned dependency's notes follow its default branch, as its code does, so the section can change on any build. Pin a `commit` to decide when.
- Unbalanced markers leave the file as it is, and a notes file that would break the section (a code block it never closes, a marker line of its own) is left out; both are reported as warnings. Markers quoted inside a fenced code block don't count.
`cfg.dependencyNotes` picks the dependencies:
| Value | Notes from |
|---|---|
| `DependencyNotes::Transitive` (default) | everything the project builds against, all the way down: its `dependencies`, its tests' dependencies and its own `#pragma crafter dependency` tooling |
| `DependencyNotes::Direct` | only the projects the project's own configurations, tests and `#pragma crafter dependency` lines name |
| `DependencyNotes::None` | none, and a section from an earlier build is removed |
Two things never count: the project's own `AGENTS.consumer.md`, and a dependency's `#pragma crafter dependency` tooling, which is about how the dependency is built, not how it is used.
## Tests
Tests live under `tests/<Name>/`. The simplest case is a single C++ file: