Step 12/12 of docs/superpowers/plans/2026-05-17-files-overlay-rewrite.md.
End of Phase C — end of the rewrite plan.
Two cleanups in one commit:
1. Delete GET /overlays/<id>/files/content.
The legacy openEditorForFile in files-overlay.js was its only caller,
and Step 9 deleted that code path. grep confirms no remaining live
callers (the matches in .claude/worktrees/* are other in-flight
branches; matches in docs/ are plan/spec text describing the route's
history). Removed:
* The @bp.get route function (was already a thin wrapper around
_load_file_for_editing from Step 11)
* The endpoint's mention in the module docstring
* test_content_returns_text
* test_content_returns_415_for_binary
* test_content_404_for_non_files_overlay
* The /files/content entry in the batched "non-files-overlay 404s
everywhere" test
The _load_file_for_editing helper from Step 11 becomes single-caller
(only the edit route uses it now). Kept because the function name
gives the prelude a useful named concept and inlining would add ~17
lines of low-density logic into overlay_file_edit_page.
2. Extract _apply_optional_rename.
overlay_file_save and overlay_file_replace had near-identical rename
branches: safe_resolve_for_move → 422-on-traversal, 409-if-dst-exists,
mkdir-parents, os.rename → echo_path = new_path. Extracted into
_apply_optional_rename(overlay, path, new_path) → (write_target,
echo_path) | Response.
The helper handles both cases:
* Rename: atomic rename, returns (dst, new_path)
* No rename: safe_resolve_for_write, mkdir parents, returns
(write_target, path)
Save's "destination is not a file" 409 (creation branch) stays inline
in overlay_file_save — it's save-specific behavior that doesn't apply
to /replace (which assumes a file exists or creates one).
Subtle behavior change in /save: the prior code called
safe_resolve_for_write(new_path or path) upfront and then potentially
overrode write_target via safe_resolve_for_move. The new code only
calls one validator per branch. Confirmed equivalent: per
overlay_files.py:36-58 (safe_resolve_for_write) vs. lines 76-106
(safe_resolve_for_move), the dst-side checks are identical (root
escape, symlink refuse, parent-is-dir) and safe_resolve_for_move adds
strictly more (src must exist, cycle check for directory moves). pytest
covers the save/replace paths and stays green.
pytest: 580 → 577 passed, 1 skipped, 3 deselected. The -3 is the 3
deleted /files/content tests.
files_routes.py: ended at 735 lines. The plan estimated ~450 — the
delta is the new /files/new route (~43 lines, Step 5), the binary
template branch (Step 7), the _load_file_for_editing helper (Step 11),
and module-header expansions. The structural goal (no dead routes,
shared helpers across paths) is met.
End-of-plan summary:
* 1091-line files-overlay.js → 4 focused modules totaling 1191 lines
(core.js 247, editor.js 309, dialogs.js 212, uploads.js 423)
* Editor flows (text edit, binary replace, create new) all run
through URL-addressable modals (?modal= deep-linkable)
* Legacy <dialog id="files-editor-modal"> deleted
* /files/content deleted (dead endpoint)
* Shared helpers _load_file_for_editing + _apply_optional_rename
* pytest stayed green at every step
* Chromium-verified every step
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>