Commit graph

896 commits

Author SHA1 Message Date
Daniel
f0cc537df1 test(e2e): the browser suite follows generation into its job, and can log in again
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 51s
Forgejo Docker Build / Build Docker image (push) Successful in 8s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 18s
Two faults kept every spec in this file from running, both in the same code
path and both from the SSO-only change. The fixtures minted a session by
shelling out to `docker compose exec`, which cannot work from inside the
Playwright container — it has no docker CLI and no socket — so all seventeen
specs (both viewports) died at the auth fixture before touching the page. The
harness now mints both sessions on the host and passes them in, and the seed's
connection banner is no longer mistaken for the token: it prints before it,
so the token is the last line. The host-side docker path stays as the fallback
for `npx playwright test` run directly on the host.

The specs then move to what generation is now: the click is answered with a
job, so the assertions follow the job list. A generation in flight is listed
and survives a reload, a job that lands reloads the library and says what it
was written from, a job that fails says why, and what was searched for is
reported when the job lands rather than when the button is pressed.
2026-09-16 04:02:10 +02:00
Daniel
ef574eddcb feat: a resource is generated as a job, and DeepSeek writes it without thinking
Some checks failed
Forgejo Docker Build / Build Docker image (push) Blocked by required conditions
Forgejo Docker Build / End-to-end (browser) (push) Blocked by required conditions
Forgejo Docker Build / Root app tests (push) Has been cancelled
Writing a resource held the request open for as long as it took: a library
search, one or two long model calls, a review, then figures. Measured end to
end that was six minutes on 2026-09-16 (00:40 to 00:46:16, resource 53), and
Firefox abandons a request that has said nothing for five — the browser
reported "NetworkError when attempting to fetch resource" while the server
carried on and saved the deck anyway, so a generation that worked looked
like a failure and left no status line.

The request now records what was asked and answers 202; the work runs on the
server as a job; the page lists what is being written, what landed and what
failed, polls while anything is in flight, and reloads the library when one
lands. Several can run at once, a reload loses nothing, and a boot pass marks
jobs stranded by a restart as failed rather than spinning for ever.

The same generation also ran with DeepSeek's thinking on, which is what made
it take minutes rather than seconds: the 16,000-token write spent the whole
budget reasoning and returned an empty reply (completion_tokens=16000,
reasoning_chars=51573), which fired the automatic retry at four times the
budget, and the 2,000-token reviews of that deck starved the same way four
times over. Thinking is now off for the writing, the review of it and a
revision — DeepSeek's own field, sent by the model wrapper. Other clinical
routes are deliberately untouched and keep the provider default.

The review inherits the writer's rule rather than hard-coding it, so a task
that wants reasoning can still ask. Migration 1781500000000_resource-jobs.js
adds user_resource_jobs; the container entrypoint applies it before the app
starts.
2026-09-16 03:53:57 +02:00
Daniel
102249cc10 chore: the app reaches the gateway by container name, not the public host
LITELLM_API_BASE came from OpenBao as https://llm.danvics.com, so every AI
call in the app also depended on Caddy, public DNS and edge TLS being up.
Pinned to the compose network while the public hostname is being taken off
the internet, at the user's request.
2026-09-16 03:53:53 +02:00
Daniel
ac3e6bf3f0 fix: the assistant page finishes loading for non-admin accounts
The download-transcript button is removed for anyone who is not an admin,
but the event binder still called addEventListener on it unguarded. The
throw stopped the binder before the saved-chat list loaded, before the
click handler for opening old chats was registered, and before the send
box was fully wired, so a non-admin saw no chats until New chat, could not
open old ones, and could not chat. The button is now bound only if present.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-15 19:59:29 +02:00
Daniel
3c04d662f6 feat: the password door is gone; One Sign In is the only way in
POST /api/auth/login answers 410 for everyone, administrators included. The
sign-in screen never draws an email or a password: it is the provider's
button, or a sentence saying sign-in is not configured. The admin CLI no
longer resets passwords. The e2e harness mints its sessions inside the
container instead of signing in with a password.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-15 04:14:04 +02:00
Daniel
29ff7e435c feat: One Sign In is the only door; the SSO-only switch is gone
With OIDC on, every password route is shut except /api/auth/login for
administrators — the way back in if the provider is down, reached from an
"Administrator sign-in" link. The disable-local-auth setting, the
registration CLI command and the docs that described them are removed;
accounts, roles and invitations live in authentik.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-15 03:33:53 +02:00
Daniel
4c699b86ef feat: local registration is closed for good, and its on/off switch is gone
Every account comes through One Sign In; an administrator sends an
invitation link from there. The register route answers 410, the
registration-status route and the admin toggle are removed, and the
setting no longer exists in defaults, lockdown lists or seeds.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-15 03:18:57 +02:00
Daniel
f94c2b9f90 revert: the starter chips are three short labels again
The user, seeing four full questions stacked on the empty page: "the former
way… was better". Labels, three of them, as before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-15 01:42:09 +02:00
Daniel
67336343cf feat: a resource's details are the brief — pasted questions, topics and cases are used as given
Tested with a pasted board question, a topic list and a SOAP case and no other
instruction: all of it was used. The prompt now says so explicitly, so it stays
that way whatever model writes the deck.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-15 00:18:04 +02:00
Daniel
6b9587d09f fix: the assistant's empty state keeps its own heading when the starters arrive
The re-render swapped "Pediatric Clinical Assistant" for a different heading
and line the moment the starter questions loaded. Same words as the page now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 23:55:33 +02:00
Daniel
91a35a4b27 fix: the assistant page keeps its layout whatever the initialiser does, and its starters are whole questions
The page class that hides the app sidebar and gives the chat its full height
was added only after the initialiser returned, so any error there left the
app menu and the chat rail side by side with the panels at half height. The
class goes on first now. The starter chips show the question itself rather
than a two-word label, four of them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 23:42:32 +02:00
Daniel
15ec830038 fix: each pool batch names what the category already holds, so no batch repeats the last
Batches three onwards reuse the first batches' snippets, and an identical
request came back with the identical list: every category stopped at exactly
40 of its quota. The list of what is covered makes each request, and each
answer, new.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 18:30:28 +02:00
Daniel
6e2ad26547 feat: starter questions are things to learn, not scenarios, and DeepSeek writes them without thinking
The pool was cases — "A 6-week-old with 3 days of projectile vomiting… which
fluid do you start?" — and the user, reading them on the assistant's front
page: "Vague nonsense clinical scenarios. I want concrete things people learn
from and pathophysiology if possible, all related to peds. No more clinical
scenarios. Use deepseek with its reasoning off."

So the brief is inverted. A question asks one definite thing with a definite
answer — a mechanism, a distinction between two look-alikes, the number that
decides, the reason behind a rule of practice — mechanism first, naming its
disease, drug or finding, and staying paediatric. The filter refuses a
vignette opener and a bare definition instead of demanding a number; the
prompt version moves to 3 so every deployment rebuilds the pool once; the
model defaults to DeepSeek flash with thinking disabled, which the assistant
already knows how to ask for.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 18:25:05 +02:00
Daniel
57ba2a268c fix: the format picker shows the format's name only — the slide count is the one length control
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 1m2s
Forgejo Docker Build / Build Docker image (push) Successful in 7s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 7s
The picker labels carried each format's typical length ('15–25 cases, three
or four slides each, 60–90 minutes'), which sat under a slide-count field and
read as a second, contradicting number. The label is the name, the hint says
who the format is for, and the brief tells the model that the slide count
asked for is the length and the parts fit into it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 16:07:05 +02:00
Daniel
6ca278c0e6 feat: deck cards fit their content, callouts use the theme's ink, questions can carry a film, formats end with references
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 52s
Forgejo Docker Build / Build Docker image (push) Successful in 6s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 7s
Compare cards were as tall as the body whatever they held, so two columns of
four short bullets sat in cards 60% empty; a one-sentence callout sat in a
card two thirds of the slide. Both now size to the text. The callout card's
fixed brown ink was the worst contrast in the catalogue on Board Review's
mint card; it takes the theme's ink. A question slide may carry image_prompt
— a film beside the stem, drawn or left as a labelled frame like a figure.
The evidence-based formats (board review, journal club, QI, abstract, debrief)
gain a References part and the brief says the deck ends with it: DeepSeek
skipped it when it was only suggested.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 15:35:10 +02:00
Daniel
50f5036118 feat: the assistant reopens the chat you were in, and DeepSeek answers without thinking when told to
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 50s
Forgejo Docker Build / Build Docker image (push) Successful in 11s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
A refresh landed on a new empty chat with the conversation a click away in
the list. The open chat's id is remembered per account and reopened on
load; New chat forgets it; a chat deleted elsewhere is quietly gone.

DeepSeek models think by default: measured on ds-deepseek-v4.1-flash, a
three-sentence clinical answer spent 301 reasoning tokens and 2.9 s before
writing and gave the same answer in 0.9 s with thinking off. The assistant's
reasoning effort now comes from CLINICAL_ASSISTANT_REASONING_EFFORT ('low'
as before; 'none' switches thinking off where a model allows it, sent as
DeepSeek's own thinking field through LiteLLM).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 15:24:48 +02:00
Daniel
381483dcf3 fix: a question slide's options are lettered once, and a bare-letter answer names its option
DeepSeek flash wrote 'A. Start IVIG' into option text the renderer already
letters, so the slide read 'A  A. Start IVIG'; and an answer of just 'A' sat
alone on the answer card, sending the room back a slide to see what A was.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 15:14:32 +02:00
Daniel
aac02ec0df feat: a figure the deck wanted and did not get keeps its place as an empty labelled frame
With illustration off, or for a picture no model should draw — a real
radiograph, a run chart, a photograph — the figure or image slide used to
become a slide of text, and the deck forgot it had wanted a picture. It now
keeps a dashed, labelled frame in the picture's place, on figure slides,
full-slide images and the image shapes of custom slides, so the author can
drop their own in after downloading; the Word export says what belongs
there. Figures already drawn are never turned into frames. The one format
guidance that implied a slide authored live now says 'fill in by hand'.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 14:46:29 +02:00
Daniel
7ea6c41941 fix: tables scroll sideways on the phone again instead of breaking words to fit the screen
The morning's change forced every table to the screen width below 640px and
let cells break mid-word, so a four-column table read as columns of broken
syllables. A swipe is the better trade; the hint under the table says so.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 14:41:40 +02:00
Daniel
cd00fae460 feat: a deck has a format as well as a theme — the shape of the session, whose parts the model may reuse
A theme is a look and the slide vocabulary is what one slide can be; neither
said what a journal club is (PICO, methods, appraisal, bottom line) or that a
board review runs in case-question-answer cycles, so every deck came out as
the same lecture. assets/deck-formats.json holds ten formats distilled from
how departments run each session — grand rounds, journal club, morning
report, M&M, board review, noon conference, simulation debrief, parent
education, QI project, research abstract — each a sequence of parts naming
the layouts it is usually drawn with and whether it may repeat. The brief is
prose after the layout vocabulary; a part is a unit the model reuses as many
times as the material needs, and every slide stays one of the twelve types.
Chosen beside the theme, 'Free' by default, stored on the deck and carried
through modifications.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 14:13:22 +02:00
Daniel
f762e91af7 feat: the assistant searches every collection the library declares, fused by rank — one collection stays one call
The search service can hold several Milvus collections, each with its own
embedder, but a search names one or gets the default, so a second collection
was invisible to the assistant. The client now learns the list off the query
path (at warm-up and on the session timer), and only when the service lists
more than the default does a search fan out — one call per collection in
parallel, fused by reciprocal rank so scores from different embedders are
never compared. With one collection, today's case, the request is byte-for-
byte what it was and no listing call is made while anyone waits.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 13:57:56 +02:00
Daniel
055c8d121b fix: the last browser confirm() in the resources library uses the app's confirm modal
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 1m4s
Forgejo Docker Build / Build Docker image (push) Successful in 19s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 9s
Deleting a generated image asked with the browser's own confirm(), a bare
dialog that looks nothing like the rest of the app. It now goes through
showConfirm like every other confirmation, with the danger styling and a
Delete button.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015j4L7Eu5Jp8gVMPsXdPaZ2
2026-09-14 10:44:31 +02:00
Daniel
5d28ebad9c feat: the assistant degrades politely under load — bounded retrieval queue, per-user limit, short search cache
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 47s
Forgejo Docker Build / Build Docker image (push) Successful in 17s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Three things the load path lacked. The retrieval slots had an unbounded
line behind them, so a burst meant silent waiting; past a bounded line, or
after eight seconds in it, a caller now gets 'the library is busy' and a
503 with a retry hint. The paid routes had no per-account ceiling; they
now get one, counted in Redis so every replica sees the same count and
nothing is refused when Redis is absent. And the same library search
asked twice within a minute (a retry, a refresh) went to the library
twice; it is now answered from Redis, with 0 turning that off.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-14 07:56:26 +02:00
Daniel
fbc6e3fa6c fix: the Nextcloud login flow waits in Redis, so any replica can answer the poll
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 1m3s
Forgejo Docker Build / Build Docker image (push) Successful in 20s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
The flow lived in a Map inside the web process; with more than one
replica the poll could land where the flow was never started and every
sign-in would look expired. It now sits in Redis with the same 20-minute
life and one-per-account rule, and falls back to memory when there is
no Redis, which is what tests and a single-process box always had.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-14 07:31:52 +02:00
Daniel
9695e3c7f9 fix: an empty reply whose budget went to reasoning is retried with room to write
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 47s
Forgejo Docker Build / Build Docker image (push) Successful in 19s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Any call with a small max_tokens could come back blank from a reasoning
model: finish_reason=length, content empty, the budget spent thinking.
The shared LiteLLM call now retries that one signature once, with at least
6000 tokens and low reasoning effort, so no caller has to guess a budget.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-14 05:49:16 +02:00
Daniel
394c543a0a fix: answer and take-home tables wrap to the phone screen instead of scrolling sideways
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 49s
Forgejo Docker Build / Build Docker image (push) Successful in 9s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 17s
The sideways swipe was not reachable on the phone, so wide tables were cut
off. Below 640px the cells break their words and the table takes the full
width; wide tables get taller, never clipped.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-14 05:40:42 +02:00
Daniel
1d58e5b509 fix: the take-home sheet gives a reasoning model room to think and still write
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 47s
Forgejo Docker Build / Build Docker image (push) Successful in 9s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
The 1,800-token ceiling was spent entirely on hidden reasoning, so the
sheet came back empty. Same budget as the answer path now, with one retry
at a larger budget if the reply is still blank.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-14 05:23:13 +02:00
Daniel
012a06c107 fix: lazily loaded components stay invisible until their stylesheet and init are ready
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 48s
Forgejo Docker Build / Build Docker image (push) Successful in 12s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
The fragment's markup was inserted before its own stylesheet resolved, so a
first visit to the assistant tab flashed unstyled content. The pending
marker app.js already sets now also hides the markup; the Loading status
line is all that shows until the tab reports ready.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-14 05:11:26 +02:00
Daniel
8142dd4ab1 fix: the assistant no longer drags the view to the end while an answer streams
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 52s
Forgejo Docker Build / Build Docker image (push) Successful in 18s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
The reader can start at the top of a long answer and scroll at their own
pace; the per-token and on-completion jumps to the bottom are gone, which
also stops a finger on the screen fighting the auto-scroll.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-14 04:26:38 +02:00
Daniel
684a8920e9 fix: a deck's illustration stays out of the page (status line only, tile under Images); a streaming table head is held back, never shown as pipes
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 47s
Forgejo Docker Build / Build Docker image (push) Successful in 8s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 21:11:36 +02:00
Daniel
4de76dbfd9 feat: a share link pasted into an open tab is handled like a fresh arrival
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 50s
Forgejo Docker Build / Build Docker image (push) Successful in 19s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 19:04:48 +02:00
Daniel
fa5ed6c2b4 feat: sharing is by link only — the share-with-everyone switch and route are gone
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 57s
Forgejo Docker Build / Build Docker image (push) Successful in 18s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 19:00:53 +02:00
Daniel
1beb2d33b0 fix: room between the starter questions and the box; a half-arrived bold run streams as bold, not asterisks
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 53s
Forgejo Docker Build / Build Docker image (push) Successful in 9s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 18:56:41 +02:00
Daniel
bbcc824b65 fix: the share panel stays open (no library redraw behind it); the Nextcloud upload button says what it is
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 54s
Forgejo Docker Build / Build Docker image (push) Successful in 14s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 18:54:30 +02:00
Daniel
4127e2d101 feat: the starter-prompt pool is built once and regenerated from the admin button only, on gpt-4.1-mini by default; the question box sits two-thirds down before a chat and at the bottom during one
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 49s
Forgejo Docker Build / Build Docker image (push) Successful in 10s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 18:38:11 +02:00
Daniel
4119788815 feat: Settings links to the PedsHub account page in a new tab
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 48s
Forgejo Docker Build / Build Docker image (push) Successful in 20s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 18:10:18 +02:00
Daniel
de13c8306b feat: templates, not just palettes — colour title and section pages, heading bands, striped callouts, question slides with answers, key-point strips, page footers; Grand Rounds and Board Review join the catalogue
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 47s
Forgejo Docker Build / Build Docker image (push) Successful in 9s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 18:05:41 +02:00
Daniel
9c86c56968 fix: a failed recording keeps its tab and the retry adds the words after the last word; Settings drops the session list; FAQ says what sign out does
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 50s
Forgejo Docker Build / Build Docker image (push) Successful in 8s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:56:32 +02:00
Daniel
cba2a312e1 feat: the preview is a viewer — one page at a time, arrows, keys, swipe, a PDF tab and downloads; the theme leaves the list row
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 51s
Forgejo Docker Build / Build Docker image (push) Successful in 11s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:49:22 +02:00
Daniel
b277ce4b10 fix: the assistant asks for context around each excerpt again — read from the stored chunks, 1400 characters by default
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 49s
Forgejo Docker Build / Build Docker image (push) Successful in 9s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:41:01 +02:00
Daniel
3e10b6faa7 feat: sign out ends the PedsHub session too (RP-initiated logout); the assistant sends the stored excerpt only
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 49s
Forgejo Docker Build / Build Docker image (push) Successful in 10s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 11s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:35:35 +02:00
Daniel
a6c2cb1080 perf: context expansion is off by default — the stored excerpt already carries the page, its tables and figure captions
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 55s
Forgejo Docker Build / Build Docker image (push) Successful in 10s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:16:28 +02:00
Daniel
cd2ee9192a fix: the silent attempt calls the real start path, /api/auth/oidc
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 58s
Forgejo Docker Build / Build Docker image (push) Successful in 15s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:06:27 +02:00
Daniel
18f7651362 feat: signed in at PedsHub means signed in here — one silent prompt=none attempt before the sign-in page, hash kept
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 51s
Forgejo Docker Build / Build Docker image (push) Successful in 19s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 7s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:04:25 +02:00
Daniel
e23d35a570 docs: library indexing is scheduled and on request; panel note matches
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 52s
Forgejo Docker Build / Build Docker image (push) Successful in 9s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 16:34:16 +02:00
Daniel
34c495b5d8 fix: the indexer address and token have their own Save; the card's Save & Close keeps its five keys
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 52s
Forgejo Docker Build / Build Docker image (push) Successful in 18s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 8s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 16:05:46 +02:00
Daniel
93426ac089 feat: the library index reconciles when the admin asks — status and Run indexing now in the Clinical Assistant card
Some checks failed
Forgejo Docker Build / Root app tests (push) Failing after 58s
Forgejo Docker Build / Build Docker image (push) Has been skipped
Forgejo Docker Build / End-to-end (browser) (push) Has been skipped
The clinical-assist indexer no longer polls Nextcloud every five minutes; it
scans once at start and then on POST /api/v1/vector-sync/scan with a bearer
token. The admin panel shows what it reports and carries the button; the
address and token are settings (or the environment). The button stays usable
under lockdown, the fields do not.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 16:02:35 +02:00
Daniel
fdbb9326c1 fix: accepting a share link failed — the insert helper adds RETURNING id and the shares table has no id
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 53s
Forgejo Docker Build / Build Docker image (push) Successful in 19s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 15:29:50 +02:00
Daniel
6c689b420c fix: lockdown also freezes the SSO settings; the gate no longer keeps a door for invites; lockdown documented
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 15:25:41 +02:00
Daniel
c7864f763e feat: sharing is by link — follow it, accept, and it is in your resources
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 56s
Forgejo Docker Build / Build Docker image (push) Successful in 10s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 12s
The author presses "Copy a share link" and sends it however they like.
Whoever follows it (app.pedshub.com/#share=<token>) is signed in first if
need be — the token survives the trip through the SSO — then shown what it
is and who from, and adds it with one press. Only the token's hash is
stored; a link lasts 30 days and can be withdrawn; accepting twice is
harmless; the owner following their own link changes nothing. Sharing by
email is gone: nobody is looked up by address. "Everyone signed in" stays
as a switch.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 15:20:35 +02:00