fix(a11y): Field and InlineField — wrap in <label> for implicit form control association#1538
Closed
hungdqdesign wants to merge 140 commits intopaperclipai:masterfrom
Closed
Conversation
… and add missing models (#1357) Cursor CLI now rejects "auto" as a model selection with "Cannot use this model: auto". Change the default to "composer-2" and add "composer-2" + "composer-2-fast" to the fallback model list. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…awbot.vn Add allowedHosts: "all" to vite server config so that requests from custom domain behind Cloudflare are not blocked. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ers from agent worktree modifications
… production deployments
Break the monolithic AgentDetail page into focused, maintainable modules: - AgentDetail.tsx: slim orchestrator (593 LOC, down from 3988) - agent-detail/OverviewTab.tsx: dashboard with charts, issues, costs - agent-detail/InstructionsTab.tsx: instructions bundle editor - agent-detail/ConfigurationTab.tsx: agent config form + permissions + keys - agent-detail/SkillsTab.tsx: skill management - agent-detail/RunsTab.tsx: run list + run detail (lazy loaded via React.lazy) - agent-detail/LogViewer.tsx: live transcript/log viewer - agent-detail/KeysTab.tsx: API key management - agent-detail/WorkspaceOperations.tsx: workspace operation UI - agent-detail/utils.ts: shared utilities and types RunsTab is lazy-loaded for better initial page performance. No functional changes — pure extraction refactor. QUA-123 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…calls When /agents/:id/wakeup is called directly (not via the checkout route), the contextSnapshot lacks issueId/projectId/workspaceId, causing the run to fall back to agent_home instead of the project workspace. Now enqueueWakeup auto-detects the agent's in-progress checked-out issue and enriches the context with issueId, projectId, and projectWorkspaceId. Also persists resolved projectId to contextSnapshot when only issueId was provided. Fixes #1387 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… locks (QUA-12) release() now clears executionRunId, executionAgentNameKey, and executionLockedAt alongside checkoutRunId. Previously these fields persisted after release, causing permanent stale locks that blocked re-checkout by other agents. Adds unit tests verifying all execution fields are nulled on release. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nsert (#QUA-91) Gemini adapter output sometimes contains null bytes (0x00) which PostgreSQL rejects in TEXT and JSONB columns. Add stripNullBytes() sanitization at the DB write layer (setRunStatus + appendRunEvent) to protect against any adapter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On Windows with WIN1252 system locale, child process stdout/stderr
default to the system encoding, causing crashes when adapter output
contains Unicode characters. Add setEncoding("utf8") on streams
immediately after spawn, matching the pattern used in codex-local.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…#1465) Users running adapters like codex_local with non-standard models (e.g. grok-4.20-beta) were blocked by the hardcoded model dropdown. Now: - ModelDropdown shows a "Use <custom>" option when search doesn't match any known model - InlineEntitySelector gains allowCustomValue prop for the same behavior - NewIssueDialog model override selector enables custom values - Custom model values display correctly in trigger buttons Closes #1465 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rver crash (#1461) When the codex binary is not installed, spawning it emits an unhandled 'error' event that crashes the entire server process. Add an error handler on the child process to catch spawn failures gracefully, and short-circuit subsequent RPC requests with the captured error. The existing try/catch in getQuotaWindows() then returns a proper error response instead of crashing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ssibility (#1473) - Fix sw.js caches.match() returning undefined causing TypeError on offline fallback - Add onError toast to createIssue mutation so users see API errors - Add sr-only DialogTitle to NewIssueDialog, NewGoalDialog, NewProjectDialog, NewAgentDialog, and Routines to suppress Radix UI accessibility warnings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cancelActiveForAgentInternal now matches cancelRunInternal's escalation pattern: SIGTERM → grace period → SIGKILL. The runningProcesses entry is deferred until after the grace window to prevent orphaned processes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…#1391) Commander.js .requiredOption() validates before the action handler runs, preventing resolveCommandContext() from applying the context profile fallback (PAPERCLIP_COMPANY_ID env var or saved profile companyId). Changed to .option() in all affected commands (dashboard, activity, issue create, agent list, agent local-cli, approval list, approval create). The requireCompany: true check in resolveCommandContext() still ensures companyId is present, with a helpful error message listing all fallback options. Closes #1391 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CodexRpcClient spawns the codex binary in its class initializer but
never listens for the 'error' event. When codex is not installed,
Node emits an unhandled ENOENT error that crashes the entire server.
Added a proc.on('error') handler that rejects all pending RPC
requests, allowing the existing try-catch in getQuotaWindows() to
gracefully surface the error instead of crashing.
Closes #1461
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ers from agent worktree modifications
… production deployments
…nsert (#QUA-91) Gemini adapter output sometimes contains null bytes (0x00) which PostgreSQL rejects in TEXT and JSONB columns. Add stripNullBytes() sanitization at the DB write layer (setRunStatus + appendRunEvent) to protect against any adapter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On Windows with WIN1252 system locale, child process stdout/stderr
default to the system encoding, causing crashes when adapter output
contains Unicode characters. Add setEncoding("utf8") on streams
immediately after spawn, matching the pattern used in codex-local.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… and add missing models (#1357) Cursor CLI now rejects "auto" as a model selection with "Cannot use this model: auto". Change the default to "composer-2" and add "composer-2" + "composer-2-fast" to the fallback model list. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…awbot.vn Add allowedHosts: "all" to vite server config so that requests from custom domain behind Cloudflare are not blocked. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cancelActiveForAgentInternal now matches cancelRunInternal's escalation pattern: SIGTERM → grace period → SIGKILL. The runningProcesses entry is deferred until after the grace window to prevent orphaned processes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…1461) The codex adapter's getQuotaWindows spawns the codex CLI in its class constructor. If codex is not installed, spawn emits ENOENT which can crash the server when the Costs → Providers page is loaded. Wrap each adapter.getQuotaWindows() call in try-catch to handle both synchronous throws and async rejections gracefully. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…#1165) enqueueWakeup can throw (budget blocked, agent state conflict, etc). Without a try-catch inside the tickTimers loop, one failing agent aborts the entire tick — silently stopping all scheduled heartbeats. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ory leak (QUA-87, QUA-89) - budgets.ts: batch-fetch observed amounts to avoid N+1 queries in evaluateBudgetPolicies - heartbeat.ts: convert activeRunExecutions from Set to Map<runId, timestamp> with 4h TTL cleanup to prevent unbounded memory growth if entries are never removed Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- docs/plans/sdlc-flowchart.md: Mermaid flowchart of intake → spec → dev → QA → release - docs/templates/spec-template.md: Implementation spec template for issue comments - docs/templates/qa-ux-a11y-checklist.md: QA/UX/A11Y review checklist template Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
# Conflicts: # ui/src/pages/IssueDetail.tsx
…e (QUA-192) - FilterBar: add aria-label to remove-filter icon button - PackageFileTree: add aria-label + aria-expanded to chevron toggle button; add aria-label to dir checkbox input - GoalTree: add role=button, tabIndex, onKeyDown to interactive div when onSelect is provided Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…bBar, InlineEditor, PackageFileTree (QUA-193) Batch 16 A11Y fixes: - AgentIconPicker: add aria-label to icon picker buttons (title alone not sufficient) - StatusIcon: wrap circle span in button with aria-label when !showLabel - PageTabBar: add aria-label="Select page" to mobile select element - InlineEditor: add role/tabIndex/onKeyDown to display mode clickable element - PackageFileTree: add aria-label to file row checkbox input Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…structionsTab, PluginSettings, CompanySkills, PluginManager (QUA-194) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…structionsTab, PluginSettings, CompanySkills, PluginManager (QUA-194) Batch 17 A11Y fixes: - AgentDetail: aria-label="More options" on overflow menu button - KeysTab: aria-label for show/hide token and copy token buttons - InstructionsTab: aria-label="Add file" on add file button - PluginSettings: aria-label="Back to plugins" on back button - CompanySkills: aria-label on scan project workspaces button - PluginManager: aria-label for enable/disable and uninstall plugin buttons Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s (QUA-195) Batch 18 A11Y fixes: - Companies: aria-label="Save changes" and "Cancel editing" for inline edit buttons - NewIssueDialog: aria-label for execution workspace mode and existing workspace selects - IssueProperties: aria-label for workspace mode and existing workspace selects Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…9 (QUA-196) - PluginSettings.tsx: aria-label="Back to plugins" on back arrow button - InstructionsTab.tsx: aria-label="Add new file" on "+" icon button - AgentConfigForm.tsx: aria-label for value type select, secret select, and X remove button - PageTabBar.tsx: aria-label prop (default "Page navigation") for mobile select fallback Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
# Conflicts: # ui/src/components/PageTabBar.tsx
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…-197)
- Agent adapter type select: aria-label="Adapter type for {agent.name}"
- Import target select: aria-label="Import target"
- Collision strategy select: aria-label="Collision strategy"
Field component's <label> lacks htmlFor association; these aria-labels
ensure screen readers announce the correct purpose for each select.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…198)
- agent-config-primitives.tsx: HintIcon button aria-label={text} (tooltip hint text as label)
- NewIssueDialog.tsx: MoreHorizontal date options button aria-label="More date options"
- AgentDetail.tsx: Agent icon picker trigger aria-label="Change agent icon"
- openclaw-gateway/config-fields.tsx: Session strategy select aria-label="Session strategy"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
# Conflicts: # ui/src/components/agent-config-primitives.tsx
# Conflicts: # ui/src/pages/agent-detail/InstructionsTab.tsx
…control association Before: <label> chỉ bọc text label → không có programmatic association với form control. After: outer <div> → <label className="block/flex"> → implicit association với form control đầu tiên bên trong. WCAG 2.1 AA: 1.3.1 Info and Relationships + 4.1.2 Name, Role, Value Fixes all Field/InlineField usages across: - All adapter config-fields (claude, codex, cursor, gemini, opencode, pi, http, process, openclaw-gateway) - AgentConfigForm, CompanySettings, CompanyImport, runtime-json-fields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
|
Too many files changed for review. ( |
Resolved conflict: AgentDetail.tsx was refactored into smaller components. Applied scope="col" fix to OverviewTab.tsx where table headers were moved. aria-label="More options" was already present in master. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…hecked, aria-label, type=button
ToggleField button:
- type="button" — prevent accidental form submission
- role="switch" — correct ARIA role for a two-state toggle
- aria-checked={checked} — communicate on/off state to screen readers
- aria-label={label} — describe what this toggle controls
ToggleWithNumber button: same fixes as above.
ToggleWithNumber number input: aria-label="${label} value in ${numberLabel}"
e.g. "Heartbeat on interval value in sec"
WCAG 2.1 AA: 4.1.2 Name, Role, Value
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
FieldvàInlineFielddùng<label>chỉ bọc text label, không cóhtmlFor→ không có programmatic association với form control bên trong<div>→<label className=\"block\">(Field) /<label className=\"flex items-center gap-3\">(InlineField) → implicit label association với form control đầu tiên bên trong childrenRoot cause
HTML spec:
<label>chỉ tạo association khi:htmlFortrỏ tớiidcủa form controlFieldđang dùng cách 1 nhưng<label>chỉ bọc text, không bọc control → screen readers không biết label này thuộc về control nào.Scope
Fix ảnh hưởng tất cả
<Field>và<InlineField>usages:AgentConfigForm,CompanySettings,CompanyImport,runtime-json-fieldsA11Y Compliance
Safety
<label>với interactive children (button): clicking button activates button only, không kích hoạt label's focus behavior<div>sang<label>npx tsc --noEmitpass ✅Test plan
npx tsc --noEmitpass ✅blockclass)Closes QUA-199
🤖 Generated with Claude Code