mirror of
https://github.com/stablyai/orca.git
synced 2026-09-28 00:02:41 +00:00
fix(renderer): stop formatted source code reading as a credential prompt
Mining 16,206 distinct credential-vocabulary lines out of this repo's own tracked files and placing each one row above a real agent composer caret produced **100 refusals across 25 distinct lines**, on Codex, Claude Code and OpenCode. The corpus had `rg` hits and diffs, which carry their own chrome, but no plain formatted source -- and that is the category that leaked. 24 of the 25 are the same shape. `AUTH_QUESTION_ROW_RE` rests on "prose never starts with a bare `?`", which is true and irrelevant: oxfmt puts a ternary's consequent on its own row as `? someValue`, and **5,666 tracked files have one**. `sawAuthQuestion` then returns unconditionally, with no position requirement, so a composer caret directly below could not clear it. Nine of those matched only because `\b(?:log[ -]?in)\b` reads `user.login` as the auth verb. The 25th is the other rule: `CREDENTIAL_ASK_PREFIX_RE` was unanchored, so an ask verb anywhere in a row made a row-final credential noun a prompt -- `// Why: a merely missing or expired bundle must not enter the credential` is a real wrapped comment in this repo, and terminal wrapping makes ending on a noun routine. Three fixes, same discipline as the flow rule already uses: - the ask verb must LEAD its row, modulo decoration and a menu number, so `2. Paste an API key` still reads as a prompt and 60 characters of prose before `enter the` does not; - `.login` is a property access, not an auth verb; - a known composer caret on the bottom row suppresses the question-row rule, because an agent sitting at its own prompt is not asking anyone anything. The caret set deliberately includes a bare `>`. It only suppresses the question-row rule, and the #19749 sign-in dialog -- whose own bottom row is `>` -- matches through `isCredentialPromptLine`, which returns first. Verified: that dialog and the auth-method menu both still refuse. Mined-corpus refusals 100 -> 0, with the mined lines added as a new corpus category so the next widening has to refuse them. Sentinel budget unchanged at 16.2ms/500ms.
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
import type { TerminalCredentialPromptCase } from './terminal-live-credential-surfaces-corpus'
|
||||
import { AGENT_AUTH_SUMMARY_SCREENS } from './terminal-agent-auth-summary-screens-corpus'
|
||||
import { AGENT_AUTH_MENTION_SCREENS } from './terminal-auth-mention-screens-corpus'
|
||||
import { AGENT_SOURCE_OUTPUT_SCREENS } from './terminal-source-output-screens-corpus'
|
||||
|
||||
export const LEGITIMATE_AGENT_SCREENS: readonly TerminalCredentialPromptCase[] = [
|
||||
// An agent narrating credential work and returning to its composer.
|
||||
@@ -163,5 +164,6 @@ export const LEGITIMATE_AGENT_SCREENS: readonly TerminalCredentialPromptCase[] =
|
||||
]
|
||||
],
|
||||
...AGENT_AUTH_SUMMARY_SCREENS,
|
||||
...AGENT_AUTH_MENTION_SCREENS
|
||||
...AGENT_AUTH_MENTION_SCREENS,
|
||||
...AGENT_SOURCE_OUTPUT_SCREENS
|
||||
]
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
// Plain source code printed into the pane — the category the corpus lacked. It had `rg` hits and
|
||||
// diffs, which carry their own chrome (`└`, `+`), but not bare formatted source, and that is what
|
||||
// leaked: every line here was mined from this repo's own tracked files and refused a prompt when
|
||||
// placed one row above a real agent composer caret.
|
||||
//
|
||||
// The dominant shape is an oxfmt ternary continuation. `AUTH_QUESTION_ROW_RE` was written on the
|
||||
// premise that "prose never starts with a bare `?`" — true, and irrelevant, because FORMATTED CODE
|
||||
// does, in 5,666 tracked files. The rest are `.login` property accesses reading as the auth verb
|
||||
// `log in`, and one wrapped comment that merely ends on a credential noun.
|
||||
import type { TerminalCredentialPromptCase } from './terminal-live-credential-surfaces-corpus'
|
||||
|
||||
const CODEX = '› Ask Codex to do anything'
|
||||
const CLAUDE = '> '
|
||||
const OPENCODE = '❯ '
|
||||
|
||||
/** One mined source row above the composer caret that was on screen under it. */
|
||||
function sourceRow(name: string, line: string, caret: string): TerminalCredentialPromptCase {
|
||||
return [name, [line, caret]]
|
||||
}
|
||||
|
||||
export const AGENT_SOURCE_OUTPUT_SCREENS: readonly TerminalCredentialPromptCase[] = [
|
||||
// Ternary continuations whose consequent contains auth wording.
|
||||
sourceRow(
|
||||
'ternary consequent with a sign-in string',
|
||||
" ? 'Update desktop Orca and sign in to connect from anywhere'",
|
||||
CODEX
|
||||
),
|
||||
sourceRow(
|
||||
'ternary consequent with an authentication template literal',
|
||||
' ? `replacement session authentication timed out (${stage})`',
|
||||
CLAUDE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary consequent with a login error',
|
||||
' ? `Codex login failed: ${trimmedOutput}`',
|
||||
OPENCODE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary consequent calling a login spawn builder',
|
||||
" ? buildWindowsHostInteractiveLoginSpawn(codexCommand, ['login'])",
|
||||
CODEX
|
||||
),
|
||||
sourceRow(
|
||||
'ternary consequent with a sign-in status string',
|
||||
" ? 'Timed out while checking Codex sign-in status'",
|
||||
CLAUDE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary consequent reading an authorization basis',
|
||||
' ? this.originPool.controlForBasis(authorization.basisConnId)',
|
||||
OPENCODE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary consequent building a gh auth command',
|
||||
' ? `gh auth login --hostname ${host}`',
|
||||
CODEX
|
||||
),
|
||||
sourceRow(
|
||||
'ternary consequent mentioning a keyring login',
|
||||
" ? ' Your keyring already has a `gh` login that will take over once the env var is gone.'",
|
||||
CLAUDE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary consequent with a translated sign-in-again label',
|
||||
" ? translate('auto.components.settings.artifacts.signInAgain', 'Sign in again')",
|
||||
OPENCODE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary consequent with a personal-access-token docs url',
|
||||
" ? 'https://learn.microsoft.com/azure/devops/accounts/use-pat-to-authenticate'",
|
||||
CODEX
|
||||
),
|
||||
sourceRow(
|
||||
'ternary consequent with a sign-in screen assertion message',
|
||||
" ? 'Codex stopped on the sign-in screen — CODEX_HOME auth was not visible to the TUI'",
|
||||
CLAUDE
|
||||
),
|
||||
// `.login` property accesses, which `\b` alone reads as the auth verb "log in".
|
||||
sourceRow(
|
||||
'ternary filtering assignees by login',
|
||||
' ? prevAssignees.filter((l) => l !== login)',
|
||||
CODEX
|
||||
),
|
||||
sourceRow(
|
||||
'ternary narrowing a login to a string',
|
||||
" ? overrides.filter((login): login is string => typeof login === 'string')",
|
||||
CLAUDE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary removing assignees by login',
|
||||
' ? { removeAssignees: [user.login] }',
|
||||
OPENCODE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary mapping project assignees',
|
||||
' ? projectRowDetail.assignees.map((login) => ({',
|
||||
CODEX
|
||||
),
|
||||
sourceRow(
|
||||
'ternary removing a reviewer by login',
|
||||
' ? handleRemoveReviewers([reviewer.login])',
|
||||
CLAUDE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary editing assignees by login',
|
||||
' ? onEditAssignees?.([], [user.login])',
|
||||
OPENCODE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary lowercasing an assignee login',
|
||||
' ? prevAssignees.filter((user) => user.login.toLowerCase() !== lowerLogin)',
|
||||
CODEX
|
||||
),
|
||||
sourceRow(
|
||||
'ternary building a login patch object',
|
||||
' ? { login: candidate.login, name: candidate.name }',
|
||||
CLAUDE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary building an assignee removal patch',
|
||||
" ? { family: 'assignees', kind: 'remove', logins: [login] }",
|
||||
OPENCODE
|
||||
),
|
||||
sourceRow(
|
||||
'ternary filtering selected assignees by login key',
|
||||
' ? selectedAssignees.filter((current) => current.login.toLowerCase() !== key)',
|
||||
CODEX
|
||||
),
|
||||
// No composer caret, and the bottom row DOES lead with an action phrase — so the only thing
|
||||
// keeping this from reading as a live prompt is that `candidate.login` is a property access
|
||||
// rather than the auth verb "log in". Pins the lookbehind on its own.
|
||||
[
|
||||
'source rows where a .login access is the only would-be auth verb',
|
||||
[
|
||||
' const owner = candidate.login',
|
||||
' // Enter the code below to finish linking the account'
|
||||
]
|
||||
],
|
||||
// Prose that merely ENDS on a credential noun, which an unanchored ask verb read as a prompt.
|
||||
sourceRow(
|
||||
'wrapped comment ending on a credential noun',
|
||||
' // Why: a merely missing or expired bundle must not enter the credential',
|
||||
OPENCODE
|
||||
),
|
||||
sourceRow(
|
||||
'wrapped comment ending on a password noun',
|
||||
' // The caller must provide the current password',
|
||||
CODEX
|
||||
),
|
||||
sourceRow(
|
||||
'wrapped jsdoc ending on an api key noun',
|
||||
' * Callers are expected to paste their API key',
|
||||
CLAUDE
|
||||
)
|
||||
]
|
||||
Reference in New Issue
Block a user