Two bugs made centered/right-aligned heading edits vanish on commit:
1. Gateway: ReflowParagraphData.align was Literal["left","justify"], so a center/right reflow
commit failed Pydantic validation -> 422 Unprocessable Entity. Widened to include
"center","right" (matches the frontend + engine, which already handle them).
2. Frontend: gatewayService.applyEdits caught ALL errors (incl. HTTP 422/403/500) and returned
fake success with a phantom `${documentId}_edited` id. The app then adopted that id and 404'd
on every fetch, so the edit silently reverted instead of showing an error. Now only genuine
network failures use the offline fallback; real HTTP errors throw the gateway's detail so the
caller toasts a clear message and stays on the current document.
Gateway runs with --reload (auto-picks up the model change); frontend needs a refresh.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reflow (primary editor):
- Geometric backstop in reflow_paragraph: adopt any text object fully inside the paragraph
bbox that the model's objectIndices omitted (PDFium glyph->object map can return -1), so it's
deleted + its original font is resolved. Fixes both the leftover-glyph "bulge/merge" and the
font-substitution-on-edit (same root cause). No-op on correctly-indexed paragraphs (gate-proven
byte-identical: overlay diff unchanged at 1.69%/1.70%).
- Preserve data-fid on edited contentEditable nodes (extractFlatRuns climbs to nearest styled
ancestor / inherits from adjacent run) so edits keep their real font instead of the dominant.
- Converge preview & commit through one buildReflowData (no preview-OK/commit-wrong drift).
- Center/right alignment: additive emission branch (greedy path only) + heading-align inference.
- IME composition handling (suppress render mid-composition; don't commit on composing Enter).
- Fix WASM document-handle leak (free superseded versions on documentId change/unmount).
- Quiet the backstop instrumentation (warn -> debug) now the root cause is confirmed.
Raw Text / StreamEditor (beta companion):
- Permission-gate both text_objects endpoints behind canModify; label tool "(beta)".
- P1a: preserve TJ kerning numbers for same-length edits (redistribute into original slots),
fall back to single-string collapse otherwise (never worse than before).
- P1b: reject edits with characters unencodable in the run's font (clear 400 instead of corruption).
- P2a: commit Raw Text edits as a new document version (add_document) and adopt the id via
pushHistory, so they join undo/redo instead of mutating in place.
- P2b: exact hit-boxes from real font metrics (re-measured once @font-face loads).
WASM preview rebuilt with the reflow changes; cache version bumped.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>