Skip to content

feat: add master checkbox for bulk selection in manual cleanup#50

Open
rdfitted wants to merge 5 commits intomainfrom
issue/49-master-checkbox-bulk-selection
Open

feat: add master checkbox for bulk selection in manual cleanup#50
rdfitted wants to merge 5 commits intomainfrom
issue/49-master-checkbox-bulk-selection

Conversation

@rdfitted
Copy link
Copy Markdown
Owner

@rdfitted rdfitted commented Jan 23, 2026

Summary

Resolves #49

Adds a tri-state master checkbox to the DuplicateGroupsPreview component header for improved bulk selection UX in manual cleanup mode.

Changes

  • Tri-state logic: Master checkbox shows checked (all selected), unchecked (none selected), or indeterminate (partial selection)
  • State management: Used useMemo for derived state (allSelected, isIndeterminate)
  • DOM sync: Used useRef + useEffect to sync indeterminate property (DOM-only, not React attribute)
  • Accessibility: Added aria-label, keyboard navigation support (Tab, Space)
  • UI replacement: Replaced old "Select All" / "Deselect All" text buttons with master checkbox
  • Styling: Matches existing individual checkboxes with dark mode support
  • Edge case: Master checkbox hidden when no groups present

Workers

  • Worker-1 (Opus): Implemented tri-state logic and master toggle handler
  • Worker-2 (Gemini): Implemented UI styling and accessibility improvements
  • Worker-3 (GLM): Verified backend/frontend coherence
  • Worker-4 (Codex): Code simplification review
  • Resolver (Opus): Addressed reviewer findings (none required)
  • Tester (Codex): Tests passing, fixed edge case for empty groups

Difficulties Encountered

Pre-existing lint warnings in unrelated files (useCleanup.ts, useFlowClone.ts) - not addressed as they don't affect this feature

Session

20260122-144008-resolve-issue-49

Generated by Hive multi-agent system

Summary by CodeRabbit

  • New Features

    • Tri-state master checkbox for bulk selecting duplicate groups; per-group selection/actions shown only in interactive/manual mode.
    • Execution now accepts pre-approved groups to skip duplicate detection and proceed immediately.
  • Accessibility

    • Updated ARIA labels and semantics to reflect multi-state checkbox behavior.
  • Documentation

    • Reorganized project guidance into curated categories and hot spots.
    • Added three new learning entries to project documentation.

✏️ Tip: You can customize this high-level summary in your review settings.

- Add tri-state master checkbox to DuplicateGroupsPreview header
- Use useMemo for allSelected and isIndeterminate calculations
- Use useRef + useEffect to sync indeterminate DOM property
- Add accessibility support (aria-label, keyboard navigation)
- Replace old text buttons with master checkbox UI
- Match styling to existing individual checkboxes
- Hide master checkbox when no groups present

Resolves #49

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @rdfitted, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the user experience for manual cleanup of duplicate groups by introducing a tri-state master checkbox. This new control allows users to efficiently select all, deselect all, or partially select groups, streamlining the bulk action process and replacing the less intuitive separate 'Select All' and 'Deselect All' buttons. The implementation focuses on robust state management, accessibility, and consistent UI design.

Highlights

  • Tri-state Master Checkbox: Implemented a tri-state master checkbox in the DuplicateGroupsPreview component, allowing for bulk selection, deselection, or partial selection of duplicate groups.
  • React Hooks for State Management: Utilized useMemo for deriving allSelected and isIndeterminate states, and useRef combined with useEffect to imperatively set the DOM's indeterminate property for the master checkbox.
  • Accessibility Improvements: Enhanced accessibility by adding aria-label attributes to both the master and individual group checkboxes, and ensured keyboard navigation support.
  • UI Streamlining: Replaced the previous 'Select All' and 'Deselect All' text buttons with the new, more integrated master checkbox for a cleaner user interface.
  • Conditional Rendering and Styling: The master checkbox is now conditionally rendered, appearing only when there are groups to select, and its styling has been updated to match existing checkboxes, including dark mode support.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 23, 2026

Walkthrough

Adds a tri-state master checkbox to DuplicateGroupsPreview for bulk selection in manual cleanup mode; introduces an isManualInteractive gate. Separately, CleanupExecutor.execute gains a fast path to accept pre-approved groups (bypassing detection) and emits detectComplete for approved input. Documentation and AI learning notes updated.

Changes

Cohort / File(s) Summary
Master Checkbox Feature
app/components/migration/DuplicateGroupsPreview.tsx
Added tri-state master checkbox using useRef + useEffect for DOM indeterminate, derived allSelected / isIndeterminate (via useMemo), introduced isManualInteractive gate, replaced Select/Deselect text buttons with master toggle, conditional per-group checkboxes, updated ARIA labels, removed DuplicateItem import.
Executor: approvedGroups bypass
lib/migration/cleanup/executor.ts
Added branch to use provided approvedGroups as limitedGroups, set hasApprovedGroups flag in logs, update job status to in_progress and emit detectComplete with approved groups to skip detection; unified limitedGroups usage downstream.
AI Docs / Learnings
.ai-docs/learnings.jsonl
Appended three learning entries documenting the master-checkbox change and PR comment follow-ups.
Project Doc Rewrite
.ai-docs/project-dna.md
Large structural/content reorganization (Core Patterns, Hot Spots, Keyword Clusters, Session Insights, Curated Guidelines); non-executable documentation updates.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant CleanupExecutor
  participant Detector
  participant JobEmitter

  Caller->>CleanupExecutor: execute(job, { approvedGroups? })
  alt approvedGroups provided
    CleanupExecutor->>CleanupExecutor: limitedGroups = approvedGroups
    CleanupExecutor->>JobEmitter: emit detectComplete(limitedGroups)
    CleanupExecutor->>JobEmitter: update job status -> in_progress
  else no approvedGroups
    CleanupExecutor->>JobEmitter: update job status -> detecting
    CleanupExecutor->>Detector: detectDuplicateGroups(jobId, filters)
    Detector-->>CleanupExecutor: detectedGroups
    CleanupExecutor->>CleanupExecutor: apply maxGroups -> limitedGroups
    CleanupExecutor->>JobEmitter: emit detectComplete(limitedGroups)
  end
  CleanupExecutor->>CleanupExecutor: proceed with manual/auto steps using limitedGroups
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop in code with tiny paws so spry,
A tri-state nibble — select many or shy.
One dash for some, a check for all,
I tidy groups and answer the call. ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes out-of-scope changes: updates to .ai-docs/learnings.jsonl and .ai-docs/project-dna.md add documentation artifacts unrelated to the feature requirement, and lib/migration/cleanup/executor.ts optimizes duplicate detection bypass logic not mentioned in issue #49. Remove learning entries from .ai-docs/learnings.jsonl, revert changes to .ai-docs/project-dna.md, and justify or remove the approvedGroups optimization from executor.ts if unrelated to this feature scope.
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 (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: adding a master checkbox for bulk selection in manual cleanup mode to the DuplicateGroupsPreview component.
Linked Issues check ✅ Passed The PR comprehensively addresses all core requirements from issue #49: implements tri-state master checkbox with proper accessibility, derives state via useMemo, syncs indeterminate via useRef/useEffect, reuses selection functions, and conditionally displays based on mode and dry-run state.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch issue/49-master-checkbox-bulk-selection

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

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request introduces a tri-state master checkbox for bulk selection in the DuplicateGroupsPreview component, which is a significant improvement for the manual cleanup user experience. The implementation correctly leverages React hooks such as useMemo, useRef, and useEffect for managing derived state and syncing DOM properties. Accessibility features like aria-label are appropriately added, and the refactoring to use the isManualInteractive variable consistently across the component enhances readability and maintainability. The handling of edge cases, such as hiding the master checkbox when no groups are present, is well-considered. Overall, the changes are well-implemented and align with best practices for React development.

Copy link
Copy Markdown

@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

🤖 Fix all issues with AI agents
In `@app/components/migration/DuplicateGroupsPreview.tsx`:
- Around line 132-141: The master checkbox doesn't expose the mixed state to
assistive tech; update the input rendered in DuplicateGroupsPreview to include
an aria-checked attribute driven by isIndeterminate: set aria-checked to "mixed"
when isIndeterminate is true, otherwise set it to the boolean value matching
allSelected (true/false); change only the input element that uses
masterCheckboxRef, checked={allSelected}, onChange={handleMasterToggle} and
aria-label={masterCheckboxAriaLabel} so screen readers receive the mixed state.

Comment on lines +132 to +141
{isManualInteractive && groups.length > 0 && (
<label className="flex items-center gap-2 cursor-pointer">
<input
ref={masterCheckboxRef}
type="checkbox"
checked={allSelected}
onChange={handleMasterToggle}
className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700"
aria-label={masterCheckboxAriaLabel}
/>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Jan 23, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Expose the mixed state via aria-checked.

The master checkbox uses indeterminate, but the mixed state isn’t announced to assistive tech. The PR objectives require aria-checked to be true / false / mixed. Please add aria-checked based on isIndeterminate.

✅ Suggested fix
             <input
               ref={masterCheckboxRef}
               type="checkbox"
               checked={allSelected}
               onChange={handleMasterToggle}
               className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700"
               aria-label={masterCheckboxAriaLabel}
+              aria-checked={isIndeterminate ? 'mixed' : allSelected}
             />
📝 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
{isManualInteractive && groups.length > 0 && (
<label className="flex items-center gap-2 cursor-pointer">
<input
ref={masterCheckboxRef}
type="checkbox"
checked={allSelected}
onChange={handleMasterToggle}
className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700"
aria-label={masterCheckboxAriaLabel}
/>
{isManualInteractive && groups.length > 0 && (
<label className="flex items-center gap-2 cursor-pointer">
<input
ref={masterCheckboxRef}
type="checkbox"
checked={allSelected}
onChange={handleMasterToggle}
className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700"
aria-label={masterCheckboxAriaLabel}
aria-checked={isIndeterminate ? 'mixed' : allSelected}
/>
🤖 Prompt for AI Agents
In `@app/components/migration/DuplicateGroupsPreview.tsx` around lines 132 - 141,
The master checkbox doesn't expose the mixed state to assistive tech; update the
input rendered in DuplicateGroupsPreview to include an aria-checked attribute
driven by isIndeterminate: set aria-checked to "mixed" when isIndeterminate is
true, otherwise set it to the boolean value matching allSelected (true/false);
change only the input element that uses masterCheckboxRef,
checked={allSelected}, onChange={handleMasterToggle} and
aria-label={masterCheckboxAriaLabel} so screen readers receive the mixed state.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ Verified by 4 OpenCode Agents

Consensus: MISTAKEN - Adding aria-checked to native HTML checkboxes is incorrect and can cause accessibility issues.

Multi-Agent Verification Results

Models Used:

  • OpenCode BigPickle (Deep Analysis)
  • OpenCode GLM 4.7 (Pattern Recognition)
  • OpenCode Grok Code (Quick Search)
  • OpenCode MiniMax M2.1 (Multi-Language)

Vote: 2-2 Tie → Claude Orchestrator Final Decision: MISTAKEN

Evidence

The current implementation uses a native HTML <input type="checkbox"> (line 136), not an ARIA role="checkbox".

According to W3C/MDN accessibility standards:

"You should NOT use aria-checked on native HTML checkboxes." The indeterminate property on native checkboxes is automatically exposed to assistive technology without additional ARIA attributes. Adding aria-checked can create inconsistencies between the native checkbox state and the ARIA state, causing different behaviors across screen readers.

Current Implementation (Correct)

<input
  ref={masterCheckboxRef}
  type="checkbox"
  checked={allSelected}
  onChange={handleMasterToggle}
  aria-label={masterCheckboxAriaLabel}  // ✅ This is correct
/>

The indeterminate property is set via ref + useEffect (lines 45-50), which is the proper pattern for native checkboxes.

When aria-checked IS Required

aria-checked is ONLY required when using role="checkbox" on non-native elements (e.g., <div role="checkbox">). For native <input type="checkbox"> elements, browsers handle accessibility automatically.

Sources

No changes needed - current implementation follows accessibility best practices.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@rdfitted Thank you for the thorough verification and correction! You're absolutely right—my original suggestion was mistaken.

For native HTML <input type="checkbox"> elements, the indeterminate property (set via ref + useEffect as done in lines 45-50) is automatically exposed to assistive technology, and adding aria-checked would be incorrect and could introduce accessibility conflicts.

The aria-checked attribute is only needed when implementing custom checkboxes with role="checkbox" on non-native elements like <div>.

Your current implementation is correct and follows accessibility best practices. I appreciate the detailed explanation and sources—this ensures better guidance going forward!


✏️ Learnings added
Learnt from: rdfitted
Repo: rdfitted/podiomigrationassistant PR: 50
File: app/components/migration/DuplicateGroupsPreview.tsx:132-141
Timestamp: 2026-01-23T01:43:58.874Z
Learning: Do NOT add `aria-checked` to native HTML `<input type="checkbox">` elements. The `indeterminate` property on native checkboxes is automatically exposed to assistive technology. The `aria-checked` attribute should only be used with `role="checkbox"` on non-native elements (e.g., `<div role="checkbox">`). For native checkboxes, use the ref + useEffect pattern to set the indeterminate property.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

- Added learning from resolveprcomments-50 session
- Key insight: aria-checked should NOT be on native checkboxes
- Multi-agent verification (4 OpenCode models) with tie-breaker works
- Regenerated project-dna.md with 6 session learnings
- Added accessibility standards patterns to DNA
- Updated hot spots and keyword clusters

Co-Authored-By: Codex GPT-5.2 <noreply@openai.com>
Copy link
Copy Markdown

@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

🤖 Fix all issues with AI agents
In @.ai-docs/project-dna.md:
- Line 128: The guideline line "Don't add ARIA to native HTML elements" is too
broad; update it to clarify that ARIA should not duplicate or conflict with
built-in semantics but that certain ARIA attributes (e.g., aria-label,
aria-describedby, aria-expanded, aria-live) are valid on native elements;
specifically call out the checkbox indeterminate case (avoid using aria-checked
on a native <input type="checkbox"> with indeterminate state, prefer using the
native indeterminate property and clear guidance instead). Replace the single
sentence with a short rule like: "Avoid adding ARIA that duplicates or conflicts
with native semantics — use native controls where possible; use ARIA attributes
(aria-label, aria-describedby, aria-expanded, aria-live) when they add necessary
semantics; do not use aria-checked on native checkbox inputs with indeterminate
state (use the input's indeterminate property and accompanying accessible
instructions)."

Update overly broad ARIA guideline in project-dna.md from "Don't add ARIA to
native HTML elements" to more specific guidance: "Don't override native semantic
state with ARIA". The refined guideline clarifies:

- Valid ARIA usage: aria-label, aria-describedby for supplementary info
- Invalid ARIA usage: aria-checked, aria-selected, aria-pressed on native elements
- Rationale: Native checkboxes/radios/buttons expose state automatically

Verified by 4 OpenCode agents (BigPickle, GLM 4.7, Grok Code, MiniMax M2.1)
confirming the codebase uses valid ARIA attributes on native elements.

Simplified by Codex GPT-5.2 for improved clarity.

Curated 7 learnings and updated project-dna.md with new patterns.

Resolves CodeRabbit PR comment on #50

Co-Authored-By: Codex GPT-5.2 <noreply@openai.com>
Copy link
Copy Markdown

@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

🤖 Fix all issues with AI agents
In @.ai-docs/project-dna.md:
- Around line 10-15: The markdown uses emphasis (e.g. "**Multi-Agent
Workflows**") as pseudo-headings which triggers MD036; replace those emphasized
labels with proper heading syntax (e.g. "## Multi-Agent Workflows") or convert
them to plain paragraph text where a heading is not intended; update all similar
occurrences referenced (lines covering the blocks like the list items and the
other flagged ranges 43-46, 47-49, 55-57, 59-61, 62-65, 153) by changing
instances of "**...**" or "*...*" used as headings into real headings (#, ##,
etc.) or plain text so markdownlint MD036 is satisfied.

rdfitted and others added 2 commits January 22, 2026 16:38
Convert bold/italic emphasis used as headings to proper markdown heading syntax (####).

Changes:
- Convert **Section Name** to #### Section Name for all subsection headers
- Update "What Works" section headers (11 fixes)
- Update "What Doesn't Work" section headers (3 fixes)
- Maintains proper heading hierarchy under ### parent sections
- Aligns with project markdown standards (README.md, bug-patterns.md)

Code simplification (Codex GPT-5.2):
- Add spacing around arrows (→) for readability
- Wrap technical terms in backticks for consistency
- Improve grammatical accuracy

Learning captured:
- Multi-agent verification (4 OpenCode models) confirmed MD036 violations
- Proper heading syntax provides semantic structure and consistency
- Updated project-dna.md with new learning and curated insights

Co-Authored-By: Codex GPT-5.2 <noreply@openai.com>
When clicking "Proceed" after a dry run, the executor was unnecessarily
re-scanning the entire app even though approved groups were already
provided. This caused:
- Status to regress to "detecting"
- Risk of getting stuck if scan was interrupted
- Wasted time re-scanning large datasets

Now when approvedGroups are provided, detection is skipped entirely
and execution proceeds directly with the pre-approved groups.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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.

improve: add master checkbox for bulk selection in manual cleanup

1 participant