Captures the 5 patterns that burned the most time in the startup_speedup_20260606 sub-track 4 work: 1. ALWAYS use manual-slop_edit_file, not custom scripts (custom scripts fail silently on indent/EOL/whitespace drift) 2. The decorator-orphan pitfall (inserting before 'def foo' leaves @property decorating YOUR new method) 3. ast.parse() is not enough (semantic errors aren't caught; import + instantiate + call after every edit) 4. The git restore trap (don't run git status/restore while a user is mid-conversation) 5. Small verified edits beat big scripts (edit_workflow says 3-10 lines; if you write 200 lines of script, wrong tool) Also adds 2 new anti-patterns to the Critical list in AGENTS.md and 3 new sections to conductor/edit_workflow.md (decorator-orphan, ast.parse-not-enough, set_file_slice-is-literal).
5.4 KiB
Manual Slop Edit Tool Workflow
The Problem
The manual-slop_edit_file tool requires exact string matches (character-for-character). Whitespace differences cause failures. The Python file uses 1-space indentation.
The Rules
1. ALWAYS Use Small, Incremental Edits
WRONG: Replace large blocks (50+ lines) RIGHT: Replace 3-10 lines at a time, verify, repeat
2. Verify Before Editing
Before ANY edit to a function you haven't touched recently:
1. Run: git checkout -- src/gui_2.py
2. Run: py_check_syntax on src/gui_2.py
3. Get current state with get_file_slice
3. Reading Before Editing (CRITICAL)
- Use
get_file_sliceto get the EXACT text including all whitespace - Copy text directly from the tool output - do NOT reformat
- If using get_definition, verify the text matches before editing
4. The Edit Tool Parameters (snake_case)
{
"path": "src/gui_2.py", # Required: file path
"old_string": "exact text", # Required: must match EXACTLY
"new_string": "replacement", # Required: replacement text
"replace_all": false # Optional: replace all occurrences
}
5. 1-Space Indentation in Python
- Class methods:
def(0 spaces, then 1) - Method body:
(2 spaces total) - Nested blocks:
(3 spaces total) - NO 4-space indentation anywhere in this file
6. The Decorator-Orphan Pitfall (Added 2026-06-07)
When inserting new methods before an existing @property def:
@property
def perf_profiling_enabled(self) -> bool:
...
If you anchor on def perf_profiling_enabled and insert before it, the @property decorator on the line above is left orphaned on the line right before YOUR new method. Now @property decorates your method (which is no longer a property), and the original setter @perf_profiling_enabled.setter blows up at import with 'function' object has no attribute 'setter'.
Fix: Anchor on a non-decorated landmark, or include the decorator in the replacement:
old_string=self._init_actions()\n\n @property\n def perf_profiling_enablednew_string=self._init_actions()\n\n def your_new(...)\n ...\n\n @property\n def perf_profiling_enabled
This keeps the @property attached to its original method.
7. ast.parse() Is Not Enough (Added 2026-06-07)
py_check_syntax only confirms ast.parse() succeeds. Semantic errors (wrong decorator targets, wrong base class, wrong attribute, missing self) are NOT caught. After any multi-line edit, ALWAYS:
- Import the module:
python -c "from src.app_controller import AppController" - Instantiate the class
- Call the new method in the way it's expected to be called (
ctrl.foo_tsfor a property,ctrl.foo_ts()for a method)
8. Do Not Use set_file_slice For Multi-Line Content (Added 2026-06-07)
set_file_slice does literal line replacement by design. It does not reindent, does not normalize EOL, does not parse decorators. Use it for surgical line-level edits (3-10 lines). If you need to insert or replace a multi-method block, use manual-slop_edit_file with verified exact-text old_string/new_string, or use py_add_def / py_update_definition for class/method-level work.
Step-by-Step Workflow for gui_2.py
Before ANY edit:
git checkout -- src/gui_2.py
Check current state:
py_check_syntax path=src/gui_2.py
get_file_slice path=src/gui_2.py start_line=X end_line=Y
For each edit:
- Make the smallest possible change (3-10 lines)
- Run
py_check_syntaxto verify - If syntax error, immediately
git checkout -- src/gui_2.py - Only proceed if syntax is OK
If edit fails with "old_string not found":
- The text you're trying to replace doesn't EXACTLY match
- Use
get_file_sliceto get the exact text - Copy it character-for-character including whitespace
- Try again with exact match
If syntax error after edit:
git checkout -- src/gui_2.py
Then try again with smaller edit.
Alternative: Update Definition Approach
For large function rewrites, use py_update_definition:
name: function_name
path: src/gui_2.py
new_content: complete new function source
This replaces the entire function at once using AST detection.
Context Composition Requirements
Current Broken State
Files & Media works. Context Composition needs:
- Add state tracking at start of function:
if not hasattr(self, 'ctx_files_open'):
self.ctx_files_open = True
if not hasattr(self, 'ctx_shots_open'):
self.ctx_shots_open = True
- Files section with collapsing header and child window:
if imgui.collapsing_header("Files", self.ctx_files_open):
imgui.begin_child("ctx_files_child", imgui.ImVec2(-1, 200), True)
# table code here
imgui.end_child()
- Screenshots section with collapsing header and child window:
if imgui.collapsing_header("Screenshots", self.ctx_shots_open):
imgui.begin_child("ctx_shots_child", imgui.ImVec2(-1, 100), True)
# screenshot list here
imgui.end_child()
-
Fixed presets bar with push_item_width(150) on the combo
-
Remove the batch action bar entirely (Full/Agg/Sig/Def/None/Sel All/Del buttons)
Key Files
src/gui_2.py- Main GUI (1-space indentation, CRLF)src/models.py- Data models including FileItem- Context Composition function: line ~2748
Test Command
uv run sloppy.py
If Everything Goes Wrong
git checkout -- src/gui_2.py
git checkout -- src/models.py