T29: Bílá kniha course catalogue (fit.catalog.*) #28

Open
dzenda wants to merge 4 commits from t29-bila-kniha into t27-fitwiki-connection
Owner

T29: Bílá kniha (course catalogue)

Stacked on #27 (the part 2 plan lives there).

New MCP functions over the public faculty catalogue bk.fit.cvut.cz:

  • fit.catalog.course { code, lang? } returns credits, completion (Z/ZK/KZ), extent (e.g. 2P+1R+1C), semester, instructors and other facts, the course website, study-plan roles, and the text sections (annotation, lecture and seminar syllabus, literature, requirements), each capped at 4,000 chars. Codes may omit the plan suffix (BI-LA1 → BI-LA1.21, the newest suffix wins).
  • fit.catalog.search { query, lang?, limit? } matches course codes by prefix and course names word by word, accent-insensitively, with light stemming for Czech.
  • English or Czech pages (/en/, /cz/). The index (6 h) and up to 200 course pages are cached per isolate.
  • Safety:
    • only digit detail paths taken from the index (00/…/p123.html) are fetched, on bk.fit.cvut.cz only;
    • manual redirects, a 15 s timeout, an identified user agent;
    • byte caps of 3 MB for the index and 500 KB for a page.
  • New shared helper src/lib/html-text.ts: entity decoding, HTML → text (keeping line structure), innerBlocks, stripTags and clip. It runs in linear time on malformed input, and T28 (FIT Wiki) reuses it.
  • Search keywords avoid "zkouška" and "zápočet" so exam-date and grade questions still go to Sirius and Grades.
  • PLAN.md: T28 is marked blocked until a FIT Wiki session is connected locally (Needs you).

Verified live against bk.fit.cvut.cz: BI-PA1 → 7 credits, Z,ZK, 2P+2R+2C, 5 sections, 23 study plans. The Czech BI-LA1 page has Czech section titles, and searching "databáze" finds the database courses.

Review (Astra)

  • Fixed [P2]: searching a course code was stemmed, so "BI-PA1" also matched BI-PA2. Code-like words now match code prefixes exactly; only name words are stemmed.
  • Fixed [P2]: quadratic regexes on malformed upstream HTML (e.g. 490k < without >) could exhaust the Worker's CPU budget. Every parser now uses linear indexOf scanners and bounded quantifiers, with timing tests for pathological pages.

Checks

lint, typecheck and test: 332 passing.

🤖 Generated with Claude Code

## T29: Bílá kniha (course catalogue) Stacked on #27 (the part 2 plan lives there). New MCP functions over the public faculty catalogue **bk.fit.cvut.cz**: - `fit.catalog.course { code, lang? }` returns credits, completion (Z/ZK/KZ), extent (e.g. 2P+1R+1C), semester, instructors and other facts, the course website, study-plan roles, and the text sections (annotation, lecture and seminar syllabus, literature, requirements), each capped at 4,000 chars. Codes may omit the plan suffix (`BI-LA1` → `BI-LA1.21`, the newest suffix wins). - `fit.catalog.search { query, lang?, limit? }` matches course codes by prefix and course names word by word, accent-insensitively, with light stemming for Czech. - English or Czech pages (`/en/`, `/cz/`). The index (6 h) and up to 200 course pages are cached per isolate. - Safety: - only digit detail paths taken from the index (`00/…/p123.html`) are fetched, on `bk.fit.cvut.cz` only; - manual redirects, a 15 s timeout, an identified user agent; - byte caps of 3 MB for the index and 500 KB for a page. - New shared helper `src/lib/html-text.ts`: entity decoding, HTML → text (keeping line structure), `innerBlocks`, `stripTags` and `clip`. It runs in **linear time** on malformed input, and T28 (FIT Wiki) reuses it. - Search keywords avoid "zkouška" and "zápočet" so exam-date and grade questions still go to Sirius and Grades. - PLAN.md: T28 is marked blocked until a FIT Wiki session is connected locally (Needs you). Verified live against bk.fit.cvut.cz: BI-PA1 → 7 credits, Z,ZK, 2P+2R+2C, 5 sections, 23 study plans. The Czech BI-LA1 page has Czech section titles, and searching "databáze" finds the database courses. ### Review (Astra) - Fixed [P2]: searching a course code was stemmed, so "BI-PA1" also matched BI-PA2. Code-like words now match code prefixes exactly; only name words are stemmed. - Fixed [P2]: quadratic regexes on malformed upstream HTML (e.g. 490k `<` without `>`) could exhaust the Worker's CPU budget. Every parser now uses linear `indexOf` scanners and bounded quantifiers, with timing tests for pathological pages. ### Checks lint, typecheck and test: 332 passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- bk.fit.cvut.cz index + course pages (en/cs): credits, completion, extent, instructors,
  study-plan roles, annotation/syllabus/literature/requirements (bounded), cached per isolate
- only digit detail paths from the index are fetched; manual redirects; identified UA
- shared src/lib/html-text.ts (entities, HTML → text, clip)
- PLAN: T28 blocked on a connected FIT Wiki session (Needs you)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin t29-bila-kniha:t29-bila-kniha
git switch t29-bila-kniha

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch t27-fitwiki-connection
git merge --no-ff t29-bila-kniha
git switch t29-bila-kniha
git rebase t27-fitwiki-connection
git switch t27-fitwiki-connection
git merge --ff-only t29-bila-kniha
git switch t29-bila-kniha
git rebase t27-fitwiki-connection
git switch t27-fitwiki-connection
git merge --no-ff t29-bila-kniha
git switch t27-fitwiki-connection
git merge --squash t29-bila-kniha
git switch t27-fitwiki-connection
git merge --ff-only t29-bila-kniha
git switch t27-fitwiki-connection
git merge t29-bila-kniha
git push origin t27-fitwiki-connection
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
dzenda/os!28
No description provided.