fix: address maintainer review — gate findProjectRoot, warn on unmatched files
1. Gate findProjectRoot to commands that access .planning/ — skip for pure-utility commands (generate-slug, current-timestamp, template, frontmatter, verify-path-exists, verify-summary) to avoid unnecessary filesystem traversal on every invocation. 2. Warn to stderr when commit-to-subrepo encounters files that don't match any configured sub-repo prefix. 3. Document that loadConfig auto-syncs sub_repos with the filesystem, so config.json may be rewritten when repos are added or removed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -181,10 +181,6 @@ async function main() {
|
||||
cwd = worktreeRoot;
|
||||
}
|
||||
|
||||
// Multi-repo guard: if CWD is inside a sub-repo, walk up to the project root
|
||||
// so .planning/ is read/written at the correct level.
|
||||
cwd = findProjectRoot(cwd);
|
||||
|
||||
const rawIndex = args.indexOf('--raw');
|
||||
const raw = rawIndex !== -1;
|
||||
if (rawIndex !== -1) args.splice(rawIndex, 1);
|
||||
@@ -195,6 +191,17 @@ async function main() {
|
||||
error('Usage: gsd-tools <command> [args] [--raw] [--cwd <path>]\nCommands: state, resolve-model, find-phase, commit, verify-summary, verify, frontmatter, template, generate-slug, current-timestamp, list-todos, verify-path-exists, config-ensure-section, init');
|
||||
}
|
||||
|
||||
// Multi-repo guard: resolve project root for commands that read/write .planning/.
|
||||
// Skip for pure-utility commands that don't touch .planning/ to avoid unnecessary
|
||||
// filesystem traversal on every invocation.
|
||||
const SKIP_ROOT_RESOLUTION = new Set([
|
||||
'generate-slug', 'current-timestamp', 'verify-path-exists',
|
||||
'verify-summary', 'template', 'frontmatter',
|
||||
]);
|
||||
if (!SKIP_ROOT_RESOLUTION.has(command)) {
|
||||
cwd = findProjectRoot(cwd);
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case 'state': {
|
||||
const subcommand = args[1];
|
||||
|
||||
@@ -298,6 +298,10 @@ function cmdCommitToSubrepo(cwd, message, files, raw) {
|
||||
}
|
||||
}
|
||||
|
||||
if (unmatched.length > 0) {
|
||||
process.stderr.write(`Warning: ${unmatched.length} file(s) did not match any sub-repo prefix: ${unmatched.join(', ')}\n`);
|
||||
}
|
||||
|
||||
const repos = {};
|
||||
for (const [repo, repoFiles] of Object.entries(grouped)) {
|
||||
const repoCwd = path.join(cwd, repo);
|
||||
|
||||
@@ -274,7 +274,7 @@ Set `commit_docs: false` so planning docs stay local and are not committed to an
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Auto-detection:** During `/gsd:new-project`, directories with their own `.git` folder are detected and offered for selection as sub-repos.
|
||||
1. **Auto-detection:** During `/gsd:new-project`, directories with their own `.git` folder are detected and offered for selection as sub-repos. On subsequent runs, `loadConfig` auto-syncs the `sub_repos` list with the filesystem — adding newly created repos and removing deleted ones. This means `config.json` may be rewritten automatically when repos change on disk.
|
||||
2. **File grouping:** Code files are grouped by their sub-repo prefix (e.g., `backend/src/api/users.ts` belongs to the `backend/` repo).
|
||||
3. **Independent commits:** Each sub-repo receives its own atomic commit via `gsd-tools.cjs commit-to-subrepo`. File paths are made relative to the sub-repo root before staging.
|
||||
4. **Planning stays local:** The `.planning/` directory is not committed; it acts as cross-repo coordination.
|
||||
|
||||
Reference in New Issue
Block a user