scenescout 3.15.0 → 3.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/CHANGELOG.md +75 -0
- package/README.md +64 -15
- package/dist/browsers.js +28 -0
- package/dist/check-run.js +190 -14
- package/dist/ci-run.js +268 -52
- package/dist/cli.js +104 -43
- package/dist/commands.js +3 -2
- package/dist/engine/baseline.js +377 -0
- package/dist/engine/brief.js +16 -7
- package/dist/engine/browser.js +1147 -286
- package/dist/engine/calibration.js +61 -30
- package/dist/engine/capture.js +164 -0
- package/dist/engine/check.js +182 -39
- package/dist/engine/ci-lanes.js +215 -0
- package/dist/engine/ci.js +136 -18
- package/dist/engine/claims.js +159 -3
- package/dist/engine/collector.js +561 -30
- package/dist/engine/crawl.js +49 -0
- package/dist/engine/design.js +281 -38
- package/dist/engine/export.js +877 -0
- package/dist/engine/fingerprint.js +92 -4
- package/dist/engine/flow.js +18 -6
- package/dist/engine/forms.js +181 -18
- package/dist/engine/journey.js +29 -1
- package/dist/engine/lane.js +13 -3
- package/dist/engine/launch.js +45 -6
- package/dist/engine/limits.js +7 -0
- package/dist/engine/live-page.js +49 -2
- package/dist/engine/live.js +4 -1
- package/dist/engine/memory.js +501 -47
- package/dist/engine/open.js +118 -0
- package/dist/engine/oracles.js +41 -1
- package/dist/engine/plain.js +268 -0
- package/dist/engine/png.js +127 -0
- package/dist/engine/policy.js +379 -9
- package/dist/engine/probes.js +3 -2
- package/dist/engine/profiles.js +45 -9
- package/dist/engine/project-folder.js +191 -0
- package/dist/engine/refresh.js +68 -3
- package/dist/engine/replay.js +63 -10
- package/dist/engine/report.js +241 -40
- package/dist/engine/request.js +317 -23
- package/dist/engine/sarif.js +120 -0
- package/dist/engine/settle.js +67 -0
- package/dist/engine/signed-in.js +256 -0
- package/dist/engine/tickets.js +671 -0
- package/dist/engine/unload.js +3 -2
- package/dist/export-run.js +633 -0
- package/dist/first-run.js +4 -0
- package/dist/installer.js +267 -3
- package/dist/intake.js +104 -0
- package/dist/login-run.js +250 -36
- package/dist/mcp-server.js +567 -57
- package/dist/playbook.js +5 -0
- package/package.json +6 -3
- package/skills/scenescout/SKILL.md +49 -16
package/dist/engine/live-page.js
CHANGED
|
@@ -173,9 +173,17 @@ export const LIVE_PAGE = `<!doctype html>
|
|
|
173
173
|
#report .doc details { margin: 8px 0; }
|
|
174
174
|
#report .doc summary { cursor: pointer; color: var(--muted); }
|
|
175
175
|
#report .doc .unset { color: var(--muted); font-style: italic; }
|
|
176
|
+
#report .doc figure.picture { margin: 8px 0 14px; max-width: min(100%, 720px); }
|
|
177
|
+
#report .doc figure.picture img { display: block; max-width: 100%; height: auto; border: 1px solid var(--line); border-radius: 6px; }
|
|
178
|
+
#report .doc figure.picture figcaption { margin-top: 4px; font-size: 12px; color: var(--muted); }
|
|
179
|
+
#report .doc figure.picture .gone-note { display: none; padding: 12px; border: 1px dashed var(--line); border-radius: 6px; color: var(--muted); }
|
|
180
|
+
#report .doc figure.picture.gone img { display: none; }
|
|
181
|
+
#report .doc figure.picture.gone .gone-note { display: block; }
|
|
176
182
|
#report .doc details.evidence { margin: 10px 0 16px; padding: 8px 12px; background: var(--panel); border: 1px solid var(--line); border-radius: 6px; }
|
|
177
183
|
#report .doc details.evidence[open] summary { margin-bottom: 10px; }
|
|
178
184
|
#report .doc details.evidence figure { margin: 0 0 12px; }
|
|
185
|
+
#report .doc figure.picture { margin: 8px 0 14px; max-width: 640px; }
|
|
186
|
+
#report .doc figure.picture img { display: block; width: auto; max-width: 100%; max-height: 360px; border: 1px solid var(--line); border-radius: 6px; }
|
|
179
187
|
#report .doc details.evidence .shots { display: flex; flex-wrap: wrap; gap: 14px; }
|
|
180
188
|
#report .doc details.evidence figure { flex: 1 1 320px; max-width: 440px; }
|
|
181
189
|
#report .doc details.evidence img { display: block; width: 100%; max-height: 280px; object-fit: cover; object-position: top;
|
|
@@ -494,7 +502,28 @@ export const LIVE_PAGE = `<!doctype html>
|
|
|
494
502
|
function evidenceFor(id) {
|
|
495
503
|
var found = null;
|
|
496
504
|
reportEvidence.forEach(function (e) { if (e.id === id) found = e; });
|
|
497
|
-
if (!found
|
|
505
|
+
if (!found) return null;
|
|
506
|
+
// The picture taken when it was filed comes first, open: it is what a reader looks for.
|
|
507
|
+
var picture = null;
|
|
508
|
+
if (found.picture) {
|
|
509
|
+
picture = el('figure', 'picture');
|
|
510
|
+
picture.setAttribute('data-testid', 'live-report-picture-' + id);
|
|
511
|
+
var link = el('a');
|
|
512
|
+
link.href = 'record/' + found.picture.file;
|
|
513
|
+
link.target = '_blank';
|
|
514
|
+
link.rel = 'noreferrer';
|
|
515
|
+
link.setAttribute('data-testid', 'live-report-picture-open');
|
|
516
|
+
var pic = el('img');
|
|
517
|
+
pic.loading = 'lazy';
|
|
518
|
+
pic.src = 'record/' + found.picture.file;
|
|
519
|
+
pic.alt = 'What the finding is about, when it was filed';
|
|
520
|
+
pic.addEventListener('error', function () { picture.classList.add('gone'); });
|
|
521
|
+
link.appendChild(pic);
|
|
522
|
+
picture.appendChild(link);
|
|
523
|
+
picture.appendChild(el('figcaption', '', found.picture.caption));
|
|
524
|
+
picture.appendChild(el('p', 'gone-note', 'This picture is no longer in ' + found.picture.file.replace(/\\/[^/]*$/, '') + '.'));
|
|
525
|
+
}
|
|
526
|
+
if (!found.frames.length) return picture;
|
|
498
527
|
var box = el('details', 'evidence');
|
|
499
528
|
box.setAttribute('data-testid', 'live-report-evidence-' + id);
|
|
500
529
|
box.appendChild(el('summary', '', found.frames.length + (found.frames.length === 1 ? ' screenshot' : ' screenshots') + ' from around this finding'));
|
|
@@ -514,7 +543,11 @@ export const LIVE_PAGE = `<!doctype html>
|
|
|
514
543
|
fig.appendChild(el('p', 'gone-note', 'This frame is no longer in ' + f.frame.replace(/\\/[^/]*$/, '') + '.'));
|
|
515
544
|
shots.appendChild(fig);
|
|
516
545
|
});
|
|
517
|
-
return box;
|
|
546
|
+
if (!picture) return box;
|
|
547
|
+
var both = el('div');
|
|
548
|
+
both.appendChild(picture);
|
|
549
|
+
both.appendChild(box);
|
|
550
|
+
return both;
|
|
518
551
|
}
|
|
519
552
|
function renderMarkdown(root, md) {
|
|
520
553
|
root.textContent = '';
|
|
@@ -567,6 +600,20 @@ export const LIVE_PAGE = `<!doctype html>
|
|
|
567
600
|
inline(h, m[2]);
|
|
568
601
|
container.appendChild(h);
|
|
569
602
|
i += 1;
|
|
603
|
+
} else if ((m = /^!\\[([^\\]]*)\\]\\((recordings\\/[A-Za-z0-9._\\/-]+)\\)$/.exec(line)) && m[2].indexOf('..') < 0) {
|
|
604
|
+
// A finding's picture from the run's recording, served by the frame
|
|
605
|
+
// route. Any other picture is a file this view cannot serve.
|
|
606
|
+
flush();
|
|
607
|
+
var fig = el('figure', 'picture');
|
|
608
|
+
var pic = el('img');
|
|
609
|
+
pic.loading = 'lazy';
|
|
610
|
+
pic.src = 'record/' + m[2];
|
|
611
|
+
pic.alt = m[1];
|
|
612
|
+
fig.appendChild(pic);
|
|
613
|
+
container.appendChild(fig);
|
|
614
|
+
i += 1;
|
|
615
|
+
} else if (/^!\\[[^\\]]*\\]\\([^)]*\\)$/.test(line)) {
|
|
616
|
+
i += 1;
|
|
570
617
|
} else if ((m = /^<details><summary>(.*)<\\/summary>$/.exec(line))) {
|
|
571
618
|
flush();
|
|
572
619
|
var details = el('details');
|
package/dist/engine/live.js
CHANGED
|
@@ -27,6 +27,7 @@ import fs from "node:fs";
|
|
|
27
27
|
import http from "node:http";
|
|
28
28
|
import path from "node:path";
|
|
29
29
|
import { LIVE_PAGE } from "./live-page.js";
|
|
30
|
+
import { isPng } from "./png.js";
|
|
30
31
|
import { JOURNEY_END, JOURNEY_START, TASK_SET } from "./memory.js";
|
|
31
32
|
/** Holds the live view's token, next to status.json. Written owner-only; removed when the engine shuts down. */
|
|
32
33
|
export const LIVE_TOKEN_FILE = "live-token";
|
|
@@ -477,7 +478,9 @@ export class LiveServer {
|
|
|
477
478
|
const jpeg = await this.provider.frame(asked);
|
|
478
479
|
if (!jpeg)
|
|
479
480
|
return this.send(res, 404, "no such frame");
|
|
480
|
-
|
|
481
|
+
// Frames are JPEG; a finding's picture is PNG (capture.ts), and is labelled as one.
|
|
482
|
+
const type = isPng(jpeg) ? "image/png" : "image/jpeg";
|
|
483
|
+
return this.send(res, 200, jpeg, type, { "Content-Length": jpeg.length, "Cache-Control": "private, max-age=3600" });
|
|
481
484
|
}
|
|
482
485
|
if (route === "events" && !name) {
|
|
483
486
|
const wanted = this.param(req, "sessions");
|