Commit 796b1e7
Proposal B PR-1: batch prior-resolution (appropriate-bleed machine-vote lean) (#72)
* Add Proposal B survey + HOLD: export-time per-side bleed normalization
The branch this was originally scoped against (claude/print-preview-
xml-2) sits at the Proposal D commit with zero Proposal-B-specific code
or design doc - the queue's "resume Proposal B to completion" gloss
("export-time per-side bleed normalization") is compatible with two
genuinely different features with very different risk profiles, and
guessing which one blind isn't a reasonable substitute for a spec that
never reached this session.
Surveys the current uniform-scale bleed handling in PDF.tsx, the
backend's already-validated whole-image bleed/trimmed classification
(reusable technique, but binary and currently unpopulated in
production), and proposes two candidate designs: automatic per-edge
detection+auto-correct (higher risk - a wrong heuristic silently
mis-crops real print orders, no validated real-image sample to trust
it against yet) vs. manual per-side controls in the existing Proposal A
WYSIWYG preview (recommended MVP - no heuristic-correctness risk,
additive to layout.ts/PagePreview.tsx/PDF.tsx). HOLD pending the
owner's choice between them.
* Build Proposal B: export-time per-side bleed normalization (core + wiring)
Implements the approved spec (docs/proposals/proposal-b-bleed-
normalization.md, recovered after a courier loss): measures each card's
real per-side bleed via probe-median + IQR-ambiguity sampling
(bleedNormalize.ts), resolves a trim/extend plan against the target
bleed with a fallback prior and three manual-override modes, and
synthesizes the corrected image via canvas crop+edge-extension
(bleedExtension.ts). Wired into PDF.tsx's PDFCardImage for full-
resolution Google Drive/local-file renders, replacing the old uniform
proportional rescale for those cards.
26 new tests (all 6 required synthetic fixtures + override modes +
geometry math + pdfImage.ts's new getPDFImageBlob split), zero
regressions in the existing 267.
Two real bugs found and fixed via actual render verification, not just
unit tests: (1) a confident-but-wrong measurement could ask to trim
more than a small source image actually has, producing a negative
canvas dimension - clamped defensively in computeBleedExtensionGeometry.
(2) @react-pdf/renderer's own stylesheet parser has a genuine bug where
a single-token transform value ("none") throws inside its layout engine
without ever propagating as a rejection, silently hanging the whole
render - caught only by running tests/PDFGenerator.spec.ts's real
Playwright suite (which hung at timeout) against a stashed before/after
baseline; fixed by omitting the transform key instead of passing
"none". Documented in docs/lessons.md as a reusable cross-session
finding.
Still not built (flagged, not silently dropped - see the proposal
doc's "Shipped vs. not yet built"): the main-thread batch resolution of
bleedPriors via APIGetTagConsensus, the manual-override UI + project-
state persistence, and the WYSIWYG preview badge.
* Build Proposal B PR-1: batch prior-resolution for bleed normalization
Main-thread, concurrency-bounded batch fetch of each export card's
appropriate-bleed machine-vote lean via the existing APIGetTagConsensus
endpoint - no new endpoint, per the approved spec. Populates
PDFProps.bleedPriors (built in PR #66, previously always undefined in
real exports) so ambiguous sides use a real per-card lean instead of
always falling through to the safe "unresolved" default.
Runs on the main thread (PDFGenerator.tsx's downloadPDF/saveToDrivePDF,
before the render worker is invoked) because APIGetTagConsensus's CSRF
header needs document.cookie, which doesn't exist inside pdf.worker.ts's
Worker context - the resolved plain map crosses that boundary the same
way every other PDFProps field already does.
New: common/concurrencyLimit.ts (a general-purpose bounded-concurrency
map, kept separate from GoogleDriveService's own private Semaphore to
avoid expanding this PR into an unrelated refactor), features/pdf/
bleedPriorResolution.ts (netPolarity -> BleedPrior mapping, per-card
failure tolerance so one bad lookup never fails the whole export). 13
new tests, 282/282 passing overall.
Verified against the real render path, not just unit tests:
tests/PDFGenerator.spec.ts has no tagConsensus mock at all, so every
lookup genuinely fails during that suite - it still passes at the same
timing as before this PR, confirming the failure-tolerance path works
end to end, not just in isolation.
Full report: docs/reports/proposal-b-pr1-bleed-prior-batch-resolution.md
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent c350d3f commit 796b1e7
7 files changed
Lines changed: 386 additions & 14 deletions
File tree
- docs
- proposals
- reports
- frontend/src
- common
- features/pdf
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
| 38 | + | |
37 | 39 | | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
Lines changed: 82 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
0 commit comments