Skip to content

Commit 214e4a1

Browse files
Merge pull request #19 from OpenStatSpec/release/python-v080
Release Python v0.8.0: read-only exports and packaged Dolt support
2 parents 180f92a + 6431067 commit 214e4a1

27 files changed

Lines changed: 793 additions & 1015 deletions

‎.github/workflows/ci.yml‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
uses: actions/checkout@v7
2121
with: &specification-checkout
2222
repository: OpenStatSpec/specification
23-
ref: cd8f198c68b849eb8ed018a894670a0904c2181d
23+
ref: 864e84479f554b8ee250ffed44c4dfb963750d4a
2424
path: openstatspec-specification
2525
- name: Checkout required SPSS engine
2626
uses: actions/checkout@v7
@@ -53,9 +53,9 @@ jobs:
5353
- run: python -m pip install --upgrade pip build
5454
- run: python -m build
5555
- run: python -m venv /tmp/openstatspec-wheel-smoke
56-
- run: /tmp/openstatspec-wheel-smoke/bin/python -m pip install ./openstatspec-pyspssio
5756
- run: /tmp/openstatspec-wheel-smoke/bin/python -m pip install dist/*.whl
58-
- run: /tmp/openstatspec-wheel-smoke/bin/openstatspec capabilities
57+
- run: env -u PYTHONPATH /tmp/openstatspec-wheel-smoke/bin/openstatspec capabilities
58+
working-directory: /tmp
5959

6060
postgres-integration:
6161
name: PostgreSQL ${{ matrix.postgres }} integration
@@ -143,7 +143,7 @@ jobs:
143143
steps: *sql-test-steps
144144

145145
dolt-integration:
146-
name: Dolt ${{ matrix.dolt }} read-only / fail-closed integration
146+
name: Dolt ${{ matrix.dolt }} default-write integration
147147
runs-on: ubuntu-latest
148148
strategy:
149149
fail-fast: false
@@ -155,6 +155,7 @@ jobs:
155155
image: dolthub/dolt:2.2.3@sha256:1a651e738a2e7275b9c69fec8c5f42c6e23954314405c412f4dc9287ee7c0080
156156
env:
157157
OPENSTATSPEC_DOLT_URL: mysql+pymysql://openstatspec:openstatspec@127.0.0.1:13308/openstatspec
158+
OPENSTATSPEC_TEST_DOLT_ADMIN_URL: mysql+pymysql://openstatspec_test_admin:ci-admin@127.0.0.1:13308/
158159
OPENSTATSPEC_EXPECTED_DOLT_VERSION: ${{ matrix.dolt }}
159160
OPENSTATSPEC_DOLT_IMAGE: ${{ matrix.image }}
160161
steps:
@@ -186,6 +187,11 @@ jobs:
186187
--workdir /var/lib/dolt \
187188
"$OPENSTATSPEC_DOLT_IMAGE" sql \
188189
-q "CREATE USER 'openstatspec'@'%' IDENTIFIED BY 'openstatspec'; GRANT ALL PRIVILEGES ON openstatspec.* TO 'openstatspec'@'%'"
190+
docker run --rm \
191+
--volume "$RUNNER_TEMP/openstatspec-dolt:/var/lib/dolt" \
192+
--workdir /var/lib/dolt \
193+
"$OPENSTATSPEC_DOLT_IMAGE" sql \
194+
-q "CREATE USER 'openstatspec_test_admin'@'%' IDENTIFIED BY 'ci-admin'; GRANT ALL PRIVILEGES ON *.* TO 'openstatspec_test_admin'@'%' WITH GRANT OPTION"
189195
docker run --detach --name openstatspec-dolt \
190196
--publish 127.0.0.1:13308:3306 \
191197
--volume "$RUNNER_TEMP/openstatspec-dolt:/var/lib/dolt" \
@@ -218,6 +224,7 @@ jobs:
218224
break
219225
PY
220226
- run: python -m pytest -m "services and not candidate_evidence"
227+
- run: python -m pytest tests/test_read_only_export.py
221228
- name: Show Dolt logs on failure and stop server
222229
if: always()
223230
run: |

‎.github/workflows/release.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
4949
with:
5050
repository: OpenStatSpec/specification
51-
ref: cd8f198c68b849eb8ed018a894670a0904c2181d
51+
ref: 864e84479f554b8ee250ffed44c4dfb963750d4a
5252
path: openstatspec-specification
5353
- name: Checkout specification package source
5454
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -159,9 +159,9 @@ jobs:
159159
- run: python -m pip install -e ".[dev]"
160160
- run: python -m pytest -m "not services"
161161
- run: python -m venv /tmp/openstatspec-release-smoke
162-
- run: /tmp/openstatspec-release-smoke/bin/python -m pip install ./openstatspec-pyspssio
163162
- run: /tmp/openstatspec-release-smoke/bin/python -m pip install dist/openstatspec/openstatspec-*.whl
164-
- run: /tmp/openstatspec-release-smoke/bin/openstatspec capabilities
163+
- run: env -u PYTHONPATH /tmp/openstatspec-release-smoke/bin/openstatspec capabilities
164+
working-directory: /tmp
165165
- name: Smoke-test specification wheel
166166
run: |
167167
python -m venv /tmp/openstatspec-specification-release-smoke

‎CHANGELOG.md‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,30 @@ All notable changes to this reference implementation are documented here.
66

77
_No unreleased changes._
88

9+
## 0.8.0 - 2026-09-07
10+
11+
### Changed
12+
13+
- Pin released specification `v0.5.0` at exact commit
14+
`864e84479f554b8ee250ffed44c4dfb963750d4a`, with normative status `released`.
15+
Capabilities identify adapter version 0.8.0 and explicitly select SAV/ZSAV 1.0
16+
with `database_io_policy=openstatspec-database-io-v1`.
17+
- Reads, inspection, validation, and SAV/ZSAV export no longer write database
18+
operation/fidelity audit records, including on failure. Export diagnostics
19+
and loss consent remain operation-scoped; export results omit `operation_id`.
20+
- Default Dolt writes use the packaged tested exact-version policy for 2.2.2
21+
and 2.2.3 without user-supplied evidence files. Unknown/untested versions
22+
remain blocked before mutation; explicit external overrides remain strict.
23+
Safety budgets are not claimed as proven native server limits.
24+
- Dolt reads no longer require write-version declarations or the write
25+
variable-count ceiling. Missing SQLite files are rejected without creation.
26+
- Exact Dolt 2.2.2/2.2.3 CI explicitly runs SELECT-only export success/failure
27+
tests using a separate fixture-admin account; normal service permissions
28+
and adapter permissions are unchanged. Wheel smoke installs resolve the
29+
required engine from PyPI rather than a source checkout.
30+
31+
No optional Transformation Workflow 0.3 implementation is claimed.
32+
933
## 0.7.1 - 2026-08-12
1034

1135
### Changed

‎README.md‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ The reference Python implementation of the OpenStatSpec specification.
44

55
This package implements the specification; it does not define or extend it.
66
The normative model lives in the `OpenStatSpec/specification` repository.
7+
Python 0.8.0 pins released specification `v0.5.0` at
8+
`864e84479f554b8ee250ffed44c4dfb963750d4a` and selects SAV/ZSAV 1.0 with
9+
`database_io_policy=openstatspec-database-io-v1`. This does not claim
10+
implementation of the optional Transformation Workflow 0.3 profile.
711

812
## Boundaries
913

@@ -96,25 +100,27 @@ SAV/ZSAV export for the semantics exposed by that engine. SQLite is the local
96100
reference path.
97101
PostgreSQL, MySQL, MariaDB, and Dolt are each covered by separate service-backed CI
98102
conformance checks. Dolt support is an independent core profile for the
99-
canonical stable range `>=2.2.2,<2.3.0`; earlier patches, other families,
100-
noncanonical versions, and unknown MySQL-wire products fail closed.
103+
exact write-supported versions 2.2.2 and 2.2.3; all other versions (including
104+
2.3.0), noncanonical versions, and unknown MySQL-wire products fail closed for writes.
101105

102106
The supported family claims are broader than the deliberately exact CI
103107
evidence points: PostgreSQL 17.x/18.x is exercised at 17.10/18.4, MySQL
104108
8.4.x/9.7.x at 8.4.11/9.7.2, and MariaDB 11.4.x/11.8.x/12.3.x at
105109
11.4.12/11.8.8/12.3.2. Each service job checks the normalized live server
106110
version against its exact matrix entry before that run can count as evidence.
107-
Dolt claims the conservative 2.2.x range `>=2.2.2,<2.3.0`; its full service
108-
suite is exercised independently at exact versions 2.2.2 and 2.2.3 using
109-
immutable container-image digests.
111+
Dolt's default-write service checks run independently at exact versions 2.2.2
112+
and 2.2.3 using immutable container-image digests. Release/CI owns this evidence;
113+
normal callers need no declaration or evidence files. The optional explicit
114+
`DoltConformanceSource` override remains strict and does not fall back to the
115+
default policy if its declarations are missing, invalid, or mismatched.
110116

111117
| Engine/profile | Runtime supported policy | Exact CI-tested versions |
112118
| --- | --- | --- |
113119
| SQLite core / optional workflow | Core `>=3.24.0,<4.0.0`; optional workflow `>=3.35.0,<4.0.0` | Runtime-provided SQLite on Python 3.11–3.14 runners; not a pinned server image |
114120
| PostgreSQL | 17.x and 18.x | 17.10 and 18.4 |
115121
| MySQL | 8.4.x and 9.7.x | 8.4.11 and 9.7.2 |
116122
| MariaDB | 11.4.x, 11.8.x, and 12.3.x | 11.4.12, 11.8.8, and 12.3.2 |
117-
| Dolt | 2.2.x with `>=2.2.2,<2.3.0` | 2.2.2 and 2.2.3 |
123+
| Dolt writes | Exactly 2.2.2 and 2.2.3 | 2.2.2 and 2.2.3 |
118124

119125
Microsoft SQL Server (MSSQL) remains roadmap-only and is not a supported
120126
runtime profile; see the specification's [MSSQL roadmap](https://github.com/OpenStatSpec/specification/blob/main/docs/mssql-dialect-roadmap.md).
@@ -124,16 +130,24 @@ Use these explicit SQLAlchemy URLs:
124130
- SQLite: `sqlite:///dataset.sqlite`
125131
- PostgreSQL: `postgresql+psycopg://user:password@host/database`
126132
- MySQL/MariaDB: `mysql+pymysql://user:password@host/database`
127-
- Dolt `>=2.2.2,<2.3.0`: `mysql+pymysql://user:password@host/database` (detected by server identity)
133+
- Dolt 2.2.2 or 2.2.3: `mysql+pymysql://user:password@host/database` (detected by server identity)
128134

129135
The Dolt core profile supports strict wide-table import, validation, and export;
130136
the separate Transformation Workflow is unsupported.
131137

132138
Run `openstatspec capabilities` before an integration to inspect the
133139
machine-readable feature matrix. Export is deliberately strict: if known
134140
dictionary semantics cannot be reproduced, it stops until you pass the exact
135-
diagnostic code with `--allow-loss`. This avoids silent loss while making an
136-
intentional lossy export auditable.
141+
diagnostic code with `--allow-loss`. Diagnostics are returned to the caller, not
142+
persisted. Reads, validation, and SAV/ZSAV export never write to the database,
143+
including on failure. Export returns no `operation_id` and needs only read
144+
permissions; Dolt reads have no write-version or write-variable-count gate.
145+
Read operations reject missing SQLite files without creating them. Imports and transformations
146+
use the packaged exact-version policy by default. Active driver/identity checks,
147+
limit preflight, and the clean expected branch/HEAD guard for in-place apply
148+
remain mandatory. Dolt's reported limits are adapter safety budgets, narrowed
149+
by the active packet limit, not proven native server ceilings; full boundary
150+
conformance is not claimed.
137151

138152
The matrix is also available to Python callers as
139153
`openstatspec.capability_matrix()`. It distinguishes supported semantics from

‎docs/release-readiness.md‎

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
# 0.7.1 release readiness
1+
# 0.8.0 release readiness
22

33
This page records the expected release contract, not a publication event.
44
Creating a version tag remains a separate maintainer action.
55

6+
The release selects SAV/ZSAV 1.0 with the optional Database I/O Execution
7+
Policy `openstatspec-database-io-v1`. Reads and exports, including failures,
8+
write no database audit records; export results omit `operation_id` and return
9+
diagnostics to the caller. Reads must not create missing SQLite files or apply
10+
Dolt write-variable-count ceilings. This release does not claim implementation
11+
of the optional Transformation Workflow 0.3 profile.
12+
613
## Supported workflow
714

815
For a supported unencrypted SAV or ZSAV source, the adapter imports one source
@@ -20,15 +27,17 @@ database contract.
2027
| PostgreSQL | `postgresql+psycopg://…` | 17.x and 18.x | 17.10 and 18.4 |
2128
| MySQL | `mysql+pymysql://…` | 8.4.x and 9.7.x | 8.4.11 and 9.7.2 |
2229
| MariaDB | `mysql+pymysql://…` | 11.4.x, 11.8.x, and 12.3.x | 11.4.12, 11.8.8, and 12.3.2 |
23-
| Dolt | `mysql+pymysql://…` | 2.2.x with `>=2.2.2,<2.3.0` | 2.2.2 and 2.2.3 |
30+
| Dolt writes | `mysql+pymysql://…` | Exactly 2.2.2 and 2.2.3 | 2.2.2 and 2.2.3 |
2431

2532
Separate service matrices test the shared MySQL/MariaDB profile contract while
2633
retaining distinct active-server identities and version claims. Dolt is an
27-
independent core profile that accepts only canonical stable versions in
28-
`>=2.2.2,<2.3.0`; the optional Transformation Workflow remains SQLite-only. This does not
29-
claim coverage for every server configuration. The machine-readable capability
30-
declaration reports both the theoretical profile boundaries and effective
31-
limits observed from the active connection.
34+
independent core profile with a packaged exact-version write policy; normal
35+
callers supply no conformance files. An explicit external declaration source
36+
remains a strict override. Read-only validation/export has no write-version gate.
37+
The optional Transformation Workflow remains SQLite-only. This does not claim
38+
coverage for every server configuration or proven Dolt native limit ceilings.
39+
Dolt capabilities report adapter safety budgets and active packet constraints;
40+
full boundary conformance remains pending.
3241
Every server service job compares the normalized live product version with its
3342
exact matrix entry, so a moved or mismatched image cannot substantiate the CI
3443
declaration. SQLite's optional Transformation Workflow retains its narrower
@@ -102,6 +111,51 @@ implemented openstatspec.frontends.spss package. Stata and SAS remain empty
102111
source-tree placeholders and must expose no compiler, apply API, CLI choice,
103112
capability claim, or implied support.
104113

114+
## Prior default Dolt write verification (before the 0.8.0 pin)
115+
116+
Local release verification used the exact 2.2.2 and 2.2.3 image digests in
117+
`.github/workflows/ci.yml`, isolated ports 13482/13483, and disposable `/tmp`
118+
database directories. With `PYTHONPATH=src:../pyspssio`,
119+
`OPENSTATSPEC_SPECIFICATION_DIR=/tmp/oss-php-spec-cd8f198`, and each matching
120+
`OPENSTATSPEC_DOLT_URL` / `OPENSTATSPEC_EXPECTED_DOLT_VERSION`:
121+
122+
- `../python/.venv/bin/python -m pytest`: **366 passed, 49 skipped per pin**.
123+
- CI selection `-m 'services and not candidate_evidence'`: **7 passed,
124+
41 skipped per pin**; other database services were not configured locally.
125+
- Dolt 2.3.0 on port 13387: read-only export and unknown-version write rejection
126+
checks passed (**19 passed**) using disposable fixture databases/users.
127+
- `python -m compileall -q src tests` and `git diff --check` passed.
128+
129+
Live failures exposed and now cover two previously dormant write blockers:
130+
owned table additions being misclassified as unrelated diffs, and Dolt retaining
131+
`@@autocommit=1` despite the driver's setting. Writes now explicitly begin their
132+
transaction. The candidate storage/identifier/column smoke probe also passed on
133+
both pins; it does **not** establish full value/row/statement limit conformance.
134+
135+
## 0.8.0 local verification
136+
137+
Using `../python/.venv/bin/python`, `PYTHONPATH=src:../pyspssio`, and
138+
`OPENSTATSPEC_SPECIFICATION_DIR=/tmp/oss-python-spec-v050-5dSTna` (an archive
139+
of exact `864e84479f554b8ee250ffed44c4dfb963750d4a`):
140+
141+
- `python -m pytest -ra`: **381 passed, 49 skipped**, with
142+
`OPENSTATSPEC_TEST_DOLT_ADMIN_URL=mysql+pymysql://root@127.0.0.1:13387/`
143+
exercising live Dolt 2.3.0 through disposable SELECT-only users.
144+
- Both immutable CI images, exact Dolt 2.2.2/2.2.3, bootstrapped with the
145+
unchanged service user and separate global fixture admin on ports 13582/13583:
146+
`python -m pytest -m 'services and not candidate_evidence'`: **7 passed,
147+
41 skipped, 382 deselected per pin**; explicit
148+
`python -m pytest tests/test_read_only_export.py`: **33 passed per pin**.
149+
- `python -m compileall -q src tests`, `git diff --check`, wheel/sdist build,
150+
and `python -m twine check /tmp/oss-python-v080-dist/*` passed.
151+
- A clean wheel install resolved the required engine from PyPI. Isolated
152+
imports came only from the smoke environment's `site-packages`; installed
153+
capabilities reported adapter 0.8.0, the selected policy, released v0.5.0
154+
provenance, and exactly 2.2.2/2.2.3 for default Dolt writes.
155+
156+
Other database services were not configured locally. This is local evidence,
157+
not a claim that the updated remote CI or release publication has completed.
158+
105159
## Maintainer checks before tagging
106160

107161
1. Publish the pinned `openstatspec-pyspssio==0.5.1.post2` engine distribution
@@ -110,14 +164,28 @@ capability claim, or implied support.
110164
2. Run `python -m pytest -m "not services"`.
111165
3. Confirm the GitHub Actions matrix is green for exact PostgreSQL 17.10/18.4,
112166
MySQL 8.4.11/9.7.2, MariaDB 11.4.12/11.8.8/12.3.2, and exact Dolt
113-
2.2.2/2.2.3 service evidence from the immutable image pins in CI.
167+
2.2.2/2.2.3 service evidence from the immutable image pins in CI. The Dolt
168+
jobs must perform default import/validate/SAV+ZSAV export, in-place recode
169+
and labels with unchanged dataset/table counts and HEAD, injected data,
170+
catalog, and audit rollback checks, and failed-import cleanup. Release/CI
171+
owns this evidence, not per-user runtime declaration files. Candidate limit
172+
probes remain non-claiming and separate from these write gates.
173+
Each Dolt job must also run `python -m pytest tests/test_read_only_export.py`
174+
explicitly, outside the `services` marker filter. Bootstrap a separate
175+
`openstatspec_test_admin` on the isolated CI server with global database/user
176+
creation and grant privileges, and set `OPENSTATSPEC_TEST_DOLT_ADMIN_URL`.
177+
The fixture creates its own database and SELECT-only reader and removes
178+
both afterward; the normal service user remains unchanged.
114179
4. Build with `python -m build` and install the generated wheel in a clean
115-
environment.
180+
environment, resolving `openstatspec-pyspssio==0.5.1.post2` from PyPI.
181+
Run the installed CLI outside the source checkout with `PYTHONPATH` unset;
182+
verify adapter version `0.8.0` and the selected database I/O policy.
116183
5. Confirm `openstatspec capabilities` reflects the intended support boundary.
117184
6. Confirm CI, release fixtures, and capabilities use the published OpenStatSpec
118-
specification `v0.3.0` at exact commit
119-
`cd8f198c68b849eb8ed018a894670a0904c2181d`, publish
120-
`specification_status=stable`, and set `specification_release` to `v0.3.0`.
185+
specification `v0.5.0` at exact commit
186+
`864e84479f554b8ee250ffed44c4dfb963750d4a`, publish
187+
`specification_status=released`, and set `specification_release` to `v0.5.0`.
188+
Use an exact checkout via `OPENSTATSPEC_SPECIFICATION_DIR` for local tests.
121189
7. Review this document, the README, and CHANGELOG for accurate scope.
122190

123191
The tag-triggered release workflow repeats the non-service test suite, builds

‎docs/sav-profile.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ equivalence of supported values, order, and dictionary metadata.
4949

5050
The `openstatspec capabilities` command and the
5151
`openstatspec.capability_matrix()` function are the machine-readable declaration
52-
of this boundary. It records the pinned source commit and installed engine version, and the adapter stores the same identity in every import and export operation record. The matrix deliberately distinguishes a supported feature from a feature that the underlying engine cannot observe or write faithfully.
52+
of this boundary. It records the pinned source commit and installed engine version, and the adapter stores the same identity in import operation records. Export is database-read-only: no operation, fidelity, recovery, or Dolt-history records are written, even on failure. Loss diagnostics are returned to the caller. Dolt export identifies the server and validates the catalog and data without requiring write-conformance declarations; write entry points retain that requirement. The matrix deliberately distinguishes a supported feature from a feature that the underlying engine cannot observe or write faithfully.
5353

5454
| SPSS semantic | Pinned pyspssio status | Behaviour |
5555
| --- | --- | --- |

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "openstatspec"
7-
version = "0.7.1"
7+
version = "0.8.0"
88
description = "Reference adapter for the OpenStatSpec relational contract"
99
readme = "README.md"
1010
requires-python = ">=3.11"

0 commit comments

Comments
 (0)