# Changelog

<!-- markdownlint-disable MD024 -->

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).

## [0.21.15] - 2026-05-22

### Added

- **Global outbound proxy** - added `tools.proxy` / `FACIO_PROXY` as the canonical runtime-wide proxy setting for browser, web, exec subprocesses, and container proxy env files, with live Management API updates and legacy `FACIO_BROWSER_PROXY` compatibility.

### Fixed

- **Browser proxy credentials** - browser launch proxy configuration now splits username/password out of proxy URLs before handing them to Playwright/Camoufox, fixing authenticated proxies that work for fetch but fail in Firefox/Chromium.

## [0.21.14] - 2026-05-22

### Added

- **GitHub backup sync** - added optional GitHub backup configuration for the local GitStore, including env and settings API support, Placet SecretStore token resolution, startup pull, auto-push after local commits, and display-safe backup status.
- **Private backup repository creation** - GitHub backup can now check for the configured repository on startup and create it as a private repo when it is missing, while still remaining fully disabled when no backup config is enabled.

### Changed

- **GitHub token labeling** - the shared `GITHUB_TOKEN` secret is now labeled as a general GitHub token so it can be used by GitHub backup without conflicting semantically with the `github` skill.

### Fixed

- **Exec runtime hardening** - Unix `exec` commands now run in their own process group so timeouts clean up child processes, and Node/npm/npx invocations get bounded Node heap and quiet npm defaults to reduce container OOM/restart risk during package installs.
- **Provider override display** - Placet settings now show the provider fallback as `default` instead of leaking the internal `__default__` sentinel.
- **Optional backup robustness** - disabled GitHub backup no longer calls GitHub at all, and GitHub API failures during optional remote setup are recorded in backup status instead of breaking agent startup.

## [0.21.13] - 2026-05-21

### Added

- **Self-improvement phase pipeline** - added phase-aware self-improvement reviews with cadence controls, active phase prompts, staged overlay provenance, conflict reporting, and richer review reports so `/improve` proposals can be inspected and rolled back more reliably.
- **Rich skill manifests** - added normalized skill manifests with indexed references, templates, scripts, assets, platform gates, dependency declarations, and startup/create/load dependency policy controls exposed through management settings.
- **Skill usage telemetry** - added audit events and a `skill_usage` tool so self-improvement reviews and operators can inspect skill summary exposure, context loads, explicit reads, missing requirements, and token estimates.

### Changed

- **Self-improvement proposal transport** - `/improve` now treats sandboxed file-tool writes, including `patch_file`, as the authoritative proposal source instead of depending on final LLM JSON.
- **Reflection skill suggestions** - Reflection now records reusable workflow suggestions in `memory/SKILL_NOTES.md` for later Improve review instead of writing skill files directly.
- **Skill creator scaffolding** - the built-in skill creator now emits the richer manifest shape, supports `templates/`, and validates script resource contracts with declared help commands.

### Fixed

- **Skill dependency safety** - metadata and summary reads no longer trigger dependency installation, skill upload dependency installation no longer blocks the aiohttp event loop, unsupported platforms are skipped before install, and management settings accept the same camelCase dependency-policy fields they return.
- **Skill availability gates** - rich manifest platform, environment, binary, and file requirements now participate in skill availability filtering and summary reporting.
- **Improve inconclusive reviews** - `/improve` now marks final text-mode tool-call output as failed validation instead of reporting `no_change` when the review never produced a real conclusion.
- **Agent finalization retry** - final answers that contain only text-mode tool-call markup now get one no-tools textual-finalization retry before being accepted as completed output.
- **Browser crash recovery** - browser tools now surface crashed or closed Playwright pages as explicit resettable errors instead of returning successful empty snapshots.
- **Browser screenshot artifacts** - repeated screenshots now use unique file names so successful captures do not overwrite each other or look identical to loop detection.
- **Runtime self-debugging** - log inspection now points agents toward `read_logs(grep=...)`, runner stuck-loop messages no longer claim successful repeated tool calls are failures, and caught tool exceptions are warning-visible.
- **Provider capacity handling** - DeepSeek-routed models now get a lower default local request concurrency unless operators explicitly override it, and transient retry logs include provider, model, and reasoning context.
- **Cron robustness** - startup now removes stale protected `dream` system jobs superseded by Reflection, and cron jobs that produce only empty or punctuation-only output are treated as failed.
- **DeepSeek gateway history** - gateway-routed DeepSeek thinking models now retain tool history by backfilling empty reasoning metadata instead of repeatedly pruning large conversation chunks.
- **Runtime dependency declaration** - PyYAML is now declared as a direct runtime dependency for rich YAML skill manifests.

## [0.21.12] - 2026-05-20

### Added

- **Central agent versioning** - added a Git-backed agent version store for agent-owned workspace state such as memory, skills, scripts, MCP configuration, policy rules, cron jobs, channels, A2A data, and workspace control files. Management clients can now list versions, create checkpoints, inspect diffs, and roll back through `/api/v1/agent/versions`, while rollbacks rehydrate MCP, policy, and cron runtime state where possible.
- **Self-improvement run ledger** - added proposal, review, approval, rejection, apply, and rollback tracking for self-improvement runs, with persistent reports, diff artifacts, validation checks, and management API access through `/api/v1/improvement/runs`.
- **`/improve` command** - added an operator flow where `/improve` runs an intelligent read-only review and creates a proposal only when useful, while `/improve diff [id]`, `/improve apply [id]`, `/improve cancel [id]`, and `/improve rollback <id>` manage the proposal lifecycle from chat or CLI channels.
- **`/version` command** - added a registered slash command and Placet menu entry that reports Facio runtime version information directly, without falling back to an LLM-generated `pip show` tool call.
- **Automatic self-improvement triggers** - self-improvement reviews can now run after goal completion, repeated tool errors, user corrections, or on a scheduled interval, with cooldown and no-change pruning to avoid noisy repeated runs.
- **Self-improvement settings API** - management settings now expose self-improvement mode, triggers, schedule interval, model/provider overrides, comprehensive scopes, and validation level.
- **Reflection auto-apply setting** - management settings now expose a separate `reflection_auto_apply` control so scheduled Reflection application can be disabled without changing self-improvement apply mode.

### Changed

- **Reflection version history** - Reflection now writes changes into the central agent version store when available, and `/reflection-log` plus `/reflection-restore` can inspect or restore those central versions instead of relying only on the legacy memory Git history.
- **Versioned management mutations** - MCP and policy management writes now create central agent-version checkpoints so runtime configuration changes can be audited and rolled back alongside Reflection and self-improvement changes.
- **Self-improvement core** - manual and automatic reviews now use the agent runner with a narrow read-only tool registry to inspect agent-owned files and runtime evidence before emitting structured proposals.
- **Self-improvement review budget** - the default self-improvement review loop now allows 12 tool-call iterations and tells the model the current iteration plus remaining budget on every request.
- **Pending proposal policy** - automatic and manual self-improvement reviews now refuse to create another proposal while a previous proposal is still awaiting review.

## [0.21.11] - 2026-05-12

### Added

- **Goal loop commands** - added `/goal`, `/subgoal`, and `/checklist` so users can set a persistent multi-turn objective, inspect or edit its checklist, pause/resume/clear it, and stop active goals through the regular `/stop` path. Goal progress now records dedicated audit events and can be bounded with the new `agents.defaults.max_goal_turns` setting, including management API and Placet settings support.
- **Heartbeat runtime controls** - added `/heartbeat status|pause|resume|clear` for inspecting Heartbeat state, pausing or resuming the service, and clearing stale Heartbeat runtime metadata or messages without editing session storage by hand.

### Changed

- **Heartbeat and Cron boundary** - Heartbeat is now reserved for fuzzy, state-based checks. Clock-based or recurring entries in `HEARTBEAT.md` are detected before LLM execution, skipped with a warning, and documented in the default `AGENTS.md` and `HEARTBEAT.md` templates as Cron-only work.

### Fixed

- **Provider setup recovery** - registered local setup commands such as `/settings` can run when no working LLM provider exists, while provider-dependent commands remain behind the setup gate. Placet provider repair now opens a provider-only form, keeps non-Placet channels on a text fallback, persists the selected default provider, and restores the Placet channel wiring expected by settings and credential forms.

## [0.21.10] - 2026-05-11

### Changed

- **Audit correlation basics** - audit events and token usage now persist turn, trace, parent-run, and channel-instance identifiers, migrate existing SQLite audit databases in place, categorize internal/Reflection audit events, and expose matching audit and usage filters for management clients.
- **Audit event context** - MCP tool executions are now recorded as `mcp_call` events while preserving the full `tool_name`, and LLM request/response audit rows now include explicit status values for management clients.

### Fixed

- **DeepSeek thinking history** - OpenAI-compatible gateway routes such as OpenCode Go now apply the same DeepSeek reasoning-history cleanup and `reasoning_content` replay safeguards as the direct DeepSeek provider.
- **Audit identity defaults** - root audit contexts now generate distinct run, turn, and trace identifiers while resumes and subagents continue to inherit the turn and trace identifiers from their parent execution.

## [0.21.9] - 2026-05-10

### Changed

- **Runtime provider onboarding** - when the gateway starts or receives messages without a working LLM provider, it keeps running, answers with a provider-setup hint, reopens Placet onboarding as needed, and hot-loads the validated provider after setup completes.

## [0.21.8] - 2026-05-10

### Changed

- **Memory consolidation rebranding** - memory consolidation now uses Reflection naming across runtime state, commands, configuration, management API, Placet UI, prompt templates, tests, and docs. The manual command is `/reflect`, history commands are `/reflection-log` and `/reflection-restore`, and management settings use `reflection_interval_h`.

## [0.21.7] - 2026-05-09

### Changed

- **Session replay hygiene** - conversation replay now strips copied assistant-side runtime artifacts such as message-time prefixes, local image breadcrumbs, and generated-tool echoes before they become in-context examples. Media breadcrumbs are now synthesized only for user messages, while provider reasoning state such as `thinking_blocks` is preserved for replay.
- **DeepSeek and DashScope reasoning compatibility** - DeepSeek V4/reasoner history now receives `reasoning_content` backfill even when reasoning is implicit, and DashScope keeps its `minimum` wire value while Facio treats it semantically like `minimal`.

### Fixed

- **Cron store durability** - cron job persistence now uses atomic replace semantics, preserves corrupt `jobs.json` files for inspection, refuses to start from an initially corrupt store instead of silently overwriting it with an empty list, keeps the last good in-memory store during hot-reload corruption, and persists Facio-specific cron payload fields such as `detailPrompt`, `scripts`, `requireApproval`, `channelMeta`, `sessionKey`, and `browserSession`.
- **Dream cursor safety** - Dream mode now advances `.dream_cursor` only after Phase 2 completes successfully, so incomplete tool runs or exceptions retry the batch instead of silently losing history entries.
- **Exec workspace guard precision** - benign device paths such as `/dev/null`, `/dev/stderr`, and `/dev/fd/*` no longer trip the workspace guard, while real outside-workspace redirects remain blocked.
- **Repeated workspace-boundary attempts** - repeated attempts against the same blocked outside-workspace target are throttled per run, while Facio's existing PolicyGate remains the source of policy decisions.
- **Voice transcription resilience** - OpenAI and Groq transcription now retry transient HTTP and network failures without retrying non-transient auth/config failures.
- **Channel authorization ordering** - Email sender allowlist checks now run before attachment extraction and reply-state updates, and Telegram callback authorization now runs before answering callbacks, editing markup, typing indicators, or dispatching message handling.
- **Slack channel parity** - Slack Socket Mode now handles ask-user button clicks, accepts user `file_share` events, downloads private Slack files only after channel-aware authorization, preserves explicit DM thread replies without threading top-level DMs, and keeps Slack policy checks channel-aware before handing messages to the bus.
- **Discord channel authorization coverage** - Discord inbound tests now lock in that denied senders do not trigger attachment downloads, typing indicators, reactions, or message dispatch, and that thread channels inherit their parent-channel allowlist.
- **CLI input sanitization** - interactive CLI input and history storage now reconstruct valid surrogate pairs and replace lone surrogates so malformed terminal input does not crash or corrupt downstream processing.
- **MCP config durability** - runtime writes to `mcp.json` now use same-directory temp files, fsync, and atomic replacement so failed writes preserve the previous config.

## [0.21.6] — 2026-05-09

### Added

- **Standalone credential management tool** — agents now use a dedicated `manage_credentials` tool for listing and deleting stored credential keys and LLM provider credentials, keeping credential workflows separate from MCP server management.

### Fixed

- **Shared runtime credential store** — the agent loop, MCP manager, and management API now share the same `CredentialStore` instance in-process, so secrets captured through chat are visible through the API without requiring a restart.
- **LLM provider key routing** — password fields whose keys match registered LLM provider env vars, such as `OPENROUTER_API_KEY`, are now routed into the provider configuration as well as the generic credential store.

## [0.21.5] — 2026-05-08

### Changed

- **Provider API base management** — Placet onboarding and the management credentials API now accept provider `apiBase`/`baseUrl` settings alongside API keys. Local/direct providers such as `custom`, `vllm`, `ollama`, `lm_studio`, `ovms`, and `azure_openai` can now be configured through the onboarding and management flows, while the existing runtime provider pool continues to consume `providers.<name>.apiBase` without additional routing changes.

### Fixed

- **Quickstart Compose PID limits** — the install-script compose file now sets matching PID limits in both `pids_limit` and `deploy.resources.limits.pids`, avoiding Docker Compose failures such as `can't set distinct values on 'pids_limit' and 'deploy.resources.limits.pids'` during initial setup.

## [0.21.4] — 2026-05-08

### Changed

- **Central provider error formatting** — user-facing LLM error messages are now produced by a single `LLMProvider._format_error_message` helper. It walks the common JSON shapes (`error.message`, `message`, `detail`, `errors[]`, plain `error` strings, JSON-encoded text bodies) and falls back cleanly to plain response text or `Error calling {label}: {exc}` when nothing parses. The Anthropic, Azure OpenAI and OpenAI-compatible providers route their `_handle_error` paths through this helper so users see the upstream message instead of a raw JSON dump regardless of provider, and unknown schemas no longer leak as `str(dict)`.
- **Provider defaults refreshed** — onboarding and provider fallback defaults now use current flagship or widely deployed model IDs: Claude Opus 4.7, GPT-5.5 for OpenAI and OAuth coding providers, Gemini 3.1 Pro Preview, DeepSeek V4 Pro, Groq-hosted GPT-OSS 120B, Mistral Medium 3.5, GLM-4.7, Qwen 3.6 Plus, Kimi K2.6, and MiniMax M2.7. OpenCode Go stays on its OpenAI-compatible `opencode-go/kimi-k2.6` default.

## [0.21.3] — 2026-05-07

### Added

- **OpenCode Zen Go provider** — Facio can now route requests to the OpenCode Zen Go subscription gateway via its OpenAI-compatible chat endpoint. The provider is wired into the registry, config schema (`providers.opencode_go`), and Placet onboarding flow (default model `opencode-go/kimi-k2.6`, key validation against `https://opencode.ai/zen/go/v1/models`). Set `OPENCODE_GO_API_KEY` or configure `providers.opencode_go.api_key` and use models prefixed with `opencode-go/`.

## [0.21.2] — 2026-05-07

### Changed

- **Agent loop refactoring completed** — the former monolithic `AgentLoop` flow was split into focused modules for streaming, loop hooks, channel context, session checkpoint handling, runtime integration, and tool registry setup, reducing coupling and keeping the core loop narrower and easier to validate.
- **MessageTool pre-send hook isolated per context** — the pre-send hook is now stored in a `ContextVar` instead of an instance attribute, preventing cross-session leakage when multiple parallel streaming turns share the same `MessageTool`.
- **Pending-queue race window closed** — the agent run loop registers the per-session pending queue synchronously before spawning the dispatch task, so a follow-up inbound arriving in the same loop tick is reliably routed for mid-turn injection instead of racing to spawn a competing task.
- **`/stop` and priority commands honour the effective session key** — priority-command dispatch and `cmd_stop` now look up active tasks by the loop's effective key, so unified-session setups can cancel in-flight work the same way regular sessions do.

### Added

- **`all_busy` runtime status** — when the per-session pending queue is full and a follow-up has to spawn a queued task, the runtime now emits an `all_busy` status so the UI can surface saturation distinctly from the regular `busy`/`active` cycle.
- **Direct unit tests for the extracted agent modules** — added focused edge-case tests for `StreamSession`, `LoopHook`, `channel_context`, `SessionCheckpointManager`, and `PlacetRuntimeIntegration` (53 new tests, total 2472 passing).

## [0.21.1] — 2026-05-06

### Added

- **Camoufox hardening & fingerprint controls** — the browser runtime now supports virtual-display WebGL in Docker, exposes Camoufox spoofing controls for OS, locale, screen bounds, WebGL vendor/renderer, fonts, low-level overrides, and can import BrowserForge fingerprints from settings or env.
- **Screenshot controls** — `browser_screenshot` now supports `full_page`, `width`, and `height`, so the agent can request either a full-page capture or a constrained viewport shot.

### Changed

- **Browser screenshots default to full pages** — tall pages and below-the-fold content are now captured without extra flags.
- **Model switching now requires explicit approval** — `switch_model action="switch"` is gated behind human approval instead of allowing silent self-swaps.
- **No-vision screenshot handling was softened** — screenshots are still saved when the active model cannot inspect images, but the tool only notes that the PNG should not be fed back into `read_file`.

### Fixed

- **Browser runtime reliability** — Docker builds now ship the required Firefox/Camoufox dependencies and prefetch the browser binary, screenshots are stored under the workspace and returned as workspace-relative paths, and BrowserForge fingerprint imports correctly rebuild nested fingerprint objects.
- **Browser interaction stability** — SPA snapshots no longer fall back to empty pages, navigation/actions wait through hydration, React-controlled inputs re-validate correctly, silent click failures are surfaced, and interactive refs stay in sync with truncated snapshots.

## [0.21.0] — 2026-05-04

### Added

- **Browser tool** — 14 agent-facing tools (navigation, content, interaction, sessions) with named sessions and persistent profiles, Camoufox (default) and Playwright Chromium backends, per-agent `domain_allowlist` / `domain_denylist` enforced before and after each action (incl. redirects), atomic `ensure_and_select` for race-free cron usage, and Management API + Placet UI surface. The new tool is enabled by default.

### Changed

- `get_config_path()` now honors `FACIO_CONFIG`, which keeps tests and operator overrides isolated from the default user config path.

## [0.20.5] — 2026-05-04

- Interactive CLI now surfaces provider retry-wait notices even when channel progress hints are suppressed.

## [0.20.4] — 2026-05-02

- First public open-source release of facio.
- Release-preparation pass across packaging, docs, quickstart, and operator-facing surfaces for public open-source use.
- Runtime polish for provider routing, memory isolation, approval flow, and release readiness.
- Hardening for URL handling, channel delivery, and crash-safe persistence.
- Regression coverage refreshed ahead of the public release.

## [0.20.3] — 2026-05-01

- Final internal refinement pass for memory cleanup, channel context, and safer runtime behavior.

## [0.20.2] — 2026-05-01

- Internal UX and reliability update for session history, status output, restart handling, and reminders.

## [0.20.1] — 2026-05-01

- Internal tuning release for dream-mode review and environment resolution.

## [0.20.0] — 2026-05-01

- Internal milestone for web-tool configuration, routing cleanup, and stronger tool safety.

## [0.19.0] — 2026-04-30

- Internal milestone expanding management APIs, provider setup, and runtime continuity.

## [0.18.0] — 2026-04-29

- Internal channel release adding Microsoft Teams support and retiring the legacy WebSocket transport.

## [0.17.1] — 2026-04-29

- Packaging fix release for Slack runtime dependencies.

## [0.17.0] — 2026-04-28

- Internal release engineering milestone for Docker images, setup flow, deployment hardening, and project docs.

## Earlier internal releases — 2026-04-14 to 2026-04-27

- Versions `0.16.4` through `0.16.0` focused on policy controls, runtime logging, session handling, and safer operator workflows.
- Versions `0.15.0` through `0.13.0` expanded channels, provider integrations, management surfaces, and runtime orchestration.
- Versions `0.12.1` through `0.10.0` tightened tooling, memory behavior, execution flow, and reliability work.
- Versions `0.9.0` through `0.7.0` pushed container, transport, and workflow foundations forward.
- Versions `0.6.0` through `0.1.0` established the initial internal runtime, onboarding flow, and core agent architecture that later became facio.
