PtcRunner.Kernel.CandidatePromotion (PtcRunner v0.14.0)

Copy Markdown View Source

Decides whether a verified candidate is fit to be promoted by a human.

Promotion is an explicit human decision. This module does not make it; it makes it cheap to reach and well evidenced, by answering questions an operator would otherwise answer by reading diffs: does the candidate compile, is it usable by the next run's model, and does it reach further than the component it replaces.

Every criterion is either intrinsic to the candidate or relative to its base. Nothing here checks capability grants, and the report says so. Real %Capability{} values — and therefore capability names — exist only after provider acquisition, and no static substitute exists: ProviderDescriptor.provides lists inter-provider service atoms disjoint from requires, not capability names, and a dynamic provider discovers its tool names at acquisition. Comparing the two would compare an atom against an unrelated string. A candidate naming a capability no provider grants therefore passes this gate and fails at run-time environment assembly, which remains authoritative. The gate narrows the distance to that failure; it does not remove it.

Criteria report :pass, :fail, or :blocked. :blocked is not a softened failure — it means the criterion could not run at all, because a candidate that does not compile has no export table for G2 and G3 to inspect, and reporting that as a failure would misattribute the cause.

Summary

Functions

Evaluates one candidate against the base it replaces.

Types

criterion()

@type criterion() :: %{
  id: binary(),
  status: status(),
  summary: binary(),
  detail: map()
}

report()

@type report() :: %{
  outcome: status(),
  environment: binary() | nil,
  criteria: [criterion()]
}

status()

@type status() :: :pass | :fail | :blocked

Functions

evaluate(base, candidate, opts \\ [])

Evaluates one candidate against the base it replaces.

base is the package acquired without an override; candidate is the same application acquired with the verified descriptor applied. Both are required: the widening criterion is relative, so there is nothing to compare against without the installed base.

:accept_widened_effect records that an operator acknowledged a widening. It turns G3 from a failure into a pass whose detail still lists every widening, because acknowledging a risk is not the same as hiding it.