It was stubbed to [] in LlmBuilderAgent, canned in PlaceholderAgent, and never
called by any handler — the Build failure path reuses Fix cognition (diagnose +
propose_repair). Removed from the DifyBuilderAgent Protocol, both implementations,
and all test doubles.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Clear fc.test_input_ref and fc.verify_run_id on the four re-plan/revert
escape branches in Build and Edit (handle_review's continue_adjusting
and handle_reverted's retry_after_revert) so a rebuild+retest
regenerates fresh schema-shaped mock inputs instead of reusing the
first build's stale ones -- the approve_repair retest path is left
untouched since it must fairly retest against the same failing case.
Also corrects three doc/comment mismatches (llm_agent's 12->13 method
count, an await_repair docstring describing a branch that doesn't
exist, and state.py's Build state-count banner), and adds tests for
the run_draft-raises degrade path and Build/Edit pass-path canvas
event symmetry.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Final consolidated fix wave from whole-branch review of the Real Build +
Edit Cognition slice:
- _ground now overwrites the model dict on ANY create_node whose config
carries a model dict (llm, question-classifier, parameter-extractor),
not just "llm", so a drifted/hallucinated provider/name on those other
node types no longer flows through ungrounded.
- to_intents now carries a generator edge's sourceHandle/targetHandle
into the connect intent's args (source_handle/target_handle) so
branching nodes (if-else, question-classifier) wire onto the correct
port instead of collapsing onto the default handle; edges without
handles still produce bare {from_node, to_node} args.
- Cleared the 17 ruff errors (PT018/E302/E306/E501) across the slice's
test files by splitting composite asserts, adding missing blank
lines, and wrapping long lines -- no assertions weakened, no noqa.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Docstring said "9 now use real LLM cognition" but enumerated 3 Fix +
6 Build + 3 Edit = 12 methods (Task B3 added the 3 Edit methods
without updating the leading count). Fix the count to 12 of 14 to
match the enumerated list.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
analyze_impact/propose_edit_plan/build_edit_intents now call
services.dify_builder.agent.edit.* via _model_or_none() instead of
delegating to the canned PlaceholderAgent. 9 of the Protocol's 14
Build/Edit/Fix methods now use real LLM cognition; only
generate_mock_inputs and propose_build_repair (returns []) remain
deferred pending the live-test step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
analyze_impact could raise on a non-list target_node_ids from the LLM (no
isinstance guard, unlike fields/values) -- violated the never-crash
contract. Guard it the same way. Also collapse the fake models' invoke_llm
signatures to **_kwargs (underscore-prefixed, no noqa) per the ARG lint
constraint, and pin two more malformed-shape degrade paths
(build_edit_intents non-list intents, propose_edit_plan non-list plan).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LlmBuilderAgent's 6 Build methods (analyze_goal, propose_plan_v1,
discover_resources, bind_resources, build_nodes, learn_from_build) now
delegate to services.dify_builder.agent.build instead of the canned
PlaceholderAgent. propose_build_repair returns [] -- there's no real
failure signal to diagnose until the live test step is de-canned.
handle_test_and_repair now conditions the error card + apply_repair on
a non-empty propose_build_repair result: placeholder mode keeps today's
"found and fixed" arc, while real cognition (which never reports a
failure yet) emits a neutral "no issues found" review summary instead
of a fake error/fix on a hardcoded node id that real build_nodes
wouldn't have generated anyway.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Grounding only overwrites provider+name on an llm node's model dict now,
preserving whatever mode/completion_params the generator produced instead
of synthesizing a temperature when none was present. knowledge-retrieval
grounding now assigns each node its own dataset_ids list copy instead of
aliasing one shared list across every KB node in the graph.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Fix S110: replace bare except-pass with explicit degrade behavior
- Fix E501: wrap long function signatures to <=120 chars
- Fix I001: sort imports in test file (resources to top)
- Fix PT018: split composite assertions into separate statements
- Add _BoomInstance for provider-error testing
- Add 5 degrade tests (analyze_goal, propose_plan_v1 x2, discover_resources, learn_from_build)
- Remove unused _KIND_BY_PREFIX dict
- Add noqa comments for test mock arguments
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Only map the first start-type node to canonical 'start'; additional starts
retain their original ids to prevent collisions and ambiguous intents.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
FINDING 1 (dataset visibility): DatasetService.get_datasets requires user
parameter and silently omits ONLY_ME/PARTIAL_TEAM datasets on RBAC tenants.
Query Dataset model directly by tenant_id for complete grounding inventory.
FINDING 2 (normalization guard): Move fetch+normalize inside _safe to prevent
malformed records from raising after _safe returns. Use lambda builders to wrap
complete resource transformation including record normalization.
FINDING 3 (test coverage): Add test_mixed_failure_partial_success (one source
fails, others succeed) and test_malformed_tool_record_degrades (missing
tool_name key gracefully degrades).
Minor: compute model id once and reuse for both id and label fields; ensure
E302 two blank lines between test functions.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implement resources.py with list_tenant_resources() to normalize tenant's
configured models, datasets, and tools to ResourceRef(id, label, meta,
readiness). Each source degrades to empty list on failure for graceful
degradation.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
filter_applicable's per-intent try/except only caught (ValueError, TypeError),
so a hallucinated insert_between with a non-dict edge arg raised an uncaught
AttributeError and crashed the whole advance instead of being rejected by the
dry-run. Broaden to except Exception (ruff does not flag it, so no noqa is
added). Add a regression test for the string-edge case.
Also update llm_agent.py's stale module docstring (Fix cognition is now real,
not delegated; Protocol has 14 methods, not 13) and fix a stray closing paren
in a test_handlers_fix.py comment.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
_touched_node_types looked up connect intents via a nonexistent node_id key,
always resolving to "" and missing the external-side-effect type of either
endpoint. Branch connect on from_node/to_node instead, and add a test proving
the external risk floor fires on a non-structural set_node_config against an
http-request node.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- test_wiring.py: expected dict was missing SessionView's new `model` field
- model_resolver.normalize_completion_params: a string `stop` was being
char-split into a list of letters instead of wrapped in a single-element
list; added a regression test
- controllers/console/dify_builder._ping: log the exception server-side
before returning the ok:false envelope
- ruff-clean the slice's new/extended test files (ARG001/ARG002/ARG005 via
precise noqa, PT018 compound-assert splits, E306, E501) with no change
to test behavior or assertion meaning
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>