-
Notifications
You must be signed in to change notification settings - Fork 1
Release Notes v1.12
Covers the whole v1.12.x line: the v1.12.0 minor release plus its two same-day-and-next-day patches. v1.12.0 on GitHub · v1.12.1 on GitHub · v1.12.2 on GitHub.
A patch release: the Pinokio-installed server now reads its own settings. v1.12.1 got the Pinokio install running for the first time — which immediately surfaced a second bug the first one had been hiding: the server started, but from the wrong directory, so it silently ignored its own configuration. Fixed; a clean Pinokio Install → Start now comes up fully configured.
-
A Pinokio-launched server no longer boots on bare defaults. After the v1.12.1 fix let the one-click install actually run, the very next step exposed this: the launcher started the server from the app's top folder instead of its
server/folder, so the server couldn't find its own.env— the file that carries your workspace location, worker counts, GPU memory budget, and analyzer settings — and quietly fell back to defaults. It now launches from the right place (matching how the desktop app has always started it), so a Pinokio install comes up with its real settings from the first run. (#1513, #1514)
Full changelog: v1.12.1...v1.12.2
A patch release: the Pinokio one-click install actually completes now. A structural bug in the installer's own scripts — undiscovered until today's first real on-box run got far enough to hit it — made every install step operate one directory too deep. Fixed; nothing else changed since v1.12.0.
-
The Pinokio one-click install no longer fails on its very first step. Every
pinokio/*.jslauncher script (install/start/stop/update/reset) lives one directory below the app root, but Pinokio runs each script's shell/file-removal steps from that script's own directory by default — none of ours accounted for it, so the very firstconda installstep landed in the wrong place and failed with a cryptic "directory exists, but is not a conda environment" error. This has been silently broken since the Pinokio installer first shipped (2026-06-15); every earlier on-box attempt was blocked by an unrelated bug before ever reaching this step. All five scripts now explicitly target the app root. (#1508, #1509)
Full changelog: v1.12.0...v1.12.1
A more honest transcript, twice over. A new deterministic evidence pass now catches and corrects tag-proven speaker mistakes before you ever see them, replacing the analyzer's own inflated self-reported confidence with an honest, derived one — and Script Review's findings, like your cast's own state, now survive a reload instead of evaporating the moment you look away. A couple of reliability fixes round out the polish: a stuck Qwen voice design now recovers on its own, and the Pinokio one-click installer — broken by an incomplete first fix — actually installs now.
A structure-evidence pass now corrects tag-proven speaker mistakes before you ever see them, and replaces the model's own inflated self-reported confidence with an honest, derived value.
-
A new pure-code
server/src/analyzer/dialogue-structure/module family (per-language convention tables for en/es/fr/de/ru) slots intoattributeChapterStage2: a structure parser derivestag-name/tag-pronoun/alternation/unanchoredspeaker evidence per paragraph, an aligner matches it against the stage-2 model output (tolerant of glyph/whitespace drift), and a cross-examiner replays every sentence against that evidence with confidence values drawn from oneCONFIDENCEconstants block instead of the model's own — measured on a 14,065-sentence Russian book, every sentence self-reported confidence ≥ 0.8, so the existing< 0.75low-confidence triage view never fired despite heaps of real ambiguity. -
Two hard invariants: a
tag-nameattribution is never overridden by anything, including the new default-on'local'escalation pass over unresolved conversation windows (analyzer.structure.escalation); a dash-continuation sentence inside a speech span is exempt from the narrator-default demotion, closing a bug in the shipped plan-221 Wave A heuristic this engine absorbs. -
Engine-off (
analyzer.structure.enabled, default on), an unsupported book language, or a chapter's alignment rate falling below its floor all degrade to byte-identical pre-engine output. Two new additivestate.jsonfields (analysisProvenance: engine/model/timestamp; a per-run structure-engine report: aligned%/confirmed/corrected/flagged/escalated) close a forensics gap — nothing previously recorded which analyzer produced a given analysis. - New Castwright-owned dash-dialogue Russian fixture plus full unit/integration coverage across parser/aligner/cross-examiner/escalation/ windows. On-box acceptance against the full Ночной дозор book is owed post-merge. See plan 247 (#1482, srv-59, Closes #1471).
Findings from a script review used to live only in the moment — reload the page, close the tab, or click away, and they were gone, whether you'd acted on them or not. They now survive across a reload, and closing the results modal can never silently discard them.
- The server checkpoints each chapter's findings into a per-book on-disk ledger as a review runs — a mid-review reload reattaches to the same server-side job instead of losing it.
- The modal's close paths now dispatch a non-destructive hide; only an explicit, confirmation-gated "Dismiss all" discards findings. A badge + re-run confirm gate also stop a fresh review from starting blind over a chapter with unresolved findings already sitting untouched.
-
Fixed a data-loss bug found while shipping this: a single-chapter (or
partial) review run could silently wipe OTHER chapters' still-unresolved
findings out of the in-memory bucket, and mount-time hydration could
force-reopen a modal the user had explicitly hidden.
setReviewnow merges by chapter instead of a whole-bucket replace;hydrateBucketpreserves an existing bucket'svisibleflag. Seedocs/features/INDEX.md's fs-58 entry for the full design (#1479).
Any finished book can now export .srt/.vtt captions — line, sentence, or word granularity, whole-book or per-chapter — as a new captions BookExportJob format (fs-52, #PR).
-
Line and sentence captions are pure metadata reconstructions over
segments.json+manuscript-edits.json(server/src/export/build-captions.ts,caption-cues.ts,manuscript-sentences.ts) — no new render-time data, no synthesis-path change. Line cues cap at 7s / 200 chars and always close on a speaker change; sentence text is always read from the live manuscript edits, never the (potentially stale) analysis cache. -
Word captions add a new sidecar capability:
/transcribeaccepts anX-Word-Timestampsheader that requests faster-whisper's per-word alignment and switches oncondition_on_previous_textfor cross-window coherence — a distinct decode profile from the existing ASR content-QA caller, which never sets it, so that path is untouched. Always one whole-chapter Whisper call, run at export time only (never during synthesis). -
De-dupe and filenames are now caption-variant-aware: the export queue's same-format revocation and filename derivation key on
captionFileFormat/captionGranularity/captionScope, not justformat, so the 12 caption variants (2 file formats × 3 granularities × 2 scopes) no longer collide. -
A staleness guard protects against captions drifting from the audio. A segment whose
textHashno longer matches its current manuscript text fails the export outright with a "regenerate this chapter" error; a segment rendered beforetextHashexisted (pre-#1105) instead sets a non-fatal, persisted jobwarningsurfaced as an amber caption on the export-queue row — captions still ship, but flagged as unverifiable rather than silently trusted. - New Captions tile on the Listen view's "Or download a file" section (
src/modals/export-audiobook.tsx,src/components/listen/listen-download-section.tsx). See plan2026-07-10-fs52-caption-srt-export.md(fs-52, Closes #975).
-
A Qwen voice design could intermittently fail with a blank "Internal error."
_load_qwen_model(server/tts-sidecar/main.py) has hit a recurring, intermittentNotImplementedError: Cannot copy out of meta tensorwhen moving a freshly loaded VoiceDesign model onto the GPU since 2026-05-26 (86 occurrences) — some submodule the checkpoint doesn't cover lands on themetadevice, and every reload attempt in the same sidecar process keeps failing identically; only a fresh process has been observed to load cleanly. The load failure now schedules a sidecar self-recycle on a dedicated exit code (_MODEL_LOAD_FAULT_EXIT_CODE = 44, deliberately distinct from the memory-watchdog's restart code so it can't trip the Node supervisor's unrelated "device too small" streak-trip) — the failing request still surfaces its real error, but the next design attempt hits a clean process instead of failing forever. This is a mitigation, not a root-cause fix; the underlyingtransformers/qwen_ttsinteraction is tracked in #1469 (#1470).
-
Script Review's in-flight jobs can now be cancelled, and a reload can no longer silently start a duplicate re-review. Two narrow, deliberately-accepted gaps in the persistence work above (#1479) are closed. A new book-level
POST .../script-review/cancelreuses each running job's existingAbortController; a mid-chapter cancel now skips the checkpoint for the in-flight chapter entirely rather than persisting a partial result the ledger couldn't distinguish from a fully-reviewed one, and the SSE stream now ends with a terminalcancelledevent instead of hanging with no terminal event at all. A new join-onlyPOST .../script-review/attachcloses a TOCTOU race in the reattach-on-reload path: if the job finished in the gap between the client'sGET /stateand its join, the route now 404s instead of falling through to create a fresh job, and the client falls back to a plain ledger re-read instead of silently re-running the whole review.attachToRunningReviewdeliberately still never dispatches the sharedclearaction itself, preserving the persistence work's own concurrent-reattach fix (#1481). -
The off-roster reattribute confirm form could leak a field across a multi-op batch.
CreateCharacterForm's name/gender/ageRange fields are seeded viauseState(initial ...), which only runs on first mount;ScriptReviewDiff's confirm-queue overlay (src/components/script-review-diff.tsx) rendered the same JSX element across everyconfirm.indexadvance with nokey, so React reused the instance and a field typed for op N could survive into op N+1's own form — and, if unedited, reach op N+1's create/reassign call. The form is now keyed on the op's own identity (opKey) so it remounts, and its state resets, on every confirm-queue advance (#1480). -
The Pinokio one-click installer's menu was fundamentally broken, across two attempts to fix it. First surfaced during on-box acceptance (#822): root
pinokio.jsused CommonJS syntax (require/__dirname/module.exports) under the rootpackage.json's"type": "module", throwing aReferenceError(bug #1458) — "fixed" by rewriting it as genuine ESM (import/export default), on the assumption that Pinokio's runtime dynamicallyimport()s app scripts. That assumption was itself wrong (bug #1484): Pinokio's kernel (pinokiocomputer/pinokiod,kernel/loader.js,requireJS()) actually loads scripts with a plain synchronousrequire(filepath), which cannot load an ES module at all — so the install screen still never loaded, for a different reason. Rootpinokio.jsis now genuine CommonJS again, matching every otherpinokio/**script, and the rootpackage.jsonis"type": "commonjs"(was"module") to make that load correctly;eslint.config.js— the only other bare.jsfile at the repo root relying on ESM syntax — is renamed toeslint.config.mjsto keep working under the new default. The regression test nowrequire()s the entry viacreateRequireinstead of dynamicallyimport()ing it, so it actually reproduces Pinokio's real loading path (#1458, #1484, #1485). -
FlashAttention-2 detection is no longer Windows-only, and the stale
Windows pin is no longer the only path.
install-qwen3.mjs --flash-attnnow checks whetherflash_attnis already importable in the sidecar venv on ANY platform/accelerator profile first — if so, it just reports how to activate it (QWEN_ATTN_IMPL=flash_attention_2) rather than attempting a reinstall. On Linux, when it isn't already present and the standalone NVIDIA CUDA Toolkit (nvcc) is on PATH, the installer now attempts an unpinnedpip install flash-attn --no-build-isolationbuild; without the toolkit it skips cleanly instead of burning a doomed compile. The Windows pinned-wheel path (still cp311-only; the cp312/torch2.11/cu128 real-stack fix is tracked on side-22, #1001) is unchanged. (side-21, #1000) -
The library welcome subhead no longer hardcodes "book seven."
LibraryChrome(src/components/library/library-chrome.tsx) claimed a character "carries through to book seven" regardless of how many books are actually in the library — now reads "book after book," which holds true at any count (#1493, Closes #1461).
Full changelog: v1.11.0...v1.12.0
- Home
- Getting Started
- Installing Castwright
- Uploading a Book
- Manuscript Management
- Analysis & the Analyzer
- Reviewing Low-Confidence Speaker Tags
- Generating Audio
- The Quality Gate
- Listening & Revising
- Exporting