fix(templates): strict prompt rendering + steps.X.output registry - #49
Open
addadi wants to merge 1 commit into
Open
fix(templates): strict prompt rendering + steps.X.output registry#49addadi wants to merge 1 commit into
addadi wants to merge 1 commit into
Conversation
resolveNewExpression silently returned an empty string for any unknown
expression or missing key, and had no steps. prefix handler — the path
used by executeTaskNode prompt rendering. So {{steps.X.output}}
rendered as an empty prompt which the worker then answered from
nothing (or hallucinated from residual session context). No error, no
failed step: the orchestration layer cannot see the failure.
Changes:
- Add renderPromptTemplateStrict which propagates UnresolvedReference,
UnknownExpression, and StepNotFound instead of swallowing them.
executeTaskNode now uses the strict variant — a missing variable
fails the node visibly.
- Parametrize resolveNewExpression with a strict flag; the lenient
path is preserved for {% if %} conditional evaluation where
empty-as-falsy is legitimate.
- Add a {{steps.X.Y}} prefix handler resolving against a
state.steps.X.Y registry. The registry is populated from each step's
raw output (buildStepRegistryUpdate) and deep-merged via
state.applyDeepUpdates so multi-step chains coexist without
last_value clobbering. {{steps.X.output}} works with no per-step
output_key configured.
- workflow_validation.checkStateRefs skips the state-schema check for
{{steps.*}} refs since the registry is runtime-populated.
Integration test: 2-step sequential run, step a emits SENTINEL_XYZ,
step b renders "Echo: {{steps.a.output}}" verbatim; a and b coexist in
the registry after deep-merge.
Fixes nullclaw#40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #40
resolveNewExpressionsilently returned an empty string for any unknown expression or missing key, and had nosteps.prefix handler — the path used byexecuteTaskNodeprompt rendering. So{{steps.X.output}}rendered as an empty prompt which the worker then answered from nothing (or hallucinated from residual session context). No error, no failed step: the failure is invisible at the orchestration layer.Changes:
renderPromptTemplateStrictwhich propagatesUnresolvedReference,UnknownExpression, andStepNotFoundinstead of swallowing them.executeTaskNodenow uses the strict variant — a missing variable fails the node visibly.resolveNewExpressionwith a strict flag; the lenient path is preserved for{% if %}conditional evaluation where empty-as-falsy is legitimate.{{steps.X.Y}}prefix handler resolving against astate.steps.X.Yregistry. The registry is populated from each step's raw output (buildStepRegistryUpdate) and deep-merged viastate.applyDeepUpdatesso multi-step chains coexist withoutlast_valueclobbering.{{steps.X.output}}works with no per-stepoutput_keyconfigured.workflow_validation.checkStateRefsskips the state-schema check for{{steps.*}}refs since the registry is runtime-populated.Integration test: 2-step sequential — step a emits
SENTINEL_XYZ, step b renders"Echo: {{steps.a.output}}"verbatim; a and b coexist in the registry after deep-merge. Full suite green (zig build test, 366/366).