Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
coverage: none
extensions: pdo_pgsql, pdo_sqlite, bcmath, mbstring, zlib
- run: composer install --no-interaction --prefer-dist
- run: vendor/bin/phpunit --filter "PostgreSqlSpssRoundTripTest|ServerVersionEvidenceTest|ServerCatalogMigrationTest|StrictSpssDictionaryConformanceTest|OfficialSpssConformanceManifestTest"
- run: vendor/bin/phpunit --filter "PostgreSqlSpssRoundTripTest|ServerVersionEvidenceTest|ServerCatalogMigrationTest|StrictSpssDictionaryConformanceTest|OfficialSpssConformanceManifestTest|InPlaceTransformationServiceTest"

mysql-integration:
name: MySQL ${{ matrix.mysql }} integration / PHP ${{ matrix.php }}
Expand Down Expand Up @@ -115,7 +115,7 @@ jobs:
coverage: none
extensions: pdo_mysql, pdo_sqlite, bcmath, mbstring, zlib
- run: composer install --no-interaction --prefer-dist
- run: vendor/bin/phpunit --filter "MySqlSpssRoundTripTest|ServerVersionEvidenceTest|ServerCatalogMigrationTest|StrictSpssDictionaryConformanceTest|OfficialSpssConformanceManifestTest"
- run: vendor/bin/phpunit --filter "MySqlSpssRoundTripTest|ServerVersionEvidenceTest|ServerCatalogMigrationTest|StrictSpssDictionaryConformanceTest|OfficialSpssConformanceManifestTest|InPlaceTransformationServiceTest"

mariadb-integration:
name: MariaDB ${{ matrix.mariadb }} integration / PHP ${{ matrix.php }}
Expand Down Expand Up @@ -159,7 +159,7 @@ jobs:
coverage: none
extensions: pdo_mysql, pdo_sqlite, bcmath, mbstring, zlib
- run: composer install --no-interaction --prefer-dist
- run: vendor/bin/phpunit --filter "MariaDbSpssRoundTripTest|ServerVersionEvidenceTest|ServerCatalogMigrationTest|StrictSpssDictionaryConformanceTest|OfficialSpssConformanceManifestTest"
- run: vendor/bin/phpunit --filter "MariaDbSpssRoundTripTest|ServerVersionEvidenceTest|ServerCatalogMigrationTest|StrictSpssDictionaryConformanceTest|OfficialSpssConformanceManifestTest|InPlaceTransformationServiceTest"

dolt-integration:
name: Dolt ${{ matrix.dolt.version }} integration / PHP ${{ matrix.php }}
Expand Down Expand Up @@ -189,6 +189,8 @@ jobs:
OPENSTATSPEC_DOLT_DSN: mysql:host=127.0.0.1;port=3306;dbname=openstatspec;charset=utf8mb4
OPENSTATSPEC_DOLT_USER: openstatspec
OPENSTATSPEC_DOLT_PASSWORD: openstatspec
OPENSTATSPEC_DOLT_ADMIN_USER: root
OPENSTATSPEC_DOLT_ADMIN_PASSWORD: root
OPENSTATSPEC_EXPECTED_DOLT_VERSION: ${{ matrix.dolt.version }}
steps:
- uses: actions/checkout@v7
Expand All @@ -211,4 +213,4 @@ jobs:
done
exit 1
- run: composer install --no-interaction --prefer-dist
- run: vendor/bin/phpunit --filter "DoltSpssRoundTripTest|ServerVersionEvidenceTest|ServerCatalogMigrationTest|StrictSpssDictionaryConformanceTest|OfficialSpssConformanceManifestTest"
- run: vendor/bin/phpunit --filter "DoltSpssRoundTripTest|ServerVersionEvidenceTest|ServerCatalogMigrationTest|StrictSpssDictionaryConformanceTest|OfficialSpssConformanceManifestTest|InPlaceTransformationServiceTest"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/vendor/
/.superpowers/
/.php-cs-fixer.cache
/.phpunit.result.cache
/.phpunit.cache/
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@
documentation with the separately versioned OpenStatSpec package.
- Made the transformation capability boundary explicit: the current PHP API uses the package-local legacy `openstatspec-transformation-plan-v1` contract and does not yet claim official Transformation Plan or SPSS Frontend profile 0.1/0.2 conformance.

- Added the PHP in-place transformation service-matrix evidence gate. SQLite
runs locally; locally unconfigured PostgreSQL, MySQL, MariaDB, and Dolt
profiles skip, while CI configures and executes every service profile. The
gate proves existing-target dataset, physical-table, and variable identity;
it restricts implicit numeric target creation to SQLite/PostgreSQL and
requires MySQL/MariaDB/Dolt targets to be created and catalogued first.
This remains adapter evidence under the legacy contract, not an official
OpenStatSpec Transformation Plan 1.0 profile claim.

## [0.4.0] - 2026-07-31

### Added
Expand Down
25 changes: 20 additions & 5 deletions docs/release-readiness.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,25 @@ Before tagging a release:

1. Run `composer check` with `OPENSTATSPEC_SPECIFICATION_DIR` pointing to the
exact `v0.3.0` checkout.
2. Confirm GitHub Actions passes on PHP 8.4 and 8.5 plus the PostgreSQL,
MySQL, MariaDB, and Dolt service matrices.
3. Confirm the changelog and release notes describe the same specification
2. Run the focused service evidence command:
```bash
OPENSTATSPEC_SPECIFICATION_DIR=/path/to/openstatspec-specification \
vendor/bin/phpunit tests/Integration/InPlaceTransformationServiceTest.php
```
Locally, SQLite executes and an unconfigured PostgreSQL, MySQL, MariaDB, or
Dolt profile skips; CI must configure and execute every one of those
service profiles.
3. Confirm that the existing-target service evidence preserves the existing
dataset UUID, physical table, and variable identities without copied or
rollback state. Confirm that implicit numeric target creation is restricted
to SQLite and PostgreSQL, while MySQL, MariaDB, and Dolt reject it before
mutation and require a pre-created, catalogued target.
4. Confirm GitHub Actions passes on PHP 8.4 and 8.5 plus the PostgreSQL,
MySQL, MariaDB, and Dolt service matrices. This is adapter evidence under
the legacy `openstatspec-transformation-plan-v1` contract, not an official
OpenStatSpec Transformation Plan 1.0 profile claim.
5. Confirm the changelog and release notes describe the same specification
release and commit.
4. Create an annotated `vX.Y.Z` tag on the reviewed `main` commit and verify
6. Create an annotated `vX.Y.Z` tag on the reviewed `main` commit and verify
that the tag points to that commit before publishing the GitHub release.
5. Confirm the resulting Composer package is installable from Packagist.
7. Confirm the resulting Composer package is installable from Packagist.
89 changes: 89 additions & 0 deletions docs/superpowers/plans/2026-08-12-php-inplace-service-matrix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# PHP In-Place Transformation Service Matrix Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Add an integration evidence gate proving the PHP adapter's in-place transformation behavior and target-creation boundary for every claimed SQL profile, using major/minor `.x` version ranges.

**Architecture:** Extend the existing PHPUnit integration conventions with one profile-aware test class. Reuse the production executor and normative catalog APIs; create isolated deterministic fixtures per test, and compare database/Dolt state before and after preflight rejection. No production behavior change is authorized unless a failing evidence test exposes a real defect.

**Tech Stack:** PHP 8.4/8.5, PHPUnit, PDO, existing OpenStatSpec normative catalog and transformation services, SQLite, PostgreSQL, MySQL, MariaDB, Dolt, GitHub Actions.

## Global Constraints

- PHP adapter only; Python remains a separate workstream.
- Test every configured profile: SQLite, PostgreSQL, MySQL, MariaDB, and Dolt.
- Missing local service configuration skips only that profile; CI service jobs must supply configuration and execute it.
- Database version expectations use major/minor `.x` ranges (`17.x`, `8.4.x`, `11.4.x`, `2.2.x`), never fixed patch versions.
- Use unique fixture names/UUIDs per test; do not drop shared schemas or hide observed state with cleanup.
- Do not create snapshots, staging/copy tables, rollback tables, Dolt commits, branch changes, resets, or other artifacts as part of evidence setup or assertions.
- Preserve the legacy transformation-contract disclaimer; do not claim an official Transformation Plan 1.0 profile.

---

## Task 1: Add the profile-aware fixture and existing-target evidence test

**Files:**
- Create: `tests/Integration/InPlaceTransformationServiceTest.php`
- Reference: `tests/Integration/ServerVersionEvidenceTest.php`
- Reference: `tests/Integration/OfficialSpssConformanceManifestTest.php`
- Reference: `src/Transformation/Execution/InPlaceTransformationExecutor.php`

- [ ] Inspect existing integration connection helpers, catalog setup, identifiers, and cleanup conventions.
- [ ] Write the provider/configuration test first and run the focused test to establish the expected failure.
- [ ] Add a profile provider covering SQLite plus the `OPENSTATSPEC_PG_*`, `OPENSTATSPEC_MYSQL_*`, `OPENSTATSPEC_MARIADB_*`, and `OPENSTATSPEC_DOLT_*` environment families, with expected-version checks as major/minor `.x` ranges.
- [ ] Add deterministic fixture setup using dataset UUID `018f47f2-8b6a-7c3d-9e1f-123456789abc`, source values `[1, 2, 3, 9, NULL]`, destination values `[-1, -1, -1, -1, -1]`, and profile-aware quoted identifiers.
- [ ] Add the existing-target test: recode to `[10, 20, 20, 9, 99]`, update the variable label and value labels, and assert result dataset UUID/plan hash, unchanged physical identity, unchanged dataset/table/variable identity, catalog metadata, and absence of snapshot/staging/copied/derived/rollback/parallel-history tables.
- [ ] Run the focused SQLite test and relevant static checks; commit as `test: add PHP in-place service evidence`.

## Task 2: Add the target-creation boundary evidence

**Files:**
- Modify: `tests/Integration/InPlaceTransformationServiceTest.php`
- Reference: `src/Transformation/Execution/InPlaceTransformationExecutor.php`
- Reference: `src/Transformation/Execution/*`

- [ ] Add a test for SQLite and PostgreSQL where a new numeric target is created in the same wide table; assert the new catalog variable, physical column, recoded values, and unchanged dataset/table identity.
- [ ] Add the equivalent MySQL, MariaDB, and Dolt test; capture rows, catalog rows, physical columns, dataset count, and table names before execution.
- [ ] Assert those profiles reject the plan during preflight with the documented capability exception and leave every captured value byte-for-byte equivalent.
- [ ] Run the focused test against SQLite and any configured service profiles; fix only defects demonstrated by the evidence test, adding regression coverage for each production fix.
- [ ] Commit as `test: prove in-place target capability boundary` (or a narrowly scoped `fix:` commit if production code is required).

## Task 3: Add Dolt repository-state assertions

**Files:**
- Modify: `tests/Integration/InPlaceTransformationServiceTest.php`
- Reference: `tests/Transformation/Execution/DoltGuardTest.php`
- Reference: `tests/Transformation/Execution/DoltHeadGuardTest.php`

- [ ] Record Dolt branch, HEAD, commit/history identity, and clean working-set status before the successful existing-target apply.
- [ ] Assert branch and HEAD remain unchanged, the expected inspectable working-set diff is present, and no commit or reset occurs.
- [ ] Record the same state before create-target rejection and assert branch, HEAD, history, status, rows, catalog, schema, and table names are unchanged afterward.
- [ ] Run the Dolt-focused test when `OPENSTATSPEC_DOLT_*` is configured and keep it skipped, not falsely green, when absent.
- [ ] Commit as `test: assert Dolt in-place repository evidence`.

## Task 4: Wire the evidence gate into CI

**Files:**
- Modify: `.github/workflows/ci.yml`

- [ ] Add `InPlaceTransformationServiceTest` to the focused PHPUnit filter for PostgreSQL, MySQL, MariaDB, and Dolt jobs without removing existing filters.
- [ ] Verify the normal PHP 8.4/8.5 job still runs the class through the complete Composer test suite with SQLite.
- [ ] Run YAML/configuration validation and inspect the diff; commit as `ci: run PHP in-place evidence across services`.

## Task 5: Document and verify

**Files:**
- Modify: `docs/transformations.md`
- Modify: `docs/release-readiness.md`
- Modify: `CHANGELOG.md`

- [ ] Document the service-matrix command, profile skip/CI execution rule, existing-target identity guarantee, and unsupported target-creation boundary.
- [ ] Keep wording explicit that this is adapter evidence and does not establish an official Transformation Plan 1.0 profile.
- [ ] Run focused PHPUnit, full `composer test`, `composer validate`, `composer lint`, `composer analyse`, and `git diff --check`.
- [ ] Review the complete diff for fixture isolation, no destructive cleanup, and coverage of every approved design requirement; commit as `docs: document PHP in-place evidence gate`.

## Final verification and handoff

- [ ] Confirm the worktree is clean and list implementation commits.
- [ ] Report which local profiles ran versus skipped due to missing configuration.
- [ ] If checks pass, request the local code-review loop before publishing a PR.
27 changes: 27 additions & 0 deletions docs/transformations.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,33 @@ as supported for every implemented SQL profile and states these target-creation
boundaries. Dolt additionally reports its clean-working-set and stable
branch/HEAD guard.

## Service-matrix evidence gate

Run the PHP adapter's in-place evidence matrix with the pinned specification
checkout:

```bash
OPENSTATSPEC_SPECIFICATION_DIR=/path/to/openstatspec-specification \
vendor/bin/phpunit tests/Integration/InPlaceTransformationServiceTest.php
```

SQLite runs locally. PostgreSQL, MySQL, MariaDB, and Dolt run only when their
respective `OPENSTATSPEC_PG_*`, `OPENSTATSPEC_MYSQL_*`,
`OPENSTATSPEC_MARIADB_*`, or `OPENSTATSPEC_DOLT_*` configuration is supplied;
an absent local profile is reported as skipped. CI supplies every service
profile configuration, so a skipped configured service is not acceptable CI
evidence.

For every configured profile, the existing-target evidence proves that
recode plus label changes preserve the dataset UUID, physical table identity,
and existing variable identities, with no copied, staging, snapshot, rollback,
or parallel-history table. Numeric implicit target creation is evidenced only
on SQLite and PostgreSQL. MySQL, MariaDB, and Dolt reject it before mutation;
their target variable must be created and catalogued by deployment workflow
before the recode. This is PHP adapter evidence only: it retains the legacy
`openstatspec-transformation-plan-v1` contract and does not establish an
official OpenStatSpec Transformation Plan 1.0 profile.

## Minimal PHP flow

```php
Expand Down
Loading