The packaged changelog is now a recent-releases slice produced by
scripts/sync-changelog.sh (which gains a --check mode); also restore the
SECURITY.md contact line the version gate guards, and finish the stale
binary-name sweep (--bin codewhale examples, qa harness doc).
Rename brand-bearing string literals across the TUI source and the
system-prompt templates that ship inside the binary. The DeepSeek
provider integration is again left intact: the `ApiProvider::Deepseek`
enum variant, the `"deepseek"` provider name string returned by
`ApiProvider`-to-string mappings, model IDs, the `~/.deepseek/` config
directory and `DEEPSEEK_CONFIG_PATH` env var, the OS keyring key
`"deepseek"`, the Ollama `deepseek-coder*` model defaults, the China
preset alias `deepseek-china`, and the various provider list error
messages all keep the legacy spelling.
Touchpoints:
- `crates/tui/src/prompts/*.md` and `*.txt`: brand language flipped to
`codewhale`; the internal `<deepseek:subagent.done>`,
`<deepseek:subagent_context>`, `<deepseek:fork_state>`,
`<deepseek:tool_call>` XML-ish event tags rename in lockstep to
`<codewhale:…>` so the model-facing format stays consistent.
- `crates/tui/src/tools/subagent/mod.rs`: emits the new event tag.
- `crates/tui/src/core/tool_parser.rs`: parses the new event tag.
- `crates/tui/src/tools/subagent/tests.rs`,
`crates/tui/tests/protocol_recovery.rs`,
`crates/tui/src/prompts.rs`: test expectations updated to match the
new tag and the new prompt text.
- Status / display strings flipped to `codewhale`: `acp_server.rs`'s
agent name + title, `config_ui.rs`'s config schema title,
`share.rs`'s export title, `welcome.rs`'s onboarding banner,
`commands/status.rs`, `core/engine*`, `tui/notifications.rs`,
`tui/sidebar.rs`, `tui/widgets/header.rs`, `tui/widgets/mod.rs`,
`tui/ui.rs`'s resume-hint, `main.rs`'s clap header and `Doctor`
prose, `tui/ui/tests.rs` and other test assertions.
- `crates/tui/src/logging.rs` test fixture: `deepseek_cli=debug` ->
`codewhale_cli=debug` so the log-filter test references the renamed
crate.
- Tracing targets that were namespaced under the brand
(`target: "deepseek::config"`) move to `target: "codewhale::config"`.
- Test-fixture tempdir prefixes (`deepseek-tui-…` / `deepseek-…`) rename
for consistency.
Local gates green: `cargo check --workspace --all-targets --locked`,
`cargo fmt --all -- --check`, `cargo clippy --workspace --all-targets
--all-features --locked -- -D warnings`, `cargo test --workspace
--all-features --locked` (3226+ pass, 0 fail).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The qa_pty integration tests booted the canonical TUI via
`Harness::cargo_bin("deepseek-tui")`. After the previous commit
renamed the canonical bin to `codewhale-tui` and made `deepseek-tui`
a tiny deprecation shim that forwards to it via PATH, those tests
launched the shim and hung waiting for a TUI frame because the
sealed PATH in the test sandbox has no `codewhale-tui`.
Point the harness at `cargo_bin("codewhale-tui")` directly. Also
add a `CARGO_BIN_EXE_codewhale-tui` compile-time fallback in the
harness so older Cargo versions still work, alongside the existing
legacy `deepseek-tui` fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two pieces:
**#1073 fix.** When a paste burst is currently being assembled, or when
the burst's Enter-suppression window is still open after a flush, the
trailing newline of the paste was firing `submit_input()` and the
in-flight burst buffer was getting destroyed by `clear_after_explicit_paste()`.
The PasteBurst module already exposed `newline_should_insert_instead_of_submit`
and `append_newline_if_active` for exactly this case, but no caller had
been wired up. Added `App::handle_composer_enter`, which checks the
suppression state and either appends `\n` to the burst buffer or inserts
it directly into the composer text — no submit. The `KeyCode::Enter`
arm in the composer event loop now dispatches through that helper.
Reproduces the Windows/PowerShell symptom from the report:
multi-line paste ending with `\n` no longer auto-submits AND the text
no longer leaks into the now-empty composer.
Four unit tests cover: active-burst Enter, post-flush window Enter,
normal Enter outside the window, and Enter with paste-burst detection
disabled (suppression must be off).
**PTY QA harness.** New `crates/tui/tests/support/qa_harness/` wraps
`portable-pty` (already a runtime dep) and `vt100` (new dev-dep) into
a small surface for scenarios that need a real PTY: spawn a binary,
send keys/paste/resize, parse the ANSI stream into a frame, assert
on visible text + filesystem state. The harness seals `$HOME` so
scenarios cannot read the developer's real `~/.deepseek/` and points
the base URL at 127.0.0.1:1 so no live request escapes. README under
`support/qa_harness/README.md` documents how to add a scenario.
Initial scenarios in `crates/tui/tests/qa_pty.rs`: smoke boot,
keystroke round-trip, and bracketed/unbracketed paste-with-trailing-
newline regression guards for #1073. The unbracketed scenario does
not deterministically reproduce the bug on macOS (single-syscall
PTY writes keep the burst continuously active), but the unit tests
above cover the path conclusively; the PTY test stands as a
regression guard for the visible-text invariant.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds `integration_mock_llm.rs` covering the LlmClient trait surface:
- streaming turn loop (text deltas + finish reason)
- reasoning-content replay across tool-call rounds (V4 §5.1.1, the
HTTP 400 path that broke v0.4.9-v0.5.1)
- tool-call round-trip with chunked input JSON
- multiple tool calls in one turn preserve event ordering
- compaction-style non-streaming `create_message`
- sub-agent style independent parent/child mocks
- capacity-gate observation of a captured request
Four full-engine tests are `#[ignore]`-marked as BLOCKED on the engine
refactor from concrete `Option<DeepSeekClient>` to `Arc<dyn LlmClient>`.
Once that wiring lands the ignored tests light up with no mock changes.
Adds:
- `tests/support/llm_client.rs` mirrors the trait so the mock can be
brought into the integration test via `#[path]` without dragging in
the rest of the binary's module tree
- `tests/fixtures/.gitkeep` so the `eval --record` output directory
rides the repo
- `tests/README.md` documents both the trait-level mocking strategy
and the `--record` fixture flow
- `record_flag_writes_one_jsonl_line_per_step` in `eval_harness.rs`
exercises the new `--record` flag end-to-end
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>