fix: Windows shell robustness, project_root detection, and hook stdin safety (#1343)
Address 4 root causes of Windows + Claude Code reliability issues:
1. Workflow shell robustness: add || true guards to informational commands
(ls, grep, find, cat) that return non-zero on "no results", preventing
workflow step failures under strict execution models. Guard glob loops
with [ -e "$var" ] || continue to handle empty glob expansion.
2. Hook stdin handling: replace readFileSync('/dev/stdin') with async
process.stdin + timeout in agent templates (gsd-verifier.md). Existing
JS hooks already have timeout guards.
3. project_root detection: fix isInsideGitRepo() to check .git at the
candidate parent level (not just below it), enabling correct detection
when .git and .planning/ are siblings at the same directory level —
the common single-repo case from a subdirectory.
4. @file: handoff: add missing @file: handlers to autonomous.md and
manager.md workflows that call gsd-tools init but lacked the handler
for large output payloads.
Fixes #1343
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1477,6 +1477,38 @@ describe('findProjectRoot', () => {
|
||||
|
||||
assert.strictEqual(findProjectRoot(backendDir), backendDir);
|
||||
});
|
||||
|
||||
test('walks up from subdirectory when .git is at same level as .planning/ (single-repo)', () => {
|
||||
// Common single-repo layout: .git and .planning are siblings at project root
|
||||
fs.mkdirSync(path.join(projectRoot, '.planning'), { recursive: true });
|
||||
fs.mkdirSync(path.join(projectRoot, '.git'), { recursive: true });
|
||||
|
||||
// User cwd is a subdirectory (e.g., src/)
|
||||
const srcDir = path.join(projectRoot, 'src');
|
||||
fs.mkdirSync(srcDir, { recursive: true });
|
||||
|
||||
// Should detect that parent has .planning/ and .git is at that same level
|
||||
assert.strictEqual(findProjectRoot(srcDir), projectRoot);
|
||||
});
|
||||
|
||||
test('walks up from deep subdirectory when .git is at same level as .planning/', () => {
|
||||
// Single-repo: .git and .planning at root, cwd deep inside
|
||||
fs.mkdirSync(path.join(projectRoot, '.planning'), { recursive: true });
|
||||
fs.mkdirSync(path.join(projectRoot, '.git'), { recursive: true });
|
||||
|
||||
const deepDir = path.join(projectRoot, 'src', 'lib', 'utils');
|
||||
fs.mkdirSync(deepDir, { recursive: true });
|
||||
|
||||
assert.strictEqual(findProjectRoot(deepDir), projectRoot);
|
||||
});
|
||||
|
||||
test('returns startDir when .planning exists at same level (cwd is project root)', () => {
|
||||
// User is already at project root — no parent to walk up to
|
||||
fs.mkdirSync(path.join(projectRoot, '.planning'), { recursive: true });
|
||||
fs.mkdirSync(path.join(projectRoot, '.git'), { recursive: true });
|
||||
|
||||
assert.strictEqual(findProjectRoot(projectRoot), projectRoot);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── reapStaleTempFiles ─────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user