Skip to content

The Drift Log · Software inventory you can trust

Identify Unexecutable Registry Entries with a Simple CI Check

21 September 2026 · 3 min read · 638 words · established

Shelves of empty glass shells with two lit solid crystals among them

Prevent phantom registry entries by verifying that registered components dynamically import and export runnable symbols in CI.

You query your internal package index or shared component registry and find 450 items listed. You pick entry number 214 to handle a standard token transformation. When you import it, the build fails: the file is an interface stub, a file containing throw new Error("TODO: implement"), or a package whose build artifact was never generated into dist/.

The registry counter went up when someone opened a pull request six months ago, but your usable surface area stayed flat. Cataloging metadata is trivial. What makes an inventory real is whether each row can be read, executed, and graded.

When unexecutable rows sit in your registry, developers waste time debugging missing implementations, and leadership reports phantom capabilities. The fix is not a company-wide refactor. It is a simple executable check that runs on every pull request.

The Anatomy of an Empty Row

Unexecutable registry entries persist because registration is decoupled from execution. Most teams validate only structural metadata in CI:

  • Does the entry exist in the manifest?
  • Does it have a valid semver tag?
  • Does the markdown documentation parse?

None of these checks determine whether the entry contains runnable code. Common failure modes that pass superficial linting include:

  1. Type-only stubs: Exporting TypeScript types or interfaces without concrete runtime values.
  2. Missing build targets: The package.json points to ./dist/index.js, but the build pipeline never compiled it.
  3. Broken internal dependencies: Unresolved local imports or environment assumptions that crash the runtime at initial load.

An honest inventory audit treats an entry as non-existent until the runtime can evaluate it without throwing an unhandled exception.

A Lightweight CI Verification Step

You do not need an end-to-end test suite for every single utility just to verify its basic viability. You need a fast registry validation pass that loads the entry point and verifies that expected symbols exist.

Below is a minimal Node.js script suitable for a CI step. It iterates over your catalog manifest, dynamically loads each entry point, and fails the build if an entry lacks an executable export.

import { resolve } from 'node:path';
import { pathToFileURL } from 'node:url';

export async function validateRegistry(manifest) {
  const failures = [];

  for (const entry of manifest.entries) {
    const targetPath = resolve(process.cwd(), entry.path);
    try {
      const module = await import(pathToFileURL(targetPath).href);
      const exportedSymbols = Object.keys(module);

      if (exportedSymbols.length === 0) {
        failures.push(`${entry.id}: Module imported successfully but exports no symbols.`);
        continue;
      }

      const hasExecutable = exportedSymbols.some(
        (key) => typeof module[key] === 'function' || typeof module[key] === 'object'
      );

      if (!hasExecutable) {
        failures.push(`${entry.id}: No executable functions or objects found in exports.`);
      }
    } catch (err) {
      failures.push(`${entry.id}: Execution failed at load time: ${err.message}`);
    }
  }

  return failures;
}

This step catches missing compilation artifacts, syntax errors, missing peer dependencies, and empty stubs before a merge happens. It runs in seconds across hundreds of entries.

What a Load Check Cannot Prove

Be clear about what this test achieves and where its boundary lies.

Importing a module proves that the file exists, its dependencies resolve, its syntax is valid, and its top-level code evaluates. It does not prove algorithmic correctness, handle deep edge cases, or verify that the component meets its input contracts under load.

For full verification, components require isolated execution harnesses. But catching import-level dead weight is the baseline requirement. If an entry cannot be loaded into memory, running functional tests against it is impossible.

How SHPBL Enforces Inventory Reality

SHPBL handles inventory trust by reporting counts strictly apart. We never sum our numbers into a single headline metric.

The engineered catalog, the unpromoted discovery-engine vault, and the standalone Crown Jewels are distinct tiers. When artifacts enter our pipeline, our certification harness executes them and records an explicit verdict: CERTIFIED, PROVISIONAL (reproducible, correctness not yet asserted), INCONCLUSIVE (a harness limitation, not an artifact defect), or FAILED.

Unexecutable stubs never reach the catalog. You can inspect the library using our typed client at @shpbl/sdk or run a free repository evaluation to see how your own tree grades under execution checks.

What to Do on Monday

Do not write a massive testing framework this week. Add a 20-line verification script to your repository's primary CI workflow:

  1. Read your component or package manifest.
  2. Attempt a dynamic import of every registered entry point.
  3. Assert that at least one callable symbol is exported.
  4. Fail the CI run if any entry throws an exception or exports zero runnable values.

This post supports the longer argument in A Component Count Is Not an Inventory.

Keep reading

Next in the log

The Strategic Master Library · written and reviewed under the house's own epistemic rules: nothing claimed that we cannot show.