14 Commits
Author SHA1 Message Date
glm-5.3-flash 66c6e693bb docs: record v0.1.0 publish in review #003 (review closed) 2026-09-05 17:02:12 +00:00
glm-5.3-flash 3baa993edb fix: local-bridge robustness, scope-gate order, sentinel contract; packaging/docs closeout (P8-P11, P2/P3/P15)
Closes review #003 (prepublish review for v0.1.0).

- P8: StdinSink::poll_shutdown parks an inflight reserve+send on a
  full channel (waker registered) — a stdin blast followed by EOF
  delivers the EOF instead of stranding it
- P9: five poisoned-lock .expect() sites -> unwrap_or_else(into_inner)
- P10: three thread-spawn .expect() sites -> TtyError::AllocFailed
- P5: tty:open scope gate runs before carriage/cmd/backend-lookup
  checks (no backend-name enumeration differential for unscoped ids)
- P11: recv_stdout terminates on the zero-length drained sentinel;
  the sentinel is no longer yielded as an item (doc was already the
  contract); stderr has no sentinel (doc noted)
- P2: exclude AGENTS.md + docs/plans/, drop dead Cargo.lock and
  docs/research/ entries (package list: 42 files, 659.2KiB)
- P3: AGENTS.md phase status (all five landed), ADR range 001..009
  (+ alktty-native ADR-009 in the mapping), alkcall guidance
  corrected to v0.4.x / pin "0.4.0"; architecture README ADR-009 row
  + landed-phase status
- P15: backend.rs doc typo; redundant tokio-stream dev-dep removed;
  NegotiationError::Io arm logs; set_identity failure logs;
  input_pump.abort() at session end; TtySessionError::Open carries
  the accept_bi StreamError (no io::Error flattening); borrowing
  deserialize in open_via_channels (no params.clone());
  error_response_bytes guards an "error" key in fields; trivial
  inline comments promoted/removed; plan-doc test counts + doc
  front-matter refreshed; session tests that raced session teardown
  under the abort change use a GatedBackend (exit held until
  released)

Verification: cargo test 104 lib / --all-features 147; clippy
(all-targets + wasm32) -D warnings; fmt; wasm check; doc 0 warnings;
publish dry-run OK.
2026-09-05 16:47:45 +00:00
glm-5.3-flash 7b0bac0671 docs: mark review #003 P12 + P6 + P7 + P4 + P16 resolved (c8e4610) 2026-09-05 16:36:22 +00:00
glm-5.3-flash a720241021 docs: mark review #003 P1 + P13 resolved (87c52e5)
Session-1 resolution section records the concurrent-drainer fix shape,
the bug-validated regression test (fails with the old order
reinstated), the two P13 boundary/discard tests, and the deferred
accept-loop harness item. Verification counts updated (98 lib / 141
--all-features).
2026-09-05 10:05:49 +00:00
glm-5.3-flash da94d5e23f docs: add review #003 (prepublish review for v0.1.0)
Two subagent reviews (code + packaging/docs vs alkcall 0.4.1) with every
finding manually re-verified against source at 918af40. 13 open findings:
P1 pump_session deadlock at >=63 stdout chunks (empirically reproduced,
N=62 ok / N=63 hangs), P2 AGENTS.md ships in the crate, P3 stale
AGENTS.md/architecture-README text, P4 no README, P5-P13 API-shape and
robustness items, P15-P16 polish/changelog. P14 closed as alkcall parity.

Includes suggested session breakdown for distributing the remediation.

Verification baseline on the reviewed tree: cargo test 95 lib (default) /
138 --all-features, clippy (all-targets + wasm32) clean, fmt clean, doc
clean, publish --dry-run OK, CJK scan clean.
2026-09-05 09:30:32 +00:00
glm-5.3-flash 918af406dd feat: InvalidParams variant + #[non_exhaustive] TtySessionError (R5)
Review #002 R5 — the open_via_channels fail-fast parse (a params value
that fails the local NegotiateRequest parse before a channel is
allocated) surfaced as NegotiationSerialize, whose name and doc
describe serializing the negotiation frame, not parsing open-op params.

- add TtySessionError::InvalidParams(String); the fail-fast path maps
  to it (the serde_json::Error's From impl stays for
  NegotiationSerialize's real users — the direct-path serialize)
- mark TtySessionError #[non_exhaustive] — the same two-way-door
  pattern as TtyError (backend.rs) and alkcall's consumer-facing
  AdapterError; the policy rationale is in the enum's doc
- NegotiationError / RawError stay exhaustive (deliberate — they
  mirror fixed wire semantics; in-crate matchers keep exhaustiveness
  checking)
- the two fail-fast tests assert InvalidParams(_) now
- review #002: R5 resolved; the superseded deferral rationale is
  recorded (circular trigger — "first channels-path consumer exists"
  fires after the change becomes expensive; misapplied citation —
  ADR-009's version-skew note governs wire skew, not error enums;
  the "unreachable" framing belonged to R4's arm, not R5's — the
  fail-fast path is live today). The #[non_exhaustive] policy is
  decided on principle, pre-publish, while the variant addition is
  additive by construction

Verification: cargo test 95 lib (default) / 138 (--all-features);
clippy -D warnings native + wasm clean; fmt clean; doc 0 warnings.
2026-09-05 08:45:58 +00:00
glm-5.3-flash 8ee9216a07 fix: channels parse-failure path writes the negotiation error frame (R4)
Review #002 R4 — a NegotiateRequest parse failure of the open op's
schema-validated input died silently (log + return, channel teardown,
consumer observed NoExitChunk — indistinguishable from a crashed
producer), while the other post-open failure classes (unknown backend,
allocate_failed, ownership denial) wrote the 0x00-prefixed error frame.

- make_tty_open_handler now accepts the channel's BiStream and writes
  a malformed_negotiation frame via the shared
  crate::adapter::send_negotiation_error (now pub(crate)) before
  returning; the consumer's M1 peek surfaces NegotiationRejected
  unchanged
- the frame type and layout are unchanged (ADR-001 wire-stable
  contract); no new frame type, no wire change
- tests: make_tty_open_handler seam test with a hand-built
  schema-bypassing input (cwd: 42) + a real-registry end-to-end test
  via ChannelClient::open_channel (bypasses open_via_channels's local
  fail-fast parse — R5's path — so it exercises the producer handler)
- docs: ADR-009 amended (Parse-failure error frame section);
  tty-adapter.md malformed_negotiation row covers both paths;
  session.rs post-open failure lists updated; review #002 R4 resolved

Note: the review's "unreachable end-to-end" premise was refined —
open_via_channels parses params locally (fail-fast) so a TtySession
consumer never hits the producer-side parse failure, but direct
ChannelClient callers do; the schema is deliberately partial so a
schema-valid value (cwd typed as a number) reaches the handler.

Verification: cargo test 95 lib (default) / 138 (--all-features);
clippy -D warnings native + wasm clean; fmt clean; doc 0 warnings.
2026-09-05 08:37:02 +00:00
glm-5.3-flash 5b608117ff docs: add review #002 (follow-up on the 2026-09-05 resolution session)
Documents the post-hoc review of the five resolution commits:
- R1 (ADR-009 missing) and R2 (stale L1-redesign docs) — resolved in
  37ae07a
- R3 — install-time identity snapshot on the channels path, closed as
  intended (hub-proxy design predating the alkcall split; constraint
  recorded: registries must stay per-connection)
- R4 (silent death on the parse-failure path, no error frame) and R5
  (NegotiationSerialize mislabel on the fail-fast path) — open,
  deferred to the first post-1.0 error-surface decision
Also cross-links review #001's L1 resolution to ADR-009 and review #002.

Verification: cargo test 93 lib pass; fmt clean.
2026-09-05 08:08:22 +00:00
glm-5.3-flash 6ad1d84fdb chore: verify MSRV 1.85, pin 1.85-compatible transitive deps (N6)
- cargo +1.85 check passes (default + --all-features), plus wasm
  target check and a full +1.85 test --all-features run (136 tests).
  The declared MSRV is real, not aspirational.
- the lockfile pins the 1.85-compatible transitive set (jsonschema
  0.46.9, idna_adapter 1.2.0, icu crates 2.0.x) — idna_adapter 1.2.2
  requires rustc 1.86, icu 2.3 requires 1.88; stable still resolves
  and all tests pass.
- review #001 is now fully resolved (status: fully-resolved). A CI
  MSRV job can gate on 'cargo +1.85 check' once CI exists.
2026-09-05 07:28:07 +00:00
glm-5.3-flash cdd6893046 test: readiness signals replace sleep-based timing (N4)
- signal tests use a marker-file readiness signal: the child's command
  is 'echo ready > <marker>; exec sleep 60', the test polls
  wait_for_file(marker, 5s) — marker exists = the shell exec'd, so the
  signal lands on the real target regardless of machine load. Applied
  in tests/pty.rs (both signal tests), tests/pipe.rs (SIGTERM), and
  the src/local unit tests; wait_for_file lives in tests/common.
- cancel-cleanup post-action sleeps became bounded polls for the
  child's death (kill(pid,0) -> ESRCH, 5s deadline) — faster and
  flake-proof in both directions.
- resize/cat-stdin tests need no readiness signal at all: the adapter's
  input pump processes chunks in order — the sleeps there were pure
  latency (integration suites now ~40ms, was 200-270ms).
2026-09-05 07:21:30 +00:00
glm-5.3-flash a73484203e test: pty bridge late-signal fallback chain; document unreachable error arms (L6)
- signal_after_child_exit_takes_both_kill_fallbacks: a late signal
  (after the child exited) takes kill(-pgid) fail -> kill(pid) fail ->
  warn + return, with no panic — the reachable part of the
  REQ-TTY-02 fallback chain.
- the remaining bridge error arms are documented-unreachable through
  the public path (per the review's disposition), with per-arm
  reasoning in the module doc: try_clone_reader (dup failure),
  reader read error (EIO -> EOF mapped), take_writer (second-take
  only), writer write/flush (externally-closed fd), waiter wait()
  (already-reaped child). The ADR-055 §4 -1 sentinel is covered at
  the adapter level (exit_error_sends_minus_one) — it also arises
  when the oneshot drops on kill-on-cancel.
- local/pty.rs line coverage 80.85% -> 86.01%; total 94.48%.
2026-09-05 07:17:48 +00:00
glm-5.3-flash 96692d3b6a feat: channels path carries the negotiation in the open op (L1, L3)
The channels path no longer carries a second negotiation frame on the
channel's data stream (ADR-009). The open op's registry-validated
input IS the negotiation:

- producer: make_tty_open_handler parses the open op's input into a
  NegotiateRequest and drives the new drive_session_pre_negotiated
  (same three-pump driver as drive_session, minus the wire-frame
  negotiation phase; validate/allocate factored into
  validate_and_allocate, shared by both paths). Post-open failures
  (unknown backend, allocate_failed, ownership denial) still go to the
  client as a 0x00-prefixed negotiation error frame, so the consumer's
  M1 disambiguation read applies unchanged. The tty:open scope gate is
  enforced by the registry's AccessControl (not re-checked in the
  handler).
- consumer: open_via_channels parses params locally (fail-fast before
  a channel is allocated), opens the channel, and starts raw-chunk
  mode directly (from_halves_raw — no negotiation write; the
  0x00-error-frame peek retained).
- tty_open_spec's input schema is now the partial NegotiateRequest
  shape (carriage/backend/cmd required; backend params stay free-form
  — raw JSON Schema is permissive on unknown keys).

Prerequisites landed upstream: alkcall 0.4.0 enforces
OperationSpec.input_schema at dispatch (the registry check this design
leans on never existed before); alkcall 0.4.1 parks early-arrival
chunks for un-adopted channels instead of dropping them — the open
response / producer's-first-write race was silently losing the first
chunks (found by L3's test; the session never resolved).

L3: open_via_channels + from_bidi_stream_via now covered end-to-end
(5 session tests + pre-negotiated adapter test + shared-harness tests
in the new crate::testing module; the channels harness moved there so
session tests share it).

Verification: cargo test 93 lib (default), 116 lib + 19 integration
(--all-features); clippy -D warnings native + wasm clean; fmt clean;
doc 0 warnings; wasm check clean.
2026-09-05 07:08:17 +00:00
deepseek-v4-pro e5330e957b docs: mark review #001 findings resolved (M1, M2, L2, L4, L5, N1-N3, N5)
Update the remediation plan with a resolution section and per-finding
status. Nine findings resolved in commit 9944153; L1, L3, L6, N4, N6
remain open.
2026-08-17 12:13:35 +00:00
deepseek-v4-pro 8ff7ba27f3 docs: add post-Phase-5 code review (coverage + correctness + smell)
First full review of the alktty crate after Phase 5 landed. Covers
coverage (cargo-llvm-cov), correctness, and code smell, with a
remediation plan.

- 2 Medium: TtySession never handles the negotiation-rejection error
  frame (M1); wait() swallows MalformedExitChunk (M2)
- 6 Low: channels input ignored (L1), consumer stdout/stderr routing
  untested (L2), open_via_channels 0% covered (L3), mocks leak into
  public API (L4), cargo fmt fails (L5), pty bridge error paths
  untested (L6)
- 6 Nit: 9 rustdoc warnings (N1), stale doc paths (N2), unsafe vs
  AGENTS.md §14 (N3), sleep-based timing (N4), duplicated seed helpers
  (N5), unverified MSRV (N6)

Verification: cargo test (81), cargo test --all-features (123),
clippy clean (native + wasm), wasm check clean, publish dry-run clean,
llvm-cov 90.74% lines / 92.24% functions.
2026-08-17 11:47:35 +00:00