Problem
Directives-file and default-pack entries are best-effort by design: an entry whose module is absent from the build is silently skipped, so one shared file can cover optional dependencies. But the same silence applies when the module IS in the build and only the target is missing — a binding renamed in a fork release, an accessor field that no longer matches the settled dictionary shape. Such an entry is dead weight and nobody finds out: the optimization it named is silently lost. For the shipped default pack (#242) this is the main staleness risk — a package-set bump that restructures an instance dictionary quietly orphans pack entries, detectable today only indirectly through golden-size regressions in this repo, which downstream users never see.
Approach
The data already exists: the translation context tracks leftover annotations, and runRepM computes the strict-error set by restricting them to module-header targets (UnusedAnnotations); the complement of that restriction is exactly the file/pack entries that matched the module but drained into no binding. Thread these out of mkModule as warnings instead of discarding them. Report policy by source: a leftover pack entry warns unconditionally (a stale shipped default is a compiler defect and should confess), a leftover --directives file entry warns only under a verbosity flag (naming a binding from a newer dependency version is legitimate for a shared file). Module-absent entries stay silent by contract, and nothing becomes a hard error — failing the build on package-set version skew would defeat the best-effort design.
Prerequisites / Relations
Follow-up to #242 / PR #327 (which shipped the pack this protects). Touches the mkModule result type, so compileModules, the CLI, and the golden harness all see the new warnings channel.
Verification / Measurement
Unit tests: a pack-tier entry naming a present module but no binding produces a warning; the same shape from the file tier is silent by default and reported under the flag; a module-absent entry is silent in both tiers; a matching entry warns nowhere. The golden corpus compiles warning-free with the current pack, which becomes the standing staleness check for future package-set bumps.
Problem
Directives-file and default-pack entries are best-effort by design: an entry whose module is absent from the build is silently skipped, so one shared file can cover optional dependencies. But the same silence applies when the module IS in the build and only the target is missing — a binding renamed in a fork release, an accessor field that no longer matches the settled dictionary shape. Such an entry is dead weight and nobody finds out: the optimization it named is silently lost. For the shipped default pack (#242) this is the main staleness risk — a package-set bump that restructures an instance dictionary quietly orphans pack entries, detectable today only indirectly through golden-size regressions in this repo, which downstream users never see.
Approach
The data already exists: the translation context tracks leftover annotations, and
runRepMcomputes the strict-error set by restricting them to module-header targets (UnusedAnnotations); the complement of that restriction is exactly the file/pack entries that matched the module but drained into no binding. Thread these out ofmkModuleas warnings instead of discarding them. Report policy by source: a leftover pack entry warns unconditionally (a stale shipped default is a compiler defect and should confess), a leftover--directivesfile entry warns only under a verbosity flag (naming a binding from a newer dependency version is legitimate for a shared file). Module-absent entries stay silent by contract, and nothing becomes a hard error — failing the build on package-set version skew would defeat the best-effort design.Prerequisites / Relations
Follow-up to #242 / PR #327 (which shipped the pack this protects). Touches the
mkModuleresult type, socompileModules, the CLI, and the golden harness all see the new warnings channel.Verification / Measurement
Unit tests: a pack-tier entry naming a present module but no binding produces a warning; the same shape from the file tier is silent by default and reported under the flag; a module-absent entry is silent in both tiers; a matching entry warns nowhere. The golden corpus compiles warning-free with the current pack, which becomes the standing staleness check for future package-set bumps.