Files
glm-5.3-flash e196ed43e3 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
2026-11-03 19:31:53 +00:00

7.5 KiB
Raw Permalink Blame History

ADR-013: The Targeted Fork: fast-socks5's T-Generic Subset Is Owned, Not Vendored

Status

Accepted (2026-09-22, post-extraction-review; supersedes the ADR-011 maintenance posture; ADR-011 stays for the extraction mechanics and the cut table; the ADR-011 §Amendment is subsumed here)

Context

ADR-011 pinned the inline-vendor posture as extraction (the T-generic subset copied in-tree, kernel-net region not copied; the net gate dissolving), and the vendor group (five implementation tasks plus the review gate) landed it in commits 57b107b..5b18d4d, with the review (tasks/implementation/ review-vendor-extraction.md) as the fidelity gate: the file-by-file diff vs /workspace/fast-socks5 v1.0.0 categorizes every hunk, and every review criterion passed.

The review also made the maintenance posture's cost visible. The tree is now permanently diverged from upstream in five categories:

  1. The extraction cut: the kernel-net region, socks4, the legacy Config/Authentication layer, Socks5Datagram, the convenience dialers, the DNS helper: gone.
  2. The carried changes: BIND's reply surface, the published new_reply.
  3. The panic translations: ReplyError::from_u8 (the review's F-1), use_password_auth, reply_error's parse.
  4. The error-pruning adjustments: anyhow/log/async-trait out, error variants pruned, MissingTargetAddr added.
  5. The lint-allow posture: module-level #[allow]s preserving upstream style (u8::max_value(), needless lifetimes, match_like_matches_macro, io_other_error, wrong_self_ convention, the F-4 verbatim string) to keep the diff mechanical.

Category 5 exists solely to keep categories 1–4 reconcilable by a line-based diff. But a future re-base against an upstream release was never going to be a clean mechanical diff again; it was always going to be manual reconciliation across all five categories. The vendor posture's maintenance apparatus (verbatim preservation, the lint allows, the re-vendor/adjustment-list discipline) pays a permanent tax to serve a re-base path that would never be used.

The "vendor" framing also produced a real defect: the review's F-1 (ReplyError::from_u8's upstream unreachable!() arm kept verbatim; wire-reachable, a misbehaving peer could panic the consumer task) escaped precisely because the vendor posture maintained a second, weaker instruction set ("verbatim + adjustments list" instead of "project conventions, unconditionally"). The fidelity-vs-conventions tension is structural to the vendor framing; the review caught the escape, but the seam itself was the vendor framing's.

The fork point is now, post-review and post-F-1, the cleanest line the tree will ever present: the extraction provenance is in git history (57b107b..5b18d4d), the review is the recorded fidelity gate, and the five divergence categories are documented in ADR-011, vendor.md, and the review task. "The tree as of the review commit (5b18d4d) is the fork point" is a trivially defensible line.

Decision

  • The extracted region is a targeted fork, fully owned by this crate. The "vendor" framing is retired: there is no upstream tree to stay reconcilable with, no re-vendor, no adjustment-list apparatus, no second instruction set. Project conventions (the AGENTS.md set) apply unconditionally to the forked code.
  • The fork point is the tree as of commit 5b18d4d (the extraction review's gate commit). The extraction provenance is carried in git history (57b107b..5b18d4d), the module docs, and the extended LICENSE notice; the review task is the recorded fidelity gate.
  • Module naming: the forked core is src/rfc1928/, re-exported as alksocks::rfc1928. "vendor" names an ownership relation (now gone); "socks5" would stutter with the crate name (alksocks::socks5) and collide with the future module structure (the producer/consumer/adapter layers are also SOCKS5-shaped). rfc1928 names what the module is (the RFC 1928 wire vocabulary and the state machines), permanent and collision-free.
  • The lint-allow posture dissolves. The module-level #[allow]s and the "verbatim lint posture" module-doc paragraphs are removed; the suppressed smells are fixed per project conventions: u8::max_value() → u8::MAX, needless lifetimes elided, match_like_matches_macro applied, io::Error::new(Other) → io::Error::other, wrong_self_convention fixed on AuthMethod:: new(self, ..), the F-4 string re-worded (it no longer names a cut function), and the #[allow(dead_code)] on AuthenticationMethod swept with actual usage. Upstream's commented-out dead code stays dropped (F-2).
  • The license mechanics: MIT permits sublicensing, so modifications after the fork point are this project's under the crate license (MIT OR Apache-2.0, per Cargo.toml). The bundled notice is extended, not replaced: upstream MIT text + copyright (the notice-preservation obligation, perpetual) + a fork-point statement + the modification note.
  • The reference checkout survives as a behavioral reference. /workspace/fast-socks5 stays for differential testing of RFC edge cases; the differential suite (tests/rfc1928-differential.rs) pins bytes, not upstream text, so it survives the rename untouched. Textual-diff discipline is retired; behavioral differential testing is retained.
  • The cut table is re-read as the not-forked inventory, the map of what to hand-port if a future need surfaces (e.g. the kernel-net region for a standalone vanilla-server example). The hand-port path replaces the re-vendor path: port against the reference checkout, adapt to the crate's conventions, and let the suite guard it.
  • The honest cost: the cheap upstream-fix path closes. A future fast-socks5 fix (a reply-code mapping correction, a codec fix) arrives as a hand-port against the reference checkout, not a diff absorb. Risk is assessed low; fast-socks5 is a quiet project, and the extracted surface is the well-trodden RFC 1928 path.

Consequences

  • Positive: one instruction set (project conventions, unconditionally); the lint-allow tax and the adjustment-list apparatus dissolve; smells are fixed at the only cost that matters: a one-time cleanup verified by the existing suite. The F-1 seam class (conventions-vs-fidelity gaps) is closed structurally.
  • Positive: the module name is stable for the crate's future (no alksocks::socks5 stutter, no socks5::producer collision pressure).
  • Negative (accepted): the cheap upstream-fix path closes; a future upstream fix is a hand-port against the reference checkout, guarded by the differential suite. Assessed low-risk (quiet upstream, well-trodden RFC surface).
  • Neutral: the differential suite survives the rename untouched (it pins bytes, not upstream text). /workspace/fast-socks5 keeps its role as the behavioral reference; the only thing it loses is being the target of a line-based diff.
  • Neutral: the fork-point line (5b18d4d) is recorded in git history, the module docs, and the extended LICENSE notice; the extraction provenance (the ADR-011 trail) remains readable.

References

  • ADR-011 (the extraction mechanics, the cut table, the carried changes; the mechanics remain authoritative), ADR-002 (the protocol base), ADR-009 (feature gates, no net feature)
  • tasks/implementation/review-vendor-extraction.md (the fidelity gate + F-1), docs/architecture/rfc1928.md (the owned-core spec)
  • /workspace/fast-socks5 (v1.0.0, MIT, the behavioral reference for differential testing)