Skip to content

Fix hidden file deletion and improve file tree state management#70

Closed
josh-padnick wants to merge 2 commits intomainfrom
claude/fix-delete-hidden-files-LzdcK
Closed

Fix hidden file deletion and improve file tree state management#70
josh-padnick wants to merge 2 commits intomainfrom
claude/fix-delete-hidden-files-LzdcK

Conversation

@josh-padnick
Copy link
Collaborator

@josh-padnick josh-padnick commented Feb 25, 2026

Summary

This PR fixes the handling of hidden files and directories (those starting with ".") in the generated files deletion flow, and improves the file tree state management to ensure the UI properly reflects deleted files.

Key Changes

  • Test Coverage: Added three comprehensive tests to verify hidden file handling:

    • TestDeleteDirectoryContents_HiddenFiles: Verifies that deleteDirectoryContents removes both hidden and non-hidden files/directories
    • TestCountFilesInDirectory_HiddenFiles: Ensures file counting includes hidden files and files within hidden directories
    • TestHandleGeneratedFilesDelete_HiddenFiles: End-to-end test of the HTTP handler flow with hidden directories like .github
  • Delete Hook Return Type: Changed useApiGeneratedFilesDelete hook to return a boolean indicating success/failure:

    • deleteFiles() now returns Promise<boolean> instead of Promise<void>
    • Returns true on successful deletion, false on error
    • Allows callers to determine if the operation succeeded
  • File Tree State Management: Updated App.tsx to properly clear the file tree after deletion:

    • Added setFileTree to the useFileTree hook destructuring
    • Call setFileTree(null) in handleFilesDeleted to clear stale generated files from the UI
    • Ensures hidden files/folders are removed from the UI after backend deletion
  • Alert Component Logic: Simplified GeneratedFilesAlert to use the boolean return value:

    • Check the success return value from deleteFiles() instead of checking for errors
    • Only dismiss the alert if deletion was successful

Implementation Details

The changes ensure that hidden files and directories (like .github, .env, .generated) are properly handled throughout the deletion flow, from the backend file system operations through to the frontend UI state management.

https://claude.ai/code/session_01Js4Mce3EEoW3Z83kpNuSEC

Summary by CodeRabbit

  • New Features

    • Added a control to enable/disable automatic rendering of generated content after deletes, preventing unwanted re-generation.
  • Bug Fixes

    • Generated files (including hidden ones) are reliably cleared from the UI after deletion.
    • Deletion flow now reports success/failure more consistently to the UI.
  • Tests

    • Expanded tests for hidden files handling, delete/check workflows, and relative vs. absolute output path behavior.

…files)

After clicking "Delete Files" in the generated files alert, the file tree
panel was not cleared, leaving stale entries (including hidden files/folders
like .github) visible in the UI even though they were deleted on disk.

Changes:
- Clear the GeneratedFiles context (setFileTree(null)) after successful
  deletion so the UI reflects the actual filesystem state
- Fix stale React state bug: deleteFiles() now returns a boolean so
  handleDeleteFiles can reliably check success instead of reading a
  stale closure-captured deleteError value
- Add backend tests confirming deleteDirectoryContents and
  countFilesInDirectory correctly handle hidden files/folders

https://claude.ai/code/session_01Js4Mce3EEoW3Z83kpNuSEC
@vercel
Copy link

vercel bot commented Feb 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
runbooks Ready Ready Preview, Comment Feb 25, 2026 2:37am

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Feb 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 707053c and be54470.

📒 Files selected for processing (4)
  • web/src/App.tsx
  • web/src/components/mdx/TemplateInline/TemplateInline.tsx
  • web/src/contexts/GeneratedFilesContext.tsx
  • web/src/contexts/GeneratedFilesContext.types.ts

Walkthrough

Adds hidden-file-aware backend tests and expands frontend flow to expose rendering control: deleteFiles now returns a boolean; GeneratedFiles context gains renderingEnabled/setRenderingEnabled; App and template rendering respect that and clear the UI file tree after successful deletions.

Changes

Cohort / File(s) Summary
Backend Test Coverage
api/generated_files_test.go
Adds tests for hidden files/dirs: deletion, counting (including hidden), HTTP check/delete endpoints, and relative vs absolute output path behavior.
Delete API Hook
web/src/hooks/useApiGeneratedFilesDelete.ts
Changed deleteFiles signature to return Promise<boolean> and updated implementation to return true on success, false on error.
App — orchestration & state
web/src/App.tsx, web/src/hooks/useFileTree
App now consumes setFileTree and setRenderingEnabled; clears fileTree (setFileTree(null)) after successful deletion and enables rendering when generated-files check resolves. useFileTree return type includes setFileTree.
Context & types
web/src/contexts/GeneratedFilesContext.tsx, web/src/contexts/GeneratedFilesContext.types.ts
Introduces renderingEnabled: boolean and setRenderingEnabled(enabled: boolean) into the GeneratedFiles context and types; initializes renderingEnabled to false with a stable setter.
UI components — rendering guard & delete flow
web/src/components/mdx/TemplateInline/TemplateInline.tsx, web/src/components/layout/GeneratedFilesAlert/GeneratedFilesAlert.tsx
Template rendering now checks renderingEnabled to prevent auto-rendering when disabled. GeneratedFilesAlert awaits deleteFiles() and uses the returned boolean to decide post-delete actions (onDeleted, dismiss).

Sequence Diagram(s)

sequenceDiagram
  participant User as User
  participant App as App UI\n(GeneratedFilesContext)
  participant API as GeneratedFiles API
  participant FS as Filesystem

  rect rgba(63, 81, 181, 0.5)
    User->>App: Click "Check generated files"
    App->>API: GET /generated-files/check
    API->>FS: Count files (include hidden)
    FS-->>API: file count
    API-->>App: count response
    App-->>App: set renderingEnabled (true if allowed)
  end

  rect rgba(0, 150, 136, 0.5)
    User->>App: Click "Delete generated files"
    App->>API: POST /generated-files/delete
    API->>FS: delete files (including hidden)
    FS-->>API: deletion result
    API-->>App: { success: true, deletedCount }
    App-->>App: if success -> setFileTree(null), setRenderingEnabled(false)
    App-->>User: show success + deletedCount
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🧹 Hidden dots and sneaky folders, gone with a click,
The tree is reset, the UI breathes quick.
Booleans return truth, no mysterious void—
Rendering waits now, until it's re-allowed. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: fixing hidden file deletion and improving file tree state management through UI updates and API return type changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/fix-delete-hidden-files-LzdcK

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/generated_files_test.go`:
- Around line 711-713: The test currently ignores json.Unmarshal errors and
fails to assert HTTP status in the end-to-end delete test: update each decode
block that reads into checkResp (and the other similar response vars) to check
the error returned by json.Unmarshal and call t.Fatalf or t.Fatalf-like
assertion on error, and before decoding assert the HTTP response status (e.g.,
checkRec.Code or the http response object) equals the expected status (200 or
404 as appropriate); locate the occurrences using the variables checkRec,
checkResp and the second "check" request sequence and add assertions for status
before calling json.Unmarshal and handle/unpack json.Unmarshal errors instead of
discarding them.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3deec3c and 707053c.

📒 Files selected for processing (4)
  • api/generated_files_test.go
  • web/src/App.tsx
  • web/src/components/layout/GeneratedFilesAlert/GeneratedFilesAlert.tsx
  • web/src/hooks/useApiGeneratedFilesDelete.ts

Comment on lines +711 to +713
var checkResp GeneratedFilesCheckResponse
json.Unmarshal(checkRec.Body.Bytes(), &checkResp)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Assert decode/status errors in the end-to-end delete test

Line 712, Line 731, and Line 759 ignore json.Unmarshal errors, and the second check request path (Line 754-Line 760) doesn’t assert HTTP status before decode. That can let malformed responses pass quietly.

🛠️ Suggested patch
-	var checkResp GeneratedFilesCheckResponse
-	json.Unmarshal(checkRec.Body.Bytes(), &checkResp)
+	var checkResp GeneratedFilesCheckResponse
+	if err := json.Unmarshal(checkRec.Body.Bytes(), &checkResp); err != nil {
+		t.Fatalf("Failed to decode check response: %v. Body: %s", err, checkRec.Body.String())
+	}

-	var deleteResp GeneratedFilesDeleteResponse
-	json.Unmarshal(deleteRec.Body.Bytes(), &deleteResp)
+	var deleteResp GeneratedFilesDeleteResponse
+	if err := json.Unmarshal(deleteRec.Body.Bytes(), &deleteResp); err != nil {
+		t.Fatalf("Failed to decode delete response: %v. Body: %s", err, deleteRec.Body.String())
+	}

 	// Verify check endpoint now shows no files
 	checkReq2, _ := http.NewRequest("GET", "/api/generated-files/check", nil)
 	checkRec2 := httptest.NewRecorder()
 	router.ServeHTTP(checkRec2, checkReq2)
+	if checkRec2.Code != http.StatusOK {
+		t.Fatalf("Second check endpoint returned %d: %s", checkRec2.Code, checkRec2.Body.String())
+	}

 	var checkResp2 GeneratedFilesCheckResponse
-	json.Unmarshal(checkRec2.Body.Bytes(), &checkResp2)
+	if err := json.Unmarshal(checkRec2.Body.Bytes(), &checkResp2); err != nil {
+		t.Fatalf("Failed to decode second check response: %v. Body: %s", err, checkRec2.Body.String())
+	}

Also applies to: 730-732, 754-760

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/generated_files_test.go` around lines 711 - 713, The test currently
ignores json.Unmarshal errors and fails to assert HTTP status in the end-to-end
delete test: update each decode block that reads into checkResp (and the other
similar response vars) to check the error returned by json.Unmarshal and call
t.Fatalf or t.Fatalf-like assertion on error, and before decoding assert the
HTTP response status (e.g., checkRec.Code or the http response object) equals
the expected status (200 or 404 as appropriate); locate the occurrences using
the variables checkRec, checkResp and the second "check" request sequence and
add assertions for status before calling json.Unmarshal and handle/unpack
json.Unmarshal errors instead of discarding them.

…ert resolves

TemplateInline components with generateFile={true} auto-execute on page mount,
which was regenerating files (like .github/workflows/ci.yml) immediately after
the user deleted them. The user would delete files, refresh, and see them
reappear because:

1. Generated files check runs first → finds 0 files → no alert
2. TemplateInline auto-renders → recreates the files

Fix: add a `renderingEnabled` flag to GeneratedFilesContext that starts false
and is only set to true once the generated files check completes and either:
- No existing files were found, or
- The user resolved the alert (clicked "Keep Files" or "Delete Files")

TemplateInline now checks this flag before auto-rendering when generateFile
is true, preventing the race condition where files are regenerated before the
user decides what to do with existing ones.

https://claude.ai/code/session_01Js4Mce3EEoW3Z83kpNuSEC
@josh-padnick
Copy link
Collaborator Author

Closing in favor of #79, which extracts the two legitimate bug fixes from this PR:

  1. Stale file tree after deletionsetFileTree(null) not called after successful delete
  2. Stale closure in error checkdeleteFiles() now returns Promise<boolean> so callers don't read a stale deleteError from the closure

The other changes in this PR were determined to be unnecessary after analysis:

  • renderingEnabled / rendering race condition: TemplateInline does not auto-execute on mount — it's gated behind hasAllInputDeps, hasAllOutputDeps, and other checks that require user input. The race condition this mechanism was designed to prevent doesn't actually occur in practice.
  • Hidden file backend tests: The tests verify that os.ReadDir() and filepath.Walk() include dot-prefixed files, which is guaranteed by Go's stdlib. The implementation has no filtering logic that could skip hidden files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants