Skip to content

feat(doc,markdown,sheets,slides,wiki): emit typed error envelopes across ccm domains#1246

Closed
evandance wants to merge 1 commit into
mainfrom
feat/errs-migrate-ccm
Closed

feat(doc,markdown,sheets,slides,wiki): emit typed error envelopes across ccm domains#1246
evandance wants to merge 1 commit into
mainfrom
feat/errs-migrate-ccm

Conversation

@evandance

@evandance evandance commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Migrates typed error envelopes across the CCM shortcut domains: doc, markdown, sheets, slides, and wiki. Scope is limited to those domains, error-contract guards, and cleanup of a legacy common helper made unreachable by the migration.

Changes

  • Converts terminal validation, API, network, file, and save-path failures in the CCM shortcut domains to typed errs.* envelopes.
  • Uses domain-local typed helpers and current typed common helpers; Sheets keeps structured param metadata and typed raw export download classification.
  • Extends .golangci.yml and lint/errscontract coverage for doc, markdown, sheets, slides, and wiki.
  • Removes the unreachable legacy common.WrapSaveErrorByCategory helper.

Test Plan

  • Focused unit and errscontract tests pass.
  • Formatting, vet, lint, build, deadcode, and dry-run E2E gates pass.
  • GitHub CI passes on 78e9d4c5.

Related Issues

  • None

@coderabbitai

coderabbitai Bot commented Jun 3, 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

Typed errs replace legacy output errors across docs, sheets, slides, and wiki shortcuts. Validation is standardized, API calls switch to CallAPITyped, new wrappers normalize network/save errors, and tests assert typed problems. Lint rules expand migrated paths.

Changes

Typed errs migration across shortcuts

Layer / File(s) Summary
Lint and contracts
.golangci.yml, lint/errscontract/*
Expands forbidigo path-except and treats more shortcut paths as migrated to typed errs.
Docs migration
shortcuts/doc/*
Moves validations to errs, adds wrapDocNetworkErr, switches to CallAPITyped, and updates media flows and helpers.
Sheets migration
shortcuts/sheets/**/*
Standardizes validations via errs/common.ValidationErrorf, introduces network/save wrappers, and switches all calls to CallAPITyped.
Slides migration
shortcuts/slides/*
Adds typed helpers, converts validations to errs, uses CallAPITyped, and updates tests to typed problems.
Wiki migration
shortcuts/wiki/*
Rewrites async polling and operations to errs, uses CallAPITyped, updates validation and hint enrichment, and adjusts tests.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~110 minutes

Possibly related PRs

  • larksuite/cli#1242 — Introduces typed common error helpers and errscontract enforcement that this migration relies on.
  • larksuite/cli#1076 — Implements wiki node creation retry/backoff logic touched here with typed errors and hints.
  • larksuite/cli#984 — Tunes errs/forbidigo lint rules aligned with this PR’s expanded path-except coverage.

Suggested reviewers

  • liangshuo-1
  • fangshuyu-768
  • caojie0621

Poem

In fields of flags I hop with glee,
Wrapping errs in typed decree.
From docs to sheets, the hints now sing,
Slides and wiki—typed in spring.
CallAPITyped—thump, thump, thump—
Bugs beware my gentle jump. 🐇✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/errs-migrate-ccm

@github-actions github-actions Bot added domain/ccm PR touches the ccm domain size/XL Architecture-level or global-impact change labels Jun 3, 2026
@evandance evandance force-pushed the feat/errs-migrate-ccm branch from b575abd to ba0b2dc Compare June 3, 2026 09:06
@evandance evandance changed the title feat: migrate CCM shortcut errors feat(doc,sheets,slides,wiki): emit typed error envelopes across ccm domains Jun 3, 2026
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@78e9d4c5970ef0265b04940d2d23998ed97890f6

🧩 Skill update

npx skills add larksuite/cli#feat/errs-migrate-ccm -y -g

@codecov

codecov Bot commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 65.18987% with 275 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.59%. Comparing base (03ea6e7) to head (78e9d4c).

Files with missing lines Patch % Lines
shortcuts/sheets/lark_sheet_write_cells.go 36.58% 26 Missing ⚠️
shortcuts/sheets/lark_sheet_workbook.go 64.70% 22 Missing and 2 partials ⚠️
shortcuts/doc/docs_update_v2.go 0.00% 16 Missing ⚠️
...ts/sheets/backward/lark_sheets_sheet_management.go 55.55% 13 Missing and 3 partials ⚠️
shortcuts/doc/doc_media_insert.go 59.45% 15 Missing ⚠️
...ets/backward/lark_sheets_spreadsheet_management.go 45.83% 12 Missing and 1 partial ⚠️
shortcuts/sheets/helpers.go 72.91% 12 Missing and 1 partial ⚠️
shortcuts/slides/slides_errors.go 37.50% 5 Missing and 5 partials ⚠️
shortcuts/wiki/wiki_node_create.go 60.00% 8 Missing and 2 partials ⚠️
shortcuts/doc/docs_fetch_v2.go 0.00% 9 Missing ⚠️
... and 35 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1246      +/-   ##
==========================================
+ Coverage   71.58%   71.59%   +0.01%     
==========================================
  Files         689      693       +4     
  Lines       65521    65561      +40     
==========================================
+ Hits        46901    46938      +37     
+ Misses      14972    14970       -2     
- Partials     3648     3653       +5     

☔ 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.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
shortcuts/wiki/wiki_async_task.go (1)

103-119: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Treat a missing async-task result block as an invalid response.

If /wiki/v2/tasks/{task_id} omits delete_space_result / simple_task_result, this parser leaves Status empty, StatusCode() falls back to "processing", and the poller eventually reports a timeout instead of surfacing the backend contract break. Failing fast here would avoid a misleading “still running” result for malformed task payloads.

Suggested fix
 func parseWikiAsyncTaskStatus(taskID string, task map[string]interface{}, resultKey string) (wikiAsyncTaskStatus, error) {
 	if task == nil {
 		return wikiAsyncTaskStatus{}, errs.NewInternalError(errs.SubtypeInvalidResponse, "wiki task response missing task")
 	}
 
 	result := common.GetMap(task, resultKey)
+	if result == nil {
+		return wikiAsyncTaskStatus{}, errs.NewInternalError(
+			errs.SubtypeInvalidResponse,
+			"wiki task response missing %s",
+			resultKey,
+		)
+	}
 	status := wikiAsyncTaskStatus{
 		TaskID: common.GetString(task, "task_id"),
 	}
 	if status.TaskID == "" {
 		status.TaskID = taskID
 	}
-	if result != nil {
-		status.Status = common.GetString(result, "status")
-		status.StatusMsg = common.GetString(result, "status_msg")
+	status.Status = common.GetString(result, "status")
+	if strings.TrimSpace(status.Status) == "" {
+		return wikiAsyncTaskStatus{}, errs.NewInternalError(errs.SubtypeInvalidResponse, "wiki task response missing status")
 	}
+	status.StatusMsg = common.GetString(result, "status_msg")
 	return status, 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/wiki/wiki_async_task.go` around lines 103 - 119, The parser
parseWikiAsyncTaskStatus currently treats a missing result block as OK and
leaves Status empty; change it to treat a nil result (common.GetMap(task,
resultKey) == nil) as an invalid response: when result is nil return an
errs.NewInternalError(errs.SubtypeInvalidResponse, "<context> wiki task response
missing "+resultKey) instead of continuing, so the caller fails fast on
malformed payloads; reference the parseWikiAsyncTaskStatus function and the
resultKey parameter to locate and implement this check.
shortcuts/wiki/wiki_move.go (1)

624-658: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reject move-task payloads that contain no parseable move_result.

Right now a task payload with no move_result entries returns an empty wikiMoveTaskStatus, which the poll loop interprets as “still processing” and eventually times out. That hides an invalid /wiki/v2/tasks/{id} response behind a misleading timeout instead of surfacing it as SubtypeInvalidResponse.

Suggested fix
 func parseWikiMoveTaskStatus(taskID string, task map[string]interface{}) (wikiMoveTaskStatus, error) {
 	if task == nil {
 		return wikiMoveTaskStatus{}, errs.NewInternalError(errs.SubtypeInvalidResponse, "wiki task response missing task")
 	}
 
 	status := wikiMoveTaskStatus{
 		TaskID: common.GetString(task, "task_id"),
 	}
 	if status.TaskID == "" {
 		status.TaskID = taskID
 	}
 
+	parsed := 0
 	for _, item := range common.GetSlice(task, "move_result") {
 		resultMap, ok := item.(map[string]interface{})
 		if !ok {
 			continue
 		}
@@
 		status.MoveResults = append(status.MoveResults, wikiMoveTaskResult{
 			Node:      node,
 			Status:    int(common.GetFloat(resultMap, "status")),
 			StatusMsg: common.GetString(resultMap, "status_msg"),
 		})
+		parsed++
+	}
+
+	if parsed == 0 {
+		return wikiMoveTaskStatus{}, errs.NewInternalError(errs.SubtypeInvalidResponse, "wiki move task response missing move_result")
 	}
 
 	return status, 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/wiki/wiki_move.go` around lines 624 - 658, The
parseWikiMoveTaskStatus function must treat payloads with no parseable
move_result as invalid: after iterating and building status.MoveResults, if
len(status.MoveResults) == 0 then return an error (errs.NewInternalError with
errs.SubtypeInvalidResponse and a clear message) instead of returning an empty
wikiMoveTaskStatus; this change ensures parseWikiMoveTaskStatus (and callers
that check wikiMoveTaskStatus) surface invalid /wiki/v2/tasks/{id} responses
that lack move_result entries.
shortcuts/wiki/wiki_node_get.go (1)

204-230: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reject --obj-type for /wiki/<token> URLs too.

A /wiki/... URL resolves to a wiki node_token, but this branch only checks mismatches when the path implies a non-empty obj_type. That means wiki +node-get --node-token https://feishu.cn/wiki/wik... --obj-type docx now passes validation and sends an invalid obj_type to get_node, instead of failing fast like the raw-node-token path does.

Suggested fix
 		switch {
+		case spec.ObjType != "" && urlObjType == "":
+			return wikiNodeGetSpec{}, errs.NewValidationError(
+				errs.SubtypeInvalidArgument,
+				"--obj-type is only valid for obj_tokens; %q resolves to a node_token",
+				spec.Token,
+			).WithParam("--obj-type")
 		case spec.ObjType == "" && urlObjType != "":
 			spec.ObjType = urlObjType
 		case spec.ObjType != "" && urlObjType != "" && spec.ObjType != urlObjType:
 			return wikiNodeGetSpec{}, errs.NewValidationError(errs.SubtypeInvalidArgument,
 				"--obj-type %q does not match the obj_type %q implied by the URL path; pass only one",
🤖 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/wiki/wiki_node_get.go` around lines 204 - 230, When parsing a
tokenInput URL in the wiki node get flow, the code currently only errors when
the URL implies a non-empty urlObjType that conflicts with spec.ObjType; you
must also reject an explicitly provided --obj-type when the URL path is a plain
/wiki/ (i.e., urlObjType == ""), to mirror the raw-node-token behavior. In the
URL-handling block (where token, urlObjType, ok :=
tokenAndObjTypeFromWikiURL(u.Path) is used and spec.SourceKind is set to
"url-wiki" or "url-obj"), add a validation: if urlObjType == "" && spec.ObjType
!= "" return an errs.NewValidationError indicating that --obj-type is not
allowed for /wiki/ URLs and attach WithParam("--obj-type"); keep the existing
mismatch check for the case urlObjType != "".
🧹 Nitpick comments (1)
.golangci.yml (1)

79-80: ⚡ Quick win

Update the comment to reflect the expanded scope.

The comment states "errs-no-legacy-helper is drive-only" but line 81 now enforces the rule on five domains: drive, doc, sheets, slides, and wiki.

📝 Suggested comment update
-      # errs-no-legacy-helper is drive-only: the shared helpers it bans are
-      # still used by other domains until their later migration phase.
+      # errs-no-legacy-helper enforced on fully-migrated shortcut domains
+      # (drive, doc, sheets, slides, wiki): the shared helpers it bans emit
+      # legacy output.Err* shapes and are replaced by domain-local typed helpers.
🤖 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 @.golangci.yml around lines 79 - 80, Update the inline comment that currently
says "errs-no-legacy-helper is drive-only" to reflect that errs-no-legacy-helper
now applies to five domains (drive, doc, sheets, slides, and wiki); locate the
comment near the errs-no-legacy-helper rule in .golangci.yml and change the
wording to indicate the expanded scope (e.g., list the domains or say "applies
to drive, doc, sheets, slides, and wiki").
🤖 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.

Outside diff comments:
In `@shortcuts/wiki/wiki_async_task.go`:
- Around line 103-119: The parser parseWikiAsyncTaskStatus currently treats a
missing result block as OK and leaves Status empty; change it to treat a nil
result (common.GetMap(task, resultKey) == nil) as an invalid response: when
result is nil return an errs.NewInternalError(errs.SubtypeInvalidResponse,
"<context> wiki task response missing "+resultKey) instead of continuing, so the
caller fails fast on malformed payloads; reference the parseWikiAsyncTaskStatus
function and the resultKey parameter to locate and implement this check.

In `@shortcuts/wiki/wiki_move.go`:
- Around line 624-658: The parseWikiMoveTaskStatus function must treat payloads
with no parseable move_result as invalid: after iterating and building
status.MoveResults, if len(status.MoveResults) == 0 then return an error
(errs.NewInternalError with errs.SubtypeInvalidResponse and a clear message)
instead of returning an empty wikiMoveTaskStatus; this change ensures
parseWikiMoveTaskStatus (and callers that check wikiMoveTaskStatus) surface
invalid /wiki/v2/tasks/{id} responses that lack move_result entries.

In `@shortcuts/wiki/wiki_node_get.go`:
- Around line 204-230: When parsing a tokenInput URL in the wiki node get flow,
the code currently only errors when the URL implies a non-empty urlObjType that
conflicts with spec.ObjType; you must also reject an explicitly provided
--obj-type when the URL path is a plain /wiki/ (i.e., urlObjType == ""), to
mirror the raw-node-token behavior. In the URL-handling block (where token,
urlObjType, ok := tokenAndObjTypeFromWikiURL(u.Path) is used and spec.SourceKind
is set to "url-wiki" or "url-obj"), add a validation: if urlObjType == "" &&
spec.ObjType != "" return an errs.NewValidationError indicating that --obj-type
is not allowed for /wiki/ URLs and attach WithParam("--obj-type"); keep the
existing mismatch check for the case urlObjType != "".

---

Nitpick comments:
In @.golangci.yml:
- Around line 79-80: Update the inline comment that currently says
"errs-no-legacy-helper is drive-only" to reflect that errs-no-legacy-helper now
applies to five domains (drive, doc, sheets, slides, and wiki); locate the
comment near the errs-no-legacy-helper rule in .golangci.yml and change the
wording to indicate the expanded scope (e.g., list the domains or say "applies
to drive, doc, sheets, slides, and wiki").

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ab5990db-5311-473f-aef1-f039aa4048ce

📥 Commits

Reviewing files that changed from the base of the PR and between 33de28f and ba0b2dc.

📒 Files selected for processing (54)
  • .golangci.yml
  • lint/errscontract/rule_no_legacy_envelope_literal.go
  • shortcuts/doc/clipboard.go
  • shortcuts/doc/doc_errors.go
  • shortcuts/doc/doc_media_download.go
  • shortcuts/doc/doc_media_insert.go
  • shortcuts/doc/doc_media_preview.go
  • shortcuts/doc/doc_media_upload.go
  • shortcuts/doc/docs_create.go
  • shortcuts/doc/docs_create_v2.go
  • shortcuts/doc/docs_fetch_v2.go
  • shortcuts/doc/docs_search.go
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/docs_update_v2.go
  • shortcuts/doc/helpers.go
  • shortcuts/sheets/helpers.go
  • shortcuts/sheets/lark_sheets_cell_data.go
  • shortcuts/sheets/lark_sheets_cell_images.go
  • shortcuts/sheets/lark_sheets_cell_style_and_merge.go
  • shortcuts/sheets/lark_sheets_dropdown.go
  • shortcuts/sheets/lark_sheets_filter_views.go
  • shortcuts/sheets/lark_sheets_float_images.go
  • shortcuts/sheets/lark_sheets_row_column_management.go
  • shortcuts/sheets/lark_sheets_sheet_manage_test.go
  • shortcuts/sheets/lark_sheets_sheet_management.go
  • shortcuts/sheets/lark_sheets_spreadsheet_management.go
  • shortcuts/sheets/sheets_errors.go
  • shortcuts/slides/helpers.go
  • shortcuts/slides/slides_create.go
  • shortcuts/slides/slides_create_test.go
  • shortcuts/slides/slides_errors.go
  • shortcuts/slides/slides_media_upload.go
  • shortcuts/slides/slides_replace_slide.go
  • shortcuts/slides/slides_replace_slide_test.go
  • shortcuts/wiki/wiki_async_task.go
  • shortcuts/wiki/wiki_async_task_test.go
  • shortcuts/wiki/wiki_delete.go
  • shortcuts/wiki/wiki_delete_test.go
  • shortcuts/wiki/wiki_member_add.go
  • shortcuts/wiki/wiki_member_helpers.go
  • shortcuts/wiki/wiki_member_list.go
  • shortcuts/wiki/wiki_member_remove.go
  • shortcuts/wiki/wiki_member_test.go
  • shortcuts/wiki/wiki_move.go
  • shortcuts/wiki/wiki_move_test.go
  • shortcuts/wiki/wiki_node_copy.go
  • shortcuts/wiki/wiki_node_create.go
  • shortcuts/wiki/wiki_node_create_test.go
  • shortcuts/wiki/wiki_node_delete.go
  • shortcuts/wiki/wiki_node_delete_test.go
  • shortcuts/wiki/wiki_node_get.go
  • shortcuts/wiki/wiki_node_list.go
  • shortcuts/wiki/wiki_space_create.go
  • shortcuts/wiki/wiki_space_list.go
💤 Files with no reviewable changes (1)
  • shortcuts/wiki/wiki_member_test.go

@evandance evandance force-pushed the feat/errs-migrate-ccm branch from ba0b2dc to 029fbd4 Compare June 3, 2026 11:10

@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/sheets/lark_sheets_float_images.go`:
- Line 118: The stat error is being mislabeled as "file not found"
unconditionally; update the code that returns sheetsInputStatError(err, "file
not found") to inspect the error (using os.IsNotExist(err)) and only use "file
not found" when IsNotExist is true, otherwise pass a message that includes the
actual error (e.g., err.Error() or fmt.Sprintf("stat error: %v", err)); locate
the call that returns sheetsInputStatError and adjust it to choose the message
based on os.IsNotExist(err) so permission/I/O errors are reported accurately.
🪄 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: bf66eadd-90fa-4244-90a8-57e396adad3c

📥 Commits

Reviewing files that changed from the base of the PR and between ba0b2dc and 029fbd4.

📒 Files selected for processing (53)
  • .golangci.yml
  • lint/errscontract/rule_no_legacy_envelope_literal.go
  • shortcuts/doc/clipboard.go
  • shortcuts/doc/doc_errors.go
  • shortcuts/doc/doc_media_download.go
  • shortcuts/doc/doc_media_insert.go
  • shortcuts/doc/doc_media_preview.go
  • shortcuts/doc/doc_media_upload.go
  • shortcuts/doc/docs_create.go
  • shortcuts/doc/docs_create_v2.go
  • shortcuts/doc/docs_fetch_v2.go
  • shortcuts/doc/docs_search.go
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/docs_update_v2.go
  • shortcuts/doc/helpers.go
  • shortcuts/sheets/helpers.go
  • shortcuts/sheets/lark_sheets_cell_data.go
  • shortcuts/sheets/lark_sheets_cell_images.go
  • shortcuts/sheets/lark_sheets_cell_style_and_merge.go
  • shortcuts/sheets/lark_sheets_dropdown.go
  • shortcuts/sheets/lark_sheets_filter_views.go
  • shortcuts/sheets/lark_sheets_float_images.go
  • shortcuts/sheets/lark_sheets_row_column_management.go
  • shortcuts/sheets/lark_sheets_sheet_manage_test.go
  • shortcuts/sheets/lark_sheets_sheet_management.go
  • shortcuts/sheets/lark_sheets_spreadsheet_management.go
  • shortcuts/sheets/sheets_errors.go
  • shortcuts/slides/helpers.go
  • shortcuts/slides/slides_create.go
  • shortcuts/slides/slides_create_test.go
  • shortcuts/slides/slides_errors.go
  • shortcuts/slides/slides_media_upload.go
  • shortcuts/slides/slides_replace_slide.go
  • shortcuts/slides/slides_replace_slide_test.go
  • shortcuts/wiki/wiki_async_task.go
  • shortcuts/wiki/wiki_async_task_test.go
  • shortcuts/wiki/wiki_delete.go
  • shortcuts/wiki/wiki_delete_test.go
  • shortcuts/wiki/wiki_member_add.go
  • shortcuts/wiki/wiki_member_helpers.go
  • shortcuts/wiki/wiki_member_list.go
  • shortcuts/wiki/wiki_member_remove.go
  • shortcuts/wiki/wiki_move.go
  • shortcuts/wiki/wiki_move_test.go
  • shortcuts/wiki/wiki_node_copy.go
  • shortcuts/wiki/wiki_node_create.go
  • shortcuts/wiki/wiki_node_create_test.go
  • shortcuts/wiki/wiki_node_delete.go
  • shortcuts/wiki/wiki_node_delete_test.go
  • shortcuts/wiki/wiki_node_get.go
  • shortcuts/wiki/wiki_node_list.go
  • shortcuts/wiki/wiki_space_create.go
  • shortcuts/wiki/wiki_space_list.go

Comment thread shortcuts/sheets/lark_sheets_float_images.go Outdated
@evandance evandance force-pushed the feat/errs-migrate-ccm branch from 029fbd4 to ba49fbc Compare June 3, 2026 11:43
@github-actions github-actions Bot added size/L Large or sensitive change across domains or core paths and removed size/XL Architecture-level or global-impact change labels Jun 3, 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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
shortcuts/doc/clipboard.go (1)

324-338: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Preserve Linux tool stderr in the typed failure message.

exec.Command(...).Output() drops stderr here, so xclip/wl-paste/xsel failures collapse to exit status 1. That loses the actionable reason (DISPLAY unset, Wayland/X11 mismatch, missing clipboard owner, etc.) right where the typed envelope is supposed to help the caller recover.

💡 Suggested change
 	for _, t := range tools {
 		if _, lookErr := exec.LookPath(t.name); lookErr != nil {
 			continue
 		}
 		foundTool = true
-		out, err := exec.Command(t.name, t.args...).Output()
+		cmd := exec.Command(t.name, t.args...)
+		var stderr bytes.Buffer
+		cmd.Stderr = &stderr
+		out, err := cmd.Output()
 		if err != nil {
-			lastErr = errs.NewValidationError(errs.SubtypeFailedPrecondition, "clipboard image read failed via %s: %s", t.name, err).WithCause(err)
+			msg := strings.TrimSpace(stderr.String())
+			if msg == "" {
+				msg = err.Error()
+			}
+			lastErr = errs.NewValidationError(errs.SubtypeFailedPrecondition, "clipboard image read failed via %s: %s", t.name, msg).WithCause(err)
 			continue
 		}
🤖 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/doc/clipboard.go` around lines 324 - 338, The code currently uses
exec.Command(t.name, t.args...).Output(), which discards stderr and causes
opaque "exit status 1" errors; change to capture stderr (e.g., use
CombinedOutput or otherwise capture both stdout and stderr) when running the
tool referenced by t.name/t.args, then include the stderr text (or combined
output) in the typed failure messages assigned to lastErr (the
errs.NewValidationError calls around clipboard image read, empty output, and PNG
validation) so the validation error contains the tool name and the
stderr/combined output for actionable diagnostics while preserving existing
checks like hasPNGMagic and the foundTool flag.
🤖 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/wiki/wiki_move.go`:
- Around line 593-595: The failure branch currently returns before the async
task_id is made available to the caller; update the status.Failed() handling so
the async task id is preserved and returned to the caller (i.e., keep the
"async" flag true and include the task id in the error/response) instead of
immediately returning status, false, err. Concretely, in the status.Failed()
block in runWikiDocsToWikiMove / wiki_move.go, ensure you let
runWikiDocsToWikiMove write "out" (or extract the task id from the status
object) and return status, true, errs.NewAPIError(... ) that includes the
task_id (or otherwise preserve the task_id field) so follow-up commands can
inspect/retry the non-idempotent move.

---

Outside diff comments:
In `@shortcuts/doc/clipboard.go`:
- Around line 324-338: The code currently uses exec.Command(t.name,
t.args...).Output(), which discards stderr and causes opaque "exit status 1"
errors; change to capture stderr (e.g., use CombinedOutput or otherwise capture
both stdout and stderr) when running the tool referenced by t.name/t.args, then
include the stderr text (or combined output) in the typed failure messages
assigned to lastErr (the errs.NewValidationError calls around clipboard image
read, empty output, and PNG validation) so the validation error contains the
tool name and the stderr/combined output for actionable diagnostics while
preserving existing checks like hasPNGMagic and the foundTool flag.
🪄 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: cbe58f5b-d47d-4c4e-88fa-e1994a10b703

📥 Commits

Reviewing files that changed from the base of the PR and between 029fbd4 and ba49fbc.

📒 Files selected for processing (53)
  • .golangci.yml
  • lint/errscontract/rule_no_legacy_envelope_literal.go
  • shortcuts/doc/clipboard.go
  • shortcuts/doc/doc_errors.go
  • shortcuts/doc/doc_media_download.go
  • shortcuts/doc/doc_media_insert.go
  • shortcuts/doc/doc_media_preview.go
  • shortcuts/doc/doc_media_upload.go
  • shortcuts/doc/docs_create.go
  • shortcuts/doc/docs_create_v2.go
  • shortcuts/doc/docs_fetch_v2.go
  • shortcuts/doc/docs_search.go
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/docs_update_v2.go
  • shortcuts/doc/helpers.go
  • shortcuts/sheets/helpers.go
  • shortcuts/sheets/lark_sheets_cell_data.go
  • shortcuts/sheets/lark_sheets_cell_images.go
  • shortcuts/sheets/lark_sheets_cell_style_and_merge.go
  • shortcuts/sheets/lark_sheets_dropdown.go
  • shortcuts/sheets/lark_sheets_filter_views.go
  • shortcuts/sheets/lark_sheets_float_images.go
  • shortcuts/sheets/lark_sheets_row_column_management.go
  • shortcuts/sheets/lark_sheets_sheet_manage_test.go
  • shortcuts/sheets/lark_sheets_sheet_management.go
  • shortcuts/sheets/lark_sheets_spreadsheet_management.go
  • shortcuts/sheets/sheets_errors.go
  • shortcuts/slides/helpers.go
  • shortcuts/slides/slides_create.go
  • shortcuts/slides/slides_create_test.go
  • shortcuts/slides/slides_errors.go
  • shortcuts/slides/slides_media_upload.go
  • shortcuts/slides/slides_replace_slide.go
  • shortcuts/slides/slides_replace_slide_test.go
  • shortcuts/wiki/wiki_async_task.go
  • shortcuts/wiki/wiki_async_task_test.go
  • shortcuts/wiki/wiki_delete.go
  • shortcuts/wiki/wiki_delete_test.go
  • shortcuts/wiki/wiki_member_add.go
  • shortcuts/wiki/wiki_member_helpers.go
  • shortcuts/wiki/wiki_member_list.go
  • shortcuts/wiki/wiki_member_remove.go
  • shortcuts/wiki/wiki_move.go
  • shortcuts/wiki/wiki_move_test.go
  • shortcuts/wiki/wiki_node_copy.go
  • shortcuts/wiki/wiki_node_create.go
  • shortcuts/wiki/wiki_node_create_test.go
  • shortcuts/wiki/wiki_node_delete.go
  • shortcuts/wiki/wiki_node_delete_test.go
  • shortcuts/wiki/wiki_node_get.go
  • shortcuts/wiki/wiki_node_list.go
  • shortcuts/wiki/wiki_space_create.go
  • shortcuts/wiki/wiki_space_list.go

Comment thread shortcuts/wiki/wiki_move.go
@evandance evandance force-pushed the feat/errs-migrate-ccm branch 2 times, most recently from e1fd240 to 7778c6d Compare June 3, 2026 13:01
@github-actions github-actions Bot added size/XL Architecture-level or global-impact change and removed size/L Large or sensitive change across domains or core paths labels Jun 3, 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: 3

🤖 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/sheets/backward/lark_sheets_spreadsheet_management.go`:
- Around line 241-244: The output-path safety check currently runs only in
Execute (the runtime.ResolveSavePath call that returns errs.NewValidationError),
causing --dry-run previews to skip this validation; move or duplicate that
validation into the command's Validate phase so the same unsafe path is rejected
during Validate (and thus for dry-run). Concretely, add the
runtime.ResolveSavePath check (and return the same errs.NewValidationError with
WithCause) inside the Validate method or shared input-builder used by Validate,
and remove or keep (idempotently) the Execute check so both phases enforce
identical path validation for the flag handling code that reads outputPath.

In `@shortcuts/sheets/lark_sheet_sheet_structure.go`:
- Around line 162-194: Replace usage of common.ValidationErrorf in
dimInsertInput (and likewise in dimFreezeInput, dimRangeOpInput,
buildDimMovePlan) with the typed-error pattern used elsewhere: return
errs.NewValidationError(errs.SubtypeInvalidArgument,
"<message>").WithParam("<flag>") for missing/invalid flag cases and include
parameter names like "--position", "--count", or the specific flag being
validated; where you currently check runtime.Changed("position") or
runtime.Changed("count") or validate parseA1Position/count, construct and return
the corresponding errs.NewValidationError(...).WithParam("--position") or
WithParam("--count") and preserve the original error message text as the
validation message. Ensure every common.ValidationErrorf(...) call in those
functions is replaced consistently with this errs.NewValidationError pattern.

In `@shortcuts/sheets/lark_sheet_write_cells.go`:
- Around line 211-220: PostMount currently uses
cmd.MarkFlagsOneRequired("start-cell", "range") which only ensures at least one
flag is present but allows both; update enforcement so exactly one is set by
calling Cobra's MarkFlagsMutuallyExclusive("start-cell","range") in PostMount
(in addition to or instead of MarkFlagsOneRequired) and add a defensive check in
csvPutInput that returns an error if both start-cell and range are non-empty
(rejecting the double-set case). Modify references around PostMount,
cmd.MarkFlagsOneRequired, MarkFlagsMutuallyExclusive, and csvPutInput to
implement both the Cobra mutual-exclusion and the explicit runtime validation.
🪄 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: d390e31a-04d1-4f46-acbe-39c5f002b0d7

📥 Commits

Reviewing files that changed from the base of the PR and between e1fd240 and 7778c6d.

📒 Files selected for processing (67)
  • .golangci.yml
  • lint/errscontract/rule_no_legacy_envelope_literal.go
  • shortcuts/doc/clipboard.go
  • shortcuts/doc/doc_errors.go
  • shortcuts/doc/doc_media_download.go
  • shortcuts/doc/doc_media_insert.go
  • shortcuts/doc/doc_media_preview.go
  • shortcuts/doc/doc_media_upload.go
  • shortcuts/doc/docs_create.go
  • shortcuts/doc/docs_create_v2.go
  • shortcuts/doc/docs_fetch_v2.go
  • shortcuts/doc/docs_search.go
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/docs_update_v2.go
  • shortcuts/doc/helpers.go
  • shortcuts/sheets/backward/helpers.go
  • shortcuts/sheets/backward/lark_sheets_cell_data.go
  • shortcuts/sheets/backward/lark_sheets_cell_images.go
  • shortcuts/sheets/backward/lark_sheets_cell_style_and_merge.go
  • shortcuts/sheets/backward/lark_sheets_dropdown.go
  • shortcuts/sheets/backward/lark_sheets_filter_views.go
  • shortcuts/sheets/backward/lark_sheets_float_images.go
  • shortcuts/sheets/backward/lark_sheets_row_column_management.go
  • shortcuts/sheets/backward/lark_sheets_sheet_manage_test.go
  • shortcuts/sheets/backward/lark_sheets_sheet_management.go
  • shortcuts/sheets/backward/lark_sheets_spreadsheet_management.go
  • shortcuts/sheets/backward/sheets_errors.go
  • shortcuts/sheets/batch_op_dispatch.go
  • shortcuts/sheets/execute_paths_test.go
  • shortcuts/sheets/flag_schema_validate.go
  • shortcuts/sheets/helpers.go
  • shortcuts/sheets/lark_sheet_batch_update.go
  • shortcuts/sheets/lark_sheet_object_crud.go
  • shortcuts/sheets/lark_sheet_range_operations.go
  • shortcuts/sheets/lark_sheet_range_operations_test.go
  • shortcuts/sheets/lark_sheet_read_data.go
  • shortcuts/sheets/lark_sheet_search_replace.go
  • shortcuts/sheets/lark_sheet_sheet_structure.go
  • shortcuts/sheets/lark_sheet_workbook.go
  • shortcuts/sheets/lark_sheet_write_cells.go
  • shortcuts/sheets/sheet_ai_api.go
  • shortcuts/slides/helpers.go
  • shortcuts/slides/slides_create.go
  • shortcuts/slides/slides_create_test.go
  • shortcuts/slides/slides_errors.go
  • shortcuts/slides/slides_media_upload.go
  • shortcuts/slides/slides_replace_slide.go
  • shortcuts/slides/slides_replace_slide_test.go
  • shortcuts/wiki/wiki_async_task.go
  • shortcuts/wiki/wiki_async_task_test.go
  • shortcuts/wiki/wiki_delete.go
  • shortcuts/wiki/wiki_delete_test.go
  • shortcuts/wiki/wiki_member_add.go
  • shortcuts/wiki/wiki_member_helpers.go
  • shortcuts/wiki/wiki_member_list.go
  • shortcuts/wiki/wiki_member_remove.go
  • shortcuts/wiki/wiki_move.go
  • shortcuts/wiki/wiki_move_test.go
  • shortcuts/wiki/wiki_node_copy.go
  • shortcuts/wiki/wiki_node_create.go
  • shortcuts/wiki/wiki_node_create_test.go
  • shortcuts/wiki/wiki_node_delete.go
  • shortcuts/wiki/wiki_node_delete_test.go
  • shortcuts/wiki/wiki_node_get.go
  • shortcuts/wiki/wiki_node_list.go
  • shortcuts/wiki/wiki_space_create.go
  • shortcuts/wiki/wiki_space_list.go
💤 Files with no reviewable changes (26)
  • shortcuts/slides/slides_errors.go
  • shortcuts/slides/slides_create_test.go
  • shortcuts/slides/slides_replace_slide_test.go
  • shortcuts/wiki/wiki_member_helpers.go
  • shortcuts/wiki/wiki_member_list.go
  • shortcuts/slides/slides_media_upload.go
  • shortcuts/wiki/wiki_space_create.go
  • shortcuts/wiki/wiki_move_test.go
  • shortcuts/wiki/wiki_delete.go
  • shortcuts/wiki/wiki_async_task_test.go
  • shortcuts/wiki/wiki_async_task.go
  • shortcuts/wiki/wiki_node_list.go
  • shortcuts/wiki/wiki_node_copy.go
  • shortcuts/slides/helpers.go
  • shortcuts/wiki/wiki_move.go
  • shortcuts/wiki/wiki_space_list.go
  • shortcuts/wiki/wiki_node_create_test.go
  • shortcuts/wiki/wiki_member_remove.go
  • shortcuts/wiki/wiki_member_add.go
  • shortcuts/wiki/wiki_node_delete.go
  • shortcuts/slides/slides_replace_slide.go
  • shortcuts/wiki/wiki_delete_test.go
  • shortcuts/slides/slides_create.go
  • shortcuts/wiki/wiki_node_delete_test.go
  • shortcuts/wiki/wiki_node_create.go
  • shortcuts/wiki/wiki_node_get.go
🚧 Files skipped from review as they are similar to previous changes (14)
  • shortcuts/doc/doc_errors.go
  • shortcuts/doc/docs_create_v2.go
  • lint/errscontract/rule_no_legacy_envelope_literal.go
  • shortcuts/doc/helpers.go
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/docs_search.go
  • shortcuts/doc/docs_create.go
  • shortcuts/doc/docs_update_v2.go
  • shortcuts/doc/doc_media_upload.go
  • shortcuts/doc/doc_media_preview.go
  • shortcuts/doc/doc_media_download.go
  • shortcuts/doc/docs_fetch_v2.go
  • shortcuts/doc/clipboard.go
  • shortcuts/doc/doc_media_insert.go

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 3

🤖 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/sheets/backward/lark_sheets_spreadsheet_management.go`:
- Around line 241-244: The output-path safety check currently runs only in
Execute (the runtime.ResolveSavePath call that returns errs.NewValidationError),
causing --dry-run previews to skip this validation; move or duplicate that
validation into the command's Validate phase so the same unsafe path is rejected
during Validate (and thus for dry-run). Concretely, add the
runtime.ResolveSavePath check (and return the same errs.NewValidationError with
WithCause) inside the Validate method or shared input-builder used by Validate,
and remove or keep (idempotently) the Execute check so both phases enforce
identical path validation for the flag handling code that reads outputPath.

In `@shortcuts/sheets/lark_sheet_sheet_structure.go`:
- Around line 162-194: Replace usage of common.ValidationErrorf in
dimInsertInput (and likewise in dimFreezeInput, dimRangeOpInput,
buildDimMovePlan) with the typed-error pattern used elsewhere: return
errs.NewValidationError(errs.SubtypeInvalidArgument,
"<message>").WithParam("<flag>") for missing/invalid flag cases and include
parameter names like "--position", "--count", or the specific flag being
validated; where you currently check runtime.Changed("position") or
runtime.Changed("count") or validate parseA1Position/count, construct and return
the corresponding errs.NewValidationError(...).WithParam("--position") or
WithParam("--count") and preserve the original error message text as the
validation message. Ensure every common.ValidationErrorf(...) call in those
functions is replaced consistently with this errs.NewValidationError pattern.

In `@shortcuts/sheets/lark_sheet_write_cells.go`:
- Around line 211-220: PostMount currently uses
cmd.MarkFlagsOneRequired("start-cell", "range") which only ensures at least one
flag is present but allows both; update enforcement so exactly one is set by
calling Cobra's MarkFlagsMutuallyExclusive("start-cell","range") in PostMount
(in addition to or instead of MarkFlagsOneRequired) and add a defensive check in
csvPutInput that returns an error if both start-cell and range are non-empty
(rejecting the double-set case). Modify references around PostMount,
cmd.MarkFlagsOneRequired, MarkFlagsMutuallyExclusive, and csvPutInput to
implement both the Cobra mutual-exclusion and the explicit runtime validation.
🪄 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: d390e31a-04d1-4f46-acbe-39c5f002b0d7

📥 Commits

Reviewing files that changed from the base of the PR and between e1fd240 and 7778c6d.

📒 Files selected for processing (67)
  • .golangci.yml
  • lint/errscontract/rule_no_legacy_envelope_literal.go
  • shortcuts/doc/clipboard.go
  • shortcuts/doc/doc_errors.go
  • shortcuts/doc/doc_media_download.go
  • shortcuts/doc/doc_media_insert.go
  • shortcuts/doc/doc_media_preview.go
  • shortcuts/doc/doc_media_upload.go
  • shortcuts/doc/docs_create.go
  • shortcuts/doc/docs_create_v2.go
  • shortcuts/doc/docs_fetch_v2.go
  • shortcuts/doc/docs_search.go
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/docs_update_v2.go
  • shortcuts/doc/helpers.go
  • shortcuts/sheets/backward/helpers.go
  • shortcuts/sheets/backward/lark_sheets_cell_data.go
  • shortcuts/sheets/backward/lark_sheets_cell_images.go
  • shortcuts/sheets/backward/lark_sheets_cell_style_and_merge.go
  • shortcuts/sheets/backward/lark_sheets_dropdown.go
  • shortcuts/sheets/backward/lark_sheets_filter_views.go
  • shortcuts/sheets/backward/lark_sheets_float_images.go
  • shortcuts/sheets/backward/lark_sheets_row_column_management.go
  • shortcuts/sheets/backward/lark_sheets_sheet_manage_test.go
  • shortcuts/sheets/backward/lark_sheets_sheet_management.go
  • shortcuts/sheets/backward/lark_sheets_spreadsheet_management.go
  • shortcuts/sheets/backward/sheets_errors.go
  • shortcuts/sheets/batch_op_dispatch.go
  • shortcuts/sheets/execute_paths_test.go
  • shortcuts/sheets/flag_schema_validate.go
  • shortcuts/sheets/helpers.go
  • shortcuts/sheets/lark_sheet_batch_update.go
  • shortcuts/sheets/lark_sheet_object_crud.go
  • shortcuts/sheets/lark_sheet_range_operations.go
  • shortcuts/sheets/lark_sheet_range_operations_test.go
  • shortcuts/sheets/lark_sheet_read_data.go
  • shortcuts/sheets/lark_sheet_search_replace.go
  • shortcuts/sheets/lark_sheet_sheet_structure.go
  • shortcuts/sheets/lark_sheet_workbook.go
  • shortcuts/sheets/lark_sheet_write_cells.go
  • shortcuts/sheets/sheet_ai_api.go
  • shortcuts/slides/helpers.go
  • shortcuts/slides/slides_create.go
  • shortcuts/slides/slides_create_test.go
  • shortcuts/slides/slides_errors.go
  • shortcuts/slides/slides_media_upload.go
  • shortcuts/slides/slides_replace_slide.go
  • shortcuts/slides/slides_replace_slide_test.go
  • shortcuts/wiki/wiki_async_task.go
  • shortcuts/wiki/wiki_async_task_test.go
  • shortcuts/wiki/wiki_delete.go
  • shortcuts/wiki/wiki_delete_test.go
  • shortcuts/wiki/wiki_member_add.go
  • shortcuts/wiki/wiki_member_helpers.go
  • shortcuts/wiki/wiki_member_list.go
  • shortcuts/wiki/wiki_member_remove.go
  • shortcuts/wiki/wiki_move.go
  • shortcuts/wiki/wiki_move_test.go
  • shortcuts/wiki/wiki_node_copy.go
  • shortcuts/wiki/wiki_node_create.go
  • shortcuts/wiki/wiki_node_create_test.go
  • shortcuts/wiki/wiki_node_delete.go
  • shortcuts/wiki/wiki_node_delete_test.go
  • shortcuts/wiki/wiki_node_get.go
  • shortcuts/wiki/wiki_node_list.go
  • shortcuts/wiki/wiki_space_create.go
  • shortcuts/wiki/wiki_space_list.go
💤 Files with no reviewable changes (26)
  • shortcuts/slides/slides_errors.go
  • shortcuts/slides/slides_create_test.go
  • shortcuts/slides/slides_replace_slide_test.go
  • shortcuts/wiki/wiki_member_helpers.go
  • shortcuts/wiki/wiki_member_list.go
  • shortcuts/slides/slides_media_upload.go
  • shortcuts/wiki/wiki_space_create.go
  • shortcuts/wiki/wiki_move_test.go
  • shortcuts/wiki/wiki_delete.go
  • shortcuts/wiki/wiki_async_task_test.go
  • shortcuts/wiki/wiki_async_task.go
  • shortcuts/wiki/wiki_node_list.go
  • shortcuts/wiki/wiki_node_copy.go
  • shortcuts/slides/helpers.go
  • shortcuts/wiki/wiki_move.go
  • shortcuts/wiki/wiki_space_list.go
  • shortcuts/wiki/wiki_node_create_test.go
  • shortcuts/wiki/wiki_member_remove.go
  • shortcuts/wiki/wiki_member_add.go
  • shortcuts/wiki/wiki_node_delete.go
  • shortcuts/slides/slides_replace_slide.go
  • shortcuts/wiki/wiki_delete_test.go
  • shortcuts/slides/slides_create.go
  • shortcuts/wiki/wiki_node_delete_test.go
  • shortcuts/wiki/wiki_node_create.go
  • shortcuts/wiki/wiki_node_get.go
🚧 Files skipped from review as they are similar to previous changes (14)
  • shortcuts/doc/doc_errors.go
  • shortcuts/doc/docs_create_v2.go
  • lint/errscontract/rule_no_legacy_envelope_literal.go
  • shortcuts/doc/helpers.go
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/docs_search.go
  • shortcuts/doc/docs_create.go
  • shortcuts/doc/docs_update_v2.go
  • shortcuts/doc/doc_media_upload.go
  • shortcuts/doc/doc_media_preview.go
  • shortcuts/doc/doc_media_download.go
  • shortcuts/doc/docs_fetch_v2.go
  • shortcuts/doc/clipboard.go
  • shortcuts/doc/doc_media_insert.go
🛑 Comments failed to post (3)
shortcuts/sheets/backward/lark_sheets_spreadsheet_management.go (1)

241-244: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate --output-path before the dry-run path too.

This safety check only runs in Execute, so +export --dry-run --output-path ... still produces a successful preview for a path the real command would reject. Moving it into Validate (or a shared input builder) keeps dry-run/error-contract behavior aligned with the real path.

Based on learnings: Validate-stage rejects in dry-run tests exit non-zero, and this repo already validates user-facing output paths during Validate.

🤖 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/sheets/backward/lark_sheets_spreadsheet_management.go` around lines
241 - 244, The output-path safety check currently runs only in Execute (the
runtime.ResolveSavePath call that returns errs.NewValidationError), causing
--dry-run previews to skip this validation; move or duplicate that validation
into the command's Validate phase so the same unsafe path is rejected during
Validate (and thus for dry-run). Concretely, add the runtime.ResolveSavePath
check (and return the same errs.NewValidationError with WithCause) inside the
Validate method or shared input-builder used by Validate, and remove or keep
(idempotently) the Execute check so both phases enforce identical path
validation for the flag handling code that reads outputPath.
shortcuts/sheets/lark_sheet_sheet_structure.go (1)

162-194: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use errs.NewValidationError consistently with other migrated sheets shortcuts.

This file uses common.ValidationErrorf(...) for validation errors, but all other sheets shortcuts in this migration (in shortcuts/sheets/backward/) consistently use errs.NewValidationError(errs.SubtypeInvalidArgument, ...).WithParam("--flag").

For consistency with the typed-error migration pattern applied across the rest of shortcuts/sheets/, these validation helpers should use the same approach.

🔄 Example refactor for dimInsertInput
 func dimInsertInput(runtime flagView, token, sheetID, sheetName string) (map[string]interface{}, error) {
 	if err := requireSheetSelector(sheetID, sheetName); err != nil {
 		return nil, err
 	}
 	if !runtime.Changed("position") {
-		return nil, common.ValidationErrorf("--position is required")
+		return nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "--position is required").WithParam("--position")
 	}
 	if !runtime.Changed("count") {
-		return nil, common.ValidationErrorf("--count is required")
+		return nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "--count is required").WithParam("--count")
 	}
 	position := strings.TrimSpace(runtime.Str("position"))
 	if _, _, err := parseA1Position(position); err != nil {
-		return nil, common.ValidationErrorf("invalid --position %q: %v", position, err)
+		return nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "invalid --position %q: %v", position, err).WithParam("--position").WithCause(err)
 	}
 	count := runtime.Int("count")
 	if count <= 0 {
-		return nil, common.ValidationErrorf("--count must be > 0 (got %d)", count)
+		return nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "--count must be > 0 (got %d)", count).WithParam("--count")
 	}

Apply the same pattern to dimFreezeInput, dimRangeOpInput, and buildDimMovePlan.

Also applies to: 324-353, 359-377, 633-651

🤖 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/sheets/lark_sheet_sheet_structure.go` around lines 162 - 194,
Replace usage of common.ValidationErrorf in dimInsertInput (and likewise in
dimFreezeInput, dimRangeOpInput, buildDimMovePlan) with the typed-error pattern
used elsewhere: return errs.NewValidationError(errs.SubtypeInvalidArgument,
"<message>").WithParam("<flag>") for missing/invalid flag cases and include
parameter names like "--position", "--count", or the specific flag being
validated; where you currently check runtime.Changed("position") or
runtime.Changed("count") or validate parseA1Position/count, construct and return
the corresponding errs.NewValidationError(...).WithParam("--position") or
WithParam("--count") and preserve the original error message text as the
validation message. Ensure every common.ValidationErrorf(...) call in those
functions is replaced consistently with this errs.NewValidationError pattern.
shortcuts/sheets/lark_sheet_write_cells.go (1)

211-220: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In github.com/spf13/cobra, does MarkFlagsOneRequired enforce mutual exclusivity, or does it only require at least one of the listed flags? Please point to the official Cobra docs or source for Cobra v1.10.x.

💡 Result:

MarkFlagsOneRequired in github.com/spf13/cobra does NOT enforce mutual exclusivity. It only requires that at least one of the listed flags is set. In Cobra v1.10.x, MarkFlagsOneRequired is validated by validateOneRequiredFlagGroups, which errors only when none of the flags in the one-required group are set: “at least one of the flags in the group […] is required” [1][2]. Mutual exclusivity is enforced separately by the mutuallyExclusive annotation + validateExclusiveFlagGroups, which errors when more than one flag in the mutually-exclusive group is set [1]. So, MarkFlagsOneRequired alone = “at least one required”; to get “exactly one”, you must also use MarkFlagsMutuallyExclusive for the same flag set (as noted in the PR discussion and example) [3].

Citations:


Fix --start-cell/--range “exactly one” enforcement.

cmd.MarkFlagsOneRequired("start-cell", "range") only guarantees that at least one of the flags is set; it does not prevent both --start-cell and --range from being provided together. If the contract is “exactly one must be set”, enforce mutual exclusivity via Cobra (e.g., MarkFlagsMutuallyExclusive) and/or add explicit validation in csvPutInput to reject the double-set case.

🤖 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/sheets/lark_sheet_write_cells.go` around lines 211 - 220, PostMount
currently uses cmd.MarkFlagsOneRequired("start-cell", "range") which only
ensures at least one flag is present but allows both; update enforcement so
exactly one is set by calling Cobra's
MarkFlagsMutuallyExclusive("start-cell","range") in PostMount (in addition to or
instead of MarkFlagsOneRequired) and add a defensive check in csvPutInput that
returns an error if both start-cell and range are non-empty (rejecting the
double-set case). Modify references around PostMount, cmd.MarkFlagsOneRequired,
MarkFlagsMutuallyExclusive, and csvPutInput to implement both the Cobra
mutual-exclusion and the explicit runtime validation.

@evandance evandance force-pushed the feat/errs-migrate-ccm branch 4 times, most recently from 5c68a27 to a8b529a Compare June 4, 2026 14:09
@evandance evandance changed the title feat(doc,sheets,slides,wiki): emit typed error envelopes across ccm domains feat(doc,markdown,sheets,slides,wiki): emit typed error envelopes across ccm domains Jun 4, 2026
@evandance evandance force-pushed the feat/errs-migrate-ccm branch 4 times, most recently from d6d99d0 to 9570105 Compare June 5, 2026 04:04
@evandance evandance force-pushed the feat/errs-migrate-ccm branch 3 times, most recently from 7c21445 to 44949a5 Compare June 6, 2026 09:21
@github-actions github-actions Bot added the domain/im PR touches the im domain label Jun 6, 2026
@evandance evandance changed the title feat(doc,markdown,sheets,slides,wiki): emit typed error envelopes across ccm domains feat(doc,im,markdown,sheets,slides,wiki): emit typed error envelopes across shortcut domains Jun 6, 2026
@evandance evandance force-pushed the feat/errs-migrate-ccm branch from 44949a5 to 62ccc69 Compare June 6, 2026 10:34
@evandance evandance changed the title feat(doc,im,markdown,sheets,slides,wiki): emit typed error envelopes across shortcut domains feat(doc,markdown,sheets,slides,wiki): emit typed error envelopes across ccm domains Jun 6, 2026
@github-actions github-actions Bot removed the domain/im PR touches the im domain label Jun 6, 2026
@ViperCai ViperCai force-pushed the feat/errs-migrate-ccm branch from 62ccc69 to 9def5a2 Compare June 8, 2026 08:17
@evandance evandance force-pushed the feat/errs-migrate-ccm branch 4 times, most recently from b0f916a to 564d4df Compare June 9, 2026 03:56
…oss ccm domains

Classify doc, markdown, sheets, slides, and wiki shortcut failures with typed errors so CLI users and automation receive more specific, actionable diagnostics.

Keep the migration scoped to the CCM shortcut domains, their error-contract guards, and the now-unreachable legacy save-error helper cleanup required after those domains stop calling it. Align the common-helper AST guard with latest main's migrated paths without reintroducing shortcuts removed upstream.
@evandance evandance force-pushed the feat/errs-migrate-ccm branch from 564d4df to 78e9d4c Compare June 9, 2026 04:17
@evandance evandance closed this Jun 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain/ccm PR touches the ccm domain feature size/XL Architecture-level or global-impact change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant