mirror of
https://github.com/stablyai/orca.git
synced 2026-10-20 16:03:20 +00:00
Resolves 208 candidate pairs where the same case title appears verbatim in two or more
files, produced by a repo-wide scan calibrated against a known positive. 46 case
declarations removed across 32 files, 798 lines gone. No file deleted whole, no
production code touched.
The headline result is the measurement, not the deletions: across the three buckets that
reported in detail, the signal ran roughly 86% false-positive (3/42, 9/42, and the rest).
It has good recall and poor precision, and it reorders a reading queue rather than
replacing one. Calibrating a detector against a known positive proves recall, not
precision.
What the deletions were:
- Duplicate invocation through a re-export shim. `native-chat-tool-summary.ts` is a
ten-line `export {...} from '../../../../shared/native-chat-tool-summary'`, and
`agent-status.ts:161` is `export { isExplicitAgentStatusFresh } from
'./pane-agent-evidence'`. Cases on the shim side were byte-equivalent to the owner's
with no rendering or transport hop.
- Provider-local replays of a shared helper: three `repository-ref` providers that are
each `createRemoteRefProbeCache(parseXRef)` and contribute nothing to transient
handling; two `local-pty` and `daemon/session` tables replaying
`shell-startup-output-scanner`, whose owner additionally checks every split point.
- A reader-side replay of store policy. `runtime-worktree-agent-rows-structured.test.ts`
asserted an attention-to-blocked mapping; the reader contains zero `attention` or
`blocked` tokens and copies `state` through. The mapping lives in
`structuredAgentSessionAgentStatus`. Consistent with
`docs/reference/agent-status-store.md`: readers keep only presentation policy.
- Constructor-only subclass duplication: the shared capability-cache case is covered by
`codex-app-server-capability-cache.test.ts`, whose ten cases include the identical
title plus all four risks `docs/reference/git-compatibility.md` names — first fallback,
later cached call, concurrent probes, per-host isolation.
- A private predicate duplicated at a real boundary, varying only a path passed straight
into the shared predicate.
Why most pairs were KEPT, because the false positives are principled rather than noise:
- Two independent execution hosts. `src/relay/git-handler-*` and `src/main/git/*` are
separate Git implementations that cannot import each other and hold separate capability
caches, exactly as the compatibility doc requires; the repo already ships
`status-branch-line-total-relay-parity.test.ts` to pin the duality deliberately. Neither
side's argv, timeout or cache regression is visible to the other.
- Deliberately duplicated production siblings: Codex vs Claude (different account fields,
different CLIs, different wire protocols), gitea vs bitbucket (`/pulls/42` vs
`/pullrequests/42`), gl-utils vs gh-utils (separate in-flight maps). Same contract
shape, different implementations — an identical title is the correct naming.
- Shared-predicate consumers: one side tests the predicate, the other tests a caller's
wiring to it. A caller that forgot to call the predicate passes the shared test.
In a codebase with intentional provider and host symmetry, identical test titles are
expected, and the signal cannot distinguish "copied" from "parallel by design" because
both produce the same prose. Only reading both bodies separates them.
Verified: 6,968 desktop test files pass; the three modified mobile files pass (39 cases);
`check-reliability-gates.mjs` 140 gates; nothing under
`mobile/src/test-support/rpc-recording/` or `mobile/rpc-foundation/goldens/` touched.
62 local failures across 12 files were each accounted for and none is caused by this
change: `browser-manager-tab-identity`, `browser-manager-viewport-ownership`,
`session-scanner-codex-workers` and `managed-hook-script-refresh` all fail identically in
a pristine `origin/main` worktree; five `mobile-web-app-*-render` tests need Playwright
browsers this machine lacks; `structured-agent-session-restart-ownership` and
`ssh-remote-commands` pass in isolation and fail only under concurrent load.
202 lines
8.0 KiB
TypeScript
202 lines
8.0 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
||
import {
|
||
CONTEXTUAL_TOURS,
|
||
normalizeContextualTourIds,
|
||
type ContextualTour,
|
||
type ContextualTourId
|
||
} from './contextual-tours'
|
||
|
||
describe('contextual tour definitions', () => {
|
||
it('defines the required tours with concise visible steps', () => {
|
||
const expectedIds: ContextualTourId[] = [
|
||
'workspace-board',
|
||
'workspace-agent-sessions',
|
||
'browser',
|
||
'client-hosted-browser',
|
||
'tasks',
|
||
'automations',
|
||
'floating-workspace',
|
||
'workspace-creation'
|
||
]
|
||
|
||
expect(CONTEXTUAL_TOURS.map((tour) => tour.id)).toEqual(expectedIds)
|
||
for (const tour of CONTEXTUAL_TOURS) {
|
||
expect(tour.steps[0]?.requiredForStart).toBe(true)
|
||
const stepCount = (tour.steps as readonly unknown[]).length
|
||
if (stepCount === 1) {
|
||
// A lone step needs a completion path beyond the default Next: either it
|
||
// self-completes on the feature interaction, or it carries an explicit
|
||
// complete CTA (the client-hosted browser tip's "Got it").
|
||
const step = tour.steps[0] as ContextualTour['steps'][number]
|
||
expect(
|
||
Boolean(step.advanceOnFeatureInteraction) || step.primaryAction?.kind === 'complete'
|
||
).toBe(true)
|
||
} else {
|
||
expect(stepCount).toBeGreaterThanOrEqual(2)
|
||
}
|
||
expect(stepCount).toBeLessThanOrEqual(tour.id === 'workspace-agent-sessions' ? 5 : 3)
|
||
for (const step of tour.steps) {
|
||
expect(step.title.length).toBeGreaterThan(0)
|
||
expect(step.body.length).toBeGreaterThan(0)
|
||
expect(step.body.length).toBeLessThanOrEqual(140)
|
||
expect(step.targetSelector).toContain('data-contextual-tour-target')
|
||
}
|
||
}
|
||
})
|
||
|
||
it('defines the workspace agent sessions value tour as split then create-worktree', () => {
|
||
const tour = CONTEXTUAL_TOURS.find((entry) => entry.id === 'workspace-agent-sessions') as
|
||
| ContextualTour
|
||
| undefined
|
||
|
||
// Two steps only: tasks and orchestration education lives in their own
|
||
// page tours, so the in-app tour ends after the worktree CTA.
|
||
expect(tour?.steps.map((step) => step.title)).toEqual([
|
||
'Split a terminal pane',
|
||
'Start another task in parallel'
|
||
])
|
||
// The opening step teaches the split gesture and offers the convenience button.
|
||
expect(tour?.steps[0]).toMatchObject({
|
||
requiredForStart: true,
|
||
primaryAction: { kind: 'split-terminal-pane', label: 'Split terminal' },
|
||
advanceOnFeatureInteraction: 'terminal-pane-split'
|
||
})
|
||
expect(tour?.steps[0]?.body).toContain('{terminal.splitRight}')
|
||
expect(tour?.steps[0]?.targetSelector).toContain('terminal-pane-split-target')
|
||
expect(tour?.steps[0]?.targetSelector).not.toContain('terminal-split-control')
|
||
expect(tour?.steps[0]?.secondaryAction).toBeUndefined()
|
||
// The closing step anchors on the real new-worktree button; the pulse makes
|
||
// that button the CTA instead of duplicating it inside the panel.
|
||
expect(tour?.steps[1]).toMatchObject({
|
||
targetPulse: true,
|
||
hidePrimaryAction: true
|
||
})
|
||
expect(tour?.steps[1]?.targetSelector).toContain('workspace-create-control')
|
||
expect(tour?.steps[1]?.primaryAction).toBeUndefined()
|
||
expect(tour?.steps[1]?.secondaryAction).toBeUndefined()
|
||
})
|
||
|
||
it('points the workspace board tour at the board center and done lane', () => {
|
||
const tour = CONTEXTUAL_TOURS.find((entry) => entry.id === 'workspace-board') as
|
||
| ContextualTour
|
||
| undefined
|
||
|
||
expect(tour?.steps.map((step) => step.title)).toEqual([
|
||
'Plan work on the board',
|
||
'Move work through lanes'
|
||
])
|
||
expect(tour?.steps[0]).toMatchObject({
|
||
targetSelector: '[data-contextual-tour-target="workspace-board-center"]',
|
||
requiredForStart: true,
|
||
preferredPlacement: 'bottom'
|
||
})
|
||
expect(tour?.steps[1]).toMatchObject({
|
||
body: 'Drag workspaces between lanes as their status changes.',
|
||
targetSelector:
|
||
'[data-contextual-tour-target="workspace-board-done-lane"], [data-contextual-tour-target="workspace-board-lanes"]'
|
||
})
|
||
})
|
||
|
||
it('orders the browser tour as grab, annotate, then import cookies', () => {
|
||
const tour = CONTEXTUAL_TOURS.find((entry) => entry.id === 'browser') as
|
||
| ContextualTour
|
||
| undefined
|
||
|
||
expect(tour?.steps.map((step) => step.title)).toEqual([
|
||
'Grab page context for agents',
|
||
'Mark design feedback in place',
|
||
'Stay logged in'
|
||
])
|
||
expect(tour?.steps[0]).toMatchObject({
|
||
targetSelector: '[data-contextual-tour-target="browser-grab-control"]',
|
||
preferredPlacement: 'bottom'
|
||
})
|
||
expect(tour?.steps[1]).toMatchObject({
|
||
targetSelector: '[data-contextual-tour-target="browser-annotation-control"]',
|
||
preferredPlacement: 'bottom'
|
||
})
|
||
expect(tour?.steps[2]).toMatchObject({
|
||
body: 'Bring your existing logins into Orca to stay signed in immediately.',
|
||
// Prefers the always-visible Import button, falling back to the overflow
|
||
// menu's Import Cookies row once the hint button is dismissed.
|
||
targetSelector:
|
||
'[data-contextual-tour-target="browser-import-hint"], [data-contextual-tour-target="browser-import-cookies-control"]',
|
||
preferredPlacement: 'bottom'
|
||
})
|
||
})
|
||
|
||
it('points the tasks tour at the row workspace action before toolbar fallbacks', () => {
|
||
const tour = CONTEXTUAL_TOURS.find((entry) => entry.id === 'tasks') as
|
||
| ContextualTour
|
||
| undefined
|
||
const step = tour?.steps[2]
|
||
|
||
expect(step).toMatchObject({
|
||
title: 'Start from work items',
|
||
body: 'Use Start or Open on a task, issue, review, or merge request to bring its context into a workspace.'
|
||
})
|
||
expect(step?.targetSelector.split(', ')).toEqual([
|
||
'[data-contextual-tour-target="tasks-start-workspace"]',
|
||
'[data-contextual-tour-target="tasks-actions"]',
|
||
'[data-contextual-tour-target="tasks-search-presets"]'
|
||
])
|
||
})
|
||
|
||
it('orders the automations tour as create, then results', () => {
|
||
const tour = CONTEXTUAL_TOURS.find((entry) => entry.id === 'automations') as
|
||
| ContextualTour
|
||
| undefined
|
||
|
||
expect(tour?.steps.map((step) => step.title)).toEqual([
|
||
'What is an automation?',
|
||
'Find the results'
|
||
])
|
||
expect(tour?.steps[0]).toMatchObject({
|
||
body: 'Automations run agent work on a schedule. Add an automation by clicking this button.',
|
||
requiredForStart: true
|
||
})
|
||
expect(tour?.steps.map((step) => step.targetSelector)).toEqual([
|
||
'[data-contextual-tour-target="automations-create"]',
|
||
'[data-contextual-tour-target="automations-runs"]'
|
||
])
|
||
})
|
||
|
||
it('defines the floating workspace tour on the action list with a surface fallback', () => {
|
||
const tour = CONTEXTUAL_TOURS.find((entry) => entry.id === 'floating-workspace') as
|
||
| ContextualTour
|
||
| undefined
|
||
|
||
expect(tour?.steps.map((step) => step.title)).toEqual([
|
||
'Run an agent across every repo',
|
||
'Or use it as a scratchpad'
|
||
])
|
||
expect(tour?.steps.map((step) => step.body)).toEqual([
|
||
'Agents here run in any folder you choose. Point one at the directory above your services to work across all your repos at once.',
|
||
'Open agents, scratch terminals, notes, and browser tabs without cluttering the worktree you’re focused on.'
|
||
])
|
||
expect(tour?.steps[0]).toMatchObject({
|
||
requiredForStart: true,
|
||
preferredPlacement: 'left'
|
||
})
|
||
expect(tour?.steps[1]?.preferredPlacement).toBe('left')
|
||
expect(tour?.steps.map((step) => step.targetSelector)).toEqual([
|
||
'[data-contextual-tour-target="floating-workspace-new-terminal"], [data-contextual-tour-target="floating-workspace-surface"]',
|
||
'[data-contextual-tour-target="floating-workspace-new-markdown"], [data-contextual-tour-target="floating-workspace-surface"]'
|
||
])
|
||
})
|
||
|
||
it('normalizes persisted ids by removing unknowns and duplicates', () => {
|
||
expect(
|
||
normalizeContextualTourIds([
|
||
'tasks',
|
||
'unknown',
|
||
'workspace-agent-sessions',
|
||
'browser',
|
||
'tasks',
|
||
null,
|
||
'workspace-creation'
|
||
])
|
||
).toEqual(['tasks', 'workspace-agent-sessions', 'browser', 'workspace-creation'])
|
||
})
|
||
})
|