dsh-root-planner-preset 1.1.2 → 1.1.3

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/release.mjs +51 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-root-planner-preset",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "type": "module",
5
5
  "description": "DSH agent preset that outsources file reading to strictly read-only subagents, while the root agent keeps the plan and owns every file mutation.",
6
6
  "license": "MIT",
package/release.mjs CHANGED
@@ -39,8 +39,8 @@ const here = dirname(fileURLToPath(import.meta.url));
39
39
  const OFFICIAL_REGISTRY = 'https://registry.npmjs.org/';
40
40
  const PROXY = process.env.HTTPS_PROXY ?? process.env.HTTP_PROXY ?? 'http://127.0.0.1:7897';
41
41
  const GIT = process.env.DSH_RELEASE_GIT ?? 'git';
42
- const NPM = process.env.DSH_RELEASE_NPM ?? 'npm';
43
42
  const GH = process.env.DSH_RELEASE_GH ?? 'gh';
43
+ const PUBLISHER = process.env.DSH_RELEASE_PUBLISHER ?? (process.platform === 'win32' ? 'pnpm' : 'npm');
44
44
 
45
45
  const argv = process.argv.slice(2);
46
46
  const dryRun = argv.includes('--dry-run');
@@ -62,12 +62,15 @@ if (bump === undefined) {
62
62
 
63
63
  const env = { ...process.env, HTTPS_PROXY: PROXY, HTTP_PROXY: PROXY, GIT_TERMINAL_PROMPT: '0' };
64
64
  const step = (text) => process.stdout.write(`\n\u25b6 ${text}\n`);
65
- const run = (command, args, options = {}) => {
66
- const result = spawnSync(command, args, { cwd: here, env, encoding: 'utf8', ...options });
67
- if (result.status !== 0 && options.allowFailure !== true) {
68
- throw new Error(`${command} ${args.join(' ')} failed (${result.status})\n${result.stdout ?? ''}${result.stderr ?? ''}`);
65
+ const run = (command, args, { allowFailure = false, shell = false, ...rest } = {}) => {
66
+ const result = spawnSync(command, args, { cwd: here, env, encoding: 'utf8', shell, ...rest });
67
+ // A spawn that never started reports status null and puts the reason in `error`;
68
+ // surfacing that by name is what turns a silent no-op into a diagnosable failure.
69
+ if (result.status !== 0 && !allowFailure) {
70
+ const reason = result.error ? `${result.error.code}: ${result.error.message}` : `exit ${result.status}`;
71
+ throw new Error(`${command} ${args.join(' ')} failed (${reason})\n${result.stdout ?? ''}${result.stderr ?? ''}`);
69
72
  }
70
- return `${result.stdout ?? ''}${result.stderr ?? ''}`;
73
+ return `${result.stdout ?? ''}${result.stderr ?? ''}${result.error ? `\n${result.error.code}: ${result.error.message}` : ''}`;
71
74
  };
72
75
  const git = (...args) => run(GIT, args).trim();
73
76
 
@@ -149,12 +152,28 @@ if (dryRun) {
149
152
  }
150
153
 
151
154
  // ── Publish ──────────────────────────────────────────────────────────────────
152
- step(`Publish to the official registry (the configured one is a read-only mirror)`);
155
+ step(`Publish with ${PUBLISHER} to the official registry (the configured one is a read-only mirror)`);
153
156
  if (dryRun) {
154
- process.stdout.write(` --dry-run: would run npm publish --registry ${OFFICIAL_REGISTRY}\n`);
157
+ process.stdout.write(` --dry-run: would run ${PUBLISHER} publish --registry ${OFFICIAL_REGISTRY}\n`);
155
158
  } else {
156
- const published = run(NPM, ['publish', '--registry', OFFICIAL_REGISTRY, '--access', 'public'], { allowFailure: true });
157
- process.stdout.write(` ${published.split('\n').filter((line) => /\+ |error|Publishing/.test(line)).join('\n ') || '(no output)'}\n`);
159
+ // Two Windows facts force the shape of this call, both learned by watching a
160
+ // publish silently do nothing:
161
+ // * `npm` and `pnpm` are shell shims, not executables — `npm` is an sh script
162
+ // (ENOENT), `npm.cmd`/`pnpm.cmd` refuse to spawn without a shell (EINVAL),
163
+ // and `npm.ps1` is PowerShell (EFTYPE). So the publisher is invoked WITH a
164
+ // shell, which is why every argument below must stay shell-safe.
165
+ // * The output must be shown even on failure. The first version filtered it
166
+ // down to matching lines and printed a blank line when the command never
167
+ // ran, hiding the real problem behind a successful-looking step.
168
+ const published = run(PUBLISHER, ['publish', '--registry', OFFICIAL_REGISTRY, '--access', 'public'], {
169
+ allowFailure: true,
170
+ shell: true,
171
+ });
172
+ const summary = published
173
+ .split('\n')
174
+ .map((line) => line.trim())
175
+ .filter((line) => line.length > 0 && !/^Progress:|^Packages:|^\+?$/.test(line));
176
+ process.stdout.write(`${summary.map((line) => ` ${line}`).join('\n') || ' (the publisher printed nothing — treat that as a failure)'}\n`);
158
177
  }
159
178
 
160
179
  // ── Confirm on the registry ──────────────────────────────────────────────────
@@ -170,22 +189,26 @@ if (dryRun) {
170
189
  encoding: 'utf8',
171
190
  }).stdout?.trim();
172
191
 
192
+ // Measured on this account: 1.1.2 was still 404 at 200s and live shortly after,
193
+ // so the window has to be generous or a successful release reads as a failure.
173
194
  let live = false;
174
- for (let attempt = 1; attempt <= 20 && !live; attempt += 1) {
195
+ for (let attempt = 1; attempt <= 60 && !live; attempt += 1) {
175
196
  await new Promise((resolve) => setTimeout(resolve, 10_000));
176
197
  const code = probe(`${OFFICIAL_REGISTRY}${manifest.name}/${version}`);
177
198
  if (code === '200') {
178
199
  live = true;
179
200
  process.stdout.write(` ${manifest.name}@${version} is live on the registry\n`);
180
- } else if (attempt % 5 === 0) {
201
+ } else if (attempt % 6 === 0) {
181
202
  process.stdout.write(` still not visible after ${attempt * 10}s (last HTTP ${code})\n`);
182
203
  }
183
204
  }
184
205
  if (!live) {
185
206
  process.stderr.write(
186
- '\n NOT VISIBLE. On this account publishing is STAGED: check for a pending\n' +
187
- ' approval on npmjs.com — `npm stage list` can report nothing while the\n' +
188
- ' registry still refuses the version.\n',
207
+ '\n NOT VISIBLE after 10 minutes. Two known causes, in order of likelihood:\n' +
208
+ ' 1. propagation lag — this registry answered 404 for over three minutes on a\n' +
209
+ ' publish that had already succeeded, so re-check before concluding anything;\n' +
210
+ ' 2. staged publishing — check npmjs.com for a pending approval. `npm stage list`\n' +
211
+ ' reports nothing even when a version is held, so it is not the test.\n',
189
212
  );
190
213
  process.exit(1);
191
214
  }
@@ -196,10 +219,14 @@ step(`Upgrade the local "${profile}" profile so the machine runs what was publis
196
219
  if (dryRun || skipInstall) {
197
220
  process.stdout.write(' skipped\n');
198
221
  } else {
199
- const spec = `${manifest.name}@${version}`;
200
- const output = run('dsh', ['plugin', '--profile', profile, 'add', spec, '--registry', OFFICIAL_REGISTRY], {
201
- allowFailure: true,
202
- });
222
+ // `dsh` is a shell shim on Windows too, so it is invoked through Node rather
223
+ // than spawned directly. DSH_RELEASE_DSH overrides the entry point.
224
+ const dshEntry = process.env.DSH_RELEASE_DSH ?? 'D:/nodejs/npm_global/node_modules/@deepseek-ai/dsh/lib/bin.js';
225
+ const output = run(
226
+ process.execPath,
227
+ [dshEntry, 'plugin', '--profile', profile, 'add', `${manifest.name}@${version}`, '--registry', OFFICIAL_REGISTRY],
228
+ { allowFailure: true },
229
+ );
203
230
  const installed = (() => {
204
231
  try {
205
232
  return JSON.parse(
@@ -212,7 +239,11 @@ if (dryRun || skipInstall) {
212
239
  if (installed === version) {
213
240
  process.stdout.write(` profile now runs ${manifest.name}@${installed}\n`);
214
241
  } else {
215
- process.stdout.write(` install reported ${installed ?? 'unknown'} — run it by hand if this matters:\n${output.trim()}\n`);
242
+ process.stdout.write(
243
+ ` the profile reports ${installed ?? 'unknown'} rather than ${version} — install it by hand:\n` +
244
+ ` dsh plugin --profile ${profile} add ${manifest.name}@${version} --registry ${OFFICIAL_REGISTRY}\n` +
245
+ `${output.trim().split('\n').slice(-6).map((line) => ` ${line}`).join('\n')}\n`,
246
+ );
216
247
  }
217
248
  }
218
249