From 06699aeb375bf3948ffe646d798facdb2001213b Mon Sep 17 00:00:00 2001 From: Imani Manyara Date: Thu, 27 Aug 2026 06:31:44 -0400 Subject: [PATCH 1/4] Prepare the 2.0.0 release v1.0.1 sits ten commits behind main, so consumers on ^1.0 are not getting code that has landed -- and two of those commits are breaking and were never written down. Both arrived through org-wide sweeps rather than through a change to this package's own surface, which is how they escaped the changelog. The translation namespace became laranail/validation:: with no alias registered, so a key spelled the old way returns itself instead of a message. No exception, no warning -- the raw key renders where the validation error should be. That is the one worth reading the upgrade note for. The service provider moved into Providers/. Auto-discovery handles it; anything naming the class explicitly fatals at boot. rector-migrate-2.0.php rewrites it, and the config imports names so a consumer's diff is a one-line change to a use statement rather than a fully-qualified name left inline beside a stale import. Verified against a scratch Testbench case rather than assumed. Also corrects docs/release.md, which described the older flow: create the release, write the body, let CI write the changelog back. release.yml does the reverse -- it extracts the ## vX.Y.Z section OUT of CHANGELOG.md and exit 1s when it is missing. Following the page as written would have failed this release on its first step. --- CHANGELOG.md | 32 +++++++++++++++++++++- README.md | 7 ++--- UPGRADING.md | 60 ++++++++++++++++++++++++++++++++++++++++++ composer.json | 14 +++++----- docs/release.md | 29 +++++++++++++++----- rector-migrate-2.0.php | 35 ++++++++++++++++++++++++ 6 files changed, 159 insertions(+), 18 deletions(-) create mode 100644 rector-migrate-2.0.php diff --git a/CHANGELOG.md b/CHANGELOG.md index b671713..c0ff556 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,37 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Entries below `Unreleased` are written by CI from the GitHub release body — see [docs/release.md](docs/release.md). Do not hand-edit released sections. -## Unreleased +## v2.0.0 - 2026-08-27 + +Two breaking changes that landed on `main` during org-wide sweeps and were never written down. +Both are mechanical; the provider rename is codemod-able. ### Changed +- **Breaking. The translation namespace is now the composer package name**, `laranail/validation::`, + where it was `laranail-validation::`. + + There is no alias. `hasTranslations()` is called without an argument, so the old namespace is not + registered at all and every key spelled the old way returns *itself* instead of a message — no + exception, no warning, just the raw key rendered wherever a validation error would have been. An + application that never names these keys directly is unaffected; one that overrode a message, or + published the translations, is not. + + Published files follow the namespace, so an override now lives at + `lang/vendor/laranail/validation/`. That nesting is where Laravel reads it back from — + `FileLoader::loadNamespaceOverrides()` interpolates the namespace into + `{$path}/vendor/{$namespace}/{$locale}/{$group}.php`. + +- **Breaking. The service provider moved** to + `Simtabi\Laranail\Validation\Providers\ValidationServiceProvider`. + + Package auto-discovery handles this on its own. Anything that names the class explicitly — a + Testbench `getPackageProviders()`, a manual entry in `config/app.php`, a `testbench.yaml` — fatals + with "class not found" until it is updated. `rector-migrate-2.0.php` rewrites it. + + The move brings the package in line with the family convention that every provider sits in a + `Providers/` directory, which Laravel's own skeleton does with `app/Providers`. + - The final re-audit against the 1.0 plan closed four release-gate gaps: the README Stability section and installation guide now speak in shipped-1.0 terms (both still said "pre-1.0, pin `^0.1`" after the major); `CREDITS.md` records the Phase-2 datasets (ISO @@ -20,6 +47,9 @@ Entries below `Unreleased` are written by CI from the GitHub release body — se attaches a CycloneDX SBOM via `laranail::package-tools.sbom`, the §12.3 item the release had shipped without. +- Package paths resolve through `package-tools`' `packagePath()` rather than hand-counted + `__DIR__ . '/../..'` strings, which cannot drift when a file moves. + ## v1.0.1 - 2026-08-24 ### Added diff --git a/README.md b/README.md index 1c31b28..826760f 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ Full documentation is at ## Stability -1.0 states what SemVer covers. The **stable surface** is: `FluentRule`, +2.0 states what SemVer covers. The **stable surface** is: `FluentRule`, `FluentSchema`, `RuleSet` (including its events and `before()`/`after()` hooks), the rule classes and their constructor signatures, the contracts (`ClientCheckable`, `PrecognitionSkippable`, `TermList`, `FluentRuleContract`), `Check`, `Regex`, @@ -122,8 +122,9 @@ Everything marked `@internal` — the fast-check compiler, the optimizer validat machinery, everything under `Internal\` — may change in a minor, and an arch test enforces the boundary. Build on the stable list; the optimizer is an implementation detail behind it. -Constrain to `^1.0` and read [UPGRADING.md](UPGRADING.md) before moving between versions — -`rector-migrate-1.0.php` auto-migrates the mechanical 0.x break. Deprecations post-1.0 are +Constrain to `^2.0` and read [UPGRADING.md](UPGRADING.md) before moving between versions — +`rector-migrate-2.0.php` auto-migrates the mechanical 1.x break (the service provider moved into +`Providers/`), and `rector-migrate-1.0.php` still covers the 0.x one. Deprecations post-1.0 are marked `@deprecated` with the replacement and removal version, kept for at least one minor, and removed only in the next major. Behaviour-correcting fixes can still mean input an application previously accepted is now correctly rejected; UPGRADING calls those out. diff --git a/UPGRADING.md b/UPGRADING.md index b9b9300..ef85ff7 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -2,6 +2,66 @@ Breaking changes, and what to do about them. Versions not listed here need no action. +## v2.0.0 - 2026-08-27 + +The provider rename below can be applied automatically: + +```bash +vendor/bin/rector process --config vendor/laranail/validation/rector-migrate-2.0.php +``` + +The translation-key rename is a string change, which Rector has no clean rule for. It is a +find-and-replace, described below. + + +### The service provider moved into `Providers/` + +| Before | After | +|---|---| +| `Simtabi\Laranail\Validation\ValidationServiceProvider` | `Simtabi\Laranail\Validation\Providers\ValidationServiceProvider` | + +**Most applications need no change.** Laravel's package auto-discovery finds the provider through +`composer.json`, which moved with it. + +You need this change if you name the class yourself: + +- a Testbench `getPackageProviders()` in a test case, +- a manual entry in `config/app.php` or `bootstrap/providers.php`, +- a `testbench.yaml` `providers:` list — worth grepping for specifically, since it is neither + `.php` nor `.json` and a namespace sweep over source files misses it. + +Left unchanged, it fatals with "class not found" the moment the provider is registered — at boot, +for the whole application. + +### The translation namespace is now `laranail/validation::` + +| Before | After | +|---|---| +| `laranail-validation::validation.iban` | `laranail/validation::validation.iban` | +| `lang/vendor/laranail-validation/` | `lang/vendor/laranail/validation/` | + +**There is no alias.** The old namespace is not registered at all, so a key spelled the old way +returns *itself* — `laranail-validation::validation.iban` renders where the message should be. No +exception is raised, which is what makes this worth checking for rather than waiting to notice. + +Two places to look: + +```bash +grep -rn 'laranail-validation::' app/ resources/ config/ lang/ +ls lang/vendor/laranail-validation 2>/dev/null # a published override, now read from elsewhere +``` + +If you published the translations, move the directory: + +```bash +mkdir -p lang/vendor/laranail +git mv lang/vendor/laranail-validation lang/vendor/laranail/validation +``` + +That nesting is not incidental — Laravel interpolates the namespace into the override path itself +(`FileLoader::loadNamespaceOverrides()` reads +`{$path}/vendor/{$namespace}/{$locale}/{$group}.php`), so the slash is exactly where it looks. + ## v1.0.0 - 2026-08-24 The mechanical break below (`getEachRules()`) can be applied automatically: diff --git a/composer.json b/composer.json index 3e1a9e9..200119e 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ } ], "name": "laranail/validation", - "description": "Fluent validation rule builders for Laravel — type-aware rule objects, structured array validation, and an optimized wildcard validator.", + "description": "Fluent validation rule builders for Laravel \u2014 type-aware rule objects, structured array validation, and an optimized wildcard validator.", "keywords": [ "laravel", "laranail", @@ -100,11 +100,11 @@ "tomasvotruba/type-coverage": "^2.3.4" }, "suggest": { - "laranail/email": "^0.1 — maintained disposable-domain and role-account lists plus a production DNS resolver, bound over the Contracts\\Email\\* fallbacks this package ships. Nothing you call changes.", - "laranail/phone": "^0.1 — required by FluentRule::phone() and Rules\\Telecom\\Phone. Suggested rather than required because it carries libphonenumber's numbering-plan metadata, which a project validating only strings and dates should not have to install.", - "nikic/php-parser": "^5.0 — required by Simtabi\\Laranail\\Validation\\Testing\\Arch\\BansFieldRuleTypeMethods, an opt-in Pest/PHPUnit arch helper that bans type-specific method calls on the untyped FluentRule::field() builder.", - "laranail/password-history": "^0.1 — reuse prevention: password()->notReused() appears when installed.", - "laranail/password-tools": "^0.2 — zxcvbn strength scoring and secure generators: password()->strength(3) appears when installed." + "laranail/email": "^0.1 \u2014 maintained disposable-domain and role-account lists plus a production DNS resolver, bound over the Contracts\\Email\\* fallbacks this package ships. Nothing you call changes.", + "laranail/phone": "^0.1 \u2014 required by FluentRule::phone() and Rules\\Telecom\\Phone. Suggested rather than required because it carries libphonenumber's numbering-plan metadata, which a project validating only strings and dates should not have to install.", + "nikic/php-parser": "^5.0 \u2014 required by Simtabi\\Laranail\\Validation\\Testing\\Arch\\BansFieldRuleTypeMethods, an opt-in Pest/PHPUnit arch helper that bans type-specific method calls on the untyped FluentRule::field() builder.", + "laranail/password-history": "^0.1 \u2014 reuse prevention: password()->notReused() appears when installed.", + "laranail/password-tools": "^0.2 \u2014 zxcvbn strength scoring and secure generators: password()->strength(3) appears when installed." }, "autoload": { "psr-4": { @@ -148,7 +148,7 @@ ] }, "branch-alias": { - "dev-main": "1.0.x-dev" + "dev-main": "2.0.x-dev" } }, "config": { diff --git a/docs/release.md b/docs/release.md index 34c7c52..3293711 100644 --- a/docs/release.md +++ b/docs/release.md @@ -70,18 +70,33 @@ requests, and weekly, since a tag can also be moved on the remote without any pu tag-currency check (`verify-tag-currency.sh` filters on `^v`) all agree on. This page once said "bare version"; that sentence contradicted all three and the script never matched it. Releases are real SemVer points — the pre-1.0 moving-tag model is retired for this package. -2. Create the GitHub release against that tag, titled the same (`v0.1.1`). -3. Write a real description in the release body. Summarise what changed and why, in prose — an - empty body or a bare "see CHANGELOG" is not a release description. This body becomes the - changelog entry, so it is the version's permanent record. +**Write the changelog section first.** `release.yml` fires on the tag push and *extracts* the +`## vX.Y.Z` section out of `CHANGELOG.md` to use as the release body — and `exit 1`s if no such +section exists. So the order is: write the entry, commit it, then tag. + +1. Write the version's section in `CHANGELOG.md`, headed `## vX.Y.Z - `. Real prose about + what changed and why; this becomes the release body and is the version's permanent record. The + heading has to match `^## (\[)?(v)?X.Y.Z([] ]|$)`, which is what the extractor greps for. +2. Confirm it extracts before you tag anything: + ```bash + awk -v ver="X.Y.Z" '$0 ~ "^## (\\[)?(v)?"ver"([] ]|$)" { grab = 1; next } grab && /^## / { exit } grab { print }' CHANGELOG.md + ``` + Empty output means the release job will fail on its first step. +3. Tag and push. Everything else is CI's: it creates the release, injects the benchmark table + between the markers it appends itself, and attaches the SBOM. + +> This page used to say "create the GitHub release, then write a description in the body", with +> the changelog written back afterwards. That was the older flow. `update-changelog.yml` still +> exists for it, but it now only backfills a release authored by hand and skips when the section is +> already present — which, on the normal path, it is. ## What CI does afterwards Publishing the release (`release: released`) fires three workflows: -- **Update Changelog** prepends the release body to `CHANGELOG.md` and commits it back to the - release's target branch. This is why `CHANGELOG.md` is never hand-edited as part of a - release — a manual entry will be duplicated. +- **Update Changelog** backfills `CHANGELOG.md` from the release body, and *only* when the section + is missing — a release authored by hand in the GitHub UI. On the normal path the section is + already there, because it is what the body was built from, and this job does nothing. - **Release Benchmark** re-runs the benchmark suite against the tagged commit and injects the results table into the release body, between the `` and `` markers. Those markers must already be present in the body for the diff --git a/rector-migrate-2.0.php b/rector-migrate-2.0.php new file mode 100644 index 0000000..f0cf016 --- /dev/null +++ b/rector-migrate-2.0.php @@ -0,0 +1,35 @@ +withImportNames(importShortClasses: false, removeUnusedImports: true) + ->withConfiguredRule(RenameClassRector::class, [ + 'Simtabi\Laranail\Validation\ValidationServiceProvider' => 'Simtabi\Laranail\Validation\Providers\ValidationServiceProvider', + ]); From 21ca1280da100f53bdea31f89302e2c63fdd0bd7 Mon Sep 17 00:00:00 2001 From: Imani Manyara Date: Thu, 27 Aug 2026 08:54:59 -0400 Subject: [PATCH 2/4] Exclude rector 2.6.4, which drops the container method rector-laravel calls Rector 2.6.4 swapped its bundled container from Illuminate's to Entropy's, and the new one has no tag(). driftingly/rector-laravel registers its node visitors with $rectorConfig->tag(), so the config fatals at load time with "Call to undefined method Rector\Config\RectorConfig::tag()". There is no stable rector-laravel built against the new container -- 2.6.0 requires rector/rector dev-main -- so the range takes a ceiling until one ships. This is a known-broken-release exclusion, not a pin; the lower bound stays open. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 200119e..c21d8c9 100644 --- a/composer.json +++ b/composer.json @@ -91,7 +91,7 @@ "phpstan/phpstan-deprecation-rules": "^2.0.4", "phpstan/phpstan-phpunit": "^2.0.16", "phpstan/phpstan-strict-rules": "^2.0.10", - "rector/rector": "^2.4.1", + "rector/rector": "^2.4.1 <2.6.4", "sandermuller/boost-skills": "^2.5", "sandermuller/package-boost-laravel": "^1.0", "spaze/phpstan-disallowed-calls": "^4.10", From 163f2b4da7021ebbd2343d0d9cbcab66287e1bba Mon Sep 17 00:00:00 2001 From: Imani Manyara Date: Thu, 27 Aug 2026 09:22:51 -0400 Subject: [PATCH 3/4] Address the 2.0.0 release-prep review docs/release.md had two competing "1." lists -- one saying tag first, one saying changelog first. Merged into a single ordered list matching what release.yml actually does: write, verify extraction, commit, tag, push. UPGRADING.md showed the codemod with no target path, while the config itself documents `app/`. The config declares no paths, so as written the command did nothing. Added `app/` and a note on which other paths matter. CHANGELOG.md lost its `## Unreleased` heading when the section was renamed to v2.0.0, which left the file's own header note describing a section that no longer existed. Restored as a placeholder; verified the v2.0.0 body still extracts (41 lines). rector-migrate-2.0.php keeps `importShortClasses: false`. The flag gates only global-namespace classes -- ShortClassImportSkipVoter skips an import solely when the name has no separator -- so it cannot affect the provider rename. Documented why it diverges from rector.php rather than changing behaviour. --- CHANGELOG.md | 4 ++++ UPGRADING.md | 7 ++++++- docs/release.md | 19 ++++++++++--------- rector-migrate-2.0.php | 11 +++++++++++ 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0ff556..2dd4f86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Entries below `Unreleased` are written by CI from the GitHub release body — see [docs/release.md](docs/release.md). Do not hand-edit released sections. +## Unreleased + +_Nothing yet._ + ## v2.0.0 - 2026-08-27 Two breaking changes that landed on `main` during org-wide sweeps and were never written down. diff --git a/UPGRADING.md b/UPGRADING.md index ef85ff7..ebfd436 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -7,9 +7,14 @@ Breaking changes, and what to do about them. Versions not listed here need no ac The provider rename below can be applied automatically: ```bash -vendor/bin/rector process --config vendor/laranail/validation/rector-migrate-2.0.php +vendor/bin/rector process app/ --config vendor/laranail/validation/rector-migrate-2.0.php ``` +The config declares no paths of its own, so pass them: `app/` at minimum, and usually `tests/` too — +a Testbench `getPackageProviders()` is the single most common place the old class name survives. +`config/` and `bootstrap/` are worth a pass. `testbench.yaml` is not PHP, so Rector will not see it; +grep for the old name there by hand. + The translation-key rename is a string change, which Rector has no clean rule for. It is a find-and-replace, described below. diff --git a/docs/release.md b/docs/release.md index 3293711..528969e 100644 --- a/docs/release.md +++ b/docs/release.md @@ -65,14 +65,9 @@ requests, and weekly, since a tag can also be moved on the remote without any pu ## Cutting the release -1. Tag the release commit with the `v`-prefixed version — `v0.1.1`. Composer reads either - form, and the `v` prefix is what the repo's existing tags, the org convention, and the - tag-currency check (`verify-tag-currency.sh` filters on `^v`) all agree on. This page once - said "bare version"; that sentence contradicted all three and the script never matched it. - Releases are real SemVer points — the pre-1.0 moving-tag model is retired for this package. -**Write the changelog section first.** `release.yml` fires on the tag push and *extracts* the -`## vX.Y.Z` section out of `CHANGELOG.md` to use as the release body — and `exit 1`s if no such -section exists. So the order is: write the entry, commit it, then tag. +**The changelog comes first, and the tag is the trigger.** `release.yml` fires on the tag push and +*extracts* the `## vX.Y.Z` section out of `CHANGELOG.md` to use as the release body — and `exit 1`s if +no such section exists. So there is one order, and tagging is the last step in it. 1. Write the version's section in `CHANGELOG.md`, headed `## vX.Y.Z - `. Real prose about what changed and why; this becomes the release body and is the version's permanent record. The @@ -82,7 +77,13 @@ section exists. So the order is: write the entry, commit it, then tag. awk -v ver="X.Y.Z" '$0 ~ "^## (\\[)?(v)?"ver"([] ]|$)" { grab = 1; next } grab && /^## / { exit } grab { print }' CHANGELOG.md ``` Empty output means the release job will fail on its first step. -3. Tag and push. Everything else is CI's: it creates the release, injects the benchmark table +3. Commit the changelog entry to `main`. +4. Tag the release commit with the `v`-prefixed version — `v2.0.0`. Composer reads either form, and + the `v` prefix is what the repo's existing tags, the org convention, and the tag-currency check + (`verify-tag-currency.sh` filters on `^v`) all agree on. This page once said "bare version"; that + sentence contradicted all three and the script never matched it. Releases are real SemVer points — + the pre-1.0 moving-tag model is retired for this package. +5. Push the tag. Everything else is CI's: it creates the release, injects the benchmark table between the markers it appends itself, and attaches the SBOM. > This page used to say "create the GitHub release, then write a description in the body", with diff --git a/rector-migrate-2.0.php b/rector-migrate-2.0.php index f0cf016..5b61e36 100644 --- a/rector-migrate-2.0.php +++ b/rector-migrate-2.0.php @@ -29,6 +29,17 @@ return RectorConfig::configure() // Without this the rename lands as a fully-qualified name inline and leaves the old `use` // sitting above it -- correct, but not what anyone wants to read in their own diff. + // + // `importShortClasses: false` deliberately diverges from this repo's own rector.php, which takes + // the defaults. It gates exactly one thing: ShortClassImportSkipVoter skips importing a class + // only when `substr_count($className, '\\') === 0` -- a global-namespace class such as + // \DateTime. The provider being renamed here carries four separators, so it is untouched by the + // flag and is still imported as a `use`. + // + // The difference is whose code Rector is pointed at. rector.php runs over this repository, where + // importing global classes everywhere is wanted. This config runs over a *consumer's* + // application, where a one-class migration that also rewrites every \DateTime and \Exception in + // their tree buries the rename in an unrelated diff. ->withImportNames(importShortClasses: false, removeUnusedImports: true) ->withConfiguredRule(RenameClassRector::class, [ 'Simtabi\Laranail\Validation\ValidationServiceProvider' => 'Simtabi\Laranail\Validation\Providers\ValidationServiceProvider', From a0c42317a865c7e950fb7675ab468d0ab8687aba Mon Sep 17 00:00:00 2001 From: Imani Manyara Date: Thu, 27 Aug 2026 09:36:16 -0400 Subject: [PATCH 4/4] Release as v0.1.0, not v2.0.0 The org floors every package at v0.1.0 while pre-stable, so the 1.x and 2.0 tags on this repo are internal history rather than published releases. The two breaking changes this branch documents are real and still land -- they just land inside v0.1.0. - CHANGELOG: the release section is v0.1.0, and the withdrawn versions move under an "Internal history (not published)" heading. That heading is deliberately `##` so the release-body extractor still stops at the end of the v0.1.0 section; verified at 41 lines. - branch-alias: 2.0.x-dev -> 0.1.x-dev, so a dev checkout satisfies ^0.1. - README constrains to ^0.1. - rector-migrate-2.0.php -> rector-migrate-0.1.php, with the docblock reworded off the 1.x -> 2.0 framing. No content was dropped; the historical entries are kept for provenance. --- CHANGELOG.md | 14 ++++++++++++-- README.md | 4 ++-- UPGRADING.md | 4 ++-- composer.json | 2 +- docs/release.md | 2 +- rector-migrate-2.0.php => rector-migrate-0.1.php | 6 +++--- 6 files changed, 21 insertions(+), 11 deletions(-) rename rector-migrate-2.0.php => rector-migrate-0.1.php (90%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dd4f86..4cd9abe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,16 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Entries below `Unreleased` are written by CI from the GitHub release body — see [docs/release.md](docs/release.md). Do not hand-edit released sections. +> **One published release: `v0.1.0`.** The org floors every package at `v0.1.0` while pre-stable, so +> that tag is the only one consumers resolve and it moves as the package moves. Sections under +> *Internal history* below were cut as tags during development and later withdrawn; their content is +> part of `v0.1.0`. They are kept for provenance, not because those versions are installable. + ## Unreleased _Nothing yet._ -## v2.0.0 - 2026-08-27 +## v0.1.0 - 2026-08-27 Two breaking changes that landed on `main` during org-wide sweeps and were never written down. Both are mechanical; the provider rename is codemod-able. @@ -38,7 +43,7 @@ Both are mechanical; the provider rename is codemod-able. Package auto-discovery handles this on its own. Anything that names the class explicitly — a Testbench `getPackageProviders()`, a manual entry in `config/app.php`, a `testbench.yaml` — fatals - with "class not found" until it is updated. `rector-migrate-2.0.php` rewrites it. + with "class not found" until it is updated. `rector-migrate-0.1.php` rewrites it. The move brings the package in line with the family convention that every provider sits in a `Providers/` directory, which Laravel's own skeleton does with `app/Providers`. @@ -54,6 +59,11 @@ Both are mechanical; the provider rename is codemod-able. - Package paths resolve through `package-tools`' `packagePath()` rather than hand-counted `__DIR__ . '/../..'` strings, which cannot drift when a file moves. +## Internal history (not published) + +These were tagged during development and the tags have since been withdrawn. Nothing here is +separately installable — it all ships inside `v0.1.0` above. + ## v1.0.1 - 2026-08-24 ### Added diff --git a/README.md b/README.md index 826760f..c6e66fb 100644 --- a/README.md +++ b/README.md @@ -122,8 +122,8 @@ Everything marked `@internal` — the fast-check compiler, the optimizer validat machinery, everything under `Internal\` — may change in a minor, and an arch test enforces the boundary. Build on the stable list; the optimizer is an implementation detail behind it. -Constrain to `^2.0` and read [UPGRADING.md](UPGRADING.md) before moving between versions — -`rector-migrate-2.0.php` auto-migrates the mechanical 1.x break (the service provider moved into +Constrain to `^0.1` and read [UPGRADING.md](UPGRADING.md) before moving between versions — +`rector-migrate-0.1.php` auto-migrates the mechanical break (the service provider moved into `Providers/`), and `rector-migrate-1.0.php` still covers the 0.x one. Deprecations post-1.0 are marked `@deprecated` with the replacement and removal version, kept for at least one minor, and removed only in the next major. Behaviour-correcting fixes can still mean input an diff --git a/UPGRADING.md b/UPGRADING.md index ebfd436..5e9451a 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -2,12 +2,12 @@ Breaking changes, and what to do about them. Versions not listed here need no action. -## v2.0.0 - 2026-08-27 +## v0.1.0 - 2026-08-27 The provider rename below can be applied automatically: ```bash -vendor/bin/rector process app/ --config vendor/laranail/validation/rector-migrate-2.0.php +vendor/bin/rector process app/ --config vendor/laranail/validation/rector-migrate-0.1.php ``` The config declares no paths of its own, so pass them: `app/` at minimum, and usually `tests/` too — diff --git a/composer.json b/composer.json index c21d8c9..2678b38 100644 --- a/composer.json +++ b/composer.json @@ -148,7 +148,7 @@ ] }, "branch-alias": { - "dev-main": "2.0.x-dev" + "dev-main": "0.1.x-dev" } }, "config": { diff --git a/docs/release.md b/docs/release.md index 528969e..12ae803 100644 --- a/docs/release.md +++ b/docs/release.md @@ -78,7 +78,7 @@ no such section exists. So there is one order, and tagging is the last step in i ``` Empty output means the release job will fail on its first step. 3. Commit the changelog entry to `main`. -4. Tag the release commit with the `v`-prefixed version — `v2.0.0`. Composer reads either form, and +4. Tag the release commit with the `v`-prefixed version — `v0.1.0`. Composer reads either form, and the `v` prefix is what the repo's existing tags, the org convention, and the tag-currency check (`verify-tag-currency.sh` filters on `^v`) all agree on. This page once said "bare version"; that sentence contradicted all three and the script never matched it. Releases are real SemVer points — diff --git a/rector-migrate-2.0.php b/rector-migrate-0.1.php similarity index 90% rename from rector-migrate-2.0.php rename to rector-migrate-0.1.php index 5b61e36..1e5184f 100644 --- a/rector-migrate-2.0.php +++ b/rector-migrate-0.1.php @@ -6,17 +6,17 @@ use Rector\Renaming\Rector\Name\RenameClassRector; /** - * The 1.x → 2.0 migration set (UPGRADING.md, v2.0.0). Run it against an + * The v0.1.0 migration set (UPGRADING.md). Run it against an * application's own code: * * vendor/bin/rector process app/ \ - * --config vendor/laranail/validation/rector-migrate-2.0.php + * --config vendor/laranail/validation/rector-migrate-0.1.php * * It applies the mechanical break only — the service provider moved into a * `Providers/` sub-namespace, and anything naming the class explicitly needs * the new name. Auto-discovered registrations need nothing. * - * The other 2.0 break, the `laranail-validation::` → `laranail/validation::` + * The other break, the `laranail-validation::` → `laranail/validation::` * translation namespace, is a change to string literals. Rector has no clean * rule for that, and a rule that rewrote arbitrary strings would be worse than * the find-and-replace UPGRADING.md gives you.