Skip to content

Separate the preview fidelity and origin from the fast canvas (#28) - #201

Merged
mberrys merged 3 commits into
devfrom
codex/issue-28-production-preview
Oct 5, 2026
Merged

mberrys merged 3 commits into
devfrom
codex/issue-28-production-preview

Conversation

@mberrys

@mberrys mberrys commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

What changed

Implements #28 (L03-02 — Separate Production Preview from fast canvas). The ordinary canvas and the authoritative Production Preview now display render fidelity and origin from one projection; overprint-sensitive content is switched explicitly to the authoritative output-preview render before it is presented as proof; and approximate canvas pixels are never presented as proof of print-safe output.

This is a delta on top of what already shipped: PreviewStateModel already carried Authority/authorityName, EditorHost::previewIdentity/previewSummary/previewSummary already drove the Production Preview workspace, pageFidelityIsExact/pageFidelityIsAuthoritative/toggleCurrentPageFidelity already existed (#49), and Core already owned the renderer's overprint/transparency behaviour and its differential goldens. The audit found three real gaps: neither surface named the render origin; the Production Preview could still describe an overprint-sensitive fast render without saying its pixels are not proof of print-safe output; and nothing made the switch to the authoritative render an explicit, pre-claim step.

Per-criterion: already satisfied vs built

Issue #28 criterion State on dev This PR
Display render fidelity on the ordinary canvas Already satisfied: CanvasPane's renderFidelityBanner shows Approximate/Accurate per page (#49) Extended: the banner renders previewFidelitySummary, naming fidelity and origin, and is always up while a document is open
Display render fidelity and origin on the authoritative Production Preview Partially: the pane showed pageFidelityIsExact/reason only; no origin, and pageFidelityIsAuthoritative was unused Built: the pane renders previewFidelityVisual/previewFidelitySummary plus a Fidelity …, origin … line from previewFidelityStateName/previewFidelityOriginName
Overprint-sensitive content explicitly switches to authoritative preview before print claim Missing: only a manual per-page canvas toggle; the document-wide preview authority stayed Approximate Built: previewRequiresAuthoritative() (exactly the approximate state) and EditorHost::ensureAuthoritativePreview(), bound to a new "Proof this page (authoritative render)" affordance in the pane
Failure case: approximate canvas pixels cannot be cited as proof of print-safe output Missing as a state/contract Built: approximate is its own state, previewFidelitySummary() states the pixels cannot stand as proof of print-safe output, and no preview state resolves to a pass (previewFidelityNeverClaimsAPass)
Required proof: visual fixtures for overprint, transparency, fidelity state Overprint + transparency goldens already committed (overprint-cmyk-mode1-on.png, flatten-transparency-normal-cmyk.png) Fidelity state added: UnitTestsPageSurface::fastCanvasOverprintRenderIsNotTheAuthoritativeGolden renders the same page with and without the authoritative marker and proves the fast render does not match the golden while the authoritative one does

New production surface (all render Core/host facts, derive no verdict):

  • LoopLibQuick/sources/loopstatevisual.* — classifyPreviewFidelityState, previewFidelityOriginName, resolvePreviewFidelityStateVisual.
  • LoopEditor/editorhost.* — six read-only properties + ensureAuthoritativePreview().
  • LoopEditor/qml/ProductionPreviewPane.qml (+ mirror) and LoopEditor/qml/CanvasPane.qml (+ mirror).

Release changelog

Topic PR: see changes/codex-issue-28-production-preview.md. The issue stays open on merge (dev is not the default branch); close it explicitly when the release promotion lands.

Proof

  • check-change.py — status: pass (report: $LOCALAPPDATA/Temp/issue28-check-change.json). Command and observed result below.
  • One changes/codex-issue-28-production-preview.md fragment (Category/Audience/Breaking-Change/Summary)
  • Changed behaviour has tests that fail without the change (all three new slots are new; the loop-state and page-surface slots discriminate on the new resolver/vs-golden facts)
  • No protected-path or contract change

Commands and observed results

Image: Windows 11 / MSVC 14.44 / Qt 6.11.1 (aqt) / Ninja; build dir C:/.dev/repos/loop-build-28, configured with the agent-fast options (-DLOOP_BUILD_QUICK_SHELL_SMOKE=ON -DLOOP_BUILD_PRODUCT_QUICK_A11Y_SMOKE=ON -DLOOP_BUILD_CANVAS_BENCHMARK=OFF).

LOOP_SRC=<worktree> bash loop-build-parity.sh cmake --build C:/.dev/repos/loop-build-28 \
  --target UnitTestsLoopStateVisual UnitTestsEditorHost UnitTestsPageSurface -j 5
# exit 0

LOOP_SRC=<worktree> bash loop-build-parity.sh ctest --test-dir C:/.dev/repos/loop-build-28 \
  -R '^(UnitTestsLoopStateVisual|UnitTestsPageSurface)$' --output-on-failure
# 100% tests passed, 0 tests failed out of 2

LOOP_SRC=<worktree> bash loop-build-parity.sh ctest --test-dir C:/.dev/repos/loop-build-28 \
  -R '^UnitTestsEditorHost$' --output-on-failure
# 1/1 Test #11: UnitTestsEditorHost ..............   Passed   26.20 sec
# 100% tests passed, 0 tests failed out of 1

UnitTestsLoopStateVisual.exe -o junitxml  -> tests="156" failures="0" errors="0" skipped="0"
UnitTestsEditorHost.exe  -o junitxml     -> tests="21"  failures="0" errors="0" skipped="0"  (includes previewFidelityNamesTheOriginAndSwitchesExplicitly)
UnitTestsPageSurface.exe -o junitxml     -> tests="27"  failures="0" errors="0" skipped="0"  (includes fastCanvasOverprintRenderIsNotTheAuthoritativeGolden)

LOOP_SRC=<worktree> bash loop-build-parity.sh python scripts/agent/check-architecture.py \
  --base <base-sha> --head-branch codex/issue-28-production-preview
# architecture contracts ok   (exit 0)

LOOP_SRC=<worktree> bash loop-build-parity.sh python scripts/agent/check-change.py \
  --base 0f2f7599e3e17ce4e57bfdedfce85582c8f51115 --head-branch codex/issue-28-production-preview \
  --build-dir C:/.dev/repos/loop-build-28 --report .../issue28-check-change.json
# status: pass
# 44 checks, 44 pass, 0 non-pass; head_sha a0195ea178019ea9092f495e7d5e66a249624c75
# modules: documentation, interaction, quick; protected_paths: []; risk: standard
# 20 mapped tests built and run (focused_tests pass); clang_tidy, format and source_integrity pass

python scripts/ci/check_preflight_truth_source.py   -> passed: 32 GUI files derive no verdict
python scripts/ci/check_qml_mirror_parity.py        -> passed: 15 mirror pairs byte-identical

check-change.py selection for this change set (--dry-run): modules documentation, interaction, quick; targets LoopEditor, LoopLibInteraction, LoopLibQuick, ProductQuickAccessibilitySmoke; 20 mapped tests. The full run's report is quoted below.

Internal logic

  • Guard clauses handle absent/stale/authoritative/inexact cases before naming a state (classifyPreviewFidelityState orders unavailable → stale → authoritative → approximate → exact); ensureAuthoritativePreview() refuses when there is no document or the page is already authoritative/exact.
  • No untrusted input is parsed; the projection only reads Core/host facts (pageFidelityIsExact, pageFidelityIsAuthoritative, previewStaleReason).
  • No mutation on an invalid state: ensureAuthoritativePreview() returns false without touching the coordinator.
  • Names carry the domain intent (previewFidelityStateName, previewFidelityOriginName, previewRequiresAuthoritative); comments give the rationale (why authoritative outranks pending diagnostics).

Quality summary

Added: one pure classifier, one origin lookup and one visual resolver in LoopLibQuick, six read-only projections and one invokable in EditorHost, and the QML that renders them. Kept on purpose: pageFidelityIsExact/pageFidelityIsAuthoritative/toggleCurrentPageFidelity (the underlying facts) and the #49 canvas banner/toggle, now fed by the shared projection. Removed nothing but the pane's duplicated inline fidelity wording.

Security and rollback

  • No untrusted input; no new unsafe construct. ensureAuthoritativePreview() only changes which render path a page uses; it writes nothing and is not an approval.
  • Rollback: git revert a0195ea1; the change is additive on the preview surface.

Docs

docs/RENDERER_DIFFERENTIALS.md gains the "Fidelity and origin on the two preview surfaces (#28)" section describing the vocabulary, the explicit switch and the fidelity-state proof.

Self-review (BSP-002 §4.3)

Anti-slop: the diff adds a small, pure state machine and renders it, rather than re-deriving fidelity in QML — the two panes now share one projection and the words come from previewFidelitySummary, so there is one place to keep honest. The one judgement call is calling the non-overprint fast path exact: that mirrors the existing diagnostics semantics ("no overprint content, or none known yet") and the summary still says the interactive preview does not certify print-safe output.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

mberrys and others added 3 commits October 3, 2026 23:18
The canvas and the Production Preview both showed something about render
fidelity, but neither named the render origin, the document-wide preview
authority never left Approximate, and no surface said that an approximate
overprint render is not proof of print-safe output (#28).

Add pdfquick::tokens::classifyPreviewFidelityState / previewFidelityOriginName /
resolvePreviewFidelityStateVisual and project them through EditorHost as
previewFidelityStateName / previewFidelityOriginName / previewFidelityVisual /
previewFidelityColor / previewFidelitySummary / previewRequiresAuthoritative.
Both the ordinary canvas banner and the Production Preview render that one
projection: fidelity unavailable/stale/exact/approximate/authoritative, origin
none/fast-canvas/output-preview. The overprint-sensitive fast render is the
`approximate` state, whose summary says its pixels cannot stand as proof of
print-safe output and which no state resolves to a pass.

EditorHost::ensureAuthoritativePreview() is the explicit switch the preview
surfaces call before a page is presented as proof: it moves the current page to
the output-preview render and returns false when it is already authoritative or
exact. The Production Preview gains a "proof this page" affordance bound to it.

Proof: UnitTestsLoopStateVisual (classification, origin, distinct shapes, never
a pass), UnitTestsEditorHost::previewFidelityNamesTheOriginAndSwitchesExplicitly
(the projection and the explicit switch on a real overprint fixture), and
UnitTestsPageSurface::fastCanvasOverprintRenderIsNotTheAuthoritativeGolden (the
fast render does not match overprint-cmyk-mode1-on.png while the authoritative
render does, and the fast diagnostics report the approximation).
…ritative-but-inexact visible

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@mberrys
mberrys merged commit d35287c into dev Oct 5, 2026
16 checks passed
@mberrys
mberrys deleted the codex/issue-28-production-preview branch October 5, 2026 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant