The thing a punit author implements gets a more honest name. UseCase carried too many readings — UML, regulatory, generic product talk — and told an author nothing about what the artefact does in the probabilistic-testing context. ServiceContract names it for what it is.
org.javai:punit:0.7.0-alpha6 is on Maven Central. The release renames the authoring-surface interface from UseCase<FT, IT, OT> to ServiceContract<FT, IT, OT>, with companion types following: ServiceContractOutcome, ServiceContractAttributes. The abstract / concrete split with Contract<I, O> is preserved by inheritance — ServiceContract extends Contract exactly as UseCase did.
Why rename
“Use case” carried too many readings. UML / Jacobson has one; regulatory-compliance prose has another; product-discussion shorthand has a third. None of them is the probabilistic-testing sense, and an author meeting UseCase<F, I, O> for the first time has no honest cue about what the type does in this context.
“Service contract” names the thing it is: the specification of correct behaviour the framework measures against. The author writes the service contract once — invoke method, postconditions, factor record, covariates, pacing — and punit drives statistical evaluation against it.
What changes for consumers
The migration is mechanical. The CHANGELOG entry on the punit release carries the full find-and-replace recipe. Summary:
- Type names:
UseCase→ServiceContract,UseCaseOutcome→ServiceContractOutcome,UseCaseAttributes→ServiceContractAttributes - Builder / parameter / field identifiers:
useCase→serviceContract,useCaseFactory→serviceContractFactory
The post-rename authoring surface reads like:
public class ProductSearch
implements ServiceContract<ShoppingFactors, String, SearchResult> {
private final LlmClient client;
public ProductSearch(String model, double temperature) {
this.client = LlmClient.builder()
.model(model)
.temperature(temperature)
.build();
}
@Override
public ServiceContractOutcome<SearchResult> apply(String query) {
SearchResult result = client.search(query);
return ServiceContractOutcome.of(result);
}
}
Wire format unchanged
The RP07 verdict XML attribute use-case-id and the YAML baseline / spec field useCaseId stay put. Existing baselines load against 0.7.0-alpha6 without regeneration; existing verdict XML validates against the unchanged schema. Downstream readers (HTML report, third-party verdict-XML consumers) keep working. The Java↔wire asymmetry is deliberate — wire-format regeneration is reserved for a separate, later release with its own migration tooling.
Worked examples
punitexamples renames in lockstep — ShoppingBasketServiceContract, PaymentGatewayServiceContract — and ships as org.javai:punit-examples:0.5.0-alpha6 on Maven Central. The example sources are the easiest way to see how the new name reads in author-facing code.
Why still -alpha
The -alpha qualifier is held, not dropped. The rename completes one strand of the breaking-change train but other strands (optimize-experiment API DX, verdict-catalogue rebuild) are still in flight. The qualifier drops when the train completes — trust in a stability signal is built slowly and lost in one move, and spending the qualifier to absorb anticipated breaks is the cheaper path.
If your project depends on 0.7.0-alpha6’s surface, pin to the exact version.
