Codex review of 3d754fdc / 85d93e7c / 1b168a84 flagged six BLOCKs +
five CONCERNs + one NIT. This commit closes them.
BLOCKs (all six fixed):
1. stderr pipe not drained → CLI deadlocks on full pipe. Now spawned
sibling task drains stderr to /dev/null for the lifetime of the
child.
2. Receiver-drop only detected on next stdout line → idle CLI keeps
running forever. Switched both BuiltIn + Subprocess channels from
`std::sync::mpsc` to `tokio::sync::mpsc` so `tx.closed()` is a
future we can race against `lines.next_line()` in a `select!`.
Sync iterator wrapper `BlockingRecvIter` in chat_runtime.rs uses
`Receiver::blocking_recv`.
3. `Done` event marked the flag but didn't break the read loop. Now
breaks immediately on any structured `done` so stdout staying
open past turn-end doesn't hang the iterator.
4. EOF path always emitted `Done { EndTurn }`, ignoring child exit
status. Now reaps the child and surfaces non-zero exit as
`Error("CLI exited with status N") + Done { Aborted }`.
5. stdout read error fell through to `Done { EndTurn }`. Now emits
`Error + Done { Aborted }` so I/O failures aren't reported as
normal completion.
6. Malformed structured events silently produced empty deltas /
empty errors / nameless tool calls. `parse_line` now requires the
shape's mandatory fields and emits `Error("malformed X event:
...")` when they're missing. Done's `stop_reason` stays optional
(already had a sensible `EndTurn` fallback).
CONCERNs (4 of 5 fixed):
1. `ChatRequest.system_prompt` + `max_output_tokens` ignored by
BuiltInProvider. Now honored per-turn: each `send` builds a
turn-local `QueryEngine` cloning the provider Arc (cheap) +
applying request's system/max-tokens with constructor defaults
as fallback. `BuiltInProvider` struct now holds the pieces
instead of a pre-built engine.
2. BuiltIn `Error` path emitted no terminal `Done`. Now every
error-terminal branch sends `Done { Aborted }` so consumers can
distinguish "stream errored" from "channel silently closed."
3. Subprocess stdin write errors silently ignored. Now surfaces as
`Error("stdin write: ...") + Done { Aborted }` with child kill +
wait.
5. `SubprocessProvider::for_cli(Codex | OpenCode)` accepted the
wrong backend silently. Signature now returns `Option<Self>`;
HttpServer-category CLIs return `None`. Direct stdio bridging to
a `codex` binary still possible via `with_binary`.
CONCERN 4 (Subprocess silently drops `system_prompt` +
`max_output_tokens`) intentionally deferred — those fields have no
universal CLI mapping; the planned settings-modal flow lets users
encode them in argv directly via `with_binary`. Documented in the
module header as the contract.
NIT 1 (chat_provider.rs doc said "three" but listed four backends)
fixed.
Tests: 14 → 16 native chat tests + 250 shell-core tests pass. Two
new tests cover for_cli's `None` return for HttpServer kinds + the
malformed structured-event paths.
|
||
|---|---|---|
| .. | ||
| openpencil-app | ||
| openpencil-desktop | ||
| openpencil-shell-core | ||
| openpencil-shell-native | ||
| openpencil-shell-web | ||
| pen-codegen | ||
| pen-core | ||
| pen-engine | ||
| pen-figma | ||
| pen-types | ||
| wasm-libc-shim | ||
| CLAUDE.md | ||