@agent-scope/cli 1.15.0 → 1.16.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/dist/index.cjs CHANGED
@@ -1130,9 +1130,9 @@ function createRL() {
1130
1130
  });
1131
1131
  }
1132
1132
  async function ask(rl, question) {
1133
- return new Promise((resolve15) => {
1133
+ return new Promise((resolve16) => {
1134
1134
  rl.question(question, (answer) => {
1135
- resolve15(answer.trim());
1135
+ resolve16(answer.trim());
1136
1136
  });
1137
1137
  });
1138
1138
  }
@@ -2412,8 +2412,8 @@ Available: ${available}`
2412
2412
  wastedRenders: opts.wastedRenders
2413
2413
  });
2414
2414
  await shutdownPool2();
2415
- const fmt = resolveFormat2(opts.format);
2416
- if (fmt === "json") {
2415
+ const fmt2 = resolveFormat2(opts.format);
2416
+ if (fmt2 === "json") {
2417
2417
  process.stdout.write(`${JSON.stringify(instrumentRoot, null, 2)}
2418
2418
  `);
2419
2419
  } else {
@@ -3132,12 +3132,12 @@ Available: ${available}`
3132
3132
  );
3133
3133
  return;
3134
3134
  }
3135
- const fmt = resolveSingleFormat(opts.format);
3136
- if (fmt === "json") {
3135
+ const fmt2 = resolveSingleFormat(opts.format);
3136
+ if (fmt2 === "json") {
3137
3137
  const json = formatRenderJson(componentName, props, result);
3138
3138
  process.stdout.write(`${JSON.stringify(json, null, 2)}
3139
3139
  `);
3140
- } else if (fmt === "file") {
3140
+ } else if (fmt2 === "file") {
3141
3141
  const dir = path.resolve(process.cwd(), DEFAULT_OUTPUT_DIR);
3142
3142
  fs.mkdirSync(dir, { recursive: true });
3143
3143
  const outPath = path.resolve(dir, `${componentName}.png`);
@@ -3258,8 +3258,8 @@ Available: ${available}`
3258
3258
  process.stderr.write(`Sprite sheet saved to ${spritePath}
3259
3259
  `);
3260
3260
  }
3261
- const fmt = resolveMatrixFormat(opts.format, opts.sprite !== void 0);
3262
- if (fmt === "file") {
3261
+ const fmt2 = resolveMatrixFormat(opts.format, opts.sprite !== void 0);
3262
+ if (fmt2 === "file") {
3263
3263
  const { SpriteSheetGenerator: SpriteSheetGenerator2 } = await import('@agent-scope/render');
3264
3264
  const gen = new SpriteSheetGenerator2();
3265
3265
  const sheet = await gen.generate(result);
@@ -3272,10 +3272,10 @@ Available: ${available}`
3272
3272
  `\u2713 ${componentName} matrix (${result.stats.totalCells} cells) \u2192 ${relPath} (${result.stats.wallClockTimeMs.toFixed(0)}ms total)
3273
3273
  `
3274
3274
  );
3275
- } else if (fmt === "json") {
3275
+ } else if (fmt2 === "json") {
3276
3276
  process.stdout.write(`${JSON.stringify(formatMatrixJson(result), null, 2)}
3277
3277
  `);
3278
- } else if (fmt === "png") {
3278
+ } else if (fmt2 === "png") {
3279
3279
  if (opts.sprite !== void 0) {
3280
3280
  } else {
3281
3281
  const { SpriteSheetGenerator: SpriteSheetGenerator2 } = await import('@agent-scope/render');
@@ -3283,9 +3283,9 @@ Available: ${available}`
3283
3283
  const sheet = await gen.generate(result);
3284
3284
  process.stdout.write(sheet.png);
3285
3285
  }
3286
- } else if (fmt === "html") {
3286
+ } else if (fmt2 === "html") {
3287
3287
  process.stdout.write(formatMatrixHtml(componentName, result));
3288
- } else if (fmt === "csv") {
3288
+ } else if (fmt2 === "csv") {
3289
3289
  process.stdout.write(formatMatrixCsv(componentName, result));
3290
3290
  }
3291
3291
  } catch (err) {
@@ -3586,12 +3586,12 @@ async function runBaseline(options = {}) {
3586
3586
  fs.mkdirSync(rendersDir, { recursive: true });
3587
3587
  let manifest$1;
3588
3588
  if (manifestPath !== void 0) {
3589
- const { readFileSync: readFileSync11 } = await import('fs');
3589
+ const { readFileSync: readFileSync12 } = await import('fs');
3590
3590
  const absPath = path.resolve(rootDir, manifestPath);
3591
3591
  if (!fs.existsSync(absPath)) {
3592
3592
  throw new Error(`Manifest not found at ${absPath}.`);
3593
3593
  }
3594
- manifest$1 = JSON.parse(readFileSync11(absPath, "utf-8"));
3594
+ manifest$1 = JSON.parse(readFileSync12(absPath, "utf-8"));
3595
3595
  process.stderr.write(`Loaded manifest from ${manifestPath}
3596
3596
  `);
3597
3597
  } else {
@@ -4225,6 +4225,135 @@ function registerDiffSubCommand(reportCmd) {
4225
4225
  }
4226
4226
  );
4227
4227
  }
4228
+ var STATUS_BADGE = {
4229
+ added: "\u2705 added",
4230
+ removed: "\u{1F5D1}\uFE0F removed",
4231
+ unchanged: "\u2014 unchanged",
4232
+ compliance_regressed: "\u274C regressed",
4233
+ compliance_improved: "\u{1F4C8} improved",
4234
+ size_changed: "\u{1F4D0} resized"
4235
+ };
4236
+ function fmt(n) {
4237
+ return `${(n * 100).toFixed(1)}%`;
4238
+ }
4239
+ function fmtDelta(delta) {
4240
+ if (delta === null) return "\u2014";
4241
+ const sign = delta >= 0 ? "+" : "";
4242
+ return `${sign}${(delta * 100).toFixed(1)}%`;
4243
+ }
4244
+ function fmtDimensions(d) {
4245
+ if (d === null) return "\u2014";
4246
+ return `${d.width} \xD7 ${d.height}`;
4247
+ }
4248
+ function complianceDeltaArrow(diff) {
4249
+ const delta = diff.currentAggregateCompliance - diff.baselineAggregateCompliance;
4250
+ if (Math.abs(delta) < 5e-4) return `\u2192 ${fmt(diff.currentAggregateCompliance)} (no change)`;
4251
+ const arrow = delta > 0 ? "\u2191" : "\u2193";
4252
+ return `${arrow} ${fmtDelta(delta)}`;
4253
+ }
4254
+ function formatPrComment(diff) {
4255
+ const { summary, components } = diff;
4256
+ const lines = [];
4257
+ const hasRegressions = diff.hasRegressions;
4258
+ const headerEmoji = hasRegressions ? "\u26A0\uFE0F" : "\u2705";
4259
+ lines.push(`## ${headerEmoji} Scope Report`);
4260
+ lines.push("");
4261
+ lines.push("| Metric | Value |");
4262
+ lines.push("|---|---|");
4263
+ lines.push(`| Baseline compliance | ${fmt(diff.baselineAggregateCompliance)} |`);
4264
+ lines.push(`| Current compliance | ${fmt(diff.currentAggregateCompliance)} |`);
4265
+ lines.push(`| Delta | ${complianceDeltaArrow(diff)} |`);
4266
+ lines.push(
4267
+ `| Components | ${summary.total} total \xB7 ${summary.added} added \xB7 ${summary.removed} removed \xB7 ${summary.complianceRegressed} regressed |`
4268
+ );
4269
+ if (summary.renderFailed > 0) {
4270
+ lines.push(`| Render failures | ${summary.renderFailed} |`);
4271
+ }
4272
+ lines.push("");
4273
+ const changed = components.filter((c) => c.status !== "unchanged");
4274
+ const unchanged = components.filter((c) => c.status === "unchanged");
4275
+ if (changed.length > 0) {
4276
+ lines.push("### Changes");
4277
+ lines.push("");
4278
+ lines.push("| Component | Status | Compliance \u0394 | Dimensions |");
4279
+ lines.push("|---|---|---|---|");
4280
+ for (const c of changed) {
4281
+ const badge = STATUS_BADGE[c.status];
4282
+ const delta = fmtDelta(c.complianceDelta);
4283
+ const dims = fmtDimensions(c.currentDimensions ?? c.baselineDimensions);
4284
+ lines.push(`| \`${c.name}\` | ${badge} | ${delta} | ${dims} |`);
4285
+ }
4286
+ lines.push("");
4287
+ }
4288
+ if (unchanged.length > 0) {
4289
+ lines.push(
4290
+ `<details><summary>${unchanged.length} unchanged component${unchanged.length === 1 ? "" : "s"}</summary>`
4291
+ );
4292
+ lines.push("");
4293
+ lines.push("| Component | Compliance |");
4294
+ lines.push("|---|---|");
4295
+ for (const c of unchanged) {
4296
+ lines.push(
4297
+ `| \`${c.name}\` | ${c.currentCompliance !== null ? fmt(c.currentCompliance) : "\u2014"} |`
4298
+ );
4299
+ }
4300
+ lines.push("");
4301
+ lines.push("</details>");
4302
+ lines.push("");
4303
+ }
4304
+ lines.push(
4305
+ `> Generated by [Scope](https://github.com/FlatFilers/Scope) \xB7 diffed at ${diff.diffedAt}`
4306
+ );
4307
+ return lines.join("\n");
4308
+ }
4309
+ function loadDiffResult(filePath) {
4310
+ const abs = path.resolve(filePath);
4311
+ if (!fs.existsSync(abs)) {
4312
+ throw new Error(`DiffResult file not found: ${abs}`);
4313
+ }
4314
+ let raw;
4315
+ try {
4316
+ raw = fs.readFileSync(abs, "utf-8");
4317
+ } catch (err) {
4318
+ throw new Error(
4319
+ `Failed to read DiffResult file: ${err instanceof Error ? err.message : String(err)}`
4320
+ );
4321
+ }
4322
+ let parsed;
4323
+ try {
4324
+ parsed = JSON.parse(raw);
4325
+ } catch {
4326
+ throw new Error(`DiffResult file is not valid JSON: ${abs}`);
4327
+ }
4328
+ if (typeof parsed !== "object" || parsed === null || !("diffedAt" in parsed) || !("components" in parsed) || !("summary" in parsed)) {
4329
+ throw new Error(
4330
+ `DiffResult file does not match expected shape (missing diffedAt/components/summary): ${abs}`
4331
+ );
4332
+ }
4333
+ return parsed;
4334
+ }
4335
+ function registerPrCommentSubCommand(reportCmd) {
4336
+ reportCmd.command("pr-comment").description(
4337
+ "Format a DiffResult JSON file as a GitHub PR comment (Markdown, written to stdout)"
4338
+ ).requiredOption("-i, --input <path>", "Path to DiffResult JSON (from scope report diff --json)").option("-o, --output <path>", "Write comment to file instead of stdout").action(async (opts) => {
4339
+ try {
4340
+ const diff = loadDiffResult(opts.input);
4341
+ const comment = formatPrComment(diff);
4342
+ if (opts.output !== void 0) {
4343
+ fs.writeFileSync(path.resolve(opts.output), comment, "utf-8");
4344
+ process.stderr.write(`PR comment written to ${opts.output}
4345
+ `);
4346
+ } else {
4347
+ process.stdout.write(`${comment}
4348
+ `);
4349
+ }
4350
+ } catch (err) {
4351
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4352
+ `);
4353
+ process.exit(1);
4354
+ }
4355
+ });
4356
+ }
4228
4357
 
4229
4358
  // src/tree-formatter.ts
4230
4359
  var BRANCH2 = "\u251C\u2500\u2500 ";
@@ -5520,6 +5649,7 @@ function createProgram(options = {}) {
5520
5649
  if (existingReportCmd !== void 0) {
5521
5650
  registerBaselineSubCommand(existingReportCmd);
5522
5651
  registerDiffSubCommand(existingReportCmd);
5652
+ registerPrCommentSubCommand(existingReportCmd);
5523
5653
  }
5524
5654
  return program;
5525
5655
  }