Skip to content

fix(sheets): +batch-update sub-op CLI-side validation + cond-format / filter schema alignment#1018

Merged
zhengzhijiej-tech merged 2 commits into
larksuite:feat/lark-sheets-refactorfrom
zhengzhijiej-tech:fix/sheets-validation-pushdown
May 21, 2026
Merged

fix(sheets): +batch-update sub-op CLI-side validation + cond-format / filter schema alignment#1018
zhengzhijiej-tech merged 2 commits into
larksuite:feat/lark-sheets-refactorfrom
zhengzhijiej-tech:fix/sheets-validation-pushdown

Conversation

@zhengzhijiej-tech

Copy link
Copy Markdown
Collaborator

Summary

Two adjacent fixes around +batch-update and related write shortcuts, both surfaced by BOE smoke testing of multi-op batches.

  • 8d0fefd fix(sheets): push +batch-update sub-op validation down into xxxInput builders — sub-ops that omit --sheet-id (or any other required flag) used to slip past CLI validation and surface as opaque server errors like sheet undefined not found after a network round-trip. Every batchable xxxInput builder now returns (map, error) and owns its own sheet-selector + required-field checks via the new requireSheetSelector helper. Standalone Validate shrinks to validateViaInput(xxxInput), so identical bad input now fires identical CLI errors from both standalone and batch paths (wrapped as operations[N] (+shortcut): ... in the batch case). sheetMoveBatchInput's explicit-source-index constraint is preserved.

  • 4e44e66 fix(sheets): align +cond-format / +filter with server schema (#4 + #5)

    • +cond-format: condFormatEnhance was writing properties.rule.type (nested), but the server schema (manage_conditional_format_object) wants flat properties.rule_type. The CLI enum (cellValue / formula / duplicate / ...) was also a CLI-invented vocabulary none of whose values the server accepts. Breaking: enum aligned with server (cellIs / duplicateValues / containsText / timePeriod / containsBlanks / notContainsBlanks / dataBar / colorScale / rank / aboveAverage / expression / iconSet); scripts using old names now hit cobra invalid value ..., allowed: .... No alias layer.
    • +filter-{update,delete}: server contract is filter_id === sheet_id and both ops MUST carry filter_id — the CLI translator never set it, so every call failed server-side. Translator now auto-injects filter_id from sheet_id. Because filter_id must equal sheet_id (not sheet_name), update/delete reject --sheet-name-only with a friendly error pointing at +workbook-info.
    • Doc artifacts that got regenerated alongside (sync from sheet-skill-spec):
      • +dim-{hide,unhide,group,ungroup} --start/--end desc changed from (0-based, inclusive) to (0-based) / (exclusive) to match the half-open range semantics the code has always implemented.
      • +sheet-move reference gains a batch-internal warning about explicit --sheet-id + --source-index.
      • +pivot-create --properties example drops the stale data_range field (data source goes through --source).

Test plan

  • go vet ./shortcuts/sheets/...
  • go build ./...
  • go test ./shortcuts/sheets/... — all green, including
    • TestBatchOp_BodyMatchesStandalone (~40 cases): batch sub-op bodies stay byte-identical to standalone bodies.
    • TestBatchOp_ErrorEquivalence (7 cases): XOR / logical-constraint errors fire identically standalone vs batch.
    • TestBatchOp_RejectsBadSubOpInput (10 cases): cobra-required flags + filter sheet-name-only now rejected CLI-side in batch.
    • TestObjectCRUDShortcuts_DryRun: cond-format body uses flat properties.rule_type; filter update/delete auto-inject filter_id = sheet_id.
  • BOE smoke (spreadsheet ICFwstkUGheyfptGWS2bB7RgcDf):
    • Missing --sheet-id in a batch sub-op now returns operations[0] (+dim-insert): specify at least one of --sheet-id or --sheet-name before any network call.
    • +cond-format-create --rule-type cellIs writes properties.rule_type: "cellIs" flat; old enum cellValue rejected by cobra with the new enum listed.
    • +filter-update --sheet-id X auto-populates filter_id: X; --sheet-name only gets the friendly error.

Notes / follow-ups

  • Breaking change for +cond-format-{create,update} --rule-type: any script passing the old vocabulary needs to migrate to server enum (cellValue → cellIs, duplicate → duplicateValues, etc.). Per offline discussion no alias layer is added — earlier alignment is better than carrying two vocabularies.
  • +sparkline-update still requires user to hand-fill properties.sparklines[].sparkline_id; auto list-then-update is a separate change of its own (architecture limit, not in this PR).
  • This PR sits on top of the upstream 0ea7c14 / 1e05e7b flagView abstraction; no overlap with those commits.

…builders

Sub-ops that omit --sheet-id (or any other required flag) used to slip
past CLI validation — Validate ran only against the standalone shortcut
path, and batchOpDispatch's translators built bodies from whatever
flagView returned, so a structurally broken sub-op surfaced as an opaque
server "sheet undefined not found" after a network round-trip.

Push each batchable shortcut's check trio down into its xxxInput builder:

  1. resolveSpreadsheetToken — stays in Validate (batch already does it
     once at the top level; sub-ops don't repeat).
  2. requireSheetSelector(sheetID, sheetName) — new helper; flagView-
     agnostic XOR + control-char check, called at the top of every
     xxxInput.
  3. shortcut-specific required / range / enum checks (--dimension,
     --range, --start <= --end, --type pixel needs --size,
     --float-image-id, image-token XOR image-uri, ...) — moved out of
     Validate into the builder body.

All ~30 batchable xxxInput builders now return (map, error). Standalone
Validate shrinks to validateViaInput(xxxInput); DryRun / Execute
propagate the error. batch_op_dispatch entries drop the noErrTranslate
wrapper and pass the builder directly — its error bubbles up wrapped
with "operations[N] (+shortcut):" context.

Tests:

- TestBatchOp_ErrorEquivalence (7 cases): XOR / logical-constraint
  errors fire identically from standalone and batch sub-op paths.
- TestBatchOp_RejectsBadSubOpInput (8 cases): cobra-required flags that
  standalone catches via MarkFlagRequired now also get rejected CLI-side
  on the batch path (where cobra is not in the loop).
- TestBatchOp_BodyMatchesStandalone (~40 cases) and
  TestBatchOp_DispatchCoversReportedBugs continue to pass — bodies stay
  byte-identical.
- BOE smoke (spreadsheet ICFwstkUGheyfptGWS2bB7RgcDf, sheet 51991c):
  +batch-update with a sub-op missing --sheet-id now returns
  "operations[0] (+dim-insert): specify at least one of --sheet-id or
  --sheet-name" before any network call.

sheetMoveBatchInput (xiongyuanwen's batch-only explicit-source-index
requirement) is preserved — it's an orthogonal batch-specific constraint
not affected by this push-down.
…te#4 + larksuite#5)

Two latent bugs in the object_crud translator surfaced during BOE smoke
testing of +batch-update. Both are schema-alignment fixes against
manage_conditional_format_object / manage_filter_object as declared in
sheet-skill-spec/canonical-spec/tool-schemas/mcp-tools.json.

larksuite#4 +cond-format: rule_type path + enum vocabulary
---------------------------------------------------
condFormatEnhance used to write the user's --rule-type value into
`properties.rule.type` (nested under a `rule` object). The server
schema actually puts it at flat `properties.rule_type` and silently
drops the nested form — so every conditional-format create/update
secretly built the wrong document.

Worse, the CLI enum exposed via flag-defs.json was its own invented
vocabulary (cellValue / formula / duplicate / unique / topBottom /
aboveBelowAverage / dataBar / colorScale / iconSet / textContains /
dateOccurring / blankCell / errorCell) — none of those values were
the strings the server accepts.

Fix:
- condFormatEnhance now writes `properties.rule_type = <value>`
  directly (no nested `rule` object).
- Synced flag-defs.json + lark-sheets-conditional-format.md enum
  vocabulary from base to match the server: duplicateValues,
  uniqueValues, cellIs, containsText, timePeriod, containsBlanks,
  notContainsBlanks, dataBar, colorScale, rank, aboveAverage,
  expression, iconSet.
- ⚠️ Breaking: scripts passing the old CLI-invented enum values
  (e.g. --rule-type cellValue) now get a cobra "invalid value …
  allowed: …" error listing the new vocabulary. No alias layer.
- TestObjectCRUDShortcuts_DryRun's +cond-format-update case updated
  to assert the flat properties.rule_type shape + new enum.

larksuite#5 +filter-{update,delete}: auto-inject filter_id = sheet_id
-------------------------------------------------------------
manage_filter_object's contract is "filter_id === sheet_id" for the
sheet-scoped filter (per per-tool description in mcp-tools.json),
and update / delete operations MUST carry filter_id. Standalone
filterUpdateInput / filterDeleteInput never set it, so the server
rejected with "filter_id is required for update/delete operation"
on every call — both standalone AND inside +batch-update.

Fix:
- filterUpdateInput / filterDeleteInput now set
  input["filter_id"] = sheetID.
- Because filter_id must equal sheet_id (not sheet_name), update /
  delete reject when only --sheet-name is given — there's no
  network lookup available inside the builder. The friendly error
  points at +workbook-info for resolving sheet-name → sheet-id.
- create still omits filter_id (server requires that — id is
  server-allocated on creation).
- New tests:
  * TestObjectCRUDShortcuts_DryRun gains a +filter-update happy-path
    case asserting filter_id is auto-injected + --range hoisting.
  * +filter-delete case updated to assert filter_id presence.
  * TestBatchOp_RejectsBadSubOpInput gains two cases asserting both
    +filter-update and +filter-delete reject --sheet-name-only with
    the friendly error.

Docs (larksuite#2 + larksuite#3 + larksuite#8) synced from sheet-skill-spec
-------------------------------------------------
Companion doc fixes that landed via npm run generate:cli + sync:cli
in sheet-skill-spec; included here because the regenerated flag-defs
and references markdown are byte-tracked in this repo:

- larksuite#2: lark-sheets-sheet-structure.md — +dim-{hide,unhide,group,
  ungroup} --start/--end desc changed from "(0-based, inclusive)" to
  "(0-based)" / "(exclusive)" to match the half-open range semantics
  the code has always implemented (requireDimRange: end > start;
  dimRange uses end - 1 for column end letters).
- larksuite#3: lark-sheets-workbook.md — +sheet-move section gains a note
  about the batch-internal requirement to pass --sheet-id AND
  --source-index explicitly (sheetMoveBatchInput's constraint).
- larksuite#8: lark-sheets-pivot-table.md — +pivot-create --properties
  example drops the stale data_range field (the actual server
  schema uses --source as a hoisted flag; properties only carries
  rows / columns / values / filters / show_*_grand_total).
@CLAassistant

CLAassistant commented May 21, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions Bot added domain/ccm PR touches the ccm domain size/L Large or sensitive change across domains or core paths labels May 21, 2026
@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 36208d4a-da1e-497a-aa79-97f66122b9c1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ 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.

@xiongyuanwen-byted xiongyuanwen-byted left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@zhengzhijiej-tech
zhengzhijiej-tech marked this pull request as ready for review May 21, 2026 09:19
@zhengzhijiej-tech
zhengzhijiej-tech merged commit 8e8a511 into larksuite:feat/lark-sheets-refactor May 21, 2026
4 checks passed
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 size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants