@massu/core init --ci no longer rolls back on fresh monorepo installs (turbo, nx, pnpm workspaces, lerna, rush, generic). Fixes the 2026-04-20 monorepo paths.source rollback regression.
Fixed
@massu/core init --cion monorepos:paths.sourceis now resolved from the repo's monorepo layout when the primary language has no root-level source directory. Previously, a fresh turbo +apps/web/page.tsxrepo (notypescriptdep, notsconfig.json, no rootsrc/) would generatepaths.source: 'src', fail post-write validation, and roll back withpaths.source 'src' does not exist on disk. The fix extendsbuildConfigFromDetection(packages/core/src/commands/init.ts) and the v1→v2 migration path (packages/core/src/detect/migrate.ts) with a monorepo-aware fallback: when the dominant source dir is empty ANDdetection.monorepo.type !== 'single',paths.sourceis set to the common top-level parent of every workspace package (apps,packages,libs, etc.), or'.'when packages span multiple parents.- Source-dir detection for plain-JS monorepos:
EXTENSIONS.javascript(packages/core/src/detect/source-dir-detector.ts) is now extended with['ts', 'tsx']via a newfallbackTsForJsflag when the repo has ajavascriptmanifest but NOtypescriptmanifest. This surfaces.tsxfiles underapps/*in plain-JS turbo repos (e.g.next+reactin apackage.jsonwithouttypescript+ notsconfig.json), which the prior strict javascript glob skipped entirely.
Added
paths.monorepo_roots: string[]— new optional config field emitted byinit --ciandconfig refresh/upgradewhenevermonorepo.type !== 'single'and workspace packages exist. Lists every distinct top-level workspace parent (e.g.['apps', 'libs']for an nx repo with both). Additive, schema-compatible with v1 configs; downstream tools may consume it for monorepo-aware scanning.- Post-write validation extended (
validateWrittenConfig) — new check that each entry inpaths.monorepo_rootsexists on disk. Parity with the existingpaths.sourceexistence check; rolls back on mismatch with messagepaths.monorepo_roots '<x>' does not exist on disk. - 3 new fresh-install fixtures (
packages/core/src/tests/fixtures/fresh-install/):nx-monorepo(apps + libs via yarn workspaces),pnpm-workspaces(pnpm + packages/*),rush-monorepo(rush + apps/). Covers every major JS monorepo shape forinit --ciregression gating. .github/workflows/fresh-install-matrix.yml— new CI matrix (6 fixtures × node:20) that runsinit --ciend-to-end on every push/PR to main. Gates merges on: exit 0,schema_version: 2emitted,paths.sourceexisting on disk, andpaths.monorepo_rootsemitted for every monorepo shape. PR runs use the local build; main-branch runs additionally verify against the last published@massu/core@1as drift protection.
Deprecated
- Legacy
generateConfigincommands/init.ts— emits a console deprecation warning on invocation. It hardcodespaths.source = 'src'and cannot resolve monorepo layouts. UsebuildConfigFromDetection(runDetection(root))instead. Kept only for the legacycli.test.tssmoke tests.
Tests
- +16 tests covering the P1 detector changes (fallbackTsForJs flag, runDetection wiring, monorepo-aware
paths.source, monorepo_roots emission), the P2 validator extension, and the P4.8 security pre-screen (IGNORE_PATTERNS + symlink-safety regressions). - Total test count: 1373 passing (was 1357 on 1.2.0).
Design notes
paths.sourceremains astring(not an array). Every live consumer inpackages/core/src/reads it as a string (config.ts:590,sentinel-scanner.ts:223,domains.ts:106/157,python/coupling-detector.ts:23,trpc-index.ts:115) — widening to an array would break all six sites silently. Monorepo multi-source precision is instead available viaframework.languages.<lang>.source_dirs(existing) and the newpaths.monorepo_roots(optional).- JS-to-TS language reclassification (when the only manifest is a plain-JS
package.jsonbut.tsxfiles are present) is NOT done in 1.2.1 — it's a classification change with its own blast radius (framework-detector rules, VR commands, schema version). Tracked as P6-001 for a future release.