Files
alkssh/tasks/implementation/w5-release-readiness.md
glm-5.3-flash f4b5f896b4 docs: sweep em dashes from all markdown prose
Renames the written-usage rule into practice across the contract surface:
docs/ (architecture, research, plans, sdd), tasks/ (all 43 task files,
taskgraph validate passes), AGENTS.md, README.md, CHANGELOG.md, and the
.opencode/agents/ prompts. Every replacement is a sense-preserving
rewrite (colons, semicolons, commas, parentheses, sentence splits, varied),
never a mechanical swap; no spaced hyphens were substituted. Enum fields,
frontmatter, tables, wire data, and cited identifiers survive verbatim;
en dashes inside numeric ranges keep their meaning.

Verification: taskgraph validate (43 tasks), repo grep clean (single
exempt hit: the verification command's own search pattern in AGENTS.md),
cargo test, clippy --all-targets -D warnings, fmt --check, doc all green.
2026-11-04 20:28:00 +00:00

232 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: w5-release-readiness
name: "Wave 5: release readiness (docs, feature matrix, CHANGELOG/README, dry-run)"
status: completed
depends_on: [w5-decline-matrix, w5-e2e-server, w5-e2e-client, w5-fuzz-harness]
scope: moderate
risk: low
impact: phase
level: implementation
---
## Description
Everything the publish needs except the publish itself
(`docs/plans/implementation.md` §Wave 5, the release-readiness
bullet; the alkgit `w5-release-readiness` shape):
- **Crate docs**: public-API rustdoc warning-free (default build +
`--all-features`; the pre-existing `client_ops.rs` private-link
warnings resolved or explicitly dispositioned); the docs-honesty
pass: module docs name each surface's postures and known limits
(the recorded limits ride the published docs: the `write_all`
no-deadline record, the PTY rule-5 fidelity limit, the port-0-only
mint wire fact, the no-reconnect-policy boundary, the no-accept-all
policy posture); crate-level docs state the feature graph and the
fail-closed invariant.
- **README.md**, which lands (none exists): what the crate is (the
two-direction door), the feature graph + the fail-closed posture
(a default build has no capabilities), minimal compile-checked
usage examples (a server mount + a dial), the custody/security
posture summary (vault-backed keys, no env vars, no secret
material on the wire), the license note.
- **CHANGELOG.md**: the 0.1.0 entry summarizing the plan's landing
per wave (the file exists; the entry lands).
- **The feature matrix**: `default` / each feature over it /
`--all-features`: test + clippy + doc green (the matrix runner
from `w5-decline-matrix` if it landed the vehicle, one command).
- **The publish dry-run**: `cargo publish --dry-run --allow-dirty`;
the packaged file list verified against the package policy (the
`exclude` list: the architecture docs ship as the authoritative
contract; the process surface (plans/research/reviews/tasks/
AGENTS.md/`.opencode`) does not); the manifest sanity (version
0.1.0, `rust-version` 1.89, edition 2024, license files present,
the pins as ADR-002 records them).
- **The freeze inventory**, the list of what the publish makes
one-way (the wire-relevant surfaces: the mapping contracts, the
honest-advertisement posture, the decline-matrix behavior, the
fingerprint string format, the russh pin's wire posture) recorded
for the gate's read, because the semver-relevant surface is frozen at
the
publish, so the gate reads this list against the landed code
before `w5-publish` executes.
## Acceptance Criteria
- [x] `cargo doc --no-deps` (+ `--all-features`) warning-free or
every residual dispositioned; the docs-honesty pass complete
(the known-limits records ride the published docs)
- [x] README.md landed (what/why, feature graph + fail-closed,
compile-checked examples, custody posture, license)
- [x] CHANGELOG.md's 0.1.0 entry landed
- [x] The feature matrix green (default / each feature /
`--all-features`: test + clippy + doc)
- [x] `cargo publish --dry-run --allow-dirty` clean; the packaged
file list verified against the package policy; manifest sanity
recorded
- [x] The freeze inventory recorded for the gate
## References
- docs/plans/implementation.md §Wave 5 (the release-readiness
bullet), §Scope authority (v0.1.0 publishes the crate)
- Cargo.toml (the package policy exclude list; the manifest ADR-002
landed), CHANGELOG.md, LICENSE-MIT / LICENSE-APACHE (present)
- docs/architecture/ (what ships as the authoritative contract),
docs/architecture/decisions/002-russh-pin.md (the pin the manifest
records)
- /workspace/@alkdev/alkgit (the sibling release shape: README,
CHANGELOG, the publish checklist's dry-run posture)
## Notes
**Crate docs.** `cargo doc --no-deps` is warning-free on both the
default build and `--all-features`. The pre-existing doc-link debt is
resolved (not dispositioned): 9 warnings (1 duplicate) at
`--all-features`: the `client_ops.rs` private-link class
(`crate::tty_map` / `crate::dispatch` / `crate::git_map`, private
modules; de-linked to backtick prose), the two
`rustdoc::redundant_explicit_links` spans (the `(client_ops::…)`
destinations on the `lib.rs` re-export docs and two
`[`TunnelChannel`](crate::TunnelChannel)` + `with_tunnel_surface` /
`KeySourceError::Decryption` same-item links in
`client_accept.rs`/`client_handler.rs`/`error.rs`), the broken
`TerminalParamsWire` path (now a resolution-correct target through
its wrapped re-export form) and the unresolved `Limits::…`
intra-doc link (now `crate::Limits::…`); plus the twin
duplicated "report is sent before close" paragraph in `tty_map.rs`
removed one. **Docs honesty:** the five recorded limits now ride the
*published* docs (the crate-root rustdoc §Known limits: the
`write_all` no-deadline record, the PTY rule-5 upstream fidelity
limit, the port-0-only mint echo wire fact, the no-reconnect-policy
boundary, the no-accept-all policy posture) with their module-doc
mirrors verified still in place (`tty_map.rs`, `exit_code.rs`
rule 5, `client_accept.rs`/`tunnel_map.rs`, `client.rs`
§Lifecycle posture, `host_key.rs`); crate-level docs state the
feature graph (each feature's row + the `default = []` decline-only
fact + no-feature-implies-another + honest advertisement) and the
fail-closed invariant.
**Compile-checked examples.** Two `no_run` doctests in the
crate-root docs (they run in every matrix build, and the publish task's
verification set keeps them compile-checked with zero extra
vehicle): a server mount (`ServeConfig::new` → `SshAdapter::new` →
`adapter.handle`, on the default build, with sketch key/identity seams
returning `Absent`/`None`, prose points at the vault-backed shapes)
and a dial (`dial(DialConfig)` → `close()`, the op rows referenced in
prose with the feature gate noted; `RejectAll` named as
connects-to-nothing by design). README mirrors them.
**README.md.** Landed (none existed): what the crate is (the
two-direction door, russh owns the wire, door-not-backend), the
feature matrix table + the fail-closed posture (a default build serves
nothing but declines; unset-config declines; never advertised), the
two usage sketches (mirroring the doctests), the custody/security
posture summary (vault-backed sources, encrypted at rest, decrypted
at use, zeroized; no env vars, no secrets on the wire; publickey-only
single attempt; fail-closed host-key default with no accept-all;
ACL-gated surface; bounded resources + the known-limits pointer; the
decline matrix as contract), the docs pointers, the license note.
**CHANGELOG.md.** The 0.1.0 entry landed (founding entry, dated
2026-10-30): the crate story (the two-direction door, the flat
fail-closed graph, ADR-003) + the posture statement, then the
landed surface wave by wave: the phase 0/1 contract, waves 1–5
(foundations, server stack, server mappings/spine, client direction,
validation+release), plus Notes (the sftp decline-only feature fact,
the OQ-09 env posture, the russh-pin one-way-door record). Only
served surface is listed; the never-features
(x11/`auth-agent`/subsystem/`env`) are named as the declines they
are.
**Feature matrix** (`scripts/matrix.sh`, the one command): all six
builds' `cargo test` green (none / git / session / tunnel / sftp-only
/ `--all-features`, with 108 result-ok reports across the matrix,
including both doctests per build), clippy ×2 (`--all-targets -D
warnings`, with and without `--all-features`) clean, `cargo fmt
--check` clean, `cargo doc --no-deps` clean; plus the fuzz corpus
gate (`cargo test --manifest-path fuzz/shared/Cargo.toml`, all 11
invariants green).
**Publish dry-run.** `cargo publish --dry-run --allow-dirty` clean,
with 76 files packaged and verified (the packaged tree compiles), upload
aborted by dry run as expected. The packaged file list verified
against the package policy (`cargo package --list`): exactly `src/`
(20 files), `tests/` (+ `common/` doubles + `vectors/`), the
architecture docs (`docs/architecture/`, the authoritative
contract), `README.md`, `CHANGELOG.md`, `LICENSE-MIT` /
`LICENSE-APACHE`, the manifests (`Cargo.toml`/`.orig`,
`Cargo.lock`, `.gitignore`, `.cargo_vcs_info.json`) and
`scripts/matrix.sh` (the verification tooling, not process surface);
none of the excluded surface appears (`.opencode/`, `AGENTS.md`,
`docs/reviews|plans|research/` / `docs/sdd_process.md`, `tasks/`,
`fuzz/` are all absent from the list). **Manifest sanity recorded:** version 0.1.0
(no bump, as `w5-publish` verifies), `rust-version` 1.89, edition
2024, `license = "MIT OR Apache-2.0"` with both license files
present, the pins as ADR-002 records them (russh 0.65
`default-features = false` + `aws-lc-rs`; alkcall 0.10; alkvault
0.1; the per-feature optional siblings alktty 0.8.1 / alkgit 0.1.0 /
alktunnels 0.4.1), the feature graph exactly ADR-003's, the
package-policy `exclude` list in place.
**The freeze inventory (for `review-wave-5` and `w5-publish`, the
surfaces the 0.1 publish makes one-way; further wire-relevant change
is a new ADR + a semver event):**
1. **The mapping contracts**, the channel-type → family-protocol
row semantics as landed (`docs/architecture/mapping.md` executed
by `dispatch.rs`/`tty_map.rs`/`git_map.rs`/`tunnel_map.rs`/
`client_ops.rs`): the route-1 bridge flow (open-direct →
accept-after-fabric-success), the exec-only git grammar + its
verdicts, the parse-only dispatch + the translation bridge
(chunk framing, the zero-length stdin sentinel, the
negotiation-error frame → 255), the exit derivation rules 1–6,
the client op-row planes (the family chunk/duplex surfaces, the
acceptor registry + payload types, the lifecycle primitives).
2. **The honest-advertisement posture**, the fail-closed invariant
as behavior: an unfeatured/unimplemented channel type is declined
(never advertised, never half-served); a default build serves
declines only; the `sftp` placeholder stays a decline in every
build (OQ-13).
3. **The decline-matrix behavior**, the decline classes and shapes:
the `OpenDeclineReason` vocabulary as exposed, the
spawned-`channel_failure`-then-close serving-path shape, the
`ConnectFailed` fabric reject, teardown-at-birth, the
token-collision refusal, the config-driven
(`seam-unconfigured`/unset-field) declines, the always-`sftp`
decline row, as pinned by the matrix suite.
4. **The fingerprint string format**, the `SHA256:` contract
format of `crate::fingerprint()` (the crate's single fingerprint
path): both the auth bridge's identity resolution and the
host-key policy's exact-string pin comparison consume it;
changing the format breaks every pin store and is a one-way door.
5. **The russh pin's wire posture**, russh 0.65.0 with
`aws-lc-rs` (no compression, `rsa` off, `des`/`dsa` never): the
kex/algorithm negotiation surface crosses the crate boundary, so
the pin is wire-relevant per ADR-002, and a bump is a deliberate,
tested, recorded event. (The `alk/ssh` ALPN pin, ADR-001, is
already its own ledger one-way door; the auth surface ships as
publickey-only, exactly one attempt.)
## Summary
Release readiness landed. Crate docs: warning-free × builds
(default + `--all-features`), the 9-warning doc-link debt resolved in
place (`client_ops.rs`'s private-link class among them), the
docs-honesty pass riding the published crate-root rustdoc (§Known
limits: the five recorded dispositions (`write_all` no-deadline, PTY
rule-5, port-0-only mint echo, no-reconnect policy, no-accept-all)
with module-doc mirrors verified) and crate-level docs stating the
feature graph + fail-closed invariant; two `no_run` usage doctests
(server mount + dial) keep the README examples compile-checked in
every matrix build. README.md landed; CHANGELOG.md carries the 0.1.0
founding entry (wave-by-wave, honest advertisement). The feature
matrix is green end to end (six test builds, clippy ×2, fmt, doc) +
the fuzz corpus gate (11 invariants). `cargo publish --dry-run
--allow-dirty` clean (76 files packaged + verified; the file list
checked against the package policy, so that architecture docs ship and the
process surface does not; manifest sanity recorded). The freeze
inventory (mapping contracts, honest advertisement, decline-matrix
behavior, fingerprint format, russh pin posture) is recorded above
for the gate's read. Ready for `review-wave-5`; `w5-publish`
executes only over a green gate.