superpowers-mcp 6.4.1 → 6.4.2

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.
@@ -58,6 +58,7 @@ function parseArgs(argv) {
58
58
  else if (arg === "--ref" || arg === "--repo" || arg === "--ignore") {
59
59
  const value = argv[++i];
60
60
  if (!value) throw new Error(`Missing value for ${arg}`);
61
+ if (value.startsWith("--")) throw new Error(`Missing value for ${arg} (got "${value}")`);
61
62
  if (arg === "--ref") opts.ref = value;
62
63
  else if (arg === "--repo") opts.repo = value;
63
64
  else opts.ignore.push(value);
@@ -269,19 +270,46 @@ async function main() {
269
270
  }
270
271
  const upstreamSkills = [...new Set(Object.keys(tree.files).map(skillNameOf).filter(Boolean))].sort();
271
272
  const recorded = { repo, ref, commit: tree.commit, capturedAt: new Date().toISOString().slice(0, 10), files, upstreamSkills, ignoredUpstreamSkills: ignored };
272
- fs.writeFileSync(BASELINE_PATH, JSON.stringify(recorded, null, 2) + "\n", "utf-8");
273
+ // Atomic write: temp file + rename so an interrupted --record can never
274
+ // truncate/corrupt the baseline (which a later run would then silently rebuild).
275
+ const tmpPath = `${BASELINE_PATH}.${process.pid}.tmp`;
276
+ try {
277
+ fs.writeFileSync(tmpPath, JSON.stringify(recorded, null, 2) + "\n", "utf-8");
278
+ fs.renameSync(tmpPath, BASELINE_PATH);
279
+ } catch (writeErr) {
280
+ try { fs.unlinkSync(tmpPath); } catch { /* ignore */ }
281
+ throw writeErr;
282
+ }
283
+
284
+ const coverageAfter = classifyCoverage(recorded, localPaths);
285
+ const movedCount = previousDrift.changed.length + previousDrift.added.length + previousDrift.removed.length;
286
+ if (opts.json) {
287
+ console.log(JSON.stringify({
288
+ recorded: true,
289
+ repo,
290
+ ref,
291
+ commit: recorded.commit,
292
+ capturedAt: recorded.capturedAt,
293
+ source: tree.source,
294
+ tracked: Object.keys(files).length,
295
+ upstreamTotal: Object.keys(tree.files).length,
296
+ movedSincePrevious: movedCount,
297
+ ignored: opts.ignore,
298
+ coverage: coverageAfter,
299
+ }, null, 2));
300
+ return;
301
+ }
273
302
 
274
303
  console.log(`Baseline recorded from ${tree.source}: ${repo}@${ref} ${tree.commit.slice(0, 12)} — ${Object.keys(files).length} tracked files of ${Object.keys(tree.files).length} upstream skill files`);
275
304
  if (Object.keys(previousFiles).length > 0) {
276
- const moved = previousDrift.changed.length + previousDrift.added.length + previousDrift.removed.length;
277
- console.log(moved === 0
305
+ console.log(movedCount === 0
278
306
  ? "No adopted skill file moved upstream since the previous baseline."
279
- : `warning: ${moved} adopted skill file(s) moved upstream since the previous baseline — record only what you actually reviewed.`);
307
+ : `warning: ${movedCount} adopted skill file(s) moved upstream since the previous baseline — record only what you actually reviewed.`);
280
308
  }
281
309
  if (opts.ignore.length > 0) {
282
310
  console.log(`Recorded as deliberately not adopted: ${opts.ignore.join(", ")}`);
283
311
  }
284
- reportCoverage(classifyCoverage(recorded, localPaths));
312
+ reportCoverage(coverageAfter);
285
313
  return;
286
314
  }
287
315
 
@@ -305,6 +333,13 @@ async function main() {
305
333
 
306
334
  const tree = await fetchUpstreamTree(repo, ref);
307
335
  const drift = classifyDrift(baseline.files, tree.files, ignored);
336
+ // A truncated upstream tree has files missing from the listing; those baseline
337
+ // files would be misclassified as "removed". Suppress the unreliable removals so
338
+ // the report does not invent drift (changed/added only cover files that ARE listed
339
+ // and remain trustworthy).
340
+ if (tree.truncated) {
341
+ drift.removed = [];
342
+ }
308
343
  const driftCount = drift.changed.length + drift.added.length + drift.removed.length;
309
344
  if (opts.json) {
310
345
  console.log(JSON.stringify({