Repository navigation
mcp: clear_scene, an agent empties a project on purpose - #1012
Conversation
…pe is refused with its code A store may refuse a write that would empty a populated project, which is an accident far more often than an intent (a client that never finished loading, a deletion of everything), and the hosted store does. An agent then had no way to start over on purpose. clear_scene, one contract in core: the scene goes back to the host's default scaffold (a site, a building, a level) and is saved with allowSceneWipe, a new save option. A store that refuses a wipe throws SceneWipeBlockedError; live sync answers it as the refusal scene_wipe_blocked, naming clear_scene, and apply_patch returns it with its code as the shared tools do. A store with no guard saves as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What this PR doesAdds
Start with |
… is stored The store refused a write that would leave the project empty, but the session had already applied it, so the agent's next writes built on a scene the project did not hold: deleting the only room it built (delete_zone) was refused, and the room was gone from the session only. Live sync now loads the stored scene back into the session before it answers scene_wipe_blocked, and the refusal fits a deletion as well as an accident: "This write would leave the project empty, so it was blocked and nothing changed. To empty the project on purpose, call clear_scene. To remove only part of it, such as its only room, build what replaces it first, then remove it." When the stored scene cannot be read back, it says to call load_scene before writing again. Other refused live-sync writes (a version conflict, a store failure) keep their behaviour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main wins: its annotation test compares the registered tools with the policy lists, so this branch's tool count goes, and clear_scene stays in the destructive list; the annotation packet's inventory is main's 73 plus clear_scene. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resetting to the host's scaffold with setScene and loadDefault dropped the plugin install state on every host, so the saved, cleared project lost its plugins, where the editor's own clear keeps them. The scaffold is applied again with the plugin state before it is saved. As load_scene does, the reset leaves no undo history in the session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e616b48. Configure here.
Without installed plugins the reset kept its undo history, so an undo after clear_scene landed on the empty intermediate (or the old scene) and the next save persisted it, on a store with no wipe guard too. The history is now cleared after every reset, as the editor's own clear does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… warning (pascalorg#1013) into the sync bundle Union with main's clear_scene (pascalorg#1012): its contract and registration sit beside the foundation's tools; live sync keeps the foundation's { status, project } answer and main's deliberate wipe path; apply_patch answers a store's refusal with its code, then rethrows MCP errors; the annotation count is computed from the policy, which lists clear_scene. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Reviewer guide: clearing a project on purpose
Merge order: this PR first, then pascalorg/private-editor#848, which points its submodule here.
On editor main (2026-10-06): d92eb5a merges main a860e19 (#915, #1000, #996). The tool lists follow main's:
read-tool-annotations.test.tscompares names with the policy lists, and the policy count is main's 73 plusclear_scene. fa483f1 is comment-only.What changes for a user (an agent on the MCP or in the hosted chat):
clear_sceneempties the project on purpose, back to the default scaffold: a site, a building and one level of the standard storey height. The agent calls it when the person asked to start over, and says what they asked inreason.scene_wipe_blockedwith its code, instead of a generic failure, and the session goes back to the project as stored: before, it kept the refused write, so deleting the only room was refused yet the room was gone from the agent's session, and its next writes built on a scene the project didn't hold. The message fits a deliberate deletion as well as an accident: "This write would leave the project empty, so it was blocked and nothing changed. To empty the project on purpose, call clear_scene. To remove only part of it, such as its only room, build what replaces it first, then remove it."clear_sceneworks there too.How to test:
bun install && bun run cion this branch.bun test packages/mcp/src/tools/clear-scene.test.ts:clear_sceneempties a house and the nextcreate_walllands on the scaffold; anapply_patchdeleting the site is refusedscene_wipe_blocked, nothing is saved and the session keeps the house;delete_zoneon a one-room project's room is refused, the session keeps the room, and the nextcreate_wallleaves the store and the session equal.What to read:
packages/core/src/agent-tools/clear-scene.ts: the contract;packages/mcp/src/tools/clear-scene.ts: the tool;packages/mcp/src/tools/live-sync.ts:allowSceneWipepassed to the store; onSceneWipeBlockedErrorthe stored scene is loaded back into the session, then the refusal is answered. Other refused live-sync writes (a version conflict, a store failure) keep their behaviour.What to skim:
packages/mcp/src/storage/types.ts(allowSceneWipe,SceneWipeBlockedError, aSceneInvalidErrorso callers that know only that keep working),apply-patch.ts(a store's refusal returned with its code), the tool list and README row.What to ignore: the tests,
plugin-evals/tool-annotation-justifications.jsonandscripts/openai-tool-annotation-policy*(the new tool's annotations).What does this PR do?
Adds
clear_scene, one shared agent tool (core contract, inAGENT_TOOL_CONTRACTS), the only way for an agent to empty a project on purpose:setScene({}, [])thenloadDefault()) and persists it through live sync with the newSceneSaveOptions.allowSceneWipe. It answers{ cleared: { removed }, version, graphHash }with the usual live-sync fields. Destructive annotation.SceneWipeBlockedError(aSceneInvalidError) is what a store throws when it refuses an emptying write withoutallowSceneWipe. Live sync loads the stored scene back into the session (asload_scenedoes), then answers the refusalscene_wipe_blockedwithmutationApplied: false; when the stored scene can't be read back, it says to callload_scenebefore writing again.apply_patchreturns that refusal with its code, as the shared tools return theirs.No schema change; old scenes load as before.
How to test
bun install && bun run ci: lint, skills validation, type checks, tests and build pass.bun test packages/mcp/src/tools/clear-scene.test.ts packages/mcp/src/tools/read-tool-annotations.test.ts.tools/listhasclear_scenewithdestructiveHint: true; on a project with walls,clear_scene { reason: "start over" }leaves the site, building and level.Screenshots / screen recording
N/A: no visual change.
Checklist
bun devbun checkto verify)mainbranch🤖 Generated with Claude Code
Note
High Risk
Destructive project-wide reset plus new persistence guard behavior on all mutating live-sync writes; incorrect wipe detection or failed session restore could block saves or desync agent sessions from stored projects.
Overview
Adds
clear_sceneas the shared agent/MCP tool for intentionally resetting a project to the default scaffold (site, building, one level), with a requiredreasonand persistence viaallowSceneWipe. Installed plugins are preserved; undo history is cleared.Stores that guard against accidental wipes can refuse emptying writes without that flag via
SceneWipeBlockedError. Live sync now reloads the stored graph into the session on that error and returnsscene_wipe_blocked(pointing agents toclear_scene) instead of leaving a refused mutation in memory;apply_patchsurfaces the same refusal shape as other agent refusals.Docs, destructive tool annotations, and policy inventories are updated for the new tool (74-tool count).
Reviewed by Cursor Bugbot for commit b288c19. Bugbot is set up for automated code reviews on this repo. Configure here.