Repository navigation
refactor: return a Result from mirror-vgi-bench-media readOptions - #172
sunwrobert wants to merge 1 commit into
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
I'll fix CI failures and address comments from users with write access that start with 'Devin'.
Original prompt from Devin Bot
|
There was a problem hiding this comment.
✅ Approved. The change returns typed failures for invalid numeric flags and handles them at the CLI boundary; no actionable regressions found.
Scope and evidence
Reviewed both changed files (+75/-12) at 872a773 against actual base c6a05aa, with two independent correctness passes plus input/security, error-path, dependency/reuse and blast-radius checks. Examined the parser, its production caller, test helpers and affected tests. Numeric validation, default values, flag precedence and success fields are preserved; both failure kinds render the original message text. The caller unwraps success before creating the S3 client and exits 1 on parser failure.
Risk
The exported parser return type changes, and the in-repository callers are updated. Invalid-flag output intentionally loses the uncaught-exception stack/source excerpt. Environment validation still runs first, as before. The change is limited to the manual media-mirroring script and its tests; no benchmark execution path changes were found.
Verification
Static review only: no PR code, tests, installs or builds were run. Inspected tests cover defaults, supplied flags, both failure variants, error precedence and exact rendered messages. The author’s reported command results were not independently reproduced. CI was not checked.
TL;DR
readOptionsinscripts/mirror-vgi-bench-media.tsreturnsResult.Result<MirrorOptions, ReadOptionsError>instead of throwing on an invalid--concurrencyor--limit; theimport.meta.mainboundary writes the same message to stderr and exits 1, so the CLI behaves exactly as before.throw-to-result: packages/bench-harness/scripts/mirror-vgi-bench-media.ts (vendored copy of
scripts/mirror-vgi-bench-media.tsin this repo)remaining: 1298 → 1296 in OpenRouterTeam/openrouter-web, measured with
git grep -E "^\s*throw new Error\(" -- 'packages/**/*.ts' 'services/**/*.ts' ':!*.test.ts' ':!*.integration.test.ts' | grep -vE "// invariant:" | wc -lonmain(1298) and with this change applied topackages/bench-harness(1296). The count drops in openrouter-web only when the follow-up subtree pull lands. In this repo the same inventory (-- 'src/**/*.ts' 'scripts/*.ts' 'scripts/**/*.ts') goes 71 → 69.This repo uses
effect/Result(Result.succeed/Result.fail/Result.isFailure,assertSuccess/assertFailurefromsrc/internal/testing.ts), so this change uses it rather than@openrouter-monorepo/lib-result, which the remediation profile names and which is not a dependency here.Why this repo and not openrouter-web:
packages/bench-harnessin openrouter-web is a read-only vendored subtree pinned byscripts/check-subtree-integrity.ts(an in-place edit failsbun run verifyon "Vendored subtree integrity", confirmed locally). The fix lands here first; ascripts/subtree-pull-bench-harness.shPR then brings it into openrouter-web and closes the scan finding there.What changed?
ReadOptionsErrorliteral union next toreadOptions:{ kind: "concurrency_not_positive_integer" } | { kind: "limit_not_positive_integer" }(no raw message strings; the messages carried no interpolated data).readOptionsreturnsResult.Result<MirrorOptions, ReadOptionsError>; boththrow new Error(...)sites becomeResult.fail({ kind }), the success path becomesResult.succeed({...}).describeReadOptionsErrorrenders eachkindto the exact message the CLI printed before, through an exhaustiveswitchending insatisfies never.main()(the only production caller, reached fromimport.meta.main) checksResult.isFailure, writes<message>\nto stderr and callsprocess.exit(1).toThrowtest becomes oneassertFailurecase perkind, plus error precedence when both flags are invalid, plus a table test that eachkindrenders to the original message; the two success tests narrow withassertSuccess.Error union:
Callers:
main()inscripts/mirror-vgi-bench-media.ts(1 production caller) andscripts/mirror-vgi-bench-media.test.ts.purely mechanical: no
error: --concurrency must be a positive integer, stack trace,Bun v1.4.4 (Linux x64)) and exited 1. Head prints exactly--concurrency must be a positive integer(or the--limitmessage) plus a newline to stderr and exits 1. Exit status and the message text are unchanged; the stack trace and source excerpt are gone. This is the change the finding asks for.readOptionsis exported; its return type changes fromMirrorOptionstoResult.Result<MirrorOptions, ReadOptionsError>. The only callers are in this file and its test.// invariant:markers added: none.Prod impact: none at runtime. The script runs manually (
bun run mirror-vgi-bench-media) to refresh the VGI-Bench media manifest; no benchmark, solver, scorer, or dataset path imports it. Worst case: an operator passing an invalid flag sees a one-line message instead of a stack trace, still with exit code 1.Why?
Code-scan finding
sfind-bcf61ee8763443058437ea79c402a49c(Throw → Result burn-down): an out-of-range--concurrencyor--limitis expected user input, not an invariant, so it belongs in the function's return type.Show me
Proof matrix
Base worktree:
git worktree add ~/proof/harness/base origin/main(c6a05aa), thengit checkout 872a773 -- scripts/mirror-vgi-bench-media.test.ts. Head:872a773. Command on both sides:bun test scripts/mirror-vgi-bench-media.test.ts.The head test file imports
describeReadOptionsError, a new export, so the unmodified head file fails to load on base (SyntaxError: Export named 'describeReadOptionsError' not found), which does not count as a base failure. The base rows below come from the same file with that one import line and thedescribeReadOptionsErrordescribe block removed (scripts/base-compat.test.ts, 6 pass / 5 fail on base); every other line is identical.--concurrency=0returns{ kind: "concurrency_not_positive_integer" }readOptions > fails with concurrency_not_positive_integer for --concurrency=0. Base:error: --concurrency must be a positive integerthrown beforeassertFailureruns. Head: pass.--limit=abcreturns{ kind: "limit_not_positive_integer" }readOptions > fails with limit_not_positive_integer for --limit=abc. Base:error: --limit must be a positive integerthrown. Head: pass.readOptions > reports the first failing flag when both are invalid(--concurrency=1.5 --limit=0). Base:error: --concurrency must be a positive integerthrown. Head: pass withconcurrency_not_positive_integer.kindrenders to the original CLI messagedescribeReadOptionsError > renders ... as the CLI message(2 cases). Base: function does not exist (import error, not counted). Head: pass.readOptions > applies defaults,readOptions > parses provided flags. Base: fail only because the return shape is now aResult(expect(received).toEqual(expected)on.success); the field values are unchanged. Head: pass.extensionOf(3),candidateSources(2),hashManifest(1): pass on base and head.CLI boundary (e2e for a script with no UI; dummy
BENCH_MEDIA_S3_*env soreadMediaMirrorEnvpasses, no network reached because option parsing fails first):Head:
bun test scripts/mirror-vgi-bench-media.test.ts13 pass / 0 fail;bun run format:check,bun run check,bun run typecheck,bun run buildclean. No committed e2e test is added: this repo has notests/e2eharness and the script needs S3 credentials and network past option parsing.Visualization
Self-contained artifact: https://openrouter.devinenterprise.com/api/presigned_proxy?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjpudWxsLCJidWNrZXRfbmFtZSI6ImRldmluYXR0YWNobWVudHMiLCJidWNrZXRfa2V5IjoiYXR0YWNobWVudHNfcHJpdmF0ZS9jbGVyay1vcmdfMmhUSzBmbWdTSk80ZncwT041T1NwOUtFZG1iL2E1NjRhZGE3LWVjMTEtNDhmZC04NTk2LTE1ZDdhZjEzYTBlOCIsImlhdCI6MTc5MzQ4MzA4Mywib3JnX2lkIjoiY2xlcmstb3JnXzJoVEswZm1nU0pPNGZ3ME9ONU9TcDlLRWRtYiIsImZpbGVuYW1lIjoidGhyb3ctdG8tcmVzdWx0LW1pcnJvci12Z2ktYmVuY2gtbWVkaWEtMjAyNi0xMS0wMS5odG1sIn0.LD07FuQ0obCDqTXhrpocZZSUI8g2Z_Bj8LzZ8XjCvPM
Thermo-nuclear fix loop
Round 1 (head
872a773, diff +75/-12 in 2 files): no actionable finding.{ kind: "flag_not_positive_integer"; flag: "concurrency" | "limit" }. Rejected: the burn-down rule asks for onekindper distinct failure, and two literal members with no payload are the smaller type.describeReadOptionsErrorintomain(). Rejected: the exhaustiveswitchis the only place the message text lives, and the test pins eachkindto its message through it.isFailureguard at the boundary; no casts, nounknown.scripts/mirror-mmmu-pro-media.ts:153carries the same--concurrencythrow. Out of scope (one module per PR); it is the next module for the burn-down.Round 2: not needed, round 1 produced no fix.
Deslop-micro pass
Fix mode, zero findings, no commit.
ReadOptionsError<fn>Errorunions with akinddiscriminant (MirrorOutcomein the same file,readonly kind:unions insrc/harness/core.ts)describeReadOptionsErrordescribeFailureinscripts/media-mirror.ts(samedescribe*verb for failure-to-text)concurrency_not_positive_integer,limit_not_positive_integerMutation testing
not measured: this repository has no
test:mutationharness (the openrouter-webbun run test:mutationscript does not exist here, and the vendored copy is read-only).How to test
Expected: 13 tests pass; the script prints
--concurrency must be a positive integerandexit 1.Reviewer focus
describeReadOptionsErrorkeeps the two messages byte-identical to the oldthrowstrings.process.exit(1)afterprocess.stderr.writematches the old exit status; the stack trace is intentionally gone.Checklist
readOptionsreturn type change is documented above; no caller outside this file)Link to Devin session: https://openrouter.devinenterprise.com/sessions/2dc315bbaa654730ada9ec2982d8cb74
Open in Devin Desktop: https://openrouter.devinenterprise.com/desktop/session/2dc315bbaa654730ada9ec2982d8cb74?variant=devin
Requested by: @sunwrobert