Commit Graph

2 Commits

Author SHA1 Message Date
Tom Boucher
ba3181204b fix(#1422,#1447): fix sub_repos/.git precedence; guard uncommitted data in new-milestone (#1484)
* fix(#1422): sub_repos config takes precedence over .git in findProjectRoot

When heuristic-3 (.git + parent .planning/) fires, do a lookahead walk
over ancestors above the matching parent to check if any further ancestor
has a sub_repos entry that explicitly claims the starting directory. If
found, return that ancestor instead — explicit config wins over the
implicit .git signal.

Regression tests updated: the heuristic-3 precedence test now asserts the
correct new behavior (sub_repos wins), and two additional coverage cases
added (startDir directly in sub_repo child, and startDir nested 2+ levels
inside the child).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(#1447): guard against uncommitted changes before deleting phase dirs in new-milestone

cmdPhasesClear now runs `git status --porcelain <phasesDir>` before
executing any rmSync. If uncommitted changes are detected it calls
error() and aborts, preventing silent data loss when new-milestone's
§6 "phases.clear --confirm" fires before the operator has archived
or committed outgoing phase work.

A new --force flag is added to bypass the guard for callers that have
already verified archival is done (or explicitly accept the loss).
When git is unavailable or the directory is not inside a git repo the
guard silently skips, preserving the existing behaviour for non-git
projects.

Five new regression tests cover: untracked files abort, staged-but-
uncommitted abort, --force bypasses, committed files pass, non-git
project passes without guard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: add changeset for #1422 and #1447

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: correct changeset format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 13:37:16 -04:00
Tom Boucher
d220ba6fd6 fix(#1414): resolve project root from descendant via nearest ancestor .planning/ (Resolution Provenance P1) (#1423)
Add heuristic (4) to findProjectRoot: after heuristics (1)-(3) (sub_repos,
multiRepo, .git+parent-.planning/) are exhausted without a match, perform a
second bounded walk-up within FIND_PROJECT_ROOT_MAX_DEPTH to locate the
nearest ancestor directory containing a .planning/ subdirectory. Returns that
ancestor as the project root, so loadConfig finds the correct config instead
of falling through to defaults when gsd-tools is invoked from a plain
descendant subdirectory of a single-repo project (#1366 cwd-drift gap).

Ordering is load-bearing: the new walk runs AFTER the existing loop so
sub_repos workspaces (where a child sub-repo may have its own .planning/)
still resolve correctly to the parent workspace. The existing own-.planning/
guard (heuristic 0, #1362) and the depth bound (FIND_PROJECT_ROOT_MAX_DEPTH=10)
are both preserved unchanged.

Part of #1411

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 00:50:30 -04:00