dsh-plugin-shop 0.8.6 → 0.8.7-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -35,9 +35,9 @@ install them once with `npm install -g @deepseek-ai/dsh pnpm` and verify with
35
35
  # holds back very recent releases, so a bare `add dsh-plugin-shop` can hand
36
36
  # you an older version for a while. Pin the current release — refresh it
37
37
  # with `npm view dsh-plugin-shop version`.
38
- dsh plugin --profile web add dsh-plugin-shop@0.8.5
38
+ dsh plugin --profile web add dsh-plugin-shop@0.8.6
39
39
  # or straight through npx, nothing installed:
40
- npx -y @deepseek-ai/dsh plugin --profile web add dsh-plugin-shop@0.8.5
40
+ npx -y @deepseek-ai/dsh plugin --profile web add dsh-plugin-shop@0.8.6
41
41
  ```
42
42
 
43
43
  Replace `web` with your profile if you use another one. Then restart `dsh` once — a
@@ -67,7 +67,7 @@ ls -1 "${DSH_HOME:-$HOME/.dsh}/profiles" | grep -v '^node_modules$'
67
67
  cooldown, and deterministic installs are the point of the agent path.
68
68
 
69
69
  ```sh
70
- dsh plugin --profile <profile> add dsh-plugin-shop@0.8.5
70
+ dsh plugin --profile <profile> add dsh-plugin-shop@0.8.6
71
71
  ```
72
72
 
73
73
  **3. Verify — do not skip this.** A zero exit from step 2 means pnpm resolved the
package/lib/client.js CHANGED
@@ -4321,6 +4321,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4321
4321
  "profiles": union([_undefined(), array(string())]).optional()
4322
4322
  })]).optional(),
4323
4323
  "dshPeers": union([_undefined(), record(string(), string())]).optional(),
4324
+ "manifestVersion": union([_undefined(), string()]).optional(),
4324
4325
  "unpackedSize": union([_undefined(), number()]).optional(),
4325
4326
  "installSize": union([_undefined(), number()]).optional(),
4326
4327
  "archived": union([
@@ -6484,10 +6485,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6484
6485
  *
6485
6486
  * The second is the one harness reason that blocks (design
6486
6487
  * 2026-09-26-dsh-017-readiness, B1, amending "warn, never block"): dsh 0.1.7
6487
- * refuses the install itself, before pnpm runs, and the shop cannot install
6488
- * past it. The verdict is dsh's own rule on the profile's own exemptions, so
6489
- * a disabled button is dsh's answer given early, never the shop's opinion —
6490
- * and recording the exemption the card shows is what enables it again.
6488
+ * refuses the install itself, an npm entry before pnpm runs and a github
6489
+ * entry after it, rolling the profile back, and the shop cannot install past
6490
+ * it. The verdict is dsh's own rule on the profile's own exemptions, whichever
6491
+ * channel the entry comes from (design
6492
+ * 2026-09-28-bundle-components-and-github-peers, section 7.3), so a disabled
6493
+ * button is dsh's answer given early, never the shop's opinion — and
6494
+ * recording the exemption the card shows is what enables it again.
6491
6495
  */
6492
6496
  function refusesInstall(blockers) {
6493
6497
  return blockers.some((blocker) => blocker.kind === "name-taken" || blocker.kind === "harness-peers");
package/lib/index.js CHANGED
@@ -21,7 +21,7 @@ import { isMap, isSeq, parseDocument } from "yaml";
21
21
  * both the source tree (tests) and the bundled `lib/index.js` sit exactly
22
22
  * one level below the package root, so the same relative URL resolves in
23
23
  * both. */
24
- function ownManifest() {
24
+ function ownManifest$1() {
25
25
  return JSON.parse(readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8"));
26
26
  }
27
27
  /**
@@ -48,7 +48,7 @@ function versionAtLoad(read) {
48
48
  }
49
49
  /** The version of the code in this process, read when the module was first
50
50
  * evaluated — at boot, before any self-update could rewrite the file. */
51
- const runningVersion = versionAtLoad(() => ownManifest().version);
51
+ const runningVersion = versionAtLoad(() => ownManifest$1().version);
52
52
  /**
53
53
  * Which run of the code this is: drawn when the module is first evaluated,
54
54
  * fixed for the life of the process, and different in the next one.
@@ -70,7 +70,7 @@ const bootId = randomUUID();
70
70
  * compare against is worth a verdict.
71
71
  */
72
72
  function ownPeerRanges() {
73
- const declared = ownManifest().peerDependencies;
73
+ const declared = ownManifest$1().peerDependencies;
74
74
  if (declared === null || typeof declared !== "object") return {};
75
75
  const ranges = {};
76
76
  for (const [spec, range] of Object.entries(declared)) if (typeof range === "string") ranges[spec] = range;
@@ -649,6 +649,7 @@ const entrySchema = z.object({
649
649
  profiles: z.array(z.string()).optional()
650
650
  }).optional(),
651
651
  dshPeers: z.record(z.string(), z.string()).optional(),
652
+ manifestVersion: z.string().optional(),
652
653
  unpackedSize: z.number().int().nonnegative().optional(),
653
654
  installSize: z.number().int().nonnegative().optional(),
654
655
  archived: z.boolean().optional()
@@ -1249,20 +1250,35 @@ function unmetProfile(declared, running, templates) {
1249
1250
  * could not tell".
1250
1251
  *
1251
1252
  * The rule is dsh's own (`check`, from the running app-boot), handed the
1252
- * manifest dsh's installer reads before it installs a registry spec — `pnpm
1253
- * view <spec> name version peerDependencies`, measured in dsh-plugin-manager
1254
- * 0.1.7-rc.2 — with the catalog's `dshPeers` for the peers. Those are the
1255
- * only peers the rule reads, verbatim. What this cannot see errs toward
1256
- * silence, never toward a refusal dsh would not make: a malformed peer range
1257
- * elsewhere in the manifest, which dsh rejects only after installing, and
1258
- * the plugins a bundle's patch rows name, which it checks then too. Those
1259
- * reach the reader as the install's own failure (`installFailureDetail`).
1260
- *
1261
- * npm entries only. dsh keys an exemption by the INSTALLED manifest's
1262
- * `name@version`, and a github entry's catalog version is a commit: its
1263
- * exemption status cannot be read, and a refusal named here could never be
1264
- * cleared from the shop. dsh refuses such an install itself, and says how
1265
- * to exempt it.
1253
+ * manifest dsh's installer judges (`ownManifest`): the name and version dsh
1254
+ * keys an exemption by, with the catalog's `dshPeers` for the peers. Those
1255
+ * are the only peers the rule reads, verbatim. Both channels are judged, each
1256
+ * by the manifest dsh reads for it:
1257
+ *
1258
+ * - An npm entry by its catalog `version`. dsh reads that manifest before it
1259
+ * installs a registry spec: `pnpm view <spec> name version
1260
+ * peerDependencies`, measured in dsh-plugin-manager 0.1.7-rc.2.
1261
+ * - A github entry by `manifestVersion`, the version of the manifest dsh
1262
+ * installs: at the pinned commit (a subpackage's own), or in the release
1263
+ * asset a rescued entry installs from. dsh skips a git or tarball spec
1264
+ * before pnpm and judges the installed manifest after it, rolling the
1265
+ * install back on a refusal (the same dsh-plugin-manager). The entry's
1266
+ * catalog `version` is a commit or a tag, so without `manifestVersion` it
1267
+ * is not judged at all: judged by its commit instead, it would miss an
1268
+ * exemption the profile holds under its real `name@version`, disabling an
1269
+ * install dsh accepts, and could offer no command, since `allow-version`
1270
+ * records no commit (design 2026-09-28-bundle-components-and-github-peers,
1271
+ * sections 6.1 and 7.3).
1272
+ *
1273
+ * dsh's key names no channel: an exemption recorded for one `name@version`
1274
+ * clears every entry whose manifest carries it, npm or github, here as in
1275
+ * dsh.
1276
+ *
1277
+ * What this cannot see errs toward silence, never toward a refusal dsh would
1278
+ * not make: a malformed peer range elsewhere in the manifest, which dsh
1279
+ * rejects only after installing, and the plugins a bundle's patch rows name,
1280
+ * which it checks then too. Those reach the reader as the install's own
1281
+ * failure (`installFailureDetail`).
1266
1282
  *
1267
1283
  * A throw from the check forms no verdict for that entry, as a resolver's
1268
1284
  * throw does in `incompatibilityMap`.
@@ -1270,14 +1286,11 @@ function unmetProfile(declared, running, templates) {
1270
1286
  function peerVerdictsOf(entries, check, exemptions, profile) {
1271
1287
  const out = {};
1272
1288
  for (const entry of entries) {
1273
- if (entry.source !== "npm" || entry.dshPeers === void 0) continue;
1289
+ const manifest = ownManifest(entry);
1290
+ if (manifest === null) continue;
1274
1291
  let issue;
1275
1292
  try {
1276
- issue = check.evaluate({
1277
- name: entry.name,
1278
- version: entry.version,
1279
- peerDependencies: entry.dshPeers
1280
- }, exemptions);
1293
+ issue = check.evaluate(manifest, exemptions);
1281
1294
  } catch {
1282
1295
  continue;
1283
1296
  }
@@ -1290,6 +1303,28 @@ function peerVerdictsOf(entries, check, exemptions, profile) {
1290
1303
  }
1291
1304
  return out;
1292
1305
  }
1306
+ /**
1307
+ * The manifest dsh judges an entry's install by, as `peerVerdictsOf` hands it
1308
+ * to the rule, or null when none can be formed: the entry declares no
1309
+ * harness peers, or it is a github entry with no `manifestVersion`. An npm
1310
+ * entry's catalog `version` is its manifest's; a github entry's is a commit
1311
+ * or a tag, so its manifest's own version is the one recorded beside its
1312
+ * peers, and the key is read on github entries only.
1313
+ */
1314
+ function ownManifest(entry) {
1315
+ if (entry.dshPeers === void 0) return null;
1316
+ if (entry.source === "npm") return {
1317
+ name: entry.name,
1318
+ version: entry.version,
1319
+ peerDependencies: entry.dshPeers
1320
+ };
1321
+ if (entry.manifestVersion === void 0) return null;
1322
+ return {
1323
+ name: entry.name,
1324
+ version: entry.manifestVersion,
1325
+ peerDependencies: entry.dshPeers
1326
+ };
1327
+ }
1293
1328
  /** npm's package-name grammar as dsh's exemption records accept it, verbatim
1294
1329
  * from app-boot 0.1.7-rc.2 (`PACKAGE_NAME` in profile-compatibility). */
1295
1330
  const EXEMPTION_PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
@@ -1671,10 +1706,14 @@ const REFUSAL_WARNING_TAIL = " Running it may cause crashes or data loss.";
1671
1706
  /**
1672
1707
  * dsh's own refusal of an install (0.1.7 on) as one detail, or null when the
1673
1708
  * log holds none. The install was dsh's to refuse, not pnpm's to fail: it
1674
- * refuses before pnpm runs, when it can read the manifest — a registry spec,
1675
- * which the catalog's peer verdict already predicts — and after pnpm
1676
- * succeeded otherwise, restoring the profile. Reading that as a pnpm failure
1677
- * sent the reader to `dsh plugin install`, which repairs nothing.
1709
+ * refuses before pnpm runs, when it can read the manifest — a registry spec —
1710
+ * and after pnpm succeeded otherwise, restoring the profile. The catalog's
1711
+ * peer verdict predicts the first, and the second only for a github entry's
1712
+ * own peers, judged by the manifest version the catalog records
1713
+ * (`peerVerdictsOf`). It predicts no refusal of a bundle's components, and
1714
+ * none of a github entry that carries no usable manifest version: dsh makes
1715
+ * those after pnpm all the same. Reading any refusal as a pnpm failure sent
1716
+ * the reader to `dsh plugin install`, which repairs nothing.
1678
1717
  *
1679
1718
  * The detail is what dsh refused, what it restored, and the command that
1680
1719
  * records its exact-version exemption, rebuilt from what dsh printed through
@@ -50,6 +50,7 @@ const dsh_plugin_shop_shop_catalog_result$schema = z.object({
50
50
  'profiles': z.union([z.undefined(), z.array(z.string())]).optional(),
51
51
  })]).optional(),
52
52
  'dshPeers': z.union([z.undefined(), z.record(z.string(), z.string())]).optional(),
53
+ 'manifestVersion': z.union([z.undefined(), z.string()]).optional(),
53
54
  'unpackedSize': z.union([z.undefined(), z.number()]).optional(),
54
55
  'installSize': z.union([z.undefined(), z.number()]).optional(),
55
56
  'archived': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
@@ -498,7 +499,7 @@ export const TYPERT = {
498
499
  },
499
500
  {
500
501
  "name": "CatalogEntry",
501
- "declaration": "export interface CatalogEntry {\n name: string;\n version: string;\n integrity: string | null;\n publishedAt: string | null;\n repository: string | null;\n license: string | null;\n tier: 'verified' | 'verified-stale' | 'community';\n metadata: 'declared' | 'derived';\n review?: { reviewedVersion?: string; reviewedCommit?: string; reviewedSha256?: string; repo?: string; reviewer: string; reviewCommit: string; notes: string; };\n catalog?: CatalogSection;\n source: 'npm' | 'github';\n publisher?: string;\n repo?: string;\n subdir?: string;\n tarball?: { url: string; sha256: string; };\n added?: string;\n peers?: string[];\n compatibility?: { dsh?: string; profiles?: string[]; };\n dshPeers?: Record<string, string>;\n unpackedSize?: number;\n installSize?: number;\n archived?: boolean;\n}"
502
+ "declaration": "export interface CatalogEntry {\n name: string;\n version: string;\n integrity: string | null;\n publishedAt: string | null;\n repository: string | null;\n license: string | null;\n tier: 'verified' | 'verified-stale' | 'community';\n metadata: 'declared' | 'derived';\n review?: { reviewedVersion?: string; reviewedCommit?: string; reviewedSha256?: string; repo?: string; reviewer: string; reviewCommit: string; notes: string; };\n catalog?: CatalogSection;\n source: 'npm' | 'github';\n publisher?: string;\n repo?: string;\n subdir?: string;\n tarball?: { url: string; sha256: string; };\n added?: string;\n peers?: string[];\n compatibility?: { dsh?: string; profiles?: string[]; };\n dshPeers?: Record<string, string>;\n manifestVersion?: string;\n unpackedSize?: number;\n installSize?: number;\n archived?: boolean;\n}"
502
503
  },
503
504
  {
504
505
  "name": "CatalogSection",
@@ -50,6 +50,7 @@ const dsh_plugin_shop_shop_catalog_result$schema = z.object({
50
50
  'profiles': z.union([z.undefined(), z.array(z.string())]).optional(),
51
51
  })]).optional(),
52
52
  'dshPeers': z.union([z.undefined(), z.record(z.string(), z.string())]).optional(),
53
+ 'manifestVersion': z.union([z.undefined(), z.string()]).optional(),
53
54
  'unpackedSize': z.union([z.undefined(), z.number()]).optional(),
54
55
  'installSize': z.union([z.undefined(), z.number()]).optional(),
55
56
  'archived': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
@@ -134,10 +134,13 @@ export declare function readsIncompatible(blockers: readonly {
134
134
  *
135
135
  * The second is the one harness reason that blocks (design
136
136
  * 2026-09-26-dsh-017-readiness, B1, amending "warn, never block"): dsh 0.1.7
137
- * refuses the install itself, before pnpm runs, and the shop cannot install
138
- * past it. The verdict is dsh's own rule on the profile's own exemptions, so
139
- * a disabled button is dsh's answer given early, never the shop's opinion —
140
- * and recording the exemption the card shows is what enables it again.
137
+ * refuses the install itself, an npm entry before pnpm runs and a github
138
+ * entry after it, rolling the profile back, and the shop cannot install past
139
+ * it. The verdict is dsh's own rule on the profile's own exemptions, whichever
140
+ * channel the entry comes from (design
141
+ * 2026-09-28-bundle-components-and-github-peers, section 7.3), so a disabled
142
+ * button is dsh's answer given early, never the shop's opinion — and
143
+ * recording the exemption the card shows is what enables it again.
141
144
  */
142
145
  export declare function refusesInstall(blockers: readonly {
143
146
  kind: BlockerKind;
@@ -181,20 +181,35 @@ export declare function compatibilityMap(entries: readonly (EntryIdentity & {
181
181
  * could not tell".
182
182
  *
183
183
  * The rule is dsh's own (`check`, from the running app-boot), handed the
184
- * manifest dsh's installer reads before it installs a registry spec — `pnpm
185
- * view <spec> name version peerDependencies`, measured in dsh-plugin-manager
186
- * 0.1.7-rc.2 — with the catalog's `dshPeers` for the peers. Those are the
187
- * only peers the rule reads, verbatim. What this cannot see errs toward
188
- * silence, never toward a refusal dsh would not make: a malformed peer range
189
- * elsewhere in the manifest, which dsh rejects only after installing, and
190
- * the plugins a bundle's patch rows name, which it checks then too. Those
191
- * reach the reader as the install's own failure (`installFailureDetail`).
184
+ * manifest dsh's installer judges (`ownManifest`): the name and version dsh
185
+ * keys an exemption by, with the catalog's `dshPeers` for the peers. Those
186
+ * are the only peers the rule reads, verbatim. Both channels are judged, each
187
+ * by the manifest dsh reads for it:
192
188
  *
193
- * npm entries only. dsh keys an exemption by the INSTALLED manifest's
194
- * `name@version`, and a github entry's catalog version is a commit: its
195
- * exemption status cannot be read, and a refusal named here could never be
196
- * cleared from the shop. dsh refuses such an install itself, and says how
197
- * to exempt it.
189
+ * - An npm entry by its catalog `version`. dsh reads that manifest before it
190
+ * installs a registry spec: `pnpm view <spec> name version
191
+ * peerDependencies`, measured in dsh-plugin-manager 0.1.7-rc.2.
192
+ * - A github entry by `manifestVersion`, the version of the manifest dsh
193
+ * installs: at the pinned commit (a subpackage's own), or in the release
194
+ * asset a rescued entry installs from. dsh skips a git or tarball spec
195
+ * before pnpm and judges the installed manifest after it, rolling the
196
+ * install back on a refusal (the same dsh-plugin-manager). The entry's
197
+ * catalog `version` is a commit or a tag, so without `manifestVersion` it
198
+ * is not judged at all: judged by its commit instead, it would miss an
199
+ * exemption the profile holds under its real `name@version`, disabling an
200
+ * install dsh accepts, and could offer no command, since `allow-version`
201
+ * records no commit (design 2026-09-28-bundle-components-and-github-peers,
202
+ * sections 6.1 and 7.3).
203
+ *
204
+ * dsh's key names no channel: an exemption recorded for one `name@version`
205
+ * clears every entry whose manifest carries it, npm or github, here as in
206
+ * dsh.
207
+ *
208
+ * What this cannot see errs toward silence, never toward a refusal dsh would
209
+ * not make: a malformed peer range elsewhere in the manifest, which dsh
210
+ * rejects only after installing, and the plugins a bundle's patch rows name,
211
+ * which it checks then too. Those reach the reader as the install's own
212
+ * failure (`installFailureDetail`).
198
213
  *
199
214
  * A throw from the check forms no verdict for that entry, as a resolver's
200
215
  * throw does in `incompatibilityMap`.
@@ -202,6 +217,7 @@ export declare function compatibilityMap(entries: readonly (EntryIdentity & {
202
217
  export declare function peerVerdictsOf(entries: readonly (EntryIdentity & {
203
218
  version: string;
204
219
  dshPeers?: Record<string, string>;
220
+ manifestVersion?: string;
205
221
  })[], check: PeerCheck, exemptions: Record<string, string[]>, profile: string): Record<string, PeerVerdict>;
206
222
  /**
207
223
  * The command that records dsh's exact-version exemption for one refused
@@ -78,12 +78,26 @@ export interface CatalogEntry {
78
78
  /** The package's peers on the harness itself (`@deepseek-ai/dsh` and
79
79
  * `@deepseek-ai/dsh-*`) with their ranges verbatim, optional ones and empty
80
80
  * ranges included — what dsh 0.1.7 refuses an install on. The host hands
81
- * them to the running dsh's own check (`peerVerdictsOf`). npm entries only:
82
- * dsh keys the exemption that clears its refusal by the installed
83
- * manifest's version, which a github entry's catalog version is not
84
- * (registry `Entry.dshPeers`). Absent when the package declares none, or
85
- * when its catalog predates the field. */
81
+ * them to the running dsh's own check (`peerVerdictsOf`) on both channels:
82
+ * an npm entry is judged by its catalog `version`, a github entry by
83
+ * {@link manifestVersion}, because dsh keys the exemption that clears its
84
+ * refusal by the installed manifest's version, which a github entry's
85
+ * catalog version is not (registry `Entry.dshPeers`; design
86
+ * 2026-09-28-bundle-components-and-github-peers, section 7.3). Absent when
87
+ * the package declares none, or when its catalog predates the field; on a
88
+ * github entry also when its manifest names no usable version, since both
89
+ * keys drop together, and until the registry re-reads its repository under
90
+ * the rule that records them. */
86
91
  dshPeers?: Record<string, string>;
92
+ /** A github entry's installed manifest `version` (registry
93
+ * `Entry.manifestVersion`): the version dsh keys an exemption by, where the
94
+ * entry's catalog `version` is a commit or a release tag. Present exactly
95
+ * when a github entry's {@link dshPeers} is. An npm entry's own `version` is
96
+ * its manifest's, so `peerVerdictsOf` never reads this key on one, and a
97
+ * github entry without it is not judged at all (design
98
+ * 2026-09-28-bundle-components-and-github-peers, section 7.3). Absent when
99
+ * the catalog predates the field. */
100
+ manifestVersion?: string;
87
101
  /** Wire-compatibility key, not a field to read — see {@link installSize},
88
102
  * which the catalog parse fills from this one. It names npm's OWN quantity
89
103
  * (`dist.unpackedSize`), so it is npm-only and the parse REFUSES one on a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-shop",
3
- "version": "0.8.6",
3
+ "version": "0.8.7-beta.0",
4
4
  "description": "The DeepSeek Harness plugin shop: browse, install, enable, and update dsh plugins from a git-auditable catalog.",
5
5
  "keywords": [
6
6
  "dsh-plugin",