Skip to content

Add standalone input routing adapter and contract coverage#134

Merged
qarlus merged 3 commits intodevfrom
feature/standalone-window-runtime-bootstrap
Apr 9, 2026
Merged

Add standalone input routing adapter and contract coverage#134
qarlus merged 3 commits intodevfrom
feature/standalone-window-runtime-bootstrap

Conversation

@qarlus
Copy link
Copy Markdown
Collaborator

@qarlus qarlus commented Apr 9, 2026

Objective

Implement standalone-side mouse-routing integration so host event handling consumes the shared routing/hyperlink contracts and is covered by parser-driven unit tests.

Scope

  • Add a new standalone input adapter module (StandaloneInputFlow) that composes SelectionEventFlow, InputRouter, and HyperlinkOpenRouter.
  • Add parser-driven standalone tests for app-owned routing, local selection fallback, shift-local override, and preview-then-open hyperlink behavior.
  • Wire the new module into the standalone crate and add the required iris-core dependency.
  • Update progress tracking docs and changelog entries to reflect the completed routing integration milestone.
  • This PR is intentionally bundled as a materially useful change set (378 insertions) rather than a micro-change.

API and Behavior Changes

  1. API surface change
  • Added crates/iris-standalone/src/input.rs with StandaloneInputFlow and StandaloneInputOutcome.
  1. Runtime behavior change
  • Standalone input handling can now process window-space mouse events through shared local-vs-app ownership rules and return PTY mouse bytes for app-owned events.
  • Local left-click interactions now apply hyperlink preview/open gating through HyperlinkOpenRouter.
  1. Error behavior change
  • handle_window_mouse_event(...) forwards iris-platform::Result errors directly from routed selection handling.

Backward Compatibility

  • additive/non-breaking
  • Existing CLI/runtime/session behavior is unchanged.

Test Coverage

Added/updated tests in crates/iris-standalone/src/input.rs:

  • standalone_input_flow_matches_routing_contract_for_app_then_local_selection
  • standalone_input_flow_applies_shift_local_override_with_active_mouse_reporting
  • standalone_input_flow_requires_local_route_for_hyperlink_preview_then_open

Coverage strategy:

  • happy-path coverage: app-owned passthrough and local selection outcomes
  • error/edge coverage: routing-mode toggles and shift-local ownership override
  • platform-specific coverage: N/A (logic-level routing tests)

Verification

Commands run and results:

  • cargo fmt --all (pass)
  • cargo clippy -p iris-standalone --all-targets -- -D warnings (pass)
  • cargo test -p iris-standalone (pass)
  • cargo clippy --all-targets -- -D warnings (pass)
  • cargo test --all (pass)

Files Changed

  • crates/iris-standalone/src/input.rs
  • crates/iris-standalone/src/main.rs
  • crates/iris-standalone/Cargo.toml
  • Cargo.lock
  • docs/phases/06.md
  • docs/phases.md
  • CHANGELOG.md

Notes

  • N/A

Summary by CodeRabbit

  • New Features

    • Standalone input handling with unified mouse routing for local vs app modes.
    • Hyperlink preview and activation for local left-clicks, with Shift-based local-override behavior.
  • Bug Fixes

    • Eliminated duplicate window-to-cell mouse processing, reducing redundant handling.
    • Reduced broad dead-code allowances to targeted exceptions.
  • Tests

    • Added unit coverage for routing, Shift override, and hyperlink preview/open sequencing.
  • Documentation

    • Updated phase docs and changelog to reflect standalone input integration and completed checklist items.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 24fe9d0f-8411-4be3-9d0c-997350714d9c

📥 Commits

Reviewing files that changed from the base of the PR and between 323b8f6 and 6b65e9d.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • crates/iris-standalone/src/input.rs

📝 Walkthrough

Walkthrough

Adds a new standalone input adapter StandaloneInputFlow that single-translation routes window-mouse events into selection-space, delegates to SelectionEventFlow, maps routing outcomes, gates hyperlink preview/open to local left-clicks, and exposes pending preview URIs. Includes unit tests and docs/Cargo updates.

Changes

Cohort / File(s) Summary
Changelog & Phase Docs
CHANGELOG.md, docs/phases.md, docs/phases/06.md
Documented the new StandaloneInputFlow, updated Phase 6 status/checklist, and described input-routing and hyperlink preview behavior.
Standalone crate metadata
crates/iris-standalone/Cargo.toml, crates/iris-standalone/src/main.rs
Added workspace dependency iris-core and declared new input module in the standalone crate.
Standalone input implementation & tests
crates/iris-standalone/src/input.rs
New StandaloneInputFlow and StandaloneInputOutcome: translates window→selection once, calls SelectionEventFlow, maps routed outcomes (route target, PTY bytes, consumed/copied), resets or resolves HyperlinkOpenRouter (preview/open only for Local left-clicks), exposes pending preview URI, and adds unit tests for routing, Shift override, and preview→open sequencing.

Sequence Diagram

sequenceDiagram
    participant Client as Client
    participant SIF as StandaloneInputFlow
    participant SEF as SelectionEventFlow
    participant HLR as HyperlinkOpenRouter
    participant Terminal as Terminal
    participant Clipboard as Clipboard

    Client->>SIF: handle_window_mouse_event(event, geometry)
    SIF->>SIF: translate window->selection (single mapping)
    SIF->>SEF: handle_routed_mouse_event(translated_event)
    SEF-->>SIF: RoutedOutcome(route_target, pty_bytes, consumed, copied)
    alt route_target == Local and left-button press
        SIF->>HLR: resolve_hyperlink_decision(translated_event.cell)
        HLR-->>SIF: Preview / Open / Deny
    else
        SIF->>HLR: reset preview state (clear)
    end
    SIF->>Terminal: (optionally) write pty_bytes
    SIF->>Clipboard: (optionally) copy selection
    SIF-->>Client: StandaloneInputOutcome{consumed, copied, route_target, pty_bytes, hyperlink_decision}
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐇
A hop, one mapping saved with care,
Clicks chose where focus should fare;
Shift nudges local to be bold,
Links whisper preview, then unfold.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add standalone input routing adapter and contract coverage' clearly and directly summarizes the main change: introduction of a new standalone input adapter (StandaloneInputFlow) with test coverage for routing contracts.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/standalone-window-runtime-bootstrap

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

@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.

Caution

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

⚠️ Outside diff range comments (1)
docs/phases.md (1)

492-501: ⚠️ Potential issue | 🟡 Minor

Keep the Phase 6 deliverables in sync with the detailed phase doc.

Session profiles is still unchecked here, but docs/phases/06.md already describes --profile <name> support as implemented. Please align the summary checklist so the active-phase snapshot doesn't drift from the detailed phase status.

Based on learnings, follow the active phase in docs/phases.md and the matching file in docs/phases.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/phases.md` around lines 492 - 501, The checklist in docs/phases.md is
out of sync: the "Session profiles" item is unchecked while docs/phases/06.md
documents implemented --profile <name> support; update the checklist entry for
"Session profiles" in docs/phases.md to checked (or otherwise match the status
described in docs/phases/06.md) so the summary snapshot matches the detailed
phase doc. Also verify any other items in docs/phases.md against
docs/phases/06.md and reconcile discrepancies to keep the active-phase summary
consistent.
🧹 Nitpick comments (1)
crates/iris-standalone/src/input.rs (1)

46-54: Avoid maintaining a second window-to-cell translation path here.

handle_routed_window_mouse_event(...) and window_mouse_adapter.translate(...) are both deriving cell coordinates from the same window event. That works today, but it gives hyperlink hit-testing its own translation path to keep in sync with routed selection behavior. I'd prefer a single source of truth here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iris-standalone/src/input.rs` around lines 46 - 54, The code currently
computes cell coordinates twice—once via window_mouse_adapter.translate(event,
geometry) and again inside selection_flow.handle_routed_window_mouse_event(...);
to fix, collapse to a single translation path: have
handle_routed_window_mouse_event return (or expose) the translated cell
coordinates along with routed_outcome.route_target (or change it so it accepts
precomputed coordinates and reuses them) and then call
resolve_hyperlink_decision(terminal, routed_outcome.route_target,
translated_coords_from_routed_outcome) instead of using
window_mouse_adapter.translate separately; update the signatures/use sites for
selection_flow.handle_routed_window_mouse_event and resolve_hyperlink_decision
accordingly to remove the duplicated translation (references:
window_mouse_adapter.translate, selection_flow.handle_routed_window_mouse_event,
resolve_hyperlink_decision, routed_outcome.route_target, translated_event).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@docs/phases.md`:
- Around line 492-501: The checklist in docs/phases.md is out of sync: the
"Session profiles" item is unchecked while docs/phases/06.md documents
implemented --profile <name> support; update the checklist entry for "Session
profiles" in docs/phases.md to checked (or otherwise match the status described
in docs/phases/06.md) so the summary snapshot matches the detailed phase doc.
Also verify any other items in docs/phases.md against docs/phases/06.md and
reconcile discrepancies to keep the active-phase summary consistent.

---

Nitpick comments:
In `@crates/iris-standalone/src/input.rs`:
- Around line 46-54: The code currently computes cell coordinates twice—once via
window_mouse_adapter.translate(event, geometry) and again inside
selection_flow.handle_routed_window_mouse_event(...); to fix, collapse to a
single translation path: have handle_routed_window_mouse_event return (or
expose) the translated cell coordinates along with routed_outcome.route_target
(or change it so it accepts precomputed coordinates and reuses them) and then
call resolve_hyperlink_decision(terminal, routed_outcome.route_target,
translated_coords_from_routed_outcome) instead of using
window_mouse_adapter.translate separately; update the signatures/use sites for
selection_flow.handle_routed_window_mouse_event and resolve_hyperlink_decision
accordingly to remove the duplicated translation (references:
window_mouse_adapter.translate, selection_flow.handle_routed_window_mouse_event,
resolve_hyperlink_decision, routed_outcome.route_target, translated_event).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 210e663c-3112-4ef0-97c0-8851fb721ebf

📥 Commits

Reviewing files that changed from the base of the PR and between a98186e and 5218603.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • CHANGELOG.md
  • crates/iris-standalone/Cargo.toml
  • crates/iris-standalone/src/input.rs
  • crates/iris-standalone/src/main.rs
  • docs/phases.md
  • docs/phases/06.md

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.

🧹 Nitpick comments (1)
crates/iris-standalone/src/input.rs (1)

1-1: Avoid blanket dead-code suppression at module scope.

Line 1 disables dead_code for the entire file, which can mask real regressions over time. Prefer removing this or scoping #[allow(dead_code)] to specific items temporarily.

Suggested diff
-#![allow(dead_code)]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iris-standalone/src/input.rs` at line 1, Remove the module-level
blanket attribute `#![allow(dead_code)]` at the top of the file and instead
apply `#[allow(dead_code)]` only to specific items that legitimately need it
(e.g., individual functions, structs, enums or impls) or use conditional
attributes like `#[cfg(test)]` for test-only code; locate the
`#![allow(dead_code)]` declaration in this file and either delete it, move the
allowance to the exact symbols that require it, or annotate test-only items
appropriately so that dead-code warnings remain active for the rest of the
module.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/iris-standalone/src/input.rs`:
- Line 1: Remove the module-level blanket attribute `#![allow(dead_code)]` at
the top of the file and instead apply `#[allow(dead_code)]` only to specific
items that legitimately need it (e.g., individual functions, structs, enums or
impls) or use conditional attributes like `#[cfg(test)]` for test-only code;
locate the `#![allow(dead_code)]` declaration in this file and either delete it,
move the allowance to the exact symbols that require it, or annotate test-only
items appropriately so that dead-code warnings remain active for the rest of the
module.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cba20d25-cdc6-492e-a7a2-7730a021eded

📥 Commits

Reviewing files that changed from the base of the PR and between 5218603 and 323b8f6.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • crates/iris-standalone/src/input.rs
  • docs/phases.md
✅ Files skipped from review due to trivial changes (1)
  • docs/phases.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md

@qarlus qarlus merged commit f1ad5ef into dev Apr 9, 2026
6 of 7 checks passed
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.

1 participant