chore: freeze the public API surface + 1.0 output contract (#88 / #89, #90) #476

Merged
manlycucumber merged 1 commit from feature/88-api-freeze into develop 2026-07-10 22:46:40 +00:00
manlycucumber commented 2026-07-10 22:44:57 +00:00 (Migrated from github.com)

What

Epic #88 — contract & API freeze: lock the public API and the 1.0 output contract so an accidental breaking change can't merge unnoticed. Additive — the only production-code change is two @internal docblocks; the golden suite is byte-identical.

#89 — public API surface freeze

  • tests/Api/PublicApiSurface.php enumerates the public surface (3 functions + 23 classes) and renders a canonical reflection snapshot of every public constant + method signature.
  • tests/Api/public-api-surface.txt (242 lines) is the committed snapshot; PublicApiSnapshotTest fails on any change; bin/freeze-api-surface.php regenerates it.
  • DayResolver and ResolvedYear marked @internal.

Cross-version correctness (caught by adversarial review): ReflectionNamedType::getName() returns the literal self on PHP ≤8.3 but resolves it to the class FQCN on 8.4+. The fixture was frozen on 8.5 (FQCN), which would have failed on all four CI legs (7.4/8.1/8.2/8.3) — 42 lines. renderType() now normalises self/static to the declaring-class FQCN so the snapshot is byte-identical across the matrix. (The CI matrix run on this PR is the definitive cross-version proof.)

#90 — 1.0 contract shape freeze

ContractShapeTest pins the structural shape: the top-level key order, the office key set, the calendar/particular/astronomical blocks, the resolution slot, and SHAPE_VERSION 1.0.2. The golden-year digest remains the exhaustive value guard.

Docs

docs/api-stability.md — the public allowlist, the semver + deprecation policy, the 0.x→1.0 migration note, and how the snapshot treats internal types named in frozen signatures (a re-freeze, not a break). output-contract.md links the guards.

Verification

  • lint · analyse · test 1036 tests (+6). Golden suite byte-identical.
  • Adversarial review: found + fixed the critical cross-version self rendering bug; the MEDIUM finding (internal types named in frozen signatures) is reconciled by explicit policy in api-stability.md; both advisories addressed.

Closes #89, closes #90.

Note: this freezes the code on develop. The actual v1.0.0 release/tag is the maintainer's step via release-please.

## What Epic **#88 — contract & API freeze**: lock the public API and the 1.0 output contract so an accidental breaking change can't merge unnoticed. Additive — the only production-code change is two `@internal` docblocks; the golden suite is byte-identical. ## #89 — public API surface freeze - `tests/Api/PublicApiSurface.php` enumerates the public surface (**3 functions + 23 classes**) and renders a canonical reflection snapshot of every public constant + method signature. - `tests/Api/public-api-surface.txt` (242 lines) is the committed snapshot; `PublicApiSnapshotTest` fails on any change; `bin/freeze-api-surface.php` regenerates it. - `DayResolver` and `ResolvedYear` marked `@internal`. **Cross-version correctness (caught by adversarial review):** `ReflectionNamedType::getName()` returns the literal `self` on PHP ≤8.3 but resolves it to the class FQCN on 8.4+. The fixture was frozen on 8.5 (FQCN), which would have **failed on all four CI legs (7.4/8.1/8.2/8.3)** — 42 lines. `renderType()` now normalises `self`/`static` to the declaring-class FQCN so the snapshot is byte-identical across the matrix. (The CI matrix run on this PR is the definitive cross-version proof.) ## #90 — 1.0 contract shape freeze `ContractShapeTest` pins the structural shape: the top-level key **order**, the office key set, the `calendar`/`particular`/`astronomical` blocks, the `resolution` slot, and `SHAPE_VERSION` `1.0.2`. The golden-year digest remains the exhaustive value guard. ## Docs `docs/api-stability.md` — the public allowlist, the semver + deprecation policy, the 0.x→1.0 migration note, and how the snapshot treats internal types named in frozen signatures (a re-freeze, not a break). `output-contract.md` links the guards. ## Verification - `lint` ✅ · `analyse` ✅ · `test` ✅ **1036 tests** (+6). Golden suite byte-identical. - Adversarial review: found + **fixed** the critical cross-version `self` rendering bug; the MEDIUM finding (internal types named in frozen signatures) is reconciled by explicit policy in `api-stability.md`; both advisories addressed. Closes #89, closes #90. > Note: this freezes the code on `develop`. The actual **v1.0.0 release/tag** is the maintainer's step via release-please.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Directorium/Core!476
No description provided.