From d178530881bb0e7c10bb624d1b98565c5f5c4b50 Mon Sep 17 00:00:00 2001 From: Layne Penney Date: Fri, 21 Aug 2026 19:03:24 -0500 Subject: [PATCH] chore: release 0.19.0 Version bump, a changelog entry, and one bug fix that belongs in the release rather than after it. WHY 0.19.0 AND NOT 0.18.1. 0.18.0 was published to PyPI at 2026-08-07T18:01:21Z. All 17 first-parent units in the range ca62880..bc594f3 landed after that instant, checked against each commit's date rather than inferred, so the published artifact contains none of them. PyPI forbids re-uploading a version. An earlier version of this message said 11 of those units landed after the publish date. That was wrong. 11 is a real count, of units carrying product changes, attached to a claim about timing where the answer is all 17. The range starts at the 0.18.0 promotion merge, four minutes before PyPI published, so no subset of it can be the post-publish set. Caught in review before anything shipped. COUNTING RULE. Over ca62880..bc594f3: 35 commits, 17 merges, 18 direct, 17 first-parent. Of the 17, twelve touch src/ and five touch only tests, docs, or fixtures; one of those five is a topology-repair merge carrying no content. THE FIX. tests/recall_store_isolation.py imported the POSIX-only pwd module at module scope. conftest.py imports that module at root scope, so on Windows the ModuleNotFoundError fired before any collection at all, taking down the whole run rather than one module. The import now happens at call time; POSIX behaviour is byte-identical. Deliberately not replaced with Path.home(). That reads $HOME, which is exactly the value a fixture can move, and the protected boundary must not be derivable from the value under test or the guarantee becomes circular. On Windows it still raises, at the point of use, which is honest for a POSIX-only guarantee. Co-Authored-By: Claude Opus 5 (1M context) --- CHANGELOG.md | 85 +++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/synapt/recall/__init__.py | 2 +- tests/recall_store_isolation.py | 14 +++++- 4 files changed, 100 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05ab3f86..80253209 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,91 @@ All notable changes to synapt are documented here. +## [0.19.0] — 2026-08-21 + +**Counting rule, stated so it can be checked.** Range `ca62880..bc594f3` — from the 0.18.0 +promotion merge to the `dev` tip at this release. Over that range: **35 commits total, 17 of +them merge commits and 18 direct. 17 first-parent commits.** + +Composition of those 17, by path: **12 touch `src/` when each unit is diffed against its first +parent**; 5 touch only tests, docs, or fixtures; and one of those 5 (`116ffcc`) is a +post-promotion topology-repair merge carrying no content by its own message. "Reviewed units +landed" is therefore 16 if you mean units that changed something, and 17 if you mean merges in +the range. + +**The diff method is part of the claim, not pedantry.** A merge commit has no canonical diff. +Against first parent — or `git log --first-parent --diff-merges=first-parent` — the answer is +12. But `git show --name-only`, which is the command most readers will reach for first, +returns **0**: a combined diff omits everything that was not a conflict resolution, and it does +so silently rather than as an error. A count offered for checking is worth only as much as the +method that reproduces it. + +**Why 0.19.0 and not 0.18.1.** 0.18.0 was published to PyPI at `2026-08-07T18:01:21Z`. **Every +one of the 17 units above landed after that instant** — measured against each commit's date, +not inferred. The published 0.18.0 artifact contains none of this work. PyPI forbids +re-uploading a version, so this is a new minor rather than a patch to the existing one. + +An earlier draft of this section said "11 of the units above landed after that date." **The +number 11 was real but attached to the wrong category** — it counts units carrying product +changes, which the prose never named, while the sentence was making a claim about *timing*, +where the true answer is all 17. Caught in review before this shipped. Worth recording rather than silently +correcting, because this section's heading invites a reader to check the numbers, and a reader +who finds one that fails has no way to know the other four are exact. + +### Fixed +- **Windows test collection, broken on every pull request since 2026-08-07.** + `tests/recall_store_isolation.py` imported the POSIX-only `pwd` module at module scope, and + `conftest.py` imports that module at *root* scope. The `ModuleNotFoundError` therefore fired + before any collection at all — earlier than skip markers exist, so no marker could have + applied — taking down the entire Windows run rather than one module. The import is now made + at call time. POSIX behaviour is byte-identical. + + **What is recorded here is the fact, without a theory attached.** Across all 19 pull-request + runs since 0.18.0 published, three Windows jobs failed in **every single one**, without + exception. That is measured, not sampled. + + Why it went unaddressed for two weeks is **not something this entry can answer honestly.** An + earlier draft offered an explanation — that the rest of the matrix stayed green, so a + partially-red result read as a flaky lane rather than a broken one. Measurement does not + support it: that pattern holds in 8 of the 19 runs and is false in the other 11, where the + entire matrix was red for reasons this fix does not address and this entry does not diagnose. + The explanation was removed rather than softened. + + Deliberately **not** replaced with `Path.home()`: that function reads `$HOME`, which is + precisely the value a test fixture can move, and the protected boundary must not be + derivable from the value under test or the guarantee becomes circular. On Windows the + function still raises, loudly and at the point of use, which is the honest outcome for a + POSIX-only guarantee. + +### Added +- **Incremental builds by default**, with a new `maintain` command and change-detection + idempotence. + +### Changed +- **Summary work moved out of `build` and into `maintain`.** This is a user-visible behaviour + change, not only an internal one: a `build` that previously produced summaries no longer + does, and `maintain` is where that work now happens. + +### Improved +- **Store and data-root isolation**, including a resolution fix so that membership takes + precedence over locality. +- **Journal correctness**, and a root-resolution fix across the archive verbs — export and + import, and also the archive, CLI, and server paths. +- **`code_git` hardening** and a session-start prompt fix. + +### Documentation +- Fixture provenance is now declared for the identify test fixtures. + +### Note on the changelog gap +**0.15.2, 0.15.3, 0.16.0, 0.17.0, and 0.18.0 shipped without changelog entries** — the gap is +wider than the three versions an earlier draft named. Rather than reconstruct them after the +fact from commit archaeology, it is recorded here honestly. + +Their content **is** recoverable from the git history between the corresponding tags. **All five +were checked on the public remote** with `ls-remote` — `v0.15.2`, `v0.15.3`, `v0.16.0`, +`v0.17.0`, and `v0.18.0` — not merely the three an earlier draft vouched for while naming five. +A recovery instruction is worth only as much as the refs it names. + ## [0.15.1] — 2026-05-12 ### Fixed diff --git a/pyproject.toml b/pyproject.toml index 521fac60..f9551a08 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "synapt" -version = "0.18.0" +version = "0.19.0" description = "Persistent conversational memory for AI coding assistants" readme = "README.md" license = "MIT" diff --git a/src/synapt/recall/__init__.py b/src/synapt/recall/__init__.py index 6269df13..9140704a 100644 --- a/src/synapt/recall/__init__.py +++ b/src/synapt/recall/__init__.py @@ -1,6 +1,6 @@ """synapt.recall — persistent conversational memory for Claude Code and ChatGPT sessions.""" -__version__ = "0.18.0" +__version__ = "0.19.0" from synapt.recall.core import ( TranscriptChunk, diff --git a/tests/recall_store_isolation.py b/tests/recall_store_isolation.py index 747ee3b7..7b927f0b 100644 --- a/tests/recall_store_isolation.py +++ b/tests/recall_store_isolation.py @@ -15,7 +15,6 @@ from __future__ import annotations import os -import pwd from pathlib import Path @@ -35,7 +34,20 @@ def account_home() -> Path: precisely because a fixture can move both of those. The protected boundary must not be derivable from the value a test is currently asking the code to use, or every guarantee here becomes circular. + + ``pwd`` is imported here rather than at module scope because it is POSIX-only. + At module scope it raises ``ModuleNotFoundError`` on Windows during pytest + *collection* — before any skip marker could apply — which took down the whole + Windows run rather than this one module. Importing at call time keeps + collection working everywhere and leaves POSIX behaviour byte-identical. + + Deliberately NOT replaced with ``Path.home()``: that reads ``$HOME``, which is + exactly the value a fixture can move, and would make the boundary circular in + the way the paragraph above forbids. On Windows this still raises, loudly and + at the point of use, which is the honest outcome for a POSIX-only guarantee. """ + import pwd + return Path(pwd.getpwuid(os.getuid()).pw_dir).resolve()