chore: establish standards in AGENTS.md
This commit is contained in:
commit
adcf4b9df6
4 changed files with 141 additions and 0 deletions
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# secrets
|
||||
.env
|
||||
|
||||
# python
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.venv/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
.pytest_cache/
|
||||
|
||||
# node
|
||||
node_modules/
|
||||
frontend/dist/
|
||||
|
||||
# eval: raw (unredacted) recordings never enter the repo
|
||||
eval/fixtures/raw/
|
||||
82
AGENTS.md
Normal file
82
AGENTS.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# Engineering standards
|
||||
|
||||
This file is the contract for every contributor to this repository — human or
|
||||
agent. `CLAUDE.md` is a symlink to it: one canonical standard, read by every
|
||||
tool. `ruff`, `mypy`, `eslint`, `prettier`, and `vue-tsc` enforce mechanically
|
||||
what they can; this document carries the rest.
|
||||
|
||||
## Architecture
|
||||
|
||||
Monorepo with a ports-and-adapters seam. The dependency direction is enforced
|
||||
by review:
|
||||
|
||||
```
|
||||
api → pipeline → ports ← adapters domain imports nothing app-level
|
||||
```
|
||||
|
||||
- `backend/app/domain/` — pure models and logic (`Track`, `TasteProfile`,
|
||||
fuzzy matching, profile compression). Imports nothing app-level.
|
||||
- `backend/app/ports/` — `Protocol` definitions (`MusicCatalog`,
|
||||
`Recommender`, `PlaylistWriter`).
|
||||
- `backend/app/adapters/` — implementations: `spotify/` (auth, thin httpx
|
||||
client, DTO mapping), `anthropic/` (both LLM calls), `demo/`
|
||||
(fixture-replay implementations of the same ports).
|
||||
- `backend/app/pipeline/` — the orchestrator composes the stages; stages never
|
||||
import each other.
|
||||
- Spotify JSON never escapes `adapters/spotify/mapping.py`.
|
||||
- Pipeline tunables (counts, thresholds, budgets, model id, effort, TTLs) live
|
||||
in `app/config.py` (pydantic-settings) — no magic numbers in code.
|
||||
- LLM prompts are versioned template files under `app/prompts/`, not inline
|
||||
strings.
|
||||
- `eval/scenarios.yaml` is one source of truth for three consumers: golden
|
||||
eval queries, demo fixture keys, and UI suggestion chips.
|
||||
|
||||
## Naming
|
||||
|
||||
Human-readable, descriptive, full words. Code reads as prose.
|
||||
|
||||
- Python: `snake_case` functions/variables, `PascalCase` classes,
|
||||
`UPPER_SNAKE` constants. Functions verb-first (`resolve_candidate`),
|
||||
variables noun-first (`grounded_tracks`), booleans as predicates
|
||||
(`is_grounded`, `should_stream`).
|
||||
- TypeScript/Vue: `camelCase` variables/functions, `PascalCase` components and
|
||||
`.vue` filenames, composables `use`-prefixed, types without `I`-prefix.
|
||||
- Abbreviations: only universally idiomatic ones (`id`, `url`, `api`, `db`,
|
||||
`llm`, `sse`). Never invented ones.
|
||||
- Single-letter names only in lambdas/comprehensions whose whole scope is
|
||||
≤ ~3 lines.
|
||||
- Modules named for what they contain, singular nouns. `utils.py`,
|
||||
`helpers.py`, `misc.py` are banned names.
|
||||
|
||||
## Sizing, DRY, modularity
|
||||
|
||||
- Soft cap ~300 lines per module, hard cap 500 — split by responsibility.
|
||||
Functions target ≤ ~40 lines.
|
||||
- One responsibility per module: if it needs "and" to describe, split it.
|
||||
- DRY by the rule of three: extract on the third occurrence, not the second.
|
||||
No premature abstraction, no helpers for one-shot operations, no designing
|
||||
for hypothetical future requirements.
|
||||
- Validate at boundaries only (user input, Spotify responses, LLM output);
|
||||
trust internal code — no defensive re-checking between our own modules.
|
||||
|
||||
## Comments & docstrings
|
||||
|
||||
Sparse and load-bearing:
|
||||
|
||||
- One-line docstring on every module and public function/class; add
|
||||
Args/Returns only where the signature genuinely doesn't tell the story.
|
||||
- Inline comments state only what the code cannot — constraints, API quirks,
|
||||
non-obvious whys. Never narrate the next line.
|
||||
- Banned: commented-out code, drive-by TODOs, decorative section banners.
|
||||
- Type hints everywhere; `mypy --strict` is the enforcement.
|
||||
|
||||
## Enforcement
|
||||
|
||||
- Backend: `ruff` (lint + format) everywhere. `mypy --strict` on `domain/`,
|
||||
`ports/`, `pipeline/`; default strictness on `adapters/` and `api/` —
|
||||
SDK/streaming typing archaeology is not where the effort goes. Every
|
||||
`# type: ignore` carries an error code and a reason.
|
||||
- Frontend: `eslint` + `prettier` + `vue-tsc --noEmit`; no `any`. The stream
|
||||
event types are a discriminated union mirrored against the Pydantic
|
||||
response schemas.
|
||||
- Commit messages describe the change, conventional-commit style.
|
||||
1
CLAUDE.md
Symbolic link
1
CLAUDE.md
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
AGENTS.md
|
||||
41
README.md
Normal file
41
README.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# discovery-by-llm
|
||||
|
||||
Muziekontdekking met een LLM als aanbevelingsmotor, op de Spotify Web API.
|
||||
|
||||
**These:** Spotify heeft zijn aanbevelings- en audio-intelligentielaag uit de
|
||||
API verwijderd (recommendations en audio features zijn weg voor nieuwe apps).
|
||||
Deze proof-of-concept beantwoordt de vraag of een LLM die rol kan overnemen,
|
||||
met Spotify teruggebracht tot resolver, verifier, personalisatiebron en
|
||||
afspeeloppervlak. Een naïeve-zoekbaseline maakt het antwoord meetbaar.
|
||||
|
||||
> Werk in uitvoering — dit bestand wordt gevuld tijdens de bouw.
|
||||
> Chronologisch verslag: [docs/logboek.md](docs/logboek.md).
|
||||
|
||||
## Demo
|
||||
|
||||
*(volgt: gehoste instantie + lokale `docker compose up --build`, met en zonder
|
||||
API-sleutels)*
|
||||
|
||||
## Hoe het werkt
|
||||
|
||||
*(volgt: pipeline-diagram en module-overzicht)*
|
||||
|
||||
## Keuzes
|
||||
|
||||
*(volgt)*
|
||||
|
||||
## Performance en optimalisaties
|
||||
|
||||
*(volgt)*
|
||||
|
||||
## Waar te kijken
|
||||
|
||||
*(volgt)*
|
||||
|
||||
## Werkwijze
|
||||
|
||||
*(volgt)*
|
||||
|
||||
## Wat ik heb geschrapt / wat ik hierna zou doen
|
||||
|
||||
*(volgt)*
|
||||
Loading…
Add table
Add a link
Reference in a new issue