Skip to content

feat(planner): expose plan approval through config (#64) - #206

Merged
Fosowl merged 1 commit into
mimosa_v2from
propose/planner-human-approve
Sep 3, 2026
Merged

feat(planner): expose plan approval through config (#64)#206
Fosowl merged 1 commit into
mimosa_v2from
propose/planner-human-approve

Conversation

@lfnothias

Copy link
Copy Markdown
Collaborator

Problem

Planner._generate_plan_with_human_validation has carried a plan-approval loop since it was written: display the plan, Enter approves it, typed feedback regenerates it with the feedback appended to the goal. Its only caller passes human_approve=False and no setting reaches it, so the loop is dead code. Issue #64 asks for this gate.

The prompt also reads stdin unconditionally. With the gate on, an unattended run would pay for the plan and then die on input() with EOF when reading a line.

Solution

  • Config.planner_human_approve (default False), persisted by jsonify and from_json, exposed as --planner_human_approve.
  • main.py passes it to start_planner on the --goal path only. The benchmark (csv_mode), onboarding and web-bridge callers keep the default and never prompt.
  • start_planner refuses the gate before the planning LLM call when stdin is not a TTY, raising UserInterventionRequired; the prompt itself carries the same guard. The exception class is identical in text and position to the one in 67b4251 on mimosa_v2_lfx, so the two lines merge cleanly.

Testing

  • New tests/planner_human_approve_test.py, seven tests: the default path never prompts; feedback regenerates the plan with the feedback in the goal; Enter approves and text is feedback; headless refusal both before planning and at the prompt; the argument defaults to off; the config field round-trips. tests/config_roundtrip_test.py covers the new field on its own.
  • Full suite in a fresh uv sync --group dev environment: 236 passed, 17 failed, 4 skipped. The 17 are the same set that fails on mimosa_v2 before this change; ci(tests): run pytest on pull requests and pushes #205 lists them.

Backwards compatibility

Off by default, so no behaviour changes unless the flag or config key is set. start_planner gains a keyword argument with a default; existing callers are untouched.

🤖 Generated with Claude Code

Planner._generate_plan_with_human_validation has carried an approval loop
since it was written (show the plan, Enter approves, typed feedback
regenerates it), but its only caller passed human_approve=False and no
setting reached it, so the loop was dead code. Issue #64 asks for exactly
this gate.

Add planner_human_approve to Config (persisted by jsonify/from_json) and a
--planner_human_approve flag; main.py passes it to start_planner on the
--goal path only. The benchmark, onboarding and web entry points keep the
default and never prompt.

A headless run with the gate on now fails before the planning LLM call with
UserInterventionRequired instead of generating a plan and dying on input().
The exception type and its placement match commit 67b4251 on mimosa_v2_lfx
so the two lines merge cleanly.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Fosowl

Fosowl commented Sep 3, 2026

Copy link
Copy Markdown
Member

Approved.

@Fosowl
Fosowl merged commit 440ea47 into mimosa_v2 Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants