docs(arch): alknet-tty spec sanity-check fixes — TtyControlHandle newtype (C1), backend cleanup contract (W1, ADR-056), clarifications (S1-S5)
C1: Box<dyn TtyControl + Clone> does not compile (Clone is not object-safe). Replace with a TtyControlHandle newtype: #[derive(Clone)] wrapping Arc<dyn TtyControl + Send + Sync>. The trait stays object-safe; the newtype carries the Clone-ability. Updated across tty-backend.md, ADR-053, OQ-43, and the tty README. W1: 'Drop is the cleanup, threads exit on channel close' was false for the local PTY waiter thread (blocked in Child::wait(), does not observe channel close) — a child that ignores stdin EOF would be orphaned on session cancel. New ADR-056 commits a backend cleanup contract: dropping the exit_code future MUST kill the session target. The local backend implements it via a ChildKiller held in the exit_code future's Drop guard (disarmed on resolve). Corrected the lifecycle section in tty-adapter.md, added the mechanism + constraint to tty-local.md, and referenced ADR-056 from tty-backend.md, overview.md, both READMEs. S1: error-frame < 16 MiB stated as a wire-format invariant (not an assumption) so the 0x00-first-byte disambiguation trick is sound by construction. S2: carriage field validation (MUST be "raw" in v1, else malformed_negotiation) specified. S3: NegotiateRequest + TerminalParamsWire Rust structs added with serde defaults and validation rules. S4: modes field annotated 'backends MUST ignore content in v1' in both tty-backend.md and ADR-053. S5: AsyncWrite/Stream qualified with crate origins (tokio::io, futures_core) in the TtyHandle struct definitions.
This commit is contained in:
1 parent
b90d717ac2
commit
25f0f55592
11 files changed
+594
-92
No files matched your search
@@ -6,18 +6,22 @@
|
||||
shape open question the local-PTY POC resolved).
|
||||
- **Status**: resolved
|
||||
- **Door type**: One-way (the `TtyControl` trait shape is part of the
|
||||
`TtyBackend` API surface — ADR-053), two-way (the concrete `Clone`
|
||||
newtype mechanism)
|
||||
`TtyBackend` API surface — ADR-053), two-way (the concrete
|
||||
`TtyControlHandle` newtype mechanism)
|
||||
- **Priority**: medium
|
||||
- **Resolution**: `TtyHandle.control` is
|
||||
`Option<Box<dyn TtyControl + Send + Unpin + Clone>>`. The `Clone`
|
||||
trait-object bound is satisfied via an `Arc`-backed `Clone` newtype: a
|
||||
small struct holding `Arc<dyn TtyControlInner>` where `TtyControlInner:
|
||||
Send + Sync` has the `resize`/`signal` methods, and the public
|
||||
`TtyControl` newtype implements `Clone` by cloning the `Arc`. The
|
||||
local-PTY POC used a concrete `PtyControl` struct (inherently `Clone` —
|
||||
it held `Arc<Mutex<...>>` fields); the trait-object form generalizes it
|
||||
so a backend can produce its own control type without the adapter
|
||||
- **Resolution**: `TtyHandle.control` is `Option<TtyControlHandle>`.
|
||||
`TtyControlHandle` is a concrete `#[derive(Clone)]` newtype wrapping
|
||||
`Arc<dyn TtyControl + Send + Sync>`; the adapter clones the `Arc` to
|
||||
hand a handle to the spawned control-chunk dispatcher. The
|
||||
`TtyControl` trait itself is NOT `Clone` — `Clone` is not object-safe
|
||||
(`fn clone(&self) -> Self` returns `Self`, which forbids `dyn`
|
||||
dispatch), so `Box<dyn TtyControl + Clone>` does not compile. The
|
||||
design splits the concerns: the trait stays object-safe (`Send +
|
||||
Sync`, no `Clone`); the newtype carries the `Clone`-ability. The
|
||||
local-PTY POC used a concrete `PtyControl` struct (inherently `Clone`
|
||||
— it held `Arc<Mutex<...>>` fields); the newtype generalizes the POC's
|
||||
shape so a backend produces its own control type via
|
||||
`TtyControlHandle::new(Arc::new(MyControl))` without the adapter
|
||||
knowing the concrete shape. The `Clone` constraint exists because the
|
||||
adapter's control-chunk dispatcher needs to be handed off to the
|
||||
spawned pump task (the POC's `session::drive_session` clones
|
||||
|
||||
Reference in new issue
Block a user