explore/plan/refactor: wire local providers with tools at all; fix lex_audit's --calls/--uses-host flags - #105
Merged
Conversation
…x_audit's --calls/--uses-host flags
Found by testing the four modes untouched all session. explore, plan,
and refactor's ollama_agent()/litellm_agent() all had `tools: []` and
`max_steps: Some(3)` — not curated-minimal like every other local mode,
just entirely unwired. Every other provider variant (cloud, mistral,
vllm, openai, google, opencode) correctly used tools_for_spec(...) with
the mode's real max_steps (20/30/40); only the two local paths were
stubs. Confirmed live: an explore-mode call said "Let me locate the
`shout` function in `widget.lex`" and then stopped, having no tool to
do it with.
Each mode's new toolset is built to match its own permissions/rules.lex
spec exactly, not shared with the others or with dynamic_tools() — the
three permission specs genuinely differ (explore gets sigid_lookup/
effects_of/attestation_query, plan gets todowrite/remember instead,
refactor gets the full edit+vcs surface), and a tool outside a mode's
own allowlist is silently dropped by with_permission_gate regardless of
what's offered, so listing it would just be dead schema weight a local
model still pays for.
Caught and reverted one wrong turn along the way: initially added
"write" to plan_permission(), reasoning from the prompt's own claim
("except writing to `.lex/plans/*.md`"). tests/test_permissions.lex
immediately failed — "explore, plan, review and bar all deny
write/edit/bash" is a deliberate, documented security invariant ("a
read-only mode that can suddenly write... looks identical from the
outside until it does"), not an oversight. The bug was in the prompt,
which had never been true on any provider, not the permission spec.
Reverted the permission change; fixed plan.lex's prompt instead to stop
claiming a write capability it was never granted, matching bar.lex's
already-correct "output is the response text" pattern.
Also caught and fixed a second, real toolset bug while inspecting the
actual dispatched lists directly (not trusting a live run): an earlier
version of refactor_dynamic_tools() extended dynamic_tools() and
separately re-added propagate_effect/lex_store_merge, which are already
in dynamic_tools()'s gated store group — duplicating both tools in the
schema. Rebuilt from vcs_read_tools()/vcs_write_tools() directly
instead.
Separately, live-testing refactor's mandatory lex_audit-first workflow
surfaced a real, independent bug in lex_audit.lex: dimension=call built
`--call` and dimension=host built `--host`, but the actual `lex audit`
CLI only has `--calls` (plural) and `--uses-host`. The model correctly
self-diagnosed the resulting `stat --call: No such file or directory`
and fell back to grep, but the tool shouldn't need that. Fixed with an
explicit dimension-to-flag mapping; verified directly against the CLI
that the crash is gone.
lex check --strict, lex fmt --check, lex test (including the
permissions security suite), and the bar-mode gate are all green.
explore/plan/refactor all live-verified against litellm/qwen3.8:27b-mlx
after the fix: explore gave a grounded, correct answer quoting real
file content; plan produced a clean text-only plan with no confused
"I have no write tool" caveat; refactor correctly found the one real
caller of a function (working around the still-separately-real
audit_tool bug until this same commit fixed it).
Co-Authored-By: Claude Sonnet 5 <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.
Found by testing the four modes untouched all session (
plan/explore/refactor/bar).explore,plan, andrefactor's local variants all hadtools: []andmax_steps: Some(3)— every other provider variant was correctly wired, only the two local paths were unfinished stubs. Confirmed live: an explore-mode call said "Let me locate theshoutfunction" and then just stopped.Each mode's new toolset matches its own
permissions/rules.lexspec exactly, not shared with the others or withdynamic_tools()— the three permission specs genuinely differ.One wrong turn, caught and reverted: initially added
"write"toplan_permission(), reasoning from the prompt's own claim.tests/test_permissions.leximmediately failed a deliberate, documented security invariant ("read-only means read-only... a mode that can suddenly write looks identical from the outside until it does"). The bug was in the prompt, not the permission spec — reverted the permission change, fixedplan.lex's prompt instead to stop claiming a capability it was never granted.A second real bug, caught by inspecting the actual dispatched tool list directly rather than trusting a live run: an earlier
refactor_dynamic_tools()duplicatedpropagate_effect/lex_store_mergein the schema (already present viadynamic_tools()'s gated store group). Rebuilt cleanly.A third, independent bug, surfaced by refactor's own mandatory-audit-first workflow:
lex_audit.lexbuilt--call/--hostfor those two dimensions, but the real CLI only has--calls/--uses-host. The model self-diagnosed the crash and fell back to grep — fixed so it doesn't have to.lex check --strict,lex fmt --check,lex test(including the permissions security suite), and the bar-mode gate are all green. All three modes live-verified against litellm/qwen3.8:27b-mlx post-fix.Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com