mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-26 14:50:55 +02:00
v1.87.5.0 perf: remove idle waits from tests and CI planning (#2897)
* v1.87.5.0 perf: remove idle waits from tests and CI planning * fix: settle split PTY redraws before routing input * docs: record final burst-safe test benchmarks * fix: keep cold-setup snapshot metadata dependency-free * fix: avoid early-reader pipe races in artifact URL parsing * fix: preserve safety matches for multiline command payloads * fix: recognize concurrent CSO publication removal * test: preload the UI design-review target before invocation * docs: record validation blocker fixes * fix: bind plan observer rejection to the invoked command * fix: count only native design decisions in the UI gate * docs: clarify UI-positive eval evidence requirements * test: recognize native UI decisions without weakening finding counts * test: decouple native UI evidence from question punctuation * test: recognize concrete native UI decisions independently of prose format * fix: retain failed eval logs under the hidden CI cache * test: await telemetry completion instead of racing disk writes
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
export interface SnapshotOptions {
|
||||
interactive?: boolean;
|
||||
compact?: boolean;
|
||||
depth?: number;
|
||||
selector?: string;
|
||||
diff?: boolean;
|
||||
annotate?: boolean;
|
||||
outputPath?: string;
|
||||
cursorInteractive?: boolean;
|
||||
heatmap?: string;
|
||||
}
|
||||
|
||||
export const SNAPSHOT_FLAGS: Array<{
|
||||
short: string;
|
||||
long: string;
|
||||
description: string;
|
||||
takesValue?: boolean;
|
||||
valueHint?: string;
|
||||
optionKey: keyof SnapshotOptions;
|
||||
}> = [
|
||||
{ short: '-i', long: '--interactive', description: 'Interactive elements only (buttons, links, inputs) with @e refs. Also auto-enables cursor-interactive scan (-C) to capture dropdowns and popovers.', optionKey: 'interactive' },
|
||||
{ short: '-c', long: '--compact', description: 'Compact (no empty structural nodes)', optionKey: 'compact' },
|
||||
{ short: '-d', long: '--depth', description: 'Limit tree depth (0 = root only, default: unlimited)', takesValue: true, valueHint: '<N>', optionKey: 'depth' },
|
||||
{ short: '-s', long: '--selector', description: 'Scope to CSS selector', takesValue: true, valueHint: '<sel>', optionKey: 'selector' },
|
||||
{ short: '-D', long: '--diff', description: 'Unified diff against previous snapshot (first call stores baseline)', optionKey: 'diff' },
|
||||
{ short: '-a', long: '--annotate', description: 'Annotated screenshot with red overlay boxes and ref labels', optionKey: 'annotate' },
|
||||
{ short: '-o', long: '--output', description: 'Output path for annotated screenshot (default: <temp>/browse-annotated.png)', takesValue: true, valueHint: '<path>', optionKey: 'outputPath' },
|
||||
{ short: '-C', long: '--cursor-interactive', description: 'Cursor-interactive elements (@c refs — divs with pointer, onclick). Auto-enabled when -i is used.', optionKey: 'cursorInteractive' },
|
||||
{ short: '-H', long: '--heatmap', description: 'Color-coded overlay screenshot from JSON map: \'{"@e1":"green","@e3":"red"}\'. Valid colors: green, yellow, red, blue, orange, gray.', takesValue: true, valueHint: '<json>', optionKey: 'heatmap' },
|
||||
];
|
||||
+3
-38
@@ -24,6 +24,9 @@ import { TEMP_DIR, isPathWithin } from './platform';
|
||||
import { escapeEnvelopeSentinels } from './content-security';
|
||||
import { stripLoneSurrogates } from './sanitize';
|
||||
import { guardScreenshotPath } from './screenshot-size-guard';
|
||||
import { SNAPSHOT_FLAGS, type SnapshotOptions } from './snapshot-flags';
|
||||
|
||||
export { SNAPSHOT_FLAGS } from './snapshot-flags';
|
||||
|
||||
// Roles considered "interactive" for the -i flag
|
||||
const INTERACTIVE_ROLES = new Set([
|
||||
@@ -33,44 +36,6 @@ const INTERACTIVE_ROLES = new Set([
|
||||
'treeitem',
|
||||
]);
|
||||
|
||||
interface SnapshotOptions {
|
||||
interactive?: boolean; // -i: only interactive elements
|
||||
compact?: boolean; // -c: remove empty structural elements
|
||||
depth?: number; // -d N: limit tree depth
|
||||
selector?: string; // -s SEL: scope to CSS selector
|
||||
diff?: boolean; // -D / --diff: diff against last snapshot
|
||||
annotate?: boolean; // -a / --annotate: annotated screenshot
|
||||
outputPath?: string; // -o / --output: path for annotated screenshot
|
||||
cursorInteractive?: boolean; // -C / --cursor-interactive: scan cursor:pointer etc.
|
||||
heatmap?: string; // -H / --heatmap: JSON color map for ref overlays
|
||||
}
|
||||
|
||||
/**
|
||||
* Snapshot flag metadata — single source of truth for CLI parsing and doc generation.
|
||||
*
|
||||
* Imported by:
|
||||
* - gen-skill-docs.ts (generates {{SNAPSHOT_FLAGS}} tables)
|
||||
* - skill-parser.ts (validates flags in SKILL.md examples)
|
||||
*/
|
||||
export const SNAPSHOT_FLAGS: Array<{
|
||||
short: string;
|
||||
long: string;
|
||||
description: string;
|
||||
takesValue?: boolean;
|
||||
valueHint?: string;
|
||||
optionKey: keyof SnapshotOptions;
|
||||
}> = [
|
||||
{ short: '-i', long: '--interactive', description: 'Interactive elements only (buttons, links, inputs) with @e refs. Also auto-enables cursor-interactive scan (-C) to capture dropdowns and popovers.', optionKey: 'interactive' },
|
||||
{ short: '-c', long: '--compact', description: 'Compact (no empty structural nodes)', optionKey: 'compact' },
|
||||
{ short: '-d', long: '--depth', description: 'Limit tree depth (0 = root only, default: unlimited)', takesValue: true, valueHint: '<N>', optionKey: 'depth' },
|
||||
{ short: '-s', long: '--selector', description: 'Scope to CSS selector', takesValue: true, valueHint: '<sel>', optionKey: 'selector' },
|
||||
{ short: '-D', long: '--diff', description: 'Unified diff against previous snapshot (first call stores baseline)', optionKey: 'diff' },
|
||||
{ short: '-a', long: '--annotate', description: 'Annotated screenshot with red overlay boxes and ref labels', optionKey: 'annotate' },
|
||||
{ short: '-o', long: '--output', description: 'Output path for annotated screenshot (default: <temp>/browse-annotated.png)', takesValue: true, valueHint: '<path>', optionKey: 'outputPath' },
|
||||
{ short: '-C', long: '--cursor-interactive', description: 'Cursor-interactive elements (@c refs — divs with pointer, onclick). Auto-enabled when -i is used.', optionKey: 'cursorInteractive' },
|
||||
{ short: '-H', long: '--heatmap', description: 'Color-coded overlay screenshot from JSON map: \'{"@e1":"green","@e3":"red"}\'. Valid colors: green, yellow, red, blue, orange, gray.', takesValue: true, valueHint: '<json>', optionKey: 'heatmap' },
|
||||
];
|
||||
|
||||
interface ParsedNode {
|
||||
indent: number;
|
||||
role: string;
|
||||
|
||||
@@ -97,10 +97,10 @@ export interface TelemetryEvent {
|
||||
}
|
||||
|
||||
/** Fire-and-forget log. Never throws. */
|
||||
export function logTelemetry(payload: TelemetryEvent): void {
|
||||
if (isTelemetryDisabled()) return;
|
||||
export function logTelemetry(payload: TelemetryEvent): Promise<void> {
|
||||
if (isTelemetryDisabled()) return Promise.resolve();
|
||||
const enriched = { ...payload, ts: new Date().toISOString() };
|
||||
ensureDir()
|
||||
return ensureDir()
|
||||
.then(() => fs.appendFile(telemetryFile(), JSON.stringify(enriched) + '\n', 'utf8'))
|
||||
.catch(() => {
|
||||
// Telemetry must never crash the caller. If the disk is full or perms
|
||||
|
||||
Reference in New Issue
Block a user