# v0.33.0

These are the release notes for gptme version v0.33.0.

## Contributors

Thanks to everyone who contributed to this release:

@AlexFerroni02, @eeshsaxena, @erikbjare, @illiand, @sujeito-operator, @TimeToBuildBob

## Changelog

Changes since v0.32.1:


## 📦 gptme

### ✨ Features (76)

 - feat(autocompact): add keep_head to protect task context from compaction ([#3567](https://github.com/gptme/gptme/issues/3567)) ([`ab731347b`](https://github.com/gptme/gptme/commit/ab731347b))
 - feat(prompts): Add code editing strategy guidance for improved model performance ([#3530](https://github.com/gptme/gptme/issues/3530)) ([`8fb767452`](https://github.com/gptme/gptme/commit/8fb767452))
 - feat(cli): fatal error envelope + exit taxonomy for non-interactive mode ([#3568](https://github.com/gptme/gptme/issues/3568)) ([`3fb862dcc`](https://github.com/gptme/gptme/commit/3fb862dcc))
 - feat(prompts): end responses with a concrete next step ([#3559](https://github.com/gptme/gptme/issues/3559)) ([`a93bf261f`](https://github.com/gptme/gptme/commit/a93bf261f))
 - feat(tools): add read-only audit preset ([#3543](https://github.com/gptme/gptme/issues/3543)) ([`7adb7f765`](https://github.com/gptme/gptme/commit/7adb7f765))
 - feat(cli): add `gptme explain` for offline concept answers ([#3542](https://github.com/gptme/gptme/issues/3542)) ([`bb48ab5be`](https://github.com/gptme/gptme/commit/bb48ab5be))
 - feat(cli): add --version-short output ([#3536](https://github.com/gptme/gptme/issues/3536)) ([`bff711a52`](https://github.com/gptme/gptme/commit/bff711a52))
 - feat(models): refresh MiniMax plugin registry ([#3533](https://github.com/gptme/gptme/issues/3533)) ([`eb0dae860`](https://github.com/gptme/gptme/commit/eb0dae860))
 - feat(cli): add JSON output to status command ([#3528](https://github.com/gptme/gptme/issues/3528)) ([`f232004be`](https://github.com/gptme/gptme/commit/f232004be))
 - feat(tools/hashline_edit): 3-way merge recovery when file changes between read and edit ([#3476](https://github.com/gptme/gptme/issues/3476) Phase 2) ([#3520](https://github.com/gptme/gptme/issues/3520)) ([`c3bdfb46d`](https://github.com/gptme/gptme/commit/c3bdfb46d))
 - feat(attestation): Phase 1 registry bridge - wire model-capability-registry ([#3525](https://github.com/gptme/gptme/issues/3525)) ([`fce2fbe69`](https://github.com/gptme/gptme/commit/fce2fbe69))
 - feat(tools/hashline_edit): add register operations (CUT @name / PUT @name) ([#3497](https://github.com/gptme/gptme/issues/3497)) ([`cbce4062e`](https://github.com/gptme/gptme/commit/cbce4062e))
 - feat(review): make reviewer toolset configurable with a read-only preset ([#3512](https://github.com/gptme/gptme/issues/3512)) ([`6b3fde6fc`](https://github.com/gptme/gptme/commit/6b3fde6fc))
 - feat(lessons): Stage 1 shadow logging — policy_class/policy_version in dropout logs ([#3455](https://github.com/gptme/gptme/issues/3455)) ([`bd99a0944`](https://github.com/gptme/gptme/commit/bd99a0944))
 - feat(review): add `gptme-util review pr` subcommand — complete the unified review pipeline (gptme[#3442](https://github.com/gptme/gptme/issues/3442)) ([#3462](https://github.com/gptme/gptme/issues/3462)) ([`374f94304`](https://github.com/gptme/gptme/commit/374f94304))
 - feat(llm/webui): capture and display resolved OpenRouter subprovider in message metadata ([#3486](https://github.com/gptme/gptme/issues/3486)) ([`34e8848a8`](https://github.com/gptme/gptme/commit/34e8848a8))
 - feat(tools/hashline_edit): add PUT N*: block-aware replace ([#3476](https://github.com/gptme/gptme/issues/3476) Phase 1 remainder) ([#3480](https://github.com/gptme/gptme/issues/3480)) ([`db8fe3881`](https://github.com/gptme/gptme/commit/db8fe3881))
 - feat(webui): add trajectory copy commands ([#3491](https://github.com/gptme/gptme/issues/3491)) ([`7c29b4177`](https://github.com/gptme/gptme/commit/7c29b4177))
 - feat(webui): add copy trajectory as markdown with detail level toggles ([#3485](https://github.com/gptme/gptme/issues/3485)) ([`786f78642`](https://github.com/gptme/gptme/commit/786f78642))
 - feat(review): add --trusted-reviewer guard for artifact mode ([#3470](https://github.com/gptme/gptme/issues/3470)) ([`702d9c219`](https://github.com/gptme/gptme/commit/702d9c219))
 - feat(tools): hashline-inspired snapshot-anchored edit format ([#3477](https://github.com/gptme/gptme/issues/3477)) ([`8fcff6ae8`](https://github.com/gptme/gptme/commit/8fcff6ae8))
 - feat(webui/model-picker): add free-text custom model ID entry ([#3466](https://github.com/gptme/gptme/issues/3466)) ([`f5c6c8be5`](https://github.com/gptme/gptme/commit/f5c6c8be5))
 - feat(review): artifact mode + structured handoff for review-watch ([#3442](https://github.com/gptme/gptme/issues/3442)) ([#3449](https://github.com/gptme/gptme/issues/3449)) ([`9130a018c`](https://github.com/gptme/gptme/commit/9130a018c))
 - feat(cli): add global stats for CLI subcommand for usage & cost analytics ([#3400](https://github.com/gptme/gptme/issues/3400)) ([`8d88b862e`](https://github.com/gptme/gptme/commit/8d88b862e))
 - feat(review): converge review-watch and shared review pipeline ([#3442](https://github.com/gptme/gptme/issues/3442)) ([#3443](https://github.com/gptme/gptme/issues/3443)) ([`4a21419d6`](https://github.com/gptme/gptme/commit/4a21419d6))
 - feat(timings): persist per-step timing breakdown in session records ([#3436](https://github.com/gptme/gptme/issues/3436)) ([`b0adaa7c7`](https://github.com/gptme/gptme/commit/b0adaa7c7))
 - feat(util): add review-watch command for autonomous PR review iteration ([#3437](https://github.com/gptme/gptme/issues/3437)) ([`81342c4e6`](https://github.com/gptme/gptme/commit/81342c4e6))
 - feat(browser): support custom executable path in GPTME_BROWSER_ENGINE ([#3439](https://github.com/gptme/gptme/issues/3439)) ([`08d61d970`](https://github.com/gptme/gptme/commit/08d61d970))
 - feat(cli): add 'gptme providers add' command for interactive custom provider setup ([#3438](https://github.com/gptme/gptme/issues/3438)) ([`542f64035`](https://github.com/gptme/gptme/commit/542f64035))
 - feat(android): sign APK/AAB and verify signature before release upload ([#3409](https://github.com/gptme/gptme/issues/3409)) ([`55ac56712`](https://github.com/gptme/gptme/commit/55ac56712))
 - feat(cost): add session budget warnings ([#3423](https://github.com/gptme/gptme/issues/3423)) ([`be1e0b4f8`](https://github.com/gptme/gptme/commit/be1e0b4f8))
 - feat(attestation): persist ModelSelectionTrace to logdir and embed in attestations ([#3424](https://github.com/gptme/gptme/issues/3424)) ([`5721cd0a7`](https://github.com/gptme/gptme/commit/5721cd0a7))
 - feat(site): add built-with-gptme badge ([#3410](https://github.com/gptme/gptme/issues/3410)) ([`3e146fcce`](https://github.com/gptme/gptme/commit/3e146fcce))
 - feat(attestation): add ModelSelectionTrace for durable model provenance (Phase 0) ([#3416](https://github.com/gptme/gptme/issues/3416)) ([`1b4616ee0`](https://github.com/gptme/gptme/commit/1b4616ee0))
 - feat(webui): add Tool Activity Panel to right sidebar ([#3413](https://github.com/gptme/gptme/issues/3413)) ([`a598f55d2`](https://github.com/gptme/gptme/commit/a598f55d2))
 - feat(tutorial): add gptme-tutorial interactive onboarding mode ([#3420](https://github.com/gptme/gptme/issues/3420)) ([`c284f67e7`](https://github.com/gptme/gptme/commit/c284f67e7))
 - feat(k-best): add k_best_guess decorator for K-candidate validation ([#3415](https://github.com/gptme/gptme/issues/3415)) ([`1ebdb1f92`](https://github.com/gptme/gptme/commit/1ebdb1f92))
 - feat(webui): replace CLI server guidance with in-app retry in Tauri desktop app ([#3407](https://github.com/gptme/gptme/issues/3407)) ([`7fe250529`](https://github.com/gptme/gptme/commit/7fe250529))
 - feat(cost): add inline per-message cost display via GPTME_SHOW_COST=1 ([#3396](https://github.com/gptme/gptme/issues/3396)) ([`2b7d77201`](https://github.com/gptme/gptme/commit/2b7d77201))
 - feat(webui): virtualize message list with @tanstack/react-virtual ([#3379](https://github.com/gptme/gptme/issues/3379)) ([`ebbce08b9`](https://github.com/gptme/gptme/commit/ebbce08b9))
 - feat(webui): add model3d artifact kind for glTF/GLB/OBJ/STL inline preview ([#3361](https://github.com/gptme/gptme/issues/3361)) ([`d315f82f3`](https://github.com/gptme/gptme/commit/d315f82f3))
 - feat(llm): add native Kimi K3 support ([#3385](https://github.com/gptme/gptme/issues/3385)) ([`8b1a993a9`](https://github.com/gptme/gptme/commit/8b1a993a9))
 - feat(logmanager): optional S3 replication for session event logs (Phase 2) ([#3382](https://github.com/gptme/gptme/issues/3382)) ([`97bc1dc22`](https://github.com/gptme/gptme/commit/97bc1dc22))
 - feat(sandbox): add Wasmtime WASI Python sandbox backend ([#3381](https://github.com/gptme/gptme/issues/3381)) ([`3697f4526`](https://github.com/gptme/gptme/commit/3697f4526))
 - feat(sandbox): add Docker sandbox for Python tool (GPTME_SANDBOX=docker) ([#3377](https://github.com/gptme/gptme/issues/3377)) ([`38f893b03`](https://github.com/gptme/gptme/commit/38f893b03))
 - feat(sandbox): add sandboxed execution mode for shell tool ([#3367](https://github.com/gptme/gptme/issues/3367)) ([`89d4ecb9a`](https://github.com/gptme/gptme/commit/89d4ecb9a))
 - feat(config): add layered lifecycle script hooks ([#3366](https://github.com/gptme/gptme/issues/3366)) ([`1531fd15d`](https://github.com/gptme/gptme/commit/1531fd15d))
 - feat(tools): add completion verification hook ([#3358](https://github.com/gptme/gptme/issues/3358)) ([`12001f153`](https://github.com/gptme/gptme/commit/12001f153))
 - feat(tui): collapsible rendering for XML and markdown tool-call formats ([#3353](https://github.com/gptme/gptme/issues/3353)) ([`78c191958`](https://github.com/gptme/gptme/commit/78c191958))
 - feat(tui): prompt before fetching URLs pasted into TUI ([#3351](https://github.com/gptme/gptme/issues/3351)) ([`609d55a76`](https://github.com/gptme/gptme/commit/609d55a76))
 - feat(tui): prefix-based history search + show Ctrl+J in input hint ([#3341](https://github.com/gptme/gptme/issues/3341)) ([`0faa850fc`](https://github.com/gptme/gptme/commit/0faa850fc))
 - feat(tui): render thinking blocks as collapsibles, show Thinking… during generation ([#3336](https://github.com/gptme/gptme/issues/3336)) ([`58851384b`](https://github.com/gptme/gptme/commit/58851384b))
 - feat(tui): tab-completion candidate overlay ([#3311](https://github.com/gptme/gptme/issues/3311)) ([#3316](https://github.com/gptme/gptme/issues/3316)) ([`48143206c`](https://github.com/gptme/gptme/commit/48143206c))
 - feat(tui): tool-execution placeholder in chat + fix gray message background ([#3321](https://github.com/gptme/gptme/issues/3321)) ([`fe71f1294`](https://github.com/gptme/gptme/commit/fe71f1294))
 - feat(tui): persist input history to shared prompt-toolkit history file ([#3314](https://github.com/gptme/gptme/issues/3314)) ([`1787ff47e`](https://github.com/gptme/gptme/commit/1787ff47e))
 - feat(tui): add Alt+Left/Right word navigation to ChatInput ([#3313](https://github.com/gptme/gptme/issues/3313)) ([`b5c9edb11`](https://github.com/gptme/gptme/commit/b5c9edb11))
 - feat(tui): add input history, fix focus and visual polish ([#3312](https://github.com/gptme/gptme/issues/3312)) ([`bb6afedd4`](https://github.com/gptme/gptme/commit/bb6afedd4))
 - feat(tui): show 'Generating…' placeholder before first token arrives ([#3310](https://github.com/gptme/gptme/issues/3310)) ([`762fd3a67`](https://github.com/gptme/gptme/commit/762fd3a67))
 - feat(webui): truly mix external sessions inline by recency ([#3217](https://github.com/gptme/gptme/issues/3217)) ([#3307](https://github.com/gptme/gptme/issues/3307)) ([`b9f4482e6`](https://github.com/gptme/gptme/commit/b9f4482e6))
 - feat(webui): open external sessions inline in native chat layout ([#3306](https://github.com/gptme/gptme/issues/3306)) ([`42982c631`](https://github.com/gptme/gptme/commit/42982c631))
 - feat(tui): add experimental jelly error feedback ([#3303](https://github.com/gptme/gptme/issues/3303)) ([`efd9942f4`](https://github.com/gptme/gptme/commit/efd9942f4))
 - feat(auth): add OpenRouter OAuth and gptme.ai device-connect to first-run setup ([#3304](https://github.com/gptme/gptme/issues/3304)) ([`6ad8c372a`](https://github.com/gptme/gptme/commit/6ad8c372a))
 - feat(webui): steer_inject for external sessions (Phase 2 of [#3217](https://github.com/gptme/gptme/issues/3217)) ([#3287](https://github.com/gptme/gptme/issues/3287)) ([`5591dd89b`](https://github.com/gptme/gptme/commit/5591dd89b))
 - feat(cli): add full-noexamples system prompt type to reduce token usage ([#3296](https://github.com/gptme/gptme/issues/3296)) ([`f207bbf4d`](https://github.com/gptme/gptme/commit/f207bbf4d))
 - feat(cli): offer subscription auth on first run ([#3295](https://github.com/gptme/gptme/issues/3295)) ([`8d55746e1`](https://github.com/gptme/gptme/commit/8d55746e1))
 - feat(hooks): hash-link manifest records with tamper-detection verification (Phase 2) ([#3297](https://github.com/gptme/gptme/issues/3297)) ([`50ceda783`](https://github.com/gptme/gptme/commit/50ceda783))
 - feat(models): add pricing_type field for subscription-backed providers ([#3292](https://github.com/gptme/gptme/issues/3292)) ([`87944b080`](https://github.com/gptme/gptme/commit/87944b080))
 - feat(providers): add grok-subscription provider for SuperGrok subscribers ([#3289](https://github.com/gptme/gptme/issues/3289)) ([`e0cd34093`](https://github.com/gptme/gptme/commit/e0cd34093))
 - feat(subagent): mid-turn steer injection via STEP_PRE checkpoint ([#3290](https://github.com/gptme/gptme/issues/3290)) ([`a46b5600b`](https://github.com/gptme/gptme/commit/a46b5600b))
 - feat(hooks): add --manifest-dir for tool-call attribution at JSON-record granularity ([#3291](https://github.com/gptme/gptme/issues/3291)) ([`b711a662a`](https://github.com/gptme/gptme/commit/b711a662a))
 - feat(subagent): subagent_steer() — inject steering messages into running subagents ([#3206](https://github.com/gptme/gptme/issues/3206)) ([`070c45cee`](https://github.com/gptme/gptme/commit/070c45cee))
 - feat(tools): make lxml optional with stdlib xml.etree fallback; move pypdf to optional ([#3280](https://github.com/gptme/gptme/issues/3280)) ([`1b55e04c2`](https://github.com/gptme/gptme/commit/1b55e04c2))
 - feat(safety): add optional haiku judge annotation to export CLI ([#3276](https://github.com/gptme/gptme/issues/3276)) ([`61c2f68b5`](https://github.com/gptme/gptme/commit/61c2f68b5))
 - feat(typecheck): add human-readable imprecision summary to typecheck-coverage ([#3272](https://github.com/gptme/gptme/issues/3272)) ([`9e3b5432e`](https://github.com/gptme/gptme/commit/9e3b5432e))
 - feat(packaging): add gptme[minimal] install extra for ARM/musl/Termux/Lambda ([#3279](https://github.com/gptme/gptme/issues/3279)) ([`4cb2bfd37`](https://github.com/gptme/gptme/commit/4cb2bfd37))
 - feat(webui): toggleable external sessions in conversation list ([#3281](https://github.com/gptme/gptme/issues/3281)) ([`1dc648dd1`](https://github.com/gptme/gptme/commit/1dc648dd1))

### 🐛 Fixes (91)
<details><summary>Click to expand</summary>
<p>

 - fix(review): verify finding file/line target matches inline comment location ([#3547](https://github.com/gptme/gptme/issues/3547)) ([`dc0109123`](https://github.com/gptme/gptme/commit/dc0109123))
 - fix(tauri): real API-key errors and Windows sidecar startup ([#3552](https://github.com/gptme/gptme/issues/3552)) ([`3f4127cd1`](https://github.com/gptme/gptme/commit/3f4127cd1))
 - fix(server): validate provider API key before persisting in BYOK setup ([#3555](https://github.com/gptme/gptme/issues/3555)) ([`33ce4182e`](https://github.com/gptme/gptme/commit/33ce4182e))
 - fix(grok-subscription): enable native tools API and add grok-4.6 ([#3571](https://github.com/gptme/gptme/issues/3571)) ([`5fdcd47b9`](https://github.com/gptme/gptme/commit/5fdcd47b9))
 - fix(shell): allowlist permitted flags per binary instead of denying four find flags (GHSA-mfh4-cxj2-jc9p) ([#3557](https://github.com/gptme/gptme/issues/3557)) ([`46806b849`](https://github.com/gptme/gptme/commit/46806b849))
 - fix(deps): bump Python critical security dependencies ([#3556](https://github.com/gptme/gptme/issues/3556)) ([`c2d1ca9cb`](https://github.com/gptme/gptme/commit/c2d1ca9cb))
 - fix(server): validate provider API key before saving it ([#3546](https://github.com/gptme/gptme/issues/3546)) ([`2ac432ef0`](https://github.com/gptme/gptme/commit/2ac432ef0))
 - fix(android): enable mobile cloud sign-in ([#3558](https://github.com/gptme/gptme/issues/3558)) ([`fef66b7f4`](https://github.com/gptme/gptme/commit/fef66b7f4))
 - fix(cli): rethink --version output format, remove --version-short ([#3539](https://github.com/gptme/gptme/issues/3539)) ([`49b4cf3aa`](https://github.com/gptme/gptme/commit/49b4cf3aa))
 - fix(dirs): terminate project-dir walk at the filesystem root (Windows infinite loop) ([#3509](https://github.com/gptme/gptme/issues/3509)) ([`0c34ffc2a`](https://github.com/gptme/gptme/commit/0c34ffc2a))
 - fix(llm): normalize proxy URL in _is_proxy() to match init() suffix rule ([#3527](https://github.com/gptme/gptme/issues/3527)) ([`6971a105a`](https://github.com/gptme/gptme/commit/6971a105a))
 - fix(constants): escape assistant display name to prevent rich markup injection ([#3517](https://github.com/gptme/gptme/issues/3517)) ([`3ff8966d1`](https://github.com/gptme/gptme/commit/3ff8966d1))
 - fix(read): reject non-positive line bounds instead of silently truncating ([#3515](https://github.com/gptme/gptme/issues/3515)) ([`902ab1b5b`](https://github.com/gptme/gptme/commit/902ab1b5b))
 - fix(prompt_queue): preserve malformed lines on drain instead of dropping them ([#3498](https://github.com/gptme/gptme/issues/3498)) ([`e75f52e1c`](https://github.com/gptme/gptme/commit/e75f52e1c))
 - fix(replay): read conversation.jsonl master log as explicit UTF-8 ([#3474](https://github.com/gptme/gptme/issues/3474)) ([`d62ae57d3`](https://github.com/gptme/gptme/commit/d62ae57d3))
 - fix(review): stop discarding reviews whose findings quote a code fence ([#3513](https://github.com/gptme/gptme/issues/3513)) ([`d003ff2bc`](https://github.com/gptme/gptme/commit/d003ff2bc))
 - fix(taskApi): include HTTP status code in all error messages ([#3516](https://github.com/gptme/gptme/issues/3516)) ([`cc4c2a15a`](https://github.com/gptme/gptme/commit/cc4c2a15a))
 - fix: correct editable-install detection in `--version` output ([#3518](https://github.com/gptme/gptme/issues/3518)) ([#3519](https://github.com/gptme/gptme/issues/3519)) ([`1bdf21a70`](https://github.com/gptme/gptme/commit/1bdf21a70))
 - fix(cli): preserve lone separator prompt ([#3514](https://github.com/gptme/gptme/issues/3514)) ([`b34ee9b2b`](https://github.com/gptme/gptme/commit/b34ee9b2b))
 - fix(webui): keep hosted demo CTA clickable ([#3510](https://github.com/gptme/gptme/issues/3510)) ([`b4e47e634`](https://github.com/gptme/gptme/commit/b4e47e634))
 - fix(message): disable Rich markup for plain rendering ([#3505](https://github.com/gptme/gptme/issues/3505)) ([`ee4bceba4`](https://github.com/gptme/gptme/commit/ee4bceba4))
 - fix(codeblock): slice body on raw first-line length to avoid lang leaking into content ([#3507](https://github.com/gptme/gptme/issues/3507)) ([`ed08de11d`](https://github.com/gptme/gptme/commit/ed08de11d))
 - fix(gh): only replace first /blob/ in transform_github_url ([#3473](https://github.com/gptme/gptme/issues/3473)) ([`7d7565f9d`](https://github.com/gptme/gptme/commit/7d7565f9d))
 - fix(cli): split chained prompts only on exact separator args ([#3502](https://github.com/gptme/gptme/issues/3502)) ([`7182eaa76`](https://github.com/gptme/gptme/commit/7182eaa76))
 - fix(server): preserve interrupt ownership across tool continuations ([#3457](https://github.com/gptme/gptme/issues/3457)) ([`4c10199a3`](https://github.com/gptme/gptme/commit/4c10199a3))
 - fix(codeblock): normalize CRLF line endings when parsing code blocks ([#3499](https://github.com/gptme/gptme/issues/3499)) ([`dfafb54ea`](https://github.com/gptme/gptme/commit/dfafb54ea))
 - fix(lessons): use correct max-z bound for population-SD BM25 z-scores ([#3500](https://github.com/gptme/gptme/issues/3500)) ([`393f7892f`](https://github.com/gptme/gptme/commit/393f7892f))
 - fix(shell): close 4 auto-approval vulnerabilities in shell_validation ([#3495](https://github.com/gptme/gptme/issues/3495)) ([`73931882c`](https://github.com/gptme/gptme/commit/73931882c))
 - fix(ci): download after-screenshots to /tmp to survive checkout workspace wipe ([#3496](https://github.com/gptme/gptme/issues/3496)) ([`44d14eec4`](https://github.com/gptme/gptme/commit/44d14eec4))
 - fix(server): prevent premature continuation when confirming concurrent tools ([#3481](https://github.com/gptme/gptme/issues/3481)) ([`f9d369c53`](https://github.com/gptme/gptme/commit/f9d369c53))
 - fix(read): reject inverted line range instead of silently returning empty ([#3494](https://github.com/gptme/gptme/issues/3494)) ([`aa64f7419`](https://github.com/gptme/gptme/commit/aa64f7419))
 - fix(ci): use official download-artifact for cross-run artifacts + add more visual snapshots ([#3493](https://github.com/gptme/gptme/issues/3493)) ([`74237f2a4`](https://github.com/gptme/gptme/commit/74237f2a4))
 - fix(gh): substitute owner/repo in per-job log-fetch fallback so run-view logs are reachable ([#3492](https://github.com/gptme/gptme/issues/3492)) ([`e461427a2`](https://github.com/gptme/gptme/commit/e461427a2))
 - fix(llm): flatten array tool-result content for DeepSeek via OpenRouter ([#3490](https://github.com/gptme/gptme/issues/3490)) ([`dc7f854af`](https://github.com/gptme/gptme/commit/dc7f854af))
 - fix(logmanager): use explicit UTF-8 for JSONL conversation I/O ([#3475](https://github.com/gptme/gptme/issues/3475)) ([`cd12e9e6a`](https://github.com/gptme/gptme/commit/cd12e9e6a))
 - fix(deepseek): flatten text-only merged tool results to string ([#3472](https://github.com/gptme/gptme/issues/3472)) ([`a05fb85e2`](https://github.com/gptme/gptme/commit/a05fb85e2))
 - fix(webui): expose Accept All as direct one-click button + compact tool cards ([#3440](https://github.com/gptme/gptme/issues/3440)) ([#3461](https://github.com/gptme/gptme/issues/3461)) ([`1f70107bd`](https://github.com/gptme/gptme/commit/1f70107bd))
 - fix(complete): enable stuck detection for interactive/web sessions ([#3463](https://github.com/gptme/gptme/issues/3463)) ([`0c343ebd9`](https://github.com/gptme/gptme/commit/0c343ebd9))
 - fix(deepseek): extract `<think>` reasoning into reasoning_content for deepseek-reasoner tool calls ([#3464](https://github.com/gptme/gptme/issues/3464)) ([`796f3d7cd`](https://github.com/gptme/gptme/commit/796f3d7cd))
 - fix(webui): scroll past InlineToolExecution during tool execution ([#3440](https://github.com/gptme/gptme/issues/3440)) ([#3450](https://github.com/gptme/gptme/issues/3450)) ([`114117db1`](https://github.com/gptme/gptme/commit/114117db1))
 - fix(lessons): port BM25 z-score gate to HybridLessonMatcher no-embedder path ([#3453](https://github.com/gptme/gptme/issues/3453)) ([`b73e2e476`](https://github.com/gptme/gptme/commit/b73e2e476))
 - fix(webui): model selector skeleton while loading + dedupe spinners ([#3440](https://github.com/gptme/gptme/issues/3440)) ([#3441](https://github.com/gptme/gptme/issues/3441)) ([`360e11052`](https://github.com/gptme/gptme/commit/360e11052))
 - fix(webui): remove workspaceUtils debug console.log spam, add useMemo to components ([#3446](https://github.com/gptme/gptme/issues/3446)) ([`d4f12a696`](https://github.com/gptme/gptme/commit/d4f12a696))
 - fix(tests): catch TypeError in _has_flask() for Python 3.13 compatibility ([#3448](https://github.com/gptme/gptme/issues/3448)) ([`91c0e25dd`](https://github.com/gptme/gptme/commit/91c0e25dd))
 - fix(tasks): align list-archived param name and include status code in errors ([#3447](https://github.com/gptme/gptme/issues/3447)) ([`4cba56d56`](https://github.com/gptme/gptme/commit/4cba56d56))
 - fix(webui): keep setup wizard reachable after skip and on mobile Tauri ([#3445](https://github.com/gptme/gptme/issues/3445)) ([`f330be623`](https://github.com/gptme/gptme/commit/f330be623))
 - fix(webui): make settings dialog full-screen on mobile, fixed-height on desktop ([#3444](https://github.com/gptme/gptme/issues/3444)) ([`2704a4f6b`](https://github.com/gptme/gptme/commit/2704a4f6b))
 - fix(server): propagate branch through tool execution and continuation step ([#3432](https://github.com/gptme/gptme/issues/3432)) ([`6d5f493c7`](https://github.com/gptme/gptme/commit/6d5f493c7))
 - fix(webui/a11y): raise green text to green-700 for WCAG AA compliance ([#3433](https://github.com/gptme/gptme/issues/3433)) ([`c6309447f`](https://github.com/gptme/gptme/commit/c6309447f))
 - fix(security): require bearer auth for all bind addresses, remove is_local_host() bypass ([#3430](https://github.com/gptme/gptme/issues/3430)) ([`511365332`](https://github.com/gptme/gptme/commit/511365332))
 - fix(server): complete cross-session generation guarding for conversations ([#3429](https://github.com/gptme/gptme/issues/3429)) ([`bd9bd781e`](https://github.com/gptme/gptme/commit/bd9bd781e))
 - fix(webui/demo): use fixed historical timestamp instead of Date.now() ([#3431](https://github.com/gptme/gptme/issues/3431)) ([`6df6b7916`](https://github.com/gptme/gptme/commit/6df6b7916))
 - fix(server): check all sessions when guarding concurrent generation in /step ([#3428](https://github.com/gptme/gptme/issues/3428)) ([`6d4c5dba1`](https://github.com/gptme/gptme/commit/6d4c5dba1))
 - fix(android): pin AAB signer fingerprint instead of -strict chain check ([#3427](https://github.com/gptme/gptme/issues/3427)) ([`17e1c1189`](https://github.com/gptme/gptme/commit/17e1c1189))
 - fix(android): print actual cert fingerprint on verification mismatch ([#3426](https://github.com/gptme/gptme/issues/3426)) ([`86cf21e4b`](https://github.com/gptme/gptme/commit/86cf21e4b))
 - fix(config): use explicit UTF-8 encoding for all TOML config I/O ([#3399](https://github.com/gptme/gptme/issues/3399)) ([`f636ae4ac`](https://github.com/gptme/gptme/commit/f636ae4ac))
 - fix(llm): buffer non-tool system msgs between tool_calls and tool responses ([#3422](https://github.com/gptme/gptme/issues/3422)) ([`09ce9b05d`](https://github.com/gptme/gptme/commit/09ce9b05d))
 - fix(shell): fold workspace hint into tool response ([#3419](https://github.com/gptme/gptme/issues/3419)) ([`4c8066890`](https://github.com/gptme/gptme/commit/4c8066890))
 - fix(server): acquire step_lock in interrupt endpoint to prevent race ([#3414](https://github.com/gptme/gptme/issues/3414)) ([`c5faab836`](https://github.com/gptme/gptme/commit/c5faab836))
 - fix(server): reject message append during generation ([#3412](https://github.com/gptme/gptme/issues/3412)) ([`aaa96d6a6`](https://github.com/gptme/gptme/commit/aaa96d6a6))
 - fix(server): guard conversation DELETE against concurrent generation ([#3405](https://github.com/gptme/gptme/issues/3405)) ([`2d40121ea`](https://github.com/gptme/gptme/commit/2d40121ea))
 - fix(tauri): avoid duplicating webui in server sidecar ([#3404](https://github.com/gptme/gptme/issues/3404)) ([`b4e1871ff`](https://github.com/gptme/gptme/commit/b4e1871ff))
 - fix(server): acquire step_lock when checking generating flag in fork/edit/delete/config ([#3401](https://github.com/gptme/gptme/issues/3401)) ([`982d2ef8c`](https://github.com/gptme/gptme/commit/982d2ef8c))
 - fix(ci): bundle webui before building Tauri sidecars ([#3403](https://github.com/gptme/gptme/issues/3403)) ([`26ba55254`](https://github.com/gptme/gptme/commit/26ba55254))
 - fix(webui): a few minor design trims/fixes, including hiding avatars in chat on small screens ([#3395](https://github.com/gptme/gptme/issues/3395)) ([`a8f8509b1`](https://github.com/gptme/gptme/commit/a8f8509b1))
 - fix(server): actually bundle modern webui in distributions ([#3387](https://github.com/gptme/gptme/issues/3387)) ([`30852e8e2`](https://github.com/gptme/gptme/commit/30852e8e2))
 - fix(sandbox): drop all Linux capabilities in Docker Python sandbox ([#3380](https://github.com/gptme/gptme/issues/3380)) ([`a534d8d20`](https://github.com/gptme/gptme/commit/a534d8d20))
 - fix(logmanager): enforce call_id atomicity in limit_log for Responses API ([#3359](https://github.com/gptme/gptme/issues/3359)) ([`6b91235d3`](https://github.com/gptme/gptme/commit/6b91235d3))
 - fix(tools): don't stamp call_id on hook messages (fixes Responses API 400) ([#3355](https://github.com/gptme/gptme/issues/3355)) ([`8c8f4afae`](https://github.com/gptme/gptme/commit/8c8f4afae))
 - fix(tui): update tool format on /model switch, pretty-render tool-format calls ([#3347](https://github.com/gptme/gptme/issues/3347)) ([`38a311d14`](https://github.com/gptme/gptme/commit/38a311d14))
 - fix(subscription): close streaming response on all exit paths to prevent SIGSEGV ([#3352](https://github.com/gptme/gptme/issues/3352)) ([`efd812233`](https://github.com/gptme/gptme/commit/efd812233))
 - fix(tui): prevent crash when pasting GitHub URL ([#3348](https://github.com/gptme/gptme/issues/3348)) ([`0a310054c`](https://github.com/gptme/gptme/commit/0a310054c))
 - fix(gh): keep the ref intact when turning a blob URL into a raw URL ([#3342](https://github.com/gptme/gptme/issues/3342)) ([`1e0ce256f`](https://github.com/gptme/gptme/commit/1e0ce256f))
 - fix: improve tui styling ([#3340](https://github.com/gptme/gptme/issues/3340)) ([`65edd236e`](https://github.com/gptme/gptme/commit/65edd236e))
 - fix(tui): use terminal-native background for active output ([#3334](https://github.com/gptme/gptme/issues/3334)) ([`26e85570d`](https://github.com/gptme/gptme/commit/26e85570d))
 - fix(webui): persistent disconnected banner in conversation view ([#3327](https://github.com/gptme/gptme/issues/3327)) ([`41591361d`](https://github.com/gptme/gptme/commit/41591361d))
 - fix(webui): strip thinking blocks from TTS output ([#3332](https://github.com/gptme/gptme/issues/3332)) ([`1d31b9821`](https://github.com/gptme/gptme/commit/1d31b9821))
 - fix(test): kill TestMaxTimeWatchdog xdist flake — prevent untracked threads ([#3331](https://github.com/gptme/gptme/issues/3331)) ([`304631e4a`](https://github.com/gptme/gptme/commit/304631e4a))
 - fix(webui): omit default dot-workspace so server applies its @log default ([#3329](https://github.com/gptme/gptme/issues/3329)) ([`8feb442f2`](https://github.com/gptme/gptme/commit/8feb442f2))
 - fix(server): validate Host header to block DNS-rebinding on unauthenticated local servers ([#3324](https://github.com/gptme/gptme/issues/3324)) ([`34b0a33f0`](https://github.com/gptme/gptme/commit/34b0a33f0))
 - fix(server): allow explicit workspace override when creating conversations ([#3319](https://github.com/gptme/gptme/issues/3319)) ([`711fb826d`](https://github.com/gptme/gptme/commit/711fb826d))
 - fix(server,webui): external sessions dedup, stable detail IDs, admin nav label ([#3325](https://github.com/gptme/gptme/issues/3325)) ([`8fa8315b2`](https://github.com/gptme/gptme/commit/8fa8315b2))
 - fix(test): use scrollback capture for inline-mode positional assertion ([#3305](https://github.com/gptme/gptme/issues/3305)) ([`b6db634ba`](https://github.com/gptme/gptme/commit/b6db634ba))
 - fix(test): wait for input prompt before asserting scrollback order in inline test ([#3301](https://github.com/gptme/gptme/issues/3301)) ([`b86d50a8d`](https://github.com/gptme/gptme/commit/b86d50a8d))
 - fix(acp): use max_turn_requests stop_reason when GPTME_MAX_STEPS reached ([#3302](https://github.com/gptme/gptme/issues/3302)) ([`2dec6bae4`](https://github.com/gptme/gptme/commit/2dec6bae4))
 - fix(webui): expose server URL validation inline ([#3299](https://github.com/gptme/gptme/issues/3299)) ([`063b5fec0`](https://github.com/gptme/gptme/commit/063b5fec0))
 - fix(acp): complete tool-driven prompt turns ([#3300](https://github.com/gptme/gptme/issues/3300)) ([`a3b121260`](https://github.com/gptme/gptme/commit/a3b121260))
 - fix(logmanager): preserve tool call/result atomicity in prune_ephemeral_messages ([#3294](https://github.com/gptme/gptme/issues/3294)) ([`caabde264`](https://github.com/gptme/gptme/commit/caabde264))
 - fix(webui): tolerate legacy provider health responses ([#3298](https://github.com/gptme/gptme/issues/3298)) ([`3fd84ba52`](https://github.com/gptme/gptme/commit/3fd84ba52))
 - fix(models): update stale OpenRouter model IDs ([#3288](https://github.com/gptme/gptme/issues/3288)) ([`dada86411`](https://github.com/gptme/gptme/commit/dada86411))
 - fix(tauri): make AppImage GTK links idempotent ([#3277](https://github.com/gptme/gptme/issues/3277)) ([`f658a411c`](https://github.com/gptme/gptme/commit/f658a411c))

</p>
</details>

### 🔨 Misc (42)
<details><summary>Click to expand</summary>
<p>

 - chore: bump version to 0.33.0 ([`b0f9e1199`](https://github.com/gptme/gptme/commit/b0f9e1199))
 - docs(models): cite the grok-4.6 model card ([#3572](https://github.com/gptme/gptme/issues/3572)) ([`6fd94609c`](https://github.com/gptme/gptme/commit/6fd94609c))
 - refactor(tests): move hashline snapshot test out of test_tools_read.py ([#3564](https://github.com/gptme/gptme/issues/3564)) ([`0a27a4539`](https://github.com/gptme/gptme/commit/0a27a4539))
 - docs: fix providers.rst structure, nest provider/browser pages, add Tool Formats guide ([#3563](https://github.com/gptme/gptme/issues/3563)) ([`9062f906d`](https://github.com/gptme/gptme/commit/9062f906d))
 - refactor(tools/read): fully decouple read.py from _hashline_snapshot ([#3562](https://github.com/gptme/gptme/issues/3562)) ([`469e7fe16`](https://github.com/gptme/gptme/commit/469e7fe16))
 - refactor(cli): move Bob-specific status fields out of core; add StatusProvider extension point ([#3537](https://github.com/gptme/gptme/issues/3537)) ([`f2438a449`](https://github.com/gptme/gptme/commit/f2438a449))
 - docs(design): complete PTC audit — paper citation + full tools/ coverage ([#3554](https://github.com/gptme/gptme/issues/3554)) ([`3d0005fd9`](https://github.com/gptme/gptme/commit/3d0005fd9))
 - docs: reordered sections in providers.rst ([`6e3529153`](https://github.com/gptme/gptme/commit/6e3529153))
 - refactor(tools/read): decouple read tool examples from hashline conventions ([#3561](https://github.com/gptme/gptme/issues/3561)) ([`e8fcfa2fe`](https://github.com/gptme/gptme/commit/e8fcfa2fe))
 - docs(tools): document hashline_edit tool + fix read examples with tag header ([#3476](https://github.com/gptme/gptme/issues/3476)) ([#3532](https://github.com/gptme/gptme/issues/3532)) ([`369eaac92`](https://github.com/gptme/gptme/commit/369eaac92))
 - docs: PTC tool interface audit + architecture rationale (fixes [#3540](https://github.com/gptme/gptme/issues/3540)) ([#3541](https://github.com/gptme/gptme/issues/3541)) ([`66057c6e8`](https://github.com/gptme/gptme/commit/66057c6e8))
 - docs: clarify conversation, branch, fork, and session terminology ([#3544](https://github.com/gptme/gptme/issues/3544)) ([`85ac622e8`](https://github.com/gptme/gptme/commit/85ac622e8))
 - test(webui): server-backed E2E generation tests with mock/echo provider ([#3440](https://github.com/gptme/gptme/issues/3440)) ([#3468](https://github.com/gptme/gptme/issues/3468)) ([`79bfe0def`](https://github.com/gptme/gptme/commit/79bfe0def))
 - docs(review): cross-reference the three PR-review implementations ([#3511](https://github.com/gptme/gptme/issues/3511)) ([`ced7357ce`](https://github.com/gptme/gptme/commit/ced7357ce))
 - refactor(review): extract infer_owner_repo into shared gptme.util.gh module ([#3503](https://github.com/gptme/gptme/issues/3503)) ([`2a84b1858`](https://github.com/gptme/gptme/commit/2a84b1858))
 - test(review): fix brittle live-PR unresolved assertion + add mocked coverage (gptme[#3442](https://github.com/gptme/gptme/issues/3442)) ([#3501](https://github.com/gptme/gptme/issues/3501)) ([`0cd374a2b`](https://github.com/gptme/gptme/commit/0cd374a2b))
 - test(review-watch): stop a global time.monotonic patch from crashing other tests ([#3489](https://github.com/gptme/gptme/issues/3489)) ([`900727b19`](https://github.com/gptme/gptme/commit/900727b19))
 - test: thread-leak detector + dict-race thread dump (residue of [#3257](https://github.com/gptme/gptme/issues/3257)) ([#3458](https://github.com/gptme/gptme/issues/3458)) ([`2f8966884`](https://github.com/gptme/gptme/commit/2f8966884))
 - docs(cookbook): add cookbook with 5 canonical usage patterns ([#3398](https://github.com/gptme/gptme/issues/3398)) ([`d83a093a2`](https://github.com/gptme/gptme/commit/d83a093a2))
 - docs(readme): update desktop app from WIP to shipped with download link ([#3397](https://github.com/gptme/gptme/issues/3397)) ([`74ccbb225`](https://github.com/gptme/gptme/commit/74ccbb225))
 - docs(automation): add review-gated autonomous workflow section ([#3391](https://github.com/gptme/gptme/issues/3391)) ([`3c1a26807`](https://github.com/gptme/gptme/commit/3c1a26807))
 - docs: add task-to-workflow onboarding guide ([#3389](https://github.com/gptme/gptme/issues/3389)) ([`49583dd01`](https://github.com/gptme/gptme/commit/49583dd01))
 - test(webui): add virtualization regression tests for [#3379](https://github.com/gptme/gptme/issues/3379) ([`0c3a4add1`](https://github.com/gptme/gptme/commit/0c3a4add1))
 - revert(logmanager): remove speculative S3 event-log replication ([#3384](https://github.com/gptme/gptme/issues/3384)) ([`1362061c2`](https://github.com/gptme/gptme/commit/1362061c2))
 - test(webui): guard streaming performance fixes ([#3362](https://github.com/gptme/gptme/issues/3362)) ([#3375](https://github.com/gptme/gptme/issues/3375)) ([`4b0a88ff1`](https://github.com/gptme/gptme/commit/4b0a88ff1))
 - perf(webui): skip buildStepRoles recompute on every streaming token ([#3370](https://github.com/gptme/gptme/issues/3370)) ([`bba854aad`](https://github.com/gptme/gptme/commit/bba854aad))
 - perf(webui): use Record instead of Map for stepRoles$ to enable per-row reactivity ([#3371](https://github.com/gptme/gptme/issues/3371)) ([`530d6ac09`](https://github.com/gptme/gptme/commit/530d6ac09))
 - perf(webui): remove debug console.log spam from useConversation ([#3369](https://github.com/gptme/gptme/issues/3369)) ([`c00fce620`](https://github.com/gptme/gptme/commit/c00fce620))
 - perf(webui): fix O(n²) DOM writes during streaming code blocks ([#3368](https://github.com/gptme/gptme/issues/3368)) ([`93c77e29b`](https://github.com/gptme/gptme/commit/93c77e29b))
 - docs: add contributor-facing PR lifecycle guide ([#3365](https://github.com/gptme/gptme/issues/3365)) ([`de9e1beaf`](https://github.com/gptme/gptme/commit/de9e1beaf))
 - perf(webui): skip hljs.highlightAuto for gptme tool-output tags ([#3364](https://github.com/gptme/gptme/issues/3364)) ([`57b2ce0e2`](https://github.com/gptme/gptme/commit/57b2ce0e2))
 - perf(webui): fix O(n²) syntax highlighting and scroll thrash during generation ([#3363](https://github.com/gptme/gptme/issues/3363)) ([`442882760`](https://github.com/gptme/gptme/commit/442882760))
 - docs(providers): add LM Studio section and tool-use verification tip ([#3357](https://github.com/gptme/gptme/issues/3357)) ([`b66e24c00`](https://github.com/gptme/gptme/commit/b66e24c00))
 - test(acp): add end-to-end smoke test for ACP agent ([#3356](https://github.com/gptme/gptme/issues/3356)) ([`6b9f7db70`](https://github.com/gptme/gptme/commit/6b9f7db70))
 - docs(providers): add provider integration guide + test scaffold ([#3354](https://github.com/gptme/gptme/issues/3354)) ([`fdd0631b0`](https://github.com/gptme/gptme/commit/fdd0631b0))
 - test(tui): guard against italic text-style regression ([#3340](https://github.com/gptme/gptme/issues/3340)) ([#3344](https://github.com/gptme/gptme/issues/3344)) ([`e6952436f`](https://github.com/gptme/gptme/commit/e6952436f))
 - test(tui): activate gray-background regression guards now that [#3334](https://github.com/gptme/gptme/issues/3334) is merged ([#3339](https://github.com/gptme/gptme/issues/3339)) ([`714035fbb`](https://github.com/gptme/gptme/commit/714035fbb))
 - test(tui): add SVG visual regression tests for TUI rendering ([#3338](https://github.com/gptme/gptme/issues/3338)) ([`f4332b337`](https://github.com/gptme/gptme/commit/f4332b337))
 - docs(server): add Security section — threat model, auth model, and workspace PATCH semantics ([#3333](https://github.com/gptme/gptme/issues/3333)) ([`a314438ad`](https://github.com/gptme/gptme/commit/a314438ad))
 - test(server): regression test for generation_complete ordering (refs [#3315](https://github.com/gptme/gptme/issues/3315)) ([#3323](https://github.com/gptme/gptme/issues/3323)) ([`20cb45f58`](https://github.com/gptme/gptme/commit/20cb45f58))
 - test(webui): add ExternalSessionDetail unit tests (steer_inject path) ([#3308](https://github.com/gptme/gptme/issues/3308)) ([`a5b65b12a`](https://github.com/gptme/gptme/commit/a5b65b12a))
 - experiment(computer): semantic verification contract prototype ([#3275](https://github.com/gptme/gptme/issues/3275)) ([`a1d8ca21d`](https://github.com/gptme/gptme/commit/a1d8ca21d))

</p>
</details>

*(excluded 11 less relevant [commits](https://github.com/gptme/gptme/compare/v0.32.1...v0.33.0))*

**Full Changelog**: https://github.com/gptme/gptme/compare/v0.32.1...v0.33.0