3c82db60

Created Started Finished

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.