Skip to content

feat(mail): unknown-flag fuzzy-match for lark-cli mail domain#806

Merged
xzcong0820 merged 1 commit into
larksuite:mainfrom
xzcong0820:harness/01kr5edze944jyrxcn6m99jcd1
May 12, 2026
Merged

feat(mail): unknown-flag fuzzy-match for lark-cli mail domain#806
xzcong0820 merged 1 commit into
larksuite:mainfrom
xzcong0820:harness/01kr5edze944jyrxcn6m99jcd1

Conversation

@xzcong0820

@xzcong0820 xzcong0820 commented May 11, 2026

Copy link
Copy Markdown
Collaborator

Generated by the harness-coding skill.

  • Task ID: 01KR5EDZE944JYRXCN6M99JCD1-9
  • Branch: harness/01kr5edze944jyrxcn6m99jcd1
  • Target: main

Summary

Adds mail-domain unknown-flag fuzzy-match → JSON ErrorEnvelope with did-you-mean candidates for lark-cli mail. Strictly scoped to shortcuts/mail/ + a 1-line branch in shortcuts/register.go; non-mail domains are untouched. Exit code is unchanged (still 1 via ExitAPI, not ExitValidation) — no breaking change to callers parsing exit codes.

3 files changed, 508 insertions:

  • shortcuts/mail/flag_suggest.go — implementation (InstallOnMail, parseUnknownToken, collectFlags, suggest w/ prefix + Levenshtein DP, suggestShorthand, buildHint).
  • shortcuts/mail/flag_suggest_test.go — 12 table-driven tests covering prefix / Levenshtein / hidden-skipped / top-N stable sort / shorthand exact + prefix fallback / parse regex / errorFunc pass-through / exit-code regression.
  • shortcuts/register.go — +3 lines: if service == "mail" { mail.InstallOnMail(svc) } after the mount loop.

Sprints

ID Title Status Commit
S1 Synthesize transport contract for larksuite/cli (mail flag_suggest) passed
S2 Implement mail-domain unknown-flag fuzzy match + ErrorEnvelope passed 5ae9c2d

Source specs

  • V5 tech-design
  • /tmp/harness-agent/coding-dev/01KR5EDZE944JYRXCN6M99JCD1/01KR5EDZE944JYRXCN6M99JCD1-9/input/tech-design.md

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

Summary by CodeRabbit

  • New Features

    • Mail commands now provide intelligent unknown-flag suggestions (up to 5 candidates) with concise “Did you mean … ?” hints or a help hint.
  • Behavior

    • Registering the Mail service installs a mail-specific flag-suggestion hook so unknown-flag errors return a structured, user-facing error and consistent exit code.
  • Tests

    • Added extensive unit and integration tests for suggestion ranking, shorthand handling, hidden-flag exclusion, parsing edge cases, and exit-error formatting.

Review Change Stack

@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 11, 2026
@coderabbitai

coderabbitai Bot commented May 11, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4ddbaaac-5cfb-4a3d-a41a-7a4deebc41d0

📥 Commits

Reviewing files that changed from the base of the PR and between 35745b5 and 4dbbe72.

📒 Files selected for processing (4)
  • shortcuts/mail/flag_suggest.go
  • shortcuts/mail/flag_suggest_test.go
  • shortcuts/register.go
  • shortcuts/register_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • shortcuts/register.go
  • shortcuts/register_test.go
  • shortcuts/mail/flag_suggest_test.go
  • shortcuts/mail/flag_suggest.go

📝 Walkthrough

Walkthrough

Adds mail-specific unknown-flag error detection and suggestion generation. A new InstallOnMail function registers a custom error handler on the mail Cobra command that detects unknown-flag errors, parses the problematic token, collects available flags, generates prefix-based and edit-distance-based suggestions, builds a user hint, and returns a structured ExitError with candidate details. Integration occurs in the shortcut registration flow.

Changes

Mail Flag Suggestion Error Handler

Layer / File(s) Summary
Package header & Candidate type
shortcuts/mail/flag_suggest.go
Adds package/imports and introduces Candidate struct plus maxCandidates.
Public API
shortcuts/mail/flag_suggest.go
Exports InstallOnMail(*cobra.Command) which installs a custom FlagErrorFunc on the command.
Error handler & install
shortcuts/mail/flag_suggest.go
Implements flagSuggestErrorFunc that detects unknown-flag errors and dispatches to parseUnknownToken, rawUnknownToken, collectFlags, suggest (long flags) and suggestShorthand (shorthand); builds hint and returns *output.ExitError with Detail.Type == "unknown_flag".
Token parsing & raw token
shortcuts/mail/flag_suggest.go
Adds parseUnknownToken to extract unknown tokens (long and shorthand formats) and rawUnknownToken to format the echoed token.
Flag snapshot
shortcuts/mail/flag_suggest.go
Adds collectFlags to snapshot command flags (name, shorthand, hidden) used by suggestion algorithms.
Long-flag suggestion
shortcuts/mail/flag_suggest.go
Adds suggest performing bidirectional prefix matches (distance=0, reason="prefix") and Levenshtein-based candidates within a computed threshold (reason="edit_distance"), stable-sorted and capped.
Shorthand suggestion
shortcuts/mail/flag_suggest.go
Adds suggestShorthand returning exact shorthand matches first or falling back to long flags starting with the shorthand char; excludes hidden flags.
Helpers: hint, threshold, levenshtein
shortcuts/mail/flag_suggest.go
Adds buildHint, levThreshold, and a two-row levenshtein DP implementation.
Registration integration
shortcuts/register.go, shortcuts/register_test.go
Calls mail.InstallOnMail(svc) during RegisterShortcutsWithContext when service == "mail" and adds registration tests asserting mail-only installation and non-mail isolation.
Tests
shortcuts/mail/flag_suggest_test.go, shortcuts/register_test.go
Unit tests cover long/shorthand suggestion, hidden-flag exclusion, token parsing (including value-tail stripping), error-to-exit conversion payload and output.ExitAPI code, nil-safety, levThreshold/levenshtein edge cases, and end-to-end registration behavior.

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Suggested reviewers:
    • liangshuo-1

🐰 Flag hints bloom like carrots in spring,
Unknown flags caught, suggestions they bring,
Edit distance measures, prefix paths show,
Better UX for mail, our CLI aglow!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description does not follow the required template structure, missing the structured 'Summary', 'Changes', 'Test Plan', and 'Related Issues' sections. Restructure the description to match the template: add 'Summary' section (1-3 sentences), 'Changes' section (bulleted list), 'Test Plan' section with checkboxes, and 'Related Issues' section.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.48% 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 'feat(mail): unknown-flag fuzzy-match for lark-cli mail domain' clearly and concisely summarizes the main change: adding fuzzy-matching for unknown flags in the mail subcommand.
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.

@codecov

codecov Bot commented May 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.11765% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.85%. Comparing base (4d62542) to head (4dbbe72).
⚠️ Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
shortcuts/mail/flag_suggest.go 94.02% 4 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #806      +/-   ##
==========================================
+ Coverage   65.46%   65.85%   +0.39%     
==========================================
  Files         510      517       +7     
  Lines       47129    48761    +1632     
==========================================
+ Hits        30851    32113    +1262     
- Misses      13607    13885     +278     
- Partials     2671     2763      +92     

☔ 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

github-actions Bot commented May 11, 2026

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@4dbbe72a6e5d49960e4cca0203dc48053a64fdc2

🧩 Skill update

npx skills add xzcong0820/larksuite-cli#harness/01kr5edze944jyrxcn6m99jcd1 -y -g

Comment thread shortcuts/mail/flag_suggest.go Outdated
Comment thread shortcuts/mail/flag_suggest.go
@xzcong0820
xzcong0820 force-pushed the harness/01kr5edze944jyrxcn6m99jcd1 branch from 5ae9c2d to d271bf3 Compare May 11, 2026 12:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@shortcuts/register_test.go`:
- Around line 357-363: The test currently only checks that returned error isn't
an *output.ExitError; additionally assert that the FlagErrorFunc is identity by
verifying the exact pointer is returned: call baseCmd.FlagErrorFunc()(baseCmd,
in) (already assigned to got) and assert got == in (pointer equality) to ensure
pass-through; update the test around the variables got and in (and the
FlagErrorFunc invocation) to include this equality check so any
wrapper/regression will fail.
🪄 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: d918f259-9a3a-4b2d-ab83-caca250b3df7

📥 Commits

Reviewing files that changed from the base of the PR and between 5ae9c2d and d271bf3.

📒 Files selected for processing (4)
  • shortcuts/mail/flag_suggest.go
  • shortcuts/mail/flag_suggest_test.go
  • shortcuts/register.go
  • shortcuts/register_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • shortcuts/register.go
  • shortcuts/mail/flag_suggest.go

Comment thread shortcuts/register_test.go
@xzcong0820
xzcong0820 force-pushed the harness/01kr5edze944jyrxcn6m99jcd1 branch from d271bf3 to 35745b5 Compare May 12, 2026 02:51

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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/flag_suggest_test.go`:
- Around line 65-80: TestSuggest_TopNAndStableSort never exercises top-N or
tie-break because unknown == "zzz" yields distances > levThreshold so suggest
returns empty; change the test so the unknown token (or the test names) produce
Levenshtein distances <= levThreshold for all candidates and equal among them so
suggest("...", names) returns a non-empty slice and exercises the cap and
lexicographic tie-break; update the string passed to suggest in
TestSuggest_TopNAndStableSort (or adjust the flagName entries) to a value within
levThreshold so the assertions on maxCandidates and stable sorting actually run.

In `@shortcuts/mail/flag_suggest.go`:
- Around line 72-84: The detail map may set "candidates" to a nil slice when
collectFlags(c) returns no entries because suggest or suggestShorthand can
return nil; change the construction so that matches is always a non-nil empty
slice before building detail (e.g., after calling suggest/suggestShorthand, if
matches == nil then set matches = []Candidate{}), so the "candidates" field in
the detail map is always emitted as an array; update references around
collectFlags(c), suggestShorthand(token, names), suggest(token, names), and the
detail variable accordingly.
🪄 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: c6beea24-3251-4623-9a5a-dd63dee4d561

📥 Commits

Reviewing files that changed from the base of the PR and between d271bf3 and 35745b5.

📒 Files selected for processing (4)
  • shortcuts/mail/flag_suggest.go
  • shortcuts/mail/flag_suggest_test.go
  • shortcuts/register.go
  • shortcuts/register_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • shortcuts/register.go
  • shortcuts/register_test.go

Comment thread shortcuts/mail/flag_suggest_test.go Outdated
Comment thread shortcuts/mail/flag_suggest.go
Adds shortcuts/mail/flag_suggest.go (~120 LOC) implementing a cobra
FlagErrorFunc hook for the mail subcommand tree. On 'unknown flag: --X'
or 'unknown shorthand flag: "X" in -X', it collects flags from the
current command via cmd.Flags().VisitAll, runs bidirectional prefix
match + Levenshtein DP (threshold=max(1,len/3+1), cap 4), and returns
top-5 candidates inside the existing ErrorEnvelope JSON:

  error.type = "unknown_flag"
  error.detail.{unknown, command_path, candidates}
  error.detail.candidates[*] = {flag, shorthand, distance, reason}

Exit code stays 1 (ExitAPI), not ExitValidation - no breaking change for
CI/agent scripts that check non-zero exit. stderr switches from plain
'Error: unknown flag: --X' to JSON envelope, aligning with the existing
'errors = JSON envelope on stderr' convention; mail unknown-flag was the
last gap.

Scope is strictly the mail subcommand tree: shortcuts/register.go gains
a single 'if service == "mail" { mail.InstallOnMail(svc) }' branch
after the existing Mount loop. Other domains (calendar / im / api /
auth / ...) keep cobra's default FlagErrorFunc and unchanged plain-text
stderr behavior.

Covers:
- shortcuts/mail/flag_suggest.go      (new, ~120 LOC)
- shortcuts/mail/flag_suggest_test.go (new, 12 table-driven tests)
- shortcuts/register.go               (+3 lines after mail Mount loop)

No changes to cmd/root.go or internal/output/* - ErrDetail.Detail is
already interface{}, handleRootError already routes *ExitError via
WriteErrorEnvelope.
@xzcong0820
xzcong0820 force-pushed the harness/01kr5edze944jyrxcn6m99jcd1 branch from 35745b5 to 4dbbe72 Compare May 12, 2026 03:21
@xzcong0820
xzcong0820 merged commit 1180baa into larksuite:main May 12, 2026
18 checks passed
@liangshuo-1 liangshuo-1 mentioned this pull request May 12, 2026
2 tasks
xzcong0820 added a commit to xzcong0820/larksuite-cli that referenced this pull request May 19, 2026
Adds a per-shortcut FlagHints map (common/types.go) that lets mail
shortcuts declare known flag aliases (e.g. "recipient" → "to").

At mount time, runner.go serialises FlagHints into cmd.Annotations so
the data is accessible at error-handling time without creating a circular
import between common and mail.

mail/flag_suggest.go's flagSuggestErrorFunc gains a Priority-0 path that
reads the hint map from cmd.Annotations and inserts the exact-match
target as candidates[0] with reason="hint" and distance=0, before the
existing prefix + Levenshtein fallback. The hint target is deduplicated
from the suggest() results so it never appears twice.

FlagHints is configured on five mail shortcuts:
- mail_draft_edit, mail_message, mail_send, mail_thread, mail_triage

Output format (candidates[] array, error.type="unknown_flag") is
unchanged from PR larksuite#806.
tuxedomm pushed a commit to zhumiaoxin/cli that referenced this pull request Jun 6, 2026
…rksuite#806)

Adds shortcuts/mail/flag_suggest.go (~120 LOC) implementing a cobra
FlagErrorFunc hook for the mail subcommand tree. On 'unknown flag: --X'
or 'unknown shorthand flag: "X" in -X', it collects flags from the
current command via cmd.Flags().VisitAll, runs bidirectional prefix
match + Levenshtein DP (threshold=max(1,len/3+1), cap 4), and returns
top-5 candidates inside the existing ErrorEnvelope JSON:

  error.type = "unknown_flag"
  error.detail.{unknown, command_path, candidates}
  error.detail.candidates[*] = {flag, shorthand, distance, reason}

Exit code stays 1 (ExitAPI), not ExitValidation - no breaking change for
CI/agent scripts that check non-zero exit. stderr switches from plain
'Error: unknown flag: --X' to JSON envelope, aligning with the existing
'errors = JSON envelope on stderr' convention; mail unknown-flag was the
last gap.

Scope is strictly the mail subcommand tree: shortcuts/register.go gains
a single 'if service == "mail" { mail.InstallOnMail(svc) }' branch
after the existing Mount loop. Other domains (calendar / im / api /
auth / ...) keep cobra's default FlagErrorFunc and unchanged plain-text
stderr behavior.

Covers:
- shortcuts/mail/flag_suggest.go      (new, ~120 LOC)
- shortcuts/mail/flag_suggest_test.go (new, 12 table-driven tests)
- shortcuts/register.go               (+3 lines after mail Mount loop)

No changes to cmd/root.go or internal/output/* - ErrDetail.Detail is
already interface{}, handleRootError already routes *ExitError via
WriteErrorEnvelope.
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.

2 participants