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.
6.4 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | |
|---|---|---|---|---|---|---|---|---|
| w4-tty-coverage | Wave 4: tty coverage minors (wave-3 gate booked item 3) | completed |
|
narrow | low | component | implementation |
Description
Close the wave-3 gate's booked finding item 3
(review-wave-3 §Booked findings, "minors, one ticket's worth"):
- The
channel_close-fired per-channel cancel path is unexercised on the wire; only the teardown signal is. Land the wire row: a channel closing (client-side close on a served tty row) fires the per-channel cancel path (the cap release + the per-channel state teardown observed, the disjoint release sites the gate verified per row, now wire-witnessed for this path). - The Closed/Break no-exit-chunk close shape has no wire row, so land the row(s): a session ending via the Closed/Break close shape emits no exit chunk (the derivation contract's close-shape class, the absent-report posture pinned, not just the happy paths).
- The tty stdout
write_allcarries no deadline, recorded as a known limit only (module docs): backpressure is bounded, liveness is covered by the inactivity timeout; no code change (the gate's recorded disposition, since a deadline here is a behavior change, not a coverage minor).
Depends on w4-channel-not-held-rows to keep tests/tty_mapping.rs
single-writer (that task's rows land first; these land into the
settled file).
Acceptance Criteria
- Wire row: the
channel_close-fired per-channel cancel path (cap release + state teardown observed on the wire) - Wire row(s): the Closed/Break no-exit-chunk close shape
- The stdout
write_allno-deadline limit recorded in module docs (no code change) cargo test(+ per-feature +--all-features), clippy ×2 (-D warnings), fmt,cargo doc --no-depspass
References
- tasks/implementation/review-wave-3.md §Booked findings item 3
- docs/architecture/mapping.md §The exit derivation contract (the close-shape classes; the PTY-path rule-5 limit, the docs-posture template), src/tty_map.rs, src/channel_cap.rs (the release sites the rows witness)
- tests/tty_mapping.rs (the per-build matrix the rows join)
Notes
- Test + module-docs only, as planned, hence no production code change; the shapes held on the wire exactly as documented.
channel_close-fired cancel path, namelya_client_close_on_a_served_row_fires_the_per_channel_cancel_and_releases_the_cap(tests/tty_mapping.rs, cfgsession): a served pipe row under a cap of 1; a second open is refused (AdministrativelyProhibited, the admission held), the client then closes the served channel, and the row witnesses (a) the per-channel state teardown, with the shim's kill-on-drop witness fires (the bridge surface's cancel → the serving task aborts the alktty session), polled before unmount so it is thechannel_closesite, not the teardown; (b) no exit report fabricated on the wire (plain close / channel end); (c) the serving path's ended lifecycle event; (d) the cap release, with the next open admits and routes (release site 1, disjoint from the bridge-failure and arrival sites).- Closed/Break no-exit-chunk close shape, namely
a_bridge_end_without_an_exit_chunk_reports_nothing_and_closes_plain(same file): the shape is constructed deterministically through the real path: the shim's stdout carries a payload beyond alktty's ownMAX_CHUNK_LENwire bound; alktty'sChunkWriterrejects it locally, its drainer shuts the write half down, and the bridge's next read is EOF (BridgeFrame::Closed) with the scripted exit (Some(0)) never forwarded. The row pins: the in-bounds chunk rode first, the end is a plain close, no exit-status/exit-signal ever rides (the absent-report posture, neither 0 nor 255), the session truly served (an allocation happened, so this is the close shape, not a decline), and the ended lifecycle event landed. - Break's classification row, which pins
clean_ends_classify_closed_and_oversized_lengths_classify_break(src/tty_map.rstest mod): Break is unreachable on the wire through alktty's own validatedChunkWriter(an oversized chunk fails local validation → the drainer break → the read sees EOF, exactly the Closed row's construction; a non-EOF duplex read error has no wire-constructible producer at this pin, and the serving-path body of Closed/Break is one arm). So the family's serving outcome is wire-witnessed by the Closed row, and the frame-levelBreakclassification (bounds-checked, never an oversized read) is pinned at the frame layer by the unit row, recorded here as the reason one wire row + one unit row cover the "row(s)". - The stdout
write_allno-deadline limit, recorded insrc/tty_map.rs's module docs (§the translation bridge): the gate's recorded disposition verbatim; backpressure bounded, liveness covered by the inactivity timeout, a deadline would be a behavior change, not a coverage minor. No code change. - A
session_with_limits/session_config(limits)driver variant was added to the binary (the cap row's ceiling of 1);session_withdelegates unchanged.
Summary
The wave-3 gate's booked item 3 is closed: the channel_close-fired
per-channel cancel path is now wire-witnessed (a served pipe row under
a cap of 1: the refused over-cap open pins the admission, the client
close pins the cancel, with the kill-on-drop witness firing before any
teardown, no exit report is fabricated, the ended lifecycle event
lands, and the succeeding re-open pins the cap release from the
established-channel-close release site); the Closed/Break
no-exit-chunk close shape landed its wire row (constructed through
the real path via an oversized shim chunk dying at alktty's own
ChunkWriter validation: EOF without an exit chunk → plain close,
nothing fabricated, the scripted exit never forwarded) plus the
frame-level Break classification row (Break is wire-unreachable
through alktty's validated writer at this pin, as recorded); and the
stdout write_all no-deadline limit is recorded in the module docs
per the gate's disposition. No production code change. Verified:
cargo test (default, session, session,git, git, tunnel,
sftp, --all-features, with the tty rows' 5×-repeat flake check
included), clippy ×2 (-D warnings), cargo fmt --check,
cargo doc --no-deps 0 warnings, taskgraph validate ✓ (35 tasks).