Files
deepseek-harness/packages/ui/app-boot
Yichen Jiang 69d8621e2e test: close the per-file coverage gaps this PR opened
The layered-env reader gained an unreadable-layer path, a default
reporter, and two absent-layer arms with no cases; the credential store
gained two error paths that must not be mistaken for an absent file.

The platform arms and the `linePos` guard cannot be reached from a POSIX
test run — the first is covered by the native Windows job, the second
only satisfies an optional type that `prettyErrors` always fills — so
both carry a v8 ignore naming why.
2026-08-05 13:20:56 +08:00
..

@deepseek-ai/dsh-app-boot

English | 中文

Shared boot glue for the app bins (dsh, dsh-cli-demo, dsh-acp-demo): 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 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)
loadLayeredEnv(binName, cwd?, warn?) The dsh product CLI's user environment: loadEnv over the invoking directory, then over the Harness home, giving user < project < inherited. The home is resolved from the inherited environment first, so a project .env cannot redirect it
installFailLoud(binName, proc?, release?) Turn an unhandled boot or later Loader rejection into one labelled stderr line + exit(1); the optional release teardown is awaited between the two (bounded by FAIL_LOUD_RELEASE_TIMEOUT_MS) so a terminal-owning surface restores the terminal before exit; returns the uninstaller (for tests)
FAIL_LOUD_RELEASE_TIMEOUT_MS How long installFailLoud waits for its release hook; a wedged disposer delays the fatal exit, never cancels it
assertEntriesLoaded(ctx, binName) Throw when a settled tree holds an enabled entry with no fiber, reporting every unresolved plugin name as a Cordis startup failure
assertEntriesActivated(ctx, binName) Include the assertEntriesLoaded check, then await every enabled entry after the Loader settles; throw with each failed plugin's original stack or each pending plugin's unresolved services
loadOverlayPatches(binName, file) Parse a required patch-list file (a surface overlay or a --config file); read or parse failures throw a labelled error
mountRootInclude(ctx, absoluteConfigPath, patches?) Mount the statically imported Include builtin as the boot's root entry
boot(binName, absoluteConfigPath, patches?, prepare?) Create the root context, expose dshHomePath(...segments) to Loader !!js config expressions, install Loader, run optional host preparation before config-tree entries mount (prepare may use Loader and provide launcher-owned context slots), then mount and await the include tree, assert entries loaded and activated, and return the root context — or dispose the partial context and reject a labelled error
renderConfigDump(binName, absoluteConfigPath, layers, warn?) Compose the base config and labeled overlay layers offline — the include's own parser and patch algorithm (entryListSchema/applyEntryPatches), so the result equals what boot() mounts — and render YAML with !!js expressions verbatim; each run of same-provenance rows is preceded by a # == comment naming the contributing file and the layers that patched it, keeping the output one loadable document; a patch matching no row goes to warn with its layer label (default: one stderr line), read/parse/shape failures throw
addHarnessSourceSection(ctx, sourceRoot) Add a global harness:source prompt section (ordered just after the harness identity, before the persona) telling the agent the on-disk path to the DSH implementation checkout while warning it not to infer the current working directory from that path and to use pwd instead; a no-op returning undefined when the booted tree has no systemPrompt service. The section is registered against that service's fiber, so a dev HMR reload of the system prompt drops it until the next boot
HARNESS_SOURCE_SECTION The 'harness:source' section name addHarnessSourceSection registers under

Loader settlement rejects import and lifecycle failures with the failing entry and stage; boot() disposes the partial context and wraps that failure with the bin name. Entries settlement leaves behind are audited separately: assertEntriesLoaded turns an enabled fiber-less entry into a rejection naming every unresolved plugin, and assertEntriesActivated awaits each failed fiber to include its original stack in the startup rejection and names each pending entry's unresolved services. Before throwing, the audit marks those exact rejection reasons through one process checkpoint so installFailLoud coalesces Loader's duplicate notification while every unrelated unhandled rejection remains fatal.

The Loader mounts entries concurrently, so a surface can already own the terminal when something else fails: exiting without the tree's own teardown would leave raw mode, bracketed paste, and the keyboard protocol set on the user's shell, and an in-flight terminal query's reply would land as literal text at the next prompt. A config-tree failure settles through boot(), whose disposal of the partial context runs the surface's own shutdown before the labelled rejection. For the rejections boot() cannot see — a plugin's detached async work rejecting during or after mounting — a terminal-owning bin passes release to dispose the tree before the exit commits; dsh captures the root context in boot()'s prepare hook rather than from its return value so the hook covers the whole mounting window. While a release is in flight the handler stays installed and latched: the first rejection is the reported one, and later rejections (teardown's own included) are swallowed rather than becoming uncaught and killing the process mid-teardown.

Bare plugin specifiers in a config (@deepseek-ai/dsh-*, npm packages) resolve through the Cordis Loader's internal module loader. Repository bins install Loader's optional node-addon-require-builtin peer; external callers must supply it or install plugins where plain Node import resolution can find them. Relative specifiers resolve against the config directory without the native helper. The built dsh-app-boot artifact embeds the statically mounted Include implementation while leaving Loader external, so the include tree and host bind to one Loader peer. The dsh source launcher additionally maps manifest-declared workspace packages to their TypeScript source; its configuration gate requires every shipped raw/Web bare plugin to appear in the resolver manifest's dependencies. The bins' subprocess smokes exercise the internal-loader path, while this package's unit suite drives boot() in-process against configs with relative specifiers.

This package carries no loader hooks and no dev-mode surface. The dsh app owns its Node source-launch hook and consumes these helpers for the boot sequence; built consumers continue to use plain Node package resolution.

The Harness home

A developer's machine-local state lives outside every repository in the Harness home (default ~/.dsh, overridable via $DSH_HOME; the single root resolveDshHome resolves). What this package reads from it is one file:

  • .env — the user's ordinary environment layer, loaded by the dsh bin through loadLayeredEnv beneath the invoking directory's .env and the inherited environment. It is plain environment with plain environment reach, not a secret boundary: what the Harness owns and isolates lives in .credentials.yaml, which no surface hoists. A key placed in this file therefore still resolves — as a read-only env layer that shadows the stored one and blocks rotation from the Web settings page.

There is no automatically discovered composition file. Loader overlays reach a surface only by being named: raw dsh --config <path> applies one over the shipped base, and dsh web/dsh -p take the same flag over their shipped overlay. Keeping an overlay in ~/.dsh is fine — it is a location, not a layer, and nothing loads it unless the launch names it (rationale).

Subprocess test launchers point DSH_HOME at an isolated per-test directory so a developer's own files can never leak into fixtures.

Model Experience

Indirectly, through the plugin tree it loads, which determines the prompts, schemas, messages, and model adapter in the resulting application; the one export that contributes model-visible text, addHarnessSourceSection, does so only when a consumer calls it after boot.

KV Cache effect

No direct invalidation from boot(); a consumer that calls addHarnessSourceSection places one short line near the system prompt's head, before per-request content, so it does not invalidate the cache across turns, and any other request-prefix change is owned by the named consumer.

Known Limitations and Deferred Work

  • Bare package specifiers depend on Loader internals — production bins need Loader's optional native helper; an in-process caller without it must use resolvable relative/file specifiers or provide its own module-resolution hook.
  • Snapshot replay swapping is basename-specific — only a config ending in cordis.yml or cordis.yaml maps to the sibling cordis.snapshot.yml; custom config names require caller-managed selection.
  • Environment loading is directory-scoped and optional — each layer is one named directory's .env, and a failure warns; neither helper searches parents or validates required variables. loadLayeredEnv fixes its two layers at the invoking directory and the Harness home, so a caller wanting different layers composes loadEnv itself.
  • Overlays are patch-shaped — an id-targeted patch replaces the entry's whole config rather than deep-merging, so an override restates the base fields it keeps.