The four near-twin helpers the two published bins carried — loadEnv, installFailLoud, assertEntriesLoaded, boot — live once in packages/ui/app-boot, parameterized by the bin's diagnostic prefix and injectable at their side-effect seams (warn sink, process slice), so every branch sits under the per-file 100% coverage gate: the unit suite drives boot() in-process against the real Loader (relative-specifier configs) through both the settled-tree path and the fiber-less-entry rejection, and exercises the ENOENT/unloadable .env split, the Error/non-Error/stackless fail-loud arms, and the disabled-entry exclusion. resolveConfigPath (snapshot-aware) becomes the single path resolver for both bins. Each bin.ts is now a thin self-executing composition plus its app-specific lifecycle (acp: replay env-skip + stdin-EOF dispose; stdio: nothing extra), exports nothing, and stays coverage-excluded; the built-bin smokes still prove both artifacts under plain node in the node_modules-shaped temp dir (now symlinking ui/app-boot), including the missing-config non-zero exit. Implements docs/rfc/implemented/simplification/2026-07-04-share-app-bin-boot-glue.md (moved from proposed/ and amended); the extract-example-app-packages RFC's bin-ownership facts are amended in the same change.
@deepseek-ai/dsh-app-boot
Shared boot glue for the app bins (dsh-stdio-agent, dsh-acp-agent): each bin is a thin self-executing composition over these helpers, parameterized by its diagnostic prefix, so the loader-failure lore lives once — under the per-file coverage gate — instead of drifting between two published artifacts.
| Export | Role |
|---|---|
resolveConfigPath(path, snapshotMode, cwd?) |
Absolute config path; snapshotMode === 'replay' swaps a cordis.yml/.yaml basename for its sibling cordis.snapshot.yml |
loadEnv(binName, dir?, warn?) |
Load the gitignored .env (Node process.loadEnvFile); absent file is fine, an unloadable one warns a single labelled line (default: stderr) |
installFailLoud(binName, proc?) |
Turn a post-boot() unhandled Loader rejection into one labelled stderr line + exit(1); returns the uninstaller (for tests) |
assertEntriesLoaded(ctx, binName) |
Throw when a settled tree holds an enabled entry with no fiber (a plugin module that failed to import) |
boot(binName, absoluteConfigPath) |
Mount the Loader, include the config by absolute file:// URL, await the whole tree, assert entries loaded, return the root context |
Two failure classes the guards close — both would otherwise exit 0 with a usable config typo reported only as a log line: loader.await() swallows init rejections (Promise.allSettled), surfaced instead by installFailLoud; a failed plugin IMPORT is only logged by the Loader, leaving a fiber-less entry that assertEntriesLoaded turns into a boot() rejection.
Bare plugin specifiers in a config (@deepseek-ai/dsh-*) resolve through the cordis Loader's internal module loader, active only under node --expose-internals; the bins' subprocess smokes exercise that path, while this package's unit suite drives boot() in-process against configs with relative specifiers.