openpencil/crates
Kayshen-X b39d69eb70 fix(desktop/chat): address codex review BLOCKs + CONCERNs on chat backend trio
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.
2026-05-14 16:16:24 +08:00
..
openpencil-app feat(openpencil-app): skeleton crate (Stage F entry placeholder) 2026-05-03 22:05:00 +08:00
openpencil-desktop fix(desktop/chat): address codex review BLOCKs + CONCERNs on chat backend trio 2026-05-14 16:16:24 +08:00
openpencil-shell-core fix(desktop/chat): address codex review BLOCKs + CONCERNs on chat backend trio 2026-05-14 16:16:24 +08:00
openpencil-shell-native fix(shell): 3 codex stop-gate regressions (anchor drag, MCP id, doc load reset) 2026-05-14 15:18:02 +08:00
openpencil-shell-web feat(shell): export dialog + multi-format raster (PNG/JPEG/WEBP) + Property-panel preview 2026-05-14 14:02:52 +08:00
pen-codegen chore(workspace): cargo-deny 0.18 activation (Phase 1 Task 1.8 Step 6) 2026-05-03 23:05:00 +08:00
pen-core chore(workspace): cargo-deny 0.18 activation (Phase 1 Task 1.8 Step 6) 2026-05-03 23:05:00 +08:00
pen-engine chore(workspace): cargo-deny 0.18 activation (Phase 1 Task 1.8 Step 6) 2026-05-03 23:05:00 +08:00
pen-figma chore(workspace): cargo-deny 0.18 activation (Phase 1 Task 1.8 Step 6) 2026-05-03 23:05:00 +08:00
pen-types feat(pen-types): skeleton crate (bucket A) 2026-05-03 22:35:00 +08:00
wasm-libc-shim style(shell): cargo fmt --all (rustfmt-clean) 2026-05-10 18:47:33 +08:00
CLAUDE.md feat(shell): canonical .op loader + jian-core layout + visual fidelity pass 2026-05-14 09:26:08 +08:00