feat(TE-22637): add threshold flags to upload-pdf - #562
Open
shrinishLT wants to merge 4 commits into
Open
Conversation
--approvalThreshold and --rejectionThreshold apply to every pdf in the
upload; --thresholds takes inline JSON or a path to a JSON file with
per-pdf overrides keyed by name, e.g.
{"invoice.pdf":{"approval":2,"rejection":5}}.
Values are forwarded as strings and left to the backend to validate
(range, band, unmatched names, use_default_thresholds), so the CLI
surfaces the server's message rather than a second copy of the rules.
A run with none of the flags sends nothing new.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QbnKfTzhr64osinPevTmVG
sushobhit-lt
reviewed
Sep 8, 2026
sushobhit-lt
left a comment
Collaborator
There was a problem hiding this comment.
Good news first: this does not repeat the --sync no-op from #558. I traced every read site back to the ctxInit whitelist in src/lib/ctx.ts:292-294 and the keys match exactly; field names, types and the 0-100 range agree with the server parser in smartui-rendering-service#1264, and an explicit 0 survives end to end.
The risk here is error handling rather than wiring — three comments below.
upload-pdf now accepts --config and reads thresholds from the same file exec uses, so one config.json serves web and PDF. Top-level approvalThreshold/rejectionThreshold apply to both; a new optional `pdf` block carries PDF-specific defaults and a per-file `thresholds` map keyed by resolved PDF name. Precedence for a PDF: CLI flag, then pdf block, then top-level config, then the project setting; the per-file map is taken whole from the first source that sets it. Strictly additive. `pdf` joins the schema's anyOf so a PDF-only file is valid for upload-pdf, and ctxInit keeps every other command on the old rule (web or mobile required) so exec behaves exactly as before. Unknown keys inside `pdf` are still rejected. Values are carried as strings via a helper that treats a numeric 0 as set, so an explicit 0 reaches the backend rather than being dropped. Verified against the built CLI: web-only, web+thresholds and web+pdf files authenticate on both commands; pdf-only authenticates on upload-pdf and is rejected by exec with the existing message; a typo inside pdf and an out-of-range value fail with the schema messages. The shared rejection<=approval check in ctxInit now also runs for PDF configs; that rule is under review separately (LambdaTest#6 on the RFC). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QbnKfTzhr64osinPevTmVG
…b path does
The CLI now resolves one final {approval, rejection} per uploaded pdf -
per-file entry, else the build-level value (flag > pdf block > top-level
config) - and posts only the complete `thresholds` map. The raw
approvalThreshold/rejectionThreshold form fields are no longer sent by
the CLI; they remain on the endpoint for raw-API callers.
Mirrors snapshotQueue's per-snapshot resolution so there is one
precedence rule, tested in one place, and every file the backend sees
carries an explicit value. Uses ?? throughout so an explicit 0 is sent.
Also fails fast, before any file goes over the wire: a --thresholds
value that is not inline JSON is treated as a path and must exist; the
JSON must parse to an object; names in the map must match the uploaded
(or --pdfNames) names; a non-numeric flag is rejected. Server-side
validation still runs as the last line.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QbnKfTzhr64osinPevTmVG
…e config file only Two ways to give the same per-pdf map (a flag taking inline JSON or a path, and the config file's pdf.thresholds block) was one too many and invited questions about which wins and whether the flag carried build-level values too. One way in per level now: build-level --approvalThreshold / --rejectionThreshold, or config.json per-pdf config.json pdf.thresholds (only) The resolver is unchanged: per-pdf entry, else build-level (flag > pdf block > top-level), else the project setting; names in pdf.thresholds that match no uploaded file still fail before anything is uploaded. Removes the file/inline parser that only served the flag. Verified on pdf-thresholds: legacy and Omni rows carry the resolved values, an unknown name in pdf.thresholds fails fast with no build, rejection=0 accepted, two uploads into one build keep their own groups. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QbnKfTzhr64osinPevTmVG
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.
What
upload-pdfgains threshold support with one way in per level:--approvalThreshold <n>/--rejectionThreshold <n>, or the config filepdf.thresholds, keyed by resolved PDF name{ "web": { "browsers": ["chrome"], "viewports": [[1920, 1080]] }, "approvalThreshold": 2, "rejectionThreshold": 5, "pdf": { "approvalThreshold": 1, "thresholds": { "invoice.pdf": { "approval": 0, "rejection": 4 } } } }upload-pdfnow accepts-c --configand reads the sameconfig.jsonexecuses: the existing top-levelapprovalThreshold/rejectionThresholdapply to PDFs too; thepdfblock is new and optional. One file serves web and PDF, which is the shape a Jenkins pipeline with one mixed PDF directory needs.Resolution — client-side, per file, like the web path
The CLI resolves one final
{approval, rejection}per uploaded PDF —pdf.thresholds[name], else the build-level value (flag→pdf.*→ top-level) — and posts only the completethresholdsmap. That mirrorssnapshotQueue.tsresolving per snapshot; there is one precedence rule, in one place (src/lib/pdfThresholds.ts).??throughout, so an explicit0is sent, never dropped. The raw per-call form fields stay on the endpoint for API/SDK callers; the CLI doesn't send them.Fails before any file is uploaded when a
pdf.thresholdskey matches no uploaded file (or--pdfNamesname), or a flag isn't numeric; the server still validates range, band (rejection > 0 && approval > rejection), anduse_default_thresholdsas the last line.Compatibility — strictly additive
pdfjoins the schema'sanyOfso a PDF-only config is valid forupload-pdf; every other command keeps the "web or mobile required" rule inctxInit, so an existing file behaves identically forexec. Unknown keys insidepdfare rejected. Verified against the built CLI: web-only, web+thresholds, web+pdf and pdf-only files on both commands; typo and out-of-range values fail with the schema messages.Behaviour when nothing is set
Unchanged: no flags, no
pdfblock, no top-level thresholds → nothing new is sent → project settings apply, exactly as today.Verified on the
pdf-thresholdsdev env (2026-09-09, 02:21–02:34 IST)dev-tests/TE-22637/run.sh, DB-verified, against smartui-rendering-service#1264 + dotlapse-event-service#2913:platform='pdf') and Omni projects, config aboveinvoice 0/4,contract 3/5,report 1/5on both tables — explicit0preservedpdf.thresholds--approvalThreshold 6 --rejectionThreshold 5--approvalThreshold 5 --rejectionThreshold 0rejection=0= never auto-reject)--approvalThreshold 101--buildName, different groups via--pdfNamesa1–3 @2/5andc1–3 @7/9Not in this PR
exitOnError: falseon this task means a server 400 prints red and exits 0 — same asexec/upload; deliberately unchanged (RFC §7.4).tsc --noEmitfails on the untouchedtsconfig.json(TS5110) — pre-existing;tsupis the build and passes.Server: LambdatestIncPrivate/smartui-rendering-service#1264 · DES: LambdatestIncPrivate/dotlapse-event-service#2913 · RFC: LambdatestIncPrivate/internal-docs#2963 · Ticket: TE-22637
🤖 Generated with Claude Code
https://claude.ai/code/session_01QbnKfTzhr64osinPevTmVG