Skip to content

Reconcile Python v0.6.1 release with main - #320

Merged
gadenbuie merged 2 commits into
mainfrom
py-v0.6.1
Aug 14, 2026
Merged

Reconcile Python v0.6.1 release with main#320
gadenbuie merged 2 commits into
mainfrom
py-v0.6.1

Conversation

@gadenbuie

@gadenbuie gadenbuie commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Merges main into the tagged py-v0.6.1 release branch so py/v0.6.1 remains in the ancestry when this work lands on main.
  • Adds the dated Python 0.6.1 changelog section with the four published fixes while keeping genuinely unreleased work under UNRELEASED.
  • Resolves the merge tree to match main everywhere except pkg-py/CHANGELOG.md, preventing older release-branch implementations from replacing refined code on main.

Landing requirement

GitHub merge commits are disabled for this repository. After review, this PR must be landed manually without squash or rebase so py/v0.6.1 remains an ancestor of main.

Verification

  • git diff --name-only origin/main..HEAD reports only pkg-py/CHANGELOG.md.
  • Both py/v0.6.1 and origin/main are ancestors of the reconciliation commit.
  • Hatch reports 0.6.2.dev23+gaa35a098.
  • Ran Ruff, Pyright, and the Python unit and browser test targets locally.
  • The isolated rerun of the initially failing history_current browser test completed successfully.

gadenbuie and others added 2 commits August 14, 2026 13:01
* fix(py,r): reject unsupported conversation-history schema versions (#313)

* fix(py,r): reject unsupported conversation-history schema versions

FileConversationStore/InMemoryConversationStore now validate
schema_version on read (get/list) and write (put) against
MIN_SCHEMA_VERSION/MAX_SCHEMA_VERSION, rejecting unsupported versions
before decoding or before any filesystem mutation. HistoryController
routes all store.get()/list() calls through internal helpers that
validate records regardless of which ConversationStore implementation
is in use, so custom stores can't bypass the check.

Fixes #312

* test(py,r): cover schema-version rejection on read, write, and custom stores

Adds tests for unsupported schema_version on get()/list(), rejecting
writes into an empty store and over an existing unsupported record
(asserting files are left byte-for-byte unchanged), InMemoryConversationStore
input rejection, legacy missing-schema_version round-trip, and a custom
ConversationStore whose output HistoryController rejects before it
reaches client state.

Also fixes two bugs surfaced by the new R tests in
FileConversationStore: list()'s tryCatch handler re-signaled the
unsupported-schema condition via stop(e), which was still caught by
the sibling error handler in the same tryCatch call; and put()'s
on-disk preflight used file.exists() without excluding directories,
breaking the existing atomic-rename-failure test.

Fixes #312

* docs(py,r): add changelog entries for schema-version rejection fix

Fixes #312

* docs(py,r): reference PR in schema-version changelog entries

* fix(py,r): harden schema version validation

* docs(py,r): omit internal schema guard notes

* Fix Python tool-result display serialization (#297)

* fix(py): serialize dictionary tool result displays

* fix(py): retain unknown tool display metadata

* test(py): cover persisted dictionary tool displays

* refactor(py): type chatlas turn serialization

* fix(pkg-py): degrade gracefully on a malformed bookmarked message (#289)

* fix(pkg-py): degrade gracefully on a malformed bookmarked message

_restore_bookmark_message() raised on a malformed message dict (e.g. a
bookmark written by an incompatible shinychat version), which aborts
the caller's restore loop and silently drops every message after the
bad one too -- Shiny's generic on_restore error handling only shows a
banner, it doesn't resume the loop.

Python has no turns-derived fallback to route into the way R's
decode_ui_snapshot() does, so the proportionate fix here is
per-message: warn and skip just the bad message, restoring everything
else.

* docs(pkg-py): changelog for the malformed bookmarked message skip

* fix(pkg-py): don't leak message content into the malformed-bookmark warning

ValidationError's default string embeds the offending input value, which
for a chat segment is arbitrary (and possibly sensitive) message content.
Use errors(include_input=False) and format loc/msg ourselves instead.

* fix: resolve race between the chat greeting and history restore (#275)

* fix(pkg-py): defer greeting to history's restore decision

Resolving the app greeting used to race an independent client-side
`{id}_greeting_requested` request against the server's async history
restore: reloading into a restored conversation could flash the
greeting before the restore replaced it, and a restored conversation's
transcript had no way to suppress a stale/incoming greeting.

Greeting resolution now defers to the same "is this conversation
restored?" decision `HistoryController` already computes on init and
on `new_chat()`, instead of a separate client-driven signal. Restoring
a conversation (whether on initial load or via the history drawer)
now explicitly clears any greeting, since a restored conversation is
never a "new chat".

* fix(pkg-r): defer greeting to history's restore decision

Mirrors the pkg-py fix: resolving the app greeting used to race an
independent client-side `{id}_greeting_requested` request against the
server's async history restore, which could flash the greeting on a
restored conversation, or leave a fresh conversation with no greeting
at all if the session began by restoring one.

Greeting resolution now defers to the same "is this conversation
restored?" decision `HistoryController` already computes on init and
on `new_chat()`. Restoring a conversation now explicitly clears any
greeting, since a restored conversation is never a "new chat".

* fix(pkg-py): add missing set_greeting support to history test fakes

_ReplayFakeChat and _TrackingChat didn't implement set_greeting, which
replay_ui() now calls to suppress the app greeting on restore.

---------

Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>

* chore(pkg-py): prepare 0.6.1 release notes

* chore(pkg-r): keep R package at v0.6.0

---------

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
@gadenbuie
gadenbuie marked this pull request as ready for review August 14, 2026 20:24
@gadenbuie
gadenbuie requested a review from cpsievert August 14, 2026 20:24
@gadenbuie
gadenbuie merged commit aa35a09 into main Aug 14, 2026
5 checks passed
@gadenbuie
gadenbuie deleted the py-v0.6.1 branch August 14, 2026 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant