By: syd <syd@kronor.io>
Derive the graph from the manifests by default; drop the checked-in table nix/graph.nix is now the source of the project graph, and nix/projects.json is deleted. Every one of the 38 build and test derivation paths is byte-identical across all three states: the old checked-in table, graph.nix reading that table as an override, and graph.nix deriving from the manifests. So the generated file was never carrying information the manifests did not already have. Nx is no longer involved in the recommended path at all, not even offline. It knows dependencies at exactly one level in a pnpm workspace, project to project, derived from the manifests: results/nx-dependency-levels.json shows all 16 dependency-carrying files are package.json and none of the 88 TypeScript files carries any. The checked-in table survives as an optional override. Dropping one at nix/projects.json switches to it with no other change, for a workspace where the manifests stop being the graph: a hoisted node_modules where phantom imports resolve, or edges coming from tsconfig path aliases. scripts/nx-to-nix.mjs generates one and now says so. The graph-agreement guard is replaced. Comparing a manifest-derived table against the manifests is tautological; the residual risk moved to the one file Nix cannot read, pnpm-workspace.yaml, whose globs graph.nix restates. The new guard asks pnpm, which reads that file itself, over a source tree containing every manifest in the repository rather than only those under Nix globs. Demonstrated: dropping "apps" from the globs silently takes the test derivations from 19 to 16, and the guard exits 1 naming apps/cli, apps/report and apps/web.