@hackerrank/astra-cli 0.1.11 → 0.1.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hackerrank/astra-cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Minimal zero-dependency AI coding agent for the HackerRank AI Gateway.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/report.html CHANGED
@@ -85,8 +85,8 @@
85
85
  </section>
86
86
 
87
87
  <section>
88
- <h2>Test-case results <span class="sub">passed, failed, blocked, and errored criteria by model</span></h2>
89
- <div id="verifier-model-pills" class="model-pills"></div>
88
+ <h2>Test-case results <span class="sub">points earned by one selected model</span></h2>
89
+ <div class="toolbar"><label for="verifier-model-select">Model</label><select id="verifier-model-select"></select></div>
90
90
  <div class="panel">
91
91
  <table id="tbl-verifier-matrix"></table>
92
92
  </div>
@@ -312,31 +312,30 @@
312
312
  // ---------------------------------------------------------------- verifier test-case matrix
313
313
  (function () {
314
314
  var container = document.getElementById("tbl-verifier-matrix");
315
- var pills = document.getElementById("verifier-model-pills");
315
+ var selector = document.getElementById("verifier-model-select");
316
316
  if (!container) return;
317
317
  var matrix = DATA.verifier_matrix || { models: [], criteria: [] };
318
- var active = matrix.models.slice();
319
- function cellHtml(cell) {
320
- if (!cell) return '<div class="criterion-cell na">NA</div>';
321
- var rate = cell.total ? Math.round(cell.passed / cell.total * 100) : 0;
322
- var cls = rate === 100 ? "pass" : (cell.failed || cell.blocked || cell.error ? "fail" : "na");
323
- return '<div class="criterion-cell ' + cls + '"><span class="rate">' + rate + '%</span><span class="counts">' + cell.passed + ' pass · ' + (cell.failed + cell.blocked + cell.error) + ' fail</span></div>';
324
- }
318
+ // Prefer a model with actual verifier evidence. Alphabetical-first often
319
+ // selects an unscored gateway failure and makes a healthy report appear
320
+ // empty on first open.
321
+ var selected = matrix.models.find(function (model) {
322
+ return matrix.criteria.some(function (criterion) { return criterion.cells[model]; });
323
+ }) || matrix.models[0] || "";
325
324
  function draw() {
326
- var visible = matrix.models.filter(function (model) { return active.indexOf(model) !== -1; });
327
- container.innerHTML = '<thead><tr><th>Test case</th>' + visible.map(function (model) { return '<th><span class="mono">' + esc(model) + '</span></th>'; }).join('') + '</tr></thead>' +
328
- '<tbody>' + matrix.criteria.map(function (criterion) { return '<tr><td><div class="mono">' + esc(criterion.id) + '</div><div class="sub">' + esc(criterion.title || criterion.id) + '</div></td>' + visible.map(function (model) { return '<td>' + cellHtml(criterion.cells[model]) + '</td>'; }).join('') + '</tr>'; }).join('') + '</tbody>';
325
+ container.innerHTML = '<thead><tr><th>Test case</th><th>Available</th><th>Earned</th><th>Result</th></tr></thead><tbody>' + matrix.criteria.map(function (criterion) {
326
+ var cell = criterion.cells[selected];
327
+ if (!cell) return '<tr><td>' + esc(criterion.title || criterion.id) + '</td><td class="n-a">NA</td><td class="n-a">NA</td><td class="n-a">Unscored</td></tr>';
328
+ var max = cell.maxPoints || 0, earned = cell.earnedPoints || 0;
329
+ var status = cell.passed === cell.total ? 'Passed' : (cell.error ? 'Errored' : cell.blocked ? 'Blocked' : 'Failed');
330
+ return '<tr><td>' + esc(criterion.title || criterion.id) + '</td><td>' + fmt1(max) + '</td><td>' + fmt1(earned) + '</td><td>' + esc(status) + '</td></tr>';
331
+ }).join('') + '</tbody>';
329
332
  }
330
- matrix.models.forEach(function (model, index) {
331
- var pill = el("button", { class: "model-pill active", type: "button" }, esc(model));
332
- pill.addEventListener("click", function () {
333
- var pos = active.indexOf(model);
334
- if (pos === -1) { active.push(model); pill.classList.add("active"); }
335
- else if (active.length > 1) { active.splice(pos, 1); pill.classList.remove("active"); }
336
- draw();
337
- });
338
- pills.appendChild(pill);
333
+ matrix.models.forEach(function (model) {
334
+ var option = el("option", { value: model }, esc(model));
335
+ if (model === selected) option.selected = true;
336
+ selector.appendChild(option);
339
337
  });
338
+ selector.addEventListener("change", function () { selected = selector.value; draw(); });
340
339
  if (!matrix.criteria.length) {
341
340
  container.innerHTML = '<tbody><tr><td class="muted">No verifier criteria have produced results yet.</td></tr></tbody>';
342
341
  return;
package/src/report.js CHANGED
@@ -264,7 +264,10 @@ export function renderReportHtml(summary) {
264
264
  if (!tpl.includes("/*__ASTRA_DATA__*/")) {
265
265
  throw new Error("src/report.html is missing the /*__ASTRA_DATA__*/ injection marker");
266
266
  }
267
- return tpl.replace("/*__ASTRA_DATA__*/", `window.__ASTRA_EMBEDDED_DATA__ = ${data};`);
267
+ // Use a callback replacement: a report payload can contain shell snippets
268
+ // such as `$'...'` or `$&`, which String.replace treats as replacement
269
+ // tokens when given a plain string and can therefore corrupt the HTML.
270
+ return tpl.replace("/*__ASTRA_DATA__*/", () => `window.__ASTRA_EMBEDDED_DATA__ = ${data};`);
268
271
  }
269
272
 
270
273
  function toRunDoc(run) {
@@ -540,9 +543,12 @@ function buildVerifierMatrix(runs) {
540
543
  if (!byCriterion.has(criterion.id)) byCriterion.set(criterion.id, { title: criterion.title || criterion.id, byModel: new Map() });
541
544
  const entry = byCriterion.get(criterion.id);
542
545
  const byModel = entry.byModel;
543
- if (!byModel.has(run.slug)) byModel.set(run.slug, { passed: 0, failed: 0, blocked: 0, error: 0, total: 0 });
546
+ if (!byModel.has(run.slug)) byModel.set(run.slug, { passed: 0, failed: 0, blocked: 0, error: 0, total: 0, maxPoints: 0, earnedPoints: 0 });
544
547
  const cell = byModel.get(run.slug);
545
548
  cell.total += 1;
549
+ const weight = Math.max(0, Number(criterion.weight) || 0);
550
+ cell.maxPoints += weight;
551
+ if (criterion.status === "passed") cell.earnedPoints += weight;
546
552
  if (criterion.status === "passed") cell.passed += 1;
547
553
  else if (criterion.status === "blocked") cell.blocked += 1;
548
554
  else if (criterion.status === "error") cell.error += 1;