Files
deepseek-harness/packages/ui/app-boot
Tianyi Cui 4a0941fb4b feat(ui): share the app bins' boot glue in @deepseek-ai/dsh-app-boot
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.
2026-07-04 16:43:06 +08:00
..

@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.