Files
gstack/test/helpers/design-count-outside.ts
T
Garry Tan 35dd014c58 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
2026-09-21 12:27:25 -04:00

43 lines
2.5 KiB
TypeScript

import type { AskUserQuestionFingerprint } from './claude-pty-runner';
/** Seeded-count fixtures cover native review cadence; outside voices have separate evals. */
export function pickDesignCountOutsideVoices(
_routing: AskUserQuestionFingerprint,
active: AskUserQuestionFingerprint,
): number | null {
const call = active.nativeCall;
let question: string;
let labels: string[];
if (call) {
if (call.answered || call.failed) return null;
const index = active.nativeQuestionIndex ?? (call.questions.length === 1 ? 0 : undefined);
if (index === undefined || !Number.isInteger(index) || index < 0 || index >= call.questions.length) return null;
const identity = `${call.sessionId}:${call.toolUseId}` +
(call.questions.length > 1 ? `:question:${index}` : '');
if (active.signature !== identity) return null;
const q = call.questions[index]!;
if (q.multiSelect || !/^outside(?: design)? voices$/i.test(q.header.trim()) ||
!/<gstack-qid:(?:outside-voices-design|plan-design-review-outside-voices)>/.test(q.question)) return null;
question = q.question;
labels = q.options.map(option => option.label);
} else {
// Native JSONL can arrive after the answer. The caller supplies the
// active viewport fingerprint; a known but unmatched packet is blocked
// before this hook. Require the specific opt-in premise and both actions.
question = active.promptSnippet;
const packetBar = /^←[^→]*[☐☒]\s+Outside voices\b[^→]*✔\s*Submit\s*→\s*[│┃]?\s*/i.exec(question);
if (packetBar) question = question.slice(packetBar[0].length);
else if (!/^(?:[☐□]\s*)?outside(?: design)? voices\b/i.test(question)) return null;
labels = active.options.map(option => option.label);
while (labels.length > 2 && /^(?:Type something\.?|Chat about this)$/i.test(labels.at(-1)!.trim())) labels.pop();
}
if (!/\b(?:want|run|include|enable)\b[^?]{0,90}\boutside(?: design)? voices\b/i.test(question) ||
!/\b(?:before|for)\s+(?:the\s+)?(?:detailed\s+)?(?:design\s+)?review\b/i.test(question)) return null;
labels = labels.map(label => label.trim().replace(/\s*\(recommended\)\s*$/i, ''));
if (labels.length !== 2) return null;
const yes = labels.map(label => /^Yes,?\s+run outside(?: design)? voices$/i.test(label));
const no = labels.map(label => /^No,?\s+proceed without$/i.test(label));
if (yes.filter(Boolean).length !== 1 || no.filter(Boolean).length !== 1) return null;
return no.findIndex(Boolean) + 1;
}