feat: first-class monorepo support (detection, per-workspace attribution, dependency graph)#9
Merged
Merged
Conversation
detectWorkspaces moves to src/detect/workspaces.ts (re-exported from stack.ts for compatibility) and gains: a kind tag per workspace (npm, pnpm, lerna, nx, cargo, go), pnpm negation patterns, lerna.json / nx.json membership fallbacks when package.json declares none, Cargo [workspace] members/exclude, and go.work use directives. Polyglot monorepos union all ecosystems. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
buildWorkspaceGraph fills each workspace's dependsOn from manifest declarations — package.json deps matching sibling names, Cargo name or path dependencies, go.mod require/replace of sibling modules — and topoOrderWorkspaces returns a deps-first order (Kahn, deterministic path-order fallback on cycles). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Each detected workspace now carries its own stack (detected from its rebased files and manifests), its own dependency manifests, its file and route counts, its schema files, and the global hints filtered to its subtree; routes are tagged in place with their workspace. Workspace stacks are detected before route detection and their frameworks merged into the global stack — previously a monorepo whose root manifest didn't declare the app framework (the normal case) never activated the route adapters, so workspace apps had no routes at all. The monorepo fixture gains real Next.js routes to lock this in. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
buildFeatures gains an optional workspaces parameter: in a monorepo an
app workspace (it owns routes) splits into per-area sub-features named
'Web · Dashboard' (slug web-dashboard), a library workspace collapses
into a single feature ('UI (@acme/ui)'), and every workspace group is
rank-offset by its topological position so shared packages always
build before the apps that consume them. Trivial app groups fold into
that app's own core; the no-workspaces path is byte-identical to the
previous behavior.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ARCHITECTURE.md gains a ## Workspaces table (workspace, path, kind, stack, depends-on, routes) with an agent note to verify roles and extend the graph with implicit edges; diagram.md gains a second mermaid graph of the manifest-declared workspace edges; REBUILD.md states that the outer build tier is the workspace topological order; SUMMARY.md lists each workspace with its edges. All sections are absent for single-package repos. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two new fixtures lock the non-JS workspace paths end to end: a Rust cargo workspace (glob members, exclude, a path dependency edge) and a go.work monorepo (block-form use, module naming from go.mod, a require/replace edge), each asserting per-workspace stack attribution and shared-package-first build order. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SKILL.md step 3 now describes the per-workspace inventory fields and the on-the-fly fallback (the agent identifies workspaces itself and scopes re-runs with --include when detection misses an unconventional layout); the playbook's §Monorepo shifts the agent's job to verifying roles and extending the graph with implicit edges; a new references/stack-guides/monorepo.md covers the supported systems, per-workspace analysis, shared-package PRD pattern, and pitfalls; README and DOCUMENTATION document the enriched workspaces schema. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
github-actions Bot
pushed a commit
that referenced
this pull request
Jun 10, 2026
# [0.11.0](v0.10.2...v0.11.0) (2026-06-10) ### Features * first-class monorepo support (detection, per-workspace attribution, dependency graph) ([#9](#9)) ([31f49c1](31f49c1))
|
🎉 This PR is included in version 0.11.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Workspaces were only detected (npm/yarn/pnpm) and surfaced as metadata — the whole pipeline ran globally on the repo, so a monorepo's inventory was misleading: one merged
StackInfo, routes from several apps mixed together, a flat feature list, and dependencies read only from the root manifest. The playbook just told the agent to re-scope manually.This PR makes monorepo support first-class: broader detection, per-workspace attribution, an inter-workspace dependency graph, features grouped by workspace, while keeping a single output tree. Single-package repos are byte-identical to before.
What's in it (7 commits, one per step)
src/detect/workspaces.ts, new module) — npm/yarn/pnpm (incl. pnpm!negation patterns),lerna.json/nx.jsonfallbacks, Cargo[workspace]members/exclude,go.workusedirectives; polyglot union. Each workspace carries akind.dependsOnfrom manifests (npm names, Cargopath/name deps, go.modrequire/replace) +topoOrderWorkspaces(Kahn, deterministic fallback on cycles).inventory.workspaces[*]carries its ownstack,dependencies,fileCount/routeCount,schemas, and filteredhints; routes are tagged with their workspace. Workspace stacks are detected before routes and merged into the global stack — otherwise a monorepo whose root manifest doesn't declare the app framework (the normal case) never activated the route adapters.web-dashboard-style sub-features; library workspaces collapse into one feature each; rank-offset by topological position so shared packages build before the apps that consume them.## Workspacestable in ARCHITECTURE.md, a second mermaid graph in diagram.md, the topo-order blurb in REBUILD.md, workspaces + edges in SUMMARY.md and the CLI log. All absent for single-package repos.cargo-workspaceandgo-workfixtures, tested end to end.references/stack-guides/monorepo.md(incl. the on-the-fly fallback: the agent identifies workspaces itself and scopes re-runs with--includewhen detection misses an unconventional layout), README + DOCUMENTATION.Known limitation (out of scope, noted in the guide)
The Next.js adapter only recognizes
apps/*/packages/*prefixes — a workspace atservices/webwon't get its routes resolved deterministically. A follow-up could thread detected workspace paths intodetectRoutes.Verification
pnpm run typecheck✓pnpm test— 326 passed (was 296) ✓pnpm run check:build— bundle regenerated & committed ✓pnpm run parity— PASS ✓pnpm run demo— sample-app output unchanged (single-package invariance) ✓🤖 Generated with Claude Code