You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A promise passed to function.call's variadic args arrives unresolved #663
Found by the first end-to-end test of function.Provider (USER-requested, 2026-08-24).
A promise passed to function.call through its variadic arguments arrives at the callable unresolved, as an Invocation object.
Reproduction
defsummarize(paths):
return",".join(sorted(paths))
walked=plan.file.walk_tree(root=root, fn=collector, include_gitignored=True)
summary=plan.function.call(summarize, walked) # walked is a promise
function.call: sorted: for parameter iterable: got Invocation, want iterable
The graph assembles, the edge is recorded, and the unit dispatches in the right order — the promise simply is not resolved before the callable receives it.
Why it happens
function.call's binding is (callable, *args, **kwargs). Promise resolution operates on declared parameters: a slot has a name and a type, and the executor fills it from the producer's result. A variadic catch-all has neither, so the Invocation passes through verbatim.
Contrast plan.file.write_text(content=walked), where content is a declared slot and the same promise resolves correctly. That asymmetry is the bug: whether a promise resolves depends on the shape of the receiving parameter rather than on the value being a promise.
Why it matters
function.call is the one action whose entire purpose is to invoke author code on a value. Chaining it after another unit is the natural use, and it is exactly the use that does not work. A caller must instead route the value through a provider with a declared slot, which defeats the point.
The likely fix
Resolve any Invocation appearing in a variadic or kwargs position, not only in declared slots. An Invocation in an argument position is a promise by definition — there is no legitimate reason to hand one to a callable as data.
Worth checking whether other variadic surfaces share the gap (shell.run, plan.choose) before fixing it in one place only.
Current coverage
cmd/devlore-test/devloretest/data/test_function_call_walk_tree.star covers function.call with literal arguments and with its result flowing onward through a promise, plus the function resource dispatched as walk_tree's reducer. It deliberately does not cover the promise-into-function.call case, because that would enshrine the defect; extend it here when this is fixed.
Activity