Skip to content

fix(a11y): add type=button to bare <button> elements — Batch 23 (QUA-201)#1551

Open
hungdqdesign wants to merge 355 commits intopaperclipai:masterfrom
hungdqdesign:fix/a11y-button-type-batch23-qua-201
Open

fix(a11y): add type=button to bare <button> elements — Batch 23 (QUA-201)#1551
hungdqdesign wants to merge 355 commits intopaperclipai:masterfrom
hungdqdesign:fix/a11y-button-type-batch23-qua-201

Conversation

@hungdqdesign
Copy link

Summary

Thêm type="button" vào 78 <button> elements không có explicit type trên 16 files.

HTML spec: <button> không có type mặc định là type="submit" bên trong <form>. Best practice: luôn khai báo type="button" cho non-submit buttons.

Không có file nào trong danh sách này chứa <form> element, nên đây là best practice fix và future-proofing.

Files changed (78 additions)

File Buttons fixed
NewIssueDialog.tsx 14
IssuesList.tsx 10
IssueProperties.tsx 10
AgentConfigForm.tsx 8
OnboardingWizard.tsx 8
ProjectProperties.tsx 5
NewAgent.tsx 5
Agents.tsx 4
AgentDetail.tsx 4
CompanySkills.tsx 4
Sidebar.tsx, CompanyImport.tsx, IssueDetail.tsx, Routines.tsx, Goals.tsx, Projects.tsx 1 each

Test plan

  • npx tsc --noEmit pass ✅
  • No functional regressions (pure attribute additions)

Closes QUA-201

🤖 Generated with Claude Code

hungdqdesign and others added 30 commits March 21, 2026 23:11
…aperclipai#1387)

When POST /agents/:id/wakeup is called directly, the contextSnapshot
lacked issueId/projectId/projectWorkspaceId, causing resolveWorkspaceForRun()
to fall back to agent_home instead of using the project workspace.

Fix:
- Include projectId and projectWorkspaceId in all issue wakeup contextSnapshots
  (checkout, update, status_change) in issues.ts
- In the wakeup endpoint (agents.ts), auto-resolve the checked-out issue
  for the agent and inject its context into the snapshot
- Add unit tests verifying contextSnapshot shape

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Addresses review comment: adapters like codex_local and cursor have
both static and dynamic model lists. Now checks listAdapterModels()
(which includes runtime-discovered models) before returning 422.

Also adds wakeup context snapshot unit tests.

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>
…rclipai#1361)

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>
…button guard (paperclipai#1473)

- Add accessible DialogTitle (sr-only) to NewIssueDialog, NewGoalDialog,
  NewProjectDialog, NewAgentDialog, and Routines dialogs to resolve
  Radix UI accessibility warnings
- Fix Create Issue button: disable when no company is selected, preventing
  silent no-op on click

Closes paperclipai#1473

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

The catch handler in sw.js could pass undefined to event.respondWith():
- Navigate requests: `caches.match("/") || fallback` used || on a Promise
  (always truthy) so the fallback Response was never reached
- Non-navigate requests: caches.match(request) resolves to undefined on
  cache miss with no fallback

Both paths now use .then() to properly chain the fallback Response.
Bump cache version to v3 to force SW update.

Closes paperclipai#1473

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…paperclipai#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 paperclipai#1465

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

The catch handler in sw.js could pass undefined to event.respondWith():
- Navigate requests: `caches.match("/") || fallback` used || on a Promise
  (always truthy) so the fallback Response was never reached
- Non-navigate requests: caches.match(request) resolves to undefined on
  cache miss with no fallback

Both paths now use .then() to properly chain the fallback Response.
Bump cache version to v3 to force SW update.

Closes paperclipai#1473

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rver crash (paperclipai#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 (paperclipai#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>
…s page (paperclipai#1461)

When the codex binary is not installed, navigating to Costs → Providers
crashes the server with an unhandled spawn ENOENT error. Add a process
error handler to CodexRpcClient that rejects pending requests gracefully
instead of crashing the server process.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s page (paperclipai#1461)

When the codex binary is not installed, navigating to Costs → Providers
crashes the server with an unhandled spawn ENOENT error. Add a process
error handler to CodexRpcClient that rejects pending requests gracefully
instead of crashing the server process.

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

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>
…uivalents (paperclipai#1462, paperclipai#1463)

Replace `cp -r` in packages/db and `chmod +x` in cli build scripts
with Node.js fs.cpSync and conditional fs.chmodSync so the build
succeeds on Windows without requiring Git Bash or WSL.

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

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>
…i#1403)

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>
…ewIssueDialog

The service worker's offline fallback used `caches.match("/") || new
Response(...)` which always evaluates to the Promise (truthy), so on
cache miss respondWith received undefined instead of a Response. Fixed
by chaining with `.then()` to properly fall back.

Also added a hidden DialogTitle to NewIssueDialog to silence Radix
accessibility warnings about missing titles for screen readers.

Closes paperclipai#1473

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

The service worker's offline fallback used `caches.match("/") || new
Response(...)` which always evaluates to the Promise (truthy), so on
cache miss respondWith received undefined instead of a Response. Fixed
by chaining with `.then()` to properly fall back.

Also added a hidden DialogTitle to NewIssueDialog to silence Radix
accessibility warnings about missing titles for screen readers.

Closes paperclipai#1473

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

jwtConfig() only read PAPERCLIP_AGENT_JWT_SECRET, while the server
startup in index.ts accepts BETTER_AUTH_SECRET as a fallback. This
caused all local agent runs to skip JWT injection when only
BETTER_AUTH_SECRET was set (common in local dev).

Now jwtConfig() falls back to BETTER_AUTH_SECRET, matching the server
startup behavior. PAPERCLIP_AGENT_JWT_SECRET still takes priority.

Closes paperclipai#1451

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…paperclipai#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 paperclipai#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 paperclipai#1461

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>
…rclipai#1361)

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 (paperclipai#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>
hungdqdesign and others added 27 commits March 22, 2026 14:53
- Remove non-existent resolveClaimedApiKeyPath re-export
- Remove extra { force } arg from release() call (signature mismatch)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove orphaned openclaw-gateway-claimed-key-path test (function removed)
- Fix duplicate betterAuthEnv declaration in agent-auth-jwt test
- Add routineService + reportRunActivity mocks to subtask/document tests
- Rename robustLink → symlinkOrCopy in paperclip-skill-utils test
- Update --json → --experimental-json in codex-local test
- Update AGENTS.md assertion to match new onboarding content
- Add groupBy() chain support to budgets-service mock
- Remove non-existent resolveClaimedApiKeyPath re-export

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

78 buttons across 16 files were missing explicit type attribute.
HTML spec: <button> without type defaults to type="submit" inside <form>.
Best practice: always declare type="button" for non-submit buttons.

Files:
- NewIssueDialog.tsx (+14)
- IssuesList.tsx (+10)
- IssueProperties.tsx (+10)
- AgentConfigForm.tsx (+8)
- OnboardingWizard.tsx (+8)
- ProjectProperties.tsx (+5)
- NewAgent.tsx (+5)
- Agents.tsx (+4)
- AgentDetail.tsx (+4)
- CompanySkills.tsx (+4)
- Sidebar.tsx (+1), CompanyImport.tsx (+1), IssueDetail.tsx (+1)
- Routines.tsx (+1), Goals.tsx (+1), Projects.tsx (+1)

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. (217 files found, 100 file limit)

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