Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions bin/contributor-relay.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,14 @@ function blockingPromptKey(text) {
// persists, so this prompt stops coming back on every restart the way a
// plain "Skip" would.
if (/Update available!/.test(text) && /Skip until next version/.test(text)) return '3';
const recent = paneTail(text, 15);
// agy: "Terms of Service & Data Use" ends on a [Previous] [Done] button row
// with focus on the CHECKBOX above it, where Enter toggles consent instead of
// advancing ("enter Toggle"). A bare Enter therefore never leaves this page.
// Down moves to the button row, Right selects [Done]; the caller appends
// Enter. The other two steps (theme picker, folder trust) do advance on a
// bare Enter and deliberately fall through to null.
if (BACKEND === 'agy' && /Terms of Service & Data Use/.test(recent) && /\[(?:Previous|Back)\]\s+\[Done\]/.test(recent)) return 'Down Right';
return null;
}

Expand Down Expand Up @@ -1449,9 +1457,18 @@ function getCLIState() {
} else if (BACKEND === 'pi') {
if (/pi v\d|0\.0%|auto\)|\d+\.\d+%/.test(text)) return 'ready';
} else if (BACKEND === 'agy') {
// Antigravity gates first run behind login plus a three-step wizard, and
// every agent that shares a $HOME can re-enter it whenever another agent
// writes antigravity-cli/cache/onboarding.json mode 600. Check the
// visible tail only: old task output may quote the wizard text, and a
// stale quote must not make a live prompt look blocked.
const recent = paneTail(text, 15);
if (/not signed in|Select login method/i.test(recent)) return 'needs-login';
if (/Choose your color scheme|Terms of Service & Data Use|Do you trust the contents|I trust this (?:folder|directory)|Welcome to (?:the )?Antigravity/i.test(recent)) return 'onboarding';
// agy shows "? for shortcuts" at the bottom when its interactive prompt
// is ready. The generic />\s*$/ fires too early (during the splash).
if (/\? for shortcuts/.test(text)) return 'ready';
// is ready. The generic />\s*$/ fires too early during splash, and the
// wizard's selection cursor is also ❯.
if (/\? for shortcuts/.test(recent)) return 'ready';
} else {
if (/>\s*$|❯|\$\s*$/.test(text)) return 'ready';
}
Expand Down
82 changes: 82 additions & 0 deletions bin/contributor-relay.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2590,6 +2590,33 @@ const CODEX_UPDATE_PANE = [
' Press enter to continue',
].join('\n');

const AGY_READY_PANE = [
'Antigravity CLI',
'',
'> ',
'? for shortcuts',
].join('\n');

const AGY_TOS_PANE = [
'Welcome to Antigravity',
'Terms of Service & Data Use',
'',
'[ ] I agree to the Terms of Service',
'',
'[Previous] [Done]',
].join('\n');

const AGY_TRUST_PANE = [
'Do you trust the contents of this directory?',
'',
'[I trust this directory]',
].join('\n');

const AGY_LOGIN_PANE = [
'You are not signed in',
'Select login method',
].join('\n');

const CODEX_COMPLETED_NO_WORK_PANE = [
'• Running GH_TOKEN=... gh issue view 4065 --repo kubestellar/hive',
'',
Expand Down Expand Up @@ -2631,6 +2658,61 @@ test('codex numbered startup menus get explicit safe selections', () => {
} finally { teardown(relay); }
});

test('agy startup gates are classified before readiness, using only the visible tail', () => {
const cases = [
[AGY_LOGIN_PANE, 'needs-login'],
[AGY_TOS_PANE, 'onboarding'],
[AGY_TRUST_PANE, 'onboarding'],
[AGY_READY_PANE, 'ready'],
];
for (const [pane, want] of cases) {
const relay = loadRelay({ backend: 'agy', cliStates: [pane] });
try {
assert.strictEqual(relay.getCLIState(), want);
} finally { teardown(relay); }
}
});

test('agy ready gate does not fire on splash or wizard cursor', () => {
for (const pane of [
'Antigravity CLI\nloading workspace...\n',
'Choose your color scheme\n❯ Dark\n Light\n',
]) {
const relay = loadRelay({ backend: 'agy', cliStates: [pane] });
try {
assert.notStrictEqual(relay.getCLIState(), 'ready',
'splash text and wizard cursors must not be treated as an idle agy prompt');
} finally { teardown(relay); }
}
});

test('agy onboarding prose in old scrollback does not override a ready tail', () => {
const pane = [
'Earlier task output quoted Terms of Service & Data Use and [Done].',
...Array.from({ length: 20 }, (_, i) => `ordinary output line ${i}`),
AGY_READY_PANE,
].join('\n');
const relay = loadRelay({ backend: 'agy', cliStates: [pane] });
try {
assert.strictEqual(relay.getCLIState(), 'ready');
assert.strictEqual(relay.blockingPromptKey(pane), null);
} finally { teardown(relay); }
});

test('agy ToS wizard selects Done, but non-agy or prose matches do not', () => {
const agy = loadRelay({ backend: 'agy' });
try {
assert.strictEqual(agy.blockingPromptKey(AGY_TOS_PANE), 'Down Right');
assert.strictEqual(agy.blockingPromptKey('Terms of Service & Data Use\n[Done] appears in a task summary'), null);
assert.strictEqual(agy.blockingPromptKey('Terms of Service & Data Use mentioned without the button row'), null);
} finally { teardown(agy); }

const codex = loadRelay({ backend: 'codex' });
try {
assert.strictEqual(codex.blockingPromptKey(AGY_TOS_PANE), null);
} finally { teardown(codex); }
});

test('codex no-work verdict is COMPLETE despite stale activity in scrollback', () => {
const relay = loadRelay({ backend: 'codex' });
try {
Expand Down
1 change: 1 addition & 0 deletions changelog.d/fixed-5661-agy-onboarding-wizard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- The contributor relay can now recognize and safely dismiss Antigravity (`agy`) first-run login/onboarding panes without mistaking splash text or wizard cursors for a ready prompt ([#5661](https://github.com/kubestellar/hive/pull/5661)). The ready gate remains the documented `? for shortcuts` footer, onboarding checks are scoped to the visible tail, and the Terms/Data Use page selects the `[Done]` button row rather than toggling the checkbox forever.
Loading