v0.9.0
The 1.0 candidate. A minor rather than a patch, and the last one before the
contract freezes: every decision of the 1.0-readiness review lands here, so
that the tag after this one can be 1.0.0 without a change to the surface.
Two of them are breaking on 0.x and Composer's caret already treats them so.
forget()answersForgottenDoublefor a double that is gone. Called a
second time on the same double, or on one areset()already dropped, it
said «Understudy::forget() expects an understudy created by Understudy::for().
This object is not one» — anInvalidCallSpecificationabout an object that
was one. It now goes through the same door as every other facade, so the
answer isForgottenDouble(retired, or gone with a reset), a stranger is
still refused by name, and a foreign context is still
ContextOwnershipViolation.- One rule for the two specification exceptions, and two factories move.
InvalidCallSpecificationis about the SHAPE of a specification — what is
called, where, how many times — andInvalidSpecificationArgumentabout a
VALUE inside it that no run could act on. An invertedArg::int/float/count()
range and anArg::string()pattern PCRE cannot compile are values, so
invertedBounds()andinvalidPattern()move toInvalidSpecificationArgument
besideArg::instanceOf()'s unloadable type,times(5, 2)andreturns().
Acatch (InvalidCallSpecification)around those two paths has to become
catch (InvalidSpecificationArgument)— orcatch (UnderstudyError), which
both implement. Both classes say the rule in their docblocks. OutcomeandCardinalityare@internal. No public path accepted or
returned either: dispatch records outcomes throughInvocation's scalar
recorders andInvocation::$outcomestayednullfor every call the engine
made, whiletimes()andverify()take integers and aVerificationFailure
carries bounds as integers. Both were@apiby inheritance from the first
design.Invocation::recordOutcome()andInvocation::__construct()are
@internaltoo — the dispatcher's bookkeeping, not a way to build a call by
hand.WhenBuilderis closed by contract. Its docblock now says that
subclassing is not supported and that theprotectedexpectation it carries
is an@internaltype; the keyword stays off only becauseExpectBuilderis
the subclass, and Psalm refuses a@finaltag for the same reason.- How
FailureKindgrows is written down. The readonly fields of
VerificationFailureand every existing case are stable; a NEW case may
arrive in a minor, so amatchover the enum needs adefaultarm. The
docblock, both READMEs,llms.txt, the skill file and the site say the same
thing — the 0.2.0 entry implied the opposite. - Docblocks that the API reference renders:
checkpoint()said «the current
context» and spans every context the test used;verify()as a free
function did not document$never;Arg::bool(),WhenBuilder::throws(),
Invocation::didReturn()/didThrow()/returned()/thrown()and seven exception
factories rendered as bare signatures. - The analyser parity matrix gains five idioms (
bin/consumer-smoke):
cardinality written past the first link, named bounds in either order, a
double reached through a helper, a first-class callable, andreturns()on a
void method past the first link. The 0.8.0 wave fixed the first four in both
plugins without a row for any of them; the fifth is the same blindness found
a week later inunderstudy-phpstan0.5.1. - The skill file caught up with the engine.
resources/skills/…/SKILL.md
— the one document that ships in the archive — said a nullable return answers
nullbefore the registry is consulted (the opposite has been true since
0.1.0), counted three free functions, listed noallOf/anyOf/rest/
captorand mentioned neitherexpectSequence()norlean(). - Documentation catch-ups: seven 0.8.0 corrections reached the READMEs and
never the site (property defaults on class doubles, built-in interfaces as
return types, whatcheckpoint()clears, verbatim arguments and
#[\SensitiveParameter],instanceOf()and PCRE$on the matchers page);
the Psalm page did not say that a leaked matcher is reported only at
errorLevel="1"; the adapter pages missed the 0.3.0/0.2.0 changes; the
Mockery table mappedshouldNotHaveReceived()tounused(), which asserts
no call at all; the README still told readers to expect a «too few
arguments» report onArg::rest()that both analyser packages have handled
since 0.2.0. - Rector is green again — red since v0.7.0, under four releases with green
builds.infection/infection^0.35,rasuvaeff/property-testing-testo
^0.9(it was three minors behind),.vale.iniisexport-ignore. The
mutation gate stays at 92 with the reason beside the number: the run
measures 94.1%, three mutants above 94, which is less than the CI count
moves between runs.