{ "$schema": "https://turbo.build/schema.json", // The CI workflow pins the toolchain these tasks run under (Node 22 today). // Without it in the global hash, bumping that version would replay cached // typecheck/test results produced by the old runtime and hide an // incompatibility behind a green check. "globalDependencies": [".github/workflows/ci.yml"], "globalEnv": [ "DATABASE_URL", "PORT", "FRONTEND_PORT", "FRONTEND_ORIGIN", "NEXT_PUBLIC_API_URL", "NEXT_PUBLIC_WS_URL", "MULTICA_SERVER_URL", "DOCS_URL", "COMPOSE_PROJECT_NAME", "POSTGRES_DB", "POSTGRES_PORT", "DESKTOP_RENDERER_PORT", "DESKTOP_APP_SUFFIX" ], "tasks": { "build": { "dependsOn": ["^build"], // No explicit `inputs`: turbo's default (every git-tracked file in the // package) is the only safe hash source now that the cache is actually // restored in CI. The previous narrow glob list matched neither // `content/**/*.mdx` (compiled by fumadocs-mdx during the build), // `public/**` assets, nor `package.json` / `tsconfig.json`, so the task // hash was unchanged by edits to any of them -- harmless while nothing // was ever cached, a stale-build bug the moment it is. "outputs": [".next/**", "!.next/cache/**", "dist/**", "out/**"] }, "dev": { "cache": false, "persistent": true }, "dev:staging": { "cache": false, "persistent": true }, "typecheck": { "dependsOn": ["^typecheck"] }, // Hash-only transit task. No package implements a `cache-inputs` script, // so every node resolves to and nothing is ever executed -- // but the edges still pull each dependency's file hashes into whatever // depends on it. `dependsOn: ["^cache-inputs"]` makes that recursive, so // the chain stays complete if a package ever gains a purely transitive // dependency. This exists because a turbo task hash covers a workspace // dependency's sources only when a task edge reaches them. "cache-inputs": { "dependsOn": ["^cache-inputs"] }, // Without a dependency edge, editing packages/views or packages/ui left // `@multica/web#test` and `@multica/desktop#test` byte-identical in hash, // so a cached pass would be replayed over changed code. `^cache-inputs` // closes that without side effects: `^typecheck` would also work but drags // three real `tsc --noEmit` runs (~223 CPU-seconds) into the test job, and // `^test` would serialise the suites behind each other. "test": { "dependsOn": ["^cache-inputs"] }, // `lint` keeps no dependency edge: eslint here is not type-aware (no // `projectService` / `parserOptions.project` anywhere in // packages/eslint-config), so it only ever reads its own package's files // and a dependency's source cannot change its result. "lint": {} } }