Skip to content

v2.5.2b1 — beta: the contract breaks (store result / check_health status / source-type enum)

Pre-release
Pre-release

Choose a tag to compare

@Cloto-dev Cloto-dev released this 25 Jul 08:46

Pre-release (first beta of the 2.5.2 stabilization ladder; the latest final release remains v2.5.1, which pip installs by default — pre-releases require explicit opt-in).

The alpha rungs stayed inside the implementation. This one changes what callers see: it is the first cut of the 2.5.x line to break the public MCP tool contract, which is why it goes through the ladder (RELEASE_LIFECYCLE_STANDARD §2.1). The DB schema is unchanged — upgrade and rollback across this cut need no migration.

Contract breaks (3)

  • store answers whether it stored. Every response now carries result: stored (a row was written), skipped (nothing written, nothing wrong — dedup, or persistence paused), rejected (the request was refused). ok tracks that verdict instead of being unconditionally true, and the old skipped: true flag is gone. Previously a store that wrote nothing — empty content, content that sanitizes to empty — answered {ok: true}, so a caller checking the obvious field read success for a write that never happened.
  • check_health has one verdict. The healthy boolean is gone; status (healthy / degraded / unhealthy) is the verdict. The two fields disagreed by construction: healthy was len(issues) == 0, so a database whose only findings were informational reported healthy: false while status in the same response said healthy. The counts are still in issues and severity_summary.
  • One definition of the source-type enum. The canonical set was stated in three places and owned by none of them (a SQL literal in the health check, a tuple in the write seam, prose in the published schema). utils.CANONICAL_SOURCE_TYPES is now the single definition; the store JSON Schema publishes it as an enum and generates its alias sentence from the alias table, so a caller no longer learns the contract by reading a health check.

Also in this cut

  • Write-path bounds (bug-156): source and metadata reach the row as JSON with no size limit, and an episode's summary/keywords never had one — content has been capped since 2.1. Oversized sidecars are now refused, episode prose is capped in the shared prepare seam (so the queue drain obeys the same rule), and update_memory runs the same sanitizer as store instead of only .strip().
  • A silent filter, disclosed (bug-157): every external_context entry filtered recall while only user/assistant entries were merged into the response, so a system entry could make a memory disappear with nothing saying why. The response now carries context_filter_only.
  • Remote-recall hydration batched (bug-158): remote mode re-hydrated every hit with its own awaited SELECT ... WHERE id = ?. A limit=100 recall paid 100 sequential round trips on the read hot path — measured 102 for 102 hits, now 2.
  • Bounded /index push (bug-159): the write-path POST inherited the embed client's 30s default while the health probe (3s) and remote search (5s) each state their own. It states 10s now.
  • Descriptions rendered from the code they describe (bug-160): the check-registry size (claimed 20, was 23), which deep checks honour fix=true, the tools a pause silences, the @auto sentinel. Structural CI gates fail when any of them falls behind the implementation again. The shipped cpersona-memory skill had the same drift and is gated too.
  • 18 findings from the independent pre-ship review (bug-162..bug-179), and the outward claims the breaks falsified — README, SUPPORT.md and the standard saying the tool contract is preserved across line transitions — corrected in the same batch.

Verification

  • Behaviour-equivalence goldens were extended to the three layers these breaks touch (handler seam, MCP boundary, health/deep-check) before the breaks landed, with a frozen clock so wall-clock never reaches the golden; pin effectiveness was proven by hand-applied mutation. Each golden line that moved in this cut is one of the documented contract changes.
  • Full suite: 664 passed, 5 skipped; verify-issues.sh 178 entries, 0 errors; ruff clean; mutation-proof CI job green; waiver registry clean.
  • PyPI artifacts (wheel + sdist) published via OIDC Trusted Publishing with provenance.

Known gap

The automated mutation-diff lane was skipped on this cut: the diff exceeded the lane's cap, and the cap currently skips everything rather than selecting a subset (tracked; the fix makes large diffs sample instead of opt out). The contract changes carry hand-applied mutation evidence instead, recorded per test.