Skip to content

feat(cli): detect project roots across ecosystems, not just Node - #214

Open
ophiocus wants to merge 1 commit into
theam:mainfrom
ophiocus:feat/multi-root-stack-detection
Open

feat(cli): detect project roots across ecosystems, not just Node#214
ophiocus wants to merge 1 commit into
theam:mainfrom
ophiocus:feat/multi-root-stack-detection

Conversation

@ophiocus

Copy link
Copy Markdown
Contributor

Closes #199 — and big thanks to @AndreyGritsa, whose nine-Poetry-roots-plus-Next.js layout from the issue thread is now a test case in this PR. That fixture reshaped the design: the fix isn't an adapter table alone, it's multi-root, multi-ecosystem detection, because a repository with no root package.json and independent Python packages beside a frontend was previously invisible to init.

What changed

packages/cli/src/detect.mjs:

  • Ecosystem adapter table — Node, Python (Poetry/uv/PDM/Hatch/pip), PHP (Composer), Go, Ruby, Rust, Java (Maven/Gradle). Same shape as detectDeploymentProvider: adding an ecosystem is one entry, not a branch. Each adapter only proposes tools the project actually configures (ruff/mypy/pytest from pyproject.toml, phpunit/pest from the files present, and so on).
  • Multi-root walk (depth ≤ 3) — every project root is discovered and kept. Checks are unioned and root-scoped — (cd scraper && poetry run pytest) — so a change anywhere in the repository has a gate. Provisioning is per root (poetry install in the touched package), not one repo-wide install, which a layout like Andrey's can't express.
  • Workspace absorption — pnpm/npm/Cargo workspace members (and packages nested below them, e.g. runner/agent-clis) are absorbed into their workspace root, whose scripts already fan out to them. This is what keeps existing Node repositories detecting identically to before.
  • Fixture/sample directories are never rootstest/, fixtures/, samples/, examples/ hold manifests on purpose; proposing their checks as repository defaults would be noise (found by running the new detection against claude-dev-kit, where samples/php volunteered its phpunit as a repo default).
  • test:run fallback when test is absent — the watch-free vitest convention, and literally the script name in the frontend from the issue thread.

detect() also returns two new advisory fields, ecosystems and roots (path/ecosystem/manager), which init can surface in its summary; existing consumers are untouched.

apps/docs/docs/faq.md: the "Does this work for non-Node projects?" answer now describes what detection actually does instead of promising only a marked slot.

How it's verified

  • New packages/cli/test/detect.test.mjs, 5 cases: single-root npm unchanged; pnpm workspace absorption incl. the nested-member case; the polyglot no-root-manifest monorepo from Stack detection covers only the Node ecosystem — every other stack starts on an empty job site #199; PHP + Go roots with migration discovery; fixture/sample dirs never become roots.
  • Full CLI suite: 103 tests, 0 failures (98 before this PR — the five are new).
  • Backward-compatibility proof, not just tests: ran main's detect() and this branch's detect() against facility's own checkout — every shared output field is identical, byte for byte. CDK's real tree confirms the fixture-skip.

@AndreyGritsa — your offer to validate against the real monorepo stands very welcome: this should now discover all nine Poetry roots plus frontend/, propose poetry install per touched package, and union poetry run pytest with npm run test:run. I'd love to hear where it guesses wrong.

`init` proposed checks and provisioning only for a repository-root Node
project; anything else — a Poetry monorepo, a PHP service beside a Go
worker — started on exactly the empty job site the method doc warns
about. Detection now walks the tree for project roots (Node, Python,
PHP, Go, Ruby, Rust, Java), absorbs workspace members into their
workspace root, skips fixture/sample directories, and proposes per-root
provisioning plus a union of root-scoped checks. Node workspace
repositories detect identically to before.

Closes theam#199

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

Stack detection covers only the Node ecosystem — every other stack starts on an empty job site

1 participant