@@ -6,13 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66
77## [Unreleased]
88
9- ### Fixed
10-
11- - fix(security): wire `ShadowProbeExecutor` into the agent executor chain (`src/runner.rs`).
12- `ShadowSentinel` is now instantiated when `security.shadow_sentinel.enabled = true` and
13- inserted between `ScopedToolExecutor` and `PolicyGateExecutor` as required by spec 050 §Phase 2.
14- Adds `ShadowSentinelProbeGateAdapter` bridge to avoid circular crate dependency. Wires
15- `sentinel.advance_turn()` into `begin_turn()`. Closes #3739.
9+ ## [0.21.0] - 2026-05-11
1610
1711### Added
1812
@@ -27,7 +21,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
2721 Bot token is redacted in `Debug` output and stripped from `reqwest` errors via `.without_url()`.
2822 Unblocks Guest Mode (#3729), Bot-to-Bot communication (#3730), and reaction moderation (#3731).
2923 Closes #3728.
30-
3124- feat(channels): add Telegram Guest Mode and Bot-to-Bot communication (`zeph-channels`, `zeph-config`).
3225 Guest Mode spawns a transparent local axum HTTP proxy on an ephemeral port that intercepts
3326 `getUpdates` responses from `api.telegram.org`, extracts `guest_message` entries (which
@@ -43,7 +36,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
4336 `ChannelMessage.is_guest_context` → `SessionState.is_guest_context` → volatile system prompt
4437 annotation. Fixed missing `is_guest_context`/`is_from_bot` fields in `gateway_spawn.rs` and
4538 `daemon.rs`. Closes #3729, #3730.
46-
4739- feat(memory): add BeliefMem probabilistic edge layer to APEX-MEM (`zeph-memory`). New
4840 `pending_beliefs` + `belief_evidence` SQLite tables (migration 084) store candidate facts with
4941 probability weights before commitment. Evidence accumulates via Noisy-OR with optional temporal
@@ -73,33 +65,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
7365 `● Explored N files` / `● Ran N commands` with a collapsible sub-list of primary args (capped
7466 at 8 in Inline density, unlimited in Block, hidden in Compact). Groups break on role change,
7567 streaming tool, or different `ToolKind`. Closes #3719. (#3724)
76-
77- ### Fixed
78-
79- - fix(hooks): `pre_tool_use` hooks now fire for tool calls intercepted by the utility gate;
80- previously the hook block was skipped because `check_call_gates` returned early with `continue`.
81- Closes #3738.
82- - fix(tui): parallel tool call output no longer gets cross-contaminated in the TUI. `tool_call_id`
83- is now threaded from `ToolCall` through `ShellExecutor` → `ToolEvent::OutputChunk` →
84- `tui_bridge` → `AgentEvent::ToolOutputChunk/ToolStart/ToolOutput`. The TUI uses id-based
85- lookup when `tool_call_id` is non-empty; on miss it drops the chunk with a `warn!` log
86- instead of falling back to the last streaming message (which was the source of the bug).
87- The legacy empty-id path retains the old `rposition` fallback for backwards compatibility.
88- Closes #3688. (#3708)
89- - fix(tui): `handle_diff_ready` now correlates diffs to tool messages by `tool_call_id` instead of
90- a position-based `.rev().find()` scan, preventing diffs from attaching to the wrong message when
91- multiple tool calls are in flight. `AgentEvent::DiffReady` is now a struct variant carrying
92- `tool_call_id: String`. `ToolOutputChunk` lookup similarly uses id-based matching with a fallback
93- to the last streaming Tool message for shell tools whose `ToolEvent::OutputChunk` lacks an id.
94- `Channel::send_diff` gains a `tool_call_id: &str` parameter. (#3711)
95-
96- - fix(cli): `zeph cocoon doctor` now reports `[FAIL]` for `cocoon_client_url` with an invalid scheme
97- (e.g. `ftp://`). `check_config_present` previously returned `[OK]` without calling
98- `entry.validate()`, silently accepting any URL scheme. The fix adds a `validate()` guard that
99- pushes a `CheckResult::fail` with the scheme error and returns early. (#3694)
100-
101- ### Added
102-
10368- feat(hooks): `PreToolUse` and `PostToolUse` hook events for the main agent and subagent paths.
10469 New `[[hooks.pre_tool_use]]` and `[[hooks.post_tool_use]]` config sections accept
10570 `HookMatcher` entries (pipe-separated tool name patterns). Hooks fire with env vars:
@@ -108,18 +73,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
10873 and `ZEPH_TOOL_DURATION_MS` (post hooks only). PreToolUse fires before the `RuntimeLayer`
10974 permission check (observers see all attempted calls). Hook dispatch is fail-open at the agent
11075 level; `fail_closed` in a `HookDef` aborts the hook-chain sequence only. Closes #3698.
111-
11276- feat(tui): native terminal text selection without Shift modifier. `EnableMouseCapture` replaced
11377 with alternate-scroll mode (`\x1b[?1007h`/`\x1b[?1007l`) so the terminal translates scroll-wheel
11478 events into arrow keys. Chat scrolling is preserved; `AppEvent::MouseScroll` removed from the
11579 event model. Panic hook updated to emit `DisableAlternateScroll` on crash. Closes #3685. (#3685)
116-
11780- feat(tui): clipboard shortcuts for copying assistant replies. New `clipboard` module with
11881 `ClipboardHandle` backed by arboard (local) with OSC 52 fallback (SSH/tmux). SSH detected via
11982 `SSH_TTY`, `SSH_CONNECTION`, `SSH_CLIENT`. `Ctrl+O` and `/copy` slash command copy the last
12083 assistant message to clipboard. `clipboard` feature flag (default-on) gates the arboard
12184 dependency for headless builds. Closes #3685. (#3685)
122-
12385- feat(tui): Two-tier tool rendering and `ToolDensity` config — replaces the boolean
12486 `compact_tools` toggle with a three-state `ToolDensity` enum (`compact` / `inline` / `block`)
12587 that cycles with the `c` key. `inline` (default) renders a head (2 lines) + ellipsis
@@ -128,12 +90,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
12890 (green `●` / red `●`); streaming messages show the braille spinner. `ToolKind` classifies tools
12991 into Run / Explore / Edit / Web / Mcp / Other; consecutive Run and Explore calls are eligible for
13092 future grouping. `tool_density` is configurable in the `[tui]` config section. (#3686)
131-
13293- feat(llm): Cocoon live integration tests — 6 `#[ignore]`-gated tests covering `health_check`,
13394 `list_models`, `chat_round_trip`, `chat_stream`, `chat_with_tools`, and `doctor` checks.
13495 Tests require `COCOON_TEST_URL` env var and skip gracefully without it; `#[ignore]` attributes
13596 include reason strings. Requires `cocoon` feature. (#3675)
136-
13797- feat(tui): Cocoon TUI integration — `/cocoon status` and `/cocoon models` palette commands
13898 dispatch through the `CommandRegistry` (same as `/acp`) and display sidecar health and available
13999 models. Status bar shows `Cocoon: healthy (N models, M workers, X TON)` or
@@ -142,13 +102,43 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
142102 HTTP calls after executor starvation. All I/O paths instrumented with `tui.cocoon.poll`,
143103 `tui.cocoon.status`, and `tui.cocoon.models` tracing spans. Requires `cocoon` + `tui` features.
144104 (#3673)
145-
146105- feat(cli): `zeph cocoon doctor [--json] [--timeout-secs N]` diagnostic subcommand for Cocoon
147106 sidecar connectivity checks. Runs 6 ordered checks: config entry presence, sidecar HTTP
148107 reachability (`GET /stats`), proxy connection, worker count, model listing, and vault key
149108 resolution. Downstream checks gracefully skip (WARN) when the sidecar is unreachable. `--json`
150109 emits a structured JSON envelope with `schema_version: 1`. Requires `cocoon` feature. (#3672)
151110
111+ ### Fixed
112+
113+ - fix(security): wire `ShadowProbeExecutor` into the agent executor chain (`src/runner.rs`).
114+ `ShadowSentinel` is now instantiated when `security.shadow_sentinel.enabled = true` and
115+ inserted between `ScopedToolExecutor` and `PolicyGateExecutor` as required by spec 050 §Phase 2.
116+ Adds `ShadowSentinelProbeGateAdapter` bridge to avoid circular crate dependency. Wires
117+ `sentinel.advance_turn()` into `begin_turn()`. Closes #3739.
118+ - fix(hooks): `pre_tool_use` hooks now fire for tool calls intercepted by the utility gate;
119+ previously the hook block was skipped because `check_call_gates` returned early with `continue`.
120+ Closes #3738.
121+ - fix(tui): parallel tool call output no longer gets cross-contaminated in the TUI. `tool_call_id`
122+ is now threaded from `ToolCall` through `ShellExecutor` → `ToolEvent::OutputChunk` →
123+ `tui_bridge` → `AgentEvent::ToolOutputChunk/ToolStart/ToolOutput`. The TUI uses id-based
124+ lookup when `tool_call_id` is non-empty; on miss it drops the chunk with a `warn!` log
125+ instead of falling back to the last streaming message (which was the source of the bug).
126+ The legacy empty-id path retains the old `rposition` fallback for backwards compatibility.
127+ Closes #3688. (#3708)
128+ - fix(tui): `handle_diff_ready` now correlates diffs to tool messages by `tool_call_id` instead of
129+ a position-based `.rev().find()` scan, preventing diffs from attaching to the wrong message when
130+ multiple tool calls are in flight. `AgentEvent::DiffReady` is now a struct variant carrying
131+ `tool_call_id: String`. `ToolOutputChunk` lookup similarly uses id-based matching with a fallback
132+ to the last streaming Tool message for shell tools whose `ToolEvent::OutputChunk` lacks an id.
133+ `Channel::send_diff` gains a `tool_call_id: &str` parameter. (#3711)
134+ - fix(cli): `zeph cocoon doctor` now reports `[FAIL]` for `cocoon_client_url` with an invalid scheme
135+ (e.g. `ftp://`). `check_config_present` previously returned `[OK]` without calling
136+ `entry.validate()`, silently accepting any URL scheme. The fix adds a `validate()` guard that
137+ pushes a `CheckResult::fail` with the scheme error and returns early. (#3694)
138+ - fix(security): extend `classify_tool` to recognise bare shell and file-write tool IDs
139+ (`bash`, `shell`, `write_file`, `write`, `create_file`) so `ShadowProbeExecutor` probes
140+ trigger correctly when callers omit the `qualified::` prefix. Closes #3744.
141+
152142### Changed
153143
154144- refactor(common,context): resolve `zeph-context → zeph-memory` same-layer violation (#3665).
@@ -157,15 +147,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
157147 `GraphRecallParams`, `TokenCounting`, `ContextMemoryBackend`) to `zeph-common::memory`.
158148 Added `SemanticMemoryBackend` adapter and `build_memory_router()` in `zeph-agent-context`.
159149 `zeph-context` no longer imports `zeph-memory`. Exception note removed from `specs/constitution.md`.
160-
161150- build: add `profiling` and `sandbox` to default Cargo features — tracing spans are compiled by
162151 default for diagnostics; macOS Seatbelt / Linux Landlock sandbox is available without
163152 `--features sandbox` (still runtime-disabled unless `tools.sandbox.enabled = true`)
164153- build: consolidate `self-check`, `env-vault`, and `task-metrics` as always-on — these were pure
165154 behavioral markers with no optional deps, violating the feature flag decision rule (spec 029 §2)
166-
167- ### Fixed
168-
169155- docs(specs): update spec 001 §9 and spec 029 §3.1/§4/§5.3 to reflect actual default feature set
170156 (was documenting `default = ["scheduler", "sqlite"]` since v0.18 while reality had 5 features
171157 since v0.20)
@@ -5793,7 +5779,8 @@ let agent = Agent::new(provider, channel, &skills_prompt, executor);
57935779- Agent::run() uses tokio::select! to race channel messages against shutdown signal
57945780
57955781[0.16.0]: https://github.com/bug-ops/zeph/compare/v0.15.3...v0.16.0
5796- [Unreleased]: https://github.com/bug-ops/zeph/compare/v0.20.2...HEAD
5782+ [Unreleased]: https://github.com/bug-ops/zeph/compare/v0.21.0...HEAD
5783+ [0.21.0]: https://github.com/bug-ops/zeph/compare/v0.20.2...v0.21.0
57975784[0.20.2]: https://github.com/bug-ops/zeph/compare/v0.20.1...v0.20.2
57985785[0.20.1]: https://github.com/bug-ops/zeph/compare/v0.20.0...v0.20.1
57995786[0.20.0]: https://github.com/bug-ops/zeph/compare/v0.19.3...v0.20.0
0 commit comments