Skip to content

Family-keyed atoms + Data.struct keys (DX feedback wanted)#32

Open
Atchferox wants to merge 3 commits into
mainfrom
chore/improve-atom-handling
Open

Family-keyed atoms + Data.struct keys (DX feedback wanted)#32
Atchferox wants to merge 3 commits into
mainfrom
chore/improve-atom-handling

Conversation

@Atchferox
Copy link
Copy Markdown
Collaborator

@Atchferox Atchferox commented May 10, 2026

Summary

Two parallel refactors landed in one commit (a83cf59):

  1. Family-key the ticket mutations. Fixes the bleed where editing one ticket's title flipped the waiting state on every other ticket that read useAtomValue(updateTicketAtom). tickets.ts now mirrors the tags.ts shape: updateTicketAtom = Atom.family((TicketKey) => ticketAtom(key).pipe(Atom.optimisticFn({ reducer: spread payload, fn: AppApiClient.mutation(...) }))). delete/create family-keyed plain mutations.

  2. Replace string-concat keys with Data.struct compound keys. Verified that Atom.family memoizes via Effect's MutableHashMap (Equal.equals-based), so structural keys hit the same atom on every call. New packages/frontend/src/atoms/keys.ts is the single source of truth: OrgKey, ProjectKey, TicketKey, CommentKey, MemberKey, BranchesKey, ReposKey. No more splitProjectKey / splitTicketKey / etc. — factories destructure directly. Also: typed-distinct (you can't pass a ProjectKey where a TicketKey is expected) and no implicit "slug must not contain /" constraint.

While I was in there I also migrated the remaining atom modules (projects.ts, comments.ts, github.ts) from runtime.atom/runtime.fn over to AppApiClient.query/mutation, and switched the project/github query atoms from .pipe(Atom.setIdleTTL(...)) to the inline timeToLive option (same primitive — AtomHttpApi.js:47 literally calls Atom.setIdleTTL for finite values).

Why I'm not sure about the DX (@Chippr-Wouter — would love your read)

A few things land differently than the old pattern, and I'd like your gut reaction before this becomes the house style:

  • Mutation call shape got more verbose. Old: await create({ id: ticket.id, name, baseBranch }). New: await create({ path: { orgSlug, slug, id: ticket.id }, payload: { name, baseBranch }, reactivityKeys: githubWriteKeys }). It's the API request shape verbatim, which is good for traceability but easy to forget reactivityKeys (silent failure — dependent queries don't refresh). Worth a lint? A helper that bakes in the right reactivityKeys per atom?

  • Data.struct keys allocate a new object every call. Cheap, but stylistically a step away from the upstream examples (which all use string keys). You lose the ability to log/inspect a key as a single string. Up-side is the type distinctness — that part I'm happy with. Want to see this style across the codebase or roll back to branded strings?

  • Family-keyed optimistic mutations have two readers (the wrapper for waiting state, the underlying mutation atom for raw status). The pattern works, but "which atom do I read for X" requires a doc to internalise. CLAUDE.md covers it, but I wonder if a thin useMutation(family, key) helper would pay off — it'd collapse useAtomSet + useAtomValue + .waiting + Result.isFailure into one hook. I deliberately didn't add that yet; let me know if the boilerplate is bothering you when you read the diff.

  • Project mutation paths now repeat { orgSlug, slug } at every call site because the family key drives memoization, not the input. This is the CLAUDE.md rule ("path fields come from the key, not the input"), but it does feel like double-typing. A helper that accepts the key + a payload-only arg might be ergonomic — though again I didn't want to invent abstractions before we feel the pain.

The bleed fix from (1) is unambiguously the right call. (2)/(3) are the discussion-worthy bits.

Test plan

  • bun run typecheck clean (✅ verified locally)
  • bun run dev boots; no console errors at startup (✅ verified)
  • Edit ticket A's title with ticket B expanded — only A pulses (the bleed fix's golden path)
  • Fire status changes on A and B back-to-back — independent waiting + independent errors
  • Comment create/edit/delete still refresh the comments list
  • Member add/remove/role change still refresh the project detail
  • Branch create/attach/clear still refresh git states
  • Project create/update/delete refresh from list and detail

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added specific error messages for HTTP conflicts, permission errors, validation issues, rate limiting, unauthorized access, and generic GitHub errors.
  • Refactor

    • Improved internal state management with more structured and type-safe key handling across data operations.
    • Enhanced error message mapping for better user-facing feedback on various failure scenarios.

Review Change Stack

Atchferox added 2 commits May 10, 2026 14:49
- Added new error messages for conflict, forbidden access, not found, rate limiting, unauthorized access, and validation errors in common.json.
- Introduced a generic GitHub error message in git.json.
- Created a new file for reactivity keys to manage state updates more effectively.
- Refactored tag management in tags.ts to utilize AppApiClient for API interactions and improved optimistic updates for tag creation, renaming, and deletion.
- Updated TagEditor component to incorporate reactivity keys for tag operations.
- Enhanced error message handling in errorMessage.ts to include new error types.
- Add keys.ts with Data.struct-based keys for structural equality in Atom.family
- Replace string-split key pattern across all atom modules with typed key objects
- Update mutation callsites to pass structured { path, payload, reactivityKeys } args
- Wrap ticketAtom in optimistic layer; make createTicketAtom family-keyed
@Atchferox Atchferox requested a review from Chippr-Wouter May 10, 2026 13:39
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

📝 Walkthrough

Walkthrough

This PR refactors frontend state management by introducing structured typed keys (OrgKey, ProjectKey, TicketKey, etc.) for Atom.family memoization, replacing string-based keys. All atom modules (auth, comments, github, projects, tags, tickets) migrate to AppApiClient with explicit reactivity groups; 20+ UI components update mutation calls to use structured path/payload/reactivityKeys arguments. Error handling expands to cover validation and GitHub-specific variants.

Changes

Frontend Atom Refactoring with Typed Keys and Reactivity

Layer / File(s) Summary
Key Type Definitions
packages/frontend/src/atoms/keys.ts
New module exports structured key types (OrgKey, ProjectKey, TicketKey, CommentKey, MemberKey, BranchesKey, ReposKey) built with Data.struct for Effect equality, domain-scoped to prevent cross-domain key misuse.
Reactivity Key Groups
packages/frontend/src/atoms/reactivity-keys.ts
New module defines ReactivityKey constant mapping domains (auth/projects/tickets/tags/comments/groups/github) and exports *WriteKeys arrays for write-scoped mutation configuration.
AppApiClient Service
packages/frontend/src/services/AppApiClient.ts
New service module configures AppApiClient as an Atom API tag using AppApi and FetchHttpClient.layer with /api base URL.
Auth Atom Refactor
packages/frontend/src/atoms/auth.ts
Updates meAtom to use AppApiClient.query("auth", "me") with ReactivityKey.auth; removes logoutAtom export.
Comments Atom Refactor
packages/frontend/src/atoms/comments.ts
Refactors comment atoms to accept structured TicketKey/CommentKey and use AppApiClient.query/mutation; optimistic reducers use typed key fields; removes manual refresh calls.
GitHub Atom Refactor
packages/frontend/src/atoms/github.ts
Refactors GitHub atoms to accept ProjectKey/ReposKey/BranchesKey; queries and mutations use AppApiClient with explicit reactivityKeys and cache TTLs; optimistic updates keyed by arg.path.id; removes manual refresh logic.
Projects Atom Refactor
packages/frontend/src/atoms/projects.ts
Refactors project/member atoms to use OrgKey/ProjectKey/MemberKey with AppApiClient.query/mutation; removes local key construction and explicit atom refresh calls.
Tags Atom Refactor
packages/frontend/src/atoms/tags.ts
Refactors tag atoms to use ProjectKey with AppApiClient.query/mutation; optimistic reducers read arg.payload/arg.path; removes manual refresh calls; re-exports tagsKey from keys module.
Tickets Atom Refactor
packages/frontend/src/atoms/tickets.ts
Refactors ticket atoms to use ProjectKey/TicketKey with AppApiClient.query/mutation; introduces internal ticketBaseAtom and wraps with Atom.optimistic; removes manual refresh calls.
Ticket List UI Atoms
packages/frontend/src/atoms/ticketListUi.ts
Updates all UI state atoms to accept ProjectKey instead of string keys; re-exports ticketListUiKey from keys module.
Component Wiring
packages/frontend/src/components/**/*.tsx
Updates 20+ components (Comments, CreateTicketRow, GithubChip, MembersSection, TagEditor, TicketGit/*, TicketList/*) to call atom actions with structured { path, payload, reactivityKeys } arguments instead of flat payloads.
Route Integration
packages/frontend/src/routes/**/*.tsx
Updates route handlers to use key constructors (orgKey, projectKey, ticketsListKey) when subscribing to atoms and to pass structured arguments with reactivityKeys for mutations.
Error Types & Localization
packages/frontend/src/lib/errorMessage.ts, packages/frontend/messages/en/*
Expands AppError union with validation and GitHub-specific variants (Validation, GitHubTokenExpired, GitHubScopeInsufficient, RepoGone, BranchExists, BranchProtected, BranchNotFound); updates errorMessage to exhaustively match all variants with specific localized messages; adds error message keys to common.json and git.json.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • Chippr-Wouter

Poem

🐰 Atoms now dance with structured keys so fine,
Typed scopes and reactivity in perfect design,
No more string soup or manual refresh today,
Components flow smoothly the AppApiClient way!
Path, payload, keys—a harmonious tale,
Your state management journey will surely prevail! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main changes: family-keyed atoms and Data.struct-based keys, which directly correspond to the primary refactors described in the objectives.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/improve-atom-handling
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch chore/improve-atom-handling

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
packages/frontend/src/atoms/tickets.ts (1)

32-52: 🏗️ Heavy lift

Bind mutation path to the family key.

Line 32 already scopes the setter to a specific TicketKey, but Lines 42, 48, and 52 still let callers pass an arbitrary path. If those ever diverge, the optimistic reducer updates ticket A while the request mutates ticket B. Capturing key inside the family helper would remove that mismatch class and also trim the callshape.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/frontend/src/atoms/tickets.ts` around lines 32 - 52, The
family-created atoms updateTicketAtom, deleteTicketAtom, and createTicketAtom
currently let callers supply an arbitrary mutation path, causing possible
mismatches between the optimistic reducer (ticketAtom(key)) and the actual
mutation target; fix by capturing the family key inside each Atom.family and
binding it into the mutation call so the path is derived from that key (e.g.,
close over TicketKey and call AppApiClient.mutation(..., { path: key } or
equivalent) instead of exposing a free path argument), and then adjust the
callshape so callers no longer pass a path; update deleteTicketAtom and
createTicketAtom to follow the same pattern used by updateTicketAtom (close over
key) so the optimistic update and network mutation always reference the same
ticket key.
packages/frontend/src/atoms/github.ts (1)

77-98: 💤 Low value

Hardcoded baseBranch: "main" in attachBranchAtom reducer.

Unlike createBranchAtom which uses arg.payload.baseBranch ?? "main", this reducer hardcodes "main". If the attach payload can include a baseBranch field, consider using arg.payload.baseBranch ?? "main" for consistency.

♻️ Suggested change for consistency
         const optimistic: GitState = {
           tag: "branch_no_pr",
           name: arg.payload.name,
-          baseBranch: "main"
+          baseBranch: arg.payload.baseBranch ?? "main"
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/frontend/src/atoms/github.ts` around lines 77 - 98,
attachBranchAtom's optimistic reducer hardcodes baseBranch as "main"; change the
reducer to derive baseBranch from the attach payload like createBranchAtom does.
In the attachBranchAtom reducer (inside Atom.family -> projectGitStatesAtom(...)
-> Atom.optimisticFn), replace the hardcoded baseBranch with
arg.payload.baseBranch ?? "main" when building the optimistic GitState (the
object using tag:"branch_no_pr", name: arg.payload.name) and ensure the result
still updates states at [arg.path.id] and returns Result.success with { waiting:
true } for the AppApiClient.mutation("tickets", "attachBranch") optimistic path.
packages/frontend/src/components/GithubChip.tsx (1)

184-184: ⚡ Quick win

Memoize the repos key to reduce per-render key allocations.

At Line 184, reposKey(query) is rebuilt every render. Memoizing keeps key-object creation tied to query changes only.

💡 Proposed refactor
 function ConnectPanel({ orgSlug, slug }: { orgSlug: string; slug: string }) {
   const [query, setQuery] = useState("")
-  const repos = useAtomValue(githubReposAtom(reposKey(query)))
+  const repoLookupKey = useMemo(() => reposKey(query), [query])
+  const repos = useAtomValue(githubReposAtom(repoLookupKey))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/frontend/src/components/GithubChip.tsx` at line 184, The repos key
passed into githubReposAtom is being re-created each render via reposKey(query);
change the code in the GithubChip component to memoize that key so it only
reallocates when query changes (e.g., compute const key = useMemo(() =>
reposKey(query), [query]) and then call useAtomValue(githubReposAtom(key))).
This ensures the symbol reposKey and the atom githubReposAtom receive a stable
key and prevents unnecessary per-render allocations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/frontend/src/atoms/tags.ts`:
- Around line 66-74: The optimistic reducer in deleteTagAtom doesn't remove the
tag from the local value; update the reducer passed to Atom.optimisticFn in
deleteTagAtom (the reducer function that currently uses (current, _arg)) to,
when Result.isSuccess(current), return Result.success(filteredValue, { waiting:
true }) where filteredValue is current.value with the tag matching
_arg.path.name removed (i.e., filter out items whose name === _arg.path.name);
keep the same Result and waiting semantics and leave removeTag as the optimistic
fn.

In `@packages/frontend/src/components/TicketGit/CreateBranchFields.tsx`:
- Around line 92-93: The branch-create flow closes the form immediately after
dispatching updateTicket(ticketKey(...)) without waiting for the status-update
result; change the logic in CreateBranchFields so that after calling
updateTicket (from useAtomSet(updateTicketAtom(ticketKey(orgSlug, slug,
ticket.id)))), you await or observe the update result and only close the form on
success, and surface or handle errors (e.g., show a toast/error state) if the
update fails; apply the same fix to the other occurrence around lines 135-141 so
both success paths wait for and react to the status write outcome before
closing.

---

Nitpick comments:
In `@packages/frontend/src/atoms/github.ts`:
- Around line 77-98: attachBranchAtom's optimistic reducer hardcodes baseBranch
as "main"; change the reducer to derive baseBranch from the attach payload like
createBranchAtom does. In the attachBranchAtom reducer (inside Atom.family ->
projectGitStatesAtom(...) -> Atom.optimisticFn), replace the hardcoded
baseBranch with arg.payload.baseBranch ?? "main" when building the optimistic
GitState (the object using tag:"branch_no_pr", name: arg.payload.name) and
ensure the result still updates states at [arg.path.id] and returns
Result.success with { waiting: true } for the AppApiClient.mutation("tickets",
"attachBranch") optimistic path.

In `@packages/frontend/src/atoms/tickets.ts`:
- Around line 32-52: The family-created atoms updateTicketAtom,
deleteTicketAtom, and createTicketAtom currently let callers supply an arbitrary
mutation path, causing possible mismatches between the optimistic reducer
(ticketAtom(key)) and the actual mutation target; fix by capturing the family
key inside each Atom.family and binding it into the mutation call so the path is
derived from that key (e.g., close over TicketKey and call
AppApiClient.mutation(..., { path: key } or equivalent) instead of exposing a
free path argument), and then adjust the callshape so callers no longer pass a
path; update deleteTicketAtom and createTicketAtom to follow the same pattern
used by updateTicketAtom (close over key) so the optimistic update and network
mutation always reference the same ticket key.

In `@packages/frontend/src/components/GithubChip.tsx`:
- Line 184: The repos key passed into githubReposAtom is being re-created each
render via reposKey(query); change the code in the GithubChip component to
memoize that key so it only reallocates when query changes (e.g., compute const
key = useMemo(() => reposKey(query), [query]) and then call
useAtomValue(githubReposAtom(key))). This ensures the symbol reposKey and the
atom githubReposAtom receive a stable key and prevents unnecessary per-render
allocations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 19a9c5ab-73bd-448e-aa52-80331c4ad4e9

📥 Commits

Reviewing files that changed from the base of the PR and between c0df546 and a83cf59.

📒 Files selected for processing (31)
  • packages/frontend/messages/en/common.json
  • packages/frontend/messages/en/git.json
  • packages/frontend/src/atoms/auth.ts
  • packages/frontend/src/atoms/comments.ts
  • packages/frontend/src/atoms/github.ts
  • packages/frontend/src/atoms/keys.ts
  • packages/frontend/src/atoms/projects.ts
  • packages/frontend/src/atoms/reactivity-keys.ts
  • packages/frontend/src/atoms/tags.ts
  • packages/frontend/src/atoms/ticketListUi.ts
  • packages/frontend/src/atoms/tickets.ts
  • packages/frontend/src/components/Comments/CommentComposer.tsx
  • packages/frontend/src/components/Comments/CommentRow.tsx
  • packages/frontend/src/components/CreateTicketRow.tsx
  • packages/frontend/src/components/GithubChip.tsx
  • packages/frontend/src/components/MembersSection.tsx
  • packages/frontend/src/components/TagEditor.tsx
  • packages/frontend/src/components/TicketGit/ClearBranchFields.tsx
  • packages/frontend/src/components/TicketGit/ConnectBranchFields.tsx
  • packages/frontend/src/components/TicketGit/CreateBranchFields.tsx
  • packages/frontend/src/components/TicketList/AssigneeField.tsx
  • packages/frontend/src/components/TicketList/Expanded.tsx
  • packages/frontend/src/components/TicketList/PriorityField.tsx
  • packages/frontend/src/components/TicketList/StatusField.tsx
  • packages/frontend/src/components/TicketList/TypeField.tsx
  • packages/frontend/src/lib/errorMessage.ts
  • packages/frontend/src/routes/_authed/orgs/$orgSlug/index.tsx
  • packages/frontend/src/routes/_authed/orgs/$orgSlug/projects/$slug/about.tsx
  • packages/frontend/src/routes/_authed/orgs/$orgSlug/projects/$slug/route.tsx
  • packages/frontend/src/routes/_authed/orgs/$orgSlug/projects/index.tsx
  • packages/frontend/src/services/AppApiClient.ts

Comment thread packages/frontend/src/atoms/tags.ts
Comment on lines +92 to 93
const updateTicket = useAtomSet(updateTicketAtom(ticketKey(orgSlug, slug, ticket.id)))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle status-update failure before closing the form.

The branch-create success path closes immediately after dispatching updateTicket, but the update result is not observed. If it fails, users see a silent partial success.

✅ Suggested fix (await status write outcome)
-  const updateTicket = useAtomSet(updateTicketAtom(ticketKey(orgSlug, slug, ticket.id)))
+  const updateTicket = useAtomSet(
+    updateTicketAtom(ticketKey(orgSlug, slug, ticket.id)),
+    { mode: "promiseExit" }
+  )

   if (Exit.isSuccess(exit)) {
-    if (status !== ticket.status)
-      updateTicket({
-        path: { orgSlug, slug, id: ticket.id },
-        payload: { status },
-        reactivityKeys: ticketWriteKeys
-      })
+    if (status !== ticket.status) {
+      const statusExit = await updateTicket({
+        path: { orgSlug, slug, id: ticket.id },
+        payload: { status },
+        reactivityKeys: ticketWriteKeys
+      })
+      if (!Exit.isSuccess(statusExit)) {
+        setBusy(false)
+        return
+      }
+    }
     close()
   } else {
     setBusy(false)
   }

Also applies to: 135-141

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/frontend/src/components/TicketGit/CreateBranchFields.tsx` around
lines 92 - 93, The branch-create flow closes the form immediately after
dispatching updateTicket(ticketKey(...)) without waiting for the status-update
result; change the logic in CreateBranchFields so that after calling
updateTicket (from useAtomSet(updateTicketAtom(ticketKey(orgSlug, slug,
ticket.id)))), you await or observe the update result and only close the form on
success, and surface or handle errors (e.g., show a toast/error state) if the
update fails; apply the same fix to the other occurrence around lines 135-141 so
both success paths wait for and react to the status write outcome before
closing.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/frontend/src/atoms/tags.ts`:
- Around line 80-81: There are stray closing parentheses after the deleteTagAtom
definition (the extra `)` tokens following the `deleteTagAtom` closure) causing
a parse error; remove the extraneous `)` characters so that `deleteTagAtom` (and
surrounding atom definitions) close only once and the file parses correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 142b2d29-db1f-4a06-8e91-ebad2f6c6a1c

📥 Commits

Reviewing files that changed from the base of the PR and between a83cf59 and e9d9e9c.

📒 Files selected for processing (1)
  • packages/frontend/src/atoms/tags.ts

Comment on lines +80 to +81
)
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Remove stray closing parentheses — parse error.

Lines 80–81 contain extra ) tokens after deleteTagAtom is already properly closed at line 79. This causes a syntax error that will fail compilation.

🐛 Proposed fix
     })
   )
 )
-  )
-)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
)
)
})
)
)
🧰 Tools
🪛 Biome (2.4.15)

[error] 80-81: Expected a statement but instead found ')
)'.

(parse)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/frontend/src/atoms/tags.ts` around lines 80 - 81, There are stray
closing parentheses after the deleteTagAtom definition (the extra `)` tokens
following the `deleteTagAtom` closure) causing a parse error; remove the
extraneous `)` characters so that `deleteTagAtom` (and surrounding atom
definitions) close only once and the file parses correctly.

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