Commit Graph

28 Commits

Author SHA1 Message Date
1fd79866f8 chore(qa): central npm run qa command with optional SonarQube stage
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 18:36:48 +02:00
5dbe8c8998 docs(voices): archetype gallery manual and architecture
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 18:23:44 +02:00
e1aca0ba34 feat(magazine): exclude entries from the untitled-page cleanup
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 22:06:28 +02:00
48af2b3ccb feat(magazine): detect continuation pages and suggest titles for untitled articles
"Page N" entries come from review stand-ins created after Approve saved only
the visible page's regions. New core/magazine_untitled.py classifies untitled
entries (continuation, article head, advert, picture page, contents, junk),
proposes merges into the previous article with confidence and evidence
(optional LLM check in the ambiguous band), and suggests titles
(deterministic, optional validated and cached LLM titles). Exposed through
derived GET /articles fields, GET /untitled, quality report, undoable
merge-into-previous / accept-title routes, POST /titles/suggest and
scripts/magazine_untitled.py (dry run by default, --apply backs up first).
Merges mark audio_stale; no audio is deleted; real titles are never
overwritten.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:36:29 +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
e60126721d feat(magazine): record/replay cache for vision responses in OCR comparisons
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 11:09:17 +02:00
35e0a64665 feat: OCR benchmark harness and first candidate results (docling, PaddleOCR)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-29 17:55:48 +02:00
faa3c16a91 fix(magazine): exclude advertisement pages from magazine-comparison statistics
A page either side marks as a full-page ad is skipped by that side's quality
run, so comparing its near-empty boxes against the same page freshly OCR'd
on the other side (ad-marking is a one-time manual step) was a review-state
difference, not a pipeline one, skewing whole-issue numbers. Verified: text
similarity 0.837->0.870, box precision 0.62->0.66 on the real re-import.

Also records the clean from-scratch re-ingest results: the ingest-time
duplicate-check ordering fix is proven in isolation (0 additional duplicates
found afterward, vs 13 before the fix), and the auto-chained Auto-fix ran
end to end.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 13:11:00 +02:00
d06f990379 feat(magazine): fast LLM calls for spelling agent, run-together word repair, magazine comparison tool
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 20:09:42 +02:00
03597d37f0 fix(release): keep index.html's cache-busting version tags in sync
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
static/index.html hardcodes ?v= query strings on style.css, the per-page
CSS files and loader.js, plus an app-version meta tag. Nothing kept them
in sync with VERSION, so they'd silently drifted to different stale
versions each (found live: style.css one release behind, loader.js
sixteen releases behind). The static-file middleware marks any CSS/JS
request with a ?v= query as max-age=31536000 immutable, so a browser
that had ever loaded e.g. magazine.js?v=1.26.10 kept serving that exact
response for a year no matter how many times the file changed on disk
or how hard the page was force-reloaded.

release.py now rewrites every ?v=X.Y.Z and the app-version meta tag to
the new version on every release, so a release is what invalidates the
cache rather than a manual, easy-to-forget edit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 20:28:46 +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
c43a11da68 perf: lazy-load section feature modules 2026-09-04 10:23:20 +02:00
a714ea0273 test: add frontend quality gate 2026-09-04 09:26:01 +02:00
cc8fcdbd69 refactor: share frontend module manifest 2026-09-04 09:15:41 +02:00
fe807d1682 Release v1.22.2 2026-09-03 16:12:02 +02:00
f7264a8c07 chore: release 1.21.0 - Consistent ComfyUI Character Renders and Audiobook Export
- Deterministic hash-based character portraits and reference sheets
- Implemented strict early Renaissance aesthetic controls and role-specific headwear rules
- Added audiobook batch export scripts and progress tooling
- Verified book profiles with a new 'confirmed' state tracking mechanism
- Updated Pillow dependency for robust image handling
- Configured .gitignore for audiobook and audio cache exports
2026-08-23 09:12:57 +02:00
b953ba1a83 Refactor table and audiobook helper modules 2026-08-19 16:39:17 +02:00
da3d442656 Add one-command runner for the book01 manual-vs-automated cast comparison
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 11:15:35 +02:00
737687789f Add cast comparison tool for validating automated casting against a manual one
Matches segments by normalised text rather than index (a recast splits and
merges segments, so indices never align) and reports where the automation
disagrees with a hand-corrected cast: lines left Unknown that the human
resolved, lines given a different speaker, and narration/dialogue type
disagreements. Intended for using a manually-optimised book as ground truth to
drive further attribution-rule work.

Known limitation: repeated identical lines match the first occurrence, so
duplicates can mispair.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 11:09:38 +02:00
ea50267c30 Add unified Studio casting workflow and fix voice/casting pipeline bugs
Introduces the new Studio section (Source -> Characters -> Voices ->
Perform & Export) that reuses the existing Read Aloud/Library/Script
Rehearsal code via DOM reparenting instead of duplicating it, and rolls up
a long tail of bugs found while producing a real audiobook through it:
umlaut-eating name sanitizers, a voice picker that mispositioned itself and
capped results at 60, PDF pagination silently breaking on trimmed \f
markers, a race letting stale audio keep playing after a new line was
clicked, an alias-overlap bug that could silently redirect a voice/image
save onto the wrong character, voice design failing outright during brief
TTS backend restarts instead of retrying, sparse cast entries defaulting to
English/wrong gender, and a reassigned voice never reaching an already-open
Stage session or invalidating its cached audio. Also adds a persistent
per-line audio cache, audiobook export browsing/download, and an inline
voice-design prompt editor. Full details in CHANGELOG.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 02:03:56 +02:00
bc6c4842b5 Optimize startup and persist engine keys 2026-06-30 14:52:17 +02:00
586dc3dc3f release: v1.12.52 2026-06-30 13:53:08 +02:00
52994df70b feat: unified Library + character tags + shared cast (v1.10.0)
Restructure the sidebar into Voices / Speak / Setup groups and fuse the
Read Aloud and Script Rehearser features into one workspace:

- New combined Library section (Books · Theater Plays · Characters/Cast)
  with cross-links (Rehearse a book, Read Aloud a play).
- Character tags like voice tags: one record, many productions, reusable
  across books/scripts; seeded with origin book, editable in the editor.
- Shared cast resolution: opening a production fills empty cast slots from
  the character roster (matched by book OR tag); voice choices written back
  on save. Productions joined by normalized title (prodKey).
- Tags nav group for voices (distinct tags + counts, Cloned/Designed/Fav).
- Fold standalone Characters into Library; Read Aloud now a single entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 12:12:22 +02:00
495550bf6a Release v1.9.0 — Character Library + richer character sheets
Add a persistent, book-scoped Character Library (new Characters section,
IndexedDB) that auto-fills from Character-sheet analysis with editable cards.
Enrich extraction with six narrative fields (backstory, relationships,
motivation, fears, mannerisms, voice/speech) plus the greyscale Good↔Evil
alignment bar, arc arrow, and 5-area Deep Analysis. Add ⋯ separators between
non-contiguous passages in Recast unknown, and harden dialogue attribution
against hallucination with same-language emotion tags.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 21:22:40 +02:00
88c74ab826 feat: persistent seed pinning and batch seeds 2026-06-22 10:43:56 +02:00
36437478a6 feat: Read Aloud reader, multi-voice audiobook casting, character sheets (v1.7.0)
Read Aloud (new "Vorlesen" tab):
- PDF (real page render + overlay highlight) / TXT reader with live word
  highlighting, voice + speed, per-sentence synthesis-state colours, zoom
  (fit-width/height, two-page, ±), resume, and a server-side book library
  (syncs across devices; per-unit MP3 audio fetched on demand).

Book -> multi-speaker audiobook:
- "Cast as audiobook" attributes dialogue to characters via the LLM
  (guillemet/quote-style aware, turn-taking, recent-context), with a
  deterministic speech-tag fallback. Editable preview, non-blocking live
  casting panel, then auto-saved as a reopenable Script Rehearser play.
- Audiobook export: synthesise every cast line -> one MP3 per chapter.

Character sheets:
- LLM-extracted, self-filling RPG-style sheets (with page+quote sources)
  in both Read Aloud and the Rehearser.

Also: MP3 storage + per-page/sentence export, voice-library "Precompute
embeddings" pre-warm, German "Vorlesen" i18n + flag language toggle,
large-PDF performance (lazy raster, buffer/canvas eviction, yielded parse),
and the Seed Finder changelog entry.

New: routes/reader.py, POST /api/attribute-dialogue, POST /api/character-sheets,
static/js/{reader,audiobook,character-sheets}.js, static/sections/s-reader.html.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:08:46 +02:00
40e42590cc Release v1.6.0: a11y (WCAG AA), i18n (DE), PWA, perf, tests, Cast UX
Cast: card/list views, sort & filter, online voice picker, "Hear a line"
sample button, AI character notes, import auto-save.

Platform: WCAG 2.1 AA accessibility pass; German UI translation + language
picker; installable PWA with offline shell; GZip + content-visibility
virtualization + lazy images + Rehearser PCM memory cap (mobile stability);
Playwright suite (desktop + iPhone); opt-in minified bundle build.

Fixes: screenplay parser false characters; Fish-Speech inline-tag tones;
narrator/voice pickers list full library; clone GUI rework; fish.audio
import dedup; voice-ID rename; bulk-delete modal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 14:23:35 +02:00
06ed33ca67 Add release automation: version bump script and pre-commit changelog hook
scripts/release.py:
  - --patch/--minor/--major flag bumps VERSION file
  - Renames [Unreleased] → [x.y.z] — date in CHANGELOG.md
  - Inserts fresh [Unreleased] section + correct compare links
  - Commits + creates annotated git tag
  - --dry-run flag for preview without writes
  - Prints git push + GitHub Releases URL on completion

scripts/hooks/pre-commit:
  - Warns (exit 0, non-blocking) when source files are staged but
    CHANGELOG.md or VERSION are not staged
  - Already installed in .git/hooks/

scripts/install-hooks.sh:
  - One-liner to install hooks after a fresh clone

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 14:14:41 +02:00