Skip to content

fix(a11y): add aria-label to selects in CompanyImport — Batch 20 (QUA-197)#1536

Closed
hungdqdesign wants to merge 121 commits intopaperclipai:masterfrom
hungdqdesign:fix/a11y-batch20-company-import-qua-197
Closed

fix(a11y): add aria-label to selects in CompanyImport — Batch 20 (QUA-197)#1536
hungdqdesign wants to merge 121 commits intopaperclipai:masterfrom
hungdqdesign:fix/a11y-batch20-company-import-qua-197

Conversation

@hungdqdesign
Copy link

Summary

Fix 3 <select> elements trong CompanyImport.tsx thiếu accessible names. Field component render <label> nhưng không có htmlFor/id association, nên screen readers không announce label khi focus vào controls.

Changes:

  • aria-label={Adapter type for ${agent.name}} — select chọn adapter cho từng agent trong import list
  • aria-label="Import target" — select chọn "new company" vs "existing company"
  • aria-label="Collision strategy" — select chọn rename/skip/replace strategy

Test plan

  • Screen reader (VoiceOver/NVDA) trên CompanyImport — adapter select announce "Adapter type for [tên agent]"
  • Import target select announce "Import target"
  • Collision strategy select announce "Collision strategy"
  • npx tsc --noEmit pass ✅

Closes QUA-197

🤖 Generated with Claude Code

hungdqdesign and others added 30 commits March 21, 2026 00:24
… 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>
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>
…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>
…s equivalents

- packages/db: replaced `cp -r` with `fs.cpSync(..., {recursive: true})`
- cli: replaced `chmod +x` with a Node.js platform check that only
  runs chmodSync on darwin/linux, skipping Windows entirely

Closes #1462
Closes #1463

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>
… local_trusted mode

When a bearer token is present but fails validation (expired JWT, invalid key),
the default local_trusted board actor was not cleared, allowing unauthenticated
requests to inherit full board-level access. This enabled agents with expired
auth to perform destructive operations like deleting other agents.

Now clears the actor to { type: "none" } when a bearer token is present before
validation, so only successful verification restores the proper actor type.

Fixes #1314

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
jwtConfig() only read PAPERCLIP_AGENT_JWT_SECRET, but server startup
(index.ts) accepts BETTER_AUTH_SECRET as a fallback. When only
BETTER_AUTH_SECRET is set (common in local dev), all agent runs failed
to get PAPERCLIP_API_KEY injected. Align the fallback chain so local
agents authenticate correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…th EPERM

On Windows without Developer Mode, symlink creation fails with EPERM.
The new symlinkOrCopy helper catches EPERM and falls back to
fs.cp(source, target, {recursive: true}), allowing skills to be
installed without requiring elevated privileges.

Closes #1464

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
)

On Windows without Developer Mode, symlink creation fails with EPERM.
Add a three-tier fallback: symlink → junction → recursive copy.
This ensures skills installation works for all Windows users without
requiring elevated permissions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hungdqdesign and others added 26 commits March 22, 2026 10:48
…oard nav (QUA-168)

- Add scope="col" to all 6 <th> elements for screen reader compatibility
- Add aria-label="Routines" to <table> element
- Add tabIndex={0}, role="button", aria-label, and onKeyDown (Enter/Space)
  to clickable <tr> rows so keyboard users can navigate to routine details

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…A-183)

CommentThread.tsx:
- CopyMarkdownButton: add aria-label="Copy as markdown"
- Sort toggle button: add aria-label matching sort state description
- Attach image button: add aria-label="Attach image"

IssueDetail.tsx:
- Copy button (mobile + desktop): add aria-label="Copy issue as markdown"
- Properties button (mobile): add aria-label="Show properties"
- Properties button (desktop): add aria-label="Show properties"
- Delete attachment button: add aria-label="Delete attachment"

BudgetPolicyCard.tsx:
- Add htmlFor="budget-policy-input" to label
- Add id="budget-policy-input" to Input
- Fixes WCAG 2.1 SC 1.3.1 form label association

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…on to load more (QUA-183)

- Use React.useId() in BudgetPolicyCard to generate unique id per instance,
  preventing duplicate id when component renders in a loop (Costs page)
- Add type="button" to Load more activity button in IssueDetail.tsx
- Make CLI company-id option optional in activity/agent/dashboard commands

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Standardize the software development lifecycle for the Engineering team:
intake → spec → dev → QA → release. Includes roles, checklists,
templates, Definition of Done, and code review guidelines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…9, QUA-170)

Add visible focus indicators for keyboard navigation (WCAG 2.4.7):
- EntityRow: focus-visible outline on clickable rows
- MetricCard: focus-visible outline on onClick variant
- OrgChart: focus-visible outline on node cards

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add missing aria-label attributes to 4 icon-only buttons:
- Minimize/Maximize toggle button
- Close button
- Remove document button
- Remove attachment button

Fixes WCAG 2.1 SC 4.1.2 (Name, Role, Value) Level AA violations.

Co-Authored-By: Claude Sonnet 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>
…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>
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 22, 2026

Too many files changed for review. (132 files found, 100 file limit)

@hungdqdesign hungdqdesign closed this by deleting the head repository Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant