CLAUDE.md flagged this as "CRITICAL" — a child package.json defining
e.g. \`"build": "turbo run build"\` causes a 10+ minute CI hang with
thousands of duplicate task spawns. The rule was documented but never
enforced, so it re-emerged every couple of months as someone copied a
parent script pattern.
- \`scripts/validate-no-recursive-turbo.mjs\` walks every tracked
package.json (via \`git ls-files\`, so node_modules is auto-skipped)
and fails if any non-root package has build/type-check/lint/test/
test:coverage/check scripts containing \`turbo run\`. \`dev\` stays
allowed — delegating it from a parent is the intended ergonomic.
- Wired as \`pnpm run validate:turbo\` + a new CI step in the validate
job (before type-check — fails fast).
- CLAUDE.md §Turborepo updated to point at the enforcer and call out
the full task list (test/test:coverage/check were missing from the
original prose).
Verified: 138 non-root package.json files scan clean. Drift simulation
(injecting \`"build": "turbo run build"\` into apps/mana/apps/web) fails
with a clear message pointing at the offending file + script + fix.
This closes audit item #32 from the architecture review.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>