fix(langgraph): implement content_not_contains condition in pure graph edge evaluator #100
No reviewers
Labels
No labels
auto/blocked-by-deps
auto/ci-timeout
auto/claimed-implementer
auto/claimed-merge
auto/claimed-reviewer
auto/driver-down
auto/invariant-violation
auto/last-attempt-tier-0
auto/last-attempt-tier-1
auto/last-attempt-tier-2
auto/last-attempt-tier-min
Automation Tracking
auto/needs-conflict-resolution
auto/needs-implementer
auto/postmortem
auto/ready-to-merge
auto/restart-throttled
auto/revert
auto/sentinel
auto/stale-inactivity
auto/unstable
Blocked
Bounty
$100
Bounty
$1000
Bounty
$10000
Bounty
$20
Bounty
$2000
Bounty
$250
Bounty
$50
Bounty
$500
Bounty
$5000
Bounty
$750
MoSCoW
Could have
MoSCoW
Must have
MoSCoW
Should have
Needs Feedback
Points
1
Points
13
Points
2
Points
21
Points
3
Points
34
Points
5
Points
55
Points
8
Points
88
Priority
Backlog
Priority
CI Blocker
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Signed-off: Owner
Signed-off: Scrum Master
Signed-off: Tech Lead
Spike
State
Completed
State
Duplicate
State
In Progress
State
In Review
State
Paused
State
Unverified
State
Verified
State
Wont Do
Type
Automation
Type
Bug
Type
Discussion
Type
Documentation
Type
Epic
Type
Feature
Type
Legendary
Type
Refactor
Type
Support
Type
Task
Type
Testing
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Blocks
Reference
cleveragents/cleveractors-core!100
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "bugfix/m1-pure-graph-content-not-contains"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
PureLangGraph._evaluate_edge_condition()had no branch forcontent_not_contains(Actor Configuration Standard §5.4), so it fell into the "unknown condition type" catch-all and always returnedTrue. A classifier node with siblingcontent_contains/content_not_containsedges (the classic if/else idiom) would traverse both edges whenever the configured text was present, instead of the single edge intended.content_not_containsbranch mirroring the existing correct implementations innodes.py,bridge.py, andreactive/stream_router.py.@tdd_expected_failfrom the issue #95 regression scenario (kept@tdd_issue/@tdd_issue_95forever as a regression guard), and adds directcontent_not_containstrue/false coverage plus a sibling-edge scenario for the text-absent direction.robot/pure_graph_sibling_edges.robot,robot/PureGraphLib.py) that executes a real two-branch pure graph end-to-end and asserts exactly one branch node runs, for both directions.### Fixed.Branch note: this branch is stacked on
tdd/m1-pure-graph-content-not-contains(PR #99, not yet merged) since the fix builds on that regression test. Once #99 merges tomaster, this PR's diff will automatically shrink to just the bugfix commit.Test plan
nox -s lintgreennox -s format -- --checkgreennox -s typecheckgreennox -s security_scangreennox -s dead_codegreennox -s unit_testsgreen — 2795/2795 scenarios, including the now-unconditionally-passing@tdd_issue_95scenario and 5 new direct coverage scenariosnox -s integration_testsgreen — 321/321 tests, including the 2 new Robot testsnox -s coverage_report— 96.8% (>= 96.5% threshold)nox -s benchmark_regression -- --quick— flags 1.1-1.56x noise in unrelated registry/cache/local_store/token_budget benchmarks (none touchpure_graph.py; no benchmark exists for this code path); consistent with known--quick-mode measurement noise on a loaded runner, not a real regression from this changeNote: Forgejo CI is currently down (confirmed by maintainer) — all checks above were run and verified locally.
Closes #95
content_not_contains, causing mutually-exclusive branch conditions to both fireLGTM ✅ — self-approving per project policy (1 approval required, self-approval permitted). All quality gates verified locally:
nox -s lint,nox -s format -- --check,nox -s typecheck,nox -s security_scan,nox -s dead_code,nox -s unit_tests(2795/2795 scenarios),nox -s integration_tests(321/321 tests), andnox -s coverage_report(96.8%) all pass.nox -s benchmark_regression -- --quickflags noise in unrelated registry/cache/local_store/token_budget benchmarks (not touched by this change, and no benchmark exists for pure_graph.py) — consistent with known --quick-mode measurement noise. Forgejo CI is currently down per maintainer confirmation; not blocking on it this session. Leaving merge to a maintainer/human.3f57ecf9fe7511c62c8cPR Review: !100 (Ticket #95)
Verdict: Approve
The fix correctly implements
content_not_containsinPureLangGraph._evaluate_edge_condition()per Actor Configuration Standard §5.4, and the test matrix (direct evaluator unit-style Behave scenarios plus an end-to-end Robot integration test) provides strong regression coverage for the mutually-exclusive sibling-edge idiom described in #95. I reviewed the changed code, related implementations (nodes.py,bridge.py,reactive/stream_router.py), the spec, and project quality gates. No critical or major correctness issues were found. The remaining items are minor process/documentation gaps.Critical Issues
None
Major Issues
None
Minor Issues
Coverage falls below the documented 97% threshold.
CONTRIBUTING.md(and thecoverage_reportdocstring) state that the enforced merge gate is 97%, whilenoxfile.pycurrently setsCOVERAGE_THRESHOLD = 96.5. Because the actual tooling passes, this is not a blocker for this PR, but the project should reconcile the documented threshold with the configured threshold, or add coverage to reach 97%.The non-string/non-dict fallback in
content_not_containsis not exercised by tests.src/cleveractors/langgraph/pure_graph.py, line 2054 (return True).content_contains's existing fallback pattern, but theTruebranch for unknown message shapes has no direct test. Adding a Behave scenario (e.g., message is a list/object that does not contain the text) would improve confidence that the fallback behaves consistently with the semantics documented in the code comment.Nits
features/steps/pure_graph_content_not_contains_steps.py, lines 1–6.PureLangGraph._get_next_nodes(), but the new scenarios also call_evaluate_edge_condition()directly. Update the docstring to mention both entry points.Summary
This is a focused, well-tested bugfix. The core change is minimal and symmetric with the existing
content_containsbranch, and the added Behave/Robot scenarios directly cover the regression from #95. The only items worth addressing are minor: aligning the documented vs. configured coverage threshold and adding coverage for the final fallback branch. I am approving so the fix can land; the minor items can be handled in a fast-follow or as part of the ongoing coverage work.Minor issues number 1, is not relevant, we have a noxfile threshold at 96.5% while having a 97% in the specification, but the 97% is the rounded value, which is also obtainable from a 96.5% real coverage.
7511c62c8ca0c2119cc3