# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.2.1] - 2026-04-25

**Patch release** — 修掉 v0.2.0 的 Reflection iteration-reset bug，并新增 Planning Pattern
与 Producer-Reviewer Reflection 两大 Agentic Design Patterns 能力。所有改动对 v0.2.0 完全
**向后兼容**；老 Plugin / 老 API 零改动即可升级。

### Fixed

- **`CMDC.Plugin.Builtin.Reflection` iteration reset 死循环** — v0.2.0 该插件在多轮评审时
  `iteration` 会被意外重置，导致在某些回合顺序下 Agent 永远不会真正 finish。引入 `phase ::
  :idle | :reviewing | :done` 状态机彻底修复，`:done` 之后 `:before_finish` 不再触发。
- **`CMDC.Plugin` behaviour `describe/0` callback 类型声明** — 放宽到 `String.t() | map()`，
  消除 `CMDC.Plugin.Builtin.ModelRouter.describe/0` 的 dialyzer callback_type_mismatch 警告。
  老插件返回 String 保持有效。

### Added — Phase 11D · Planning + Reflection（对齐 ADP Ch4+Ch6+Ch7+Ch11）

Agentic Design Patterns 对齐首批能力，基于 O'Reilly《Agentic Design Patterns》一书 Ch4 Reflection、
Ch6 Planning、Ch7 Multi-Agent Collaboration、Ch11 Goal Setting and Monitoring 四章设计。

- **`CMDC.Plan` / `CMDC.Plan.Step`（new）** — 显式 Plan 数据结构，含 `step_started/2`、`step_completed/3`、
  `step_failed/3`、`step_skipped/3`、`annotate_step/3`、`approve/1`、`progress/1`、`to_markdown/1`、
  `to_prompt_section/1`。每个 step 有 `:pending | :in_progress | :completed | :failed | :skipped` 状态。
- **`CMDC.Plan` replan API（ADP Ch6 适应性要求）** — `replace_steps/2` 整体重规划、`add_step/3` 追加、
  `insert_step/4` 在指定锚点前/后插入、`remove_step/2` 删除。所有修改自动打 `last_replanned_at` 时戳。
- **`CMDC.Agent.State.dynamic_context_sections`（new）** — Agent 状态新增此字段，Plugin 可通过
  `{:emit, {:update_system_context, key, text}, state}` 事件把内容动态注入下一轮 system prompt。
  `SystemPrompt` 的 `:full / :task / :minimal` 三种模式都会合并这些动态段落。
- **`CMDC.Context.last_assistant_reply`（new）** — 只读 Context 新增此字段，Plugin / Tool 可直接拿到
  最后一条 AI 回复全文，无需自己翻 `messages`。
- **`CMDC.Plugin.Builtin.Planning`（new）** — plan-first 规划插件。对较长 prompt 先 `intervene` 要求
  LLM 产出 markdown checklist，`after_response` 解析为 `CMDC.Plan` 并通过 `dynamic_context_sections`
  把 plan 持续注入 system prompt。失败重试（`max_plan_attempts: 2`）兜底，放弃后不阻塞主流程。
  emit `{:plan_generated, %CMDC.Plan{}}`。
- **`CMDC.Plugin.Builtin.Reflection` 大重构（modified）** — 修掉 v0.2 的 iteration reset 死循环 bug：
  - 新 `phase :: :idle | :reviewing | :done` 状态机，`:done` 之后 `:before_finish` 不再触发，杜绝无限循环。
  - `max_reviews`（原 `max_iterations` 作为兼容别名）。`pass_signal` 支持字符串或 `%Regex{}`。
  - **`reviewer_subagent: true`** — ADP Ch4+Ch7 推荐的 Producer-Reviewer 分离：启动独立 Reviewer
    SubAgent（`CMDC.Agent.start_link` 新进程），可用 `reviewer_model` 指定不同模型评审主 Agent 输出，
    显著降低同模型自评的认知偏差。SubAgent 失败自动降级为内联自评，永不阻塞主会话。
  - emit `{:reflection_approved, %{critique, iteration}}`。
- **Agent before_prompt intervene（modified）** — `CMDC.Agent` 在 `idle` 状态处理 `{:prompt, text}`
  和 `do_steer/5` 中的 `:passthrough_to_prompt` 分支，现在正确处理 `{:intervene, prompt, state}`
  返回值：把 intervene prompt 作为 user 消息追加，并广播 `{:intervention, prompt}` 事件。

### Changed

- `CMDC.Agent.broadcast_emitted_events/2` 支持 3-tuple emit 事件（被包装成
  `{:plugin_event, name, {a, b}}`），用于 `{:update_system_context, key, text}` 等 Plugin→Agent
  状态同步。
- `CMDC.Agent.State.to_context/1` 自动填充 `last_assistant_reply`。

### Tests

- `test/cmdc/plan_test.exs` — `CMDC.Plan` 全量单测（新加 47 tests, 16 doctests）。
- `test/cmdc/plugin/builtin/planning_test.exs` — Planning 插件 14 tests。
- `test/cmdc/plugin/builtin/reflection_test.exs` — Reflection 18 tests（完整多轮循环、`phase` 状态机、
  regex pass_signal、SubAgent 兜底降级）。
- `test/cmdc/agent/integration_test.exs` — 新增 Planning E2E 2 tests + Reflection SubAgent Reviewer
  E2E 3 tests，含多轮 Producer-Reviewer 循环。
- 全量 **21 doctests + 1063 tests, 0 failures, 5 skipped**（v0.2.0 基线 1060 → v0.2.1 共 1063，
  所有新模块单元测试累计 47 (Plan) + 14 (Planning) + 18 (Reflection) = 79，
  集成测试累计 Planning E2E ×2 + Reflection SubAgent E2E ×3 = 5 条新端到端）。
- `mix dialyzer` passed successfully（v0.2.0 遗留 `model_router.ex` callback 警告一并修复）。

## [0.2.0] - 2026-04-24

This is a major feature release aligning CMDC with the 13 RFC proposals from the
Hive enterprise-agent team (April 2026) **plus** the four Phase 10 items originally
planned for v0.2 (`Steering`, `PromptMode`, `MemoryFlush`, `ModelRouter`).

All additions are **additive and backward-compatible** unless otherwise noted under
"Breaking". Integration code written for v0.1 continues to work with zero changes.

**Stats**: `+17` new features • `991` total tests (0 failures, 5 skipped) • `82.5%`
line coverage (up from 79.2%; four built-in plugins lifted from 0% → 100%) • `0` deprecations.

### Added — Facade API (RFC A1–A4)

- **`CMDC.Options.user_data`** (RFC A1) — opaque business-context map, propagated verbatim
  into `CMDC.Context.user_data`. SubAgent and `Tool.Task` inherit automatically unless
  the subagent explicitly sets its own `user_data`.
- **`CMDC.create_agent(messages: [...])`** (RFC A2) — inject prior history at boot so
  resumed / cloned sessions continue the LLM turn sequence naturally; accepts
  `%CMDC.Message{}` structs or maps.
- **`CMDC.approve/3` and `CMDC.reject/3` with `:auto_resume`** (RFC A3) — approve now
  auto-resumes the turn by default (`auto_resume: true`); reject defaults to
  `auto_resume: false`. Both emit `:agent_resumed` event when they actually restart a
  turn, so UIs can follow without race conditions. Legacy `approve/2` / `reject/2`
  still work (`auto_resume: true / false` defaults).
- **`normalize_session/1` + session-as-string everywhere** (RFC A4) — every public API
  accepts `pid() | String.t()`; `subscribe/1` can target not-yet-started sessions
  (common for UI pre-mount subscribe); `user_respond/3` broadcasts by session id
  without SessionRegistry round-trip.

### Added — Protocol (RFC B5–B7)

- **`%CMDC.TokenUsage{}`** (RFC B5) — typed struct `{input, output, total, cache_read,
  cache_write}`; all token-bearing events (`:after_response`, `:turn_complete`,
  `:agent_finished`) now emit this struct. Legacy map format remains readable.
- **`CMDC.abort/2` options** (RFC B6) — `reason:` (defaults `:user_abort`, embedded in
  `:agent_abort` event), `kill_tools:` (`:running` default / `:all` / `:none`),
  `clear_queue:` (default `true`). Documented 4-state behavior matrix and the
  `100ms within` emit guarantee for `:agent_abort`.
- **Plugin Hook × Action matrix** (RFC B7) — `docs/guides/plugin-matrix.md` with full
  11×7 table plus 5 copy-paste Cookbook scenarios (block tool, rate-limit, audit
  log, cost guard, steering-on-loop).

### Added — Runtime Control (RFC C8–C12)

- **`CMDC.switch_model/2`** (RFC C8) — change the LLM model mid-session; emits
  `:model_switched` with `{from, to, reason, turn, ts}`. Also exposed as a Plugin
  action `{:switch_model, new_model, state}` (used by the upgraded `ModelRouter`).
- **`CMDC.attach_tool/2` / `CMDC.detach_tool/2`** (RFC C9) — runtime toolset mutation.
  Emits `:tool_attached` / `:tool_detached`. If the LLM later calls a detached tool,
  the kernel emits `:tool_call_unknown` (no crash, no hang) and returns a tool_result
  error so the next turn lets the LLM self-correct.
- **EventBus replay buffer + `subscribe(:since)`** (RFC C10) — every session keeps a
  bounded ring of past events (default 500); subscribers can recover missed events on
  reconnect via `CMDC.subscribe(session, since: ts | event_id)`.
- **`CMDC.status/1` extensions** (RFC C11) — now returns
  `pending_tools`, `pending_approvals`, `pending_user_inputs`, `queue_sizes`
  (pending prompts / steerings) so dashboards can reflect the true "what is the
  agent blocked on right now".
- **`CMDC.monitor/1` + structured reason** (RFC C12) — `Process.monitor`-style API
  that returns a structured reason map (`{:normal | :shutdown | :exception |
  :max_turns_exceeded | :provider_timeout | {:plugin_aborted, name, why}}`) instead
  of the raw OTP term. Use `CMDC.demonitor/2` to cancel.

### Added — Event Protocol (RFC D14)

- **Generic `:plugin_event` event** — unified envelope
  `{:plugin_event, %{kind: atom, v: integer, session_id, occurred_at, ...}}` that all
  built-in and third-party plugins use to publish business-level events to EventBus.
  Subscribing to a single event gives the integrator access to every plugin's
  structured output. First producer: `MemoryFlush` (`kind: :memory_flush`).

### Added — Phase 10 (original roadmap)

- **10A. Steering** — `CMDC.steer(session, instruction)` injects a mid-run "soft
  interrupt" without aborting. Queued when busy (default `max=3`), applied at the
  next safe point, emits `:steering_applied`. Plugins can gate via new
  `:before_steering` hook.
- **10B. PromptMode** — new `CMDC.Options.prompt_mode` field with 4 values:
  - `:full` (default) — full BasePrompt + identity + tools + Skills + Memory
  - `:task` — compact base for focused subagents (saves ~50% tokens)
  - `:minimal` — tool-name list only, no descriptions (saves ~90%)
  - `:none` — completely delegated to user-provided `system_prompt`

  `SubAgent` defaults to `:task` (SDK-level token savings); `Tool.Task` propagates
  the mode to children; 8-layer SubAgent chain drops from ~7200 to ~2400 tokens.
- **10C. MemoryFlush plugin** — new `CMDC.Plugin.Builtin.MemoryFlush` subscribes
  to the new `:before_compact` event, extracts key facts via configurable
  `extract_fn` (heuristic default, LLM-pluggable), deduplicates with SHA256, and
  appends to `working_dir/MEMORY.md`. Closes the loop with `MemoryLoader` for
  true long-session memory across restarts. Emits both `:memory_flushed`
  (internal) and `:plugin_event` (kind `:memory_flush`, per RFC D14).
- **10D. ModelRouter v2** — `Plugin.Builtin.ModelRouter` now uses
  `{:switch_model, ...}` action (no more `[系统]` message pollution) and adds five
  new business-friendly condition families on top of the original three runtime
  conditions:
  - `:token_budget_lt` — remaining budget from `user_data[:token_budget]`
  - `:task_complexity` / `:task_complexity_in` — `:simple` / `:normal` / `:complex`
  - `:time_of_day_in` — list of UTC-hour ranges (with injectable `now_fn`)
  - `:user_tier` / `:user_tier_in` — `:free` / `:pro` / `:enterprise` / custom
  - `:user_data, key, value` and `:user_data, key, op, value` (`:eq/:gt/:lt/:gte/:lte`)

  Robustness: all conditions run inside a `rescue` wrapper; `user_data = nil` and
  unknown condition tuples safely degrade to `false`.

### Changed

- `ModelRouter` no longer injects `[系统] 已切换到模型 X` assistant messages; uses
  `{:switch_model, ...}` Plugin action + `:model_switched` event instead. Conversation
  history remains clean.
- `HumanApproval` / HITL flow now emits `:agent_resumed` when `approve(auto_resume: true)`
  actually restarts the turn (was previously silent).
- `CMDC.Agent` emits `:before_compact` event (new plugin hook) before Compactor runs,
  giving plugins a chance to persist facts before summarization.

### Fixed

- `CMDC.subscribe("session-id")` on a not-yet-started session no longer raises
  `ArgumentError`; it now succeeds and delivers events as soon as the session starts
  (RFC A4).
- `Plugin.Pipeline` `{:emit, ...}` action can now emit multiple events in a single
  return (`{:emit, [{name1, payload1}, ...], state}`) and accepts a 3-tuple shortcut
  `{:emit, name, payload, state}`.

### Breaking

- `Plugin.Builtin.ModelRouter` behavior change: existing users who relied on the
  `[系统] 已切换到模型 X` message being injected into context must migrate to subscribe
  `:model_switched` events or consume the new `:switch_model` action's side effects.
  Most users will experience this as a cleaner UX.

### Documentation

- `docs/guides/plugin-matrix.md` — complete 11 hooks × 7 actions matrix + 5 Cookbook
  scenarios (RFC B7).
- `docs/dev/rfc/2026-04-hive-feedback-review.md` — official response to the Hive team,
  documenting every accepted RFC's design decisions and migration paths.
- `llm.txt` / `llms-full.txt` — updated with PromptMode, MemoryFlush, ModelRouter v2,
  `:plugin_event`, `switch_model/2`, `attach_tool/2`, `monitor/1`, `:since` replay,
  and `status/1` extensions.
- `docs/dev/KNOWLEDGE.md` — added sections 5.24 / 5.25 / 5.26 documenting pitfalls
  found during 10B / 10C / 10D implementation (SubAgent token explosion, memory
  flush robustness, ModelRouter current_model state chain).

[0.2.0]: https://github.com/tuplehq/cmdc/releases/tag/v0.2.0

## [0.1.1] - 2026-04-08

### Fixed

- 修复 ex_doc 文档 10 处引用 warning（隐藏函数引用、不存在函数引用、LICENSE 文件缺失）
- LICENSE 文件加入 HexDocs extras
- README 许可证描述和联系方式更正

## [0.1.0] - 2026-04-08

Initial release of CMDC — Elixir Agent Kernel.

### Added

#### Core Infrastructure (L0)
- `CMDC.Options` — typed struct with NimbleOptions schema for AI-friendly agent configuration; all fields with precise `doc:` annotations
- `CMDC.Config` — application-level configuration struct with provider routing (`resolve_provider/2`)
- `CMDC.Context` — runtime execution context passed to Tools and Plugins
- `CMDC.Message` — typed message struct supporting system/user/assistant/tool_result roles; `@derive Jason.Encoder`
- `CMDC.Event` — 22 structured event types covering full agent lifecycle
- `CMDC.EventBus` — Registry-based PubSub; `subscribe/1`, `broadcast/2`, `subscribe_all/0`
- `CMDC.SubAgent` — declarative sub-agent specification struct with `nil`-means-inherit semantics

#### Core Abstractions (L1)
- `CMDC.Plugin` — behaviour with 11 event hooks and 7 action types (continue/intervene/abort/skip/block_tool/replace_tool_args/emit)
- `CMDC.Plugin.Pipeline` — priority-ordered plugin execution with short-circuit support
- `CMDC.Plugin.Registry` — plugin registration with deduplication and priority sorting
- `CMDC.Tool` — behaviour with `name/0`, `description/0`, `parameters/0`, `execute/2`; result type `{:ok, text} | {:error, text} | {:effect, term}`
- `CMDC.Sandbox` — behaviour abstracting file/command execution (8 callbacks); `CMDC.Sandbox.Local` as default OS implementation
- `CMDC.Skill` — SKILL.md discovery, loading, and system prompt injection
- `CMDC.Blueprint` — behaviour for declarative reusable agent configurations; struct pipeline helpers (`add_tools/2`, `add_plugins/2`, etc.)
- `CMDC.Provider` — thin `req_llm` wrapper; `stream/4`, `convert_messages/2`, `convert_tools/1`
- `CMDC.Provider.StreamBridge` — converts `ReqLLM.StreamResponse` into gen_statem messages

#### Agent Kernel (L2)
- `CMDC.Agent` — `gen_statem` state machine with 4-state loop: `idle → running → streaming → executing_tools`
- `CMDC.Agent.State` — runtime state with token/cost tracking, loop detection hashes, sandbox/todos/memory fields
- `CMDC.Agent.Stream` — streaming delta accumulation with XML tag extraction (`<status>`, `<title>`)
- `CMDC.Agent.ToolRunner` — parallel tool execution with built-in loop detection (exact duplicate + pattern + consecutive failure) + tool retry with `on_tool_error` Plugin hook; configurable via `:tool_max_retries` (default 0) and `:tool_retry_delay_ms` (default 500ms)
- `CMDC.Agent.Emitter` — EventBus event broadcasting with ETS ring buffer for recent event retrieval
- `CMDC.Agent.BasePrompt` — default base prompt aligned with DeepAgents `BASE_AGENT_PROMPT`
- `CMDC.Agent.SystemPrompt` — system prompt assembly: BasePrompt + user prompt + blueprint identity + skills + memory
- `CMDC.Agent.Compactor` — automatic context compaction; token-based trigger with character estimation fallback; offload to file
- `CMDC.Agent.Compactor.ArgTruncator` — pre-truncation of large tool arguments (write_file/edit_file/execute)

#### Built-in Plugins (6)
- `CMDC.Plugin.Builtin.SecurityGuard` (priority 10) — path and command blacklist enforcement
- `CMDC.Plugin.Builtin.HumanApproval` (priority 15) — HITL approval flow via `approval_required` events
- `CMDC.Plugin.Builtin.EventLogger` (priority 50) — JSON Lines session audit log
- `CMDC.Plugin.Builtin.MemoryLoader` (priority 100) — AGENTS.md loading and `<agent_memory>` injection; auto-reload on write_file/edit_file
- `CMDC.Plugin.Builtin.PatchToolCalls` (priority 120) — synthetic tool result injection for dangling tool_calls
- `CMDC.Plugin.Builtin.PromptCache` (priority 130) — Anthropic prompt caching headers; auto-skip for other providers

#### Built-in Tools (11)
- `CMDC.Tool.ReadFile` — file reading with offset/limit pagination; Sandbox proxy
- `CMDC.Tool.WriteFile` — file writing with parent directory creation; Sandbox proxy
- `CMDC.Tool.EditFile` — exact string replacement (str_replace); Sandbox proxy
- `CMDC.Tool.Shell` — shell command execution; large output auto-saved to temp file; Sandbox proxy
- `CMDC.Tool.Grep` — regex file search with line numbers and glob filtering; Sandbox proxy
- `CMDC.Tool.ListDir` — directory listing with type and size; Sandbox proxy
- `CMDC.Tool.Glob` — glob pattern file matching; Sandbox proxy
- `CMDC.Tool.Task` — OTP-process-level sub-agent spawning under SubAgent.Supervisor; broadcasts `subagent_start`/`subagent_end`
- `CMDC.Tool.WriteTodos` — Context.todos update with `todo_change` event broadcast
- `CMDC.Tool.AskUser` — pause execution, wait for `user_responded` event
- `CMDC.Tool.CompactConversation` — manual context compaction trigger

#### Integration Layer (L3)
- `CMDC.SessionServer` — per-session Supervisor tree (Agent + SubAgent.Supervisor)
- `CMDC.SubAgent.Supervisor` — DynamicSupervisor for isolated child agent processes (`:temporary` restart)
- `CMDC.MCP.Bridge` — dynamic CMDC.Tool module generation from MCP server tool definitions
- `CMDC.MCP.Client` — `anubis_mcp`-based MCP client with Registry naming per server
- `CMDC.MCP.Supervisor` — DynamicSupervisor for MCP client processes
- `CMDC.MCP.Config` — mcp.json discovery with multiple path fallbacks
- `CMDC.Memory.ETS` — ETS-backed key-value memory store with keyword search
- `CMDC.Gateway` / `CMDC.Gateway.Local` — outbound event reporting contract and local EventBus implementation

#### Public API (L4)
- `CMDC` — facade with `create_agent/1`, `prompt/2`, `collect_reply/2`, `stop/2`, `abort/1`, `subscribe/1`, `unsubscribe/1`, `approve/2`, `reject/2`, `status/1`, `agent_pid/1`, `session_id/1`
- `CMDC.Blueprint.Base` — built-in base blueprint (SecurityGuard + EventLogger + PatchToolCalls)

#### Documentation
- `README.md` — Quick Start, feature comparison table (CMDC vs DeepAgents), architecture diagram, built-in tool/plugin tables
- `llm.txt` — AI quick reference (~230 lines): all public API signatures, parameter types, common patterns
- `llms-full.txt` — AI complete reference (~999 lines): event protocol, Tool/Plugin development guide, 14 known pitfalls

[0.1.0]: https://github.com/tuplehq/cmdc/releases/tag/v0.1.0
