A briefing packet for coding agents (e.g., Codex) working in this repository. Treat this as source-of-truth for build, test, style, and project rules. Follow these instructions before editing files or running commands.
Name: RAG Writer — Retrieval-Augmented Writing & Analysis
Purpose: Automate literature reviews, meta-analysis, and derivative content generation using a multi-agent, RAG-centric pipeline. Outputs include structured notes, reports, and publishable artifacts.
Core pillars:
- Modularity (swappable backends and steps)
- Reproducibility (deterministic builds, pinned deps, logged runs)
- Auditability (citations, provenance, config capture)
Primary language: Python (backend/CLIs). Key frameworks: FastAPI, SQLModel, Alembic, Rich (logging/UI), Textual (TUI research tools).
/ # repo root
├─ src/ # python app + packages
│ ├─ models/ # SQLModel models & Pydantic schemas
│ ├─ payloads/ # request/response payload schemas (mirrors /schemas/payloads)
│ ├─ services/ # service classes (e.g., messaging components)
│ ├─ api/ # versioned FastAPI routes (e.g., /api/v1)
│ └─ ...
├─ migrations/ # Alembic migration scripts (parallel to /src)
├─ schemas/ # shared schema definitions
│ └─ payloads/ # payload schemas imported by /src/payloads
├─ research/ # collectors, experiments, evaluation templates
├─ eval/ # evaluation configs and gold template files
├─ scripts/ # helper CLI utilities
├─ tests/ # unit/integration tests
├─ .env.example # sample environment
├─ pyproject.toml # python build metadata
├─ requirements.txt # pinned dependencies (if used)
├─ Makefile # common developer commands
└─ README.md # human-facing intro
Python version: 3.11+ recommended.
python -m venv .venv
. .venv/bin/activate
pip install -U pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
if [ -f pyproject.toml ]; then pip install -e .; fiCopy .env.example → .env and fill in as needed. Never commit secrets.
Required (typical):
DATABASE_URL— SQLModel/Alembic connection stringDATA_DIR— base path for processed corporaLOG_LEVEL— defaultINFO
make setup # install Python deps
make fmt # format with ruff + black
make lint # static checks (ruff, mypy if configured)
make test # run pytest suite
make dev # run FastAPI dev server with reloadruff check --fix . || true
black .
pytest -q
uvicorn src.api.main:app --reload --port 8000
python -m src.tool.mcp_stdioCodex and other coding agents must follow Test‑Driven Development. Write/modify tests before implementing or changing code. Treat failing tests as your guidance loop.
-
Red:
- For a new feature: write failing tests in
tests/that specify the behavior. - For a bug: reproduce with a failing regression test (name like
test_issue_<id>_regression). - Run
pytest -qand confirm failures.
- For a new feature: write failing tests in
-
Green:
- Implement the minimal code to pass the tests.
- Run
make test(orpytest -q) until green.
-
Refactor:
- Improve code structure, keep tests green.
- Run
make fmt lint testto ensure style and static checks.
-
Mirroring: tests mirror source paths (e.g.,
src/services/retrieval/foo.py→tests/services/retrieval/test_foo.py). -
Coverage gate: target ≥ 80% for changed files. If under target, add tests. Command:
pytest -q --cov=src --cov-report=term-missing
-
Property tests (where useful): use
hypothesisfor pure functions and text transforms. -
Snapshot tests: for deterministic RAG outputs (store under
tests/snapshots/). -
Network isolation: mock providers and HTTP; mark external calls with
-m external. -
Fixtures: place shared fixtures in
tests/conftest.pyandtests/fixtures/. -
Regression first: any discovered bug must first land as a failing test.
- If tests fail, read the traceback, locate the function, and iterate.
- If
ruff/mypyfail, fix style/types before pushing. - Commit tests and implementation together; PR description must note new/changed tests.
- Mutation tests: (e.g.,
mutmut) for critical modules. - Pre‑commit hooks: add
pre-commitwithruff,black, andpytest -q(fast subset) on commit.
- Ingestion → Chunking → Embedding → Indexing interfaces: do not change function signatures without updating adapters & tests.
- Provenance fields (
doc_id,chunk_id,source_path,page,span) must survive transformations. - Retrieval must return ranked JSON results consistently.
- Synthesis must include citations or
references[]. - Evaluation configs in
eval/must not break; add metrics incrementally.
- Python style: ruff + black defaults, 88 cols, f-strings, type hints required for public functions.
- FastAPI: dependency-injected services; no global mutable state.
- SQLModel/Alembic: one migration per schema change.
- Logging: use Rich logging factory; no raw
print(). - Errors: raise typed exceptions with context.
- Directory discipline: core logic in
src/; side effects isolated inservices/. - Variable/Function names: use descriptive variable and function names rather than cryptic ones, favor readable code over excessive consicion.
DO NOT MAKE CODING STYLE UPDATES TO LINES OTHER THAN THOSE CHANGING TO FULFILL THE REQUIREMENTS OF THE CURRENT TASK UNLESS THE CURRENT TASK SPECIFIES REFACTORING OVER ALL OR A SUBSET OF THE SOURCE FILES. UNNECESSARY CHANGES CAN RESULT IN UNNECESSARY MERGE CONFLICTS WHEN MULTIPLE CODING TASKS ARE HANDLED IN PARALLEL
Docstrings: Google or NumPy style.
We practice Test Driven Development (TDD). Codex and other coding agents must always:
- Write or update tests first that describe the desired behavior or bug fix.
- Run
pytest -qand observe failures. - Implement the minimal code changes to make the new tests pass.
- Re-run all tests and ensure the full suite is green.
Guidelines:
- For every new function/class, create a corresponding test file in
tests/mirroring the source path. - For bug fixes, add regression tests that fail under the old code.
- Do not submit PRs without matching tests.
Run:
pytest -q
pytest -q -m "not external" # default in CIFeedback loop: Agents must interpret failing test output as self‑feedback, iterating until all tests pass locally before proposing changes.
- Do not commit raw PDFs or proprietary datasets.
- Redact PII in stored chunks.
- Secrets in
.env, not code.
-
Branches:
feat/…,fix/…,docs/…,chore/…. -
Conventional commits enforced.
-
PRs must:
- Pass
make fmt lint test - Document migrations or breaking changes
- Pass
You may:
- Run commands in Sections 3–4.
- Edit code under
src/,scripts/,tests/.
You must:
- Follow the TDD protocol in §4.1 (write/modify tests first; ensure red→green→refactor).
- Pass
make fmt lint testbefore proposing patches. - Preserve contracts in Section 5.
- Update this file if commands/structure/env vars change.
You must NOT:
- Commit secrets or binaries.
- Strip provenance fields from outputs. **
- Commit secrets or binaries.
- Strip provenance fields from outputs.
- Lint + tests run on PRs.
- CI green is required before merge.
These are common development playbooks for adding or modifying functionality.
Add a new ingestion loader
- Implement
src/services/ingestion/<name>_loader.pywithload()→Iterable[Doc]. - Register in ingestion factory.
- Add tests under
tests/ingestion/test_<name>_loader.py.
Add a retriever strategy
- Implement
src/services/retrieval/<name>.pywithretrieve(query, k, …). - Wire into strategy registry.
- Add tests under
tests/retrieval/.
Add an evaluation metric
- Create
eval/metrics/<metric>.py. - Add gold examples in
eval/data/. - Write pytest assertions for correctness.
The project also defines YAML playbooks that orchestrate multi-stage RAG workflows.
Format example:
- section: "1B1"
task: "Define AI literacy for teachers"
instruction: "Write a 3–4 paragraph overview..."Fields:
section— identifier (ties to book chapter/outline)task— description of what the agent should doinstruction— detailed prompt for generation
Playbooks live in eval/ or research/ and are consumed by orchestration scripts. Agents must preserve field names and structure.
The research/ directory contains experimental CLIs and TUIs (Textual-based).
Example: collector.py
- A Textual TUI app for capturing article metadata and notes.
- Key class:
ArticleFormApp(App). - Common issues: ensure correct
LinkClickedimport from Textual (textual.widgets.Linkevents may differ by version).
To run:
python research/collector.pyAgents extending these tools should:
- Follow Textual 0.5+ API conventions.
- Keep event handler signatures aligned with framework imports.
- Provide minimal fixtures for tests under
tests/research/.
- Python:
snake_case.py; classes:PascalCase; functions/vars:snake_case. - Test files:
tests/<pkg>/test_<module>.py. - Configs: YAML/JSON under
config/or alongside feature.
- Primary owner: @pfahlr
Add a new ingestion loader
- Create
src/services/ingestion/<name>_loader.pyexposingload(path_or_url, **kwargs) -> Iterable[Doc]. - Register it in the ingestion factory/registry.
- Add tests under
tests/ingestion/test_<name>_loader.pywith small fixtures.
Add a retriever strategy
- Implement
src/services/retrieval/<name>.pywithretrieve(query: str, k: int = 10, **kwargs) -> list[Hit]. - Wire it into the strategy registry and config.
- Add tests + a small benchmark in
tests/retrieval/.
Add an evaluation metric
- Create
eval/metrics/<metric>.pyand register it. - Add golden examples in
eval/data/with expected JSON outputs. - Write
pytestfor metric correctness.
Your YAML playbooks orchestrate multi‑stage operations (e.g., chunk → embed → retrieve → synthesize). Codex should generate/modify these files rather than hard‑coding pipelines.
# eval/jobs/1b1.yaml (example)
section: "1B1"
task: "Define AI literacy for teachers"
instruction: |
Write a 3–4 paragraph overview covering core skills and understandings.id: "job-001"
section: "1.B.1"
track: "education"
stages:
- name: chunk
params: { strategy: recursive, max_tokens: 1200 }
- name: embed
params: { provider: openai, model: text-embedding-3-large }
- name: retrieve
params: { k: 12, hybrid: true }
- name: synthesize
params: { style: "teacher-friendly", cite: inline }
outputs:
- type: markdown
path: "out/chapters/ch1/1b1.md"
metadata:
sourceset: "edu-core-2025-08"
references: []- Place jobs under
eval/jobs/(or the directory you choose and document here). - File names: lowercase with dots/dashes, e.g.,
1a1a.yaml,1b1.yaml. - Each stage must map to a registered pipeline step in
src/services/. - Parameters are validated; add schema tests in
tests/eval/test_job_schema.py. - Job outputs should include provenance (citations or
references[]).
# run a single job
python -m scripts.run_job eval/jobs/1b1.yaml
# run all jobs in a directory
python -m scripts.run_job --glob 'eval/jobs/*.yaml'Location: research/collector.py (Textual 5.x UI for manual article capture/annotation).
# from repo root
python research/collector.py
# or
python -m research.collector- Python 3.11+
textual(v5.x),rich, and any parsers you enable
- Event class names and handlers changed across Textual versions.
- If you see
NameError: LinkClicked, ensure you import the correct event symbol for your installed version and use the current handler pattern (e.g., decorators like@on(...)or the appropriateon_*method signature). - Prefer consulting the versioned API docs for 5.x and updating the handler to match the widget/event you use.
- Keep UI state handling isolated; avoid global state.
- Add fixtures for CLI/UI behaviors under
tests/research/. - Provide small sample inputs in
research/fixtures/.
Reminder for agents: If you change any command or directory here, reflect that change in this file as part of the patch. This file is authoritative for future runs.
-
create a corresponding target in
Makefile -
update the
make helpoutput inMakefile -
update
README.mddocumenting all means of invoking the script- individual scripts:
CLI Usage > Scripts Overview- follow format used on existing entries - make operations not 1:1 with a scripts+options:
Makefile Usage > Core Workflow TargetsandMakefile Usage > Advanced Makefile Features - CLI commands:
CLI Commands (src/cli/commands.py) > [various sections]
- individual scripts:
-
update
/docs/rag_writer.1with all new commands
When adding anything that defines a modular interface where additional components can be created that follow a specific pattern.
- document the details in
README.mdunderREADME.md:## 😵💫 Miscellaneous
When defining any classes, inheritance based code, or function libraries update README.md:## 💾 Classes and Function Libraries
- document the class interface and inheritance tree, member variables, methods, parameters, and return type
- document the list of functions, parameters, and return type
- a link to the library documentation
- usage example demonstrtating one way it is used in this project
docker-composecommands
- name
- default value
- references to locations in source that access them
When defining any new system that operates using yaml or any such configuration based operation document this in README.md
- document the structure of the yaml files
README.md:## 🛠️ YAML Configuration Files - document how they interact with the program operation
When defining new Model Context Protocol (MCP) Tools update README.ms: ## 🧩 Tool Agent Schema section
See docs/MCP.md for how to run HTTP/STDIO servers, the full
*.tool.yaml reference, JSON contracts for subprocess tools, prompt
registry format, determinism guarantees, and copy‑paste examples.
- When in doubt search the websites that are available to you. The answer to your question is probably there, and if not... ask for clarification before proceeding.
MCP (Model Context Protocol): MCP is an open-source standard for connecting AI applications to external systems. Using MCP, AI applications like Claude or ChatGPT can connect to data sources (e.g. local files, databases), tools (e.g. search engines, calculators) and workflows (e.g. specialized prompts)—enabling them to access key information and perform tasks. Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect electronic devices, MCP provides a standardized way to connect AI applications to external systems. MODEL CONTEXT PROTOCOL WEBSITEMODEL CONTEXT PROTOCOL WIKIPEDIA