Skip to content

iter-56: dogfooding session 41 fixes (exit codes, defaults, schema docs)#59

Merged
ractive merged 2 commits intomainfrom
iter-56/dogfood-41-fixes
May 10, 2026
Merged

iter-56: dogfooding session 41 fixes (exit codes, defaults, schema docs)#59
ractive merged 2 commits intomainfrom
iter-56/dogfood-41-fixes

Conversation

@ractive
Copy link
Copy Markdown
Owner

@ractive ractive commented May 10, 2026

Summary

Bugfix iteration driven by dogfooding session 41. Two themes: trust the contract (exit codes, help text schemas match reality) and sensible defaults (timeouts, visible-only filtering, no double-encoded strings, quiet stderr).

  • A1 — Exit codes: AppError::Connection → 3, AppError::Timeout → 124. Reclassified daemon/connect/wait timeout sites. New exit_codes.rs e2e suite asserts 0/1/2/3/124 per failure class.
  • A2 — Help text drift: Fixed responsive, click, wait, inspect, sources, page-text --help JSON schemas to match actual output. Other iter-55 C2 commands had no drift.
  • B1 — Daemon-drain timeout: Floor raised to 15 s for network non-follow path; timeout reclassified to user-actionable Timeout (exit 124) with hint message.
  • B2 — Visible-only default: geometry and responsive skip hidden / zero-rect elements by default. Replaces --visible-only with --include-hidden. Behavior change — scripts relying on the old default need --include-hidden.
  • B3 — eval --stringify strings: Page-side helper skips JSON.stringify when the result is already a string, so document.title returns "Example Domain" not "\"Example Domain\"". Objects/arrays still stringified.
  • B4 — Quiet stderr: Gated eprintln!("debug: …") in sources, console, a11y behind --verbose / RUST_LOG. Added --verbose global flag.
  • Deferred: A3 (screenshot fallback on FF 150) and C1 (navigate --wait-text noSuchActor) both need live recordings against Firefox 150 to capture exact failure shape — moved to backlog.

Test plan

  • cargo fmt
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace -q
  • New e2e tests for exit codes (0/1/2/3/124) pass
  • New e2e tests for eval --stringify string/number/object cases pass
  • New e2e tests for silent vs verbose sources fallback pass
  • geometry/responsive default-changed tests updated
  • Manual smoke: ff-rdp network against a heavy real-world page (~100 requests) succeeds with default timeout — verify post-merge against Comparis or similar.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added --verbose flag to emit debug messages to stderr
    • Added --include-hidden flag for geometry and responsive commands to include hidden/zero-sized elements
  • Bug Fixes

    • Fixed stringify behavior to prevent double-encoding of string results
    • Suppressed debug fallback messages in stderr unless --verbose is enabled
    • Improved daemon drain timeout handling to prevent premature timeouts
    • Improved error classification for connection and timeout failures
  • Exit Codes

    • Connection failures now exit with code 3
    • Timeout errors now exit with code 124

Review Change Stack

- A1: Map AppError variants to documented exit codes (3=connection, 124=timeout)
- A2: Align responsive/click/wait/inspect/sources/page-text --help schemas with actual JSON output
- B1: Bump daemon-drain timeout floor to 15s and reclassify as Timeout (exit 124)
- B2: geometry/responsive default to visible-only; add --include-hidden to opt in
- B3: eval --stringify no longer double-encodes string results
- B4: Gate "debug:" stderr lines behind --verbose / RUST_LOG

A3 (screenshot fallback on FF150) and C1 (navigate --wait-text noSuchActor)
deferred to backlog — both need live recordings against Firefox 150 to capture
exact failure shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

Warning

Rate limit exceeded

@ractive has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 50 minutes and 1 second before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5752bb36-761a-42b4-b009-89a7d07d08e7

📥 Commits

Reviewing files that changed from the base of the PR and between 6fd84fc and 0c07563.

📒 Files selected for processing (6)
  • crates/ff-rdp-cli/src/commands/eval.rs
  • crates/ff-rdp-cli/src/commands/js_helpers.rs
  • crates/ff-rdp-cli/src/commands/network.rs
  • crates/ff-rdp-cli/src/commands/responsive.rs
  • kb/backlog/future-features.md
  • kb/iterations/iteration-56-dogfood-41-fixes.md
📝 Walkthrough

Walkthrough

This PR consolidates fixes from dogfooding session 41, introducing dedicated error types with documented exit codes (3 for connection, 124 for timeout), inverting visibility defaults for geometry/responsive to --include-hidden, centralizing eval stringify logic to prevent double-encoding, gating debug output behind a --verbose flag, improving daemon drain timeouts, and adding comprehensive exit-code e2e test coverage across all code paths.

Changes

Dogfooding Session 41 Fixes

Layer / File(s) Summary
Error Contract
crates/ff-rdp-cli/src/error.rs, crates/ff-rdp-cli/src/main.rs
AppError gains Connection and Timeout variants with display formatting. Main maps them to exit codes 3 and 124. Protocol errors convert to these variants with helpful diagnostics.
CLI Arguments & Verbose Flag
crates/ff-rdp-cli/src/cli/args.rs
Adds --verbose flag and is_verbose() helper that checks both flag and RUST_LOG. Changes geometry/responsive from --visible-only to --include-hidden. Updates help text and documented output schemas for multiple commands.
Timeout Error Handling
crates/ff-rdp-cli/src/commands/js_helpers.rs, crates/ff-rdp-cli/src/commands/network.rs
poll_js_condition returns AppError::Timeout on deadline. Network daemon drain enforces minimum timeout floor, temporarily elevates read timeout for drain, and converts drain failures to timeout errors.
Visibility Filtering Semantics
crates/ff-rdp-cli/src/commands/geometry.rs, crates/ff-rdp-cli/src/commands/responsive.rs
run signatures accept include_hidden instead of visible_only, deriving visible_only = !include_hidden internally. Responsive JS template adds __VISIBLE_ONLY__ sentinel and guard to skip hidden/zero-sized elements by default.
Connection Error Reclassification
crates/ff-rdp-cli/src/commands/connect_tab.rs, crates/ff-rdp-cli/src/commands/tabs.rs, crates/ff-rdp-cli/src/daemon/client.rs
Maps connection failures from AppError::User to AppError::Connection, preserving diagnostic messages and hints.
Debug Verbosity Gating
crates/ff-rdp-cli/src/commands/a11y.rs, crates/ff-rdp-cli/src/commands/console.rs, crates/ff-rdp-cli/src/commands/sources.rs
Gates debug eprintln! messages behind cli.is_verbose() checks so they only appear when --verbose is set or RUST_LOG is configured.
Eval Stringify Fix
crates/ff-rdp-cli/src/commands/eval.rs
Centralizes stringify via shared STRINGIFY_HELPER JavaScript function: returns strings unchanged (no double-encoding), JSON-stringifies non-strings, handles circular reference TypeErrors. Unit tests verify helper presence and string passthrough logic.
Dispatch Wiring
crates/ff-rdp-cli/src/dispatch.rs
Routes new include_hidden field from Command::Geometry and Command::Responsive into respective run functions.
E2E Test Suite
crates/ff-rdp-cli/tests/e2e/exit_codes.rs, crates/ff-rdp-cli/tests/e2e/eval.rs, crates/ff-rdp-cli/tests/e2e/geometry.rs, crates/ff-rdp-cli/tests/e2e/sources.rs, crates/ff-rdp-cli/tests/e2e/tabs.rs, crates/ff-rdp-cli/tests/e2e/wait.rs
Introduces comprehensive exit-code tests (0 success, 2 usage, 3 connection, 124 timeout, 1 exception). Tests visibility defaults, stringify type conversions, and verbose debug suppression. Updates existing tests to match new exit codes.
Test Fixtures & Module Wiring
crates/ff-rdp-cli/tests/fixtures/eval_result_stringify_*.json, crates/ff-rdp-cli/tests/e2e/main.rs
Adds stringify test fixtures for string and number results. Wires exit_codes test module into harness.
Knowledge Base
kb/dogfooding/dogfooding-session-41.md, kb/iterations/iteration-56-dogfood-41-fixes.md, kb/backlog/future-features.md
Documents session 41 findings (exit codes, timeouts, schema drift, debug output), iteration 56 fixes checklist with acceptance criteria, and deferred carryover backlog items.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • ractive/ff-rdp#50: Modifies eval --stringify behavior and test fixtures, directly related to the stringify double-encoding fixes.
  • ractive/ff-rdp#49: Modifies geometry and responsive command implementation and visibility filtering in the same files.
  • ractive/ff-rdp#39: Modifies daemon network timeout and drain behavior with timeout error semantics overlapping this PR's timeout handling.

Poem

🐰 A hop through contracts and defaults so fine,
Exit codes now align with error design,
Visible only flipped—now hidden's the shout,
Stringify strings stay clear, no double-doubt,
Verbose logs whisper softly, till asked to speak loud—
The dogfooding bugs squashed, the rabbit is proud!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: exit codes, defaults, and schema documentation fixes from dogfooding session 41 fixes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch iter-56/dogfood-41-fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Bugfix iteration to make ff-rdp CLI behavior match its published contract (exit codes + --help JSON schemas) while improving defaults for real-world usage (timeouts, visible-only geometry/responsive, eval --stringify string handling, and quieter stderr via --verbose).

Changes:

  • Implemented explicit exit code mapping (3 = connection failure, 124 = timeout) and added an e2e exit-code contract suite.
  • Updated multiple subcommand --help JSON schemas to match actual output; introduced global --verbose to gate fallback/debug stderr.
  • Adjusted defaults/behavior: daemon network drain timeout floor, geometry/responsive visible-only-by-default with --include-hidden, and eval --stringify avoiding double-encoded strings.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
kb/iterations/iteration-56-dogfood-41-fixes.md New iteration writeup capturing tasks, rationale, acceptance criteria.
kb/dogfooding/dogfooding-session-41.md New dogfooding session log driving the fixes and priorities.
kb/backlog/future-features.md Backlog carryover + deferred items recorded for follow-up.
crates/ff-rdp-cli/tests/fixtures/eval_result_stringify_string.json Fixture for eval --stringify string passthrough case.
crates/ff-rdp-cli/tests/fixtures/eval_result_stringify_number.json Fixture for eval --stringify number-to-string case.
crates/ff-rdp-cli/tests/e2e/wait.rs Updated wait-timeout test to assert exit code 124.
crates/ff-rdp-cli/tests/e2e/tabs.rs Updated connection-refused test to assert exit code 3.
crates/ff-rdp-cli/tests/e2e/sources.rs Added e2e tests asserting fallback stderr is gated behind --verbose.
crates/ff-rdp-cli/tests/e2e/main.rs Registered new exit_codes e2e module.
crates/ff-rdp-cli/tests/e2e/geometry.rs Updated tests for visible-only default + --include-hidden opt-in.
crates/ff-rdp-cli/tests/e2e/exit_codes.rs New e2e suite asserting documented exit code contract (0/1/2/3/124).
crates/ff-rdp-cli/tests/e2e/eval.rs Added e2e coverage for eval --stringify string/number/object behavior.
crates/ff-rdp-cli/src/main.rs Added top-level exit handling for AppError::Connection (3) and AppError::Timeout (124).
crates/ff-rdp-cli/src/error.rs Introduced new AppError variants and protocol-error classification into connection/timeout.
crates/ff-rdp-cli/src/dispatch.rs Wired --include-hidden through dispatch to geometry/responsive commands.
crates/ff-rdp-cli/src/daemon/client.rs Reclassified daemon connect failures as AppError::Connection.
crates/ff-rdp-cli/src/commands/tabs.rs Reclassified connect failures into AppError::Connection for exit code 3.
crates/ff-rdp-cli/src/commands/sources.rs Gated fallback debug stderr behind cli.is_verbose().
crates/ff-rdp-cli/src/commands/responsive.rs Added visible-only filtering control in JS + --include-hidden plumbing and tests.
crates/ff-rdp-cli/src/commands/network.rs Raised daemon drain read-timeout floor and reclassified drain timeouts to exit 124.
crates/ff-rdp-cli/src/commands/js_helpers.rs Converted poll timeout path to AppError::Timeout (exit 124).
crates/ff-rdp-cli/src/commands/geometry.rs Default visible-only behavior; --include-hidden opt-in.
crates/ff-rdp-cli/src/commands/eval.rs Updated --stringify page-side helper to avoid double-encoding string results.
crates/ff-rdp-cli/src/commands/console.rs Gated debug stderr behind cli.is_verbose().
crates/ff-rdp-cli/src/commands/connect_tab.rs Reclassified connect failures into AppError::Connection.
crates/ff-rdp-cli/src/commands/a11y.rs Gated debug stderr behind cli.is_verbose().
crates/ff-rdp-cli/src/cli/args.rs Added global --verbose, updated help schemas, and flipped geometry/responsive default flag semantics.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/ff-rdp-cli/src/commands/eval.rs Outdated
Comment on lines +78 to +80
// BigInt/Symbol cannot be JSON.stringify'd either, so we fall back to
// String() coercion for those — consistent with the pre-existing circular
// reference fallback that returns a plain string.
Comment on lines +48 to +57
drain_result.map_err(|e| {
if let AppError::Internal(ref inner) = e {
let msg = format!("{inner:#}");
if msg.contains("timed out") || msg.contains("WouldBlock") {
return AppError::Timeout(format!(
"network drain timed out — try --timeout {drain_timeout_ms}"
));
}
}
e
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/ff-rdp-cli/tests/e2e/tabs.rs (1)

156-157: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the docstring to reflect exit code 3.

The function documentation states "must exit 1" but the test now asserts exit code 3 (line 177). The comment should be updated to match the new exit-code contract for connection errors.

📝 Proposed fix
-/// Connecting to a port with nothing listening must exit 1 and print a
+/// Connecting to a port with nothing listening must exit 3 and print a
 /// user-friendly message that mentions whether Firefox is running.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/ff-rdp-cli/tests/e2e/tabs.rs` around lines 156 - 157, Update the test
docstring to match the asserted exit code: change the sentence "must exit 1" to
"must exit 3" in the comment above the test in
crates/ff-rdp-cli/tests/e2e/tabs.rs so the documentation reflects the current
expectation asserted by the test (the assertion that the process exits with code
3).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/ff-rdp-cli/src/commands/js_helpers.rs`:
- Line 131: Update the stale rustdoc for poll_js_condition to reflect the new
timeout behavior: change the docs that claim a timeout returns AppError::Exit(1)
and is printed to stderr so they instead state that poll_js_condition returns
AppError::Timeout(timeout_context) on timeout (and note any change in printing
behavior if applicable). Locate the doc comment above the poll_js_condition
function in js_helpers.rs and replace the outdated description/examples to
reference AppError::Timeout and the timeout_context payload.

In `@crates/ff-rdp-cli/src/commands/network.rs`:
- Around line 49-53: Update drain_daemon_events to preserve typed timeout
errors: change its signature from returning anyhow::Result to Result<Vec<Value>,
ProtocolError> and stop wrapping transport.recv() errors with .context() so
ProtocolError::Timeout is propagated; this lets the existing From<ProtocolError>
-> AppError conversion (see error.rs) produce AppError::Timeout in network.rs
instead of doing string matching on the formatted anyhow error, and removes the
brittle checks for "timed out" or "WouldBlock" in the code handling
drain_daemon_events.

In `@crates/ff-rdp-cli/src/commands/responsive.rs`:
- Around line 138-140: The template substitution can collide if a selector
string contains "__VISIBLE_ONLY__"; to avoid this, swap the replacement order so
you replace "__VISIBLE_ONLY__" before "__SELECTORS__" (i.e., call
RESPONSIVE_JS_TEMPLATE.replace("__VISIBLE_ONLY__",
visible_only_str).replace("__SELECTORS__", &selectors_json)), or otherwise
perform the two substitutions with a method that avoids mutating serialized
selector JSON first; update the code that builds the final JS from
RESPONSIVE_JS_TEMPLATE, referencing RESPONSIVE_JS_TEMPLATE, selectors_json, and
visible_only_str.

In `@kb/backlog/future-features.md`:
- Line 73: The wikilink [[`#ultrareview`]] is dangling because there is no
corresponding "ultrareview" heading in the document; update the note to point to
an existing heading or create a matching heading (e.g., add a heading like "##
ultrareview" or "### ultrareview") so the anchor resolves, and ensure you use
Obsidian-compatible wikilinks (keep the double-bracket syntax) when editing the
reference or heading.

---

Outside diff comments:
In `@crates/ff-rdp-cli/tests/e2e/tabs.rs`:
- Around line 156-157: Update the test docstring to match the asserted exit
code: change the sentence "must exit 1" to "must exit 3" in the comment above
the test in crates/ff-rdp-cli/tests/e2e/tabs.rs so the documentation reflects
the current expectation asserted by the test (the assertion that the process
exits with code 3).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 529bea9c-83f6-4e86-a357-fea047804a71

📥 Commits

Reviewing files that changed from the base of the PR and between 954993b and 6fd84fc.

📒 Files selected for processing (27)
  • crates/ff-rdp-cli/src/cli/args.rs
  • crates/ff-rdp-cli/src/commands/a11y.rs
  • crates/ff-rdp-cli/src/commands/connect_tab.rs
  • crates/ff-rdp-cli/src/commands/console.rs
  • crates/ff-rdp-cli/src/commands/eval.rs
  • crates/ff-rdp-cli/src/commands/geometry.rs
  • crates/ff-rdp-cli/src/commands/js_helpers.rs
  • crates/ff-rdp-cli/src/commands/network.rs
  • crates/ff-rdp-cli/src/commands/responsive.rs
  • crates/ff-rdp-cli/src/commands/sources.rs
  • crates/ff-rdp-cli/src/commands/tabs.rs
  • crates/ff-rdp-cli/src/daemon/client.rs
  • crates/ff-rdp-cli/src/dispatch.rs
  • crates/ff-rdp-cli/src/error.rs
  • crates/ff-rdp-cli/src/main.rs
  • crates/ff-rdp-cli/tests/e2e/eval.rs
  • crates/ff-rdp-cli/tests/e2e/exit_codes.rs
  • crates/ff-rdp-cli/tests/e2e/geometry.rs
  • crates/ff-rdp-cli/tests/e2e/main.rs
  • crates/ff-rdp-cli/tests/e2e/sources.rs
  • crates/ff-rdp-cli/tests/e2e/tabs.rs
  • crates/ff-rdp-cli/tests/e2e/wait.rs
  • crates/ff-rdp-cli/tests/fixtures/eval_result_stringify_number.json
  • crates/ff-rdp-cli/tests/fixtures/eval_result_stringify_string.json
  • kb/backlog/future-features.md
  • kb/dogfooding/dogfooding-session-41.md
  • kb/iterations/iteration-56-dogfood-41-fixes.md

Comment thread crates/ff-rdp-cli/src/commands/eval.rs
Comment thread crates/ff-rdp-cli/src/commands/js_helpers.rs
Comment thread crates/ff-rdp-cli/src/commands/network.rs
Comment thread crates/ff-rdp-cli/src/commands/responsive.rs
Comment thread kb/backlog/future-features.md Outdated
- Clarify --stringify helper comment to match actual TypeError handling
  (only circular references get the sentinel; BigInt/Symbol rethrow).
- Reword poll_js_condition rustdoc: timeout now returns AppError::Timeout.
- Replace brittle substring matching in network drain timeout
  classification with typed downcast through the anyhow chain
  (ProtocolError::Timeout + io::ErrorKind::{WouldBlock,TimedOut}).
- Swap responsive JS template substitution order so a selector literal
  containing the visible-only placeholder can't collide.
- Drop dangling wikilink anchor in backlog/future-features.
- Tick iteration-56 scope checkboxes for the work that landed; mark A3
  and C1 explicitly deferred with reasons.
@ractive ractive merged commit f84ec85 into main May 10, 2026
4 of 6 checks passed
@ractive ractive deleted the iter-56/dogfood-41-fixes branch May 10, 2026 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants