fix: disambiguate project profiles that share a directory basename (#74)
CI / Lint (ruff) (pull_request) Successful in 12s
CI / Tests (py3.12 / windows-latest) (pull_request) Successful in 22s
CI / Tests (py3.10 / ubuntu-latest) (pull_request) Successful in 19s
CI / Tests (py3.12 / ubuntu-latest) (pull_request) Successful in 19s
CI / Tests (py3.13 / ubuntu-latest) (pull_request) Successful in 19s
CI / Catalog signature (pull_request) Successful in 11s
CI / Lint (ruff) (pull_request) Successful in 12s
CI / Tests (py3.12 / windows-latest) (pull_request) Successful in 22s
CI / Tests (py3.10 / ubuntu-latest) (pull_request) Successful in 19s
CI / Tests (py3.12 / ubuntu-latest) (pull_request) Successful in 19s
CI / Tests (py3.13 / ubuntu-latest) (pull_request) Successful in 19s
CI / Catalog signature (pull_request) Successful in 11s
discover_project_configs labelled every project by basename alone, so
~/work/app/.mcp.json and ~/personal/app/.mcp.json both read as
"Project: app". Paths dedupe correctly, so both profiles existed -- they
were just indistinguishable in the picker, and picking the wrong one meant
editing, backing up, and writing the wrong repo's config. api/web/app/
server/client as repo names make this common.
- disambiguate_project_labels(dirs): pure, testable. Labels stay
"Project: <name>" until a basename collides, then only the colliding
ones widen toward the root one component at a time
("Project: work/app" vs "Project: personal/app"), widening further if the
parent also collides. The common no-collision case is unchanged.
- Full path goes in the combo item's ToolTipRole, so a profile is always
verifiable by hover regardless of label.
- Tightened the "is this a project config?" check: the docstring claimed a
top-level object but the code only checked is_file(), so a .mcp.json that
was a JSON array or garbage still became a profile and only failed on
open. It now must parse (strict) to a dict, else it's skipped.
Tests: +6 (no-collision basename, colliding widen, deeper widen, and
discover_project_configs disambiguation + skipping array/garbage/missing).
463 passed, ruff clean.
Closes #74
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKwBecy6N83jnqQmw8ezwE
This commit is contained in:
@@ -2043,6 +2043,11 @@ class MainWindow(QMainWindow):
|
||||
for p in self.profiles:
|
||||
tag = "" if p.config_exists else " (no config yet)"
|
||||
self.profile_combo.addItem(f"{p.label}{tag}")
|
||||
# Full path in the tooltip so a profile is always verifiable even
|
||||
# when two labels look alike (e.g. two repos both named "app").
|
||||
self.profile_combo.setItemData(
|
||||
self.profile_combo.count() - 1, str(p.path), Qt.ItemDataRole.ToolTipRole
|
||||
)
|
||||
self.profile_combo.blockSignals(False)
|
||||
if self.profiles:
|
||||
self.profile_combo.setCurrentIndex(0)
|
||||
|
||||
Reference in New Issue
Block a user