The Calculation editor asked users to pick a “target data point” and stored
formula variables inside the sources list — the same list the universal-source-wiring
refactor (Phases 2/3) redefined as “what invokes this node”. After the Phase 3 rollout
the Calculation editor was broken: formula variable selection no longer worked, and
the UX incorrectly conflated invocation wiring with formula-variable wiring. Tracked
as the D7 “fix before release” follow-up of openspec/changes/universal-source-wiring-ux.
CalculationEngineNodeMetaData had no dedicated field for formula-variable node
references. The editor re-used sources for that purpose, and FormulaResolver read
from sources at eval time. When sources was repurposed to mean invocation wiring,
the formula-variable semantics silently broke. Additionally, writing the computed result
into a separate “target” DataPoint created an unnecessary coupling and a confusing UX.
inputs: List<NodeIdentity> (formula variables, read at eval time) and
derived: Snapshot? (computed output snapshot) to CalculationEngineNodeMetaData
in krill-sdk (repo: krill-oss). The SDK change is consumed via a guarded, opt-in
(KRILL_SDK_LOCAL=true) Gradle composite build.FormulaResolver now resolves formula variables from inputs instead of sources.ServerCalculationProcessor computes the formula, persists the result in derived,
then calls executeSources to wake downstream nodes — the “target” concept is gone.ServerDataPointProcessor.onSourceTrigger (net-new) pulls a Calc source’s derived
snapshot when the Calc node is listed as a source.EditCalc) lost the target-picker row and gained a chip rail
inputs.Keep formula-variable wiring (inputs) and invocation wiring (sources) structurally
separate — never overload one list for both. New TargetingNodeMetaData value-producing
nodes that downstream nodes pull from should expose a derived-style snapshot field,
not write into a named target node. The CalculationMetaDataSerializationTest,
FormulaResolverInputsTest, ServerCalculationProcessorTest, and DataPointPullsCalcTest
suites guard these invariants; any new eval-output node type should follow the same
inputs/derived pattern and add equivalent tests.