Skip to content

fix(base): improve dashboard data diagnostics and slim lark-base skill#1601

Open
zhouyue-bytedance wants to merge 1 commit into
larksuite:mainfrom
zhouyue-bytedance:pr-base-dashboard
Open

fix(base): improve dashboard data diagnostics and slim lark-base skill#1601
zhouyue-bytedance wants to merge 1 commit into
larksuite:mainfrom
zhouyue-bytedance:pr-base-dashboard

Conversation

@zhouyue-bytedance

@zhouyue-bytedance zhouyue-bytedance commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

What

  • Diagnose empty dashboard measure values so agents do not report success on empty charts.
  • Clarify dashboard text block readback in record markdown rendering.
  • Accept --json output shorthand on +record-list.
  • Slim the lark-base SKILL entry routing, clarify dashboard parameter traps, and limit overly broad dashboard verification guidance.

Scope

base dashboard ops, record list --json shorthand, record markdown, and the lark-base skill doc. No unrelated files.

Summary by CodeRabbit

  • New Features

    • Added a hidden --json shortcut for record list output, making JSON mode easier to access.
    • Dashboard text and data outputs now include helpful diagnostics when values are returned in an unexpected or empty format.
  • Bug Fixes

    • Improved handling of JSON-encoded dashboard text so plain text is read back correctly.
    • Updated output validation to better distinguish between Markdown and JSON responses, reducing formatting mismatches.

- diagnose empty dashboard measure values so agents don't report success on empty charts
- clarify dashboard text readback in record markdown
- slim lark-base SKILL routing, clarify dashboard parameter traps, limit broad verification
- accept --json output shorthand on record list
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds dashboard block diagnostics for JSON-encoded text and missing computed measure values, introduces a hidden --json alias for base +record-list, and updates related tests and base skill guidance.

Changes

Dashboard diagnostics

Layer / File(s) Summary
Text readback diagnostics
shortcuts/base/dashboard_ops.go, shortcuts/base/base_dashboard_execute_test.go, skills/lark-base/SKILL.md
executeDashboardBlockGet and executeDashboardBlockUpdate now attach dashboard_text_json_readback when data_config.text is JSON-encoded, and the matching tests assert the new readback fields. The skill guide updates the dashboard fast path and related guidance.
Computed measure diagnostics
shortcuts/base/dashboard_ops.go, shortcuts/base/base_dashboard_execute_test.go
executeDashboardBlockGetData now collects measure aliases from measures, scans main_data rows, and emits _diagnostics with empty_measure_values when computed values are missing. The test now covers both presence and absence cases.

Record-list JSON alias

Layer / File(s) Summary
Alias flag and format resolution
shortcuts/base/record_list.go, shortcuts/base/record_markdown.go, shortcuts/base/record_ops.go
BaseRecordList registers hidden --json, validation accepts it as --format json, and list rendering uses the resolved output format.
Alias coverage
shortcuts/base/base_execute_test.go, shortcuts/base/base_shortcuts_test.go, tests/cli_e2e/base/base_record_list_dryrun_test.go
Unit and e2e tests cover hidden flag visibility, JSON output, markdown suppression, and dry-run request URLs.

Sequence Diagram(s)

sequenceDiagram
  participant executeDashboardBlockGetData
  participant attachDashboardBlockDataDiagnostics
  participant extractMeasureAliases
  participant hasComputedMeasureValues
  participant appendDashboardDiagnostic
  executeDashboardBlockGetData->>attachDashboardBlockDataDiagnostics: inspect block data
  attachDashboardBlockDataDiagnostics->>extractMeasureAliases: read measures
  attachDashboardBlockDataDiagnostics->>hasComputedMeasureValues: scan main_data rows
  hasComputedMeasureValues-->>attachDashboardBlockDataDiagnostics: missing computed values
  attachDashboardBlockDataDiagnostics->>appendDashboardDiagnostic: add empty_measure_values
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

  • larksuite/cli#341: Extends the same dashboard text-block test area and type=text handling touched here.
  • larksuite/cli#388: Adds the dashboard text-block plumbing that this PR builds on for readback diagnostics.
  • larksuite/cli#726: Modifies the same record output-format behavior around JSON vs markdown and --json/--format semantics.

Suggested labels

size/L

Suggested reviewers

  • kongenpei

Poem

I hopped through dashboards, quick and bright,
Found JSON carrots in the light.
With --json I nibble, neat and free,
And diagnostics bloom for me. 🐇
No markdown crumbs, just tidy lore,
A happier burrow than before.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers scope, but it does not follow the required template sections for Summary, Changes, Test Plan, and Related Issues. Add the required headings with a brief summary, a bullet list of changes, a test plan, and a Related Issues entry.
Docstring Coverage ⚠️ Warning Docstring coverage is 29.63% 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 matches the main changeset, covering dashboard diagnostics and the lark-base skill cleanup.
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.
✨ 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.

@github-actions github-actions Bot added domain/base PR touches the base domain size/M Single-domain feat or fix with limited business impact labels Jun 26, 2026
@github-actions

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 Skill update

npx skills add zhouyue-bytedance/cli#pr-base-dashboard -y -g

@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

🧹 Nitpick comments (1)
shortcuts/base/record_markdown.go (1)

40-43: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider documenting the --json semantic split across base record commands. Within the base family, --json means "output as JSON" for +record-list but means "JSON request body" for +record-search/+record-get. This is a deliberate divergence, but it can confuse users/agents reusing flags across subcommands. A short inline comment near this helper (or in the flag description) noting the distinction would help future maintainers.

🤖 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/base/record_markdown.go` around lines 40 - 43, Add a brief inline
comment near recordReadJSONOutputAlias in shortcuts/base/record_markdown.go
clarifying that --json has different meanings across base record commands: it
means output-as-JSON for record-list, but request-body JSON for record-search
and record-get. Keep the note close to the helper or the related flag definition
so future maintainers can find the semantic split quickly.
🤖 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/base/dashboard_ops.go`:
- Around line 282-304: The empty-measure diagnostic in dashboard block data
handling is skipped when main_data has zero rows, so the zero-result chart case
is treated as success. Update dashboardBlockRowHasMeasureValue-related logic in
dashboard_ops.go to emit the same empty_measure_values diagnostic whenever
measures are declared and main_data is empty, not just when rows exist but lack
computed values, and add a regression test in
TestBaseDashboardBlockExecuteGetData covering the zero-row case.

---

Nitpick comments:
In `@shortcuts/base/record_markdown.go`:
- Around line 40-43: Add a brief inline comment near recordReadJSONOutputAlias
in shortcuts/base/record_markdown.go clarifying that --json has different
meanings across base record commands: it means output-as-JSON for record-list,
but request-body JSON for record-search and record-get. Keep the note close to
the helper or the related flag definition so future maintainers can find the
semantic split quickly.
🪄 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: d6e80fe2-98bc-4f00-903e-14bfce33835f

📥 Commits

Reviewing files that changed from the base of the PR and between 6b83325 and 3a9e0aa.

📒 Files selected for processing (9)
  • shortcuts/base/base_dashboard_execute_test.go
  • shortcuts/base/base_execute_test.go
  • shortcuts/base/base_shortcuts_test.go
  • shortcuts/base/dashboard_ops.go
  • shortcuts/base/record_list.go
  • shortcuts/base/record_markdown.go
  • shortcuts/base/record_ops.go
  • skills/lark-base/SKILL.md
  • tests/cli_e2e/base/base_record_list_dryrun_test.go

Comment on lines +282 to +304
rows, ok := data["main_data"].([]interface{})
if !ok || len(rows) == 0 {
return
}
for _, rawRow := range rows {
row, ok := rawRow.(map[string]interface{})
if !ok {
continue
}
if dashboardBlockRowHasMeasureValue(row, measureAliases) {
return
}
}
data["_diagnostics"] = []interface{}{
map[string]interface{}{
"type": "empty_measure_values",
"message": "chart data defines measures, but main_data rows contain no computed measure values",
"hint": "Recreate or update the block data_config with a computable numeric measure or count_all, then rerun +dashboard-block-get-data before declaring the chart complete.",
"measure_aliases": measureAliases,
"main_data_rows": len(rows),
},
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Emit empty_measure_values for zero-row results too.

Line 283 returns before adding diagnostics when main_data is empty, so a block with declared measures but zero result rows still looks like a clean success. That misses the exact “empty chart” case this change is trying to surface. Please emit the same diagnostic when measures exist and main_data is [], and add the matching regression case in TestBaseDashboardBlockExecuteGetData.

Proposed fix
 func attachDashboardBlockDataDiagnostics(data map[string]interface{}) {
 	measureAliases := dashboardBlockMeasureAliases(data["measures"])
 	if len(measureAliases) == 0 {
 		return
 	}
 	rows, ok := data["main_data"].([]interface{})
-	if !ok || len(rows) == 0 {
+	if !ok {
 		return
 	}
+	if len(rows) == 0 {
+		appendDashboardDiagnostic(data, map[string]interface{}{
+			"type":            "empty_measure_values",
+			"message":         "chart data defines measures, but main_data rows contain no computed measure values",
+			"hint":            "Recreate or update the block data_config with a computable numeric measure or count_all, then rerun +dashboard-block-get-data before declaring the chart complete.",
+			"measure_aliases": measureAliases,
+			"main_data_rows":  0,
+		})
+		return
+	}
 	for _, rawRow := range rows {
 		row, ok := rawRow.(map[string]interface{})
 		if !ok {
 			continue
 		}
 		if dashboardBlockRowHasMeasureValue(row, measureAliases) {
 			return
 		}
 	}
-	data["_diagnostics"] = []interface{}{
-		map[string]interface{}{
-			"type":            "empty_measure_values",
-			"message":         "chart data defines measures, but main_data rows contain no computed measure values",
-			"hint":            "Recreate or update the block data_config with a computable numeric measure or count_all, then rerun +dashboard-block-get-data before declaring the chart complete.",
-			"measure_aliases": measureAliases,
-			"main_data_rows":  len(rows),
-		},
-	}
+	appendDashboardDiagnostic(data, map[string]interface{}{
+		"type":            "empty_measure_values",
+		"message":         "chart data defines measures, but main_data rows contain no computed measure values",
+		"hint":            "Recreate or update the block data_config with a computable numeric measure or count_all, then rerun +dashboard-block-get-data before declaring the chart complete.",
+		"measure_aliases": measureAliases,
+		"main_data_rows":  len(rows),
+	})
 }
📝 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
rows, ok := data["main_data"].([]interface{})
if !ok || len(rows) == 0 {
return
}
for _, rawRow := range rows {
row, ok := rawRow.(map[string]interface{})
if !ok {
continue
}
if dashboardBlockRowHasMeasureValue(row, measureAliases) {
return
}
}
data["_diagnostics"] = []interface{}{
map[string]interface{}{
"type": "empty_measure_values",
"message": "chart data defines measures, but main_data rows contain no computed measure values",
"hint": "Recreate or update the block data_config with a computable numeric measure or count_all, then rerun +dashboard-block-get-data before declaring the chart complete.",
"measure_aliases": measureAliases,
"main_data_rows": len(rows),
},
}
}
rows, ok := data["main_data"].([]interface{})
if !ok {
return
}
if len(rows) == 0 {
appendDashboardDiagnostic(data, map[string]interface{}{
"type": "empty_measure_values",
"message": "chart data defines measures, but main_data rows contain no computed measure values",
"hint": "Recreate or update the block data_config with a computable numeric measure or count_all, then rerun +dashboard-block-get-data before declaring the chart complete.",
"measure_aliases": measureAliases,
"main_data_rows": 0,
})
return
}
for _, rawRow := range rows {
row, ok := rawRow.(map[string]interface{})
if !ok {
continue
}
if dashboardBlockRowHasMeasureValue(row, measureAliases) {
return
}
}
appendDashboardDiagnostic(data, map[string]interface{}{
"type": "empty_measure_values",
"message": "chart data defines measures, but main_data rows contain no computed measure values",
"hint": "Recreate or update the block data_config with a computable numeric measure or count_all, then rerun +dashboard-block-get-data before declaring the chart complete.",
"measure_aliases": measureAliases,
"main_data_rows": len(rows),
})
}
🤖 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/base/dashboard_ops.go` around lines 282 - 304, The empty-measure
diagnostic in dashboard block data handling is skipped when main_data has zero
rows, so the zero-result chart case is treated as success. Update
dashboardBlockRowHasMeasureValue-related logic in dashboard_ops.go to emit the
same empty_measure_values diagnostic whenever measures are declared and
main_data is empty, not just when rows exist but lack computed values, and add a
regression test in TestBaseDashboardBlockExecuteGetData covering the zero-row
case.

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

Labels

domain/base PR touches the base domain 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