dshmarket 1.66.29 → 1.66.30

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/lib/install.js CHANGED
@@ -339,6 +339,21 @@ export async function withHoistRecovery(run, profile, pluginArgs, profileDirecto
339
339
  : `这台宿主(官方桌面端)自己执行安装,不接受市场附加的 pnpm 参数(${unavailableOption}),所以这一步没有自动重试。 / This host (the official desktop app) runs the install itself and takes no pnpm options from the market (${unavailableOption}), so that automatic retry could not be attempted.`;
340
340
  result = { ...result, stderr: `${result.stderr}\n\n${note}` };
341
341
  }
342
+ // pnpm can append a second rule even on success (#883, #878), including
343
+ // after a recovery retry or an official Desktop manager install. Repair
344
+ // the final file now, before another plugin operation reads it; a successful
345
+ // command must never be retried just because its exclusions needed merging.
346
+ if (ok(result) && (verb === 'add' || verb === 'remove' || verb === 'install' || verb === 'update')) {
347
+ try {
348
+ const merged = mergeDuplicateReleaseAgeExcludes(profile, profileDirectory);
349
+ if (merged.length > 0) {
350
+ logEvent('warn', 'install', `merged duplicate minimumReleaseAgeExclude rules for ${merged.join(', ')} after success (#883, #878)`);
351
+ }
352
+ }
353
+ catch (error) {
354
+ logEvent('warn', 'install', `could not merge minimumReleaseAgeExclude after success (#883, #878): ${String(error)}`);
355
+ }
356
+ }
342
357
  return result;
343
358
  }
344
359
  /**
@@ -362,8 +362,27 @@ export function classifyPnpmFailure(output, exitCode) {
362
362
  // (MINIMUM_RELEASE_AGE_VIOLATION), and a later add can fail re-resolving
363
363
  // the young dep (NO_MATURE_MATCHING_VERSION). Recovery is a one-shot
364
364
  // --config.minimum-release-age=0 retry, automated in withHoistRecovery.
365
+ //
366
+ // That gate has a THIRD face, and it is the one that fails AFTER the
367
+ // lockfile check has said yes. pnpm skips that check when the verification
368
+ // cache holds a run whose recorded window is at least as wide as the
369
+ // current one (`canTrustPastCheck`: past >= current, pnpm's own
370
+ // lockfile-verified cache), and the resolver then applies the same policy
371
+ // from scratch. A re-resolved dependency still inside the window comes back
372
+ // as a `policyViolation`, which the CLI only knows how to consume through a
373
+ // handler it never wires on this call path — so it throws
374
+ // RESOLUTION_POLICY_VIOLATIONS_UNHANDLED instead of reporting anything the
375
+ // user can act on. Measured on the bundled pnpm 11.7.0 (DSH Desktop), with
376
+ // a cached pass in place: verification prints "passes supply-chain
377
+ // policies", and the next phase dies with "2 resolution-policy violations
378
+ // were produced but no handleResolutionPolicyViolations callback was wired".
379
+ // Same cause, same cure as the two shapes above — pnpm's hint names
380
+ // `setupPolicyHandlers`, which an integration calling the CLI cannot wire,
381
+ // so the only answer is the one-shot override. Classifying it here is what
382
+ // connects it to that retry; without it the raw internal hint was surfaced.
365
383
  if (output.includes('ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION')
366
- || output.includes('ERR_PNPM_NO_MATURE_MATCHING_VERSION')) {
384
+ || output.includes('ERR_PNPM_NO_MATURE_MATCHING_VERSION')
385
+ || output.includes('ERR_PNPM_RESOLUTION_POLICY_VIOLATIONS_UNHANDLED')) {
367
386
  return {
368
387
  code: 'release-age-violation',
369
388
  recoverable: false,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dshmarket",
3
3
  "description": "Visual plugin market inside DeepSeek Harness — browse, search, and one-click install community plugins. · DSH 可视化插件市场:逛一逛,点一下,装好。",
4
- "version": "1.66.29",
4
+ "version": "1.66.30",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/types/index.d.ts",
package/src/install.ts CHANGED
@@ -345,6 +345,20 @@ export async function withHoistRecovery(
345
345
  : `这台宿主(官方桌面端)自己执行安装,不接受市场附加的 pnpm 参数(${unavailableOption}),所以这一步没有自动重试。 / This host (the official desktop app) runs the install itself and takes no pnpm options from the market (${unavailableOption}), so that automatic retry could not be attempted.`
346
346
  result = { ...result, stderr: `${result.stderr}\n\n${note}` }
347
347
  }
348
+ // pnpm can append a second rule even on success (#883, #878), including
349
+ // after a recovery retry or an official Desktop manager install. Repair
350
+ // the final file now, before another plugin operation reads it; a successful
351
+ // command must never be retried just because its exclusions needed merging.
352
+ if (ok(result) && (verb === 'add' || verb === 'remove' || verb === 'install' || verb === 'update')) {
353
+ try {
354
+ const merged = mergeDuplicateReleaseAgeExcludes(profile, profileDirectory)
355
+ if (merged.length > 0) {
356
+ logEvent('warn', 'install', `merged duplicate minimumReleaseAgeExclude rules for ${merged.join(', ')} after success (#883, #878)`)
357
+ }
358
+ } catch (error) {
359
+ logEvent('warn', 'install', `could not merge minimumReleaseAgeExclude after success (#883, #878): ${String(error)}`)
360
+ }
361
+ }
348
362
  return result
349
363
  }
350
364
 
@@ -399,8 +399,27 @@ export function classifyPnpmFailure(output: string, exitCode?: number | null): P
399
399
  // (MINIMUM_RELEASE_AGE_VIOLATION), and a later add can fail re-resolving
400
400
  // the young dep (NO_MATURE_MATCHING_VERSION). Recovery is a one-shot
401
401
  // --config.minimum-release-age=0 retry, automated in withHoistRecovery.
402
+ //
403
+ // That gate has a THIRD face, and it is the one that fails AFTER the
404
+ // lockfile check has said yes. pnpm skips that check when the verification
405
+ // cache holds a run whose recorded window is at least as wide as the
406
+ // current one (`canTrustPastCheck`: past >= current, pnpm's own
407
+ // lockfile-verified cache), and the resolver then applies the same policy
408
+ // from scratch. A re-resolved dependency still inside the window comes back
409
+ // as a `policyViolation`, which the CLI only knows how to consume through a
410
+ // handler it never wires on this call path — so it throws
411
+ // RESOLUTION_POLICY_VIOLATIONS_UNHANDLED instead of reporting anything the
412
+ // user can act on. Measured on the bundled pnpm 11.7.0 (DSH Desktop), with
413
+ // a cached pass in place: verification prints "passes supply-chain
414
+ // policies", and the next phase dies with "2 resolution-policy violations
415
+ // were produced but no handleResolutionPolicyViolations callback was wired".
416
+ // Same cause, same cure as the two shapes above — pnpm's hint names
417
+ // `setupPolicyHandlers`, which an integration calling the CLI cannot wire,
418
+ // so the only answer is the one-shot override. Classifying it here is what
419
+ // connects it to that retry; without it the raw internal hint was surfaced.
402
420
  if (output.includes('ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION')
403
- || output.includes('ERR_PNPM_NO_MATURE_MATCHING_VERSION')) {
421
+ || output.includes('ERR_PNPM_NO_MATURE_MATCHING_VERSION')
422
+ || output.includes('ERR_PNPM_RESOLUTION_POLICY_VIOLATIONS_UNHANDLED')) {
404
423
  return {
405
424
  code: 'release-age-violation',
406
425
  recoverable: false,