Skip to content

fix: resolve project root from caller cwd git toplevel, not script anchor (#328)#329

Merged
azalio merged 1 commit into
mainfrom
claude/compassionate-cerf-2eej6h
Jul 4, 2026
Merged

fix: resolve project root from caller cwd git toplevel, not script anchor (#328)#329
azalio merged 1 commit into
mainfrom
claude/compassionate-cerf-2eej6h

Conversation

@azalio

@azalio azalio commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #328.

map_orchestrator.py's main() previously anchored cwd exclusively to Path(__file__).resolve().parents[2]. When invoked via an absolute path from a git worktree that lacks its own .map/scripts/ copy, this silently changed directory to the main clone's root — causing get_branch_name() to return the wrong branch and all .map/<branch>/ reads/writes to operate on an unrelated workflow.

Root cause

# OLD — always uses the script file's location, ignores caller's cwd
script_anchored_root = Path(__file__).resolve().parents[2]
os.chdir(script_anchored_root)

Fix

New resolution priority (highest first):

  1. CLAUDE_PROJECT_DIR env var (explicit operator intent)
  2. git -C <caller_cwd> rev-parse --show-toplevel — uses the caller's actual cwd so a worktree invocation anchors to the worktree root, not the main clone
  3. Path(__file__).resolve().parents[2] — script-anchored fallback when caller's cwd is not a git repo (preserves the old non-worktree behaviour)

Emits an INFO message to stderr when the resolved root differs from the script anchor so cross-checkout usage is auditable but non-fatal.

Tests

Two new regression tests added to TestCwdIndependence:

  • test_claude_project_dir_takes_priority_over_script_anchorCLAUDE_PROJECT_DIR wins over the script-anchored root
  • test_git_toplevel_from_caller_cwd_takes_priority_over_script_anchor — git toplevel from the caller's cwd wins when CLAUDE_PROJECT_DIR is unset (the worktree scenario from the issue)

All 3 existing TestCwdIndependence tests continue to pass: they use a non-git project_b, so git resolution fails and the code correctly falls back to the script-anchored root.


Generated by Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved project root detection so the tool now starts from the correct directory more reliably, including git worktrees and custom project paths.
    • The working directory is now set based on the resolved project root before state lookup, reducing path-related errors.
    • Added clearer informational output when the resolved root differs from the script location.
  • Tests

    • Added coverage for project-root precedence and working-directory independence in subprocess-based scenarios.

…chor (#328)

map_orchestrator.py's main() previously anchored cwd exclusively to
Path(__file__).resolve().parents[2], which silently operates on the
main clone when invoked via absolute path from a git worktree that
lacks its own .map/scripts/ copy.

New resolution priority (highest first):
  1. CLAUDE_PROJECT_DIR env var (explicit operator intent)
  2. git rev-parse --show-toplevel from the caller's cwd (handles
     git worktrees: the worktree root is correct, not the main clone)
  3. Path(__file__).resolve().parents[2] — script-anchored fallback
     (legacy behaviour when caller's cwd is not a git repo)

Emits an INFO message to stderr when the resolved root differs from
the script anchor so cross-checkout usage is auditable but not fatal.

Tests added (TestCwdIndependence):
- test_claude_project_dir_takes_priority_over_script_anchor
- test_git_toplevel_from_caller_cwd_takes_priority_over_script_anchor
Existing three tests still pass (non-git caller cwd → falls back to
script-anchored root, preserving the prior-fix behaviour).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015J78vXZPNJcBCwUKYHVEWi
@azalio azalio merged commit 557de04 into main Jul 4, 2026
1 of 2 checks passed
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dbe34526-7f7f-483a-925b-7b3ac7422364

📥 Commits

Reviewing files that changed from the base of the PR and between 228b0d0 and d5783b4.

📒 Files selected for processing (4)
  • .map/scripts/map_orchestrator.py
  • src/mapify_cli/templates/map/scripts/map_orchestrator.py
  • src/mapify_cli/templates_src/map/scripts/map_orchestrator.py.jinja
  • tests/test_map_orchestrator.py

📝 Walkthrough

Walkthrough

Project root resolution in map_orchestrator.py's main() was reworked across three parallel copies (deployed script, templates package, jinja template). Instead of always chdir'ing to the script-anchored root, root is now resolved via CLAUDE_PROJECT_DIR, then git rev-parse --show-toplevel from the caller's cwd, then script fallback, with logging on mismatch. Two subprocess integration tests were added.

Changes

Project root resolution fix

Layer / File(s) Summary
Root resolution logic across orchestrator copies
.map/scripts/map_orchestrator.py, src/mapify_cli/templates/map/scripts/map_orchestrator.py, src/mapify_cli/templates_src/map/scripts/map_orchestrator.py.jinja
main() now resolves project_root by priority: CLAUDE_PROJECT_DIR (if a valid directory), then git rev-parse --show-toplevel from the caller's cwd (worktree-aware), then script-anchored fallback; chdir's to it and logs an info message when it differs from the script root, replacing the prior unconditional script-anchored chdir with mismatch warning.
Precedence tests for root resolution
tests/test_map_orchestrator.py
Adds import os and two subprocess integration tests in TestCwdIndependence verifying CLAUDE_PROJECT_DIR precedence and git-toplevel precedence over the script anchor when resolving get_next_step.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

Poem

A rabbit hopped through worktrees deep,
Chasing roots the script once misplaced asleep. 🐇
Now CLAUDE_PROJECT_DIR leads the way,
Or git's toplevel shows where to stay,
Chdir true, no more confusion to keep!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/compassionate-cerf-2eej6h

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.

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.

map_orchestrator.py file-anchored chdir breaks branch/state resolution when invoked by absolute path from another checkout (git worktrees)

2 participants