mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-20 21:46:41 +02:00
Citycorners-Reste vom vorherigen Sprint mit committet. food → Nutriphi,
wardrobe → Werdrobe sind als Standalone-Apps live; die mana.how-unified-
App trägt die Modul-Surfaces nicht mehr.
Gelöscht / abgebaut:
- Module: apps/mana/.../modules/{food,wardrobe} + Routen + Locales
- Landing-Apps: apps/{food,citycorners}/ Top-Level
- Backend: apps/api/src/modules/{food,wardrobe} + MCP-Tools log_meal /
nutrition_summary, picture-routes verifyMediaOwnership-Allowlist
- shared-branding: APP_BRANDING, APP_ICONS, MANA_APPS, Logos, Onboarding
- shared-ai, mana-tool-registry, credits, shared-types/spaces,
shared-utils/analytics, spiral-db/MANA_APP_INDEX, website-blocks
- Cross-Module: Body-CalorieWeightChart, Comic-CharacterPicker-Wardrobe,
website-Embed wardrobe.outfits, DaySnapshot.nutrition, FoodEventType,
MealLogged/Meal*-Streaks/Goals/Companion/Trigger, AI-Agent-Policy,
GoalEditor MealLogged, MyDay/RitualRunner/Rules nutrition-Refs,
Crypto-Registry meals/wardrobeGarments/wardrobeOutfits
- Generic: PlaceCategory 'food' (places + geocoding + Locales),
spaces.ts 'food'/'wardrobe' Modul-IDs
- Infrastruktur: cloudflared, docker-compose CORS, nginx-Landing,
prometheus-Probe, load-tests, package.json dev-Scripts,
generate-env, mac-mini/build-landings, dependabot
Dexie v62 Migration:
- droppt meals, goals, foodFavorites, mealTags, wardrobeGarments,
wardrobeOutfits Tabellen
- entfernt wardrobeOutfitId / wardrobeGarmentId aus images-Index
- Upgrade-Callback strippt die toten FK-Properties aus alten image-Rows
Test/Doku:
- module-registry.test.ts: Snapshot refresht auf aktuellen Stand mit
56 Modulen (vorher 32, statisch eingefroren pre-refactor). Plus
LEGACY_TABLES-Exclusion für nicht-mehr-registrierte Tabellen aus
cards/citycorners/moodlit/rituals/wishes/who.
- streaks.test.ts: MealLogged-Test in TaskCompleted-Test umgebaut
- apps/mana/CLAUDE.md: food-Refs in AI-Tool-Tabelle und
AiProposalInbox-Liste entfernt
- validate-i18n-keys.mjs + validate-no-recursive-turbo.mjs:
existsSync-Guard, damit die Skripte mit gestaged-aber-rm'ten Dateien
klarkommen
mana-web svelte-check 0 errors / 7436 files, betroffene Tests grün
(streaks, dashboard, module-registry), validate:pg-schema,
validate:turbo, validate:i18n-parity grün.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
92 lines
3.2 KiB
JavaScript
Executable file
92 lines
3.2 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
/**
|
|
* Validate that no non-root package.json calls `turbo run` in a script
|
|
* that turbo itself orchestrates. Those recursive calls are a 10+ minute
|
|
* build hang waiting to happen — see the root CLAUDE.md §Turborepo for
|
|
* the incident that prompted this rule.
|
|
*
|
|
* Rule: inside any package.json EXCEPT the repo root, the scripts
|
|
* { build, type-check, lint, test, test:coverage }
|
|
* must NOT contain `turbo run`. Turbo drives them from the root; if a
|
|
* child also calls turbo, you get N² task spawns, duplicate work, and
|
|
* eventually a hung CI job.
|
|
*
|
|
* `dev` is explicitly allowed: it's persistent, usually scoped via
|
|
* --filter, and delegating it from a parent package is the intended
|
|
* ergonomic shortcut (e.g. `pnpm mana:dev` → turbo run dev --filter=mana...).
|
|
*
|
|
* Zero deps — runs as plain Node ESM. Uses `git ls-files` so it
|
|
* automatically respects .gitignore (no node_modules traversal).
|
|
*/
|
|
|
|
import { execSync } from 'node:child_process';
|
|
import { readFileSync, existsSync } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { dirname, join } from 'node:path';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const REPO_ROOT = join(__dirname, '..');
|
|
|
|
/** Scripts that turbo orchestrates from the root. Recursive turbo calls
|
|
* in these scripts are what cause the build hang. */
|
|
const FORBIDDEN_TASKS = new Set(['build', 'type-check', 'lint', 'test', 'test:coverage', 'check']);
|
|
|
|
function listPackageJsons() {
|
|
const out = execSync('git ls-files "package.json" "**/package.json"', {
|
|
cwd: REPO_ROOT,
|
|
encoding: 'utf8',
|
|
});
|
|
return out
|
|
.split('\n')
|
|
.map((p) => p.trim())
|
|
.filter(Boolean);
|
|
}
|
|
|
|
function validate() {
|
|
const paths = listPackageJsons();
|
|
const rootRel = 'package.json';
|
|
const violations = [];
|
|
let scanned = 0;
|
|
|
|
for (const rel of paths) {
|
|
if (rel === rootRel) continue; // root is ALLOWED to orchestrate turbo
|
|
const abs = join(REPO_ROOT, rel);
|
|
if (!existsSync(abs)) continue; // tracked but deleted-on-disk (rm without commit)
|
|
scanned++;
|
|
let pkg;
|
|
try {
|
|
pkg = JSON.parse(readFileSync(abs, 'utf8'));
|
|
} catch (err) {
|
|
violations.push(`${rel}: invalid JSON (${err.message})`);
|
|
continue;
|
|
}
|
|
const scripts = pkg.scripts ?? {};
|
|
for (const [task, cmd] of Object.entries(scripts)) {
|
|
if (!FORBIDDEN_TASKS.has(task)) continue;
|
|
if (typeof cmd !== 'string') continue;
|
|
// Match `turbo run` as a whole word — don't trip on strings like
|
|
// "turbot run" (hypothetical) or unrelated tooling.
|
|
if (/\bturbo\s+run\b/.test(cmd)) {
|
|
violations.push(
|
|
`${rel}: script '${task}' calls \`turbo run\` — this causes recursion when ` +
|
|
`the root turbo also runs '${task}'. Replace with the direct tool ` +
|
|
`(e.g. \`tsc --noEmit\`, \`vite build\`) or remove the script entirely.`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (violations.length > 0) {
|
|
console.error(`\n✗ Recursive-turbo check FAILED (${violations.length} violation(s)):\n`);
|
|
for (const v of violations) console.error(` • ${v}`);
|
|
console.error(
|
|
`\nSee CLAUDE.md §Turborepo for context. Allowed: \`dev\` scripts may call ` +
|
|
`\`turbo run dev --filter=…\` (persistent + scoped).\n`
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log(`✓ No recursive turbo calls: scanned ${scanned} non-root package.json files.`);
|
|
}
|
|
|
|
validate();
|