Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .cursor/rules/main.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
description: SwimBlocks deck-eval-parser — agent guide pointer
alwaysApply: true
---

The full repo guide is in [AGENTS.md](../../AGENTS.md). It points at the canonical org-wide
rules in [swimblocks/.github](https://github.com/swimblocks/.github). Follow the work-loop in
the canonical AGENTS.md (issue → branch → PR → hand off; agents do not self-merge).
5 changes: 5 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# GitHub Copilot instructions

The full agent / contributor guide for this repo lives in [AGENTS.md](../AGENTS.md). Read it
before suggesting changes. It points at the org-wide canonical rules in
[swimblocks/.github](https://github.com/swimblocks/.github).
62 changes: 62 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Agent guide — deck-eval-parser

Parses Canadian swimming on-deck evaluation PDFs into structured data via per-province
templates. Handles both **fillable PDFs** (form widgets, deterministic) and **scanned PDFs**
(via a local Ollama vision model). Both paths converge on the same `PageExtraction` shape,
so the merge → JSON/CSV/XLSX pipeline downstream is path-agnostic.

## Canonical rules

The cross-repo rules for any SwimBlocks project live in the [`swimblocks/.github`](https://github.com/swimblocks/.github)
standards repo. Read these first:

- [AGENTS.md](https://github.com/swimblocks/.github/blob/main/AGENTS.md) — distilled agent guide
- [CONTRIBUTING.md](https://github.com/swimblocks/.github/blob/main/CONTRIBUTING.md) —
long-form house rules
- [development.md](https://github.com/swimblocks/.github/blob/main/docs/development.md) —
setting up a new machine

Everything below is **repo-specific** — quirks that the canonical guide doesn't cover.

## Repo-specific quirks

- **Two parse paths, one shape.** Fillable PDFs go through `src/pdf_io.read_widgets` +
`src/form_extract.extract_page`. Scanned PDFs get rasterized in `src/pdf_io.rasterize_page`
and handed to the vision model in `src/vision_extract.py`. Both emit `PageExtraction`
(`meet`/`session`/`rows` dicts of `FieldValue`). Never blend the paths within a single
PDF — if any page has widgets, the whole document goes through the form-field path.
Background: [docs/architecture.md](docs/architecture.md), [docs/pdf-parsing.md](docs/pdf-parsing.md).
- **Province templates are a registry.** Each province lives in `src/templates/<id>.py` and
registers via `src/templates/__init__.py`. Today Swim Ontario is implemented; Quebec /
Alberta / BC and others are stubs that raise `NotImplementedError`. **Don't generalise** a
template hack into shared code — provincial differences are real and load-bearing. See
[docs/templates/](docs/templates/) and the per-province issues
([#20–#28](https://github.com/swimblocks/deck-eval-parser/issues?q=is%3Aissue+is%3Aopen+label%3Atemplate)).
- **Canonical field names** live in `src/schema.py` (`MEET_FIELDS`, `SESSION_FIELDS`,
`ROW_FIELDS`, `ALL_FIELDS`). Every module imports from there; **don't sprinkle string
literals** for field names.
- **PyMuPDF widget naming has gotchas.** `[NNN]` disambiguator suffixes get stripped in
`read_widgets`; the widget name in each template's `widget_field_map` is the
post-suffix-strip form. See [docs/pdf-parsing.md](docs/pdf-parsing.md) before touching
field maps.
- **Ollama is a runtime dependency.** `src/ollama_runtime.py` manages the lifecycle (auto-pull
models, start/stop). GPU tier is detected in `src/gpu_detect.py` and influences which
vision model is chosen. Don't hand-call `ollama` from elsewhere; route through the runtime.
- **Synthetic fixtures, not real PDFs.** Real eval forms contain officials' names and emails
(PII). Test fixtures under `tests/fixtures/` are generated by
`tests/fixtures/form_field/make_synthetic_fixture.py` and friends. **Never commit real
scanned forms** as test fixtures — see issue [#29](https://github.com/swimblocks/deck-eval-parser/issues/29)
for the pseudonymisation pipeline.
- **No `pyproject.toml` for ruff yet** in this repo — lint config lives in `pytest.ini` and
ruff defaults. If you add ruff config, mirror the swimblocks/.github CI workflow's
expectations.

## Where to start reading

- [`README.md`](README.md) — user-facing overview + quick-start
- [`docs/architecture.md`](docs/architecture.md) — current state, end-to-end
- [`docs/pdf-parsing.md`](docs/pdf-parsing.md) — PyMuPDF / widget specifics
- [`docs/templates/README.md`](docs/templates/README.md) — how to add a provincial template
- [`docs/design/`](docs/design/) — design docs (the *why*)
- [`src/schema.py`](src/schema.py) — canonical field constants (shared vocabulary)
- [`main.py`](main.py) — CLI entry point
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Claude Code — deck-eval-parser

Repo-specific guide and canonical org-wide rules:

@AGENTS.md
Loading