Overall preflight startability: every supplied initial-field row is
valid and every declared start requirement is satisfied. outcome describes only the
predicates; structurally invalid rows can therefore produce
allowed: false with outcome: 'satisfied'.
Supplied rows startInstance would reject before writing. Empty means
every row targets a workflow-scope, input-sourced declaration exactly
once. Render these as corrections, not an authorization verdict.
Required input entries initialFields doesn't fill yet — the rows a
startInstance now would throw RequiredFieldNotProvidedError about.
Three-valued, BINDABILITY-AWARE verdict over the start predicates:
'unsatisfied' is a definitive no for these inputs (disable and
explain), 'unevaluable' means the verdict can't be decided yet —
either a null operand reached an ordered comparison, or a predicate
reads an entry initialFields doesn't supply
(StartEvaluation.unboundReads non-empty). One exception outranks
the provisional rule: any definitive requirement refusal keeps the
aggregate 'unsatisfied' even while other reads are unbound. Keep the
affordance enabled on 'unevaluable'; startInstance still enforces
the final verdict, where absence is final rather than provisional.
One result per declared readiness node, in author order.
The $fields entries the predicates read that initialFields doesn't
supply — "fill these to decide", including a singleSubject node's
implicit subject read. Non-empty makes undecided requirements
'unevaluable'; a separate definitive refusal still keeps the aggregate
outcome 'unsatisfied'. Empty when the definition declares no requirements.
What
evaluateStartprojects — the same gatesstartInstanceenforces, as renderable state.allowedandmissingRequiredare deliberately orthogonal: a missing required input is a caller mistake (the verb throwsRequiredFieldNotProvidedErrorfor it), never a readiness verdict.