Commit Graph

56 Commits

Author SHA1 Message Date
268ed391a3 feat(magazine): EPUB 3 Media Overlay export with measured sentence timings; tolerate missing mutagen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 10:33:08 +02:00
4a20a12f66 feat(magazine): show sidebars in the reading view as labelled, never-narrated asides
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 10:26:27 +02:00
30b80fcbf7 feat(magazine): mark hand-edited text, show a word diff against the recognised text, restore it
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 10:24:27 +02:00
0f4b28ba14 feat(magazine): link a tail to its head from 'continued from page N'
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 10:20:35 +02:00
0005ae0ebd feat(magazine): import a magazine from PNG/JPEG page images
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 10:19:14 +02:00
1fb5528112 fix(magazine): drop hallucinated vision-OCR refusal text tiled over unreadable images
TODO A-E marked done for this pass; comparison report saved as evidence.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 23:26:59 +02:00
63cb129d24 fix(magazine): draw panel placed inside the window; Undo/Redo lead the toolbar's second row; lines and frames are not missed text
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 18:33:15 +02:00
1b9a4bd3bc fix(magazine): clipped-edge audit requires ink on the box's own text lines
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 17:54:12 +02:00
25eea74096 feat(magazine): mend column seams; docs: TODO for verify/re-import/compare and Voice Studio evaluation
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 17:44:28 +02:00
32a23a237a fix(magazine): dotted leaders and thin rules are not reported as missed text
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 17:34:06 +02:00
3d5da78a98 feat(magazine): blue unreviewed articles, auto-resolve overlapping boxes, ignore unboxed ink near graphics/ads, fewer false clipped edges
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 15:20:25 +02:00
c62cc6953d feat(magazine): auto-add figures for unboxed pictures, junk filter for linking, keep quality report in step
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 13:33:11 +02:00
bf5c795f02 fix(magazine): keep approval when auto-linking already-approved text
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 13:10:57 +02:00
4c1c97400b fix(magazine): apply column reading order automatically; article-end detection by signed end or following headline; link-next-page chip
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 13:00:14 +02:00
05bdecd58a feat(magazine): auto-link continuation pages, manual page linking, flow arrows by reading order, compact report, names/brands in spellcheck
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 11:46:32 +02:00
d0fba6a16f feat(magazine): text flow indicator (arrows, chips, reading-view seams); Auto-fix all pages with backup
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 10:46:55 +02:00
efaab0590e feat(magazine): cut a paragraph's box where its text wraps around an inset pull quote
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 09:50:26 +02:00
e00b215bc6 feat(magazine): detect inset pull quotes as their own region
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 09:27:04 +02:00
05a3ef4095 fix(magazine): full text with spelling underlines in review rows; drop [Non-Text]/hairline boxes; pad grown boxes
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 08:45:29 +02:00
d1c15b0e2b fix(magazine): boxes grow over cut-off lines without entering neighbours; re-read grown boxes
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 08:35:35 +02:00
e5bf4e70f9 fix(magazine): box_snapped/box_manual are Block fields (page re-OCR crashed rebuilding blocks)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 08:30:47 +02:00
3ec7f89009 fix(magazine): snap boxes also for vision-labelled paragraphs, per-side growth, run after page re-OCR
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 08:28:23 +02:00
559c165010 fix(magazine): suspect-OCR check uses page language and page vocabulary
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 08:23:09 +02:00
f4892dbde4 feat(magazine): fit text boxes to their ink in Clean up boxes
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 08:12:12 +02:00
91caa6cf90 feat(magazine): fuse paragraphs across columns/pages, article-aware acronyms, German/English spellcheck
- fuse_paragraph_blocks joins a paragraph split by a column or page break into one
  narration block (reader, podcast source and MP3), keeping source regions for highlighting
- language decided once per article; per-article acronym glossary (LLM classifies unknown
  acronyms from context), letter-spelled acronym lists, extended DE/EN database
- core/spelling: dictionary findings (compounds, inflections, line-break hyphens, other-language
  words), marked in review and listed per page/article; guarded LLM agent fixes; quality run
  now includes the spelling pass
- keep suspended compound hyphens (Programmier- und) when merging regions / building layouts

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 08:09:30 +02:00
48c546fbc8 fix(magazine): region-type picker and page-quality buttons work; stronger quality audit
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
- Export the region-type picker handlers and magRunPageQuality to the page (they threw
  "not defined", so the picker never opened and Find missed text / Verify OCR did nothing)
- Add a unit test that fails when an inline mag* handler is not exported
- Quality audit: pixel-level clipping check on all four box edges, duplicate-article
  detection, detected full-page advertisements skipped and shown green (no manual button)
- Driving mode text is karaoke-style (whole article, current sentence and word highlighted)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 23:07:19 +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
b1c0197652 Release v1.53.2
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
2026-09-24 07:44:16 +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
f24a83eb75 fix(magazine): screen invented picture/chart/table regions against page ink
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 05:03:57 +02:00
1edc941dbf feat(magazine): live region boxes in the import preview; interrupted imports no longer spin for ever
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
The preview carries each page's regions (percent of the page, type, reading
order) for the reading pass and the labelling pass, drawn over the page image
with a legend. A server restart that killed the import left it "running" for
ever; the status route now reports it as failed. v1.42.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 01:09:12 +02:00
703052d1d2 fix(magazine): adding a region crashed after a byline split; undo could roll back later changes
original_text is now a Block field, so paths that rebuild blocks keep it
instead of crashing. Undo snapshots are sealed with a digest of the saved
state and refused once anything else changed; actions without their own undo
point clear the Undo button. v1.41.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 00:50:33 +02:00
f155839300 feat(magazine): select many boxes and act once, undo instead of confirm, fold labels into new pictures
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
Bulk delete/type for a click- or rectangle-selected set; every destructive
region change returns an undo token (one level, refused once something newer
happened); text inside a region that becomes a picture is folded into it.
TODO: model-based layout detection (PP-DocLayout, LayoutReader) with licence
notes. v1.39.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 16:33:01 +02:00
99f2f2260e feat(magazine): edit, split, merge and re-OCR a region from its row, with keyboard control
Split at the cursor and merge-with-next keep article membership right; typed
letters in the editor never fire shortcuts; focus returns to the same row
after a redraw. v1.38.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 12:11:14 +02:00
b7aa823455 feat(magazine): clean up boxes - text in pictures, OCR noise, duplicates, run-on author lines
Rules sized on a real 204-page issue before writing them; each re-types
(not read aloud, reversible), none deletes. A run-on author line's sentence
becomes its own paragraph instead of being glued to "the next paragraph",
which was right in only 1 of 5 real cases. Runs on import and re-OCR, and on
demand with a layout backup. v1.37.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 12:06:33 +02:00
baab49dbdf feat(magazine): set a page's reading order by hand (type a position or click in order)
A hand-ordered page is locked: Fix reading order, type changes and newly drawn
boxes leave it alone until Automatic order. v1.36.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 11:58:37 +02:00
fd1de80f83 feat(magazine): column reading order, region type picker and delete per row, fix reading order
Columns are found from where column-width text starts, not from the whitespace
between them (loose OCR boxes shrank one gutter to 4-6 pt and a pull-quote
bridged it, collapsing page 38 into one interleaved column). Headlines get
their own band, pull-quotes are read at the end of the page. Measured over a
204-page issue: 89 sentence continuations kept vs 85.

Each review row gets a type picker (text kinds, page number, source, ad,
image) and its own delete button; text<->image conversions keep the region
in its article. Fix reading order re-reads existing issues without OCR and
leaves hand-ordered pages alone. The shared confirm dialog is now an
alertdialog for screen readers. v1.35.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 11:38:33 +02:00
2dd5cea7b7 feat(magazine): let review screen boxes be moved, resized, deleted, and re-OCRed in place
Some checks failed
Test and SonarQube / quality (push) Has been cancelled
Adds "Edit boxes" mode to article review: drag an already-detected
region to move it, its corner handle to resize it, or press its x to
delete it -- for correcting a box the layout engine got wrong, not one
it missed entirely ("Draw it" still covers that case). Moving or
resizing opens a confirm panel; "Save" keeps the region's existing
text at its new position, and for text regions "Save & re-OCR" reads
the corrected area again and replaces the text.

New core/magazine.py update_region()/delete_region() and PATCH/DELETE
/api/magazine/{doc}/pages/{page}/regions/{block_id}. An image region
is re-cropped from the page render whenever its bbox changes, since
its saved file is exactly that crop.

Live-verified against the real ingested c't KI Wissen 2026 magazine:
add -> move -> move+re-OCR (correctly kept old text when the corrected
area had nothing readable) -> delete -> confirmed gone, repeat delete
404s.

275 tests passing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-15 12:40:07 +02:00
c81ae28da2 feat(magazine): add figure/chart/table description generation and spoken narration
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
Adds a "Describe" action per figure in article review: sends the cropped
image to the configured vision engine (with fallback) for a type-aware
one- or two-sentence description -- a chart gets a prompt about what it
measures and its trend, a table about headings and what stands out, etc.
Editable before approval. A new "Read figure descriptions" toggle in the
reading controls speaks these where they occur; purely additive, off by
default, and a figure with no description behaves exactly as before.

New core/magazine.py describe_visual_region()/_chain() reuse the same
reliability guards as page OCR (repetition-loop detection, sentence-
boundary truncation). New routes: POST .../images/{id}/describe
(background job), PATCH .../images/{id} (manual edit), descriptions=1 on
the article-text endpoint.

Live-verified end to end against the ingested c't KI Wissen 2026
magazine. Also found and documented a real, config-dependent limitation:
the currently-configured primary vision engine is transcription-only and
returns empty content for any descriptive prompt (confirmed with three
different prompts) -- not a code defect, but description generation
needs a genuinely caption-capable engine reachable as the fallback.

251 tests passing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 17:39:57 +02:00
a78dac98fa fix(magazine): catch vision OCR decoding loops before they become page text
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
Confirmed live: re-ingesting c't KI Wissen 2026 with a local Qwen VL
engine, page 18's chart transcription degenerated into "das Produkt,
das Produkt, das Produkt, ..." repeated hundreds of times, filling the
whole response budget -- and was accepted as real region text, which
would have been narrated verbatim.

The codebase already had two narrow signatures for specific observed
failures (a formatting-instruction echo, a fabricated LaTeX loop), both
scoped to the plain-text fallback path only. Added a general detector
(_looks_like_repetition_loop): any short phrase containing a real word,
repeated 8+ times immediately back-to-back. Deliberately excludes
patterns with no letters -- a dot-leader contents line, a repeated
number sequence -- which are legitimate and must not be flagged.

Applied at both call sites: vision_ocr_page (the labelled-region path
most engines use) and _whole_page_region (the plain-text fallback).
Treated as a failed call in both, so vision_ocr_page_chain's existing
fallback (secondary engine, then tesseract) gets a real chance instead
of garbage being accepted as the page's transcription.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 10:09:32 +02:00
b458306ab9 fix(magazine): recover sparse charts, stabilize adjacent-figure snapping
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
Real failures found by re-inspecting a fresh re-ingest of c't KI Wissen
2026 after the previous figure-boundary-snapping release: a bar chart
was still truncated to roughly a third of its real height, and a
chart's top edge cut into an unrelated paragraph above it.

Root causes, each independently confirmed against the real page render
before fixing:

- A bar chart's bars/gridlines/axis labels rarely reach the "solid
  ink" density a photo does (measured 0.25-0.5 vs the 0.55 threshold),
  so the existing pass anchored only on the one fully-solid element
  (the zero-line) and never grew further. Added a second, looser pass
  that grows an anchor -- or the seed itself -- through any real mark
  at all, fenced by the same blocked cells.

- Anchor selection ("which solid component does the seed overlap
  most") was seed-size-dependent: a small seed touching only the
  zero-line anchored there, but re-running the SAME function on the
  box it had just produced -- now large enough to also touch a dense
  axis-label strip -- picked that instead and shrank an already-good
  box back down. Fixed by dilating the solid mask and labelling once,
  BEFORE any seed is considered, so which components count as one
  figure is a property of the page alone.

- A merged bounding box can enclose real text sitting between two
  components even though neither component's own cells touched it (a
  rectangle union, not the components' actual shape). Added
  _trim_blocked_edges() to pull each edge back to the nearest text
  wall found searching outward from the box's own centre.

- Two adjacent figures fencing each other's growth made each one's
  result depend on the other's CURRENT box -- for two dark photos
  sharing a caption strip, this never settled, swinging by over 100pt
  call after call. snap_visual_bboxes() now re-seeds every visual on a
  page from every other's last result for a bounded number of rounds,
  deciding same-graphic ambiguity once up front (fenced against the
  original seeds, before any iteration) so two disputed seeds can't
  mutually fence each other into a tidy-looking split instead of being
  recognised as the same disputed claim.

- A result is now only accepted once it reproduces itself when fed
  back through the same rules (IoU-checked), and the minimum
  seed/graphic overlap for repositioning a badly-offset box was
  lowered slightly -- it was narrowly rejecting some real cases.

Verified against the full 204-page/147-figure document: idempotency
holds except for one confirmed non-convergent pair, which now lands on
the same deterministic answer every run instead of continuing to
drift.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 21:21:04 +02:00
96b0b9dd71 fix(magazine): finish and harden the live ingest preview
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
Resumes an in-progress, uncommitted change from a previous session: the
live "page image + recognised text" preview shown during ingestion was
reworked to render formatted HTML (styled headings, a figure
placeholder) instead of a plain-text dump, but was left with a
duplication bug, dead code, inline styles, and no tests.

- Fixed duplication: a figure block's own transcribed text (usually its
  on-screen UI copy) was rendered as an ordinary paragraph in addition
  to the new figure placeholder box. Figure/chart/table/code blocks are
  now represented only by the placeholder.
- Furniture/sidebar/pullquote/ad text is shown muted instead of being
  dropped with no replacement, and is never promoted to a heading
  regardless of font size.
- Factored the formatting logic out of the progress closure into a
  standalone, unit-tested _render_ingest_preview_html().
- Replaced dead getattr(bbox, "y0", ...) calls (bbox is always a plain
  [x, y, w, h] list) with direct indexing, moved statistics/logging
  imports to module level, switched manual character replacement to
  html.escape(), and bounded the preview by an accumulated line budget
  instead of a blind slice that could truncate mid-tag.
- Replaced inline style="..." with CSS classes matching the panel's
  existing dark console treatment.
- The frontend now always uses innerHTML (every text node is escaped
  server-side), dropping the startsWith('<') content-type sniffing.
- Marked the preview panel aria-hidden -- decorative, and would
  otherwise churn noisily for screen reader users on top of the
  adjacent progress bar.

Verified against the real c't KI Wissen 2026 layout: a figure's raw
OCR text no longer appears twice, a real headline renders as <h3>, a
footer/pull-quote render muted, and all text is correctly escaped.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 15:24:16 +02:00
55f147d7a7 fix(magazine): derive figure boundaries from the page render
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
A vision OCR engine grounds a figure far less precisely than it
transcribes one. Over all 138 figure regions of a 204-page issue the
transcribed contents were right while the boxes were routinely offset,
undersized, or sitting on the neighbouring text column -- page 23's card
grid was reported at x 0.24-0.54 where the graphic runs 0.41-0.95.

snap_visual_bboxes() reduces the page render to an ink-coverage grid,
seeds a connected-component search with the engine's box, and re-joins
tiles a gutter apart so a card grid comes back as one figure. Text
blocks are excluded from the mask, which is what stops a figure
swallowing the column beside it. A candidate must be solidly inked or
framed on nearly all of its rows and columns (admitting a white-interior
screenshot), may not shrink below 30% of the seed, and reverts when two
figures land on the same graphic; anything else keeps the box it had.

Runs before the figure crop in both OCR paths, so the images shown
during playback are framed correctly too. Replaces refine_picture_
bounds(), which only recognised coloured panels and had no text fence.

Also adds "Fix figure boundaries" in review and POST
/api/magazine/{id}/figures/refine behind it, so an issue ingested before
this pass can be corrected without re-running OCR. Verified live against
c't KI Wissen 2026: 78 of 138 boxes corrected, the rest declined.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 10:17:00 +02:00
f5f887bb1d Release v1.26.11: Enhanced layout-aware OCR element recognition, grounding parsing, and preview thumbnails
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
2026-09-10 13:08:53 +02:00
e6211f1333 Release v1.26.9
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
2026-09-10 12:45:42 +02:00
9b1e29bb79 feat: automate semantic magazine layout
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
2026-09-09 17:48:56 +02:00
31b13a4e16 feat: improve magazine review navigation
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
2026-09-09 17:36:27 +02:00
272d4872bd fix: use native Unlimited-OCR layout regions
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
2026-09-09 13:27:14 +02:00
037f3dd74d fix: stabilize OCR and character sheet casting
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
2026-09-09 07:51:59 +02:00
b7aade39db Release v1.26.1
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
2026-09-08 23:39:44 +02:00