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

- Rewrote em dash prose across the whole tree outside docs/reviews/
  (the historical reviews stay verbatim, matching the alktunnels and
  alktty precedent): src doc comments and inline comments (587),
  docs/architecture (319), docs/research + sdd_process (484), tests
  (361), tasks (899), fuzz (28), README/CHANGELOG/Cargo.toml (77),
  AGENTS.md (85), and the .opencode/agents prompts (109)
- Fenced content follows the precedent: comments, ASCII-diagram label
  separators, and template placeholders rewritten; wire data, JSON/BAST
  documents, byte diagrams, and transcripts survive verbatim; assert,
  expect, panic, error-display, and format message literals rewritten
  as prose; no code, fixture, or test data change
- src/rfc1928/LICENSE: the two dashes in alksocks' own provenance
  header rewritten; the MIT legal text untouched
- AGENTS.md adds Project Convention 18: no em dashes in prose; varied
  restructure, no spaced-hyphen substitutes, fenced prose rule, en
  dash numeric ranges exempt, docs/reviews/ exempt from the greps
- tasks/*.md frontmatter: the name values rewritten by the sweep are
  now quoted (a raw colon inside an unquoted YAML scalar parsed as
  null); taskgraph validate reports 37 tasks, no issues

Verification: cargo test; cargo clippy --all-targets -D warnings;
cargo fmt --check; cargo doc --no-deps; fuzz corpus replay
(cargo test --manifest-path fuzz/shared/Cargo.toml); wasm check and
clippy for wasm32-unknown-unknown with -D warnings; em dash grep over
the repo returns matches only in docs/reviews/ and the bast.md BAST
JSON data fence
This commit is contained in:
glm-5.3-flash committed 2026-11-03 19:31:53 +00:00
1 parent 9ca8c52601
commit e196ed43e3
115 files changed
+3593 -3531

No files matched your search

+6 -6
View File
@@ -5,19 +5,19 @@ libFuzzer targets for alksocks' wire surfaces (see
## Layout
- `fuzz_targets/` — one binary per target; thin `fuzz_target!` wrappers.
- `shared/` — the invariant logic, as a plain library so normal
- `fuzz_targets/`: one binary per target; thin `fuzz_target!` wrappers.
- `shared/`: the invariant logic, as a plain library so normal
`cargo test` (stable toolchain) can replay the committed corpora
through the same invariants (`fuzz/shared/src/*.rs` `#[cfg(test)]`
modules; quinn's CI pattern). The fuzz binaries are nightly-only;
the shared crate is stable-clean.
- `corpus/<target>/` — committed hand-made seeds (regenerate with
- `corpus/<target>/`: committed hand-made seeds (regenerate with
`python3 fuzz/gen_fuzz_seeds.py` from the repo root). Grown corpora
and artifacts are gitignored.
- `run-detached.sh` — mandatory runner for agent sessions: wraps
- `run-detached.sh`: mandatory runner for agent sessions; wraps
`cargo fuzz run` in `setsid` + `nohup` + log redirection so an OOM
in a target can never take down the agent host (research doc §5).
- `json.dict` — JSON token dictionary for the params target.
- `json.dict`: JSON token dictionary for the params target.
## Targets
@@ -31,7 +31,7 @@ libFuzzer targets for alksocks' wire surfaces (see
`cargo fuzz build` and `cargo fuzz run` must be executed with `fuzz/`
(or deeper) as the working directory so rustup selects the pinned
nightly toolchain — the detached runner handles that itself.
nightly toolchain; the detached runner handles that itself.
```sh
# build (nightly, pinned by rust-toolchain.toml inside fuzz/; run from fuzz/)
+1 -1
View File
@@ -81,7 +81,7 @@ def datagram_codec_seeds():
# The joint-bound max-domain shape: a legal RFC payload that would
# overflow the u16 (65507 to a 255-char domain = 65766). The frame
# itself can never carry that length field — encode the closest
# itself can never carry that length field, so encode the closest
# wire-legal shape (0xFFFF declared with the max-domain body) for
# the decode walk; the encode-side 65766 rejection is pinned in
# the shared invariants.
+1 -1
View File
@@ -1,4 +1,4 @@
//! `Arbitrary` support for `serde_json::Value` — a bounded-depth
//! `Arbitrary` support for `serde_json::Value`: a bounded-depth
//! recursive generator shared by the semantic targets. Depth and size
//! bounds keep exec/s high (serde_json's own 128-depth recursion limit
//! is the decode-side guard; this generator explores structure).
+11 -11
View File
@@ -35,7 +35,7 @@ fn probe_addr() -> TargetAddr {
pub fn fuzz_datagram_codec(data: &[u8]) {
// The infallible reassembly direction: any chunk sequence feeds
// cleanly. Drive the reader with the whole input and with awkward
// 3-byte slices — splitting transparency must hold for both.
// 3-byte slices; splitting transparency must hold for both.
let mut whole = DatagramReader::new();
let whole_dgs = whole.feed(data);
assert_retained_bound(&whole, data.len());
@@ -117,7 +117,7 @@ pub fn fuzz_datagram_codec(data: &[u8]) {
// Re-frame round-trip: for input that is a concatenation of
// complete frames, parsing then re-framing reproduces the frames
// byte-for-byte — except a `len == 0` frame, which is well-framed
// byte-for-byte, except for a `len == 0` frame, which is well-framed
// but decodes to `Err(EmptyFrame)` (protocol garbage; it has no
// addr to re-frame). The frame count holds over every frame; the
// byte-for-byte re-frame holds over the decodable ones.
@@ -136,7 +136,7 @@ pub fn fuzz_datagram_codec(data: &[u8]) {
}
Err(WireError::EmptyFrame) => {
// The frame-walk must agree this is a `len == 0`
// frame — the only zero-inner-byte shape.
// frame: the only zero-inner-byte shape.
let declared = u16::from_be_bytes([frame_bytes[0], frame_bytes[1]]) as usize;
assert_eq!(declared, 0);
assert_eq!(frame_bytes.len(), 2);
@@ -147,7 +147,7 @@ pub fn fuzz_datagram_codec(data: &[u8]) {
// A well-framed frame can decode to the address
// garbage shapes: the declared length carried a
// too-short, non-UTF-8, or unknown-ATYP addr
// region. The decode refused the addr — the only
// region. The decode refused the addr, so the only
// re-frame possible is the raw frame itself, which
// the count/prefix walks above already pin.
}
@@ -159,7 +159,7 @@ pub fn fuzz_datagram_codec(data: &[u8]) {
}
// Frame direction: the joint bound exactly at the edge, with the
// sizes echoed — including the 65766 max-domain shape (a legal RFC
// sizes echoed, including the 65766 max-domain shape (a legal RFC
// payload that would overflow the u16 length field).
let max_payload = MAX_INNER_LEN - addr_encoding_len(&probe_addr());
let framed = frame(&probe_addr(), &vec![0u8; max_payload]).expect("exact limit is legal");
@@ -214,7 +214,7 @@ pub fn fuzz_datagram_codec(data: &[u8]) {
// Mid-frame observability: after the final feed, the reader is
// mid-frame exactly when the input ends inside a frame (a partial
// frame beyond the 2-byte header; a dangling 1-byte header
// fragment is NOT mid-frame — the header is not yet consumed).
// fragment is NOT mid-frame: the header is not yet consumed).
let expected_mid = ends_inside_frame(data, well_framed_len);
assert_eq!(
whole.is_mid_frame(),
@@ -236,7 +236,7 @@ fn result_shapes(dgs: &[Result<(TargetAddr, bytes::Bytes), WireError>]) -> Vec<S
.collect()
}
/// A cheap digest stand-in: length + first/last bytes — enough to pin
/// A cheap digest stand-in: length + first/last bytes, enough to pin
/// equality across the split feeds.
fn digest(payload: &[u8]) -> u64 {
let mut h = payload.len() as u64;
@@ -251,7 +251,7 @@ fn digest(payload: &[u8]) -> u64 {
/// Walk the framing exactly as the decoder does: complete frames from
/// the start; the walk stops at the first frame that overruns the
/// input. Returns the frames and the byte length they occupy — the
/// input. Returns the frames and the byte length they occupy: the
/// remainder (if any) is a partial/trailing region.
fn split_frames(data: &[u8]) -> (Vec<&[u8]>, usize) {
let mut frames = Vec::new();
@@ -269,12 +269,12 @@ fn split_frames(data: &[u8]) -> (Vec<&[u8]>, usize) {
}
/// Count complete, well-formed-address frames whose payload region is
/// empty — the only source an empty-payload datagram may come from
/// empty: the only source an empty-payload datagram may come from
/// (the F-2 walk, alktunnels' count_empty_frames shape adapted to the
/// `(addr, payload)` inner structure: a frame's empty payload needs
/// `declared == addr_len`, not `declared == 0`). Domain-form frames
/// must also carry a valid-UTF-8 domain: the codec validates UTF-8
/// before the payload split — a non-UTF-8 domain with an empty payload
/// before the payload split, so a non-UTF-8 domain with an empty payload
/// region surfaces as `DomainNotUtf8`, never as an empty datagram.
fn count_empty_payload_frames(data: &[u8]) -> usize {
let mut count = 0usize;
@@ -315,7 +315,7 @@ fn ends_inside_frame(data: &[u8], well_framed_len: usize) -> bool {
// Mid-frame iff the well-framed prefix leaves a *parsed but
// incomplete* frame: a remainder ≥ 2 bytes means the length header
// was consumed and the frame is in flight (a remainder of 1 byte
// is a buffered header fragment — not yet a frame in flight).
// is a buffered header fragment, not yet a frame in flight).
let remainder = data.len() - well_framed_len;
remainder >= 2
}
+5 -5
View File
@@ -31,12 +31,12 @@ pub fn fuzz_params_parse(data: &[u8]) {
}
fn parse_shapes(value: &Value) {
// The trivial params: the canonical form is `{}` — it parses and
// The trivial params: the canonical form is `{}`; it parses and
// round-trips to the canonical form. Unknown fields reject loudly
// (the serde pin and the schema's additionalProperties agree —
// (the serde pin and the schema's additionalProperties agree;
// ADR-001). NOTE the serde reality the harness must model: a
// fieldless struct deserializes from ANY empty JSON composite
// (the seq form `[]` included) — the wire's `type: object` input
// (the seq form `[]` included), but the wire's `type: object` input
// schema (the registry's gate) is what keeps the non-object forms
// from ever reaching the type; the serde pin is the second gate.
let parses = serde_json::from_value::<Socks5Params>(value.clone()).is_ok();
@@ -54,7 +54,7 @@ fn parse_shapes(value: &Value) {
assert_ne!(
value,
&serde_json::json!({}),
"the empty object must parse — anything else must reject"
"the empty object must parse; anything else must reject"
);
}
@@ -102,7 +102,7 @@ fn parse_shapes(value: &Value) {
// The reason surface is a pass-through extraction, not a validated
// table: Some(details.reason) iff the code is channel:open_failed
// and the reason is a string — any string surfaced as-is (the
// and the reason is a string; any string is surfaced as-is (the
// alktunnels harness-model finding #2, the modeled contract).
let code = value
.get("code")
+4 -4
View File
@@ -1,7 +1,7 @@
//! Invariants for the forked RFC 1928 core (`src/rfc1928/`, ADR-013 —
//! Invariants for the forked RFC 1928 core (`src/rfc1928/`; ADR-013:
//! fully owned code): no-panic on any byte sequence across the whole
//! handshake state machine, every malformed shape is a typed error
//! (the F-1 class — wire bytes must never reach `unreachable!()`),
//! (the F-1 class: wire bytes must never reach `unreachable!()`),
//! round-trips for well-formed messages, and the full-domain
//! reply-code table. Both protocol directions are covered: the server
//! typestate (the producer drives it against consumer bytes) and the
@@ -80,7 +80,7 @@ async fn fuzz_read_address(data: &[u8]) {
}
}
Err(err) => {
// Typed failure — fine; the ATYP gate maps unknown
// Typed failure: fine; the ATYP gate maps unknown
// types to IncorrectAddressType (the F-1 class).
if let AddrError::IncorrectAddressType = err {
assert!(
@@ -191,7 +191,7 @@ async fn fuzz_udp_header(data: &[u8]) {
/// `ReplyError::from_u8` over the full u8 domain: total, no panic,
/// unassigned codes map to the GeneralFailure catch-all (the F-1
/// pin — the direct probe of the class the fork already fixed).
/// pin, the direct probe of the class the fork already fixed).
fn fuzz_reply_table(data: &[u8]) {
for &code in data {
let reply = ReplyError::from_u8(code);