Proposal B PR-1: batch prior-resolution (appropriate-bleed machine-vote lean) - #72
Merged
Merged
Conversation
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.
…ring)
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.
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
…ct after squash-merge)
WilfordGrimley
added a commit
that referenced
this pull request
Jul 18, 2026
WilfordGrimley
added a commit
that referenced
this pull request
Jul 18, 2026
…_request+push:master Confirmed via API (workflows/test-pre-commit.yml/runs?branch=X, total_count) that the on:push:branches:["*"] trigger silently dropped events under this session's high-push-volume merge sweep: zero runs ever fired on 3 confirmed feature branches (#68, #69/#72, #70), while it fired reliably (2/2) earlier in the session on a lower-volume branch. test-frontend.yml's on:pull_request trigger never missed a beat under the same load. Switching to pull_request (proper PR check) + push:branches:["master"] (covers direct pushes to master, which this session did twice today for formatting fixes) - dropping the wildcard branch-push trigger entirely closes both gaps: PR branches get a reliable check, and direct-to-master pushes still get checked too.
5 tasks
WilfordGrimley
added a commit
that referenced
this pull request
Jul 18, 2026
…staleness mini-pass (#79) * publish_wiki.py: fix link rewriting for parent-relative paths and slug casing GitHub wiki's native [[...]] auto-linking reinterprets our own docs/ [[file.md]] convention: [[../troubleshooting.md]] became a dead literal slug, and [[printing-tags.md]] linked the raw filename casing instead of the published page name "Printing-Tags" (both visible live on Catalog-Completion-Plan). Every internal link is now resolved against its source file's real repo path and mapped through wiki-publish-map.json: a published target becomes a same-wiki link using its real page name, an unpublished-but-real target becomes an absolute GitHub blob URL, and a target resolving to neither is a hard publish error. docs_lint.py can't catch this class of bug since it only checks links within docs/ itself, not the wiki-transform's own reinterpretation downstream - the script now self-checks at publish time instead. Also adds two docs/ pages that were listed in docs/README.md's index but missing from the mapping entirely (found via the new validation): documentation-process.md and upstream-wiki-drift.md. * Docs staleness pass: Part 3 write-pass status + proposal B/C/E-1/E-2 markers catalog-completion-plan.md: Part 3 heading and Status section updated to reflect the completed write pass (run_id 20260718T145157-a12b1387, 13,275 votes, all hard bounds passed, 0/7,124 zero-resolution violations at full population), pointing to docs/reports/2026-07-18-part3-write-pass-complete.md. Filled the dangling "see the follow-up entry below" reference and replaced the now-stale "HOLD #P3 stands" language. Part 4's heading now notes it's confirmed unstarted with HOLD #B prep queued. proposal-b-bleed-normalization.md: top summary no longer lists the prior-resolution batch fetch as remaining work - it shipped as PR-1 (#72). proposal-g-user-accounts-saved-decks.md: noted the build-order queue (E-1 #61, E-2 #62, Level-2 grid fix #63, audit pass #64, GIS error UX #65, Proposal B #66/#72, Proposal C part (a) #67) has fully cleared. docs/README.md: added proposal-b and proposal-c to the "Plans & proposals" table - both have dedicated docs but were missing from the index entirely, despite the section's own stated policy that any proposal with a dedicated doc gets a row. printing-tags.md and vote-system.md checked per the mini-pass's minimum list; no changes needed - printing-tags.md already defers Stage 8+ status to catalog-completion-plan.md, and vote-system.md has no AI-terminology or merged-PR staleness. * Report relay: wiki review findings (publish-script fix, Part 3 status, staleness mini-pass) * CI: black-format publish_wiki.py, prettier-format cache-transition-resilience.md black reformatting for publish_wiki.py (never run locally - only py_compile was checked, missing the repo's black rev 22.8.0 pinned in .pre-commit-config.yaml). cache-transition-resilience.md's prettier drift predates this PR (introduced by #75) and is unrelated to its content - swept here since the "Formatting and static type checking" check runs pre-commit against all files, not just the diff, and this PR's own CI needs to go green. --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
entry
Description
Stacks on #66 (base branch set accordingly, so this diff shows only the new work). Full report:
docs/reports/proposal-b-pr1-bleed-prior-batch-resolution.md.``Builds the main-thread, concurrency-bounded batch fetch of each export card's
appropriate-bleedmachine-vote lean via the existingAPIGetTagConsensusendpoint (no new endpoint, per the approved spec). This populatesPDFProps.bleedPriors(added in #66, previously alwaysundefinedin 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 —
APIGetTagConsensus's CSRF header needsdocument.cookie, which doesn't exist insidepdf.worker.ts's Worker context — resolved right before the render call indownloadPDF/saveToDrivePDF, skipped entirely when no remote backend is configured.New:
frontend/src/common/concurrencyLimit.ts(a general-purpose bounded-concurrency map — kept separate fromGoogleDriveService's own privateSemaphoreto avoid expanding this PR into an unrelated refactor),frontend/src/features/pdf/bleedPriorResolution.ts(netPolarity →BleedPriormapping, per-card failure tolerance).Checklist
pre-commitand installed the hooks withpre-commit installbefore creating any commits.npx tsc --noEmitclean,npx eslint0 errors/warnings,npx prettier@2.7.1 --writeapplied.npx jest --runInBand: 282/282 passing, zero regressions.npx playwright test tests/PDFGenerator.spec.ts: 4/4 passing, same timing as before this PR. That suite has notagConsensusmock at all, so every lookup genuinely fails during the run — passing cleanly is real end-to-end confirmation of the failure-tolerance path, not just a unit-test assertion.docs/proposals/proposal-b-bleed-normalization.md,docs/reports/proposal-b-pr1-bleed-prior-batch-resolution.md)Merge-time checklist
Generated by Claude Code