Skip to content
v1.2.1April 20, 2026

`@massu/core init --ci` no longer rolls back on fresh monorepo installs (turbo, nx, pnpm workspaces, lerna, rush, generic).

`@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.

@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 --ci on monorepos: paths.source is 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.tsx repo (no typescript dep, no tsconfig.json, no root src/) would generate paths.source: 'src', fail post-write validation, and roll back with paths.source 'src' does not exist on disk. The fix extends buildConfigFromDetection (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 AND detection.monorepo.type !== 'single', paths.source is 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 new fallbackTsForJs flag when the repo has a javascript manifest but NO typescript manifest. This surfaces .tsx files under apps/* in plain-JS turbo repos (e.g. next + react in a package.json without typescript + no tsconfig.json), which the prior strict javascript glob skipped entirely.

Added

  • paths.monorepo_roots: string[] — new optional config field emitted by init --ci and config refresh/upgrade whenever monorepo.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 in paths.monorepo_roots exists on disk. Parity with the existing paths.source existence check; rolls back on mismatch with message paths.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 for init --ci regression gating.
  • .github/workflows/fresh-install-matrix.yml — new CI matrix (6 fixtures × node:20) that runs init --ci end-to-end on every push/PR to main. Gates merges on: exit 0, schema_version: 2 emitted, paths.source existing on disk, and paths.monorepo_roots emitted for every monorepo shape. PR runs use the local build; main-branch runs additionally verify against the last published @massu/core@1 as drift protection.

Deprecated

  • Legacy generateConfig in commands/init.ts — emits a console deprecation warning on invocation. It hardcodes paths.source = 'src' and cannot resolve monorepo layouts. Use buildConfigFromDetection(runDetection(root)) instead. Kept only for the legacy cli.test.ts smoke 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.source remains a string (not an array). Every live consumer in packages/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 via framework.languages.<lang>.source_dirs (existing) and the new paths.monorepo_roots (optional).
  • JS-to-TS language reclassification (when the only manifest is a plain-JS package.json but .tsx files 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.

Try this release

Install the latest version of Massu and start governing your AI development today.