test(agents): capture LLM-agent file_write unsafe-mode regression (#115) #119
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!119
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "tdd/m1-llm-tool-unsafe-mode"
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
Adds a failing-first Behave regression test proving issue #115:
LLMAgent._execute_tool_loop()(cleveractors.agents.llm) and its two budget/stuck-model synthesis-retry mirrors all computeparent_unsafe = self.config.get("unsafe_mode", False)before building the ephemeral per-callToolAgent's context viaLLMAgent._build_tool_context(). No code anywhere in the codebase ever setsconfig["unsafe_mode"]— the field an actor author actually sets perdocs/index.md§4.5 issafe_mode. Because the dispatch sites never readsafe_mode,parent_unsafeis alwaysFalse,_build_tool_contextnever includes_unsafe_modein the tool-call context, andToolAgent._file_write_tool(§4.5.4) unconditionally raises "File writing requires unsafe mode" regardless of the agent'ssafe_modeconfiguration.Extends the shared
features/llm_agent_tool_loop.feature/features/steps/llm_agent_tool_loop_steps.pypair (rather than adding a new feature/step file) with a scenario that configures anLLMAgentwithtools: [file_write]andsafe_mode: false, mocks a model-issuedfile_writetool call through the real (unmocked)ToolAgentdispatch path, and asserts the resultingToolMessagereports success. Today it doesn't: the tool call fails with "File writing requires unsafe mode".The scenario is tagged
@tdd_issue,@tdd_issue_115, and@tdd_expected_failper the TDD issue-capture workflow.The actual fix (deriving
parent_unsafefrom the agent's ownsafe_modefield) lands separately onbugfix/m1-llm-tool-unsafe-modeper issue #115.Test plan
nox -s lintgreennox -s format -- --checkgreennox -s typecheckgreennox -s security_scangreennox -s dead_codegreennox -s unit_testsgreen — confirmed the assertion fails viaAssertionErrorwithout the@tdd_expected_failtag (verified locally by temporarily removing it), andTddExpectedFailPolicyinverts it to a pass with the tag presentnox -s coverage_report— 96.6% (>= 96.5% threshold; test-only change, features/ excluded from coverage)nox -s integration_tests— green (345/345)nox -s benchmark_regression— skipped; this is a test-only change with no new/affected ASV benchmarksCloses #116
PR Review: !119 (Ticket #116 / underlying #115)
Verdict: Request Changes
The PR is not in a mergeable state: Gitea reports
mergeable: false, and the branch carries stale versions of issue #107 changes that are already onmaster. If merged as-is, it would regress the_sandboxed_importsecurity boundary and duplicate/conflict with already-merged work. The intended #116 TDD regression test for #115 is structurally sound, but it cannot land until the branch is cleanly rebased onto currentmasterand the unrelated #107 artifacts are removed.Critical Issues
PR is unmergeable and based on stale
mastermergeable: falsefor this PR. The branch appears to have diverged frommasterbefore the final version of the issue #107 fix landed.tdd/m1-llm-tool-unsafe-modeonto currentorigin/master(or recutting the branch frommaster) so that only the intended #116 changes remain in the diff._sandboxed_importwould lose the relative-import guard (regression of #107)src/cleveractors/agents/tool.py(_sandboxed_import)_sandboxed_importonly checksif name not in _SANDBOX_ALLOWED_IMPORTSand ignores thelevelargument. Currentmasteralready has the reviewed #107 fix that also rejectslevel != 0(from .json import dumpsand other relative-import forms) per docs/index.md §13.2.1.Stale #107 test collateral would regress
masterfeatures/inline_sandbox_import_restriction.featurejsonscenario that was added during #107 review.features/steps/inline_sandbox_import_restriction_steps.pyisinstance(context.error, ExecutionError). The reviewedmasterversion additionally verifies that the rejected module name appears in the error message and that the statement after the import never ran (resultstays unset), preventing the test from passing on an unrelated error.Major Issues
Scope contamination: PR bundles unrelated #107 work
src/cleveractors/agents/tool.py,CHANGELOG.md,features/inline_sandbox_import_restriction.feature,robot/InlineSandboxImportRestrictionLib.py,robot/inline_sandbox_import_restriction.robot), rewrites oftests/fixtures/email_graph/*.yaml, and deletion offeatures/stderr_suppression.feature/features/steps/stderr_suppression_steps.py.master(commitc515470and its predecessors). It should not appear in a PR whose sole purpose is #116.Misleading PR description
src/cleveractors/agents/tool.py). Once the branch is rebased, only the intended Behave/Robot test additions for #116 should remain.Minor Issues
tests/fixtures/email_graph/components/business_email.yaml,tests/fixtures/email_graph/components/component_orders.yaml,tests/fixtures/email_graph/local_graph.yaml,tests/fixtures/email_graph/mixed_graph.yaml,tests/fixtures/email_graph/namespaced/*.yaml,tests/fixtures/email_graph/remote_graph.yamlmasteralready deduplicates this via constants inrobot/EmailGraphLib.py(_expand_shared_snippets). If any fixture rewrite is genuinely needed, it should follow the existing shared-snippet pattern, not re-introduce duplication.Nits
Summary
The #116 TDD test itself — the new
@tdd_issue @tdd_issue_115 @tdd_expected_failscenario infeatures/llm_agent_tool_loop.featureand its step definitions — is well-targeted: it configures anLLMAgentwithsafe_mode: false, mocks afile_writetool call, and asserts success, which will fail today becauseLLMAgentreads the nonexistentunsafe_modekey instead ofsafe_mode. However, the branch as it stands is not rebased on currentmasterand carries stale issue #107 changes that would regress the repository. Please rebase (not merge) ontoorigin/master, drop the unrelated #107 artifacts, and verify the diff contains only the #116 test additions before resubmitting.d2979e1ab6ede57c02b4PR Review: !119 (Ticket #116)
Verdict: Approve
The PR now contains only the intended TDD regression test for issue #115. The previous critical concerns (unmergeable branch carrying stale #107 artifacts) have been resolved: the diff is limited to the two expected test files, and Gitea reports the PR as mergeable. The scenario correctly reproduces the bug described in #115: with
safe_mode: false, the LLM-agent tool-call dispatch still reads the deadunsafe_modekey, so_unsafe_modenever reaches the ephemeral ToolAgent's context andfile_writefails. The assertion is anAssertionError, whichTddExpectedFailPolicyinverts under@tdd_expected_fail, matching the TDD workflow.Critical Issues
None
Major Issues
None
Minor Issues
None
Nits
None
Summary
Clean, focused TDD capture PR. The new scenario in
features/llm_agent_tool_loop.featureand its step definitions infeatures/steps/llm_agent_tool_loop_steps.pyextend existing shared BDD files rather than adding unnecessary new ones, consistent with the project's conventions. The tags@tdd_issue @tdd_issue_115 @tdd_expected_failare well-formed, the assertion type is correct, and the test will flip to a real pass (and trigger stale-tag detection) once #115's fix lands onbugfix/m1-llm-tool-unsafe-mode. Approved.