[draft] cmd/edit: the edit tool as a standalone program for program tool calls - #1266
Open
bobzhang wants to merge 2 commits into
Open
[draft] cmd/edit: the edit tool as a standalone program for program tool calls#1266bobzhang wants to merge 2 commits into
bobzhang wants to merge 2 commits into
Conversation
…l calls An `mbtx` snippet can now compose edits itself instead of the model emitting one tool call per change, so edits can be derived from something the model just computed (a `moon check` run, a grep) and applied in one turn. `cmd/edit` is a thin main over `agent_tool/edit`: it builds that package's definition and runs its own executor, so the decode, exact-match discipline, parse gate, and response text are the in-process tool's, with no second implementation to drift. Arguments are the tool's own JSON, from argv or stdin; exit is 0 on a normal response and 1 on a reported error so a snippet can branch without parsing the message. Write confinement deliberately does NOT come from the payload — the caller authors that, so it must not be able to widen its own reach. `OPENSEEK_EDIT_ROOT` bounds writes to one root and `OPENSEEK_EDIT_ALLOWED_PATHS` narrows it to a worker's `allowed_paths`; a malformed allowlist fails the run rather than widening to the whole root. With neither set the program is unconfined against the working directory, which is the standalone mode. Provenance is not carried: the engine's `FileStateMap` is an in-memory handle, so edits made here are invisible to it and `remove` refuses to delete a file only this program touched. That is fail-closed and documented; sharing the record across both paths is separate work. tests/cram/edit.md covers a successful edit, stdin input, a failed match, the parse gate, and the confinement (including a `..` escape attempt). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HHGA6k85VnewvkWC5miLzR
A snippet controls a spawned child's environment (@process.run takes extra_env/inherit_env), so environment-supplied confinement binds the engine but not a model-authored snippet. Snippets cannot write the workspace today, so admitting an editor with a caller-chosen scope would be a regression, not an addition. Names the discovery-based shape that would fix it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HHGA6k85VnewvkWC5miLzR
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
First step of the program-tool-call plan:
cmd/editruns theeditagent tool as a standalone program, so anmbtxsnippet can compose edits itself instead of the model emitting one tool call per change. Edits can then be derived from something the model just computed (amoon checkrun, a grep) and applied within a single turn.It is deliberately thin: it builds
agent_tool/edit's definition and runs that package's own executor, so the decode, exact-match discipline, parse gate, and response text are the in-process tool's. There is no second implementation of edit to drift.Exit is 0 on a normal response and 1 on a reported error, so a snippet can branch without parsing the message.
Confinement
The caller writes the JSON, so the JSON does not decide where writes may land.
OPENSEEK_EDIT_ROOTbounds writes to one root;OPENSEEK_EDIT_ALLOWED_PATHSnarrows it to a worker'sallowed_paths. A malformed allowlist fails the run rather than widening to the whole root.Known limitation, and why mbtx wiring is NOT in this PR
Environment-supplied confinement binds a trusted spawner (the engine) but not a model-authored snippet:
@process.runtakesextra_envandinherit_env, so a snippet can start this program with any environment it chooses.Today a snippet cannot write the workspace at all — moonrun's
fsrules grant only its temp directory and a read-only role's scratch lab, specifically so a snippet cannot route aroundremove's provenance check. Adding this binary to the mbtx spawn allowlist as it stands would hand that reach back, so it is not on the allowlist and this PR does not touchspawnable_commands.The fix is discovery instead of instruction: the engine writes the policy inside the workspace and the program finds it by walking up from the file it is about to modify. A snippet cannot plant a competing policy there because it cannot write there. That is the next step and wants its own review.
Provenance is also not carried:
FileStateMapis an in-memory handle in the engine, soremoverefuses to delete a file only this program touched. Fail-closed and documented.Verification
moon fmt,moon check --deny-warn,moon info(no interface drift)moon test agent_tool/edit agent_tool/multi_edit agent_tool/write_scope cmd/edit --target native— 103 passedmoon cram test tests/cram— 30 passed, including the newtests/cram/edit.mdcovering a successful edit, stdin input, a failed match, the parse gate, out-of-allowlist denial, and a..escape attempt🤖 Generated with Claude Code
https://claude.ai/code/session_01HHGA6k85VnewvkWC5miLzR