# template_prose_project — Agent Guide
## Purpose
Prose-focused exemplar demonstrating end-to-end use of
`infrastructure/prose/` and `infrastructure/reference/`. Standalone editorial
workflow — fast and offline by default. Exemplar roster:
[`projects/AGENTS.md`](../../AGENTS.md#permanent-canonical-exemplars).
Decision memory and verifier hardening follow [`docs/rules/memory_and_decision_records.md`](../../../docs/rules/memory_and_decision_records.md): use nearby `WHY:` comments only for surprising local choices, keep volatile counts generated, and add negative controls for verifier-like gates.
## Layout
```mermaid
flowchart TB
P[projects/templates/template_prose_project]
P --> SRC[src
domain orchestration]
P --> T[tests
real-data tests · no mocks]
P --> SC[scripts
thin orchestrators]
P --> M[manuscript]
P --> DOCS[docs]
P --> OUT[output
regeneratable]
P --> META[pyproject.toml · README.md ·
AGENTS.md · .gitignore]
P --> OVERLAY[domain_profile.yaml · experiment_plan.yaml ·
data/claim_ledger.yaml
advisory controls · evidence validation]
SRC --> SRC_F[config.py · pipeline/ · figures.py ·
manuscript_variables.py · report.py ·
prose_facade.py]
SC --> SC_F[run_prose_pipeline.py ·
y_generate_prose_figures.py ·
z_generate_manuscript_variables.py]
M --> M_F[config.yaml · preamble.md ·
00_abstract → 06_reproducibility.md ·
99_references.md · references.bib]
classDef d fill:#0f172a,stroke:#0f172a,color:#fff
classDef pkg fill:#1e3a8a,stroke:#0f172a,color:#fff
classDef f fill:#0f766e,stroke:#0f172a,color:#fff
class P d
class SRC,T,SC,M,DOCS,OUT pkg
class SRC_F,SC_F,M_F,META,OVERLAY f
```
## Layer contract
| Surface | Rule |
| --- | --- |
| `src/` | Domain-only: `prose_facade.py` protocols, checks, figures, reports — **zero** `infrastructure` imports |
| `scripts/run_prose_pipeline.py` | Calls `infrastructure.prose.analyze_manuscript`, then `src.pipeline.run_prose_pipeline` |
| `scripts/z_generate_manuscript_variables.py` | Calls `infrastructure.rendering.manuscript_injection` for resolved trees |
| Live counts | Link [`docs/_generated/COUNTS.md`](../../../docs/_generated/COUNTS.md) |
## Key contracts
* `src/config.py::ProjectConfig` — every knob is here. Add a new check
by adding a field to `ProseAnalysisConfig`, parsing it in
`from_dict`, and wiring it into `pipeline.run_prose_pipeline`.
* `scripts/run_prose_pipeline.py` — calls `infrastructure.prose.analyze_manuscript`,
then `src/pipeline.run_prose_pipeline` with the typed report. Returns a
:class:`ProseRunArtifacts` so the script knows where every artefact
landed.
* `src/figures.py` — pure matplotlib; takes a `ManuscriptReport` and a
`Path`, returns the saved file paths.
* `src/manuscript_variables.py` — derives substitution variables from
the JSON report; no project-specific knowledge embedded.
* `src/report.py::write_review_report` — single function that takes a
`ManuscriptReport` + `CheckResult`s and writes markdown.
* `src/pipeline::build_evidence_summary` — writes the machine-readable,
diagnostic-only evidence summary; it must not be interpreted as publication
approval.
* `domain_profile.yaml` and `experiment_plan.yaml` — declarative advisory
overlays for review gates, source policy, artifact expectations, benchmark
rubric weights, validation conditions, primary metric, baseline, and ablation.
* `data/claim_ledger.yaml` — file-backed registry of numeric claims that are
intentionally sourced from project code, manuscript examples, or generated
reports rather than manuscript variables.
These files are validation inputs only and do not run autonomous review agents.
## Run modes
| Command | Behaviour |
|---|---|
| `python scripts/run_prose_pipeline.py` | Default config; reads `manuscript/`, writes everything. |
| `… --strict` | Exit non-zero if any configured check fails. |
| `… --config other.yaml` | Use an alternative config file. |
| `… --project-root path` | Run against an isolated project root. |
## Testing
```bash
uv run pytest projects/templates/template_prose_project/tests/ -v
```
All tests run offline. Real prose inputs, real BibTeX files, real
`tmp_path` directories, real subprocess invocation of the scripts. No
mocks.
## Extending
To add a new check:
1. Edit `src/config.py::ProseAnalysisConfig` to add the new field, and add
its YAML key to `_KNOWN_PROSE_KEYS` at the top of `src/config.py` —
the strict validator rejects any key not listed there. (See the full
"To add a new knob" recipe in [`docs/faq.md`](docs/faq.md).)
2. Add a `_check_` function in `src/pipeline/checks.py`.
3. Wire it into `run_prose_pipeline` so it appears in `artifacts.checks`.
4. Add a test in `tests/test_pipeline.py` covering both `passed=True`
and `passed=False` outcomes (the existing `TestCheckUnits` class
shows the pattern).
5. Optionally surface its result in `src/report.py::write_review_report`.
To add a new figure:
1. Add a `plot_` function in `src/figures.py`.
2. Append it to `generate_all_figures`.
3. Reference the output PNG in `manuscript/03_results.md` if desired.
To target a different manuscript:
1. Edit `manuscript_dir` in `manuscript/config.yaml`.
2. Adjust `prose.target_grade_level_*` and `bibliography.fail_on_*` to
match the target audience.
3. Re-run the pipeline.
## See also
* [`README.md`](README.md) — quick reference.
* [Publishing guide](../../../docs/guides/publishing-guide.md) · [Publishing module reference](../../../infrastructure/publishing/README.md) · [Zenodo DOI strategy](../../../docs/guides/zenodo-doi-strategy.md) · [Archival targets](../../../docs/maintenance/archival-targets.md)
* [`docs/architecture.md`](docs/architecture.md) — module dependency graph.
* [`docs/quickstart.md`](docs/quickstart.md) — getting started.
* [`infrastructure/prose/AGENTS.md`](../../../infrastructure/prose/AGENTS.md) —
underlying module agent guide.
* [`infrastructure/reference/AGENTS.md`](../../../infrastructure/reference/AGENTS.md) —
bibliography agent guide.