seek://news/dshmarket-1-73-17
dshmarket 1.73.17: Three Fixes and a Market Speedup, All From First-Time Contributors (Nov 9, 2026)
TL;DR
Per the npm registry (fetched 2026-11-09), dshmarket published 1.73.17 at 17:08 UTC on 2026-11-09. All four changes come from first-time contributors: a CLI entry inside an .asar archive inherits the launcher cwd, boot replay stops disabling a carrier's gate, the market stops re-scanning the whole catalog on every render, and the origin fence trusts the listener bind host.
A third straight single-release evening: per the npm registry (fetched 2026-11-09), 1.73.17 went up at 17:08:25 UTC on November 9 and took over the dist-tag latest — dshmarket 1.73.16: Three Fixes Across Compatibility, Verify and Profile (Nov 8, 2026) covered the previous evening. The GitHub release page stamps 17:03:20 UTC, authored by the repo’s github-actions bot, and links the compare range v1.73.16…v1.73.17.
Four changes, four first-timers
Per the release notes, the What’s Changed list holds exactly four items — three fixes and one perf — and the New Contributors section names all four authors, each making their first contribution. The previous evening mixed one new name among three authors, the other two of whom had contributed before: per 1.73.16’s release notes, that section named only @Eapp1e.
-
PR #1152 (fix(dsh-cli)) — a CLI entry inside an .asar archive inherits the launcher’s cwd, and with it the market’s writes start working again on community desktop shells. Per issue #1146 (filed by hairyf), from desktop 0.31.0 every market-initiated install, update or uninstall failed with a spawn ENOENT naming an executable that actually exists; the PR body names hairyf/deepseek-harness-desktop as the example shell packaging the DSH CLI inside an asar. The mechanics per the two artifacts: dshArgv() exempted only the official desktop carrier from setting a working directory, so a generic bin.js entry got its cwd inside the asar — a path Electron’s fs shim resolves but Windows’s CreateProcess refuses to chdir into — and the failure lands on process.execPath, a file unrelated to the real problem. Per the PR body, the child died within 8–19 ms (exit 127) with pnpm never started, while manual pnpm worked; the fix tests the entry path for an .asar segment and gives it the carrier treatment — cwd: undefined, the launcher’s real directory. The body’s on-machine check: nine consecutive package updates each exited 0 with drain succeeded, then restart scheduled.
-
PR #1158 (fix(routes)) — boot replay keeps a carrier’s gate alive. Per the PR body, switching a package off records it in .dsh-market/state.json#disabled and replays the list at boot; the replay disabled every loader entry matching the package name, including the separate gate entry named
<pkg>/<row>whose service gets injected into foreign presets. With the gate stopped, those foreign rows waited forever for a service that no longer existed, every official preset stayed pending, and boot failed withUnknown agent preset: cordis/entries did not activate. The body locates the gap as the same class the live toggle and Recovery routes already handled through carrierRowIds (#224, #938) — moving the whole bundle out of dsh.profile.bundles — a class the boot replay path and the self-heal guard had not picked up. The fix adds a carrier-safe replayDisabledPackage: when the package is a carrier that declares a bundle and still sits in the profile stack, the whole bundle is removed for the next composition instead of disabling its entries; ordinary packages keep the existing best-effort entry disable, and the self-heal guard exempts carriers so the restart finishes the switch. Per the body, the full suite read 3281 passed — the only 2 failures being Windows symlink-permission tests that fail on clean main too — and the carrier contract is unchanged: reconciliation still waits for one restart. -
PR #1160 (perf(market)) — the market stops re-scanning the catalog on every render. Per the PR body, two full-catalog passes ran on render paths, together the main-thread cost behind issue #1097: installedBlocked re-walked the whole catalog per render through three unmemoized update-reminder lists, whatever tab was open, and the host filter sat inside the query building pluginsAll, so every batch arrival of hostCompatibility rebuilt the list and re-ran the whole-catalog pass. The first is now one memoized batch per render input; the second runs after that pass, with hostHiddenCount keeping its meaning over the pre-block pool. The body’s measurements — Windows x64, DSH Desktop (Electron 44.7.0 / Chrome 152), dshmarket 1.73.16, a 9.7k-entry catalog with 28 installed packages: the scroll’s long tasks (227 / 233 / 433 ms) read none after, sameSourceConflict dropped from 62.9% of the scroll profile to out of the top 12, opening the market to the first list went 1324 ms to 884 ms, and long tasks in the first 3.4 s fell from 3128 ms to about 2255 ms. The body keeps the residue on the record: pluginsUnblocked still runs the whole-catalog pass whenever its inputs change — about 700 ms at this size — so opening the market still spends about 2.2 s in long tasks. No new test: per the body, memoization of a pure function plus a reorder of two pure filters.
-
PR #1155 (fix(http)) — the origin fence trusts the listener bind host, as the host fence does. Per issue #1154, on a host started with a non-loopback bind — the report’s repro is
dsh web --host 100.126.218.120 --no-open— browsing worked but every mutating route, install through uninstall, answered403 {"error":"untrusted origin"}for the life of the process, while the same page’s GET routes and /api transport passed. Per the PR body, market mutating routes are exact registrations on the bare webServer and never pass the host’s fence, so sameOrigin is the only guard — and it read only connection.trustedHosts, a list the host deliberately keeps free of the bind IP because the host fence receives it separately as carrier.host. The fix feeds useTrustedHosts the bind host as a port-less entry, normalized like the host’s own isBindAddressAuthority — the %zone id stays an interface selector, a bare IPv6 literal gets bracketed. Per the body, DNS-rebinding stays blocked because the rebinding page’s Host header names its own domain rather than the IP, hosts without webServer (embedded Desktop) keep today’s behavior, and the author verified an install POST passing the fence from a page served atdsh web --host 100.126.218.120. Suites per the body: trusted-hosts 5/5, http 9/9, host-gate 6/6, flows+restart 473/473, full suite 3272 passed.
The notes list nothing beyond the four — no features, no other fixes.
Cadence
Per the same 2026-11-09 registry fetch: eighteen of the nineteen evenings from 10-22 to 11-09 carry at least one dshmarket release, with quiet 10-25 still the only gap; 11-09 counts exactly one version at the fetch (17:08:25 UTC), the third straight single-release evening. dsh-market keeps its nightly rhythm, and the release page is still authored by the repo’s github-actions bot rather than a human account.
More in this series
Official references
- releaseRelease notes: dshmarket 1.73.17 ↗
- releasenpm: dshmarket ↗
- discussionissue #1146: an asar-packaged CLI entry read as spawn cwd ↗
- discussionissue #1154: mutating routes 403 untrusted origin through the bind IP ↗
- discussionissue #1097: the market gets noticeably laggy as installed plugins pile up ↗