serve-question: self-detect headless environments, capability-first routing

The env-var bypass (IMPECCABLE_QUESTION_DISABLED) relied on the harness
remembering to set it. The script now also self-detects CI, SSH-without-
display, and displayless Linux and exits 2 with the structured-question
advice; --no-open skips detection (caller opens the URL itself, as the
tests do) and IMPECCABLE_QUESTION_FORCE=1 overrides it. new-work.md now
frames the decision-page rule by capability: open a browser if you can,
structured question tool if you cannot, exit 2 means fallback not error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-07-21 20:53:37 -07:00
co-authored by Claude Fable 5
parent 40ba97db20
commit b0a7deb688
2 changed files with 17 additions and 2 deletions
+16 -1
View File
@@ -9,7 +9,10 @@
*
* ANSWER: {"optionId":"...","steer":"..."}
*
* Exit codes: 0 answered · 2 timed out or closed without answering.
* Exit codes: 0 answered · 2 timed out, closed without answering, or no
* browser is available (IMPECCABLE_QUESTION_DISABLED, or a detected
* CI/headless/remote environment; IMPECCABLE_QUESTION_FORCE=1 overrides
* detection, --no-open skips it since the caller opens the URL itself).
*
* Payload (JSON file via --payload, or stdin):
* {
@@ -72,6 +75,18 @@ if (process.env.IMPECCABLE_QUESTION_DISABLED) {
console.log('serve-question: disabled in this session (no browser); use the structured question tool instead.');
process.exit(2);
}
// Headless self-detection: --no-open means the caller opens the URL itself,
// so only environments that would need a browser opened for them are checked.
if (!process.argv.includes('--no-open') && !process.env.IMPECCABLE_QUESTION_FORCE) {
const headless =
process.env.CI ||
(process.env.SSH_CONNECTION && !process.env.DISPLAY) ||
(process.platform === 'linux' && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY);
if (headless) {
console.log('serve-question: no browser detected in this environment (CI/headless/remote); use the structured question tool instead. Set IMPECCABLE_QUESTION_FORCE=1 to serve anyway.');
process.exit(2);
}
}
const payloadPath = arg('payload');
const timeoutSec = Number(arg('timeout', '900'));