refactor: extract plan mode into tools/plan_mode.py#52
Draft
Simon-Free wants to merge 3 commits intoSafeRL-Lab:mainfrom
Draft
refactor: extract plan mode into tools/plan_mode.py#52Simon-Free wants to merge 3 commits intoSafeRL-Lab:mainfrom
Simon-Free wants to merge 3 commits intoSafeRL-Lab:mainfrom
Conversation
…nExtract inline plan mode code from tools/__init__.py into tools/plan_mode.py.`nAdd WritePlan tool (was missing). Validate plan file before exit.`n`nRef SafeRL-Lab#43
The previous revision of this PR created tools/plan_mode.py but left an inline copy of EnterPlanMode / ExitPlanMode at the bottom of tools/__init__.py which was loaded AFTER the extension module, so plan_mode.py's registrations were silently overwritten. On top of that the extension loader list had a syntax error (`"task.tools",, "plan_mode"]`) which crashed tools/__init__.py import, making every test that touched the tools package fail at collection time. Changes: - Fix the extension list syntax and use the fully-qualified `"tools.plan_mode"` module name. - Delete the ~90-line inline plan_mode block from tools/__init__.py. - Rewrite tools/plan_mode.py around the inline block's mature logic (.nano_claude/plans/<_session_id>.md, header-detection for empty-plan guard, permission restoration on exit). WritePlan is dropped: the regular Write tool is used, scoped by agent._check_permission's "plan" branch to only allow writes to the plan_file. - Replace the unit tests: they now exercise the actual _enter_plan_mode / _exit_plan_mode and the empty-plan guard. - Add tests/test_plan_mode_e2e.py driving agent.run with a mocked stream: (1) full EnterPlanMode -> Write(plan_file) -> ExitPlanMode flow, (2) Write to an unrelated path in plan mode is rejected and the file is never created. - Upgrade the silent `except Exception: pass` in the extension loader to a stderr log so optional-module load failures are visible without crashing startup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Consolidate the plan-mode tools (
EnterPlanMode/ExitPlanMode) into a single moduletools/plan_mode.py. The previous revision split them out but left an inline copy at the bottom oftools/__init__.py, and the extension-loader list had a"task.tools",, "plan_mode"]syntax error that crashed thetoolspackage import - so plan-mode registrations were both duplicated and unreachable.Why this matters
Plan mode is the agent's structured-thinking entry point:
EnterPlanModeflipsconfig["permission_mode"]to"plan", which tellsagent._check_permissionto allowWriteonly on the per-session plan file.ExitPlanModereads the plan back, refuses to leave if it is empty or only a top-level title, and restores the previous permission mode. There is no dedicatedWritePlantool - the normalWritetool, scoped by the permission check, does the right thing and avoids teaching the LLM a second file-writing primitive.Changes
tools/plan_mode.py_enter_plan_mode,_exit_plan_mode, tiny helpers_plan_file_for,_read_plan_content,_plan_has_substance; register both toolstools/__init__.py"tools.plan_mode"added,"task.tools",,"plan_mode"]syntax error corrected); replace the silentexcept Exception: passwith a stderr log so optional-module load failures are visibletests/test_plan_mode.pytests/test_plan_mode_e2e.pyagent.runwith a mockedproviders.stream: full Enter?Write(plan_file)?Exit flow on disk; Write outside the plan file in plan mode is denied and the target file is never createdBackwards compatibility
config["disabled_tools"] = ["EnterPlanMode", "ExitPlanMode"]will suppress registration once #55 lands (it adds that gate to the registry). Behaviour on disk is the same as before this PR: same plan-file location (<cwd>/.nano_claude/plans/<session_id>.md), same permission-mode semantics, same empty-plan guard. The only model-facing change is thatWritePlanis no longer advertised - the existingWritetool is used instead.Ref #43