list_pages: order_by=TITLE liefert stillschweigend unvollständige Ergebnisse #1

Closed
opened 2026-08-16 11:42:42 +02:00 by Lyra · 1 comment
Collaborator

Beobachtung

list_pages gibt mit der Default-Sortierung order_by="TITLE" nur einen Bruchteil der Seiten zurück. Gemessen gegen einer produktiven Instanz (91 Seiten, Locale de):

order_by limit Ergebnis
ID 10 10 Seiten + Hinweis „Limit erreicht"
ID 100 91 Seiten (vollständig)
TITLE 5 2 Seiten
TITLE 10 3 Seiten

Die bei TITLE zurückgegebenen Treffer sind jeweils der Anfang der alphabetischen Sortierung (ALB-Cloud, ALB-DNS01, ALB-DNS) — die Liste wird also nicht falsch sortiert, sondern nach dem Sortieren abgeschnitten. Die Trefferzahl sinkt weit unter das gesetzte Limit.

Warum das kritisch ist

TITLE ist der Default (server.py:152, client.py:174). Ein Aufruf ohne Parameter liefert damit im Normalfall eine unvollständige Liste, die vollständig aussieht — der Hinweis „Limit erreicht" bleibt aus, weil len(pages) < limit ist. Ein Konsument (LLM oder Skript) hat keine Möglichkeit, die Lücke zu erkennen.

Einordnung

client.list_pages (client.py:169-201) reicht limit und orderBy unverändert an die GraphQL-Query durch, es gibt keine Nachbearbeitung mehr. Der Kommentar ab client.py:179 dokumentiert, dass ein früherer Post-Filter-Bug dieser Art bereits behoben wurde. Die Kürzung passiert demnach oberhalb, im pages.list-Resolver von Wiki.js. Ursache dort ist noch nicht verifiziert.

Ein Fix in diesem Repo ist damit defensiv, nicht ursächlich.

Vorschlag

  • Default in server.py:152 und client.py:174 auf ID umstellen.
  • TITLE/PATH/UPDATED erst wieder als Default zulassen, wenn das Verhalten gegen die eingesetzte Wiki.js-Version verifiziert ist.
  • Alternative, falls Sortierung nach Titel gebraucht wird: vollständig nach ID laden und client-seitig sortieren.

Definition of Done

  • list_pages() ohne Parameter liefert gegen eine Instanz mit >90 Seiten dieselbe Menge wie order_by="ID".
  • Regressionstest, der Trefferzahl bei ID und TITLE bei gleichem limit vergleicht.
## Beobachtung `list_pages` gibt mit der Default-Sortierung `order_by="TITLE"` nur einen Bruchteil der Seiten zurück. Gemessen gegen einer produktiven Instanz (91 Seiten, Locale `de`): | `order_by` | `limit` | Ergebnis | |---|---|---| | `ID` | 10 | 10 Seiten + Hinweis „Limit erreicht" | | `ID` | 100 | 91 Seiten (vollständig) | | `TITLE` | 5 | 2 Seiten | | `TITLE` | 10 | 3 Seiten | Die bei `TITLE` zurückgegebenen Treffer sind jeweils der Anfang der alphabetischen Sortierung (`ALB-Cloud`, `ALB-DNS01`, `ALB-DNS`) — die Liste wird also nicht falsch sortiert, sondern nach dem Sortieren abgeschnitten. Die Trefferzahl sinkt weit unter das gesetzte Limit. ## Warum das kritisch ist `TITLE` ist der Default (`server.py:152`, `client.py:174`). Ein Aufruf ohne Parameter liefert damit im Normalfall eine unvollständige Liste, die vollständig aussieht — der Hinweis „Limit erreicht" bleibt aus, weil `len(pages) < limit` ist. Ein Konsument (LLM oder Skript) hat keine Möglichkeit, die Lücke zu erkennen. ## Einordnung `client.list_pages` (`client.py:169-201`) reicht `limit` und `orderBy` unverändert an die GraphQL-Query durch, es gibt keine Nachbearbeitung mehr. Der Kommentar ab `client.py:179` dokumentiert, dass ein früherer Post-Filter-Bug dieser Art bereits behoben wurde. Die Kürzung passiert demnach oberhalb, im `pages.list`-Resolver von Wiki.js. Ursache dort ist noch nicht verifiziert. Ein Fix in diesem Repo ist damit defensiv, nicht ursächlich. ## Vorschlag - Default in `server.py:152` und `client.py:174` auf `ID` umstellen. - `TITLE`/`PATH`/`UPDATED` erst wieder als Default zulassen, wenn das Verhalten gegen die eingesetzte Wiki.js-Version verifiziert ist. - Alternative, falls Sortierung nach Titel gebraucht wird: vollständig nach `ID` laden und client-seitig sortieren. ## Definition of Done - `list_pages()` ohne Parameter liefert gegen eine Instanz mit >90 Seiten dieselbe Menge wie `order_by="ID"`. - Regressionstest, der Trefferzahl bei `ID` und `TITLE` bei gleichem `limit` vergleicht.
Author
Collaborator

Behoben in 7245ca1 — Ursache ist eine andere als vermutet.

pages.list holt die Tags über withGraphJoined('tags') und legt limit auf das Ergebnis dieses Joins, also auf Zeilen statt Seiten. Eine Seite mit vier Tags verbraucht vier Plätze. Gemessen gegen einer produktiven Instanz, inzwischen 128 Seiten:

order_by limit Seiten
ID 10 10
ID 100 91#95 zeigt 2 statt 4 Tags
ID 500 128
TITLE 10 3
TITLE 500 128

orderBy ist unbeteiligt. Dass ID unauffällig wirkte, lag allein daran, dass die Seiten mit niedriger id ungetaggt sind — bei limit: 100 schneidet ID genauso ab, zusätzlich mit gekürzter Tag-Liste auf der letzten Seite. Der vorgeschlagene Default ID hätte den Fehler also nur verschoben.

Umgesetzt stattdessen: kein limit in der Query, sortiert wird client-seitig in sort_pages(), gekürzt erst im Tool. Regressionstest vergleicht die Trefferzahl bei ID und TITLE.

Behoben in 7245ca1 — Ursache ist eine andere als vermutet. `pages.list` holt die Tags über `withGraphJoined('tags')` und legt `limit` auf das Ergebnis dieses Joins, also auf **Zeilen statt Seiten**. Eine Seite mit vier Tags verbraucht vier Plätze. Gemessen gegen einer produktiven Instanz, inzwischen 128 Seiten: | `order_by` | `limit` | Seiten | |---|---|---| | ID | 10 | 10 | | ID | 100 | **91** — #95 zeigt 2 statt 4 Tags | | ID | 500 | 128 | | TITLE | 10 | 3 | | TITLE | 500 | 128 | `orderBy` ist unbeteiligt. Dass ID unauffällig wirkte, lag allein daran, dass die Seiten mit niedriger id ungetaggt sind — bei `limit: 100` schneidet ID genauso ab, zusätzlich mit gekürzter Tag-Liste auf der letzten Seite. Der vorgeschlagene Default `ID` hätte den Fehler also nur verschoben. Umgesetzt stattdessen: kein `limit` in der Query, sortiert wird client-seitig in `sort_pages()`, gekürzt erst im Tool. Regressionstest vergleicht die Trefferzahl bei ID und TITLE.
Lyra closed this issue 2026-08-16 13:10:12 +02:00
Sign in to join this conversation.
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
draventec/wikijs-mcp#1
No description provided.