# Changelog All notable changes to Agnes AI Data Analyst. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html), pre-1.0 — public surface (CLI flags, REST endpoints, `instance.yaml` schema, `extract.duckdb` contract) may shift between minor versions; breaking changes called out under **Changed** or **Removed** with the **BREAKING** marker. CalVer image tags (`stable-YYYY.MM.N`, `dev-YYYY.MM.N`) are produced for every CI build; semver tags (`v0.X.Y`) are cut at release boundaries and reference the same commit as a `stable-*` tag from the same day. --- ## [Unreleased] ## [0.54.14] — 2026-05-14 ### Changed - **Marketplace submission surfaces — clearer CTA + fuller guides (#308).** The curated-tab action-row CTA now reads "Submit a skill or plugin" (was "Submit a plugin") — skills are first-class on the curated shelf — with the same wording mirrored in the empty-state JS and the route titles so the surfaces can't drift. The curated guide (`/marketplace/guide/curated`) grows from a 4-line stub into a 3-step walkthrough of the Named Curator handoff plus a `.guide-fastpath` callout pointing lighter submissions at the Flea Market; the flea guide (`/marketplace/guide/flea`) grows from a 3-line stub into a 4-step walkthrough of the `/store/new` self-serve flow and its automated guardrails (manifest, content-quality, and prompt-injection scans). ### Fixed - **`agnes refresh-marketplace` now enables stack plugins in workspace settings (#307).** The reconcile step previously stopped at `claude plugin install --scope project`, which only writes the global plugin registry (`~/.claude/plugins/installed_plugins.json`). Without a corresponding entry in the workspace `.claude/settings.json` `enabledPlugins` map, Claude Code treats every installed stack plugin as disabled — `/plugins` hides them from the active section and their slash commands, skills, and agents are unreachable. Refresh now writes `"@agnes": true` to the workspace settings file after install and update, treating the user's marketplace stack as the source of truth and re-enabling any plugin that a prior local `claude plugin disable` had turned off. - **Runtime CLI commands now work on Initial Workspace Template (override) workspaces (#307).** The `.claude/init-complete` sentinel carrying `override: true` previously short-circuited **every** Agnes writer to `.claude/`, which trapped admin-templated workspaces at a stale snapshot: `agnes refresh-marketplace` couldn't write the `enabledPlugins` map (the fix above stayed inert), and `agnes self-upgrade`'s `maybe_refresh_claude_hooks` couldn't migrate workspaces to new Agnes hook layouts. The sentinel was meant to gate **init-time** skip only — let admins ship the *initial* `.claude/` contents — not to lock the workspace permanently. The override check moves from inside the writers (`cli/lib/hooks.py::install_claude_hooks`, `cli/lib/hooks.py::maybe_refresh_claude_hooks`, `cli/lib/commands.py::install_claude_commands`, `cli/commands/refresh_marketplace.py::_enable_plugins_in_workspace_settings`) to the init-time call site that always was the right place (`cli/commands/init.py::init`, `if not override_active:`). Init-time behavior unchanged — `agnes init` on an override workspace still defers the workspace skeleton to admin's template. Admin custom hooks survive runtime refresh: Agnes only rewrites entries matching `_OUR_COMMAND_MARKERS` (`agnes self-upgrade` / `agnes pull` / ... substring set in `cli/lib/hooks.py`); foreign commands fall through unchanged, same contract as in default workspaces. Existing override workspaces auto-converge on the next `agnes self-upgrade` (which fires from every SessionStart hook); no manual operator action needed. Retracts the earlier *"full responsibility transfer; future Agnes hook fixes will NOT auto-propagate"* contract documented in the `[0.54.10]` `### Internal — risk-accepted by design` bullets — that scope was wider than the feature's actual intent. ### Removed - **`/home` connectors block dropped — the onboarding flow covers it (#305).** The dedicated `
` section on `/home` (three tiles — Asana / Google Workspace / Atlassian — each with a "Copy prompt" button) duplicated content the install-hero's Step 4 clipboard payload already inlines via `app/web/setup_instructions.py::_connectors_block`: users walking the setup script visit every connector inline. The install-hero lead paragraph now names the connector families so the benefit stays visible before kick-off. The per-instance "Email admin" mailto CTA — previously gated inside the GWS tile when an operator contact email was set and GWS OAuth was unconfigured — was dropped along with the block; the GWS connector setup prompt still tells the user to ask an admin, but without the pre-filled per-instance contact address. ### Internal - Post-#305 cleanup. Removed the now-orphaned `gws_oauth`, `instance_admin_email`, and `connector_prompts` keys from the shared `_build_context` ctx dict in `app/web/router.py` — no template referenced them once the connectors block was dropped, and `connector_prompts` was calling `all_connector_prompts()` on every page render app-wide. Swept the dead `.connector-tile*`, `.connector-copy`, `.connector-preview`, `.copy-next-hint`, `.time-badge`, `.gating-note`, `.email-admin`, `.card-mini-cmd`, and `.connector-head` CSS rules plus the orphaned `.connector-copy` click-wiring JS from `home_not_onboarded.html`. Also removed the dead `.automode-*`, `.setup-collapsible`, and `.setup-minimize` CSS blocks and the `setupMinimizeToggle` / `data-setup-minimized` JS handler from the same template — the `
` sections and the "Minimize setup view" toggle they styled were removed by earlier PRs (#243 onward), leaving the whole minimize-mode machinery unreachable. ## [0.54.13] — 2026-05-14 ### Security - **RBAC filter uses stable `user_id` (UUID) instead of mutable email local-part (#293).** Non-admin users querying `agnes_sessions` / `agnes_telemetry` are now filtered by `user_id` (immutable UUID) rather than `username` (email local-part, which changes on rename). Schema v45 adds a `user_id` column to `usage_session_summary` and `usage_events`; the session pipeline's `resolve_user_id()` populates it on every (re)process run. `USAGE_PROCESSOR_VERSION` bumps 3→4 to trigger backfill. During the transition period, RBAC queries include an OR fallback on `username` so pre-backfill rows remain visible. ## [0.54.12] — 2026-05-14 ### Fixed - **Usage processor now extracts user-typed slash invocations.** Claude Code records `/foo` and `/plugin:name` slash commands as `/foo` XML tags embedded in user message content; the previous `^\s*/` regex in `iter_events` only matched raw `/foo` prefixes, which never appear in real session jsonls. Result on production: `usage_events.command_name` and `usage_session_summary.slash_commands` stayed NULL/0 for every actually-typed slash invocation (`/clear`, `/exit`, `/plugin`, `/model`, plugin commands of the form `/plugin:name`). Replaced with a `` tag scan; `USAGE_PROCESSOR_VERSION` bumps 2 → 3. Operators wanting to rewrite historical rows under the new logic call `POST /api/admin/usage/reprocess` (CLI: `agnes admin telemetry reprocess`). Implicit Skill tool_use extraction (LLM-decided invocations) is unchanged. ## [0.54.11] — 2026-05-14 ### Changed - Catalog page: each `catalog_data` bucket now renders as its own top-level Data Package card instead of being nested as a collapsible accordion under a single "Core Business Data" wrapper. The page hero title ("Data Packages") now describes the actual visual structure, and the card grain matches the `bucket` column on `table_registry`. Tables inside each package are flat-listed (no per-bucket accordion), mirroring the existing `Agnes Internal` card; the `Agnes Internal` and `Business Metrics` cards themselves are unchanged. Per-table sync info ("Synced …" / "Queried directly from BigQuery") on each row is preserved. The aggregate meta line ("N tables · ~M rows total · Synced X") on the old wrapper is dropped with no replacement — the global sync timestamp is no longer shown on this page. An instance with zero registered tables now renders no Data Package cards at all, where the old wrapper always rendered (showing "0 tables"). ## [0.54.10] — 2026-05-14 ### Changed - Web UI design system unified: single stylesheet (`style-custom.css`), canonical primitives for buttons, form controls, page headers, tables, empty states, toasts, and stat cards. Top-nav Admin entry now shares styling 1:1 with sibling links (font, color, padding, hover, active state) — previously a `