Relationships
↔ sibling #3178#3179 Lazy hydration: expressions reading another model's data get empty attributes; hydrate a step's read set before evaluation
Opened by zack · 10/8/2026· Shipped 10/8/2026
Summary
Under hydrationStrategy: lazy, a workflow expression that reads another model's data gets empty attributes when that model's content is not in the local cache. design/enablers/datastores.md records this as the getContentSync limitation. It blocks swamp-club#2435: making swamp serve hydrate lazily would expose every serve-run workflow to it.
Where
model.<name>.resource.<spec>.<name>.attributesis loaded by a synchronous getter during CEL evaluation:findAllForModelSync→populateFromItems→dataToRecord→getContentSyncinsrc/domain/expressions/model_resolver.ts. A synchronous read cannot download, soattributesis{}.data.latest()builds its record with the samedataToRecordbeforematerializePath()downloads the file, and the attributes are not re-read afterwards.- The only pull before a step runs covers the step's own model:
createStepLockHookinsrc/serve/deps.ts, andacquireModelLocksfor the CLI.
Example
A step evaluates an expression reading model.vpc.resource.state.main.attributes.vpcId. The vpc data was written by another host, so only its metadata is local. The expression fails with a missing key, or silently takes a default branch.
Proposed change
Ensure a step's read set is local before its expressions are evaluated: widen the scoped pull from the step's own model to that model plus the models its expressions reference. analyzeExpression already computes those targets for authorization. Synchronous readers then stay synchronous and correct.
Open points:
- Expressions
analyzeExpressionreports as wide (for exampledata.query()over everything) need a defined fallback: pull in full, or keep the documented null-content behaviour. - Whether
analyzeExpressioncovers every reference form has not been checked. data.latest()can also re-read attributes after materialising the path, as a smaller independent fix.
Shipped
Click a lifecycle step above to view its details.