I assumed projecting my private monorepo down to a public repo was a solved problem. It wasn't, and the failures were more interesting than the feature I was shipping that week.
OpenComplAI's Enterprise and Community editions live in related codebases. Every release means projecting the enterprise repo down into the public one. Strip internal packages, regenerate lockfiles, publish clean.
First. Stripping a private directory out of the public projection doesn't strip it from pnpm-lock.yaml or the workspace manifest. The lockfile still listed the private package by name, full dependency graph included, in a repo that was supposed to contain none of it. Deleting a folder isn't the same as regenerating everything that referenced it.
Second. My assemble.sh script, built to prune the enterprise-only bits, was aggressive enough to delete the public repo's own .github/ directory on a re-run. CI workflows and issue templates went with it. A prune script that can't tell "generated cruft" from "the thing that makes this repo work" will eventually delete something you needed.
I also shipped a package-lock.json that leaked the enterprise package's internal name before review caught it, and ended up with orphaned badge SVGs pointing at workflows that no longer existed after the prune.
None of these are exotic. They are what happens when "copy files, remove the private parts" is treated as a file-deletion problem instead of a full re-projection-and-verify one. Prune and regenerate, then gate on a verification pass. Not the other way around.
That's the lesson, and it took me too long to see: the script that builds something can't be the one that certifies it.
I added that verification pass after this round. sync/doctor.py and verify-sbom.sh check the projected repo's actual state. Both are in the repo if you want to see what I now consider the minimum for this kind of pipeline: github.com/opencomplai/opencomplai, under sync/.