docs: remove em dashes from repo prose and forbid them going forward

- Rewrote ~1090 em dashes across docs/ (excluding docs/reviews/
  history), README, CHANGELOG, and .opencode/agents prompts with varied
  restructures (colons, semicolons, parentheses, commas, sentence
  splits); ADR decisions, status lines, wire-shape examples, and code
  fences preserved
- Rewrote 234 em dashes in src doc comments plus a handful of existing
  inline comments and one test assert message; no code, JSON literals,
  or wire shapes touched
- Added Project Convention 15: no em dashes in prose (doc comments,
  markdown, agent prompts, commit messages); restructure instead; no
  spaced hyphens as a substitute
Verification: cargo test; cargo clippy --all-targets -- -D warnings;
cargo fmt --check; cargo doc --no-deps; cargo test --all-features;
cargo test --manifest-path fuzz/shared/Cargo.toml; cargo check and
clippy for wasm32-unknown-unknown with -D warnings; em dash grep over
src + docs + agent prompts returns no matches outside docs/reviews/
This commit is contained in:
glm-5.3-flash committed 2026-11-01 13:11:32 +00:00
1 parent e9e01c04e1
commit 58da42a021
39 files changed
+1310 -1295

No files matched your search

+14 -14
View File
@@ -6,7 +6,7 @@ be][payload]`), a backend-agnostic `TtyBackend` trait, a
backend-agnostic producer adapter, and a typed consumer client.
A producer/consumer protocol crate on top of
[alkcall](https://crates.io/crates/alkcall) channels — no networking, no
[alkcall](https://crates.io/crates/alkcall) channels: no networking, no
transport dependencies. Downstream crates (a `alknet-docker` or
`alknet-ssh` backend, a sandboxed TS/Python adapter) compose on top of
it: implement [`TtyBackend`](https://docs.rs/alktty/latest/alktty/trait.TtyBackend.html)
@@ -14,7 +14,7 @@ for your execution environment, and the adapter handles the wire.
## Quick start
### Producer — register backends and run the adapter
### Producer: register backends and run the adapter
```rust
use std::collections::HashMap;
@@ -27,11 +27,11 @@ backends.insert("local".into(), Arc::new(alktty::LocalTtyBackend::new()));
let tty_adapter = alktty::TtyAdapter::new(backends);
// tty_adapter implements alkcall::core::ProtocolHandler on the `alk/tty`
// ALPN — hand it to your transport accept loop:
// ALPN; hand it to your transport accept loop:
// tty_adapter.handle(connection, &auth).await
```
### Producer — via `alk/channels` instead of a dedicated ALPN
### Producer via `alk/channels` instead of a dedicated ALPN
```rust
use std::collections::HashMap;
@@ -44,10 +44,10 @@ let backends: HashMap<String, Arc<dyn alktty::TtyBackend>> =
// In your channels acceptor's `install_channel_zero` hook (per-connection):
// alktty::register_openable(&channel_core, Arc::new(backends), None, &mut registry, auth)
// Consumers open `channels/tty/sub`; the open op's params ARE the
// negotiation (ADR-009) — no second frame on the channel stream.
// negotiation (ADR-009); no second frame on the channel stream.
```
### Consumer — open a session over the direct ALPN
### Consumer: open a session over the direct ALPN
```rust
use alkcall::core::Connection;
@@ -73,14 +73,14 @@ session.close_stdin().await?;
let mut stdout = session.recv_stdout().await;
while let Some(bytes) = futures::StreamExt::next(&mut stdout).await {
// The stream ends on the zero-length stdout sentinel ("drained") —
// The stream ends on the zero-length stdout sentinel ("drained");
// it is never yielded as an item.
// ... render bytes ...
}
let code = session.wait().await?;
```
### Consumer — open a session via `alk/channels`
### Consumer: open a session via `alk/channels`
```rust
use alkcall::channels::client::ChannelClient;
@@ -106,14 +106,14 @@ both sides of a connection can be either):
| Role | Direct `alk/tty` | Via `alk/channels` |
|------|------------------|--------------------|
| **Producer** (runs backends, emits terminal bytes) | [`TtyAdapter`](https://docs.rs/alktty/latest/alktty/adapter/struct.TtyAdapter.html) as a `ProtocolHandler` — negotiation frame → access control → backend allocation → three-pump session driver | [`register_openable`](https://docs.rs/alktty/latest/alktty/channels/fn.register_openable.html) — the registry's ACL gates the open op; the handler spawns the same session driver pre-negotiated |
| **Consumer** (types input, renders output) | [`TtySession::connect_direct`](https://docs.rs/alktty/latest/alktty/struct.TtySession.html#method.connect_direct) — writes the negotiation frame, exposes typed stdin/stdout/stderr/control/exit methods | [`TtySession::open_via_channels`](https://docs.rs/alktty/latest/alktty/struct.TtySession.html#method.open_via_channels) — the open op's params are the negotiation |
| **Producer** (runs backends, emits terminal bytes) | [`TtyAdapter`](https://docs.rs/alktty/latest/alktty/adapter/struct.TtyAdapter.html) as a `ProtocolHandler`: negotiation frame → access control → backend allocation → three-pump session driver | [`register_openable`](https://docs.rs/alktty/latest/alktty/channels/fn.register_openable.html): the registry's ACL gates the open op; the handler spawns the same session driver pre-negotiated |
| **Consumer** (types input, renders output) | [`TtySession::connect_direct`](https://docs.rs/alktty/latest/alktty/struct.TtySession.html#method.connect_direct), which writes the negotiation frame and exposes typed stdin/stdout/stderr/control/exit methods | [`TtySession::open_via_channels`](https://docs.rs/alktty/latest/alktty/struct.TtySession.html#method.open_via_channels), where the open op's params are the negotiation |
One connection hosts many sessions (one per bidi stream on the direct
path, one per channel on the channels path); sessions are independent.
The wire format (ADR-001) is two carriages: a 4-byte
length-prefixed JSON negotiation frame, then raw chunks —
length-prefixed JSON negotiation frame, then raw chunks of the form
`[stream_type: u8][length: u32 be][payload]` with five stream types
(`STREAM_STDIN`=0 … `STREAM_CTRL_OUT`=4; see
[`alktty::wire`](https://docs.rs/alktty/latest/alktty/wire/index.html)).
@@ -126,7 +126,7 @@ document at `docs/architecture/tty-bast.md`.
### WASM target
The default crate (no features) compiles to `wasm32-unknown-unknown` —
The default crate (no features) compiles to `wasm32-unknown-unknown`;
this is what makes the downstream TS/Python adapter story work: a
wasm-compiled alktty is the protocol layer for a sandboxed adapter. The
`local` feature (the [`LocalTtyBackend`](https://docs.rs/alktty/latest/alktty/struct.LocalTtyBackend.html)
@@ -135,10 +135,10 @@ real OS and is non-wasm by design.
## Documentation
- [Architecture docs](docs/architecture/README.md) — the authoritative
- [Architecture docs](docs/architecture/README.md), the authoritative
spec: ADRs (001–009), the wire format, the backend trait contract,
and the local backend's cancel-cleanup semantics.
- [API docs](https://docs.rs/alktty) — full crate documentation on
- [API docs](https://docs.rs/alktty): full crate documentation on
docs.rs.
## License