refactor(hooks/builtins): inline & simplify add_prompt_files#2530
Merged
dgageot merged 3 commits intodocker:mainfrom Apr 27, 2026
Merged
Conversation
The session.ReadPromptFiles helper had only one caller — the add_prompt_files builtin — so move it (and its private findFileInHierarchy / isFile helpers) into the builtin itself as unexported functions and drop the cross-package dependency. - pkg/hooks/builtins/add_prompt_files.go: inlines readPromptFiles, findFileInHierarchy, isFile; removes the pkg/session import. - pkg/hooks/builtins/add_prompt_files_test.go: relocates the seven prompt-file behavior tests as internal tests so they can exercise the now-unexported readPromptFiles directly. - pkg/session/prompt_file.go and prompt_file_test.go: removed. No behavior change: the public add_prompt_files hook keeps the same working-dir-hierarchy + home-folder lookup, dedup, and missing-file tolerance. Assisted-By: docker-agent
The previous shape stacked three layers — addPromptFiles → readPromptFiles → findFileInHierarchy/home-lookup — and the middle layer mixed path discovery with file reading just to surface a (rare, swallowed) read error to the hook for logging. Flatten to two layers with a single responsibility each: - promptFilePaths(workDir, filename) []string — pure path discovery, no I/O errors (Stat failures already surface as "not a regular file"). Returns the workdir-hierarchy match first, then the home-dir match if it exists and isn't the same path. Dedup is now an explicit slices.Contains rather than an inline path comparison. - addPromptFiles — owns the read loop and the log-and-skip policy in one place: per-path os.ReadFile with a single slog.Warn site. Behavioral envelope unchanged: same workdir-hierarchy + home-folder lookup, same dedup, same missing-file tolerance, same turn_start output joined with "\n\n". Read errors are now logged per path rather than per filename, which is strictly more informative and keeps a partially-readable filename's surviving file contributing. Tests retargeted at promptFilePaths, asserting on the discovered paths (more precise than round-tripping byte content). End-to-end content reading remains covered by TestAddPromptFiles* in builtins_test.go. Assisted-By: docker-agent
…meDir The previous test file used a homeFixture helper that wrote into the real $HOME with a unique-looking filename and conditionally cleaned up. That had three problems: 1. If a real file with the test's "unique" name happened to exist in the user's home directory, the helper would overwrite it without cleaning up afterwards — silent data loss. 2. The `_, existed := os.Stat(path)` variable name lied about its semantics: existed is the error, so existed != nil means the file did *not* exist. 3. Tests required a writable $HOME and used t.Skip to mask write failures, blocking any future move to t.Setenv (which is also incompatible with t.Parallel). Fix by dependency-injecting homeDir: - promptFilePaths(workDir, homeDir, filename) now takes homeDir explicitly. homeDir == "" disables the home lookup entirely. - addPromptFiles resolves homeDir once via os.UserHomeDir() and passes it in (errors fall back to "" — same observable behavior as the previous err == nil guard). - Tests pass t.TempDir() for both workDir and homeDir, so they never touch the real user environment. Drops homeFixture, the t.Skip, the unique-filename hack, and the conditional cleanup. Two new tests cover regressions the previous shape couldn't: - TestPromptFilePathsWorkDirNestedInHome: workDir is a subdirectory of homeDir and the prompt file lives at homeDir; the hierarchy walk finds it and the home lookup must not duplicate it. - TestPromptFilePathsEmptyHomeDirSkipsHomeLookup: homeDir == "" unambiguously disables the home-dir branch. writePrompt and makeDir helpers replace the per-test boilerplate. No behavior change in production code. Assisted-By: docker-agent
gtardif
approved these changes
Apr 27, 2026
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.
Moves
session.ReadPromptFiles(and its private helpers) into the onlypackage that consumed it —
pkg/hooks/builtins/add_prompt_files.go—then simplifies the architecture and tightens up the tests. No
production behavior change.
Commits
refactor(hooks/builtins): inline readPromptFiles into add_prompt_filessession.ReadPromptFiles,findFileInHierarchy, andisFileinto the builtin as unexported helpers; drops thepkg/sessionimport.pkg/hooks/builtins.pkg/session/prompt_file{,_test}.go.refactor(hooks/builtins): split discovery from I/O in add_prompt_filesreadPromptFiles(workDir, filename) ([]string, error)(which mixed path discovery with I/O just to bubble a swallowed
error up to the hook) with
promptFilePaths(workDir, filename) []string— pure path discovery, no error return.
a single
os.ReadFile+slog.Warnsite.slices.Containsinstead of an inline pathcomparison.
promptFilePaths, asserting on discoveredpaths (more precise than round-tripping byte content). Content
reading remains covered end-to-end by
TestAddPromptFiles*inbuiltins_test.go.test(hooks/builtins): make prompt-file tests hermetic via injected homeDirpkg/sessiontests: ahomeFixturehelper that wrote into thereal
\$HOMEand could silently overwrite a user file with acolliding name (skip-cleanup-when-it-existed semantics).
promptFilePaths(workDir, homeDir, filename)now takeshomeDirexplicitly; the hook resolves it once viaos.UserHomeDir()(errors → "", which disables the homebranch). Same observable behavior in production.
t.TempDir()for both `workDir` and `homeDir`,so they never touch the real user environment. Drops the
homeFixturehelper, thet.Skip, the unique-filename hack,and the conditional cleanup.
TestPromptFilePathsWorkDirNestedInHome(workdir as asubdirectory of home, dedup via the hierarchy walk) and
TestPromptFilePathsEmptyHomeDirSkipsHomeLookup(explicitdisable contract).
Validation