Skip to content

Report unresolvable template references from analyze_workflow, and close two activity-reference gaps - #220

Merged
Sev7eNup merged 1 commit into
mainfrom
fix/analyzer-and-activity-reference-gaps
Aug 16, 2026
Merged

Report unresolvable template references from analyze_workflow, and close two activity-reference gaps#220
Sev7eNup merged 1 commit into
mainfrom
fix/analyzer-and-activity-reference-gaps

Conversation

@Sev7eNup

Copy link
Copy Markdown
Owner

Small batch of the remaining findings from the lab test run.

1. analyze_workflow was silent about unresolvable references

The check existed — but only behind its own tool, find_unresolved_references. analyze_workflow is what an agent reaches for and what the in-canvas assistant is built around, so the whole class was invisible to a caller asking the obvious question.

Measured against a 1.2.6 install, this definition:

{"nodes":[{"id":"trig",...,"manualTrigger"},
          {"id":"n1",...,"log","config":{"message":"hallo {{gibtsnicht.output}}"}},
          {"id":"waise",...,"log"}],
 "edges":[{"source":"trig","target":"n1"}]}

returned {"ok":true,...,"findings":[{"code":"unreachable-node","nodeId":"waise"}]} — the orphan was caught, the reference that fails the run on first execution was not.

Findings now come from Analyze itself, at the severity the engine applies:

node type engine behaviour severity
most activities step aborts (T-7.1) error
runScript, custom:* literal passes through, run survives warning

References on disabled nodes are skipped — that node never runs. find_unresolved_references stays as-is for callers who want just that list.

2. Two activity-config-reference.json entries described a shape the executor rejects

key documented actually required
wmiQuery.captureProperties "CIM property names" a JSON array; a comma-separated string is rejected
startProgram.filePath "Executable path." an absolute local path; cmd.exe is rejected, PATH is not searched

Both failed on first use in the lab. That file feeds the AI prompt catalog and the MCP config tools, so an imprecise description there becomes a generated workflow that looks right and fails.

3. CLAUDE.md documented the debug resume body without stepId

ResumeDebugRequest requires it; posting the documented {"mode":"continue","overrides":{}} returns 400 The StepId field is required.

Tests

WorkflowAnalyzerFrontendParityTests — three cases: an unresolvable reference is an error and flips ok to false; the same reference on a runScript is a warning and leaves ok true; a reference on a disabled node is not reported.

Ran: dotnet test tests/NodePilot.Mcp.Tests (181 passed), plus the guard tests for the touched surfaces — ActivityConfigReferenceTests (5) and PromptCatalogDriftTest (5).

…ose two activity-reference gaps

analyze_workflow never ran the unresolved-reference check. It existed, but only
behind its own tool (find_unresolved_references), so the tool an agent actually
reaches for -- and the one the in-canvas assistant is built around -- answered
ok:true / findings:[] for a workflow that fails on its first run. Measured
against a 1.2.6 install: a log message reading {{gibtsnicht.output}} analysed
clean, while the orphan node in the same definition was reported correctly.

The findings now come back from Analyze itself, at the severity the engine
actually applies: an error where an unresolved placeholder aborts the step, a
warning on runScript and custom activities, which resolve their own templates and
tolerate a leftover {{...}} because it can be legitimate script text. References
on disabled nodes are skipped -- that node never runs.

Two entries in activity-config-reference.json described a shape the executor
rejects. wmiQuery's captureProperties is a JSON array and refuses a
comma-separated string; startProgram's filePath must be an absolute local path
and refuses a bare "cmd.exe". Both failed on first use in the lab. That file
feeds the AI prompt catalog and the MCP config tools, so an imprecise description
there becomes a generated workflow that looks right and fails.

CLAUDE.md documented the debug resume body without stepId, which
ResumeDebugRequest requires -- posting the documented body returns 400.
Comment on lines +135 to +150
foreach (var unresolved in VariableResolver.FindUnresolved(definition))
{
if (doc.DisabledNodeIds.Contains(unresolved.NodeId)) continue;

var nodeType = typeByNodeId.GetValueOrDefault(unresolved.NodeId, string.Empty);
var tolerated = nodeType.Equals("runScript", StringComparison.OrdinalIgnoreCase)
|| nodeType.StartsWith("custom:", StringComparison.OrdinalIgnoreCase);

var severity = tolerated ? "warning" : "error";
var consequence = tolerated
? "the step keeps running and the literal reaches the script"
: "the step fails with an unresolved-template error";

findings.Add(new Finding(severity, unresolved.Code, unresolved.NodeId,
$"{unresolved.Reference}: {unresolved.Reason} At run time {consequence}."));
}
@Sev7eNup
Sev7eNup merged commit ca7df2a into main Aug 16, 2026
9 checks passed
@Sev7eNup
Sev7eNup deleted the fix/analyzer-and-activity-reference-gaps branch August 16, 2026 16:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants