Commit Graph

93 Commits

Author SHA1 Message Date
1d65a4df7c fix(sonar): remove unused variables and commented-out code
Removes 43 small Sonar findings (unused locals, dead helpers, a misread comment); behaviour unchanged. CHANGELOG entry was already swept into 9f78a15.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-06 03:42:44 +02:00
e7a25d80ff feat(conversation): metrics view with TTFB charts and token usage
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-06 00:48:32 +02:00
2479617964 fix: run blocking requests/sleep in async routes via to_thread
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-06 00:40:34 +02:00
8ce8e791b2 feat(conversation): thinking on/off switch
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-06 00:21:11 +02:00
4f30ee5c0d fix: keep references to background asyncio tasks
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 18:57:20 +02:00
9b169037a4 feat(tts): inline tags in generate, audiobook and magazine paths
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 17:35:18 +02:00
7eabdf0e43 feat(characters): distinct deterministic face profiles per character
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 14:25:56 +02:00
1f812d2faf fix(characters): merge profiles only on real names, keep other cast names, reasoning and foreign quotes out of a character
Real-library audit (270 records) traced the data damage to:
- identity matching on ANY shared token ("Zwerg", "der Zwerg", "Mann") with
  "longer text wins" merging (Arthag b02 = Kolon's species/relationships), and
- csRosterCanonicalName renaming a sheet to the first cast name among its
  aliases, which saved 16 whole-sheet copies (Zwerg/Kolon = Arthag b03,
  Fremder = Mann, Alchimist = Promos ...).

Fixes:
- static/js/character-identity.js + core/character_records.py: generic labels
  are never identity evidence; csFindMergeKey, csConsolidateAliasDuplicates,
  csRosterCanonicalName, clSameIdentity use it; own name always wins; clUpsert
  writes to the exact-name record before any alias scan; no seed rename onto a
  name that has its own record.
- _charsheets_parse: in cast-target mode drop other cast members' names from
  aliases / first / last name (Kolon: "Sharraz Garthai"), strip reasoning
  leakage ("Warte:", "Der Text sagt ...") from every text field.
- _character_scene_evidence: only a quote naming the character is used,
  otherwise its own mannerisms (16 panels showed another character's scene).
- _character_age_category: Junge/Mädchen/boy/girl, number words, Sommer/
  Winter ages, evidence clause, age-tagged quotes; "15 Jahre älter" is no age.
- scripts/audit_character_records.py (read-only) and
  scripts/clean_character_records.py (dry run by default, --apply backs up).

Tests: tests/test_character_record_hygiene.py, tests/character-identity.test.mjs.
Docs: architecture/character-extraction.md, Manual, CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:09:53 +02:00
04f791e1f5 feat(characters): translate character info to English before image prompts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 12:01:42 +02:00
4fd21b1d1c fix(characters): base dwarf body lock and species text on the character's own species assertion
Extraction notes in race_species that mention another character's species
("Mensch (oder Zwerg, ...)", "... 'Der Zwerg' wird separat erwähnt ...")
switched on the dwarf body lock (short legs, full beard) for human characters
and carried a sentence about another character into the Subject clause.
Confirmed on the real library: Marrad, Kolon and Arthag (book 02).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:09:19 +02:00
084a99af2c fix(characters): isolate image generation per character
Bind the consistent-image Idempotency-Key to the character request so a reused
key cannot return another character's job; add back-to-back and concurrent
two-character regression tests.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 22:34:07 +02:00
904d6a432c fix(characters): accessory pictures show only props, no body parts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 12:33:33 +02:00
d4099e45c6 fix(characters): remove the gutters between the concept sheet panels
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 08:12:15 +02:00
1a527c3b41 fix(characters): ground the concept sheet's lower pictures in the character and the book's world
The story moment was a ~5,400-character prompt whose period rules sat at
the end, out of reach of the 4-step model; it opened with "ears clearly
visible" and asked for studio photography by a photographer with a real
actor, and drew a modern man with headphones and a camera in a garden,
captioned with pseudo-text. The prop tile was a stock catalog photo. The
negative prompts were inert because those samplers run at cfg 1.0.

Story moment and signature-item prompts are now short, world-first and
positive-only: The Dark Eye, 900-1300 AD and the book profile's setting
(never the title), the same identity, appearance and costume as the
turnaround, the book moment, a period background and a hand-made,
unmarked world; the item is the character's own, in the craftsmanship
and colours of their costume, on a table in a medieval room. Text and
modern objects are added to the scene and prop negatives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:00:53 +02:00
6d1c6c1b88 fix(characters): remove divider lines from the concept sheet
The sheet composer drew light lines between the three poses and between
the top and bottom rows, cutting through capes and swords.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 07:49:19 +02:00
3f4dfb70a4 fix(characters): harder gender/period locks in scene prompts, no unchecked sheet overwrites a validated one, weapon wording only for armed characters, poll survives 5xx blips
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-29 21:20:56 +02:00
9904459913 feat(magazine): whole-magazine quality check, page stages, ad pages, driving-mode player
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
- Quality run: per-page missed-text recovery, guarded OCR re-read and a pixel audit
  (uncovered ink, overlapping boxes, clipped box edges); report saved as quality_report.json
- Thumbnail grid: quality-stage colours, flag badge, live per-page indicator for every
  batch step (OCR, detection, figure fixing, quality run, audio)
- Pages can be approved as advertisements (not narrated, skipped by quality run)
- Driving mode: +/-15 s, seek bar, playback speed, text and image toggles
- Plus the previously uncommitted 1.53.5 magazine/OCR work in the same tree

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 19:29:43 +02:00
94331320c0 feat(magazine): one-click draw tool, table regions, batch approve, MP3 export, remove-all-boxes
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
Bundles this session's magazine review work: a single "Draw region" tool
replacing six preset-kind buttons; "Table" as a real, non-narrated region
type; uniform auto-OCR for every text-like drawn/re-read region with a
Tesseract fallback when the vision OCR backend is unreachable; a thumbnail
grid view and inline title editing for the article list; batch
approve/reject; standalone MP3 export with embedded title/author/album,
lyrics and cover art (adds mutagen); "Remove all boxes" for starting a
tangled page from scratch; Approve advancing straight to the next article;
a merged, sticky review toolbar; and a fix for stale image previews after
resizing a region's box.

Also fixes several character-portrait rendering biases confirmed live
across this session's DSA audiobook cast (routes/conversation.py): modern
or bald/receding hair regardless of established coverage, armored women
rendering masculinized, duplicated/malformed weapons, a ranged weapon
rendering as a firearm due to a German compound-word regex miss, an
established dwarf rendered with human proportions, and occasional extra
hands or lost non-human species in scene panels.

See CHANGELOG.md [1.43.0] for the full list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 20:14:11 +02:00
2d5d5da777 feat(characters): short framing-first portrait prompt; the sheet follows what the finished portrait shows
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
Portrait backdrop measured 0/4 -> 4/4 plain on the failing character, no
change on the one that already passed. After the portrait passes, the vision
model describes hair, facial hair and eyes, and the turnaround and story
prompts are rebuilt with it -- a character with no hair in his sheet got a
different haircut on the sheet and failed the same-person check 3/3.
Costume cut and colours restored for armed characters. v1.41.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 20:09:45 +02:00
fb56f4a6d7 fix(characters): short framing-first turnaround prompt; drop passing moods, gestures and scars from images
Measured with the image check: full-body turnarounds 0/5 -> 10/10 (Karyla),
12/12 on Karyla, Darrag and Eolan after the face fixes. The 4-step model
loses the tail of a ~3000-char prompt. Scars are left out of image prompts:
any scar wording, even "fully healed", rendered as fresh gashes. v1.40.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 17:38:03 +02:00
981341de3f feat(characters): check every render, retry with a new seed, and take the sheet's face from the profile
The job checks the portrait crop, then the turnaround, story panel and
same-person against the sheet, re-renders on failure (up to 3 attempts) and
keeps the attempt with the fewest faults. ReActor transfers the profile's face
onto the turnaround and the largest face in the story panel. If the checker is
down, retries stop and the pair is marked unverified. The outcome is saved
with the pair and shown on the character page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 10:32:47 +02:00
ac8a6c7a24 feat(characters): automatic vision check for generated character images
The model only reports observations; expectations come from the sheet and the
comparison is in code. Fail-safe: an unreachable checker or unreadable answer
is a failure. Calibrated 14/14 on panels with known defects using the already
loaded LLM; Ling 3.0 Flash VL (free) scored 8/14 with 6 unreadable answers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 10:23:42 +02:00
16df95ec97 fix(characters): elf ears on humans, gender drift in the scene panel, bleeding scars, firearm sword grip
Each fix pins a defect seen in a real render. The species test read the raw
sheet field, so a hedged "Mensch (oder Halbelfe...)" matched the elf pattern.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 09:47:28 +02:00
9edafe8f4a fix(characters): revert per-view turnaround renders to the single triptych
Drawing front/side/rear separately with the edit model reproduced the exact
failure the triptych was introduced to fix: three near-identical front views,
mixed styles between panels, cropped bodies, and the wireframe pose guide
rendered into the costume.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 09:33:23 +02:00
69b5e06f02 fix(characters): reword stored Renaissance book profiles to high-fantasy medieval in image prompts
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 22:11:02 +02:00
46967ade68 feat(engines): list LiteLLM router aliases in the model dropdown
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 16:23:25 +02:00
4b59d06479 fix(characters): map tricorn hats to a period helm in image prompts
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 16:13:50 +02:00
fb4cdbba0c feat(characters): turnaround drawn from the portrait, Dark Eye medieval setting, object-only prop tiles
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 06:19:56 +02:00
e19f2b524c fix(characters): period-safe, uninjured, more varied image prompts with taller adult proportions
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 05:34:31 +02:00
a9b4a493d8 fix(characters): retry empty character-sheet extraction with thinking disabled
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 22:58:10 +02:00
37e2622d4e feat(audiobook): advisory verify and span-native recast for span casts
Verify / recast now run span-natively (no text re-emission): a second differently-windowed
pass marks lines agreed/disputed and records the other answer, without changing any speaker
(~9 min vs ~49 min). Measured on the real pipeline, overruling disputed lines with a reasoning
adjudication made them worse (66.5% -> 61.4%), so that step was removed; agreed lines were 83%
right vs 48.5% for disputed ones, which is the signal used for confidence and review.
Auto-repair no longer runs after a span cast; segments carry a spanId.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 20:17:38 +02:00
5877aa2edc fix(characters): persist base-appearance image pairs, deterministic prompts, form-aware review; add forms panel
- fix: base-appearance matched pair lost its concept image + metadata on reload; visual save
  wrote base concept art to the record root; one save path for base and forms now
- fix: extraction no longer lets the LLM author image_prompt (source of avatar/concept drift);
  avatar-only generation uses the deterministic prompt and flags an existing pair
- fix: prompt writes and Physical/Clothing edits go to the active form; review endpoint checks
  each form's own pair; fingerprint parity with the browser incl. visual_* overrides
- feat: appearance forms panel (add/rename/delete/show, per-form stale flag, generate one/all)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 15:27:21 +02:00
e7cb92c572 feat(audiobook): span-mode casting - deterministic quote spans, LLM only names speakers
Split the book into narration/dialogue spans from its own quotation marks and ask
the LLM only who speaks each dialogue span (POST /api/attribute-spans), so text can
no longer be fused, dropped or duplicated and a novel takes ~10 min instead of ~4 h.
Book 1 vs the hand-corrected reference: every-word-right 87.0% -> 92.3%, type
agreement 93.6% -> 97.4%; Books 2/3 (not tuned on) 90.8% / 89.9%.

- static/js/audiobook-spans.js (pure, unit-tested) + audiobook-cast-spans.js
- core/attribution_spans.py, route, tests; scripts/score_attribution.py
- default on; localStorage ab-span-mode=0 restores the classic engine
- architecture/audiobook-attribution.md, Manual, CHANGELOG 1.32.0, TODO

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 08:30:26 +02:00
ff827a74bd fix: recover character sheet requests from gateway 405
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
2026-09-09 06:49:52 +02:00
b6f4a9518b test: lock visual identity prompts 2026-09-04 15:30:39 +02:00
c4a5689a1d fix: prevent narrator phantom speakers in book2 2026-09-04 10:04:20 +02:00
aa8a96c48f feat: add safe retries for background jobs 2026-09-04 09:58:45 +02:00
6ca044ef64 feat: validate canonical image asset digests 2026-09-04 09:53:50 +02:00
9b15dae205 fix: preserve live image job results 2026-09-04 09:52:40 +02:00
690673625d feat: persist background job result artifacts 2026-09-04 09:48:37 +02:00
5219bc4588 feat: unify transient provider retries 2026-09-04 09:36:48 +02:00
e234a6e9a3 feat: persist background job metadata 2026-09-04 09:23:17 +02:00
4300d22cd9 feat: add background casting jobs 2026-09-04 09:17:56 +02:00
3456b5a3b0 feat: support character appearance forms 2026-09-04 08:51:33 +02:00
4ffe6e9012 feat: add consistent image job cancellation 2026-09-04 08:34:35 +02:00
3c6245a5f8 fix: repair split guillemet dialogue 2026-09-04 08:26:27 +02:00
fc0361bc71 feat: deduplicate casting requests 2026-09-04 08:10:55 +02:00
d21a6f28e8 feat: record protected generation history 2026-09-04 08:07:42 +02:00
8235b36afd security: validate upload filenames and archive paths 2026-09-04 08:04:26 +02:00
9517cca00c feat: detect stale character image identity 2026-09-04 07:59:17 +02:00