Repository navigation
feat(byo): harness picker rows come from the walk table (TASK-361) #2930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
0472a73
feat(byo): harness picker rows come from the walk table (TASK-361)
lilyshen0722 3fffb3a
test(byo): pin the harness picker dot rules in v2.css (TASK-361)
lilyshen0722 5f3ee97
fix(byo): fit the harness picker at 390 and label each OS dot (TASK-361)
lilyshen0722 f18a3c5
fix(byo): size harness picker columns to their headings (TASK-361)
lilyshen0722 1a757ff
fix(byo): put the head and rows on the same fixed tracks (TASK-361)
lilyshen0722 fcef4e8
fix(byo): size the phone harness tracks to their headings (TASK-361)
lilyshen0722 948e9e7
fix(byo): restore the phone row gap to 6px and let the name wrap (TAS…
lilyshen0722 17af06c
fix(byo): declare the mono family on the phone picker head (TASK-361)
lilyshen0722 8e3561d
test(byo): pin the picker's state classes, complete selectors and tra…
lilyshen0722 aebe8fe
test(byo): match only standalone selectors and pin the one-command ro…
lilyshen0722 a35e69d
fix(i18n): correct harness picker zh-CN strings per Vera's review (TA…
lilyshen0722 81a5efe
fix(i18n): zh-CN harness label and mcp-only state per review (TASK-361)
lilyshen0722 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| // @ts-nocheck | ||
| import React from 'react'; | ||
| import { fireEvent, render, screen, within } from '@testing-library/react'; | ||
| import V2HarnessPicker from '../components/V2HarnessPicker'; | ||
| import { HARNESS_WALK_TABLE, HIDDEN_HARNESS_IDS } from '../utils/harnessWalkTable'; | ||
| import fs from 'fs'; | ||
| import path from 'path'; | ||
|
|
||
| const v2Css = fs.readFileSync(path.join(__dirname, '../v2.css'), 'utf8').replace(/\/\*[\s\S]*?\*\//g, ''); | ||
| // Body of the first rule whose selector list includes `selector` as a complete selector | ||
| // (not a prefix of a longer class name), so grouped selectors match too. | ||
| const ruleBody = (selector) => { | ||
| // Escape the selector, then require it to start a selector-list entry and end at a comma or | ||
| // an opening brace. A compound selector such as `.dot--walked.is-active` does not match. | ||
| const escaped = selector.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | ||
| const match = v2Css.match(new RegExp(`(?:^|[,\\n])\\s*${escaped}\\s*(?=,|\\{)[^{}]*\\{([^}]*)\\}`)); | ||
| return match ? match[1] : ''; | ||
| }; | ||
|
|
||
| afterEach(() => jest.clearAllMocks()); | ||
|
|
||
| describe('V2HarnessPicker', () => { | ||
| it('renders exactly the walked harnesses from the walk table, in table order', () => { | ||
| render(<V2HarnessPicker selectedId="claude" onSelect={jest.fn()} />); | ||
| const rows = within(screen.getByTestId('harness-picker')).getAllByRole('button'); | ||
| expect(rows.map((r) => r.getAttribute('data-testid'))).toEqual( | ||
| HARNESS_WALK_TABLE.map((row) => `harness-row-${row.id}`), | ||
| ); | ||
| expect(rows.map((r) => r.textContent.replace(/\s+/g, ' ').trim()).join('|')).toContain('Qwen Code'); | ||
| }); | ||
|
|
||
| it('never renders a harness that has no walk on record', () => { | ||
| render(<V2HarnessPicker selectedId="claude" onSelect={jest.fn()} />); | ||
| HIDDEN_HARNESS_IDS.forEach((id) => { | ||
| expect(screen.queryByTestId(`harness-row-${id}`)).toBeNull(); | ||
| }); | ||
| expect(screen.queryByText('Hermes')).toBeNull(); | ||
| expect(screen.queryByText('goose')).toBeNull(); | ||
| }); | ||
|
|
||
| it('shows Qwen Code and hides Hermes, per the rev 3 walk table', () => { | ||
| render(<V2HarnessPicker selectedId="claude" onSelect={jest.fn()} />); | ||
| expect(screen.getByTestId('harness-row-qwen')).toBeInTheDocument(); | ||
| expect(screen.queryByTestId('harness-row-hermes')).toBeNull(); | ||
| }); | ||
|
|
||
| it('draws the OS dots from the table: filled when walked, dashed when not', () => { | ||
| render(<V2HarnessPicker selectedId="claude" onSelect={jest.fn()} />); | ||
| const claude = screen.getByTestId('harness-row-claude'); | ||
| expect(within(claude).getByTestId('harness-dot-claude-mac')).toHaveAttribute('data-state', 'walked'); | ||
| expect(within(claude).getByTestId('harness-dot-claude-linux')).toHaveAttribute('data-state', 'mcp-only'); | ||
| expect(within(claude).getByTestId('harness-dot-claude-windows')).toHaveAttribute('data-state', 'mcp-only'); | ||
| expect(within(screen.getByTestId('harness-row-codex')).getByTestId('harness-dot-codex-linux')).toHaveAttribute('data-state', 'not-walked'); | ||
| }); | ||
|
|
||
| it('gives each dot the state class the stylesheet keys on, for every state', () => { | ||
| render(<V2HarnessPicker selectedId="claude" onSelect={jest.fn()} />); | ||
| expect(screen.getByTestId('harness-dot-claude-mac')).toHaveClass('v2-harness-picker__dot--walked'); | ||
| expect(screen.getByTestId('harness-dot-claude-linux')).toHaveClass('v2-harness-picker__dot--mcp-only'); | ||
| expect(screen.getByTestId('harness-dot-codex-linux')).toHaveClass('v2-harness-picker__dot--not-walked'); | ||
| expect(screen.getByTestId('harness-dot-dsh-windows')).toHaveClass('v2-harness-picker__dot--not-offered'); | ||
| }); | ||
|
|
||
| it('titles each OS dot with why it is filled or dashed', () => { | ||
| render(<V2HarnessPicker selectedId="claude" onSelect={jest.fn()} />); | ||
| expect(screen.getByTestId('harness-dot-claude-mac')).toHaveAttribute('title', 'Walked on Mac'); | ||
| expect(screen.getByTestId('harness-dot-claude-linux')).toHaveAttribute('title', 'Linux: connects over MCP only, no @mention listener'); | ||
| expect(screen.getByTestId('harness-dot-dsh-windows')).toHaveAttribute('title', 'Not offered on Windows'); | ||
| }); | ||
|
|
||
| it('keeps the filled and dashed dot rules in v2.css', () => { | ||
| expect(ruleBody('.v2-harness-picker__dot--walked')).toContain('background: var(--v2-ink)'); | ||
| expect(ruleBody('.v2-harness-picker__dot--not-walked')).toContain('border: 1px dashed var(--v2-text-tertiary)'); | ||
| }); | ||
|
|
||
| it('marks only DeepSeek Harness as private-pods-only', () => { | ||
| render(<V2HarnessPicker selectedId="claude" onSelect={jest.fn()} />); | ||
| const privateRows = HARNESS_WALK_TABLE.filter((row) => row.privatePodsOnly).map((row) => row.id); | ||
| expect(privateRows).toEqual(['dsh']); | ||
| expect(within(screen.getByTestId('harness-row-dsh')).getByRole('img', { name: 'private pods only' })).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('marks the selected row and reports the id it picks', () => { | ||
| const onSelect = jest.fn(); | ||
| render(<V2HarnessPicker selectedId="codex" onSelect={onSelect} />); | ||
| expect(screen.getByTestId('harness-row-codex')).toHaveAttribute('aria-pressed', 'true'); | ||
| expect(screen.getByTestId('harness-row-claude')).toHaveAttribute('aria-pressed', 'false'); | ||
| fireEvent.click(screen.getByTestId('harness-row-opencode')); | ||
| expect(onSelect).toHaveBeenCalledWith('opencode'); | ||
| }); | ||
|
|
||
| it('pins the one-command rows to Claude Code and Codex', () => { | ||
| expect(HARNESS_WALK_TABLE.filter((row) => row.connects === 'command').map((row) => row.id)).toEqual(['claude', 'codex']); | ||
| }); | ||
|
|
||
| it('uses the connect method from the table for each row', () => { | ||
| render(<V2HarnessPicker selectedId="claude" onSelect={jest.fn()} />); | ||
| expect(screen.getByTestId('harness-connects-claude')).toHaveAttribute('aria-label', 'one command'); | ||
| expect(screen.getByTestId('harness-connects-opencode')).toHaveAttribute('aria-label', 'terminal steps'); | ||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| import React from 'react'; | ||
| import { useTranslation } from 'react-i18next'; | ||
| import { HARNESS_WALK_TABLE, HarnessOsState, HarnessWalkRow } from '../utils/harnessWalkTable'; | ||
|
|
||
| interface V2HarnessPickerProps { | ||
| selectedId: string; | ||
| onSelect: (id: string) => void; | ||
| } | ||
|
|
||
| const GLYPH_PROPS = { width: 16, height: 16, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.8, 'aria-hidden': true }; | ||
|
|
||
| const ClipboardGlyph = () => ( | ||
| <svg {...GLYPH_PROPS}><rect x="6" y="4" width="12" height="17" rx="2" /><path d="M9 4V3h6v1" /></svg> | ||
| ); | ||
| const TerminalGlyph = () => ( | ||
| <svg {...GLYPH_PROPS}><rect x="3" y="4" width="18" height="16" rx="2" /><path d="M7 9l3 3-3 3M13 15h4" /></svg> | ||
| ); | ||
| const LockGlyph = () => ( | ||
| <svg {...GLYPH_PROPS}><rect x="5" y="11" width="14" height="10" rx="2" /><path d="M8 11V7a4 4 0 0 1 8 0v4" /></svg> | ||
| ); | ||
|
|
||
| // One dot per OS. Filled when walked, dashed ring otherwise. The title says why. | ||
| const OsDot = ({ state, os, row }: { state: HarnessOsState; os: 'mac' | 'linux' | 'windows'; row: HarnessWalkRow }) => { | ||
| const { t } = useTranslation(); | ||
| const title = t(`agentByo.harnessPicker.osState.${state}`, { os: t(`agentByo.harnessPicker.${os}`) }); | ||
| return ( | ||
| <span | ||
| className={`v2-harness-picker__dot v2-harness-picker__dot--${state}`} | ||
| data-testid={`harness-dot-${row.id}-${os}`} | ||
| data-state={state} | ||
| title={title} | ||
| aria-label={title} | ||
| role="img" | ||
| /> | ||
| ); | ||
| }; | ||
|
|
||
| const HarnessRow = ({ row, selected, onSelect }: { row: HarnessWalkRow; selected: boolean; onSelect: (id: string) => void }) => { | ||
| const { t } = useTranslation(); | ||
| const connectsLabel = t(row.connects === 'command' ? 'agentByo.harnessPicker.connectsCommand' : 'agentByo.harnessPicker.connectsTerminal'); | ||
| return ( | ||
| <button | ||
| type="button" | ||
| className={`v2-harness-picker__row${selected ? ' v2-harness-picker__row--selected' : ''}`} | ||
| aria-pressed={selected} | ||
| data-testid={`harness-row-${row.id}`} | ||
| onClick={() => onSelect(row.id)} | ||
| > | ||
| <span className="v2-harness-picker__name"> | ||
| <span className="v2-harness-picker__mark" aria-hidden="true">{row.monogram}</span> | ||
| <span>{row.label}</span> | ||
| {row.privatePodsOnly && ( | ||
| <span className="v2-harness-picker__lock" role="img" title={t('agentByo.harnessPicker.privateOnly')} aria-label={t('agentByo.harnessPicker.privateOnly')}> | ||
| <LockGlyph /> | ||
| </span> | ||
| )} | ||
| </span> | ||
| <span className="v2-harness-picker__connects" role="img" title={connectsLabel} aria-label={connectsLabel} data-testid={`harness-connects-${row.id}`}> | ||
| {row.connects === 'command' ? <ClipboardGlyph /> : <TerminalGlyph />} | ||
| </span> | ||
| <OsDot state={row.os.mac} os="mac" row={row} /> | ||
| <OsDot state={row.os.linux} os="linux" row={row} /> | ||
| <OsDot state={row.os.windows} os="windows" row={row} /> | ||
| </button> | ||
| ); | ||
| }; | ||
|
|
||
| // Renders only the rows in HARNESS_WALK_TABLE. Hidden harnesses have no entry to render. | ||
| const V2HarnessPicker = ({ selectedId, onSelect }: V2HarnessPickerProps) => { | ||
| const { t } = useTranslation(); | ||
| return ( | ||
| <div className="v2-harness-picker" role="group" aria-label={t('agentByo.harnessPicker.label')} data-testid="harness-picker"> | ||
| <div className="v2-harness-picker__head" aria-hidden="true"> | ||
| <span /> | ||
| <span>{t('agentByo.harnessPicker.connects')}</span> | ||
| <span>{t('agentByo.harnessPicker.mac')}</span> | ||
| <span>{t('agentByo.harnessPicker.linux')}</span> | ||
| <span>{t('agentByo.harnessPicker.windows')}</span> | ||
| </div> | ||
| {HARNESS_WALK_TABLE.map((row) => ( | ||
| <HarnessRow key={row.id} row={row} selected={row.id === selectedId} onSelect={onSelect} /> | ||
| ))} | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default V2HarnessPicker; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| // The harness walk table, as data. Source of truth: ~/agents/shared/d15/harness-walk-table.md | ||
| // (ux-lead, 2026-10-27). A harness is listed in the picker only when it has a passing walk on | ||
| // record. Change a row here only with a new walk on record, and update the table to match. | ||
|
|
||
| /** | ||
| * walked: passing walk on record. mcp-only: connects, but no @mention listener on this OS. | ||
| * not-walked: no walk yet. not-offered: the harness does not ship for this OS. | ||
| */ | ||
| export type HarnessOsState = 'walked' | 'mcp-only' | 'not-walked' | 'not-offered'; | ||
|
|
||
| export interface HarnessWalkRow { | ||
| id: string; | ||
| label: string; | ||
| /** Two-letter stand-in until the vendor's own mark is wired in. */ | ||
| monogram: string; | ||
| /** `command` = one clipboard command; `terminal` = steps in your terminal. */ | ||
| connects: 'command' | 'terminal'; | ||
| os: { mac: HarnessOsState; linux: HarnessOsState; windows: HarnessOsState }; | ||
| /** Private pods only (lock glyph). */ | ||
| privatePodsOnly: boolean; | ||
| walkedOn: string; | ||
| } | ||
|
|
||
| export const HARNESS_WALK_TABLE: readonly HarnessWalkRow[] = [ | ||
| { | ||
| id: 'claude', | ||
| label: 'Claude Code', | ||
| monogram: 'CC', | ||
| connects: 'command', | ||
| os: { mac: 'walked', linux: 'mcp-only', windows: 'mcp-only' }, | ||
| privatePodsOnly: false, | ||
| walkedOn: '2026-10-26', | ||
| }, | ||
| { | ||
| id: 'codex', | ||
| label: 'Codex', | ||
| monogram: 'CX', | ||
| connects: 'command', | ||
| os: { mac: 'walked', linux: 'not-walked', windows: 'not-walked' }, | ||
| privatePodsOnly: false, | ||
| walkedOn: '2026-10-27', | ||
| }, | ||
| { | ||
| id: 'opencode', | ||
| label: 'OpenCode', | ||
| monogram: 'OC', | ||
| connects: 'terminal', | ||
| os: { mac: 'walked', linux: 'not-walked', windows: 'not-walked' }, | ||
| privatePodsOnly: false, | ||
| walkedOn: '2026-10-27', | ||
| }, | ||
| { | ||
| id: 'qwen', | ||
| label: 'Qwen Code', | ||
| monogram: 'QW', | ||
| connects: 'terminal', | ||
| os: { mac: 'walked', linux: 'not-walked', windows: 'not-walked' }, | ||
| privatePodsOnly: false, | ||
| walkedOn: '2026-10-27', | ||
| }, | ||
| { | ||
| id: 'dsh', | ||
| label: 'DeepSeek Harness', | ||
| monogram: 'DS', | ||
| connects: 'terminal', | ||
| os: { mac: 'walked', linux: 'not-offered', windows: 'not-offered' }, | ||
| privatePodsOnly: true, | ||
| walkedOn: '2026-10-23', | ||
| }, | ||
| ]; | ||
|
|
||
| /** Harnesses with no passing walk on record. They never render in the picker. */ | ||
| export const HIDDEN_HARNESS_IDS: readonly string[] = ['hermes', 'goose', 'pi', 'gemini', 'grok-build']; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.