Skip to content

feat(mail): add +rule-reorder shortcut with auto-fill algorithm#1173

Open
bubbmon233 wants to merge 1 commit into
larksuite:mainfrom
bubbmon233:feat/f089f54
Open

feat(mail): add +rule-reorder shortcut with auto-fill algorithm#1173
bubbmon233 wants to merge 1 commit into
larksuite:mainfrom
bubbmon233:feat/f089f54

Conversation

@bubbmon233
Copy link
Copy Markdown
Collaborator

@bubbmon233 bubbmon233 commented May 29, 2026

Generated by the harness-coding skill.

  • Branch: feat/f089f54
  • Target: main

Sprints

ID Title Status Commit
S1 Synthesize transport contract for larksuite/cli passed
S2 Add +rule-reorder shortcut with auto-fill algorithm skipped

Skipped

  • S2: already_implemented: all 5 items from sprint intent already exist on branch feat/f089f54 (commit 3b2aaaa)

Source specs

  • tech-design.md

This MR was created autonomously. Quality gates were enforced by the repo's own pre-commit hooks.

Implement mail rule reorder shortcut that auto-fills missing rule IDs
based on current sorting order. User-provided IDs are treated as anchors;
unmentioned IDs fill gaps between consecutive anchor pairs that enclose
them in current order, preserving their relative sequence.

sprint: S2
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

📝 Walkthrough

Walkthrough

This PR introduces the +rule-reorder mail shortcut, enabling users to reorder mailbox inbox rules by providing a subset of rule IDs. The implementation validates input, auto-fills missing rule IDs using a gap-filling algorithm that preserves relative ordering, calls the backend reorder API, and provides comprehensive test coverage and documentation.

Changes

Mail rule reorder shortcut

Layer / File(s) Summary
Mail rule reorder shortcut implementation
shortcuts/mail/mail_rule_reorder.go
MailRuleReorder shortcut with validation for required --rule-ids, dry-run flow listing current rules, execution that fetches rules, validates user IDs, gap-fills missing IDs, and posts reorder request. Helper functions parse CSV IDs, extract IDs from API responses, and implement the gap-filling reorder algorithm.
Unit and integration tests
shortcuts/mail/mail_rule_reorder_test.go
Test coverage for the gap-filling algorithm (no-op, swaps, partial reordering, error cases), CSV parsing, ID extraction, shortcut metadata, validation callbacks (empty/duplicate/invalid IDs), dry-run JSON structure, and end-to-end execution with mocked APIs including success and error paths.
Shortcut registration
shortcuts/mail/shortcuts.go
MailRuleReorder is added to the exported shortcuts list.
Skill documentation
skill-template/domains/mail.md, skills/lark-mail/references/lark-mail-rule-reorder.md
Skill template and reference documentation covering command purpose, parameters, execution flow with gap-filling algorithm example, return values, typical scenarios, error handling, constraints, and related commands.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

domain/mail, size/M

Suggested reviewers

  • chanthuang
  • infeng

Poem

📬 A clever rabbit sorts the inbox with care,
Reordering rules with a gap-fill so fair,
Each ID finds its place in the order anew,
Auto-filling the blanks—now that's quite a clue! 🐰✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is largely incomplete. While it provides task ID and branch metadata, it lacks the required Summary, Changes list, Test Plan checklist, and Related Issues sections from the template. Add a brief summary of motivation, list the main changes (new shortcut implementation, tests, documentation), document test verification steps, and specify related issues or state 'None'.
Docstring Coverage ⚠️ Warning Docstring coverage is 41.38% 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
Title check ✅ Passed The title accurately describes the main change: adding a mail rule reorder shortcut with an auto-fill algorithm, which matches the primary focus of the changeset.
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 unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions github-actions Bot added domain/mail PR touches the mail domain size/L Large or sensitive change across domains or core paths labels May 29, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 29, 2026

Codecov Report

❌ Patch coverage is 88.61789% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.97%. Comparing base (e18ea9a) to head (3b2aaaa).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
shortcuts/mail/mail_rule_reorder.go 89.34% 7 Missing and 6 partials ⚠️
shortcuts/mail/shortcuts.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1173      +/-   ##
==========================================
+ Coverage   68.92%   68.97%   +0.05%     
==========================================
  Files         628      630       +2     
  Lines       58744    58885     +141     
==========================================
+ Hits        40487    40614     +127     
- Misses      14951    14959       +8     
- Partials     3306     3312       +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@3b2aaaa4f53fcf218459d432aae5529f438c666b

🧩 Skill update

npx skills add bubbmon233/cli#feat/f089f54 -y -g

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

🧹 Nitpick comments (2)
shortcuts/mail/mail_rule_reorder_test.go (2)

428-443: ⚡ Quick win

Prefer the shared runtime test helper here.

runtimeForRuleReorder hand-builds RuntimeContext, which is easy to drift from the repo’s shortcut test setup. Using the standard validate/dry-run helper keeps these tests aligned with future runtime initialization changes.

Based on learnings, use common.TestNewRuntimeContext(t, config) for validate/dry-run unit tests that only cover flag parsing and branch logic and do not perform HTTP requests.

🤖 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 `@shortcuts/mail/mail_rule_reorder_test.go` around lines 428 - 443, The test
helper runtimeForRuleReorder manually constructs a RuntimeContext from flags and
should be replaced with the shared helper to avoid drift; update the function
(or callers) to call common.TestNewRuntimeContext(t, values) instead of
hand-building cobra.Command and setting flags, or change runtimeForRuleReorder
to simply return common.TestNewRuntimeContext(t, values), ensuring the same
map[string]string values are passed through so flag parsing and RuntimeContext
creation use the canonical test helper.

335-368: ⚡ Quick win

Assert the reorder request body in the success path.

This test only checks the formatted output. If Execute prints the right rule_ids but posts a different payload, the backend contract regresses and this still passes. Please have the POST stub verify the rule_ids body as well.

🤖 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 `@shortcuts/mail/mail_rule_reorder_test.go` around lines 335 - 368, The POST
stub for "/user_mailboxes/me/rules/reorder" currently only returns {"code":0}
but doesn't assert the request payload; update the httpmock.Stub registered for
that URL so its Body (or BodyJSON matcher) verifies the incoming "rule_ids"
array equals the expected payload (the reordered IDs from the test input, e.g.
["E","A"]) before returning code 0. Locate the stub registration near the test
that calls runMountedMailShortcut(t, MailRuleReorder, ...) and add the
verification of the "rule_ids" field to ensure the Execute call posts the
correct request body.
🤖 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 `@shortcuts/mail/mail_rule_reorder.go`:
- Around line 117-137: The extractRuleIDs function must fail closed instead of
silently skipping malformed items: change extractRuleIDs to validate every item
and return an error when an entry is not a map[string]interface{} or when an
"id" is missing/empty (e.g. change signature to return ([]string, error)), and
update the caller Execute to check the error and abort before
constructing/posting rule_ids; ensure the error message identifies the offending
item index or content so the reorder POST is never sent with an incomplete
rule_ids list.

---

Nitpick comments:
In `@shortcuts/mail/mail_rule_reorder_test.go`:
- Around line 428-443: The test helper runtimeForRuleReorder manually constructs
a RuntimeContext from flags and should be replaced with the shared helper to
avoid drift; update the function (or callers) to call
common.TestNewRuntimeContext(t, values) instead of hand-building cobra.Command
and setting flags, or change runtimeForRuleReorder to simply return
common.TestNewRuntimeContext(t, values), ensuring the same map[string]string
values are passed through so flag parsing and RuntimeContext creation use the
canonical test helper.
- Around line 335-368: The POST stub for "/user_mailboxes/me/rules/reorder"
currently only returns {"code":0} but doesn't assert the request payload; update
the httpmock.Stub registered for that URL so its Body (or BodyJSON matcher)
verifies the incoming "rule_ids" array equals the expected payload (the
reordered IDs from the test input, e.g. ["E","A"]) before returning code 0.
Locate the stub registration near the test that calls runMountedMailShortcut(t,
MailRuleReorder, ...) and add the verification of the "rule_ids" field to ensure
the Execute call posts the correct request body.
🪄 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

Run ID: bf332ee4-2d15-4046-807f-912cf4067e8e

📥 Commits

Reviewing files that changed from the base of the PR and between 1ba107d and 3b2aaaa.

📒 Files selected for processing (5)
  • shortcuts/mail/mail_rule_reorder.go
  • shortcuts/mail/mail_rule_reorder_test.go
  • shortcuts/mail/shortcuts.go
  • skill-template/domains/mail.md
  • skills/lark-mail/references/lark-mail-rule-reorder.md

Comment on lines +117 to +137
func extractRuleIDs(data map[string]interface{}) []string {
if data == nil {
return nil
}
items, ok := data["items"].([]interface{})
if !ok {
return nil
}
ids := make([]string, 0, len(items))
for _, item := range items {
m, ok := item.(map[string]interface{})
if !ok {
continue
}
id, _ := m["id"].(string)
if id != "" {
ids = append(ids, id)
}
}
return ids
}
Copy link
Copy Markdown

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

Fail closed on malformed rule items.

extractRuleIDs silently skips non-object entries and empty/missing id fields. That lets Execute build and POST an incomplete rule_ids list even though this API requires the full ordered set. Please return an error here and abort before the reorder call instead of dropping bad items.

Suggested direction
-func extractRuleIDs(data map[string]interface{}) []string {
+func extractRuleIDs(data map[string]interface{}) ([]string, error) {
 	if data == nil {
-		return nil
+		return nil, output.Errorf(output.ExitAPI, "api_error", "list rules response missing data")
 	}
 	items, ok := data["items"].([]interface{})
 	if !ok {
-		return nil
+		return nil, output.Errorf(output.ExitAPI, "api_error", "list rules response missing items")
 	}
 	ids := make([]string, 0, len(items))
-	for _, item := range items {
+	for i, item := range items {
 		m, ok := item.(map[string]interface{})
 		if !ok {
-			continue
+			return nil, output.Errorf(output.ExitAPI, "api_error", "rule item %d is malformed", i)
 		}
-		id, _ := m["id"].(string)
-		if id != "" {
-			ids = append(ids, id)
+		id, ok := m["id"].(string)
+		if !ok || id == "" {
+			return nil, output.Errorf(output.ExitAPI, "api_error", "rule item %d missing id", i)
 		}
+		ids = append(ids, id)
 	}
-	return ids
+	return ids, nil
 }
📝 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
func extractRuleIDs(data map[string]interface{}) []string {
if data == nil {
return nil
}
items, ok := data["items"].([]interface{})
if !ok {
return nil
}
ids := make([]string, 0, len(items))
for _, item := range items {
m, ok := item.(map[string]interface{})
if !ok {
continue
}
id, _ := m["id"].(string)
if id != "" {
ids = append(ids, id)
}
}
return ids
}
func extractRuleIDs(data map[string]interface{}) ([]string, error) {
if data == nil {
return nil, output.Errorf(output.ExitAPI, "api_error", "list rules response missing data")
}
items, ok := data["items"].([]interface{})
if !ok {
return nil, output.Errorf(output.ExitAPI, "api_error", "list rules response missing items")
}
ids := make([]string, 0, len(items))
for i, item := range items {
m, ok := item.(map[string]interface{})
if !ok {
return nil, output.Errorf(output.ExitAPI, "api_error", "rule item %d is malformed", i)
}
id, ok := m["id"].(string)
if !ok || id == "" {
return nil, output.Errorf(output.ExitAPI, "api_error", "rule item %d missing id", i)
}
ids = append(ids, id)
}
return ids, nil
}
🤖 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 `@shortcuts/mail/mail_rule_reorder.go` around lines 117 - 137, The
extractRuleIDs function must fail closed instead of silently skipping malformed
items: change extractRuleIDs to validate every item and return an error when an
entry is not a map[string]interface{} or when an "id" is missing/empty (e.g.
change signature to return ([]string, error)), and update the caller Execute to
check the error and abort before constructing/posting rule_ids; ensure the error
message identifies the offending item index or content so the reorder POST is
never sent with an incomplete rule_ids list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain/mail PR touches the mail domain size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant