Behavioral guidelines to reduce common LLM coding mistakes in this repo (FastAPI backend in backend/app/, Vite + React/TS SPA in frontend/src/, K8s manifests in k8s/).
Tradeoff: These guidelines bias toward caution over speed. For trivial tasks, use judgment.
Don't assume. Don't hide confusion. Surface tradeoffs.
Before implementing:
- State the placement decision out loud. "Adding this as a new endpoint on
routers/json_tools.py, a schema inschemas/json_tools.py, and a pure function inservices/." If you're not sure where it goes, ask. - If multiple interpretations exist, present them. A new "convert" tool could be another endpoint on
routers/convert.pyor a new module underrouters/codec.py— don't pick silently. - If a simpler approach exists, say so. A pure function in
services/reused by an existing route often beats a new endpoint. A tailwind class often beats a new component. - If something is unclear, stop. Common ambiguities here: which deploy topology (combined
Dockerfile, splitDockerfile.dev, or split K8s), whether the SPA needs a route entry infrontend/src/tools.ts, whether a change should also touch the slowapi rate-limit settings inbackend/app/config.py.
Minimum code that solves the problem. Nothing speculative.
- No features beyond what was asked. If the task is one tool, don't also tweak adjacent routers or pages "while I'm here."
- No abstractions for single-use code. A service function called by one router is a function, not a class hierarchy.
- No "flexibility" or "configurability" that wasn't requested. Don't add new fields to
Settingsinbackend/app/config.pyfor hypothetical env vars; don't add new ConfigMap keys ink8s/10-configmap.yamlthat nothing reads. - No error handling for impossible scenarios. Pydantic schemas in
schemas/already validate router inputs — don't re-validate the same shapes insideservices/. - If a route handler grows past ~30 lines, the work probably belongs in
services/and the handler should call it.
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
Touch only what you must. Clean up only your own mess.
When editing existing code:
- Don't "improve" adjacent routers, schemas, services, components, or formatting.
- Don't refactor patterns that aren't broken. The repo's convention is one module per tool group across
routers/,schemas/, andservices/, mirrored byfrontend/src/pages/<area>/. Match it. - Match existing style. Run
uv run ruff format .frombackend/for Python; mirror the style of neighboring.tsxfiles for TypeScript. - If you notice unrelated dead code (a stray export in
services/, a stale entry infrontend/src/tools.ts), mention it — don't delete it.
When your changes create orphans:
- Remove imports and helpers your edits left unused.
- Don't remove pre-existing dead code unless asked.
Don't auto-bump dependencies in backend/pyproject.toml or frontend/package.json beyond what the task requires. (The frontend peer-dep tree is currently clean — vite@8 and @vitejs/plugin-react@6 are compatible, so npm ci / npm install resolve without --legacy-peer-deps. Treat dep bumps as their own task.)
The test: every changed line should trace directly to the user's request.
Define success criteria. Loop until verified.
Transform tasks into verifiable goals:
- "Add validation" → write a
pytestcase inbackend/tests/test_<area>_router.pyfor the invalid input, then make it pass. - "Fix the bug" → reproduce it first in
tests/test_<area>_router.py(ortests/test_services.pyfor pure logic), then fix. - "Refactor X" →
cd backend && uv run pytestpasses before and after. - Frontend changes have no automated test layer yet. Verify by running
npm run dev(proxies/api→:8000), clicking through the affected page, and confirmingnpm run lint(which istsc --noEmit) is clean. - K8s changes →
kubectl apply -f k8s/, thenkubectl rollout status deploy/<name> -n devtoolsandkubectl get pods -n devtoolsshow Ready.
For multi-step tasks, state a brief plan:
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
These guidelines are working if: fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.