Minimal Electron shell over the DSH JSON-RPC runtime — a first-look at what a ChatGPT.app-style host on top of the DeepSeek Harness looks like, with the harness's normally-invisible internals (trace timeline, context surface, subagent tree, compaction, plugin registry, rubrics) brought forward as first-class UI surfaces so plugin authors and researchers can see what the agent is actually doing. Runs against three keyless-to-live profiles (stdio-echo works on master out of the box; daemon-echo / daemon-vibe-echo activate once the daemon-demo lands; stdio-deepseek and daemon-vibe hit the real DeepSeek API when you supply a key). HARNESS_DEV auto-resolves to the in-repo runtime when this shell ships under examples/desktop/, so a fresh clone launches without config; env DSH_DEV_ROOT overrides for custom layouts, and a sibling deepseek-harness-dev/ checkout is the original dev workflow. Cold-clone gate (P0 fixes for first-time-clone usability): - HARNESS_DEV: 3-candidate resolver (env → walk-up in-repo marker → sibling), unit-tested via mock fs so ordering is locked without needing either real layout on disk. - config yml leaves rewritten at assemble time so the sibling-clone paths (../../deepseek-harness-dev/examples/echo-agent/…) become the in-repo paths (../../echo-agent/…) in the released tree — source yml stays usable for local dev, released tree ships a working shape. - pnpm-workspace.yaml allowBuilds.electron = true (was placeholder). - missing-key card in stdio-deepseek offers a one-click switch to stdio-echo (the keyless profile that works on master) rather than daemon-echo (blocked on the not-yet-shipped daemon-demo). - assemble-oss-release.sh rewrites the source-side breadcrumb name 'dsh-desktop-demo' → 'dsh-desktop' for the released package.json. FOUC guard on the onboarding gate (41fc5df carried) keeps the first-launch splash from flashing before the runtime probe finishes. Test suite (1634 tests in source, 3990 in the runtime repo) covers resolver ordering, renderer classifiers, trace timeline shape, compaction diff rendering, rubric parity, and the missing-key onboarding paths.
default-profile-real probe (2026-07-18)
Isolated real-machine verification for fix/default-profile-real (default
profile → stdio-deepseek + missing-key guided-switch card).
Isolation (mandatory)
--user-data-dir=/tmp/dsh-probe-default-real/user-data (Electron caches +
Local Storage) AND DSH_DESKTOP_HOME=/tmp/dsh-probe-default-real/dsh-home
(shell overlay + config.json + .onboarded sentinel). Team-lead flagged
that a prior probe wrote through to the user's real ~/.dsh-desktop/user- overlay.cordis.yml because DSH_DESKTOP_HOME wasn't isolated; this probe
respects both.
Driver: /tmp/dsh-probe-default-real/run.sh {with-key|no-key} [port].
Scenarios
01 · no-key boot (01-no-key-boot.png)
Boots stdio-deepseek with DEEPSEEK_API_KEY unset. Confirms:
- Bottom-right chip:
stdio-deepseek · deepseek-v4-flash(NEW DEFAULT correctly landed — wasdaemon-echo · mock-echobefore this change) - Composer model chip:
deepseek-v4-flash(matches profile default) - Status bar:
crashed(expected — the deepseek runtime dies during plugin load because this dev-clone snapshot has aworkspaceContextschema drift; NOT the api-key error we designed against) - Banner: generic "Runtime warning" — the raw message reaching
the classifier is
runtime not writable(fromtransport.js:53 write() throws when stdin isn't writable), which correctly falls through to the generic bucket. My missing-api-key regex would ONLY match if the deepseek plugin actually got to throw its api-key error, which requires the config schema to pass first.
02 · guided-switch card (synthetic inject, 02-guided-card-injected.png)
Fires showRuntimeErrorBanner('llm-deepseek: an API key is required (Config.apiKey or $DEEPSEEK_API_KEY)') via the __dshRenderer test seam
so we can see the classifier + banner logic end-to-end without needing
the real llm-deepseek error to surface. Confirms:
- Banner title: "! DEEPSEEK_API_KEY needed for real-model profile"
- Hint: full two-option copy (set env in .env/shell, or try keyless demo)
- Switch button: "Switch to keyless demo (daemon-echo)" (ghost small,
under hint, wired to
window.dsh.startRuntime('daemon-echo')) - Layout: amber-tinted banner sits above the welcome cards, NO red wall, full-width row (respects density spec)
03 · with-key boot (03-with-key-boot.png)
Boots stdio-deepseek with the dev-clone .env key loaded. Same shape as
#01 in this environment because the config schema drift dies before the
key check — the WITH-key scenario would surface status=ready +
no banner only after the dev clone is bumped past the workspaceContext
requirement. Documenting for reproducibility.
Known limits (dev-clone drift)
deepseek-harness-dev currently requires workspaceContext in the
agent-spine-demo entry (packages/examples/agent-spine-demo/src/index.ts:94).
The demo repo's config/deepseek-jsonrpc.yml predates that requirement, so
the runtime dies at config validation before either the key check or the
actual daemon handshake. This is orthogonal to the default-profile change
and does NOT block:
- The default profile stdio-deepseek IS observably active (screenshots
and CDP eval of
#profile.valueconfirm) - The guided-switch card renders correctly when the api-key error DOES reach the classifier (screenshot #02 proves this via the test seam)
- The static test suite (
test/default-profile-real.test.js+test/renderer-runtime-banner-classify.test.js) locks every step of the wire path (currentProfileName, cfg.profile persistence, stderr accumulator, classification bucket, banner switch button)
Follow-up
- Dev-clone bump: separate ticket. When
agent-spine-demobecomes optional or the yml gainsworkspaceContext, re-run this probe in full to see the api-key error surface organically. Current 1554 test suite locks the code paths that would fire when it does. - README quick-start — team-lead owns this batch, keeping just the minimum quote-of-fact edits to README in this commit (default is stdio-deepseek, keyless demo callout).