Repository navigation
feat(cli): scope protected-file warnings to a project - #440
Open
NoRiceToday wants to merge 9 commits into
Open
NoRiceToday wants to merge 9 commits into
NoRiceToday wants to merge 9 commits into
Conversation
added 9 commits
October 29, 2026 11:09
Detections from one scan arrive as one decision dialog instead of one popup per file. The dialog offers, narrow to broad: ignore this exact file, ignore all files in this batch, or ignore every file with that basename in all projects. "Keep warning" is the default. Exceptions are stored in ~/.config/omac/prefs.yaml; files stay protected at launch, only the repeated notice is skipped. The session-end report collapses a burst to one summary line, --verbose lists every path, and the audit log keeps one event per path. Closes #438 🤖 Generated with DeepSeek V4.1 Flash Signed-off-by: Sajjad Ahmad <sajjad.ahmad@tngtech.com>
Captures the original noise requirements, the exact-path and batch baseline from #438, the rejected global basename option, and a design for a git-root-scoped name exception. No implementation yet; the tasks list the follow-up work. Refs #438 🤖 Generated with DeepSeek V4.1 Flash Signed-off-by: Sajjad Ahmad <sajjad.ahmad@tngtech.com>
A worktree created under .worktrees/<name> brings new .env files with a new path, so an exact-path exception never covers the next worktree. Add one broader dialog choice: ignore a basename inside the repository. The root comes from git common dir, which is shared by every worktree of the repo, and is accepted only when it contains the workdir. That keeps the scope off other projects and off a forged .git. Global basename exceptions stay out: .env.local often holds real secrets. The file stays protected at launch and every detection is still audited. Exact-path and batch choices are unchanged. Signed-off-by: Sajjad Ahmad <sajjad.ahmad@tngtech.com>
core.worktree lives in a config file the sandboxed agent can write, and git rev-parse --show-toplevel honours it. A forged .git pointer could therefore scope a project exception to a parent tree that holds other checkouts. Discover the root by walking up to the first .git entry instead. A .git directory roots at its parent. A .git file roots at the main repository only when sandboxrun.ResolveWorktreeCommonDir validates the worktree back-pointer and layout; a submodule, separate git dir, or forged gitfile stays at the directory that holds the file. The containment check plus the root/home/shallow-ancestor gates reject every broader scope. Lift the duplicated canonicalisation and containment helpers into internal/pathutil. Signed-off-by: Sajjad Ahmad <sajjad.ahmad@tngtech.com>
Three related defects in the mid-session watch: - A broken prefs.yaml was silently replaced with an empty store, dropping every stored preference on the next save. Keep the load error, run the watch with an in-memory-only store, and record one notice. - "Ignore all" rewrote prefs.yaml once per path. Add AddProtectedWatchIgnores, which appends the missing paths and saves once. - Exact-path matching used filepath.Clean, so a symlinked spelling re-prompted. Canonicalise both sides through pathutil. Also document that w.ignored is owned by the watch goroutine, use slices.DeleteFunc so removePath/removePaths stop writing through the caller's slice header, note the scan pause in askExceptions, and show "(8 listed)" when the batch covers more files than the dialog lists. Signed-off-by: Sajjad Ahmad <sajjad.ahmad@tngtech.com>
The protected-file dialog can offer fourteen long options. The generic zenity/kdialog path passed no width or height, so the batch and project choices could land below the fold. Pass dialogDimensions() into both backends, add --no-markup to zenity, and stop Pango-escaping the plain-text kdialog labels. An option that contains &, <, or > now returns the same string the caller looks up. Delete the unused Choose helper and its duplicated five-minute timeout; ChooseContext already has a caller-owned context. Signed-off-by: Sajjad Ahmad <sajjad.ahmad@tngtech.com>
The design and tasks still described the rev-parse invocation that trusted core.worktree. Rewrite the resolution section around the filesystem walk: a .git directory roots at its parent, a validated linked worktree at the main repository, and anything else at the directory holding the .git file. State that core.worktree is ignored and that the filesystem root, $HOME, and too-shallow ancestors are refused. Also correct the dialog wording: "Ignore all N" covers every file in the batch (showing "(8 listed)"), --verbose lists the warnings the user kept, and the 10-second scan pauses while a dialog is open. Signed-off-by: Sajjad Ahmad <sajjad.ahmad@tngtech.com>
The depth gate refused a strict ancestor with fewer than two path components. That hit legitimate layouts such as /repo or /app: the main checkout got the project option, its worktree did not, even though both resolve to the same git root. Discovery already anchors the root at the directory that owns .git, so the depth heuristic only added a false negative. Keep the two concrete refusals, / and $HOME. Signed-off-by: Sajjad Ahmad <sajjad.ahmad@tngtech.com>
"Keep warning" read like "warn me again soon", but the watch reports each path once per session. The choice saves no exception and keeps the file in the audit log and the session-end report. Label it "Keep warning for N files (report at exit)" and say in the body and docs what keeping it means. Signed-off-by: Sajjad Ahmad <sajjad.ahmad@tngtech.com>
NoRiceToday
force-pushed
the
NoRiceToday/Reduce-protected-file-noise
branch
from
October 29, 2026 14:02
df3b043 to
6f84638
Compare
This branch has not been deployed
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.
Issue: Closes #438
What
Why
Creating a worktree can generate a burst of protected-pattern files such as
.envand.env.local. omac cannot tell whether they are local defaults or real secrets, so it warns. The old watch produced one popup per file; an exact path does not cover the next worktree, and a global basename exception would silence that name in every project. A project-scoped exception is the narrowest scope that covers future worktrees of the same repository.How
.gitentry; a validated linked worktree maps to the main repository.core.worktreeis never read.{root, name}in~/.config/omac/prefs.yaml; match only below the canonical root./and$HOMEas roots. Non-git projects and worktrees outside the repository keep exact-path and batch choices.Diagram
flowchart TD W[workdir] --> G{first .git entry} G -- directory --> R[parent = repo root] G -- file --> V{validated linked worktree?} V -- yes --> M[parent of common dir = main repo] V -- no --> L[directory holding .git = repo root] R --> C{contains workdir and<br/>not / or $HOME?} M --> C L --> C C -- yes --> P[project option offered] C -- no --> N[no project option]Verification
go build ./...— passgo vet ./internal/cli ./internal/prefs ./internal/netprompt ./internal/sandboxrun— passgo test ./internal/prefs ./internal/netprompt ./internal/pathutil— passgo test -race ./internal/cli -run 'Protected|GitProjectRoot|PathUnder|AskExceptions'— passgo test ./internal/sandboxrun -run 'Worktree|Grant' -skip 'Integration'— passinternal/clistill fails only on pre-existing sandbox limits (/tmp,~/.config/omac).Follow-up
Revoking a project exception still means editing
prefs.yaml.