|
| 1 | +# Copilot instructions for openarmature-python |
| 2 | + |
| 3 | +This is the reference Python implementation of OpenArmature, a workflow |
| 4 | +framework for LLM pipelines and tool-calling agents. Behavior is defined by |
| 5 | +the language-agnostic specification in `openarmature-spec` and verified by |
| 6 | +conformance fixtures under `tests/conformance/`; the spec and its fixtures are |
| 7 | +the source of truth, not local style preference. |
| 8 | + |
| 9 | +## Conventions to respect when reviewing |
| 10 | + |
| 11 | +- **User-facing copy uses no em dashes.** `README.md`, `docs/**`, PR |
| 12 | + descriptions, and `examples/**` avoid the em dash (`U+2014`) as an |
| 13 | + LLM-output tell; use commas, colons, parentheses, or sentence splits instead. `src/` |
| 14 | + code comments are exempt. Do not suggest adding an em dash. New `CHANGELOG.md` |
| 15 | + entries also avoid them (older entries are intentionally left as-is). |
| 16 | + |
| 17 | +- **`examples/**` are teaching artifacts, not production code.** They |
| 18 | + deliberately use the codebase's house idioms, construct providers lazily |
| 19 | + (so importing the module opens no network client), close providers in a |
| 20 | + `finally`, carry moon-themed subject matter, and reference no spec sections. |
| 21 | + Each exposes a `build_graph()` factory (a smoke test depends on it). Prefer |
| 22 | + consistency with the sibling examples over generic style preferences. |
| 23 | + |
| 24 | +- **Documentation code snippets are illustrative** unless they live under |
| 25 | + `docs/getting-started/`, `docs/model-providers/`, or |
| 26 | + `docs/retrieval-providers/` (those are executed for drift). Concept-page |
| 27 | + snippets reference names defined out of band and are not standalone programs; |
| 28 | + do not flag them for missing imports or incompleteness. |
| 29 | + |
| 30 | +- **Typed default factories are intentional.** On a Pydantic `State`, a |
| 31 | + `list[int]` field uses `Field(default_factory=list[int])`, not a bare |
| 32 | + `default_factory=list`: strict pyright flags the bare `list` factory as |
| 33 | + `list[Unknown]` on a `list[int]` field (a `list[str]` field happens to pass). |
| 34 | + Both the typed factory and a bare `[]` default are safe here because Pydantic |
| 35 | + copies the default per instance. |
| 36 | + |
| 37 | +- **`usage = None` is the contract, not a bug.** When a provider reports no |
| 38 | + token usage, `EmbeddingResponse.usage` / `RerankResponse.usage` and the |
| 39 | + corresponding event `usage` are `None`. A mapping must never fabricate a |
| 40 | + usage record, a zero, or a client-side estimate; a malformed usage figure is |
| 41 | + treated as not-reported, not as an error. |
| 42 | + |
| 43 | +- **`input_type` is a wire no-op on symmetric embedding providers** (for |
| 44 | + example the OpenAI mapping). Setting `input_type="query"` / `"document"` |
| 45 | + keeps a pipeline portable to asymmetric providers (TEI, Cohere, Jina); it is |
| 46 | + not dead code. |
| 47 | + |
| 48 | +## Toolchain |
| 49 | + |
| 50 | +- Python `>=3.12`, strict pyright, and ruff (line length 110). A suggestion |
| 51 | + that would break strict typing or ruff formatting is not useful; the CI gate |
| 52 | + runs all three. |
| 53 | + |
| 54 | +- Provider error handling maps to the canonical error categories in |
| 55 | + `openarmature.llm.errors`. For the retrieval providers the applicable subset |
| 56 | + is: 401/403 to authentication, 404 to invalid-model, 429 to rate-limit, |
| 57 | + 400/413/422 to invalid-request, other 5xx to unavailable, and a 200 with a |
| 58 | + malformed body to `ProviderInvalidResponse`. |
| 59 | + |
| 60 | +## Generated files (do not review as hand-written) |
| 61 | + |
| 62 | +- `src/openarmature/AGENTS.md` and `src/openarmature/_patterns/` are generated |
| 63 | + by `scripts/build_agents_md.py`; edit the generator, not the output. |
0 commit comments