Fix Primary Package Selection in Monorepos

The primary package heuristic picks the package with the most files when no `apps/` directory with framework evidence exists. For library and platform monorepos, the biggest package is often the admin dashboard, test suite, i18n data, or example app — not the core product. This cascades to wrong framework detection, wrong shape, wrong UI system, and wrong version display.

verdict PASSscore 27 / 27findings 6 (0 risk · 2 debt · 4 obs)duration 1h 24mrejection cycles 0shipped May 22, 2026surface cli

Pipeline timeline

Intent to proven code in 1h 24m across Think, Plan, Build, and Verify.

Think
28m
Plan
18m
Build
6m
Verify
5m

Assertion ledger

27 claims, each independently verified. Showing 8 — show all →

IDSaysMatcher
A001A package whose name exactly matches the repo directory is selected as primaryverifiedok
A002A scoped package whose bare name matches the repo directory is selectedverifiedok
A003A scoped package with identity word 'core' whose scope matches the directory is selectedverifiedok
A004A scoped package with identity word 'server' whose scope matches the directory is selectedverifiedok
A005A scoped self-named package whose bare name equals the scope is selectedverifiedok
A006Higher-priority tiers win over lower-priority tiersverifiedok
A007When multiple packages match the same tier, the one with more files winsverifiedok
A008A name-matched package with fewer than 10 files is rejected by the guardverifiedok

Findings 6 total

debtpackages/cli/tests/engine/census-primary.test.tsclosed
A007 tiebreaker test uses toContain('larger') — would pass if result were 'larger-thing' or any string containing 'larger'
obspackages/cli/tests/engine/census-primary.test.tsclosed
A026 caller test doesn't verify actual call site — it only shows selectPrimary accepts 3 args. Caller verified by source inspection (census.ts:571).
obspackages/cli/src/engine/census.tsmonitor
Tier 4 (scoped+self-named) matches any package where bare === scope, regardless of projectDirName. @strapi/strapi matches in any repo whose packages include it, not just 'strapi' directories.
obspackages/cli/src/engine/census.tsclosed
parsePackageName is a private helper but has no guard for empty-string input — returns { scope: '', bare: '' }. Harmless because nameMatchCandidates filters null packageName, but empty-string packageName would pass the filter and produce an empty bare match.
debtpackages/cli/tests/engine/census-primary.test.tsscope
No test for the Policy 1 + Policy 0 interaction: an apps/ package in a non-product path (e.g., 'examples/apps/web') — would Policy 0 filter it before Policy 1 can match?
+1more findings

Integrity seal

scopesha256:dc146d74f36b1...
contractsha256:45188d7f874f2...
plansha256:a98d577337ead...
specsha256:499b3796fd3b3...
build-reportsha256:07a49df75a5f0...
build-datasha256:958045e8ead38...
verify-reportsha256:0d41c8d37cb5d...
verify-datasha256:1d7999cb3ac0d...
audit cmd$ ana proof audit fix-primary-selection   → all hashes match