No description
- JavaScript 42%
- Python 41%
- CSS 16.2%
- Dockerfile 0.4%
- HTML 0.4%
|
All checks were successful
Build and Deploy / lint-backend (push) Successful in 13s
Build and Deploy / lint-frontend (push) Successful in 14s
Build and Deploy / test-backend (push) Successful in 32s
Build and Deploy / build-and-push (push) Successful in 10s
Build and Deploy / deploy (push) Successful in 19s
Acts on feedback from an agent that actually used the server.
Views instead of more typed tools (migrations v7/v8). Domain knowledge belongs
in SQL, not in every query the caller writes, and a view stays composable where
a typed tool answers exactly one question:
- courses_resolved: price/duration lifted out of the JSON metadata blob,
mirroring get_course_price_map (manual override wins, '' and 0 are absent).
- work_days_enriched: days joined to course and location with students (NULL->1),
month, weekday, in_catalog, earns_revenue, revenue and travel_km.
SUM(revenue) over the view reproduces compute_stats exactly — asserted by a test,
verified against a 67-day dataset covering all four price/duration permutations.
get_availability. Free days have no row, so "when am I free" is not expressible
as a SELECT; the calendar has to be generated and subtracted from. This was the
one question the previous server could not answer at all.
data_health. Four checks on the loose work_days <-> courses text join. The
scraped-name check requires EXACT equality against a known spelling: a substring
test repeats the scraper's own bug, since the alias "Python" is a substring of
"Machine Learning with Python". Measured on the real catalog, the substring rule
found 0 of 25 mis-scrapes and the exact rule found 15, ranked by token overlap so
the certainly-wrong ones sort above translations. The duration check uses the
modal block length and needs real evidence, so honest bookings stay silent.
Output. Tools are now annotated `-> Any`: a `-> str` annotation made FastMCP
generate an output schema wrapping every result as {"result": "<json string>"},
so callers parsed JSON out of a JSON string. A test asserts no tool declares an
outputSchema. format="table" is the new default at roughly half the characters
of JSON, and list_days drops all-empty columns; query_sql never does, because a
column the caller selected being empty is itself an answer.
describe_schema returns DDL only — the parallel column array just restated it —
and now covers views.
Docs rewritten around the views, and the query recipes are executed by a test so
they cannot rot.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|---|---|---|
| .claude | ||
| .forgejo/workflows | ||
| docs | ||
| frontend | ||
| routers | ||
| tests | ||
| .dockerignore | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| .ruff.toml | ||
| CLAUDE.md | ||
| db.py | ||
| dependencies.py | ||
| docker-compose.yml | ||
| Dockerfile | ||
| GEMINI.md | ||
| insights_logic.py | ||
| main.py | ||
| mcp_server.py | ||
| migrate_from_sheets.py | ||
| pyproject.toml | ||
| requirements.txt | ||
| scrape_courses.py | ||
| seed.json | ||
| stats_logic.py | ||
| token_store.py | ||
| tracker.db | ||