Resolves #12147
Authored by Claude Opus 4.7 (Claude Code). Session efd8dc2e-2052-4089-814a-ab22cd8c6a62.
FAIR-band: operator-directed quick-win — surfaced and greenlit by @tobiu during #12145; FAIR-band self-selection is N/A for directed work.
Evidence: L2 (unit-tested helper resolves <root>/ai/scripts/migrations → <root> + a regression guard; 35/35 bootstrapWorktree spec passing) → L2 sufficient (pure path-math fix, fully unit-covered). A post-merge L3 CLI run is optional confirmation.
Summary
The isMain CLI block computed path.resolve(__dirname, '..', '..'), but the script lives at ai/scripts/migrations/ (3 levels deep) — two .. climbs only to <root>/ai, not the repo root. Config copies then landed in <root>/ai/ai/, the real ai/config.mjs never materialized, and worktree bootstrap left every ai/services.mjs consumer at ERR_MODULE_NOT_FOUND. The comment ("ai/scripts/ → ai/ → root") was stale from before the file moved into migrations/.
- Extract
resolveCliProjectRoot(moduleDir) (three ..), exported so the CLI projectRoot computation is unit-testable.
isMain uses the helper; corrected the stale comment.
- Spec asserts the helper resolves to root + a regression guard for the prior 2-level mislanding.
Deltas from ticket (if any)
None — implementation matches the ticket's prescription (extract + correct + test).
Test Evidence
npm run test-unit -- test/playwright/unit/ai/scripts/migrations/bootstrapWorktree.spec.mjs → 35/35 passing, including the new resolveCliProjectRoot case.
Post-Merge Validation
Commits
d7f19c07d — resolveCliProjectRoot helper + corrected level count + spec coverage
Resolves #12147
Authored by Claude Opus 4.7 (Claude Code). Session efd8dc2e-2052-4089-814a-ab22cd8c6a62.
FAIR-band: operator-directed quick-win — surfaced and greenlit by @tobiu during #12145; FAIR-band self-selection is N/A for directed work.
Evidence: L2 (unit-tested helper resolves
<root>/ai/scripts/migrations→<root>+ a regression guard; 35/35 bootstrapWorktree spec passing) → L2 sufficient (pure path-math fix, fully unit-covered). A post-merge L3 CLI run is optional confirmation.Summary
The
isMainCLI block computedpath.resolve(__dirname, '..', '..'), but the script lives atai/scripts/migrations/(3 levels deep) — two..climbs only to<root>/ai, not the repo root. Config copies then landed in<root>/ai/ai/, the realai/config.mjsnever materialized, and worktree bootstrap left everyai/services.mjsconsumer atERR_MODULE_NOT_FOUND. The comment ("ai/scripts/ → ai/ → root") was stale from before the file moved intomigrations/.resolveCliProjectRoot(moduleDir)(three..), exported so the CLIprojectRootcomputation is unit-testable.isMainuses the helper; corrected the stale comment.Deltas from ticket (if any)
None — implementation matches the ticket's prescription (extract + correct + test).
Test Evidence
npm run test-unit -- test/playwright/unit/ai/scripts/migrations/bootstrapWorktree.spec.mjs→ 35/35 passing, including the newresolveCliProjectRootcase.Post-Merge Validation
node ai/scripts/migrations/bootstrapWorktree.mjsin a fresh worktree hydratesconfig.mjsfiles at the repo root (noai/ai/stray).Commits
d7f19c07d—resolveCliProjectRoothelper + corrected level count + spec coverage