Skip to content

Merge the two workflow analyzers into one in NodePilot.Core - #222

Merged
Sev7eNup merged 2 commits into
mainfrom
refactor/single-workflow-analyzer
Aug 16, 2026
Merged

Merge the two workflow analyzers into one in NodePilot.Core#222
Sev7eNup merged 2 commits into
mainfrom
refactor/single-workflow-analyzer

Conversation

@Sev7eNup

Copy link
Copy Markdown
Owner

Problem

analyze_workflow existed twiceWorkflowReviewAnalyzer (Core, behind the AI chat) and WorkflowAnalyzer (Mcp/Analysis, behind the MCP tool). Both mirrored the canvas linter independently, with no parity test between them, and they had already drifted:

  • cycle was an error on one side and a warning on the other, though the engine has no inDegree fallback and a cyclic graph Fails outright;
  • the chat copy flagged missing-target-machine on runScript/waitForCondition, which the Localhost bypass makes perfectly valid — it told authors to "fix" a correct workflow;
  • the chat copy did not know unresolvable {{...}} references at all, so a log message reading {{gibtsnicht.output}} analysed as ok with no findings and then failed on the first run.

Change

The MCP implementation was the superset and moves to NodePilot.Core.WorkflowDefinitions, keeping the structural pre-check and the empty-workflow case from the Core copy. Both surfaces now call it, so their findings can no longer disagree. Mcp/Analysis/VariableResolver moves along as WorkflowDataBusAnalyzer — the rename avoids a collision with the engine's runtime VariableResolver, which Core is visible to.

Two behaviour notes:

  • the analyzer no longer reports unknown-activity-type of its own, because the structural pre-check already rejects it and names the node index and the offending type;
  • ok now means "no error-severity finding" on both surfaces, with warnings still counted in count/findings.

WorkflowAnalyzerFrontendParityTests moves to Engine.Tests, where Core-level guards live, and becomes the single mirror guard against workflowLint.ts. A roadmap entry under E records the direction that was not taken — routing the chat through nodepilot-mcp — and why: one DPAPI session versus per-request ClaimsPrincipal, loopback HTTP per call, and ~90 write tools the chat deliberately lacks.

Second commit: a guard that the move broke

TemplateGrammarParityTests locates the databus analyzer by path and still read src/NodePilot.Mcp/Analysis/VariableResolver.cs. It threw FileNotFoundException instead of comparing anything. Fixed to the new path, with the file's existence now asserted explicitly so the failure names the path to update rather than surfacing as an IO stack trace.

Tests

Full solution builds. Ran:

project result
NodePilot.Engine.Tests 1873 passed (was 1838 — the parity + analyzer tests landed here)
NodePilot.Mcp.Tests 165 passed (was 181 — 16 moved to Engine.Tests)
NodePilot.Ai.Tests 497 passed

analyze_workflow existed twice: WorkflowReviewAnalyzer (Core, behind the AI
chat) and WorkflowAnalyzer (Mcp/Analysis, behind the MCP tool). Both mirrored
the canvas linter independently, with no parity test between them, and they had
already drifted:

- cycle was an error on one side and a warning on the other, though the engine
  has no inDegree fallback and a cyclic graph Fails outright;
- the chat copy flagged missing-target-machine on runScript/waitForCondition,
  which the Localhost bypass makes perfectly valid — it told authors to "fix" a
  correct workflow;
- the chat copy did not know unresolvable {{...}} references at all, so a log
  message reading {{gibtsnicht.output}} analysed as ok with no findings and then
  failed on the first run.

The MCP implementation was the superset and moves to
NodePilot.Core.WorkflowDefinitions, keeping the structural pre-check and the
empty-workflow case from the Core copy. Both surfaces now call it, so their
findings can no longer disagree. Mcp/Analysis/VariableResolver moves along as
WorkflowDataBusAnalyzer; the rename avoids a collision with the engine's
runtime VariableResolver, which Core is visible to.

Two behaviour notes: the analyzer no longer reports unknown-activity-type of its
own, because the structural pre-check already rejects it and names the node
index and the offending type; and ok now means "no error-severity finding" on
both surfaces, with warnings still counted in count/findings.

WorkflowAnalyzerFrontendParityTests moves to Engine.Tests, where Core-level
guards live, and becomes the single mirror guard against workflowLint.ts.

A roadmap entry under E records the direction that was NOT taken — routing the
chat through nodepilot-mcp — and why: one DPAPI session versus per-request
ClaimsPrincipal, loopback HTTP per call, and ~90 write tools the chat
deliberately lacks.
TemplateGrammarParityTests locates the databus analyzer by PATH and still read
src/NodePilot.Mcp/Analysis/VariableResolver.cs, which the consolidation moved to
NodePilot.Core/WorkflowDefinitions/WorkflowDataBusAnalyzer.cs. The test threw
FileNotFoundException instead of comparing anything -- loudly here, but the same
guard shape fails open if the read is ever made tolerant, so the missing file is
now asserted with a message naming the path to update.

Wording follows the move as well: the analyzer is no longer MCP-specific, it
backs the MCP tool and the AI chat.
Comment on lines +43 to +44
var analyzerPath = Path.Combine(
RepoRoot(), "src", "NodePilot.Core", "WorkflowDefinitions", "WorkflowDataBusAnalyzer.cs");
@Sev7eNup
Sev7eNup merged commit 6b7e8cf into main Aug 16, 2026
9 checks passed
@Sev7eNup
Sev7eNup deleted the refactor/single-workflow-analyzer branch August 16, 2026 17:30
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