From 7b37e4d61d94322d89f5957687da96e2b7398532 Mon Sep 17 00:00:00 2001 From: leynos Date: Mon, 22 Jun 2026 18:55:40 +0200 Subject: [PATCH 01/12] Add execplan for actor/codec-driver boundary approval (10.1.3) Draft the decision-closure ExecPlan for roadmap item 10.1.3, which approves ADR 010 by resolving its three Outstanding Decisions: protocol hooks stay packet-oriented (app-router before_send gap tracked to 11.2.1), no public Vec compatibility shim is added (CorrelatableFrame for Vec leaves the core surface under the breaking release in 11.2.2), and no new "serializable packet" trait is introduced (Packet + EncodeWith suffices, corroborated by tonic and tokio_util prior art). The plan is documentation-only; runtime work is deferred to phase 11. It records a Logisphere "proceed with conditions" review and the sibling-item delivery pattern from 10.1.1/10.1.2. Co-Authored-By: Claude Opus 4.8 (1M context) --- ...approve-actor-and-codec-driver-boundary.md | 542 ++++++++++++++++++ 1 file changed, 542 insertions(+) create mode 100644 docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md diff --git a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md new file mode 100644 index 00000000..97a67da6 --- /dev/null +++ b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md @@ -0,0 +1,542 @@ +# Approve the actor and codec-driver boundary (10.1.3) + +This ExecPlan (execution plan) is a living document. The sections +`Constraints`, `Tolerances`, `Risks`, `Progress`, `Surprises & Discoveries`, +`Decision Log`, and `Outcomes & Retrospective` must be kept up to date as work +proceeds. + +Status: DRAFT + +## Purpose / big picture + +Roadmap item `10.1.3` is a *decision-closure* item, not a code change. Its job +is to move +[ADR 010: transport-frame boundary for zero-copy](../adr-010-transport-frame-boundary-for-zero-copy.md) +from `Proposed` to `Accepted` by resolving its three Outstanding Decisions, so +that the later runtime work in roadmap phase 11 has an approved, written +boundary to build against. After this item lands, the project has a single +agreed answer to "who owns transport-frame emission, where do protocol hooks +run, and which `Vec` bridges survive", and the migration can stop keeping +`Vec` bridges alive merely because the architecture was underspecified. + +A reader can observe success in three ways once the plan is executed: + +1. `docs/adr-010-transport-frame-boundary-for-zero-copy.md` reads `Accepted`, + carries dual `Proposed`/`Accepted` dates, and its former "Outstanding + Decisions" are each resolved in place with a link to the roadmap item that + implements them. +2. `docs/roadmap.md` item `10.1.3` and + `docs/zero-copy-frame-and-payload-migration-roadmap.md` item `1.1.3` (with + its child bullets) are checked `[x]`. +3. `make check-fmt`, `make lint`, `make test`, and `make markdownlint` all pass + on a clean tree, and a `coderabbit review --agent` pass raises no + outstanding concerns. + +This item changes **no Rust code and no public API**. It is a documentation and +decision artefact. The runtime changes it sanctions are deliberately deferred to +roadmap phase 11 (items `11.1.2`, `11.2.1`, `11.2.2`, `11.2.3`) and the release +review in `14.2.1`. + +## The decision being approved (summary) + +The plan approves ADR 010's **Option B**: the connection actor stays +packet-oriented, and the codec driver becomes the sole owner of transport-frame +emission. Concretely, the three Outstanding Decisions in ADR 010 are resolved as +follows. Each is justified in the `Decision Log` and `Context and orientation` +sections below. + +1. **Where protocol hooks run.** Protocol hooks stay **packet-oriented** and + continue to execute against `Envelope` (a `Packet`) inside the connection + actor, before serialization. The codec driver hosts serialization and + transport framing only; it introduces no new transport-frame-level hook. The + current asymmetry — `before_send` fires for actor-driven push and + multi-packet frames but not yet for app-router responses routed through + `FramePipeline` — is documented as a known limitation and tracked for closure + under roadmap `11.2.1`. +2. **Where the `Vec` bridges live.** No public, feature-gated `Vec` + compatibility shim is introduced at the actor boundary. `Packet for Vec` + stays test-only in `src/connection/test_support.rs`. The public + `impl CorrelatableFrame for Vec` is sanctioned to **leave the core + runtime surface** and move to test support; because it is a public impl, its + removal is a breaking change and is sequenced with the epic-284 breaking + release under roadmap `11.2.2` and reviewed in `14.2.1`. +3. **Whether a new "serializable packet" trait is needed.** **No new trait.** + The existing `Packet` trait composed with `EncodeWith` already + expresses "a packet that can be serialized"; `Envelope` satisfies both. + Adding a bridging trait is ADR 010's rejected Option C and is corroborated as + unnecessary by prior art (see `Artifacts and notes`). + +## Constraints + +Hard invariants that must hold throughout implementation. Violation requires +escalation, not a workaround. + +1. **No code or public API change in this item.** `10.1.3` edits documentation + only. Do not modify any file under `src/`, `crates/`, `tests/`, `examples/`, + or `wireframe_testing/`. Runtime changes belong to phase 11. +2. **ADRs are append-only decisions, not rewrites of history.** ADR 010 must be + moved to `Accepted` by *resolving* its Outstanding Decisions and expanding + the Decision Outcome, mirroring how ADR 008 and ADR 009 were accepted. Do not + delete the record of the options considered or the rationale. +3. **The accepted boundary must match the code as it exists today.** The + production outbound path already routes every frame through the codec driver, + with exactly one production `FrameCodec::wrap_payload` call site at + `src/app/outbound_encoding.rs:36`. The ADR text must not claim a boundary the + code does not yet have; where the boundary is aspirational (for example, + `before_send` for app-router responses), it must be labelled as deferred and + linked to its roadmap item. +4. **British English, Oxford spelling.** Follow the documentation style guide: + en-GB with Oxford spelling, the Oxford comma where it improves clarity, ATX + headings, two blank lines after each heading in this ExecPlan, and ordered + lists written `1.`, `2.`, and so on. +5. **Cross-references stay consistent.** Every document that states ADR 010's + status (`roadmap.md`, the zero-copy migration roadmap, the inventory, + `contents.md`) must agree that it is accepted once the change lands. + +## Tolerances (exception triggers) + +1. **Scope.** If executing the plan appears to require editing any non-documentation + file, stop and escalate. This item is documentation-only by definition. +2. **Decision drift.** If, while writing the accepted ADR, any of the three + resolved decisions appears wrong against the actual code (for example, a + second production `wrap_payload` caller is discovered, or `before_send` turns + out to already fire for app-router responses), stop and escalate rather than + quietly changing the decision. +3. **Ambiguity.** If the user's intent for a decision differs from the + resolution recorded here and the difference is material to phase 11, stop and + present the options with trade-offs. +4. **Document growth.** If the ADR rewrite exceeds roughly double its current + length, stop and reconsider — an accepted decision record should be + sharper, not longer. +5. **Gate failures.** If `make markdownlint`, `make check-fmt`, `make lint`, or + `make test` fail after the documentation edits and the cause is not an + obvious local formatting fix, stop and escalate. + +## Risks + +1. Risk: The accepted ADR overstates the boundary, claiming the codec driver is + the sole framing owner when a non-driver `wrap_payload` caller still exists. + Severity: medium. Likelihood: low. + Mitigation: the inventory of `wrap_payload` call sites was taken during + planning (one production caller, `src/app/outbound_encoding.rs:36`; all + others are tests, examples, or testkit). The ADR records this list and the + plan adds a requirement (executed in phase 11) for a guard test that fails if + a new non-driver production caller appears. +2. Risk: Removing the public `impl CorrelatableFrame for Vec` is treated as + a free internal change and slips into a non-breaking release. + Severity: medium. Likelihood: medium. + Mitigation: the ADR and decision log mark the removal as breaking and bind it + to the epic-284 breaking release via roadmap `11.2.2` and the review in + `14.2.1`, governed by the ADR 009 rollout policy. +3. Risk: The documented `before_send` asymmetry confuses a downstream protocol + author whose hook fires for push frames but not for routed responses. + Severity: low. Likelihood: medium. + Mitigation: the asymmetry is stated explicitly in ADR 010 and the developers' + guide, with a tracked closure item (`11.2.1`). +4. Risk: Cross-reference drift — one document still calls ADR 010 "proposed". + Severity: low. Likelihood: medium. + Mitigation: the concrete steps enumerate every file that names the ADR + status, and validation greps for stale "proposed" references to ADR 010. + +## Progress + +- [ ] (pending) Stage A: research and propose — gather code, prior art, and the + sibling-item delivery pattern; draft the resolved decisions. (completed during + planning; see `Context and orientation` and `Artifacts and notes`.) +- [ ] Stage B: author the accepted ADR 010 rewrite (status, dates, Decision + Outcome expansion, resolved Outstanding Decisions, tracked call-site note). +- [ ] Stage C: propagate the acceptance across `roadmap.md`, the zero-copy + migration roadmap, the inventory, `contents.md`, and `developers-guide.md`. +- [ ] Stage D: run documentation and commit gates, then a `coderabbit + review --agent` pass; clear all concerns. +- [ ] Mark roadmap `10.1.3` done and finalise this ExecPlan to `COMPLETE`. + +Each stage is gated by `make markdownlint` (and `make nixie` if a diagram is +touched) before commit. Stages B and C are committed separately so the decision +edit and its propagation can be reviewed independently. + +## Surprises & discoveries + +- Observation: The "sole owner" goal of ADR 010 is already substantially met in + code on the outbound path. + Evidence: `rg -n "\.wrap_payload\(" src/` shows exactly one non-test + production caller, `src/app/outbound_encoding.rs:36` + (`codec.wrap_payload(Bytes::from(bytes))`); all other matches are under + `*/tests.rs`, `src/codec/examples.rs`, `src/test_helpers/`, or + `src/testkit/`. + Impact: `10.1.3` is genuinely a decision-closure item. The remaining work is + to write the boundary down precisely and dispose of the test-only bridges, not + to relocate production framing logic. +- Observation: The final outbound copy is a single, already-annotated bridge. + Evidence: `src/app/outbound_encoding.rs` carries a comment citing + `https://github.com/leynos/wireframe/issues/538`, noting the + `Bytes::from(bytes)` conversion is behaviour-preserving until the serializer + contract becomes `Bytes`-native. + Impact: ADR 010 should point its "remove the final copy" consequence at + roadmap `11.1.2` / issue #538 rather than implying `10.1.3` removes it. + +## Decision log + +- Decision: Resolve ADR 010 Outstanding Decision (A) by keeping protocol hooks + packet-oriented and documenting the app-router `before_send` gap as a tracked + limitation. + Rationale: `before_send` currently runs in `ConnectionActor::push_frame` + (`src/connection/frame.rs`) against `F: Packet` (production `Envelope`), where + it has access to packet identity and correlation. Moving hooks to the + transport-frame layer would force them to operate on `F::Frame` (for example + `Bytes`), discarding the packet semantics they rely on. The genuine gap — that + `FramePipeline` does not yet fire `before_send` for app-router responses + because `F::Frame` and `Envelope` can differ (deferred in roadmap `9.3.1`) — + is best closed by unifying the response path onto the actor's `Envelope` hook + stage under `11.2.1`, not by relocating hooks downward. + Date/Author: 2026-06-22, planning agent (with Logisphere panel input). + +- Decision: Resolve ADR 010 Outstanding Decision (B) with no public + feature-gated compatibility shim; keep `Packet for Vec` in test support and + sanction the public `CorrelatableFrame for Vec` impl to leave the core + surface under the breaking release. + Rationale: `Packet for Vec` is already test-only + (`src/connection/test_support.rs`) and provides actor-test value, matching ADR + 010's non-goal of removing test helpers prematurely. + `impl CorrelatableFrame for Vec` lives in production module + `src/correlation.rs` but has no production caller; ADR 009 already routes + runtime bridges to ADR 010 and removes middleware `&mut Vec` editors. + Because the impl is public, Telefono (contracts lens) flagged its removal as + a breaking change, so it is bound to `11.2.2` / `14.2.1` rather than treated + as a free internal cleanup. + Date/Author: 2026-06-22, planning agent (with Logisphere panel input). + +- Decision: Resolve ADR 010 Outstanding Decision (C) as "no new trait". + Rationale: `Packet` (`id`, `into_parts`, `from_parts`) plus + `EncodeWith` already composes "serializable packet", satisfied by + `Envelope`. A bridging trait is ADR 010's rejected Option C and adds a wrapper + layer without removing copies. Prior art corroborates: tonic reuses the message + type plus an `Encoder` rather than a bespoke packet trait, and keeps gRPC + length-framing in a separate buffer layer (see `Artifacts and notes`). + Date/Author: 2026-06-22, planning agent (with Logisphere panel input). + +- Decision: Record the canonical production `wrap_payload` call site in the ADR + and require a guard against new non-driver callers (implemented in phase 11). + Rationale: ADR 010's "Known Risks" already asks for a tracked list of + non-driver callers. Buzzy Bee (scaling lens) and Doggylump (ops lens) noted a + manual list rots; a grep-style guard test keeps the "sole owner" guarantee + enforceable. The requirement is recorded now; the test is added with the + runtime work (`11.2.3`). + Date/Author: 2026-06-22, planning agent (with Logisphere panel input). + +- Decision: Deliver `10.1.3` as documentation only, mirroring `10.1.1` and + `10.1.2`. + Rationale: those sibling approval items each flipped an ADR to `Accepted`, + expanded its Decision Outcome, ticked the roadmaps, aligned the inventory, and + added a developers'-guide note, with no runtime change. Consistency keeps the + decision-closure phase reviewable and reversible. + Date/Author: 2026-06-22, planning agent. + +## Outcomes & retrospective + +To be completed when the plan is executed. Compare the accepted ADR against this +plan's purpose: a single written boundary that lets phase 11 remove `Vec` +bridges deliberately. Note any divergence between the resolved decisions and what +phase 11 ultimately implements. + +## Context and orientation + +This section assumes no prior knowledge of the repository. + +### Where the boundary lives in code + +- **The connection actor.** `src/connection/mod.rs` defines + `ConnectionActor` with the bound + `F: FrameLike + CorrelatableFrame + Packet`. In production the server + instantiates the actor with `F = Envelope`; the generic parameter exists so + protocol-native packet types remain possible. `FrameLike` is a + `Send + 'static` marker; `CorrelatableFrame` (`src/correlation.rs`) supplies + `correlation_id`/`set_correlation_id`; `Packet` (`src/app/envelope.rs`) + supplies `id`, `into_parts`, `from_parts`. The actor never emits transport + frames directly. +- **The codec driver.** `src/app/codec_driver.rs` owns `FramePipeline` + (fragmentation and metrics over `Envelope`) and `send_envelope`. + `src/app/outbound_encoding.rs::encode_message_frame` performs the + `packet -> bytes -> transport frame` transition: it calls + `Serializer::serialize` (returning `Vec`), bridges with `Bytes::from`, and + calls `FrameCodec::wrap_payload` — the single production framing site. +- **Production connection wiring.** `src/server/connection_spawner.rs` reads the + preamble, wraps the stream in `RewindStream`, then calls + `app.handle_connection_result`. The app path drives responses through the + codec driver. The actor's hook stage is `ConnectionActor::push_frame` + (`src/connection/frame.rs`), which calls `self.hooks.before_send(&mut frame, + ..)` before buffering each outbound frame. +- **The `Vec` bridges.** `src/correlation.rs` implements + `CorrelatableFrame` for `u8`, `Vec`, and (in `src/app/envelope.rs`) + `Envelope`. The `Vec` impl is a no-op correlation carrier with no + production caller. `src/connection/test_support.rs` implements `Packet` for + `Vec` (and `u8`) for actor unit tests. +- **The serializer.** `src/serializer.rs` defines + `Serializer::serialize(&self, &M) -> Result, _>`; + `BincodeSerializer` preserves that return type. Issue #538 tracks moving this + to a `Bytes`-native container, which is what removes the final outbound copy + under roadmap `11.1.2`. + +### The governing documents + +- [`docs/adr-010-transport-frame-boundary-for-zero-copy.md`](../adr-010-transport-frame-boundary-for-zero-copy.md) + — the decision to accept; currently `Proposed`. +- [`docs/frame-vec-u8-inventory.md`](../frame-vec-u8-inventory.md) — the source + inventory; its "Resolved direction for epic 284" and ADR list reference ADR + 010. +- [`docs/zero-copy-frame-and-payload-migration-roadmap.md`](../zero-copy-frame-and-payload-migration-roadmap.md) + — item `1.1.3` mirrors roadmap `10.1.3`. +- [`docs/roadmap.md`](../roadmap.md) — item `10.1.3` and the phase-11 items that + consume the decision. +- [`docs/developers-guide.md`](../developers-guide.md) — has a "Public + byte-container model" section (added by `10.1.1`/`10.1.2`) to extend with the + boundary note. +- [`docs/contents.md`](../contents.md) — indexes ADRs and execution plans. + +### The sibling-item delivery pattern + +Items `10.1.1` (ADR 008, commit `cd153de`) and `10.1.2` (ADR 009, commit +`3969c3b`) set the template this plan follows. Each: + +1. flipped the ADR `Status` from `Proposed` to `Accepted`, with the date field + becoming `Proposed . Accepted .` and a prose acceptance statement + in the Status section; +2. renamed `## Decision Outcome / Proposed Direction` to `## Decision Outcome` + and changed "The proposed direction is:" to "The accepted direction is:"; +3. expanded the outcome with concrete, named commitments and links to the + roadmap items that implement deferred parts; +4. ticked the matching checkboxes in `roadmap.md` and the zero-copy migration + roadmap; +5. aligned `frame-vec-u8-inventory.md` and added a `developers-guide.md` note; +6. added the execplan and a `contents.md` index line. + +## Plan of work + +### Stage A: research and propose (no edits) — done during planning + +Completed. Findings are captured in `Context and orientation`, `Surprises & +discoveries`, and `Artifacts and notes`. The three Outstanding Decisions are +resolved in `Decision log`. The Logisphere panel returned "Proceed with +conditions"; the conditions are folded into the constraints and the ADR rewrite +below. + +### Stage B: author the accepted ADR 010 + +Edit `docs/adr-010-transport-frame-boundary-for-zero-copy.md` only: + +1. **Status.** Change `Proposed` to `Accepted` and add an acceptance paragraph + in the form used by ADR 008/009: "Accepted on 2026-06-22. Wireframe keeps the + connection actor packet-oriented and makes the codec driver the sole owner of + transport-frame emission …", naming the three resolved decisions in one + sentence each and linking roadmap items `11.1.2`, `11.2.1`, `11.2.2`, + `11.2.3`, and `14.2.1`. +2. **Date.** Change `2026-04-12` to `Proposed 2026-04-12. Accepted 2026-06-22.` +3. **Decision Outcome.** Rename the heading to `## Decision Outcome`, change the + lead-in to "The accepted direction is:", and keep the four existing bullets, + making each a firm commitment rather than a proposal. +4. **Resolve Outstanding Decisions.** Replace the `## Outstanding Decisions` + section with `## Resolved Decisions`, recording the three resolutions from + this plan's `Decision log`, each linking to its implementing roadmap item. + Keep the question text so the record shows what was asked and answered. +5. **Tracked call-site note.** In `## Known Risks and Limitations` (or a short + `## Tracked transport-frame call sites` subsection), record that the sole + production `wrap_payload` caller today is `src/app/outbound_encoding.rs`, that + all other callers are tests/examples/testkit, and that a guard against new + non-driver production callers is required and tracked under `11.2.3`. +6. **Goals/Non-Goals.** Adjust tense so the decision-closure goals read as + achieved, leaving the runtime goals pointing at phase 11. + +Validate with `make markdownlint` and commit Stage B on its own. + +### Stage C: propagate the acceptance + +1. `docs/roadmap.md`: tick item `10.1.3` `[ ]` to `[x]`. +2. `docs/zero-copy-frame-and-payload-migration-roadmap.md`: tick item `1.1.3` + and its three child bullets `[x]`. +3. `docs/frame-vec-u8-inventory.md`: update the "Resolved direction for epic + 284" / ADR list entry so ADR 010 reads `(accepted)` with acceptance-tense + wording, matching how ADR 008/009 are described there. +4. `docs/developers-guide.md`: add a short "Actor and codec-driver boundary" + subsection after "Public byte-container model", stating that the actor stays + packet-oriented, the codec driver owns transport-frame emission, protocol + hooks run at the packet stage, and the app-router `before_send` gap is tracked + under `11.2.1`; cross-reference ADR 010. +5. `docs/contents.md`: update the ADR 010 line to acceptance wording and add an + "Execution plans" index line for this plan. + +Validate with `make markdownlint` and commit Stage C on its own. + +### Stage D: gates and review + +Run the full commit gateway and a CodeRabbit pass; clear every concern before +finalising. Then tick this plan's `Progress` items, set `Status: COMPLETE`, and +complete `Outcomes & retrospective`. + +## Concrete steps + +Run all commands from the repository root +(`/home/leynos/.lody/repos/github---leynos---wireframe/worktrees/9f3f8a4e-aca9-4624-b9c5-92de91c9e0bf`). + +1. Confirm the call-site inventory still holds before writing the ADR claim: + + ```bash + rg -n "\.wrap_payload\(" src/ | grep -v -i test + ``` + + Expected: a single line, `src/app/outbound_encoding.rs:36: ... codec.wrap_payload(Bytes::from(bytes));`. + +2. Apply Stage B edits, then: + + ```bash + make markdownlint 2>&1 | tee /tmp/markdownlint-wireframe-10-1-3.out + git add docs/adr-010-transport-frame-boundary-for-zero-copy.md + ``` + + Commit with a message recording acceptance of ADR 010 and resolution of its + Outstanding Decisions. + +3. Apply Stage C edits, then re-run `make markdownlint`, confirm no document + still calls ADR 010 proposed: + + ```bash + rg -ni "adr.?010|transport.frame boundary" docs/ | rg -i "propos" + ``` + + Expected: no output (every reference now reads accepted). Stage and commit the + propagation edits. + +4. Run the commit gateway (documentation-only change, but the full suite must + stay green): + + ```bash + make check-fmt 2>&1 | tee /tmp/check-fmt-wireframe-10-1-3.out + make lint 2>&1 | tee /tmp/lint-wireframe-10-1-3.out + make test 2>&1 | tee /tmp/test-wireframe-10-1-3.out + ``` + + Run sequentially (the environment caches builds; do not parallelise). + +5. Request review: + + ```bash + coderabbit review --agent 2>&1 | tee /tmp/coderabbit-wireframe-10-1-3.out + ``` + + Resolve every concern, re-running the relevant gate, before finalising. + +## Validation and acceptance + +Because this item changes only documentation, there is no Red-Green-Refactor +code cycle; the nearest observable substitutes are the documentation gates and +the cross-reference checks below (recorded under the execplans guidance for when +test-first delivery is genuinely unavailable). + +Acceptance is behaviour a reviewer can verify: + +1. Opening `docs/adr-010-transport-frame-boundary-for-zero-copy.md` shows + `Status: Accepted`, dual dates, a `## Decision Outcome` heading, and a + `## Resolved Decisions` section answering all three former Outstanding + Decisions, each linking a phase-11 roadmap item. +2. `docs/roadmap.md` line for `10.1.3` and the zero-copy migration roadmap line + for `1.1.3` (and children) render checked. +3. `rg -ni "adr.?010" docs/ | rg -i "propos"` returns nothing. +4. `make markdownlint`, `make check-fmt`, `make lint`, and `make test` each exit + 0; their `tee` logs in `/tmp` show success. +5. `coderabbit review --agent` reports no unresolved concerns. + +Quality criteria ("done"): + +- Tests: `make test` passes unchanged (no new or altered tests; documentation + only). +- Lint/format: `make lint`, `make check-fmt`, and `make markdownlint` pass. +- Documentation: all five governing documents agree ADR 010 is accepted; the + developers' guide records the boundary and the tracked `before_send` gap. + +Quality method: the commands in `Concrete steps`, then CodeRabbit. + +## Idempotence and recovery + +Every step is a documentation edit and is safe to re-run; re-running +`make markdownlint` or the grep checks has no side effects. If a stage commit is +wrong, `git revert` it — there is no runtime state to roll back. If the +call-site inventory in step 1 returns more than one production caller, that +breaches Tolerance 2: stop and escalate rather than weakening the ADR's "sole +owner" claim. + +## Artifacts and notes + +### Prior art (firecrawl research) + +The "no new trait" resolution of Outstanding Decision (C) is corroborated by two +mature Rust networking ecosystems that separate message/packet semantics from +transport framing: + +- **tonic** (`tonic::codec`) defines a `Codec` that yields an `Encoder` and + `Decoder` over *message types*, while gRPC length-framing is handled by a + separate buffer layer (`EncodeBuf`/`DecodeBuf` over `bytes::Bytes`). The + decoder receives "exactly the bytes of a full message"; framing is not the + message trait's concern. tonic introduces no bespoke "serializable packet" + trait — it reuses the message type plus an encoder. + Source: . +- **tokio_util::codec** parameterises `Encoder`/`Decoder` on the item + type and owns framing in `Framed`, keeping the *item* distinct from the byte + buffer. The tonic maintainers note the two trait families differ mainly in + tokio-util's `Encoder` taking the item as a type parameter. + Source: . + +Both build the byte plane on `bytes::Bytes`, matching ADR 008's accepted public +byte container and reinforcing Option B: keep packet semantics in `Packet` + +`EncodeWith`, and keep transport framing in the codec driver. + +### Logisphere design review (conditions folded in) + +Verdict: ⚠️ Proceed with conditions. Conditions, each addressed above: + +- ☎️ Telefono: removing public `CorrelatableFrame for Vec` is breaking — + sequence with the epic-284 breaking release (`11.2.2`/`14.2.1`); `10.1.3` + changes no public API. (Constraint 1; Risk 2; Decision (B).) +- 🐶 Doggylump: document the `before_send` asymmetry, do not hide it; track to + `11.2.1`. (Decision (A); Risk 3; Stage C step 4.) +- 🐝 Buzzy Bee: guard the "sole owner" guarantee with a check against new + non-driver `wrap_payload` callers; record now, implement in `11.2.3`. + (Decision; ADR tracked-call-site note.) +- 🐼 Pandalump: state the actor stays generic over `Packet` while `Vec` + ceases to be a sanctioned frame type. (Context; ADR Decision Outcome.) +- 🐈🧇 Wafflecat: the strongest alternative — move hooks to the transport-frame + layer — is rejected because it strips the packet semantics hooks rely on. + (Decision (A).) + +## Interfaces and dependencies + +This item defines no new Rust interfaces. It records the boundary the phase-11 +runtime work must honour. The interfaces named below already exist and must +remain stable through `10.1.3`: + +- `crate::connection::ConnectionActor` with + `F: FrameLike + CorrelatableFrame + Packet` (`src/connection/mod.rs`) — stays + packet-oriented; `Envelope` in production. +- `crate::app::outbound_encoding::encode_message_frame` and + `crate::app::codec_driver` (`FramePipeline`, `send_envelope`) — the sole + owner of `packet -> bytes -> transport frame`. +- `crate::codec::FrameCodec::wrap_payload` — the canonical transport-frame + emission point; production callers must stay confined to the codec driver. +- `crate::serializer::Serializer::serialize` — remains `Vec`-returning until + issue #538 / roadmap `11.1.2`. +- `crate::correlation::CorrelatableFrame` and `crate::app::Packet` — the + composition that expresses "serializable packet"; no new trait is added. + +Downstream roadmap items that depend on this decision: `11.1.2` (remove the +final outbound copy), `11.2.1` (implement the boundary and close the +`before_send` gap), `11.2.2` (move `CorrelatableFrame for Vec` out of +production), `11.2.3` (allocation and pointer-reuse regressions plus the +non-driver-caller guard), and `14.2.1` (review retained bridges after the +breaking release). + +## Revision note + +Initial draft (2026-06-22): created the decision-closure plan for roadmap +`10.1.3`. Resolved ADR 010's three Outstanding Decisions, captured the +sibling-item delivery pattern from `10.1.1`/`10.1.2`, recorded prior-art +corroboration (tonic, tokio_util) and a Logisphere "proceed with conditions" +review, and scoped the work to documentation only with implementation deferred +to roadmap phase 11. Status: DRAFT, awaiting approval before execution. From 7e98339b182b1207a61b66673657501b1a58231b Mon Sep 17 00:00:00 2001 From: leynos Date: Wed, 24 Jun 2026 20:08:47 +0200 Subject: [PATCH 02/12] Start actor boundary plan execution Mark the approved execplan as in progress and record the preflight findings used before editing ADR 010. --- ...approve-actor-and-codec-driver-boundary.md | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md index 97a67da6..370e45d7 100644 --- a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md +++ b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md @@ -5,7 +5,7 @@ This ExecPlan (execution plan) is a living document. The sections `Decision Log`, and `Outcomes & Retrospective` must be kept up to date as work proceeds. -Status: DRAFT +Status: IN PROGRESS ## Purpose / big picture @@ -140,10 +140,11 @@ escalation, not a workaround. ## Progress -- [ ] (pending) Stage A: research and propose — gather code, prior art, and the +- [x] (2026-06-24) Stage A: research and propose — gather code, prior art, and the sibling-item delivery pattern; draft the resolved decisions. (completed during planning; see `Context and orientation` and `Artifacts and notes`.) -- [ ] Stage B: author the accepted ADR 010 rewrite (status, dates, Decision +- [ ] (2026-06-24, in progress) Stage B: author the accepted ADR 010 rewrite + (status, dates, Decision Outcome expansion, resolved Outstanding Decisions, tracked call-site note). - [ ] Stage C: propagate the acceptance across `roadmap.md`, the zero-copy migration roadmap, the inventory, `contents.md`, and `developers-guide.md`. @@ -174,6 +175,22 @@ edit and its propagation can be reviewed independently. contract becomes `Bytes`-native. Impact: ADR 010 should point its "remove the final copy" consequence at roadmap `11.1.2` / issue #538 rather than implying `10.1.3` removes it. +- Observation: The plan's preflight call-site inventory still holds at + execution time. + Evidence: on 2026-06-24, + `rg -n "\.wrap_payload\(" src/ | grep -v -i test` returned only + `src/app/outbound_encoding.rs:36: let frame = + codec.wrap_payload(Bytes::from(bytes));`. + Impact: the ADR can safely state the codec driver is the only production + transport-frame emission site today, while deferring enforcement coverage to + roadmap `11.2.3`. +- Observation: `AGENTS.md` asks readers to start with + `docs/repository-layout.md`, but that file is absent in this worktree. + Evidence: `sed -n '1,220p' docs/repository-layout.md` failed with + `No such file or directory`. + Impact: execution used `docs/contents.md`, the documentation style guide, and + the governing ADR, roadmap, inventory, and developers' guide files listed in + this plan instead. ## Decision log @@ -232,6 +249,14 @@ edit and its propagation can be reviewed independently. decision-closure phase reviewable and reversible. Date/Author: 2026-06-22, planning agent. +- Decision: Begin execution from explicit user approval on 2026-06-24 while + leaving the scope documentation-only. + Rationale: the user asked to proceed with implementation of this plan. The + branch already tracks `origin/10-1-3-approve-actor-and-codec-driver-boundary`, + and the preflight inventory confirmed no decision-drift tolerance has been + breached. + Date/Author: 2026-06-24, implementation agent. + ## Outcomes & retrospective To be completed when the plan is executed. Compare the accepted ADR against this @@ -540,3 +565,8 @@ sibling-item delivery pattern from `10.1.1`/`10.1.2`, recorded prior-art corroboration (tonic, tokio_util) and a Logisphere "proceed with conditions" review, and scoped the work to documentation only with implementation deferred to roadmap phase 11. Status: DRAFT, awaiting approval before execution. + +Execution update (2026-06-24): user approval received, branch tracking confirmed +against `origin/10-1-3-approve-actor-and-codec-driver-boundary`, preflight +call-site inventory rechecked, and status moved to IN PROGRESS before Stage B +ADR edits. From 1ab5302f04fe1c4755414eb053e4696dcbb1ae9d Mon Sep 17 00:00:00 2001 From: leynos Date: Wed, 24 Jun 2026 20:09:50 +0200 Subject: [PATCH 03/12] Accept actor codec boundary ADR Move ADR 010 to Accepted and resolve its protocol hook, Vec bridge, and serializable packet trait decisions. --- ...-transport-frame-boundary-for-zero-copy.md | 114 +++++++++++++----- 1 file changed, 84 insertions(+), 30 deletions(-) diff --git a/docs/adr-010-transport-frame-boundary-for-zero-copy.md b/docs/adr-010-transport-frame-boundary-for-zero-copy.md index 83e9caf1..70e3d0fb 100644 --- a/docs/adr-010-transport-frame-boundary-for-zero-copy.md +++ b/docs/adr-010-transport-frame-boundary-for-zero-copy.md @@ -2,11 +2,22 @@ ## Status -Proposed +Accepted + +Accepted on 2026-06-22. Wireframe keeps the connection actor +packet-oriented and makes the codec driver the sole owner of transport-frame +emission. Protocol hooks remain packet-oriented until the app-router response +gap is closed under roadmap item `11.2.1`; no public actor-boundary +`Vec` compatibility shim is introduced, with the public +`CorrelatableFrame for Vec` bridge removed under roadmap item `11.2.2` and +reviewed under `14.2.1`; and no new "serializable packet" trait is added +because `Packet` plus `EncodeWith` already expresses that +requirement. The remaining final outbound copy is removed under roadmap item +`11.1.2`, and the sole-owner boundary is guarded under roadmap item `11.2.3`. ## Date -2026-04-12 +Proposed 2026-04-12. Accepted 2026-06-22. ## Context and Problem Statement @@ -94,31 +105,44 @@ adds complexity without necessarily removing copies. _Table 1: Trade-offs for the actor and transport-frame boundary._ -## Decision Outcome / Proposed Direction +## Decision Outcome Adopt Option B: keep the actor packet-oriented, and make the codec driver the only component that owns transport frame emission. -The proposed direction is: +The accepted direction is: - `ConnectionActor` continues to reason about packet-shaped values such as - `Envelope`. + `Envelope`. In production, the actor remains generic over packet semantics + rather than over transport frame buffers. - The serializer and codec driver own the final - `packet -> bytes -> transport frame` transition. -- Any protocol hook that requires codec-frame visibility is attached at the - codec-driver boundary, not by forcing codec frames through actor traits they - do not naturally satisfy. -- `Vec` frame bridges are removed from the core runtime once the chosen - codec-driver path is proven. + `packet -> bytes -> transport frame` transition. Today the only production + `FrameCodec::wrap_payload` caller is the codec-driver path in + `src/app/outbound_encoding.rs`. +- Protocol hooks remain packet-oriented. The codec driver hosts serialization + and transport framing, not a second transport-frame hook surface. +- `Vec` frame bridges are removed from the core runtime once the approved + codec-driver path is proven. `Packet for Vec` stays test-only, while the + public `CorrelatableFrame for Vec` bridge leaves the core runtime in the + breaking release governed by roadmap items `11.2.2` and `14.2.1`. + +This closes roadmap item `10.1.3` and the corresponding zero-copy migration +roadmap item `1.1.3`. Runtime implementation is intentionally deferred to +roadmap items `11.1.2`, `11.2.1`, `11.2.2`, and `11.2.3`. ## Goals and Non-Goals ### Goals -- Keep transport framing and packet semantics decoupled. -- Remove accidental `Vec` dependencies at the actor boundary. +- Keep transport framing and packet semantics decoupled. This ADR now records + that boundary; roadmap item `11.2.1` implements any remaining runtime + alignment. +- Remove accidental `Vec` dependencies at the actor boundary. The + production boundary decision is accepted here; bridge removal is sequenced + under roadmap item `11.2.2`. - Give the zero-copy migration a stable place to enforce pointer reuse and - allocation tests. + allocation tests. Roadmap item `11.2.3` adds the regression coverage and the + guard against new non-driver production `wrap_payload` callers. ### Non-Goals @@ -132,16 +156,19 @@ The proposed direction is: ### Phase 1: formalize the packet-to-frame boundary Document which component owns serialization, protocol hook invocation, and -`wrap_payload`, and update the runtime so that ownership is reflected in code. -Consolidate any non-driver `FrameCodec::wrap_payload` callers into the -codec-driver boundary, including the current runtime inbound emission path, so -`ConnectionActor` no longer participates in transport frame emission outside -the codec driver. +`wrap_payload`, and update the runtime so that ownership is reflected in code +where any gap remains. The accepted owner is the codec driver. The known +app-router `before_send` asymmetry is closed under roadmap item `11.2.1`; +guard coverage for new non-driver production `wrap_payload` callers is added +under roadmap item `11.2.3`. ### Phase 2: remove obsolete core bridges Delete or move `Vec`-specific core frame bridges once the actor no longer -needs them for production behaviour. +needs them for production behaviour. `Packet for Vec` remains in test +support. `CorrelatableFrame for Vec` is a public production impl, so its +removal is a breaking-release change tracked under roadmap items `11.2.2` and +`14.2.1`. ### Phase 3: validate the boundary @@ -151,25 +178,52 @@ stage. ## Known Risks and Limitations -- The protocol hook story still needs a precise statement of which hooks run on - packets and which run on transport frames. +- Protocol hooks stay packet-oriented. The current limitation is narrower: + `before_send` fires for actor-driven push and multi-packet frames, but not yet + for app-router responses routed through `FramePipeline`. Roadmap item + `11.2.1` owns that closure. - If the codec driver becomes the only framing boundary, its tests must carry more of the performance and correctness burden than they do today. - Some example or test harness code may continue to use `Vec` as a convenience type even after the production boundary is cleaned up. -- Until every non-driver `FrameCodec::wrap_payload` caller is relocated, the - project needs an explicit tracked list of remaining call sites, including the - inbound emission path adjacent to `ConnectionActor`, so reviews can verify - that the codec driver is becoming the sole owner of transport frame emission. +- The final serializer-to-codec bridge still materializes `Vec` before + converting to `Bytes`. Roadmap item `11.1.2` and issue + own the + `Bytes`-native serializer contract that removes this copy. +- The project needs guard coverage against future non-driver production + `FrameCodec::wrap_payload` callers. Roadmap item `11.2.3` owns that guard. -## Outstanding Decisions +## Tracked transport-frame call sites + +At acceptance time, the sole production `FrameCodec::wrap_payload` caller is +`src/app/outbound_encoding.rs`, which sits inside the codec-driver boundary and +performs the current `Serializer::serialize -> Bytes::from -> wrap_payload` +transition. Other `wrap_payload` call sites are tests, examples, test helpers, +or testkit support. + +Roadmap item `11.2.3` must add a guard that fails if a new non-driver +production caller appears. Until that guard exists, reviews should verify this +inventory manually. + +## Resolved Decisions - Which existing protocol hooks should move to the codec-driver boundary, and - which should remain packet-oriented? + which should remain packet-oriented? Existing hooks remain packet-oriented and + continue to run against `Envelope` before serialization. The codec driver + does not gain a new transport-frame-level hook surface. The app-router + response `before_send` gap is documented as a limitation and tracked under + roadmap item `11.2.1`. - Should any remaining `Vec` bridge live in `test_support`, a feature-gated - compatibility module, or nowhere at all? + compatibility module, or nowhere at all? No public feature-gated actor-boundary + compatibility shim is introduced. `Packet for Vec` stays in test support. + The public `CorrelatableFrame for Vec` impl leaves the core runtime under + the breaking-release work in roadmap item `11.2.2`, with retained bridges + reviewed under roadmap item `14.2.1`. - Does the project need a new internal trait to express "serializable packet" - separately from transport frame semantics? + separately from transport frame semantics? No. The existing `Packet` trait + composed with `EncodeWith` already expresses "a packet that can be + serialized"; `Envelope` satisfies both. Adding a bridging trait would recreate + rejected Option C without removing copies. ## Architectural Rationale From c7d5b785d20407d2e454aa68743b5b3cb4eb25cc Mon Sep 17 00:00:00 2001 From: leynos Date: Wed, 24 Jun 2026 20:10:59 +0200 Subject: [PATCH 04/12] Propagate ADR 010 acceptance Mark the actor and codec-driver boundary decision complete across the roadmaps, inventory, developers' guide, and documentation index. --- docs/contents.md | 4 +++- docs/developers-guide.md | 14 ++++++++++++++ docs/frame-vec-u8-inventory.md | 18 ++++++++++++------ docs/roadmap.md | 2 +- ...copy-frame-and-payload-migration-roadmap.md | 8 ++++---- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/docs/contents.md b/docs/contents.md index 1a276f80..7d1ca727 100644 --- a/docs/contents.md +++ b/docs/contents.md @@ -43,12 +43,14 @@ reference when navigating the project's design and architecture material. - [ADR 009: owned-byte migration rollout](adr-009-vec-u8-migration-rollout.md) Rollout policy for owned-byte compatibility during migration. - [ADR 010: transport frame boundary for zero-copy](adr-010-transport-frame-boundary-for-zero-copy.md) - Decision for the frame boundary during zero-copy migration. + Accepted actor and codec-driver boundary for zero-copy transport framing. ## Execution plans - [Approve stable public byte container](execplans/10-1-1-approve-stable-public-byte-container.md) Completed execution plan for roadmap item `10.1.1` and ADR 008. +- [Approve actor and codec-driver boundary](execplans/10-1-3-approve-actor-and-codec-driver-boundary.md) + Execution plan for roadmap item `10.1.3` and ADR 010. - [Execution plan directory](execplans/) Working plans for roadmap items, migrations, verification work, and documentation follow-up tasks. diff --git a/docs/developers-guide.md b/docs/developers-guide.md index fda632ff..a024abfc 100644 --- a/docs/developers-guide.md +++ b/docs/developers-guide.md @@ -38,6 +38,20 @@ storage. Do not introduce new public `Vec` payload contracts unless the [ADR 009 compatibility policy](adr-009-vec-u8-migration-rollout.md) for the zero-copy rollout explicitly calls for them. + +## Actor and codec-driver boundary + +[ADR 010](adr-010-transport-frame-boundary-for-zero-copy.md) accepts the +runtime boundary for zero-copy transport framing. The connection actor remains +packet-oriented and works with `Envelope` or another packet-shaped type; it +does not become responsible for codec frame buffers. + +The codec driver owns the `packet -> bytes -> transport frame` transition, +including serialization and `FrameCodec::wrap_payload`. Protocol hooks remain +packet-oriented and run before serialization. The known gap is narrower: +`before_send` does not yet fire for app-router responses routed through +`FramePipeline`; roadmap item `11.2.1` owns that closure. + ## Allowed aliases and prohibited mixing | Canonical term | Allowed aliases | Avoid in the same context | diff --git a/docs/frame-vec-u8-inventory.md b/docs/frame-vec-u8-inventory.md index e8c456b7..33a57a35 100644 --- a/docs/frame-vec-u8-inventory.md +++ b/docs/frame-vec-u8-inventory.md @@ -325,7 +325,7 @@ The inventory suggests several non-prescriptive workstreams: long as public mutation hooks still require owned mutable bytes. - Remove `CorrelatableFrame for Vec` from the core surface once raw `Vec` stops being a documented or production frame shape. If a bridge is - still useful, keep it in docs, `test-support`, or a feature-gated + still useful, keep it in test support rather than as a public actor-boundary compatibility shim. - Keep client preamble leftovers as owned `Vec` values for now. Revisit that path only if the broader public byte APIs converge on a shared buffer @@ -348,8 +348,12 @@ The current direction is now explicit: - The long-term outbound boundary should be `Bytes`-compatible rather than `Vec`-centric, with `Vec` retained only as a compatibility adapter while mutable byte-edit hooks still require it. -- `CorrelatableFrame for Vec` should leave the core surface once raw - `Vec` stops serving as a documented or production frame shape. +- The connection actor stays packet-oriented, while the codec driver owns + serialization and transport-frame emission. Protocol hooks remain + packet-oriented; the app-router `before_send` gap is tracked separately. +- `CorrelatableFrame for Vec` should leave the core surface under the + breaking-release runtime-boundary work. `Packet for Vec` remains + test-only, and no public actor-boundary compatibility shim is added. - Client preamble leftovers remain a separate compatibility surface and should stay as owned `Vec` for now. @@ -372,9 +376,11 @@ The design choices are captured in three Architecture Decision Records (ADRs): compatibility and release rollout strategy, including the finite `Vec` helper set, default-build deprecation discipline, and the event-based removal trigger. -- [ADR 010](adr-010-transport-frame-boundary-for-zero-copy.md) (proposed) - covers the actor, codec-driver, and transport-frame boundary for the - zero-copy path. +- [ADR 010](adr-010-transport-frame-boundary-for-zero-copy.md) (accepted) + keeps the connection actor packet-oriented, makes the codec driver the owner + of transport-frame emission, keeps protocol hooks at the packet stage, and + sequences public `CorrelatableFrame for Vec` removal with the + breaking-release runtime-boundary work. If epic 284 is updated outside the repository, the local source-of-truth links to add are: diff --git a/docs/roadmap.md b/docs/roadmap.md index 75c8be66..4df4bd28 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -455,7 +455,7 @@ starts. See `docs/frame-vec-u8-inventory.md` and ADRs 008 through 010. - [x] 10.1.2. Approve the compatibility and rollout policy for downstream users, including which `Vec` helpers survive the breaking release. See `docs/adr-009-vec-u8-migration-rollout.md`. -- [ ] 10.1.3. Approve the actor and codec-driver boundary so `Vec` bridges +- [x] 10.1.3. Approve the actor and codec-driver boundary so `Vec` bridges leave the core runtime deliberately rather than incidentally. See `docs/adr-010-transport-frame-boundary-for-zero-copy.md`. diff --git a/docs/zero-copy-frame-and-payload-migration-roadmap.md b/docs/zero-copy-frame-and-payload-migration-roadmap.md index d0e98b68..15b726cd 100644 --- a/docs/zero-copy-frame-and-payload-migration-roadmap.md +++ b/docs/zero-copy-frame-and-payload-migration-roadmap.md @@ -71,13 +71,13 @@ Success is measured by the following outcomes: are removed, and runtime bridges are governed by ADR 010. - [x] Success criteria: the release branch has an agreed downstream migration story before code changes start landing. -- [ ] 1.1.3. Approve the transport-frame boundary for the zero-copy path. See +- [x] 1.1.3. Approve the transport-frame boundary for the zero-copy path. See [ADR 010](adr-010-transport-frame-boundary-for-zero-copy.md). - - [ ] Confirm whether `ConnectionActor` remains envelope-oriented or takes on + - [x] Confirm whether `ConnectionActor` remains envelope-oriented or takes on codec-frame responsibilities. - - [ ] Confirm where protocol hooks execute when `F::Frame` differs from the + - [x] Confirm where protocol hooks execute when `F::Frame` differs from the actor payload type. - - [ ] Success criteria: the actor, codec driver, and protocol hook boundary + - [x] Success criteria: the actor, codec driver, and protocol hook boundary are documented and no longer depend on ad hoc `Vec` bridges. ### 1.2. Establish performance and migration baselines From 818583967071401d56016d3dbc3357cfa4372740 Mon Sep 17 00:00:00 2001 From: leynos Date: Wed, 24 Jun 2026 20:11:36 +0200 Subject: [PATCH 05/12] Update actor boundary execplan progress Record completed ADR and propagation stages plus the refined stale-reference validation note before the full gates. --- ...approve-actor-and-codec-driver-boundary.md | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md index 370e45d7..688359b0 100644 --- a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md +++ b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md @@ -140,15 +140,17 @@ escalation, not a workaround. ## Progress -- [x] (2026-06-24) Stage A: research and propose — gather code, prior art, and the - sibling-item delivery pattern; draft the resolved decisions. (completed during - planning; see `Context and orientation` and `Artifacts and notes`.) -- [ ] (2026-06-24, in progress) Stage B: author the accepted ADR 010 rewrite - (status, dates, Decision - Outcome expansion, resolved Outstanding Decisions, tracked call-site note). -- [ ] Stage C: propagate the acceptance across `roadmap.md`, the zero-copy - migration roadmap, the inventory, `contents.md`, and `developers-guide.md`. -- [ ] Stage D: run documentation and commit gates, then a `coderabbit +- [x] (2026-06-24) Stage A: research and propose — gather code, prior art, and + the sibling-item delivery pattern; draft the resolved decisions. (completed + during planning; see `Context and orientation` and `Artifacts and notes`.) +- [x] (2026-06-24) Stage B: author the accepted ADR 010 rewrite (status, dates, + Decision Outcome expansion, resolved Outstanding Decisions, tracked call-site + note). Commit: `813898b`. +- [x] (2026-06-24) Stage C: propagate the acceptance across `roadmap.md`, the + zero-copy migration roadmap, the inventory, `contents.md`, and + `developers-guide.md`. Commit: `4123b3e`. +- [ ] (2026-06-24, in progress) Stage D: run documentation and commit gates, + then a `coderabbit review --agent` pass; clear all concerns. - [ ] Mark roadmap `10.1.3` done and finalise this ExecPlan to `COMPLETE`. @@ -191,6 +193,14 @@ edit and its propagation can be reviewed independently. Impact: execution used `docs/contents.md`, the documentation style guide, and the governing ADR, roadmap, inventory, and developers' guide files listed in this plan instead. +- Observation: The original stale-reference grep in this plan was too broad + after execution started because the ExecPlan itself intentionally describes + the risk of stale "proposed" references. + Evidence: after Stage C, `rg -ni "adr.?010|transport.frame boundary" docs/ | + rg -i "propos"` matched only this ExecPlan's risk and validation text. + Impact: no governing document still describes ADR 010 as proposed. The + concrete validation step now treats ExecPlan self-references and preserved ADR + proposal history as non-drift. ## Decision log @@ -427,8 +437,10 @@ Run all commands from the repository root rg -ni "adr.?010|transport.frame boundary" docs/ | rg -i "propos" ``` - Expected: no output (every reference now reads accepted). Stage and commit the - propagation edits. + Expected: no governing document still describes ADR 010 as proposed. Matches + inside this ExecPlan's risk/validation text, or inside preserved ADR proposal + history such as dual dates and rejected options, are not cross-reference + drift. Stage and commit the propagation edits. 4. Run the commit gateway (documentation-only change, but the full suite must stay green): From c2258e61988d46a2977708d21fddcad752db3762 Mon Sep 17 00:00:00 2001 From: leynos Date: Wed, 24 Jun 2026 20:25:43 +0200 Subject: [PATCH 06/12] Complete actor boundary execplan Record final gate results, CodeRabbit findings, and retrospective for the ADR 010 decision-closure work. --- ...approve-actor-and-codec-driver-boundary.md | 48 +++++++++++++++---- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md index 688359b0..669efbb2 100644 --- a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md +++ b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md @@ -5,7 +5,7 @@ This ExecPlan (execution plan) is a living document. The sections `Decision Log`, and `Outcomes & Retrospective` must be kept up to date as work proceeds. -Status: IN PROGRESS +Status: COMPLETE ## Purpose / big picture @@ -149,10 +149,11 @@ escalation, not a workaround. - [x] (2026-06-24) Stage C: propagate the acceptance across `roadmap.md`, the zero-copy migration roadmap, the inventory, `contents.md`, and `developers-guide.md`. Commit: `4123b3e`. -- [ ] (2026-06-24, in progress) Stage D: run documentation and commit gates, - then a `coderabbit - review --agent` pass; clear all concerns. -- [ ] Mark roadmap `10.1.3` done and finalise this ExecPlan to `COMPLETE`. +- [x] (2026-06-24) Stage D: run documentation and commit gates, then a + `coderabbit review --agent` pass; clear all concerns. CodeRabbit completed + with `findings: 0`. +- [x] (2026-06-24) Mark roadmap `10.1.3` done and finalise this ExecPlan to + `COMPLETE`. Each stage is gated by `make markdownlint` (and `make nixie` if a diagram is touched) before commit. Stages B and C are committed separately so the decision @@ -201,6 +202,13 @@ edit and its propagation can be reviewed independently. Impact: no governing document still describes ADR 010 as proposed. The concrete validation step now treats ExecPlan self-references and preserved ADR proposal history as non-drift. +- Observation: The full gate and review pass succeeded after the documentation + changes. + Evidence: `make markdownlint`, `make check-fmt`, `make lint`, and `make test` + all exited 0 on 2026-06-24 using tee logs under `/tmp`. `coderabbit + review --agent` completed with `findings: 0`. + Impact: no deterministic gate failure or CodeRabbit concern remains for this + decision-closure item. ## Decision log @@ -267,12 +275,29 @@ edit and its propagation can be reviewed independently. breached. Date/Author: 2026-06-24, implementation agent. +- Decision: Treat the broad stale-reference grep as an advisory drift check + rather than a literal zero-output command. + Rationale: accepted ADRs deliberately preserve proposal history such as + proposed dates, options considered, and rejected directions. After Stage C, + the only matches from the original command were this ExecPlan's own risk and + validation prose. No governing status reference still described ADR 010 as + proposed, so this did not breach the cross-reference-drift risk. + Date/Author: 2026-06-24, implementation agent. + ## Outcomes & retrospective -To be completed when the plan is executed. Compare the accepted ADR against this -plan's purpose: a single written boundary that lets phase 11 remove `Vec` -bridges deliberately. Note any divergence between the resolved decisions and what -phase 11 ultimately implements. +ADR 010 is accepted and now records the actor and codec-driver boundary needed +for phase 11. The accepted record keeps the connection actor packet-oriented, +makes the codec driver the production transport-frame emission owner, keeps +protocol hooks at the packet stage, rejects a new "serializable packet" trait, +and sequences the public `CorrelatableFrame for Vec` bridge removal with +the breaking-release runtime-boundary work. + +The roadmap, zero-copy migration roadmap, inventory, developers' guide, and +documentation index now agree with the accepted decision. No Rust code or +public API changed in this item. The main lesson from execution is that the +planned stale-reference grep was useful but too broad; a human check still has +to distinguish preserved ADR history from live status drift. ## Context and orientation @@ -582,3 +607,8 @@ Execution update (2026-06-24): user approval received, branch tracking confirmed against `origin/10-1-3-approve-actor-and-codec-driver-boundary`, preflight call-site inventory rechecked, and status moved to IN PROGRESS before Stage B ADR edits. + +Completion update (2026-06-24): accepted ADR 010, propagated the acceptance +through the governing documentation, passed `make markdownlint`, +`make check-fmt`, `make lint`, and `make test`, and completed +`coderabbit review --agent` with `findings: 0`. Status: COMPLETE. From 15790e80c176438ec459dbcdcc400bdc2cc65bcc Mon Sep 17 00:00:00 2001 From: leynos Date: Sat, 18 Jul 2026 17:54:10 +0200 Subject: [PATCH 07/12] Fix ADR 010 documentation review Align the completed plan index, Oxford spelling, roadmap traceability, and ExecPlan privacy wording. --- docs/contents.md | 2 +- docs/developers-guide.md | 4 +-- ...approve-actor-and-codec-driver-boundary.md | 27 +++++++++---------- docs/frame-vec-u8-inventory.md | 3 ++- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/contents.md b/docs/contents.md index 7d1ca727..075f8757 100644 --- a/docs/contents.md +++ b/docs/contents.md @@ -50,7 +50,7 @@ reference when navigating the project's design and architecture material. - [Approve stable public byte container](execplans/10-1-1-approve-stable-public-byte-container.md) Completed execution plan for roadmap item `10.1.1` and ADR 008. - [Approve actor and codec-driver boundary](execplans/10-1-3-approve-actor-and-codec-driver-boundary.md) - Execution plan for roadmap item `10.1.3` and ADR 010. + Completed execution plan for roadmap item `10.1.3` and ADR 010. - [Execution plan directory](execplans/) Working plans for roadmap items, migrations, verification work, and documentation follow-up tasks. diff --git a/docs/developers-guide.md b/docs/developers-guide.md index a024abfc..17df71bc 100644 --- a/docs/developers-guide.md +++ b/docs/developers-guide.md @@ -47,8 +47,8 @@ packet-oriented and works with `Envelope` or another packet-shaped type; it does not become responsible for codec frame buffers. The codec driver owns the `packet -> bytes -> transport frame` transition, -including serialization and `FrameCodec::wrap_payload`. Protocol hooks remain -packet-oriented and run before serialization. The known gap is narrower: +including serialisation and `FrameCodec::wrap_payload`. Protocol hooks remain +packet-oriented and run before serialisation. The known gap is narrower: `before_send` does not yet fire for app-router responses routed through `FramePipeline`; roadmap item `11.2.1` owns that closure. diff --git a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md index 669efbb2..537bfeb6 100644 --- a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md +++ b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md @@ -152,7 +152,7 @@ escalation, not a workaround. - [x] (2026-06-24) Stage D: run documentation and commit gates, then a `coderabbit review --agent` pass; clear all concerns. CodeRabbit completed with `findings: 0`. -- [x] (2026-06-24) Mark roadmap `10.1.3` done and finalise this ExecPlan to +- [x] (2026-06-24) Mark roadmap `10.1.3` done and finalize this ExecPlan to `COMPLETE`. Each stage is gated by `make markdownlint` (and `make nixie` if a diagram is @@ -224,7 +224,7 @@ edit and its propagation can be reviewed independently. because `F::Frame` and `Envelope` can differ (deferred in roadmap `9.3.1`) — is best closed by unifying the response path onto the actor's `Envelope` hook stage under `11.2.1`, not by relocating hooks downward. - Date/Author: 2026-06-22, planning agent (with Logisphere panel input). + Date: 2026-06-22 - Decision: Resolve ADR 010 Outstanding Decision (B) with no public feature-gated compatibility shim; keep `Packet for Vec` in test support and @@ -239,7 +239,7 @@ edit and its propagation can be reviewed independently. Because the impl is public, Telefono (contracts lens) flagged its removal as a breaking change, so it is bound to `11.2.2` / `14.2.1` rather than treated as a free internal cleanup. - Date/Author: 2026-06-22, planning agent (with Logisphere panel input). + Date: 2026-06-22 - Decision: Resolve ADR 010 Outstanding Decision (C) as "no new trait". Rationale: `Packet` (`id`, `into_parts`, `from_parts`) plus @@ -248,7 +248,7 @@ edit and its propagation can be reviewed independently. layer without removing copies. Prior art corroborates: tonic reuses the message type plus an `Encoder` rather than a bespoke packet trait, and keeps gRPC length-framing in a separate buffer layer (see `Artifacts and notes`). - Date/Author: 2026-06-22, planning agent (with Logisphere panel input). + Date: 2026-06-22 - Decision: Record the canonical production `wrap_payload` call site in the ADR and require a guard against new non-driver callers (implemented in phase 11). @@ -257,7 +257,7 @@ edit and its propagation can be reviewed independently. manual list rots; a grep-style guard test keeps the "sole owner" guarantee enforceable. The requirement is recorded now; the test is added with the runtime work (`11.2.3`). - Date/Author: 2026-06-22, planning agent (with Logisphere panel input). + Date: 2026-06-22 - Decision: Deliver `10.1.3` as documentation only, mirroring `10.1.1` and `10.1.2`. @@ -265,7 +265,7 @@ edit and its propagation can be reviewed independently. expanded its Decision Outcome, ticked the roadmaps, aligned the inventory, and added a developers'-guide note, with no runtime change. Consistency keeps the decision-closure phase reviewable and reversible. - Date/Author: 2026-06-22, planning agent. + Date: 2026-06-22 - Decision: Begin execution from explicit user approval on 2026-06-24 while leaving the scope documentation-only. @@ -273,7 +273,7 @@ edit and its propagation can be reviewed independently. branch already tracks `origin/10-1-3-approve-actor-and-codec-driver-boundary`, and the preflight inventory confirmed no decision-drift tolerance has been breached. - Date/Author: 2026-06-24, implementation agent. + Date: 2026-06-24 - Decision: Treat the broad stale-reference grep as an advisory drift check rather than a literal zero-output command. @@ -282,7 +282,7 @@ edit and its propagation can be reviewed independently. the only matches from the original command were this ExecPlan's own risk and validation prose. No governing status reference still described ADR 010 as proposed, so this did not breach the cross-reference-drift risk. - Date/Author: 2026-06-24, implementation agent. + Date: 2026-06-24 ## Outcomes & retrospective @@ -429,13 +429,12 @@ Validate with `make markdownlint` and commit Stage C on its own. ### Stage D: gates and review Run the full commit gateway and a CodeRabbit pass; clear every concern before -finalising. Then tick this plan's `Progress` items, set `Status: COMPLETE`, and +finalizing. Then tick this plan's `Progress` items, set `Status: COMPLETE`, and complete `Outcomes & retrospective`. ## Concrete steps -Run all commands from the repository root -(`/home/leynos/.lody/repos/github---leynos---wireframe/worktrees/9f3f8a4e-aca9-4624-b9c5-92de91c9e0bf`). +Run all commands from the repository root (`.`). 1. Confirm the call-site inventory still holds before writing the ADR claim: @@ -476,7 +475,7 @@ Run all commands from the repository root make test 2>&1 | tee /tmp/test-wireframe-10-1-3.out ``` - Run sequentially (the environment caches builds; do not parallelise). + Run sequentially (the environment caches builds; do not parallelize). 5. Request review: @@ -484,7 +483,7 @@ Run all commands from the repository root coderabbit review --agent 2>&1 | tee /tmp/coderabbit-wireframe-10-1-3.out ``` - Resolve every concern, re-running the relevant gate, before finalising. + Resolve every concern, re-running the relevant gate, before finalizing. ## Validation and acceptance @@ -540,7 +539,7 @@ transport framing: message trait's concern. tonic introduces no bespoke "serializable packet" trait — it reuses the message type plus an encoder. Source: . -- **tokio_util::codec** parameterises `Encoder`/`Decoder` on the item +- **tokio_util::codec** parameterizes `Encoder`/`Decoder` on the item type and owns framing in `Framed`, keeping the *item* distinct from the byte buffer. The tonic maintainers note the two trait families differ mainly in tokio-util's `Encoder` taking the item as a type parameter. diff --git a/docs/frame-vec-u8-inventory.md b/docs/frame-vec-u8-inventory.md index 33a57a35..a8d84d3a 100644 --- a/docs/frame-vec-u8-inventory.md +++ b/docs/frame-vec-u8-inventory.md @@ -350,7 +350,8 @@ The current direction is now explicit: while mutable byte-edit hooks still require it. - The connection actor stays packet-oriented, while the codec driver owns serialization and transport-frame emission. Protocol hooks remain - packet-oriented; the app-router `before_send` gap is tracked separately. + packet-oriented; the app-router `before_send` gap is tracked separately in + [roadmap item `11.2.1`](roadmap.md#112-actor-and-codec-driver-boundary). - `CorrelatableFrame for Vec` should leave the core surface under the breaking-release runtime-boundary work. `Packet for Vec` remains test-only, and no public actor-boundary compatibility shim is added. From 14af936227e8774bc5e07ef2e4071616d3707ead Mon Sep 17 00:00:00 2001 From: leynos Date: Sun, 19 Jul 2026 23:13:19 +0200 Subject: [PATCH 08/12] Fix documentation spelling checks Align the ADR 010 documentation with the repository spelling policy and Markdown lint rules. --- docs/developers-guide.md | 5 ++--- .../10-1-3-approve-actor-and-codec-driver-boundary.md | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/developers-guide.md b/docs/developers-guide.md index 17df71bc..8d4c89d4 100644 --- a/docs/developers-guide.md +++ b/docs/developers-guide.md @@ -38,7 +38,6 @@ storage. Do not introduce new public `Vec` payload contracts unless the [ADR 009 compatibility policy](adr-009-vec-u8-migration-rollout.md) for the zero-copy rollout explicitly calls for them. - ## Actor and codec-driver boundary [ADR 010](adr-010-transport-frame-boundary-for-zero-copy.md) accepts the @@ -47,8 +46,8 @@ packet-oriented and works with `Envelope` or another packet-shaped type; it does not become responsible for codec frame buffers. The codec driver owns the `packet -> bytes -> transport frame` transition, -including serialisation and `FrameCodec::wrap_payload`. Protocol hooks remain -packet-oriented and run before serialisation. The known gap is narrower: +including serialization and `FrameCodec::wrap_payload`. Protocol hooks remain +packet-oriented and run before serialization. The known gap is narrower: `before_send` does not yet fire for app-router responses routed through `FramePipeline`; roadmap item `11.2.1` owns that closure. diff --git a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md index 537bfeb6..bf2f14ae 100644 --- a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md +++ b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md @@ -375,7 +375,7 @@ Items `10.1.1` (ADR 008, commit `cd153de`) and `10.1.2` (ADR 009, commit ### Stage A: research and propose (no edits) — done during planning Completed. Findings are captured in `Context and orientation`, `Surprises & -discoveries`, and `Artifacts and notes`. The three Outstanding Decisions are +discoveries`, and `Artefacts and notes`. The three Outstanding Decisions are resolved in `Decision log`. The Logisphere panel returned "Proceed with conditions"; the conditions are folded into the constraints and the ADR rewrite below. @@ -524,7 +524,7 @@ call-site inventory in step 1 returns more than one production caller, that breaches Tolerance 2: stop and escalate rather than weakening the ADR's "sole owner" claim. -## Artifacts and notes +## Artefacts and notes ### Prior art (firecrawl research) From 61a0f90b9572f11d7d099d2540400c71ea913e68 Mon Sep 17 00:00:00 2001 From: leynos Date: Mon, 20 Jul 2026 00:00:49 +0200 Subject: [PATCH 09/12] Anonymize ExecPlan review metadata Keep the ADR 010 decision conditions while removing review tooling and reviewer persona references. --- ...approve-actor-and-codec-driver-boundary.md | 73 +++++++++---------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md index bf2f14ae..3670992f 100644 --- a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md +++ b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md @@ -29,8 +29,7 @@ A reader can observe success in three ways once the plan is executed: `docs/zero-copy-frame-and-payload-migration-roadmap.md` item `1.1.3` (with its child bullets) are checked `[x]`. 3. `make check-fmt`, `make lint`, `make test`, and `make markdownlint` all pass - on a clean tree, and a `coderabbit review --agent` pass raises no - outstanding concerns. + on a clean tree, and an automated review raises no outstanding concerns. This item changes **no Rust code and no public API**. It is a documentation and decision artefact. The runtime changes it sanctions are deliberately deferred to @@ -149,9 +148,8 @@ escalation, not a workaround. - [x] (2026-06-24) Stage C: propagate the acceptance across `roadmap.md`, the zero-copy migration roadmap, the inventory, `contents.md`, and `developers-guide.md`. Commit: `4123b3e`. -- [x] (2026-06-24) Stage D: run documentation and commit gates, then a - `coderabbit review --agent` pass; clear all concerns. CodeRabbit completed - with `findings: 0`. +- [x] (2026-06-24) Stage D: run documentation and commit gates, then an + automated review; clear all concerns. The automated review found no concerns. - [x] (2026-06-24) Mark roadmap `10.1.3` done and finalize this ExecPlan to `COMPLETE`. @@ -205,10 +203,10 @@ edit and its propagation can be reviewed independently. - Observation: The full gate and review pass succeeded after the documentation changes. Evidence: `make markdownlint`, `make check-fmt`, `make lint`, and `make test` - all exited 0 on 2026-06-24 using tee logs under `/tmp`. `coderabbit - review --agent` completed with `findings: 0`. - Impact: no deterministic gate failure or CodeRabbit concern remains for this - decision-closure item. + all exited 0 on 2026-06-24 using tee logs under `/tmp`. The automated review + completed with no concerns. + Impact: no deterministic gate failure or automated-review concern remains for + this decision-closure item. ## Decision log @@ -236,8 +234,8 @@ edit and its propagation can be reviewed independently. `impl CorrelatableFrame for Vec` lives in production module `src/correlation.rs` but has no production caller; ADR 009 already routes runtime bridges to ADR 010 and removes middleware `&mut Vec` editors. - Because the impl is public, Telefono (contracts lens) flagged its removal as - a breaking change, so it is bound to `11.2.2` / `14.2.1` rather than treated + Because the impl is public, its removal is a breaking change, so it is bound + to `11.2.2` / `14.2.1` rather than treated as a free internal cleanup. Date: 2026-06-22 @@ -253,8 +251,8 @@ edit and its propagation can be reviewed independently. - Decision: Record the canonical production `wrap_payload` call site in the ADR and require a guard against new non-driver callers (implemented in phase 11). Rationale: ADR 010's "Known Risks" already asks for a tracked list of - non-driver callers. Buzzy Bee (scaling lens) and Doggylump (ops lens) noted a - manual list rots; a grep-style guard test keeps the "sole owner" guarantee + non-driver callers. A manual list rots; a grep-style guard test keeps the + "sole owner" guarantee enforceable. The requirement is recorded now; the test is added with the runtime work (`11.2.3`). Date: 2026-06-22 @@ -376,9 +374,8 @@ Items `10.1.1` (ADR 008, commit `cd153de`) and `10.1.2` (ADR 009, commit Completed. Findings are captured in `Context and orientation`, `Surprises & discoveries`, and `Artefacts and notes`. The three Outstanding Decisions are -resolved in `Decision log`. The Logisphere panel returned "Proceed with -conditions"; the conditions are folded into the constraints and the ADR rewrite -below. +resolved in `Decision log`. Design review identified conditions that are folded +into the constraints and the ADR rewrite below. ### Stage B: author the accepted ADR 010 @@ -428,7 +425,7 @@ Validate with `make markdownlint` and commit Stage C on its own. ### Stage D: gates and review -Run the full commit gateway and a CodeRabbit pass; clear every concern before +Run the full commit gateway and an automated review; clear every concern before finalizing. Then tick this plan's `Progress` items, set `Status: COMPLETE`, and complete `Outcomes & retrospective`. @@ -477,11 +474,8 @@ Run all commands from the repository root (`.`). Run sequentially (the environment caches builds; do not parallelize). -5. Request review: - - ```bash - coderabbit review --agent 2>&1 | tee /tmp/coderabbit-wireframe-10-1-3.out - ``` +5. Run the automated review and record its result under + `/tmp/automated-review-wireframe-10-1-3.out`. Resolve every concern, re-running the relevant gate, before finalizing. @@ -503,7 +497,7 @@ Acceptance is behaviour a reviewer can verify: 3. `rg -ni "adr.?010" docs/ | rg -i "propos"` returns nothing. 4. `make markdownlint`, `make check-fmt`, `make lint`, and `make test` each exit 0; their `tee` logs in `/tmp` show success. -5. `coderabbit review --agent` reports no unresolved concerns. +5. The automated review reports no unresolved concerns. Quality criteria ("done"): @@ -513,7 +507,7 @@ Quality criteria ("done"): - Documentation: all five governing documents agree ADR 010 is accepted; the developers' guide records the boundary and the tracked `before_send` gap. -Quality method: the commands in `Concrete steps`, then CodeRabbit. +Quality method: the commands in `Concrete steps`, then the automated review. ## Idempotence and recovery @@ -549,23 +543,22 @@ Both build the byte plane on `bytes::Bytes`, matching ADR 008's accepted public byte container and reinforcing Option B: keep packet semantics in `Packet` + `EncodeWith`, and keep transport framing in the codec driver. -### Logisphere design review (conditions folded in) +### Design review conditions -Verdict: ⚠️ Proceed with conditions. Conditions, each addressed above: +Design review identified the following conditions, each addressed above: -- ☎️ Telefono: removing public `CorrelatableFrame for Vec` is breaking — - sequence with the epic-284 breaking release (`11.2.2`/`14.2.1`); `10.1.3` +- Removing public `CorrelatableFrame for Vec` is breaking. Sequence the + change with the epic-284 breaking release (`11.2.2`/`14.2.1`); `10.1.3` changes no public API. (Constraint 1; Risk 2; Decision (B).) -- 🐶 Doggylump: document the `before_send` asymmetry, do not hide it; track to - `11.2.1`. (Decision (A); Risk 3; Stage C step 4.) -- 🐝 Buzzy Bee: guard the "sole owner" guarantee with a check against new - non-driver `wrap_payload` callers; record now, implement in `11.2.3`. +- Document the `before_send` asymmetry and track its closure under `11.2.1`. + (Decision (A); Risk 3; Stage C step 4.) +- Guard the "sole owner" guarantee against new non-driver `wrap_payload` + callers. Record the requirement now and implement the check in `11.2.3`. (Decision; ADR tracked-call-site note.) -- 🐼 Pandalump: state the actor stays generic over `Packet` while `Vec` - ceases to be a sanctioned frame type. (Context; ADR Decision Outcome.) -- 🐈🧇 Wafflecat: the strongest alternative — move hooks to the transport-frame - layer — is rejected because it strips the packet semantics hooks rely on. - (Decision (A).) +- State that the actor stays generic over `Packet` while `Vec` ceases to be + a sanctioned frame type. (Context; ADR Decision Outcome.) +- Reject moving hooks to the transport-frame layer because it strips the packet + semantics hooks rely on. (Decision (A).) ## Interfaces and dependencies @@ -598,8 +591,8 @@ breaking release). Initial draft (2026-06-22): created the decision-closure plan for roadmap `10.1.3`. Resolved ADR 010's three Outstanding Decisions, captured the sibling-item delivery pattern from `10.1.1`/`10.1.2`, recorded prior-art -corroboration (tonic, tokio_util) and a Logisphere "proceed with conditions" -review, and scoped the work to documentation only with implementation deferred +corroboration (tonic, tokio_util) and a design review with conditions, and +scoped the work to documentation only with implementation deferred to roadmap phase 11. Status: DRAFT, awaiting approval before execution. Execution update (2026-06-24): user approval received, branch tracking confirmed @@ -610,4 +603,4 @@ ADR edits. Completion update (2026-06-24): accepted ADR 010, propagated the acceptance through the governing documentation, passed `make markdownlint`, `make check-fmt`, `make lint`, and `make test`, and completed -`coderabbit review --agent` with `findings: 0`. Status: COMPLETE. +an automated review with no concerns. Status: COMPLETE. From 3b7b017d37dfb5f532f0843c629831b1f579f691 Mon Sep 17 00:00:00 2001 From: leynos Date: Mon, 20 Jul 2026 11:12:05 +0200 Subject: [PATCH 10/12] Address ExecPlan review feedback for ADR 010 acceptance Resolve four inline review comments on the 10.1.3 ExecPlan: - Describe ADR 010 as now Accepted in the "governing documents" section, aligning the completed plan with the accepted ADR. - Fix the internal reference to use the en-GB heading "Artefacts and notes" so it matches the section title exactly. - Replace the case-insensitive `grep -v -i test` wrap_payload inventory with a path-aware `rg` glob exclusion (examples, tests, test helpers, testkit) and correct the recorded evidence to the paths that actually match (src/codec/tests.rs, src/codec/tests/property/, testkit/support.rs). - Replace the unconditional no-match stale-reference expectation with an executable path-aware assertion that filters this ExecPlan's own risk/validation prose and the ADR's preserved proposal history, and fails on any governing document that still calls ADR 010 proposed; update the matching Validation and acceptance check to reference it. Docs-only. make check-fmt, lint, typecheck, test, and markdownlint pass. Co-Authored-By: Claude Opus 4.8 (1M context) --- ...approve-actor-and-codec-driver-boundary.md | 66 +++++++++++++------ 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md index 3670992f..862cfdde 100644 --- a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md +++ b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md @@ -63,7 +63,7 @@ sections below. The existing `Packet` trait composed with `EncodeWith` already expresses "a packet that can be serialized"; `Envelope` satisfies both. Adding a bridging trait is ADR 010's rejected Option C and is corroborated as - unnecessary by prior art (see `Artifacts and notes`). + unnecessary by prior art (see `Artefacts and notes`). ## Constraints @@ -161,11 +161,15 @@ edit and its propagation can be reviewed independently. - Observation: The "sole owner" goal of ADR 010 is already substantially met in code on the outbound path. - Evidence: `rg -n "\.wrap_payload\(" src/` shows exactly one non-test + Evidence: a path-aware inventory that excludes examples, tests, test helpers, + and testkit — + `rg -n "\.wrap_payload\(" src/ -g '!**/tests.rs' -g '!**/tests/**' -g + '!**/testkit/**' -g '!**/examples.rs' -g '!**/examples/**' -g + '!**/test_helpers/**' -g '!**/test_support.rs'` — returns exactly one production caller, `src/app/outbound_encoding.rs:36` - (`codec.wrap_payload(Bytes::from(bytes))`); all other matches are under - `*/tests.rs`, `src/codec/examples.rs`, `src/test_helpers/`, or - `src/testkit/`. + (`codec.wrap_payload(Bytes::from(bytes))`); the excluded non-production + matches live under `src/codec/tests.rs`, `src/codec/tests/property/`, and + `src/testkit/support.rs`. Impact: `10.1.3` is genuinely a decision-closure item. The remaining work is to write the boundary down precisely and dispose of the test-only bridges, not to relocate production framing logic. @@ -178,8 +182,10 @@ edit and its propagation can be reviewed independently. roadmap `11.1.2` / issue #538 rather than implying `10.1.3` removes it. - Observation: The plan's preflight call-site inventory still holds at execution time. - Evidence: on 2026-06-24, - `rg -n "\.wrap_payload\(" src/ | grep -v -i test` returned only + Evidence: on 2026-06-24, the path-aware inventory + `rg -n "\.wrap_payload\(" src/ -g '!**/tests.rs' -g '!**/tests/**' -g + '!**/testkit/**' -g '!**/examples.rs' -g '!**/examples/**' -g + '!**/test_helpers/**' -g '!**/test_support.rs'` returned only `src/app/outbound_encoding.rs:36: let frame = codec.wrap_payload(Bytes::from(bytes));`. Impact: the ADR can safely state the codec driver is the only production @@ -338,7 +344,7 @@ This section assumes no prior knowledge of the repository. ### The governing documents - [`docs/adr-010-transport-frame-boundary-for-zero-copy.md`](../adr-010-transport-frame-boundary-for-zero-copy.md) - — the decision to accept; currently `Proposed`. + — the accepted decision; now `Accepted`. - [`docs/frame-vec-u8-inventory.md`](../frame-vec-u8-inventory.md) — the source inventory; its "Resolved direction for epic 284" and ADR list reference ADR 010. @@ -433,13 +439,22 @@ complete `Outcomes & retrospective`. Run all commands from the repository root (`.`). -1. Confirm the call-site inventory still holds before writing the ADR claim: +1. Confirm the call-site inventory still holds before writing the ADR claim. + Exclude every non-production path explicitly (examples, tests, test helpers, + and testkit) rather than a case-insensitive `test` filter, which would drop a + production path that merely contains "test": ```bash - rg -n "\.wrap_payload\(" src/ | grep -v -i test + rg -n "\.wrap_payload\(" src/ \ + -g '!**/tests.rs' -g '!**/tests/**' -g '!**/testkit/**' \ + -g '!**/examples.rs' -g '!**/examples/**' \ + -g '!**/test_helpers/**' -g '!**/test_support.rs' ``` - Expected: a single line, `src/app/outbound_encoding.rs:36: ... codec.wrap_payload(Bytes::from(bytes));`. + Expected: a single line, + `src/app/outbound_encoding.rs:36: let frame = codec.wrap_payload(Bytes::from(bytes));`. + The excluded non-production matches live under `src/codec/tests.rs`, + `src/codec/tests/property/`, and `src/testkit/support.rs`. 2. Apply Stage B edits, then: @@ -451,17 +466,27 @@ Run all commands from the repository root (`.`). Commit with a message recording acceptance of ADR 010 and resolution of its Outstanding Decisions. -3. Apply Stage C edits, then re-run `make markdownlint`, confirm no document - still calls ADR 010 proposed: +3. Apply Stage C edits, then re-run `make markdownlint`, and assert that no + governing document still calls ADR 010 proposed. The assertion filters out + this ExecPlan's own risk/validation prose and the ADR's preserved proposal + history (dual dates, rejected options), then fails if anything else survives: ```bash - rg -ni "adr.?010|transport.frame boundary" docs/ | rg -i "propos" + if rg -ni "adr.?010|transport.frame boundary" docs/ \ + | rg -i "propos" \ + | rg -v -e "execplans/10-1-3-approve-actor-and-codec-driver-boundary\.md" \ + -e "adr-010-transport-frame-boundary-for-zero-copy\.md" \ + | grep -q .; then + echo "FAIL: a governing document still describes ADR 010 as proposed" + exit 1 + fi + echo "OK: no governing document describes ADR 010 as proposed" ``` - Expected: no governing document still describes ADR 010 as proposed. Matches - inside this ExecPlan's risk/validation text, or inside preserved ADR proposal - history such as dual dates and rejected options, are not cross-reference - drift. Stage and commit the propagation edits. + Expected: the assertion prints `OK` and exits 0. The only remaining matches + are this ExecPlan's risk/validation text and the ADR's preserved proposal + history, which are not cross-reference drift. Stage and commit the + propagation edits. 4. Run the commit gateway (documentation-only change, but the full suite must stay green): @@ -494,7 +519,10 @@ Acceptance is behaviour a reviewer can verify: Decisions, each linking a phase-11 roadmap item. 2. `docs/roadmap.md` line for `10.1.3` and the zero-copy migration roadmap line for `1.1.3` (and children) render checked. -3. `rg -ni "adr.?010" docs/ | rg -i "propos"` returns nothing. +3. The path-aware stale-reference assertion in `Concrete steps` step 3 prints + `OK` and exits 0: once this ExecPlan's risk/validation prose and the ADR's + preserved proposal history are excluded, no governing document describes ADR + 010 as proposed. 4. `make markdownlint`, `make check-fmt`, `make lint`, and `make test` each exit 0; their `tee` logs in `/tmp` show success. 5. The automated review reports no unresolved concerns. From f3138982e4530dce9a7ca923d49d15f77090d904 Mon Sep 17 00:00:00 2001 From: leynos Date: Tue, 21 Jul 2026 01:01:22 +0200 Subject: [PATCH 11/12] Narrow ADR 010 stale-reference assertion in ExecPlan Address review feedback on the 10.1.3 ExecPlan's validation: - Add a positive check that the ADR declares Status: Accepted, so the assertion verifies acceptance rather than only the absence of stale "proposed" references. - Stop excluding the entire ADR file from the cross-reference scan; exclude only the documented preserved dual-date proposal-history line. A future stale status or governing reference elsewhere in the ADR is now caught again instead of masked by a whole-file exclusion. - Update the matching Validation and acceptance criterion to describe both the positive status check and the narrowed exclusion consistently. Docs-only. make check-fmt, lint, typecheck, test, and markdownlint pass. Co-Authored-By: Claude Opus 4.8 (1M context) --- ...approve-actor-and-codec-driver-boundary.md | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md index 862cfdde..52341977 100644 --- a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md +++ b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md @@ -466,27 +466,39 @@ Run all commands from the repository root (`.`). Commit with a message recording acceptance of ADR 010 and resolution of its Outstanding Decisions. -3. Apply Stage C edits, then re-run `make markdownlint`, and assert that no - governing document still calls ADR 010 proposed. The assertion filters out - this ExecPlan's own risk/validation prose and the ADR's preserved proposal - history (dual dates, rejected options), then fails if anything else survives: +3. Apply Stage C edits, then re-run `make markdownlint`. Assert two things: that + the ADR itself declares acceptance, and that no governing document still + calls ADR 010 proposed. The stale-reference scan excludes only this + ExecPlan's own risk/validation prose and the ADR's documented preserved + proposal-history line (the dual `Proposed`/`Accepted` dates), so a future + stale status or governing reference elsewhere in the ADR is still caught: ```bash + adr=docs/adr-010-transport-frame-boundary-for-zero-copy.md + + # 1. The ADR must declare acceptance in its Status section. + if ! rg -Uq "## Status\n\nAccepted\b" "$adr"; then + echo "FAIL: ADR 010 does not declare Status: Accepted" + exit 1 + fi + + # 2. No governing document may still call ADR 010 proposed. Exclude this + # ExecPlan's own prose and the ADR's preserved dual-date line only. if rg -ni "adr.?010|transport.frame boundary" docs/ \ | rg -i "propos" \ | rg -v -e "execplans/10-1-3-approve-actor-and-codec-driver-boundary\.md" \ - -e "adr-010-transport-frame-boundary-for-zero-copy\.md" \ + -e "Proposed 2026-04-12\. Accepted 2026-06-22\." \ | grep -q .; then echo "FAIL: a governing document still describes ADR 010 as proposed" exit 1 fi - echo "OK: no governing document describes ADR 010 as proposed" + echo "OK: ADR 010 is Accepted and no governing document calls it proposed" ``` - Expected: the assertion prints `OK` and exits 0. The only remaining matches - are this ExecPlan's risk/validation text and the ADR's preserved proposal - history, which are not cross-reference drift. Stage and commit the - propagation edits. + Expected: both checks pass and the script prints `OK` and exits 0. The scan + still fails on any other ADR line, or any other document, that ties a + governing ADR 010 reference to "proposed". Stage and commit the propagation + edits. 4. Run the commit gateway (documentation-only change, but the full suite must stay green): @@ -519,10 +531,10 @@ Acceptance is behaviour a reviewer can verify: Decisions, each linking a phase-11 roadmap item. 2. `docs/roadmap.md` line for `10.1.3` and the zero-copy migration roadmap line for `1.1.3` (and children) render checked. -3. The path-aware stale-reference assertion in `Concrete steps` step 3 prints - `OK` and exits 0: once this ExecPlan's risk/validation prose and the ADR's - preserved proposal history are excluded, no governing document describes ADR - 010 as proposed. +3. The assertion in `Concrete steps` step 3 passes: the ADR declares + `Status: Accepted`, and — once this ExecPlan's risk/validation prose and the + ADR's preserved dual-date proposal-history line are excluded — no governing + document, including any other line of the ADR, describes it as proposed. 4. `make markdownlint`, `make check-fmt`, `make lint`, and `make test` each exit 0; their `tee` logs in `/tmp` show success. 5. The automated review reports no unresolved concerns. From 2c69c0b492048db37f450dcb762163dc526bea12 Mon Sep 17 00:00:00 2001 From: leynos Date: Tue, 21 Jul 2026 10:54:11 +0200 Subject: [PATCH 12/12] Scope ADR 010 date exclusion to the ADR path in ExecPlan Address review feedback on the 10.1.3 ExecPlan's stale-reference scan: - Restrict the preserved dual-date exclusion to the ADR 010 document path by anchoring it to `adr-010-...md::` in the ripgrep filter, instead of matching the dual-date text in any document. - The exact dual-date proposal-history line is still excepted within the ADR, but the same "Proposed .. Accepted .." text in any other governing document now remains detectable as drift. - Clarify the accompanying comment to state the exception is scoped to the ADR's own path. Docs-only. make check-fmt, lint, typecheck, test, and markdownlint pass. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../10-1-3-approve-actor-and-codec-driver-boundary.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md index 52341977..0bb88d2e 100644 --- a/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md +++ b/docs/execplans/10-1-3-approve-actor-and-codec-driver-boundary.md @@ -483,11 +483,14 @@ Run all commands from the repository root (`.`). fi # 2. No governing document may still call ADR 010 proposed. Exclude this - # ExecPlan's own prose and the ADR's preserved dual-date line only. + # ExecPlan's own prose and, only within the ADR's own path, its + # preserved dual-date line; the same dates in any other document stay + # detectable. if rg -ni "adr.?010|transport.frame boundary" docs/ \ | rg -i "propos" \ - | rg -v -e "execplans/10-1-3-approve-actor-and-codec-driver-boundary\.md" \ - -e "Proposed 2026-04-12\. Accepted 2026-06-22\." \ + | rg -v \ + -e "execplans/10-1-3-approve-actor-and-codec-driver-boundary\.md" \ + -e "adr-010-transport-frame-boundary-for-zero-copy\.md:[0-9]+:Proposed 2026-04-12\. Accepted 2026-06-22\." \ | grep -q .; then echo "FAIL: a governing document still describes ADR 010 as proposed" exit 1