Skip to content

feat: standardize mail +triage output to ok/data envelope#1830

Open
zhaojunlin0405 wants to merge 16 commits into
mainfrom
feat/mail-default-json-output
Open

feat: standardize mail +triage output to ok/data envelope#1830
zhaojunlin0405 wants to merge 16 commits into
mainfrom
feat/mail-default-json-output

Conversation

@zhaojunlin0405

@zhaojunlin0405 zhaojunlin0405 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

mail +triage historically printed a bare JSON object, inconsistent with the
rest of the CLI. This standardizes it onto the {ok, data} envelope, with the
message list and pagination inside data — matching the repo-wide list
convention (im +chat-messages-list, calendar +search-event, etc.):

{"ok":true,"data":{"messages":[{…,"mailbox_id":"me"}],"total":N,"has_more":true,"page_token":"list:…"}}

--format supports json | pretty | table | ndjson | csv (Enum-validated,
default json; --json shorthand); table/csv/ndjson render the message rows
via output.ExtractItems, pretty renders the curated human table. mail +watch keeps its streaming output but its default --format is now json,
and its fetch-failure path is emitted as a single NDJSON line (no longer a
multi-line blob). This is a breaking change to mail +triage's JSON contract
(migration below).

Changes

  • Route mail +triage output through a typed triageOutput struct →
    {ok, data:{messages,total,has_more,page_token}}, meta nil
    (shortcuts/mail/mail_triage.go). Uses a struct (like calendar +search-event) so output.toGeneric round-trips it and ExtractItems can
    extract messages for table/csv/ndjson.
  • mail +watch: default --formatjson; keep the fetch-failure line on a
    single NDJSON line via watchFailureOutputValue (shortcuts/mail/mail_watch.go).
  • Adapt triage tests to .data.messages / .data.total|has_more|page_token;
    add an ndjson-per-line regression test and a typed-error --format data
    rejection test.
  • Rewrite skills/lark-mail/references/lark-mail-triage.md; update
    lark-mail-watch.md default.
  • internal/output/envelope.go is unchanged — pagination lives in data,
    so no shared Meta fields were added.

Test Plan

  • go build ./..., go test ./shortcuts/mail/... ./internal/output/...
  • validate: build / vet / unit / integration / convention / security
  • sandbox E2E: 4/4 (envelope-by-format, --format data rejection, --json
    equivalence, ndjson per-line)
  • acceptance review: PASS
  • skill eval: 2/2
  • skipped: mail +watch default enveloped-NDJSON stream — not provable in a
    bounded E2E (long-running WebSocket)

Breaking change (mail +triage): .messages.data.messages; .count
.data.total; .has_more/.page_token.data.has_more/.data.page_token;
top-level mailbox_id removed (still per message); --format data removed
(rejected by the Enum); the curated table moved from --format table to
--format pretty.

Related Issues

N/A

@zhaojunlin0405 zhaojunlin0405 added enhancement New feature or request domain/mail PR touches the mail domain size/M Single-domain feat or fix with limited business impact labels Jul 9, 2026
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Mail triage now defaults to JSON envelopes, supports additional output formats, exposes pagination metadata under meta, and sends notices and navigation hints to stderr. Mail watch also defaults to JSON envelopes. Tests and reference documentation reflect these output contracts.

Changes

Mail output formats

Layer / File(s) Summary
Envelope pagination metadata
internal/output/envelope.go, internal/output/envelope_test.go
Success envelope metadata adds optional has_more and page_token fields with serialization coverage.
Triage output contract and rendering
shortcuts/mail/mail_triage.go
MailTriage defaults to json, supports json, pretty, table, ndjson, and csv, renders through runtime.OutFormat, and emits notices and navigation hints on stderr.
Triage validation and documentation
shortcuts/mail/mail_triage_test.go, shortcuts/mail/mail_json_shorthand_test.go, shortcuts/mail/mail_read_help_test.go, skills/lark-mail/references/lark-mail-triage.md
Tests and documentation cover the JSON envelope, metadata placement, stderr output, explicit formats, pagination fields, and rejection of the removed data format.
Watch JSON output default
shortcuts/mail/mail_watch.go, shortcuts/mail/mail_watch_test.go, skills/lark-mail/references/lark-mail-watch.md
MailWatch defaults to JSON, uses watchOutputValue for enveloped versus bare NDJSON, and documents and tests both output modes.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested labels: feature, size/XL

Suggested reviewers: chanthuang, liangshuo-1

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.57% 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
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.
Title check ✅ Passed The title is concise and describes the main change: standardizing mail +triage output on the ok/data envelope.
Description check ✅ Passed The description includes all required sections and gives a clear summary, change list, test plan, and related issues.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mail-default-json-output

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.

@zhaojunlin0405
zhaojunlin0405 force-pushed the feat/mail-default-json-output branch from e1d151f to c02fa92 Compare July 9, 2026 09:10
@zhaojunlin0405 zhaojunlin0405 changed the title feat: default mail +triage/+watch output to global json format feat: default mail +triage/+watch output to json Jul 9, 2026

@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/mail/mail_watch.go`:
- Line 102: Add a watch test for the default format behavior in
mail_watch_test.go by exercising the +watch flow without passing --format and
asserting stdout uses the default json envelope with {"ok": true, "data": ...}.
Reuse the existing watch/test helpers around the +watch command and the relevant
mail watch entrypoints so the new case verifies the default format path in
mail_watch.go when no format flag is provided.
🪄 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: 17482e69-76bd-4c4d-bb8d-0f11add5381a

📥 Commits

Reviewing files that changed from the base of the PR and between e1d151f and c02fa92.

📒 Files selected for processing (6)
  • shortcuts/mail/mail_read_help_test.go
  • shortcuts/mail/mail_triage.go
  • shortcuts/mail/mail_triage_test.go
  • shortcuts/mail/mail_watch.go
  • skills/lark-mail/references/lark-mail-triage.md
  • skills/lark-mail/references/lark-mail-watch.md
✅ Files skipped from review due to trivial changes (2)
  • skills/lark-mail/references/lark-mail-watch.md
  • skills/lark-mail/references/lark-mail-triage.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • shortcuts/mail/mail_read_help_test.go
  • shortcuts/mail/mail_triage_test.go

Comment thread shortcuts/mail/mail_watch.go
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.66667% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.67%. Comparing base (4847f06) to head (81b778d).
⚠️ Report is 11 commits behind head on main.

Files with missing lines Patch % Lines
shortcuts/mail/mail_triage.go 85.18% 3 Missing and 1 partial ⚠️
shortcuts/mail/mail_watch.go 85.71% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1830      +/-   ##
==========================================
+ Coverage   74.58%   74.67%   +0.08%     
==========================================
  Files         861      877      +16     
  Lines       89971    91736    +1765     
==========================================
+ Hits        67106    68503    +1397     
- Misses      17669    17922     +253     
- Partials     5196     5311     +115     

☔ View full report in Codecov by Harness.
📢 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 Jul 9, 2026

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@81b778de692e20411ea504390e67c876a96679bd

🧩 Skill update

npx skills add larksuite/cli#feat/mail-default-json-output -y -g

@zhaojunlin0405 zhaojunlin0405 changed the title feat: default mail +triage/+watch output to json feat: standardize mail +triage output to ok/data envelope Jul 10, 2026

@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 `@internal/output/envelope.go`:
- Around line 17-22: Remove `omitempty` from the `Meta.Count` JSON tag so zero
counts remain serialized, and update the empty-list envelope test to assert that
`count` is present with value zero.

In `@shortcuts/mail/mail_json_shorthand_test.go`:
- Around line 96-110: Update TestMailTriageRejectsRemovedDataFormat to assert
the typed validation metadata returned by errs.ProblemOf, matching
TestMailTriageEnumRejectsUnknownFormat: verify the expected Category, Subtype,
and Param values for the rejected --format input, and remove the
message-substring assertion.
🪄 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: 5cc992be-b575-4a3a-8eda-a71be3c71e4c

📥 Commits

Reviewing files that changed from the base of the PR and between cc56cc5 and afd4555.

📒 Files selected for processing (8)
  • internal/output/envelope.go
  • internal/output/envelope_test.go
  • shortcuts/mail/mail_json_shorthand_test.go
  • shortcuts/mail/mail_read_help_test.go
  • shortcuts/mail/mail_triage.go
  • shortcuts/mail/mail_triage_test.go
  • skills/lark-mail/references/lark-mail-triage.md
  • skills/lark-mail/references/lark-mail-watch.md
💤 Files with no reviewable changes (1)
  • shortcuts/mail/mail_read_help_test.go
✅ Files skipped from review due to trivial changes (2)
  • skills/lark-mail/references/lark-mail-watch.md
  • skills/lark-mail/references/lark-mail-triage.md

Comment thread internal/output/envelope.go
Comment thread shortcuts/mail/mail_json_shorthand_test.go
Align TestMailTriageRejectsRemovedDataFormat with the repo *_test.go
guideline (error-path tests assert typed errs.ProblemOf metadata —
category/subtype/param — not message substrings alone), matching the
sibling TestMailTriageEnumRejectsUnknownFormat. Addresses CodeRabbit
review on PR #1830.
The default json watch stream emits one enveloped JSON object per line via
PrintNdjson, but the fetch-message failure branch used PrintJson (multi-line
MarshalIndent) and bypassed the envelope, so a mid-stream failure injected a
multi-line {ok:false,...} blob that breaks line-based NDJSON parsers. Route
failures through watchFailureOutputValue: bare payload for --format data,
identity-tagged single line for the default json envelope.
Meta.Count had json:"count,omitempty", so an empty mail +triage result
dropped .meta.count entirely, contradicting the migration contract
(.count -> .meta.count) and forcing callers to distinguish missing-vs-zero.
Every output.Meta construction already sets Count=len(data), so dropping
omitempty only makes empty list envelopes emit a correct count:0 across all
list commands. Add empty-result and serialization assertions.
Align mail +triage with the repo-wide list convention: pagination lives inside
the data object, not meta. Output is {ok, data:{messages, total, has_more,
page_token}} with meta=nil.

Uses a typed triageOutput struct (like calendar +search-event) rather than a
map: output.toGeneric JSON-round-trips a struct, normalizing the nested
messages into []interface{} so output.ExtractItems can find it for
table/csv/ndjson rendering. (A top-level map is not round-tripped, which would
flatten the wrapper into a single row — caught by the new
TestMailTriageNdjsonEmitsOneMessagePerLine regression test.)

internal/output/envelope.go is restored to main (no Meta.HasMore/PageToken, no
Count omitempty change) — this PR no longer touches the shared envelope struct;
supersedes the CodeRabbit-A/P2 discussion. Docs, skill-eval, E2E updated to
.data.messages / .data.total / .data.has_more / .data.page_token.
…ON line

Two review follow-ups on mail +watch:
- --print-output-schema showed only the bare per-event structure (.message
  paths), but the default --format json wraps each event as
  {ok,identity,data:<structure>}. Callers building parse logic from the schema
  would look for .message and miss it (it is at .data.message under the default).
  Add a _format_note documenting the .data prefix for default json.
- The NDJSON failure test only json.Marshal'd watchFailureOutputValue and never
  went through the real print function, so a revert to multi-line PrintJson
  would not be caught. Add TestWatchFailurePrintsSingleNDJSONLine, which drives
  output.PrintNdjson (the function the failure branch calls) and asserts exactly
  one decodable line for both json and data formats.
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 enhancement New feature or request size/M Single-domain feat or fix with limited business impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant