Skip to content

feat(base): improve field update completion signals - #2219

Open
yballul-bytedance wants to merge 1 commit into
larksuite:mainfrom
yballul-bytedance:auto-research-sync/01KWNBD6WC5QZ2YTZZBB6CTZ37/mr-948-d8299934
Open

feat(base): improve field update completion signals#2219
yballul-bytedance wants to merge 1 commit into
larksuite:mainfrom
yballul-bytedance:auto-research-sync/01KWNBD6WC5QZ2YTZZBB6CTZ37/mr-948-d8299934

Conversation

@yballul-bytedance

@yballul-bytedance yballul-bytedance commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Improve Base field shortcut behavior for field lookup aliases, field update no-op handling, auto-number reformatting, and rating validation.

Changes

  • Add a hidden --field-id-or-name compatibility alias for base +field-get while keeping --field-id as the public flag.
  • Treat no-op field update API responses as successful completion signals and expose submitted field metadata without synthesizing field IDs.
  • Add explicit --reformat-existing-records support for auto-number updates, including bitable v1 request conversion and dry-run coverage.
  • Reject rating fields with max > 10 and update Base skill references for the new field-update workflow.

Test Plan

  • git diff --check

Related Issues

Auto research task: 01KWNBD6WC5QZ2YTZZBB6CTZ37

Summary by CodeRabbit

  • New Features
    • Find Base fields using either their ID or name.
    • Reformat existing auto-number records with the new --reformat-existing-records option.
  • Bug Fixes
    • No-op field updates are now reported as successful without changes.
    • Invalid rating limits and unsupported auto-number date formats are rejected before execution.
    • Dry-run validation now mirrors actual field operations.
  • Documentation
    • Updated guidance for Base shortcuts, auto-number reformatting, rating limits, and supported date formats.

Co-authored-by: TRAE CLI <noreply@bytedance.com>
@github-actions github-actions Bot added domain/base PR touches the base domain size/L Large or sensitive change across domains or core paths labels Aug 6, 2026
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Base field commands now accept a hidden field-name alias, validate selectors and field definitions more strictly, support explicit auto-number reformatting through the Bitable v1 endpoint, and treat matching no-op updates as successful unchanged results.

Changes

Base field operations

Layer / File(s) Summary
Field selector alias
shortcuts/base/field_get.go, shortcuts/base/field_ops.go, shortcuts/base/base_shortcuts_test.go, tests/cli_e2e/base/base_field_dryrun_test.go, shortcuts/base/base_dryrun_ops_test.go
+field-get accepts exactly one trimmed value from --field-id or hidden --field-id-or-name. Dry-run and execution use the resolved reference.
Auto-number reformat flow
shortcuts/base/field_update.go, shortcuts/base/field_ops.go, shortcuts/base/helpers.go, shortcuts/base/base_dryrun_ops_test.go, shortcuts/base/base_execute_test.go, tests/cli_e2e/base/base_field_update_dryrun_test.go, skills/lark-base/references/lark-base-field-update.md, skills/lark-base/references/lark-base-field-json.md
--reformat-existing-records converts auto-number updates to the Bitable v1 payload and endpoint. Supported rules and date formats are validated.
Validation and no-op handling
shortcuts/base/field_ops.go, shortcuts/base/base_execute_test.go, shortcuts/base/base_shortcuts_test.go, tests/cli_e2e/base/base_field_update_dryrun_test.go, skills/lark-base/references/lark-base-field-update.md, skills/lark-base/references/lark-base-field-json.md
Rating maxima above 10 and embedded reformat flags are rejected. Matching no-op update responses return successful unchanged results.
Base operation guidance
skills/lark-base/SKILL.md
Base guidance now excludes unsupported command paths and UI-only settings.

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

Sequence Diagram(s)

sequenceDiagram
  participant BaseFieldUpdate
  participant FieldOperations
  participant BitableV1
  BaseFieldUpdate->>FieldOperations: submit auto-number update
  FieldOperations->>BitableV1: send converted reformat request
  BitableV1-->>FieldOperations: return update result
  FieldOperations-->>BaseFieldUpdate: return completed or unchanged response
Loading

Possibly related PRs

  • larksuite/cli#2153: Covers overlapping Base field shortcut validation in field_ops.go and base_execute_test.go.

Suggested reviewers: liangshuo-1

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check ✅ Passed The title clearly describes the primary field-update completion behavior change, although it does not mention the related alias, reformatting, or rating validation work.
Description check ✅ Passed The description includes all required sections and summarizes the main changes, but the test plan only lists git diff --check.
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 commented Aug 6, 2026

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 Skill update

npx skills add yballul-bytedance/cli#auto-research-sync/01KWNBD6WC5QZ2YTZZBB6CTZ37/mr-948-d8299934 -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: 11

🤖 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/base_dryrun_ops_test.go`:
- Around line 88-93: Add a direct case in the dry-run field-get tests using `"
Amount "` as the `field-id-or-name` value, and assert through `dryRunFieldGet`
that the generated request path contains `/fields/Amount`. Keep the existing
untrimmed selector coverage and use the same `assertDryRunContains` pattern.

In `@shortcuts/base/base_shortcuts_test.go`:
- Around line 1208-1216: Update the BaseFieldGet validation failure assertions
to verify typed metadata, not only error text: use errors.As to extract
*errs.ValidationError and assert its Param, and assert the expected category and
subtype through errs.ProblemOf(err) where supported. Apply the same metadata
assertions to the related error-path test around the field-id alias validation.

In `@shortcuts/base/field_ops.go`:
- Around line 256-270: Update the reformat_existing_records branch in
fieldUpdate to return verification guidance requiring field readback and
sampling regenerated record values, rather than field_get_recommended:false,
field_get_required:false, and next_step:"done". Update
shortcuts/base/base_execute_test.go lines 980-1015 to assert this required
guidance, and align skills/lark-base/references/lark-base-field-update.md lines
107-115 with the resulting output contract.
- Around line 559-563: Update the rule length handling in the incremental-number
branch to distinguish an absent length from an explicitly provided one: use the
default value 3 only when length is absent, and return a validation error for
explicit values outside the documented 1..9 range, including 0 and values above
9. Preserve the existing system_number response for valid lengths.
- Around line 330-337: Update isFieldUpdateNoop in shortcuts/base/field_ops.go
(lines 330-337) to recognize the no-op solely by baseFieldUpdateNoopCode,
removing the problem.Message text check. Add a regression case in
shortcuts/base/base_execute_test.go (lines 909-929) using code 800070003 with a
different message and assert it still returns the successful no-op result.
- Around line 148-154: In shortcuts/base/field_ops.go lines 148-154, validate
containsAutoNumberReformatKey(body) before branching on
runtime.Bool("reformat-existing-records"), returning the existing typed
validation error for every embedded reformat key; only invoke
buildAutoNumberReformatBody when no embedded key is present and the flag is
enabled. In shortcuts/base/base_shortcuts_test.go lines 1254-1262, add coverage
supplying both --reformat-existing-records and an embedded reformat key, and
assert the typed validation failure.
- Around line 466-567: Replace the map-based conversion in
buildAutoNumberReformatBody with typed input models for the field definition,
property, auto_serial, style, and rules, decoding the incoming JSON at the
boundary with strict type validation. Add dedicated projection functions for the
auto_serial and style/rules shapes that produce a typed Bitable v1 request,
preserving existing defaults and validation errors. Return the projected request
in the existing API shape without direct map reads or writes in the conversion
helpers.

In `@skills/lark-base/references/lark-base-field-json.md`:
- Line 476: Update the existing-record regeneration statement in the auto-number
update documentation to clarify that values are regenerated only when
`--reformat-existing-records` is specified; standard updates use the Base v3
endpoint without setting `reformat_existing_records`.

In `@skills/lark-base/references/lark-base-field-update.md`:
- Around line 56-58: Add the text language identifier to the fenced code block
containing the PUT endpoint, changing the unlabeled fence to a text-labeled
fence while preserving the endpoint content.

In `@tests/cli_e2e/base/base_field_dryrun_test.go`:
- Around line 37-40: Update the validation assertions in the base field dry-run
test to also verify the expected invalid-argument value of error.subtype,
alongside the existing error.type and error.param checks. Keep the assertion
against the structured result.StdErr payload and preserve the current message
validation.

In `@tests/cli_e2e/base/base_field_update_dryrun_test.go`:
- Around line 37-58: Add a live E2E test alongside
TestBaseFieldUpdateAutoNumberReformatDryRun that creates a base, table,
auto-number field, and records; invokes base field-update with
--reformat-existing-records and --yes using the changed numbering rule; verifies
the updated auto-number values through the live API or CLI; and reliably cleans
up all created resources. Keep the workflow self-contained and follow existing
live E2E create/use/cleanup patterns in tests/cli_e2e.
🪄 Autofix

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 Plus

Run ID: 152b48b8-c614-4f35-918e-aef5cd61c0ea

📥 Commits

Reviewing files that changed from the base of the PR and between 164d3cc and bd8db4c.

📒 Files selected for processing (12)
  • shortcuts/base/base_dryrun_ops_test.go
  • shortcuts/base/base_execute_test.go
  • shortcuts/base/base_shortcuts_test.go
  • shortcuts/base/field_get.go
  • shortcuts/base/field_ops.go
  • shortcuts/base/field_update.go
  • shortcuts/base/helpers.go
  • skills/lark-base/SKILL.md
  • skills/lark-base/references/lark-base-field-json.md
  • skills/lark-base/references/lark-base-field-update.md
  • tests/cli_e2e/base/base_field_dryrun_test.go
  • tests/cli_e2e/base/base_field_update_dryrun_test.go

Comment on lines +88 to +93
fieldGetAliasRT := newBaseTestRuntime(
map[string]string{"base-token": "app_x", "table-id": "tbl_1", "field-id-or-name": "Amount"},
nil,
nil,
)
assertDryRunContains(t, dryRunFieldGet(ctx, fieldGetAliasRT), "GET /open-apis/base/v3/bases/app_x/tables/tbl_1/fields/Amount")

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 | 🟡 Minor | ⚡ Quick win

Test selector trimming.

The contract accepts one trimmed selector value. Add a case with " Amount " and assert that the generated path ends in /Amount. The current test passes if fieldGetRef stops trimming.

As per coding guidelines, each behavior change needs a direct contract test.

🤖 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/base_dryrun_ops_test.go` around lines 88 - 93, Add a direct
case in the dry-run field-get tests using `" Amount "` as the `field-id-or-name`
value, and assert through `dryRunFieldGet` that the generated request path
contains `/fields/Amount`. Keep the existing untrimmed selector coverage and use
the same `assertDryRunContains` pattern.

Source: Coding guidelines

Comment on lines +1208 to +1216
if err := BaseFieldGet.Validate(ctx, newBaseTestRuntime(map[string]string{"base-token": "b", "table-id": "t"}, nil, nil)); err == nil || !strings.Contains(err.Error(), "--field-id is required") {
t.Fatalf("err=%v", err)
}
if err := BaseFieldGet.Validate(ctx, newBaseTestRuntime(map[string]string{"base-token": "b", "table-id": "t", "field-id-or-name": "Amount"}, nil, nil)); err != nil {
t.Fatalf("field get alias validate err=%v", err)
}
if err := BaseFieldGet.Validate(ctx, newBaseTestRuntime(map[string]string{"base-token": "b", "table-id": "t", "field-id": "fld_1", "field-id-or-name": "Amount"}, nil, nil)); err == nil || !strings.Contains(err.Error(), "mutually exclusive") {
t.Fatalf("err=%v", err)
}

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 | 🟡 Minor | ⚡ Quick win

Assert typed metadata for validation failures.

These new error-path tests only inspect error text. Assert errs.ProblemOf(err) category and subtype. Use errors.As with *errs.ValidationError to assert Param.

As per coding guidelines, error-path tests must assert typed metadata. Based on learnings, errs.ProblemOf does not expose Param.

Also applies to: 1257-1262

🤖 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/base_shortcuts_test.go` around lines 1208 - 1216, Update the
BaseFieldGet validation failure assertions to verify typed metadata, not only
error text: use errors.As to extract *errs.ValidationError and assert its Param,
and assert the expected category and subtype through errs.ProblemOf(err) where
supported. Apply the same metadata assertions to the related error-path test
around the field-id alias validation.

Sources: Coding guidelines, Learnings

Comment on lines +148 to +154
if runtime.Bool("reformat-existing-records") {
if _, err := buildAutoNumberReformatBody(body); err != nil {
return err
}
} else if containsAutoNumberReformatKey(body) {
return baseFlagErrorf("--reformat-existing-records is required for auto_number existing-record regeneration; remove reformat_existing_records from --json and pass --reformat-existing-records")
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject embedded reformat keys even when --reformat-existing-records is set.

The current else if only rejects embedded keys when the dedicated flag is absent. When both are supplied, the command accepts prohibited input. It can silently discard a nested style key or forward an auto_serial key.

  • shortcuts/base/field_ops.go#L148-L154: check containsAutoNumberReformatKey(body) before branching on reformat-existing-records, then return the validation error for every embedded reformat key.
  • shortcuts/base/base_shortcuts_test.go#L1254-L1262: add a case that supplies both --reformat-existing-records and an embedded reformat key, then assert typed validation failure.

As per coding guidelines, do not silently ignore unsupported input or unhonored options.

📍 Affects 2 files
  • shortcuts/base/field_ops.go#L148-L154 (this comment)
  • shortcuts/base/base_shortcuts_test.go#L1254-L1262
🤖 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/field_ops.go` around lines 148 - 154, In
shortcuts/base/field_ops.go lines 148-154, validate
containsAutoNumberReformatKey(body) before branching on
runtime.Bool("reformat-existing-records"), returning the existing typed
validation error for every embedded reformat key; only invoke
buildAutoNumberReformatBody when no embedded key is present and the flag is
enabled. In shortcuts/base/base_shortcuts_test.go lines 1254-1262, add coverage
supplying both --reformat-existing-records and an embedded reformat key, and
assert the typed validation failure.

Source: Coding guidelines

Comment on lines +256 to +270
if runtime.Bool("reformat-existing-records") {
body, err := buildAutoNumberReformatBody(body)
if err != nil {
return err
}
data, err := baseV3Call(runtime, "PUT", bitableV1Path("apps", baseToken, "tables", tableIDValue, "fields", fieldRef), nil, body)
if err != nil {
return err
}
field := interface{}(data)
if inner, ok := data["field"]; ok {
field = inner
}
runtime.Out(fieldUpdateNoReadbackResult(map[string]interface{}{"field": field, "updated": true, "reformat_existing_records": true}), nil)
return nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Do not report auto-number reformatting as fully verified.

The reformat path changes existing record values but returns field_get_recommended:false, field_get_required:false, and next_step:"done". This contradicts the documented requirement to read back and sample regenerated values.

  • shortcuts/base/field_ops.go#L256-L270: return a verification result that recommends field readback and record-value sampling for reformat_existing_records.
  • shortcuts/base/base_execute_test.go#L980-L1015: assert the required verification guidance instead of asserting a completed no-readback result.
  • skills/lark-base/references/lark-base-field-update.md#L107-L115: keep the documentation aligned with the final output contract.
📍 Affects 3 files
  • shortcuts/base/field_ops.go#L256-L270 (this comment)
  • shortcuts/base/base_execute_test.go#L980-L1015
  • skills/lark-base/references/lark-base-field-update.md#L107-L115
🤖 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/field_ops.go` around lines 256 - 270, Update the
reformat_existing_records branch in fieldUpdate to return verification guidance
requiring field readback and sampling regenerated record values, rather than
field_get_recommended:false, field_get_required:false, and next_step:"done".
Update shortcuts/base/base_execute_test.go lines 980-1015 to assert this
required guidance, and align
skills/lark-base/references/lark-base-field-update.md lines 107-115 with the
resulting output contract.

Comment on lines +330 to +337
func isFieldUpdateNoop(err error) bool {
problem, ok := errs.ProblemOf(err)
if !ok {
return false
}
return problem.Code == baseFieldUpdateNoopCode &&
strings.Contains(strings.ToLower(problem.Message), "no operation produced")
}

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 | 🟡 Minor | ⚡ Quick win

Recognize the no-op response by its API code.

800070003 is the dedicated no-op code, but recognition also depends on the English message fragment "no operation produced". A localized or revised server message converts a successful no-op into an API failure.

  • shortcuts/base/field_ops.go#L330-L337: match baseFieldUpdateNoopCode without inspecting problem.Message.
  • shortcuts/base/base_execute_test.go#L909-L929: add a regression case with code 800070003 and a different message that still returns the successful no-op result.
📍 Affects 2 files
  • shortcuts/base/field_ops.go#L330-L337 (this comment)
  • shortcuts/base/base_execute_test.go#L909-L929
🤖 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/field_ops.go` around lines 330 - 337, Update isFieldUpdateNoop
in shortcuts/base/field_ops.go (lines 330-337) to recognize the no-op solely by
baseFieldUpdateNoopCode, removing the problem.Message text check. Add a
regression case in shortcuts/base/base_execute_test.go (lines 909-929) using
code 800070003 with a different message and assert it still returns the
successful no-op result.

Comment on lines +559 to +563
length := toInt(rule["length"])
if length <= 0 {
length = 3
}
return map[string]interface{}{"type": "system_number", "value": fmt.Sprintf("%d", length)}, nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject invalid explicit incremental lengths.

An explicit length: 0 becomes "3" instead of failing validation. Values above 9 also pass through, although the documented range is 1..9. This can regenerate existing record numbers with a format the user did not request.

Apply the default only when length is absent. Reject explicit values outside 1..9.

🤖 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/field_ops.go` around lines 559 - 563, Update the rule length
handling in the incremental-number branch to distinguish an absent length from
an explicitly provided one: use the default value 3 only when length is absent,
and return a validation error for explicit values outside the documented 1..9
range, including 0 and values above 9. Preserve the existing system_number
response for valid lengths.


默认值 / 约束:
- `date_format` 可用:`yyyyMMdd`、`yyyyMM`、`yyMM`、`MMdd`、`yyyy`、`MM`、`dd`
- 开启 `+field-update --reformat-existing-records` 时优先用 `yyyyMMdd` 或 `yyyyMM`;`yyMM` 会被已有记录重排接口拒绝

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 | 🟡 Minor | ⚡ Quick win

Correct the existing-record regeneration statement.

The sentence at Line 423 says every auto-number update reapplies rules to existing values. Standard updates stay on the Base v3 endpoint and do not set reformat_existing_records. State that existing values are regenerated only with --reformat-existing-records.

🤖 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 `@skills/lark-base/references/lark-base-field-json.md` at line 476, Update the
existing-record regeneration statement in the auto-number update documentation
to clarify that values are regenerated only when `--reformat-existing-records`
is specified; standard updates use the Base v3 endpoint without setting
`reformat_existing_records`.

Comment on lines +56 to +58
```
PUT /open-apis/bitable/v1/apps/:base_token/tables/:table_id/fields/:field_id
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a language to the fenced block.

Markdownlint reports MD040 because this block has no language identifier.

Proposed fix
-```
+```text
 PUT /open-apis/bitable/v1/apps/:base_token/tables/:table_id/fields/:field_id
</details>

Based on static analysis, fenced code blocks must specify a language.

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.23.2)

[warning] 56-56: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 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 `@skills/lark-base/references/lark-base-field-update.md` around lines 56 - 58,
Add the text language identifier to the fenced code block containing the PUT
endpoint, changing the unlabeled fence to a text-labeled fence while preserving
the endpoint content.

Source: Linters/SAST tools

Comment on lines +37 to +40
require.Empty(t, strings.TrimSpace(result.Stdout), result.Stdout)
require.Equal(t, "validation", gjson.Get(result.Stderr, "error.type").String(), result.Stderr)
require.Equal(t, "--field-id", gjson.Get(result.Stderr, "error.param").String(), result.Stderr)
require.Contains(t, gjson.Get(result.Stderr, "error.message").String(), "--field-id is required")

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 | 🟡 Minor | ⚡ Quick win

Assert the validation subtype.

The test verifies error.type and error.param but omits error.subtype. Assert the expected invalid-argument subtype so the structured validation contract cannot regress to an arbitrary validation error.

As per coding guidelines, error-path tests must assert category, subtype, and parameter metadata.

🤖 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 `@tests/cli_e2e/base/base_field_dryrun_test.go` around lines 37 - 40, Update
the validation assertions in the base field dry-run test to also verify the
expected invalid-argument value of error.subtype, alongside the existing
error.type and error.param checks. Keep the assertion against the structured
result.StdErr payload and preserve the current message validation.

Source: Coding guidelines

Comment on lines +37 to +58
func TestBaseFieldUpdateAutoNumberReformatDryRun(t *testing.T) {
result := runBaseDryRun(t, 0,
"base", "+field-update",
"--base-token", "app_x",
"--table-id", "tbl_x",
"--field-id", "fld_x",
"--json", `{"name":"评分","type":"number","style":{"type":"rating","icon":"star","min":0,"max":20}}`,
"--json", `{"name":"编号","type":"auto_number","style":{"rules":[{"type":"text","text":"TASK-"},{"type":"created_time","date_format":"yyyyMM"},{"type":"text","text":"-"},{"type":"incremental_number","length":4}]}}`,
"--reformat-existing-records",
"--yes",
)

out := result.Stdout
require.Equal(t, "/open-apis/base/v3/bases/app_x/tables/tbl_x/fields/fld_x", gjson.Get(out, "data.api.0.url").String(), out)
require.Equal(t, "/open-apis/bitable/v1/apps/app_x/tables/tbl_x/fields/fld_x", gjson.Get(out, "data.api.0.url").String(), out)
require.Equal(t, "PUT", gjson.Get(out, "data.api.0.method").String(), out)
require.Equal(t, "评分", gjson.Get(out, "data.api.0.body.name").String(), out)
require.Equal(t, "rating", gjson.Get(out, "data.api.0.body.style.type").String(), out)
require.Equal(t, int64(20), gjson.Get(out, "data.api.0.body.style.max").Int(), out)
require.Equal(t, "编号", gjson.Get(out, "data.api.0.body.field_name").String(), out)
require.Equal(t, int64(1005), gjson.Get(out, "data.api.0.body.type").Int(), out)
require.True(t, gjson.Get(out, "data.api.0.body.property.auto_serial.reformat_existing_records").Bool(), out)
require.Equal(t, "fixed_text", gjson.Get(out, "data.api.0.body.property.auto_serial.options.0.type").String(), out)
require.Equal(t, "created_time", gjson.Get(out, "data.api.0.body.property.auto_serial.options.1.type").String(), out)
require.Equal(t, "system_number", gjson.Get(out, "data.api.0.body.property.auto_serial.options.3.type").String(), out)
require.Equal(t, "4", gjson.Get(out, "data.api.0.body.property.auto_serial.options.3.value").String(), out)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Add live E2E coverage for record reformatting.

This test only verifies the generated dry-run request. It cannot verify that the Bitable v1 endpoint accepts the payload or that existing auto-number values are regenerated correctly.

Add a self-contained live workflow that creates test data, changes the numbering rule with --reformat-existing-records, verifies affected record values, and cleans up.

As per coding guidelines, new behavior under tests/cli_e2e/**/*.go requires live E2E coverage with create, use, and cleanup steps.

🤖 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 `@tests/cli_e2e/base/base_field_update_dryrun_test.go` around lines 37 - 58,
Add a live E2E test alongside TestBaseFieldUpdateAutoNumberReformatDryRun that
creates a base, table, auto-number field, and records; invokes base field-update
with --reformat-existing-records and --yes using the changed numbering rule;
verifies the updated auto-number values through the live API or CLI; and
reliably cleans up all created resources. Keep the workflow self-contained and
follow existing live E2E create/use/cleanup patterns in tests/cli_e2e.

Source: Coding guidelines

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/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant