Skip to content

Unify outbound codec path with FramePipeline & CodecDriver#461

Merged
leynos merged 13 commits intomainfrom
unify-codec-handling-9-3-1-mn7az7
Feb 19, 2026
Merged

Unify outbound codec path with FramePipeline & CodecDriver#461
leynos merged 13 commits intomainfrom
unify-codec-handling-9-3-1-mn7az7

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Feb 15, 2026

Summary

  • Implements a unified, codec-driven outbound path for all server paths by introducing a FramePipeline and a codec-aware CodecDriver that bridge the app router and ConnectionActor. This unifies fragmentation, metrics, and hook application for handler responses, streaming, and pushes.
  • Reworks several modules to route outbound frames through the new pipeline, removing per-response codec wrapping and centralizing encoding/wrapping in the driver.
  • Adds comprehensive tests, fixtures, and infrastructure to exercise the unified path end-to-end, including BDD-style scenarios.
  • Updates design docs and roadmap to reflect the unified path and notes deferred protocol hook integration for a follow-up.

Changes

  • Code
    • Adds src/app/codec_driver.rs containing FramePipeline and send_envelope / flush_pipeline_output helpers. The FramePipeline applies outbound fragmentation and metrics to Envelope values and buffers resulting frames for serialisation via the codec.
    • Updates src/app/connection.rs to instantiate and use FramePipeline, wiring inbound decoding with the codec-driven outbound path.
    • Adjusts src/app/frame_handling/core.rs, reassembly.rs, and response handling to route through FramePipeline instead of direct per-frame handling.
    • Refactors response flow to push envelopes through the pipeline and use flush_pipeline_output for codec-wrapped sending.
    • Keeps standalone ConnectionActor API compatible for client use; the server-facing path owns framing.
    • Exposes FramePipeline in app/mod.rs via codec_driver module.
  • Tests & fixtures
    • Adds tests/unified_codec.rs implementing integration tests for the unified path.
    • Adds fixtures/unified_codec/ with transport helpers and a unified_codec_world fixture (tests/fixtures/unified_codec/mod.rs and transport.rs).
    • Adds tests/features/unified_codec.feature and tests/scenarios/unified_codec_scenarios.rs for BDD-style coverage, plus steps in tests/steps/unified_codec_steps.rs.
  • Documentation & design
    • Adds docs/execplans/9-3-1-fragment-adapter-trait.md (ExecPlan for 9.3.1) as a living reference.
    • Updates docs/asynchronous-outbound-messaging-design.md and docs/multi-packet-and-streaming-responses-design.md to reflect the unified server-side pipeline.
    • Updates docs/roadmap.md to mark 9.3.1 done and reflect the unified path.
    • Updates docs/users-guide.md with guidance around the unified codec path and its effects on public guidance.
  • Misc
    • Minor package/module exposure updates to expose codec_driver in app module for tests.
    • Revision note retained for historical context.

Rationale

  • Today there are two outbound paths that diverge in codec construction, hook invocation, fragmentation, and flow control. This change introduces a single, codec-driven Path (FramePipeline + CodecDriver) on the server-facing side that consolidates fragmentation, metrics, and hook application, ensuring consistent behavior across handler responses, streams, and pushes.
  • The approach preserves the existing ConnectionActor API for client usage while enabling the server runtime to own the framing and serialization process, simplifying back-pressure and fragmentation semantics and paving the way for future hook integration.

Plan of work (status)

  • Stage A–H from the ExecPlan are implemented in code/tests/docs. The PR includes the living ExecPlan and the concrete implementation, tests, and docs.
  • Protocol hooks integration is deferred for a follow-up stage due to frame-type constraints; framing/framing-aware path is now unified.

How to review

  • Read the new ExecPlan at docs/execplans/9-3-1-fragment-adapter-trait.md to understand boundaries and decisions.
  • Review the FramePipeline and CodecDriver implementation for correctness, performance implications, and API stability.
  • Inspect how outbound paths are routed through the pipeline in src/app/connection.rs and related frame_handling modules.
  • Run the new tests (unit/integration/BDD) to confirm the unified path behaves as expected.

Impact

  • No public API breaks for existing users; internal server path now uses a unified codec flow.
  • All outbound frames (handler responses, streams, multi-packet, pushes) pass through a single codec-driven path.
  • Protocol hook invocation for outbound frames is unified where possible; some hooks are deferred to follow-up work due to type constraints.

Documentation updates

  • docs/execplans/9-3-1-fragment-adapter-trait.md (new ExecPlan)
  • docs/asynchronous-outbound-messaging-design.md (unified pipeline notes)
  • docs/multi-packet-and-streaming-responses-design.md (unified pipeline note)
  • docs/users-guide.md (unified codec path guidance)
  • docs/roadmap.md (mark item 9.3.1 as done upon completion)

Validation & acceptance criteria

  • All outbound frames pass through the unified FramePipeline before reaching the wire.
  • before_send hook fires for every outbound frame (where implemented in the unified path).
  • Duplicate codec construction removed; the server-facing path owns framing.
  • Integration and BDD tests demonstrate streaming, back-pressure, interleaving, and fragmentation through the unified path.
  • Documentation reflects the unified behavior and updated roadmaps.

Artifacts

  • New: src/app/codec_driver.rs
  • Updated: src/app/connection.rs, src/app/frame_handling/core.rs, reassembly.rs, response.rs
  • New tests and fixtures under tests/ and tests/fixtures/unified_codec/
  • New: tests/features/unified_codec.feature, tests/scenarios/unified_codec_scenarios.rs, tests/steps/unified_codec_steps.rs
  • New: docs/execplans/9-3-1-fragment-adapter-trait.md
  • Updated: docs/asynchronous-outbound-messaging-design.md, docs/multi-packet-and-streaming-responses-design.md, docs/users-guide.md, docs/roadmap.md

Task reference

Revision note (2026-02-15)

  • Initial draft added for roadmap item 9.3.1, outlining a codec-aware connection driver to unify outbound framing and hook/fragmentation behavior across server paths.

Summary by Sourcery

Unify the server-side outbound codec path by introducing a FramePipeline and codec driver utilities, routing all outbound envelopes through a single fragmentation- and metrics-aware pipeline and adding end-to-end tests and docs to cover the unified behaviour.

Enhancements:

  • Replace per-response fragmentation and send helpers with a FramePipeline that centralises outbound fragmentation and metrics for all envelopes.
  • Wire the connection handling and response flow to use FramePipeline for both outbound fragmentation and inbound reassembly, removing direct FragmentationState management from the connection loop.
  • Introduce codec-aware helpers (send_envelope and flush_pipeline_output) to serialise envelopes, wrap them with the configured codec, and write them to the framed transport stream.

Documentation:

  • Add an ExecPlan document for roadmap item 9.3.1 detailing the design, constraints, decisions, and outcomes of the unified codec handling work.
  • Update asynchronous outbound messaging, multi-packet/streaming response design docs, and the user guide to describe the new unified server-side FramePipeline behaviour.
  • Mark roadmap item 9.3.1 and its sub-tasks as complete, reflecting the unified codec handling implementation.

Tests:

  • Add unified_codec integration tests that exercise the unified outbound pipeline over in-memory duplex streams, covering round-trips, fragmentation, sequential requests, and disabled-fragmentation cases.
  • Introduce a UnifiedCodecWorld fixture plus rstest-bdd feature, scenario, and step modules to provide BDD coverage of the unified codec pipeline semantics.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Feb 15, 2026

Reviewer's Guide

Unifies the server-side outbound path around a new FramePipeline and codec-aware helpers so that all handler responses, fragmentation, and metrics flow through a single pipeline, and adds end-to-end tests and docs to validate and describe the unified codec behavior.

Sequence diagram for unified outbound response path via FramePipeline

sequenceDiagram
    actor Client
    participant WireframeApp
    participant HandlerService
    participant ResponseContext
    participant FramePipeline
    participant Serializer
    participant FrameCodec
    participant Framed
    participant Transport

    Client->>WireframeApp: send_request
    WireframeApp->>HandlerService: call_handler(env)
    HandlerService-->>WireframeApp: Response

    WireframeApp->>ResponseContext: forward_response(env, response)
    ResponseContext->>ResponseContext: build_PacketParts
    ResponseContext->>ResponseContext: Envelope::from_parts
    ResponseContext->>FramePipeline: process(envelope)
    FramePipeline->>FramePipeline: fragment_envelope
    FramePipeline->>FramePipeline: push_frame(outbound_envelope)

    ResponseContext->>FramePipeline: drain_output
    FramePipeline-->>ResponseContext: Vec<Envelope>

    ResponseContext->>Serializer: serialize(envelope)
    Serializer-->>ResponseContext: bytes
    ResponseContext->>FrameCodec: wrap_payload(bytes)
    FrameCodec-->>ResponseContext: frame
    ResponseContext->>Framed: send(frame)
    Framed-->>Transport: write_bytes
    Transport-->>Client: response_frames
Loading

Updated class diagram for FramePipeline and codec driver helpers

classDiagram
    class FramePipeline {
        -Option~FragmentationState~ fragmentation
        -Vec~Envelope~ out
        +FramePipeline new(fragmentation: Option~FragmentationConfig~)
        +process(envelope: Envelope) void
        +purge_expired() void
        +drain_output() Vec~Envelope~
        +fragmentation_mut() Option~&mut FragmentationState~
        +has_fragmentation() bool
        -fragment_envelope(envelope: Envelope) Result~Vec~Envelope~, FragmentationError~
        -push_frame(envelope: Envelope) void
    }

    class Envelope {
        +id: u32
        +correlation_id: Option~u64~
        +payload: Vec~u8~
        +new(id: u32, correlation_id: Option~u64~, payload: Vec~u8~) Envelope
        +from_parts(parts: PacketParts) Envelope
    }

    class FragmentationState {
        +new(config: FragmentationConfig) FragmentationState
        +fragment(envelope: Envelope) Result~Vec~Envelope~, FragmentationError~
        +reassemble(envelope: Envelope) Result~Option~Envelope~, FragmentationError~
        +purge_expired() void
    }

    class FragmentationConfig
    class FragmentationError

    class Serializer {
        <<trait>>
        +serialize(envelope: &Envelope) Result~Vec~u8~, SerializeError~
    }

    class FrameCodec {
        <<trait>>
        +wrap_payload(payload: Bytes) Frame
    }

    class ConnectionCodec {
    }

    class Framed {
        +send(frame: Frame) Future~Result~(), io::Error~~
    }

    class Bytes

    class ResponseContext {
        +serializer: &Serializer
        +framed: &mut Framed
        +pipeline: &mut FramePipeline
        +codec: &FrameCodec
    }

    class codec_driver_helpers {
        +send_envelope(serializer: &Serializer, codec: &FrameCodec, framed: &mut Framed, envelope: &Envelope) Future~Result~(), io::Error~~
        +flush_pipeline_output(serializer: &Serializer, codec: &FrameCodec, framed: &mut Framed, envelopes: &mut Vec~Envelope~) Future~Result~(), io::Error~~
    }

    FramePipeline --> FragmentationState : uses
    FramePipeline --> Envelope : processes
    FramePipeline --> FragmentationConfig : configured_by
    FramePipeline --> FragmentationError : error_type

    ResponseContext --> FramePipeline : holds_mut_ref
    ResponseContext --> Serializer : uses
    ResponseContext --> FrameCodec : uses
    ResponseContext --> Framed : writes_to

    codec_driver_helpers --> Serializer : uses
    codec_driver_helpers --> FrameCodec : uses
    codec_driver_helpers --> Framed : writes_to
    codec_driver_helpers --> Envelope : sends

    ConnectionCodec ..> FrameCodec : wraps
    Framed ..> ConnectionCodec : parameterized_by
    FrameCodec ..> Bytes : payload_type
Loading

Flow diagram for unified inbound and outbound fragmentation with FramePipeline

flowchart LR
    subgraph InboundPath
        A[Inbound_frame_from_transport] --> B[ConnectionCodec_decode]
        B --> C[Envelope]
        C --> D[FramePipeline_fragmentation_mut]
        D --> E[FragmentationState_reassemble]
        E -->|Some_Envelope| F[Handler_dispatch]
        E -->|None| G[Wait_for_more_fragments]
    end

    subgraph HandlerAndResponse
        F --> H[HandlerService_execute]
        H --> I[Response]
        I --> J[build_PacketParts]
        J --> K[Envelope::from_parts]
        K --> L[FramePipeline_process]
        L --> M[FramePipeline_drain_output]
    end

    subgraph OutboundPath
        M --> N[Vec_Envelope_]
        N --> O[flush_pipeline_output]
        O --> P[send_envelope]
        P --> Q[Serialize_with_Serializer]
        Q --> R[FrameCodec_wrap_payload]
        R --> S[Framed_send]
        S --> T[Bytes_on_wire]
    end

    subgraph SharedFragmentationState
        D --- L
        L --- U[FragmentationState_shared_in_FramePipeline]
    end
Loading

File-Level Changes

Change Details Files
Introduce FramePipeline and codec-aware helpers to own outbound fragmentation, metrics, and sending
  • Add src/app/codec_driver.rs implementing FramePipeline, send_envelope, and flush_pipeline_output to fragment Envelope values, record outbound metrics, and serialize/wrap/send via FrameCodec::wrap_payload
  • Provide pipeline utilities such as fragmentation_mut, purge_expired, and tests verifying basic behavior and lack of fragmentation when disabled
src/app/codec_driver.rs
Refactor connection handling to route outbound and reassembly through FramePipeline instead of ad-hoc FragmentationState and per-response codec wrapping
  • Change HandleFrameContext to carry &mut FramePipeline instead of &mut Option and construct FramePipeline once per connection using the app’s FragmentationConfig
  • Use pipeline in the main connection loop for outbound responses and inbound reassembly, including purge_expired on read timeouts
  • Remove local fragmentation_config helper and direct FragmentationState management from connection.rs
src/app/connection.rs
src/app/frame_handling/core.rs
src/app/frame_handling/reassembly.rs
Route response forwarding through FramePipeline and shared codec helpers instead of doing fragmentation and send logic inline
  • Update forward_response to build an Envelope from PacketParts, push it through ctx.pipeline.process, then drain and flush via flush_pipeline_output
  • Remove fragment_responses, serialize_response, and send_response_payload helpers in response.rs in favor of the shared codec_driver helpers
  • Adapt tests to target send_envelope instead of send_response_payload and update ResponseContext tests to validate pipeline usage
src/app/frame_handling/response.rs
src/app/frame_handling/tests.rs
Expose codec_driver module and hook it into the app namespace
  • Add codec_driver module to src/app/mod.rs so FramePipeline and helpers are available to app internals and tests
src/app/mod.rs
Add integration tests exercising the unified codec path via WireframeApp over in-memory transports
  • Create tests/unified_codec.rs to validate round-trip handler responses, fragmented responses, small unfragmented payloads, sequential requests, and behavior when fragmentation is disabled
  • Reuse shared fragment_helpers to build and send fragmented envelopes and to read/reassemble responses under the new pipeline
tests/unified_codec.rs
tests/common/fragment_helpers.rs
Add rstest-bdd fixtures, transport helpers, and scenarios for unified codec behavior
  • Add UnifiedCodecWorld fixture and transport helpers under tests/fixtures/unified_codec/ to drive duplex connections, fragmentation, and payload collection
  • Add BDD steps and scenarios in tests/steps/unified_codec_steps.rs and tests/scenarios/unified_codec_scenarios.rs, plus a unified_codec.feature describing behavior around fragmentation, ordering, and unfragmented paths
  • Wire new unified_codec fixture, steps, and scenarios into the existing test harness modules
tests/fixtures/mod.rs
tests/fixtures/unified_codec/mod.rs
tests/fixtures/unified_codec/transport.rs
tests/steps/mod.rs
tests/steps/unified_codec_steps.rs
tests/scenarios/mod.rs
tests/scenarios/unified_codec_scenarios.rs
tests/features/unified_codec.feature
Document the unified outbound pipeline and mark roadmap item 9.3.1 as complete
  • Add an ExecPlan document detailing constraints, decisions, and outcomes for 9.3.1 and how FramePipeline & CodecDriver unify outbound handling
  • Update asynchronous-outbound-messaging-design.md, multi-packet-and-streaming-responses-design.md, and users-guide.md with notes on the server-side FramePipeline and its interaction with fragmentation and hooks
  • Mark roadmap item 9.3.1 and its sub-items as done, explaining that protocol hooks are partially deferred
docs/execplans/9-3-1-fragment-adapter-trait.md
docs/asynchronous-outbound-messaging-design.md
docs/multi-packet-and-streaming-responses-design.md
docs/users-guide.md
docs/roadmap.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 15, 2026

No actionable comments were generated in the recent review. 🎉


Summary by CodeRabbit

  • New Features

    • Unified codec pipeline for all outbound server responses, applying consistent fragmentation and outbound metrics to handler responses, streaming frames and multi‑packet channels.
  • Documentation

    • Added design and execution plans plus roadmap and user‑guide updates describing the unified pipeline.
  • Tests

    • Added end‑to‑end and behaviour‑driven tests covering fragmented, unfragmented and sequential payload scenarios.

Walkthrough

Add a FramePipeline and codec_driver module that centralises outbound fragmentation, buffering and metrics; replace prior FragmentationState usage across connection, reassembly and response flows; add envelope-based send helpers and extensive BDD and integration tests validating the unified outbound codec path.

Changes

Cohort / File(s) Summary
Documentation & Design
docs/asynchronous-outbound-messaging-design.md, docs/multi-packet-and-streaming-responses-design.md, docs/roadmap.md, docs/users-guide.md, docs/execplans/9-3-1-fragment-adapter-trait.md
Document the unified FramePipeline / codec-driver server path, update roadmap/status, add staged execplan and deferred protocol-hook integration; include codec/fragmentation snippets.
Codec Pipeline Core
src/app/codec_driver.rs, src/app/mod.rs
Add codec_driver module and FramePipeline (optional fragmentation, internal output buffer, metrics) plus helpers send_envelope and flush_pipeline_output; wire module into app mod.
Connection & Frame Handling
src/app/connection.rs, src/app/frame_handling/core.rs, src/app/frame_handling/reassembly.rs, src/app/frame_handling/response.rs, src/app/frame_handling/tests.rs
Replace FragmentationState/FragmentationConfig with FramePipeline; update ResponseContext and reassemble/forward_response flows to use pipeline APIs and pipeline.flush semantics.
Tests — BDD & Integration
tests/features/unified_codec.feature, tests/scenarios/unified_codec_scenarios.rs, tests/unified_codec.rs
Add feature file, scenario bindings and integration tests exercising unified pipeline across fragmented, unfragmented, sequential and disabled-fragmentation cases.
Tests — Fixtures & Transport
tests/fixtures/mod.rs, tests/fixtures/unified_codec/mod.rs, tests/fixtures/unified_codec/transport.rs, tests/common/unified_codec_transport.rs
Introduce UnifiedCodecWorld fixture, transport helpers, fragmentation/reassembly helpers, and shared test send/recv utilities for envelopes.
Tests — Steps & Wiring
tests/steps/mod.rs, tests/steps/unified_codec_steps.rs, tests/scenarios/mod.rs
Add BDD step definitions, runtime shim for sync steps and module wiring for unified codec scenarios.
Test helpers & assembly
src/test_helpers.rs, src/app/frame_handling/assembly_tests.rs, tests/fixtures/message_assembly_inbound.rs, tests/steps/message_assembly_inbound_steps.rs
Change test payload helpers to return Results, update tests to unwrap/propagate helper results and add a singular step alias.
Minor docs/test edits
docs/execplans/vocabulary-normalization.md, src/client/builder/mod.rs, assorted test files
Editorial and grammar fixes across docs and tests.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant Pipeline as FramePipeline
    participant Fragmenter as Fragmenter
    participant Serializer as Serializer
    participant Wire as Wire

    Client->>Pipeline: submit Envelope
    alt fragmentation enabled
        Pipeline->>Fragmenter: fragment_envelope(Envelope)
        Fragmenter-->>Pipeline: fragments (Vec<Envelope>)
    else fragmentation disabled
        Pipeline-->>Pipeline: pass-through Envelope
    end
    Pipeline->>Pipeline: push_frame(envelope) / increment metrics
    Pipeline->>Serializer: send_envelope(serializer, codec, framed, envelope)
    alt send succeeds
        Serializer->>Wire: write framed bytes
        Wire-->>Client: deliver framed response
    else send error
        Serializer->>Pipeline: log error / increment handler errors
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

Frames align where fragments once played,
One pipeline sings; the pathways laid,
Envelopes march, metrics count the tune,
Tests light the night and catch the moon 🌙
Code sleeps sound beneath the unified rune

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed Title concisely summarises the main architectural change: introducing FramePipeline and CodecDriver to unify outbound codec path.
Description check ✅ Passed Description is comprehensive and directly related to the changeset, detailing implementation, testing, documentation updates, and rationale for the unified codec path.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch unify-codec-handling-9-3-1-mn7az7

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

@leynos leynos changed the title Add ExecPlan: unify codec handling for app router & Connection actor Unify outbound codec path with FramePipeline & CodecDriver Feb 15, 2026
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Feb 17, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix:

tests/fixtures/unified_codec/mod.rs

Comment on lines +107 to +127

    pub fn verify_handler_payloads(&self) -> TestResult {
        if self.handler_observed.len() != self.sent_payloads.len() {
            return Err(format!(
                "handler payload count mismatch: expected {}, got {}",
                self.sent_payloads.len(),
                self.handler_observed.len()
            )
            .into());
        }
        for (i, (observed, expected)) in self
            .handler_observed
            .iter()
            .zip(self.sent_payloads.iter())
            .enumerate()
        {
            if observed != expected {
                return Err(format!("handler payload {i} mismatch").into());
            }
        }
        Ok(())
    }

❌ New issue: Code Duplication
The module contains 2 functions with similar structure: UnifiedCodecWorld.verify_handler_payloads,UnifiedCodecWorld.verify_response_payloads

@coderabbitai

This comment was marked as resolved.

@leynos leynos marked this pull request as ready for review February 18, 2026 19:46
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 8 issues, and left some high level feedback:

  • In FramePipeline::process fragmentation errors are now logged and dropped rather than propagated (unlike the previous fragment_responses path that returned an io::Error); if this change in failure semantics is intentional it might be worth double‑checking that callers are happy with fragmentation failures becoming non‑fatal and invisible to the response path.
  • The warning in FramePipeline::process ("failed to fragment outbound envelope") no longer includes the envelope id/correlation id that the old fragment_responses logging had; consider adding those fields back into the log context to make production debugging easier.
  • The new unified codec tests duplicate low‑level send/receive helpers (e.g. send_one/recv_one) in both tests/unified_codec.rs and tests/fixtures/unified_codec/transport.rs; factoring these into a single shared helper would reduce repetition and keep the transport behaviour consistent across tests.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `FramePipeline::process` fragmentation errors are now logged and dropped rather than propagated (unlike the previous `fragment_responses` path that returned an `io::Error`); if this change in failure semantics is intentional it might be worth double‑checking that callers are happy with fragmentation failures becoming non‑fatal and invisible to the response path.
- The warning in `FramePipeline::process` (`"failed to fragment outbound envelope"`) no longer includes the envelope id/correlation id that the old `fragment_responses` logging had; consider adding those fields back into the log context to make production debugging easier.
- The new unified codec tests duplicate low‑level send/receive helpers (e.g. `send_one`/`recv_one`) in both `tests/unified_codec.rs` and `tests/fixtures/unified_codec/transport.rs`; factoring these into a single shared helper would reduce repetition and keep the transport behaviour consistent across tests.

## Individual Comments

### Comment 1
<location> `src/app/codec_driver.rs:55-61` </location>
<code_context>
+    ///
+    /// Processed envelopes are buffered internally. Call
+    /// [`drain_output`](Self::drain_output) to retrieve them.
+    pub(crate) fn process(&mut self, envelope: Envelope) {
+        let frames = match self.fragment_envelope(envelope) {
+            Ok(frames) => frames,
+            Err(err) => {
+                warn!("failed to fragment outbound envelope: error={err:?}");
+                crate::metrics::inc_handler_errors();
+                return;
+            }
+        };
</code_context>

<issue_to_address>
**issue (bug_risk):** Outbound fragmentation errors are now swallowed, changing previous error-propagation semantics.

Previously, `fragment_responses` returned an `io::Result<Vec<Envelope>>` and `forward_response` propagated fragmentation failures as `io::Error`, so transport-level issues were surfaced to callers. In the new flow, `process` logs, bumps metrics, and returns `()` on `FragmentationError`, so `forward_response` still appears to succeed and the handler behaves as if the response was sent. That changes the intended separation between handler failures (`Ok(())`) and transport failures (`Err(io::Error)`). If this change isn’t deliberate, consider having `process` return a `Result` (or similar) so `forward_response` can propagate transport/protocol/serialization errors instead of silently dropping them.
</issue_to_address>

### Comment 2
<location> `docs/execplans/9-3-1-fragment-adapter-trait.md:150-153` </location>
<code_context>
+- [x] (2026-02-15 01:00Z) Stage B: created `src/app/codec_driver.rs` with
+  `FramePipeline` struct. Handles outbound fragmentation and metrics. All
+  existing tests pass.
+- [x] (2026-02-15 01:30Z) Stage C: updated `frame_handling/core.rs`,
+  `frame_handling/response.rs`, `frame_handling/reassembly.rs`, and
+  `frame_handling/tests.rs` to use `FramePipeline`. Responses now route through
+  the pipeline (fragment → metrics → serialize → send). All gates pass (fmt,
+  lint, test).
</code_context>

<issue_to_address>
**nitpick (typo):** Use en-GB spelling for “serialise” to match the stated spelling constraint.

In “Responses now route through the pipeline (fragment → metrics → serialize → send)”, please change “serialize” to “serialise” to match the en-GB-oxendict constraint and existing uses like “serialisation” elsewhere in the docs.

```suggestion
  `frame_handling/response.rs`, `frame_handling/reassembly.rs`, and
  `frame_handling/tests.rs` to use `FramePipeline`. Responses now route through
  the pipeline (fragment → metrics → serialise → send). All gates pass (fmt,
  lint, test).
```
</issue_to_address>

### Comment 3
<location> `docs/execplans/9-3-1-fragment-adapter-trait.md:134` </location>
<code_context>
+  codec-aware variant (or wrapper) for the server path. The standalone actor
+  remains useful for client scenarios and direct testing.
+
+- Risk: the app router currently handles deserialization failures with a
+  counter and threshold (`MAX_DESER_FAILURES`). Moving decode into a separate
+  loop task may complicate shared mutable state. Severity: low. Likelihood:
</code_context>

<issue_to_address>
**nitpick (typo):** Use en-GB spelling for “deserialisation” for consistency.

Since we’re standardising on en-GB-oxendict, please change “deserialization failures” to “deserialisation failures” to match nearby terms like “serialisation” and “behavioural”.

```suggestion
- Risk: the app router currently handles deserialisation failures with a
```
</issue_to_address>

### Comment 4
<location> `docs/asynchronous-outbound-messaging-design.md:840` </location>
<code_context>
+- **Unified Codec Pipeline:** On the server side, the `FramePipeline`
+  (`src/app/codec_driver.rs`) applies outbound fragmentation and metrics to
+  every `Envelope` before it reaches the wire. Handler responses pass through
+  the pipeline before serialisation and codec wrapping, ensuring the same
+  fragmentation logic applies to both handler responses and push traffic.
+  Protocol hooks are applied at the connection-actor level and are currently
</code_context>

<issue_to_address>
**suggestion (review_instructions):** "serialisation" should use an -ize form under en-GB-oxendict conventions ("serialization").

The style guide specifies en-GB-oxendict spelling, which uses -ize forms. Please change "serialisation" here to "serialization".

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Use en-GB-oxendic (-ize / -yse / -our) spelling and grammar.

</details>
</issue_to_address>

### Comment 5
<location> `docs/users-guide.md:877` </location>
<code_context>

+On the server side, a unified `FramePipeline` applies the same fragmentation
+logic to all outbound `Envelope` values — handler responses, streaming frames,
+and multi-packet channels — before serialisation and codec wrapping. This
+guarantees that a single connection-scoped `FragmentationState` manages both
+outbound fragmentation and inbound reassembly.
</code_context>

<issue_to_address>
**suggestion (review_instructions):** "serialisation" should be written with -ize spelling ("serialization") to match en-GB-oxendict.

To align with the en-GB-oxendict style (-ize / -yse / -our), please update "serialisation" to "serialization" here.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Use en-GB-oxendic (-ize / -yse / -our) spelling and grammar.

</details>
</issue_to_address>

### Comment 6
<location> `docs/execplans/9-3-1-fragment-adapter-trait.md:162` </location>
<code_context>
+  `tests/unified_codec.rs`. Five tests: round-trip, fragmented response,
+  unfragmented small payload, multiple sequential requests, disabled
+  fragmentation. Committed in `1b2851a`.
+- [x] (2026-02-15 03:00Z) Stage F: BDD behavioural tests added. Five
+  rstest-bdd scenarios in `tests/features/unified_codec.feature` with fixture
+  `tests/fixtures/unified_codec/` and steps
</code_context>

<issue_to_address>
**suggestion (review_instructions):** "BDD" is introduced without being expanded on first use.

The instructions ask for uncommon acronyms to be defined on first use. Please expand this to something like "Behaviour-Driven Development (BDD) behavioural tests" here, or add an explicit definition immediately before this bullet.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Define uncommon acronyms on first use.

</details>
</issue_to_address>

### Comment 7
<location> `docs/execplans/9-3-1-fragment-adapter-trait.md:586` </location>
<code_context>
+The exact integration point (pre-wrapped frames vs. `Envelope` values) will be
+decided in Stage A and recorded in the decision log.
+
+### Fragmentation reconciliation
+
+Today path 1 fragments at the `Envelope` level (before serialisation) and path
</code_context>

<issue_to_address>
**suggestion (review_instructions):** Within this section, "serialiser" should be "serializer" to follow the -ize/-izer convention.

In the sentence "The design documents specify outbound order as \"serialiser → fragmentation → codec framing\"", "serialiser" should be updated to "serializer" to follow en-GB-oxendict (-ize/-izer) spelling.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Use en-GB-oxendic (-ize / -yse / -our) spelling and grammar.

</details>
</issue_to_address>

### Comment 8
<location> `docs/execplans/9-3-1-fragment-adapter-trait.md:421` </location>
<code_context>
+1. Construct the codec-aware driver from Stage B.
+2. Split the connection loop into an inbound decode task and an outbound
+   actor/writer task communicating via an internal bounded channel.
+3. When a handler returns `Response::Single(bytes)` or `Response::Vec(v)`,
+   send the serialised, wrapped frames through the actor's input channel so
+   hooks and fragmentation apply.
</code_context>

<issue_to_address>
**suggestion (review_instructions):** Later in this list item, "serialised" should be "serialized" to match en-GB-oxendict spelling.

This bullet refers to "the serialised, wrapped frames". To comply with the en-GB-oxendict (-ize) guidance, please change "serialised" to "serialized".

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Use en-GB-oxendic (-ize / -yse / -our) spelling and grammar.

</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/app/codec_driver.rs Outdated
Comment thread docs/execplans/9-3-1-fragment-adapter-trait.md
Comment thread docs/execplans/9-3-1-fragment-adapter-trait.md
Comment thread docs/asynchronous-outbound-messaging-design.md Outdated
Comment thread docs/users-guide.md Outdated
Comment thread docs/execplans/9-3-1-fragment-adapter-trait.md Outdated
Comment thread docs/execplans/9-3-1-fragment-adapter-trait.md
Comment thread docs/execplans/9-3-1-fragment-adapter-trait.md
@coderabbitai coderabbitai Bot added the codex label Feb 18, 2026
chatgpt-codex-connector[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

leynos and others added 9 commits February 18, 2026 21:10
…etween app router and Connection actor

Introduce a comprehensive 626-line ExecPlan document outlining the design, constraints, risks, progress, and testing strategies for unifying codec handling between the app router and Connection actor in the Wireframe server runtime. This living document elaborates on the existing dual-path architecture, the need for uniform protocol hook invocation, fragmentation, and metrics handling by routing all outbound payloads through a codec-aware ConnectionActor wrapper.

The plan defines stages from initial design, scaffolding a codec driver, refactoring response handling, integration and BDD tests, to documentation updates, ensuring source compatibility and no public API breaks. This foundational strategy aims to harmonize streaming, push, and multi-packet responses and enhance robustness and maintainability.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
Introduce `FramePipeline` in `src/app/codec_driver.rs` to centralise
outbound fragmentation and metrics for handler responses. All outbound
envelopes now pass through a single pipeline that applies optional
fragmentation before serialisation and codec wrapping.

Key changes:
- Add `codec_driver` module with `FramePipeline`, `send_envelope`, and
  `flush_pipeline_output` helpers
- Update `frame_handling/core.rs` `ResponseContext` to hold a
  `FramePipeline` reference instead of raw `FragmentationState`
- Simplify `frame_handling/response.rs` to route through the pipeline
  instead of ad-hoc fragment → serialize → send
- Update `frame_handling/reassembly.rs` to access fragmentation state
  via `FramePipeline::fragmentation_mut()`
- Remove duplicate `fragment_responses()`, `serialize_response()`, and
  `send_response_payload()` helpers
- Update exec plan with progress and design decisions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add `tests/unified_codec.rs` with five integration tests exercising the
`FramePipeline`-based outbound path end-to-end:

- handler_response_round_trips_through_pipeline
- fragmented_response_passes_through_pipeline
- small_payload_passes_unfragmented
- multiple_sequential_requests_through_pipeline
- pipeline_with_no_fragmentation_passes_large_payload

Tests use duplex streams with `handle_connection_result` to validate
that handler responses flow correctly through the unified pipeline,
including both fragmented and unfragmented payloads.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Five rstest-bdd scenarios validate the FramePipeline end-to-end:
handler round-trip, fragmented response, unfragmented small payload,
multiple sequential requests, and disabled-fragmentation passthrough.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Record the FramePipeline unification in the outbound messaging design,
multi-packet/streaming design, and users guide. Mark roadmap item 9.3.1
and its sub-items as done. Update exec plan progress to stage H.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All stages complete. Quality gates pass. Protocol hooks deferred to
follow-up stage due to F::Frame vs Envelope type constraint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ion logic

Extracted common verification logic from verify_handler_payloads and verify_response_payloads into a new verify_payloads_match helper method to reduce code duplication and improve maintainability.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
…458)

* docs(execplans): add execplan for integrating MessageAssembler inbound

Introduces a comprehensive execution plan document detailing the integration of the MessageAssembler trait into the inbound connection path. The plan covers constraints, tolerances, risks, progress stages, tests, and documentation updates corresponding to roadmap items 8.2.5 and 8.2.6.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

* feat(app/frame_handling): integrate inbound message assembly in connection path

- Added protocol-level message assembly on the inbound path after transport fragmentation reassembly and before handler dispatch.
- Implemented parsing and continuity validation for message assembly frames with unified failure handling using deserialization failure policy.
- Introduced new modules for assembly logic (`assembly.rs`) and envelope decoding (`decode.rs`) to streamline connection code.
- Updated `WireframeApp` connection handling to create and maintain message assembly state alongside fragmentation state.
- Added detailed unit tests and behavioral tests for interleaving, ordering violations, timeout purging, and integration scenarios.
- Upgraded `rstest-bdd` dev-dependencies to v0.5.0 to support new behavioral tests.
- Updated documentation, exec plans, and roadmap to reflect completed message assembly integration (items 8.2.5 and 8.2.6).

This enhancement completes the roadmap for streaming requests and shared message assembly, improving protocol multiplexing and robustness on the inbound connection path.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

* refactor(tests): refactor continuation frame sending into single helper method

Refactored the sending of continuation frames in message_assembly_inbound.rs by combining repeated code into a new helper method `send_continuation_frame_impl`. This reduces duplication and clarifies the distinction between final and non-final continuation frames while preserving existing functionality.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

* refactor(tests): use newtype wrappers for message key and frame sequence

Introduce MessageKey and FrameSequence newtype structs to enhance type safety
in the message assembly inbound test fixture. Update related methods to accept
these types via Into conversions, improving code clarity and preventing misuse
of raw integers.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

* refactor(tests): use ContinuationFrameParams struct in message assembly tests

Refactor send_continuation_frame_impl method to accept a ContinuationFrameParams struct instead of multiple parameters, improving code clarity and maintainability in the message assembly inbound test fixture.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

* refactor(frame_handling): extract helper to simplify assembly testing code

Introduced `process_assembly_frame` helper function to encapsulate calls to `assemble_if_needed` with assembly state and parameters. Replaced repetitive assembly invocation patterns in integration tests with this helper to improve code readability and maintainability without changing test logic.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

* refactor(frame_handling): unify message assembly error handling and payload helpers

- Introduced AssemblyContext::fail_invalid_none for streamlined error recording
- Replaced envelope_from_assembled function with Envelope::from_assembled method
- Moved test helpers for building first and continuation frame payloads to a common test_helpers module
- Updated tests and fixtures to use shared payload builders instead of local copies
- Adjusted failure counter reset in connection.rs to occur only after full inbound pipeline success
- Minor docs wording improvements

This refactor improves consistency in error handling, code reuse for test data generation, and overall maintainability of the message assembly logic.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

* test(frame_handling): replace thread sleep with synthetic clock in assembly timeout test

Replaced the use of thread::sleep with advancing a synthetic clock (Instant) in the inbound assembly timeout test. This change makes the test deterministic and independent of real wall-clock scheduling, improving reliability of timeout purging behavior verification.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

* test(fixtures): deterministically control tokio time in message assembly tests

Refactor MessageAssemblyInboundWorld tests to use a current-thread Tokio runtime with all features enabled.
Pause the Tokio clock at test start and replace sleep calls with time advancements. This improves test determinism and makes time-dependent actions independent of wall-clock scheduling.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

* feat(message_assembler): preserve envelope routing metadata from first frame

- Introduce `EnvelopeRouting` struct to carry envelope_id and correlation_id.
- Extend `FirstFrameInput` and `AssembledMessage` to include `EnvelopeRouting`.
- Modify message assembly state to track and propagate routing metadata through assembly.
- Update frame handling and assembly tests to preserve routing info on completed messages.
- Ensure completed messages use envelope routing metadata from the initial first frame regardless of continuation frames.
- Improves message dispatching and correlation by retaining original envelope identifiers throughout multi-frame message assembly.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

* feat(message-assembler): introduce EnvelopeId and CorrelationId newtypes for routing

Refactor routing metadata types by replacing raw u32 and u64 identifiers with
strongly typed wrappers: EnvelopeId and CorrelationId. This improves type safety
and clarity in message assembly and frame handling components. Update related
code, tests, and documentation to use these newtypes accordingly.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

* docs(tests): enhance fixture documentation for inbound message assembly

Improve the doc comment for the MessageAssemblyInboundWorld fixture used in BDD test scenarios. Clarifies its purpose for rstest injection and its role in exercising inbound message assembly integration within scenario tests.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>

---------

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
Deduplicate the message assembly local and context field bindings in
src/app/connection.rs after the rebase conflict merge.

This keeps the merged FramePipeline + message assembly behaviour while
restoring a compilable FrameHandlingContext construction/destructuring
path.
@leynos leynos force-pushed the unify-codec-handling-9-3-1-mn7az7 branch from a3fae3e to 8735a08 Compare February 18, 2026 21:19
coderabbitai[bot]

This comment was marked as resolved.

…per modules

- Introduced a shared Tokio runtime for synchronous BDD test steps to avoid
  repetitive runtime creation and blocking.
- Extracted common send/receive helpers into a shared module for reuse across
  integration and behavioral tests.
- Refactored test fixtures and integration test harness to use shared helpers
  and runtime.
- Improved error handling and test code clarity by eliminating redundant
  async runtime creations.

This refactor improves test code maintainability and performance by
centralizing common logic and resource usage.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
coderabbitai[bot]

This comment was marked as resolved.

Refactored the 'then_handler_receives_payload' and 'then_handler_receives_reassembled' test steps in `unified_codec_steps.rs` to use a new helper function `collect_and_verify_handler_payloads`. This reduces code duplication and improves test code clarity.

Additionally, improved documentation clarity in `docs/execplans/9-3-1-fragment-adapter-trait.md` with expanded acronyms and consistent spelling, and added a doc comment in `unified_codec.rs` for the `setup_harness` function.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Feb 18, 2026

@coderabbitai Have the following now been resolved?

Please address the comments from this code review:

## Overall Comments
- In `FramePipeline::process` fragmentation errors are now logged and dropped rather than propagated (unlike the previous `fragment_responses` path that returned an `io::Error`); if this change in failure semantics is intentional it might be worth double‑checking that callers are happy with fragmentation failures becoming non‑fatal and invisible to the response path.
- The warning in `FramePipeline::process` (`"failed to fragment outbound envelope"`) no longer includes the envelope id/correlation id that the old `fragment_responses` logging had; consider adding those fields back into the log context to make production debugging easier.
- The new unified codec tests duplicate low‑level send/receive helpers (e.g. `send_one`/`recv_one`) in both `tests/unified_codec.rs` and `tests/fixtures/unified_codec/transport.rs`; factoring these into a single shared helper would reduce repetition and keep the transport behaviour consistent across tests.

## Individual Comments

### Comment 1
<location> `src/app/codec_driver.rs:55-61` </location>
<code_context>
+    ///
+    /// Processed envelopes are buffered internally. Call
+    /// [`drain_output`](Self::drain_output) to retrieve them.
+    pub(crate) fn process(&mut self, envelope: Envelope) {
+        let frames = match self.fragment_envelope(envelope) {
+            Ok(frames) => frames,
+            Err(err) => {
+                warn!("failed to fragment outbound envelope: error={err:?}");
+                crate::metrics::inc_handler_errors();
+                return;
+            }
+        };
</code_context>

<issue_to_address>
**issue (bug_risk):** Outbound fragmentation errors are now swallowed, changing previous error-propagation semantics.

Previously, `fragment_responses` returned an `io::Result<Vec<Envelope>>` and `forward_response` propagated fragmentation failures as `io::Error`, so transport-level issues were surfaced to callers. In the new flow, `process` logs, bumps metrics, and returns `()` on `FragmentationError`, so `forward_response` still appears to succeed and the handler behaves as if the response was sent. That changes the intended separation between handler failures (`Ok(())`) and transport failures (`Err(io::Error)`). If this change isn’t deliberate, consider having `process` return a `Result` (or similar) so `forward_response` can propagate transport/protocol/serialization errors instead of silently dropping them.
</issue_to_address>

### Comment 2
<location> `docs/execplans/9-3-1-fragment-adapter-trait.md:150-153` </location>
<code_context>
+- [x] (2026-02-15 01:00Z) Stage B: created `src/app/codec_driver.rs` with
+  `FramePipeline` struct. Handles outbound fragmentation and metrics. All
+  existing tests pass.
+- [x] (2026-02-15 01:30Z) Stage C: updated `frame_handling/core.rs`,
+  `frame_handling/response.rs`, `frame_handling/reassembly.rs`, and
+  `frame_handling/tests.rs` to use `FramePipeline`. Responses now route through
+  the pipeline (fragment → metrics → serialize → send). All gates pass (fmt,
+  lint, test).
</code_context>

<issue_to_address>
**nitpick (typo):** Use en-GB spelling for “serialise” to match the stated spelling constraint.

In “Responses now route through the pipeline (fragment → metrics → serialize → send)”, please change “serialize” to “serialise” to match the en-GB-oxendict constraint and existing uses like “serialisation” elsewhere in the docs.

```suggestion
  `frame_handling/response.rs`, `frame_handling/reassembly.rs`, and
  `frame_handling/tests.rs` to use `FramePipeline`. Responses now route through
  the pipeline (fragment → metrics → serialise → send). All gates pass (fmt,
  lint, test).
```
</issue_to_address>

### Comment 3
<location> `docs/execplans/9-3-1-fragment-adapter-trait.md:134` </location>
<code_context>
+  codec-aware variant (or wrapper) for the server path. The standalone actor
+  remains useful for client scenarios and direct testing.
+
+- Risk: the app router currently handles deserialization failures with a
+  counter and threshold (`MAX_DESER_FAILURES`). Moving decode into a separate
+  loop task may complicate shared mutable state. Severity: low. Likelihood:
</code_context>

<issue_to_address>
**nitpick (typo):** Use en-GB spelling for “deserialisation” for consistency.

Since we’re standardising on en-GB-oxendict, please change “deserialization failures” to “deserialisation failures” to match nearby terms like “serialisation” and “behavioural”.

```suggestion
- Risk: the app router currently handles deserialisation failures with a
```
</issue_to_address>

### Comment 4
<location> `docs/asynchronous-outbound-messaging-design.md:840` </location>
<code_context>
+- **Unified Codec Pipeline:** On the server side, the `FramePipeline`
+  (`src/app/codec_driver.rs`) applies outbound fragmentation and metrics to
+  every `Envelope` before it reaches the wire. Handler responses pass through
+  the pipeline before serialisation and codec wrapping, ensuring the same
+  fragmentation logic applies to both handler responses and push traffic.
+  Protocol hooks are applied at the connection-actor level and are currently
</code_context>

<issue_to_address>
**suggestion (review_instructions):** "serialisation" should use an -ize form under en-GB-oxendict conventions ("serialization").

The style guide specifies en-GB-oxendict spelling, which uses -ize forms. Please change "serialisation" here to "serialization".

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Use en-GB-oxendic (-ize / -yse / -our) spelling and grammar.

</details>
</issue_to_address>

### Comment 5
<location> `docs/users-guide.md:877` </location>
<code_context>

+On the server side, a unified `FramePipeline` applies the same fragmentation
+logic to all outbound `Envelope` values — handler responses, streaming frames,
+and multi-packet channels — before serialisation and codec wrapping. This
+guarantees that a single connection-scoped `FragmentationState` manages both
+outbound fragmentation and inbound reassembly.
</code_context>

<issue_to_address>
**suggestion (review_instructions):** "serialisation" should be written with -ize spelling ("serialization") to match en-GB-oxendict.

To align with the en-GB-oxendict style (-ize / -yse / -our), please update "serialisation" to "serialization" here.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Use en-GB-oxendic (-ize / -yse / -our) spelling and grammar.

</details>
</issue_to_address>

### Comment 6
<location> `docs/execplans/9-3-1-fragment-adapter-trait.md:162` </location>
<code_context>
+  `tests/unified_codec.rs`. Five tests: round-trip, fragmented response,
+  unfragmented small payload, multiple sequential requests, disabled
+  fragmentation. Committed in `1b2851a`.
+- [x] (2026-02-15 03:00Z) Stage F: BDD behavioural tests added. Five
+  rstest-bdd scenarios in `tests/features/unified_codec.feature` with fixture
+  `tests/fixtures/unified_codec/` and steps
</code_context>

<issue_to_address>
**suggestion (review_instructions):** "BDD" is introduced without being expanded on first use.

The instructions ask for uncommon acronyms to be defined on first use. Please expand this to something like "Behaviour-Driven Development (BDD) behavioural tests" here, or add an explicit definition immediately before this bullet.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Define uncommon acronyms on first use.

</details>
</issue_to_address>

### Comment 7
<location> `docs/execplans/9-3-1-fragment-adapter-trait.md:586` </location>
<code_context>
+The exact integration point (pre-wrapped frames vs. `Envelope` values) will be
+decided in Stage A and recorded in the decision log.
+
+### Fragmentation reconciliation
+
+Today path 1 fragments at the `Envelope` level (before serialisation) and path
</code_context>

<issue_to_address>
**suggestion (review_instructions):** Within this section, "serialiser" should be "serializer" to follow the -ize/-izer convention.

In the sentence "The design documents specify outbound order as \"serialiser → fragmentation → codec framing\"", "serialiser" should be updated to "serializer" to follow en-GB-oxendict (-ize/-izer) spelling.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Use en-GB-oxendic (-ize / -yse / -our) spelling and grammar.

</details>
</issue_to_address>

### Comment 8
<location> `docs/execplans/9-3-1-fragment-adapter-trait.md:421` </location>
<code_context>
+1. Construct the codec-aware driver from Stage B.
+2. Split the connection loop into an inbound decode task and an outbound
+   actor/writer task communicating via an internal bounded channel.
+3. When a handler returns `Response::Single(bytes)` or `Response::Vec(v)`,
+   send the serialised, wrapped frames through the actor's input channel so
+   hooks and fragmentation apply.
</code_context>

<issue_to_address>
**suggestion (review_instructions):** Later in this list item, "serialised" should be "serialized" to match en-GB-oxendict spelling.

This bullet refers to "the serialised, wrapped frames". To comply with the en-GB-oxendict (-ize) guidance, please change "serialised" to "serialized".

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Use en-GB-oxendic (-ize / -yse / -our) spelling and grammar.

</details>
</issue_to_address>

@coderabbitai

This comment was marked as resolved.

… return Results

Refactored `first_frame_payload` and `continuation_frame_payload` functions to return `Result<Vec<u8>, io::Error>` instead of unconditionally returning the payload vector. Added error handling for body length exceeding `u32::MAX`. Updated call sites in tests and related code to handle the Result with `.expect("valid test payload")` or propagating the error as appropriate. This improves robustness by explicitly handling potential payload construction failures.

Also includes minor documentation and style tweaks unrelated to the core fix.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Feb 19, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 19, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/execplans/9-3-1-fragment-adapter-trait.md`:
- Around line 161-164: The documentation uses the British -ise spelling
"initialisation" in the text; update it to the en-GB-oxendict -ize form
"initialization" in this file (docs/execplans/9-3-1-fragment-adapter-trait.md)
and scan nearby prose for other -ise/-yse/-our variants (e.g., initialise,
emphasise, colour) and replace them with their -ize/-yze/-our forms per the
styleguide to ensure consistent en-GB-oxendict spelling.

In `@tests/steps/unified_codec_steps.rs`:
- Around line 13-19: The helper runtime() currently panics on Runtime::new()
failure; change it to return a TestResult (propagating errors) instead of
panicking and use a fallible OnceLock/OnceCell initializer (e.g.,
get_or_try_init) so initialization errors are returned; update all call sites of
runtime() to handle the Result via the ? operator rather than
unwrapping/panicking. Ensure you reference the runtime() function, the static
OnceLock/OnceCell, and Runtime::new() when making these changes so callers
return/propagate TestResult errors.

Comment thread docs/execplans/9-3-1-fragment-adapter-trait.md
Comment thread tests/steps/unified_codec_steps.rs Outdated
…ation

Changed runtime() to return a Result to handle potential initialization errors.
Updated callers to propagate these errors properly instead of panicking.
This improves error handling and robustness in the unified_codec_steps test code.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
@leynos leynos merged commit ce1ff12 into main Feb 19, 2026
6 checks passed
@leynos leynos deleted the unify-codec-handling-9-3-1-mn7az7 branch February 19, 2026 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant