mirror of
https://github.com/langgenius/dify.git
synced 2026-10-04 13:47:55 +08:00
The planner names a branch's outgoing source_handle values in one LLM call; the node builder chooses the case / class / action ids in another. ESQ1-303's edges left its if-else on "score_equals_60" and "else" against a case named "true", so the engine skipped both arms and the run succeeded with nothing. declared_branch_handles lists what a node routes on; repair_branch_edge_ handles re-homes an edge only when it is forced (exact / alias / name / stem match, one arm fanning out under a single invented name, default- source edges onto unused handles in order) and returns everything ambiguous untouched; undeclared_branch_handles reports what is left so a validator can reject it. A wrong guess would silently swap IF and ELSE. Aliases are trusted as names -- the documented limit -- which is why the node-builder handle contract, not this repair, is the primary fix. A fail-branch node's success path stays on "source" (what graphon's NodeRunResult.edge_source_handle actually emits by default), not an invented "success" handle nothing ever routes on; a fail-branch branch-type node (if-else / question-classifier / human-input) just gains the extra "fail-branch" arm. human-input also always declares its implicit "__timeout" arm, since every human-input node has a timeout config and the FE always renders that handle; that arm is excluded from the "unused declared handles" pool the fan-out/default-order repair rules count against, since it is routinely left unwired by design and must not block or absorb repair of the arms the author did configure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>