feat(cli,core,cdp): --viewport flag + viewport multi-run orchestration - #103
Merged
Merged
Conversation
New entry point that takes any iterator of snapshots and returns the deterministic, sorted, deduped union of their violations. `run` is now a thin wrapper. Sort key is unchanged: (rule_id, viewport, selector, dom_order). Refs #16 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New `BrowserDriver::snapshot_all` reuses a single browser session across multiple targets. ChromiumDriver overrides it to launch Chromium exactly once per CLI invocation and validate the version once; per-target snapshot work is still `CdpError::NotImplemented` until #15 lands. FakeDriver now carries the requested viewport on the canned snapshot so downstream multi-viewport orchestrators have distinguishable per-viewport output. Refs #16
Adds repeatable `--viewport <name>` flag to `plumb lint`. CLI resolves the configured viewport set, optionally filtered by the flag, builds one `Target` per viewport, and calls `BrowserDriver::snapshot_all` once so Chromium launches exactly once per CLI invocation. Violations from every viewport flow through `plumb_core::run_many` and into the existing exit-code aggregator, so the worst severity across viewports wins. Unknown viewport names produce a clear input error (exit 2) listing the configured viewports. Closes #16 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rustdoc with -Dwarnings rejects public-item docs that link to private items. The reference is informational; replace the link with plain prose so `cargo doc --no-deps` stays clean. Refs #16
This was referenced Apr 24, 2026
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.
Target branch
mainSpec
Fixes #16. Part of #10 Phase 1, Gate 2, Batch
1B(sibling: #15 DOMSnapshot integration).PRD references: §10.3 (data flow / per-viewport pipeline), §13.3 (exit codes), §15.4 (
plumb lintflags).Summary
--viewport <name>flag toplumb lint. Filters the configured viewport set fromplumb.toml; absent the flag, every configured viewport runs. Unknown names produce a clear input error (exit 2) listing the available viewports.BrowserDriver::snapshot_alltrait method with a default fan-out impl.ChromiumDriveroverrides it so Chromium launches exactly once per CLI invocation for the full viewport batch (the per-viewport DOMSnapshot conversion still returnsCdpError::NotImplementeduntil feat(cdp): DOMSnapshot.captureSnapshot integration with style whitelist #15 lands).plumb_core::run_manyaggregates rule output across multiple snapshots, re-sorts by(rule_id, viewport, selector, dom_order), and dedups. The existingexit_code_forthen computes worst-severity-wins across all viewports (AC chore(roadmap): link phase-2 parent #4).Crates touched
plumb-core— newrun_manyentry point;runis now a thin wrapper.plumb-formatplumb-cdp—BrowserDriver::snapshot_all+ viewport-awareFakeDriver.plumb-configplumb-mcpplumb-cli—--viewportflag + orchestrator +LintError(thiserror).xtaskdocs/.agents/or.claude/.github/System impact
plumb_core::run_many,BrowserDriver::snapshot_all. Both have full rustdoc with# Determinismnotes; both are infallible-or-Resultshaped per the existing patterns.BrowserDriver::snapshot_alladded; security-auditor reviewed.plumb-cliaddsthiserror(workspace dep already in tree);tempfileadded to[dev-dependencies]only.run_manyre-sorts + dedups across snapshots; tested input-order-independent.Architectural compliance
plumb-coreadds no internal deps;plumb-cdpstill depends only onplumb-core; onlyplumb-cliprints.LintErroristhiserror-derived;anyhowonly at the orchestrator boundary.unwrap/expect/panic!in libraries. The unreachable empty-pop case inChromiumDriver::snapshotreturns a typedCdpError::Driverrather than panicking.SystemTime::now/Instant::nowinplumb-core.HashMapin observable output paths (IndexMapthroughout).#[allow(...)]annotations.Test plan
just validatepasses locally (54 tests, 0 failed).cargo xtask pre-release(no rule or schema change).just determinism-check— three byte-identical runs.cargo deny check— advisories ok, bans ok, licenses ok, sources ok.plumb-core::engine_run_many— 3 cases (collects-from-every, sort order, input-order independence).plumb-cdp::snapshot_all_default::fake_driver_snapshot_all_preserves_target_order_and_viewport— 1 case.plumb-cli::commands::lint::tests— 7 cases onresolve_targets(default fallback, IndexMap order, filter, unknown-name error shape).plumb-cli::tests::cli_integration— 4 new cases covering all four ACs end-to-end.Documentation
run_many,snapshot_all,LintError, the newLint::viewportsflag).# Errorsnot needed forrun_many(infallible) orsnapshot_all(already documentedCdpError).docs/src/— no user-facing book changes in this PR. CLI reference docs for--viewportwill land alongside the broader CLI docs page in a later PR (humanizer pass deferred to that PR).docs/src/rules/— no new rules.docs/src/**changes).Breaking change?
Checklist
codex/16-feat-cli-viewport-flag-multirunReviewer notes
ChromiumDriverreal path still returnsCdpError::NotImplementedper feat(cdp): DOMSnapshot.captureSnapshot integration with style whitelist #15. This PR's job is the orchestrator + single-launch invariant; the per-viewport DOMSnapshot conversion lands in feat(cdp): DOMSnapshot.captureSnapshot integration with style whitelist #15. The two PRs can land in either order — they don't conflict.Config::viewportsis empty by default. The default-fallback path (singledesktop1280×800 target) preserves the walking-skeleton quickstart soplumb lint plumb-fake://helloworks in a fresh checkout. Once a[viewports.*]section is added toplumb.toml, the bareplumb lint <url>command begins running every configured viewport — that's per PRD §10.3.--viewport <name>arg silently falls back to the default desktop target rather than erroring. This is documented inresolve_targets's rustdoc and asserted byempty_config_ignores_viewport_arg_and_returns_default. Erroring would regress the no-config quickstart.crates/plumb-cli/CLAUDE.mdmapping. Spec reviewer flagged this as a divergence from PRD §13.3's literal "exit 3 for input errors" but accepted it as consistent with the established CLI convention; if the PRD is canonical, that reconciliation is a separate ticket.🤖 Generated with Claude Code