Skip to content

fix(sheets): never write outside the requested range on positional updates - #941

Merged
steipete merged 5 commits into
openclaw:mainfrom
cathrynlavery:fix/sheets-comma-split
Aug 2, 2026
Merged

fix(sheets): never write outside the requested range on positional updates#941
steipete merged 5 commits into
openclaw:mainfrom
cathrynlavery:fix/sheets-comma-split

Conversation

@cathrynlavery

@cathrynlavery cathrynlavery commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Problem

gog sheets update <id> "G31" "text, with, commas" parses the positional value as comma-separated rows, so a single-cell write fans out down the column and silently overwrites neighboring cells. We hit this in production against a live tracker sheet.

Fix

  • When the target range resolves to a single cell, the positional value is written literally — commas and pipes are never treated as separators.
  • For finite multi-cell ranges, the parsed matrix is validated against maximum bounds: only payloads whose rows or columns EXCEED the range are rejected (loudly, before the Values API call). Matrices smaller than the range pass through unchanged, preserving the partial-write behavior current main and the Values API support (review round 2 — thanks, the exact-equality check in round 1 was indeed a compatibility regression).
  • Named ranges resolve through the existing range catalog before shape checks. --values-json and append behavior unchanged.
  • links set --cells-json now accepts @file and @- (stdin), matching its sibling flags; docs updated.

Real behavior proof (redacted)

Built from this branch (v0.34.2-0.20260727222104+dirty), run against a disposable test spreadsheet created for this proof; spreadsheet ID redacted:

$ gog sheets update <SHEET_ID> "A1" "text, with, commas"   # single cell, comma-bearing value
Updated 1 cells in 'gog-pr941-proof-disposable'!A1

$ gog sheets get <SHEET_ID> "A1:A3"   # A1 literal, neighbors untouched
text, with, commas

$ gog sheets update <SHEET_ID> "A1:B2" "r1a|r1b,r2a|r2b,r3a|r3b"   # 3 rows into 2-row range -> must reject BEFORE API call
positional values have 3 rows, which exceeds the update range maximum of 2 rows
exit: 2

$ gog sheets update <SHEET_ID> "C1:D2" "only-one-value"   # partial write within larger finite range -> must succeed (P1 compat)
Updated 1 cells in 'gog-pr941-proof-disposable'!C1

$ gog sheets get <SHEET_ID> "C1:D2"
only-one-value

All three review asks demonstrated live: (1) comma-containing single-cell update lands literally in exactly one cell with neighbors untouched, (2) oversize payload rejected before the API call (exit 2), (3) partial positional write within a larger finite range succeeds — the P1 case.

Tests

go test ./internal/sheetsvalues, go test ./internal/cmd -run 'TestSheetsUpdatePositional|TestSheetsLinksSet', and go test ./... all green (42 packages). New coverage: TestSheetsUpdatePositionalPartialMultiCellRangeWritesOneCell (asserts the recorder receives exactly [["one"]]), TestParseArgsForShapeAllowsSmallerMatrix, TestParseArgsForShapeRejectsExceedingRangeBounds, plus the existing single-cell literal and zero-write-on-error assertions.

…dates

- single-cell ranges preserve the positional value literally (commas and
  pipes are no longer treated as row/cell separators), fixing silent
  overwrite of neighboring live cells
- multi-cell positional updates validate parsed shape against the range
  and error loudly on mismatch instead of fanning out past the range
- links set --cells-json now accepts @file and @- like its sibling flags
- command-level HTTP recorder tests prove request bodies and that no
  update call is issued on shape errors
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 Urgent regression or broken agent/channel workflow affecting real users now. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. labels Jul 27, 2026
@clawsweeper

clawsweeper Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed August 2, 2026, 3:57 AM ET / 07:57 UTC.

ClawSweeper review

What this changes

The branch makes positional Google Sheets updates range-aware, preserving comma-bearing single-cell text, rejecting finite-range overflow before the Values API update, resolving named ranges for live validation, and accepting @file or @- for links set --cells-json.

Merge readiness

⚠️ Ready for maintainer review - 2 items remain

This PR is still necessary: current main still splits positional Sheet values on commas and pipes without considering the requested range, while the final branch preserves literal single-cell text and rejects only matrices that exceed finite range bounds. The prior named-range dry-run blocker is resolved by the maintainer-authored follow-up, and the supplied redacted live transcript covers the overwrite, overflow rejection, and partial-write compatibility cases.

Priority: P1
Reviewed head: 26d982231a052ee566dfb28c322a0c199f6570fa

Review scores

Measure Result What it means
Overall readiness 🦞 diamond lobster (5/6) The final branch is focused, cleanly mergeable, backed by targeted regression coverage, and supported by direct redacted live behavior proof.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (live_output): The PR body provides a redacted branch-built live Sheets transcript showing literal single-cell handling, an exit-2 overflow rejection before the update call, and a successful partial write; it directly covers the changed behavior.
Patch quality 🦞 diamond lobster (5/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (live_output): The PR body provides a redacted branch-built live Sheets transcript showing literal single-cell handling, an exit-2 overflow rejection before the update call, and a successful partial write; it directly covers the changed behavior.
Evidence reviewed 6 items Current-main defect: Current main sends positional values through sheetsvalues.ParseArgs, which unconditionally splits commas into rows and pipes into cells; it has no target-range shape check before Values.Update.
Final range-aware implementation: The PR parses resolvable A1 ranges with shape bounds, resolves named ranges against spreadsheet metadata before the live write, and rejects unresolved positional named-range dry runs rather than emitting an inaccurate preview.
Compatibility behavior is covered: ParseArgsForShape treats a 1×1 range as one literal value, permits matrices smaller than finite bounds, and rejects only rows or cells exceeding those bounds; focused command and parser tests cover the single-cell, named-range, partial-write, and no-write-on-overflow paths.
Findings None None.
Security None None.

How this fits together

The Sheets CLI converts positional or JSON input into a matrix sent to the Google Sheets Values API. This patch changes the positional-input path between range parsing and the update request so the payload cannot silently extend outside a finite target range.

flowchart LR
  Input[CLI range and positional values] --> Parse[Parse positional matrix]
  Parse --> Range[A1 or named-range resolution]
  Range --> Bounds[Validate finite range bounds]
  Bounds --> Preview[Offline dry-run or live request]
  Preview --> API[Google Sheets Values API]
  API --> Result[Updated spreadsheet cells]
Loading

Before merge

  • Resolve merge risk (P1) - Existing scripts that preview positional updates to named or otherwise unresolved ranges with --dry-run will now receive exit code 2 instead of a delimiter-split preview; the maintainer explicitly selected this fail-safe behavior to preserve the no-network dry-run contract.
  • Complete next step (P2) - No discrete repair remains for automation: the prior blocker is fixed and this PR is ready for normal maintainer landing review.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Patch scope 9 files; 426 added, 14 removed The implementation is concentrated in Sheets command parsing, the shared value parser, focused tests, and matching command documentation.
Range-safety proof 3 live scenarios The supplied redacted transcript demonstrates the literal single-cell case, pre-write overflow rejection, and preserved partial-write behavior.

Merge-risk options

Maintainer options:

  1. Land with the explicit dry-run contract (recommended)
    Merge the branch with the documented exit-2 behavior for positional named-range dry runs, which avoids an inaccurate offline preview while preserving supported A1 and --values-json paths.
  2. Pause for a different preview design
    Do not merge if maintainers want positional named-range dry runs to remain successful; that would require a separately designed offline representation rather than reintroducing delimiter-split output.

Technical review

Best possible solution:

Merge the focused range-aware positional parsing change and retain the explicit named-range dry-run refusal, while documenting that scripts needing an offline named-range preview should use A1 notation or --values-json.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main's positional parser splits commas and pipes without inspecting the requested range, and the supplied live transcript demonstrates the resulting single-cell overwrite scenario plus the fixed behavior on the branch.

Is this the best way to solve the issue?

Yes. Range-aware validation at the positional parsing boundary is the narrowest maintainable fix: it preserves the existing delimiter syntax for multi-cell updates, allows smaller valid matrices, and stops only writes that exceed finite bounds.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 3c9466af5171.

Labels

Label justifications:

  • P1: The patch addresses a reported live Sheets workflow that can silently overwrite neighboring cells.
  • merge-risk: 🚨 compatibility: The PR intentionally changes positional range validation and named-range dry-run behavior for existing scripts.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body provides a redacted branch-built live Sheets transcript showing literal single-cell handling, an exit-2 overflow rejection before the update call, and a successful partial write; it directly covers the changed behavior.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body provides a redacted branch-built live Sheets transcript showing literal single-cell handling, an exit-2 overflow rejection before the update call, and a successful partial write; it directly covers the changed behavior.

Evidence

What I checked:

  • Current-main defect: Current main sends positional values through sheetsvalues.ParseArgs, which unconditionally splits commas into rows and pipes into cells; it has no target-range shape check before Values.Update. (internal/cmd/sheets.go:206, 3c9466af5171)
  • Final range-aware implementation: The PR parses resolvable A1 ranges with shape bounds, resolves named ranges against spreadsheet metadata before the live write, and rejects unresolved positional named-range dry runs rather than emitting an inaccurate preview. (internal/cmd/sheets.go:196, 26d982231a05)
  • Compatibility behavior is covered: ParseArgsForShape treats a 1×1 range as one literal value, permits matrices smaller than finite bounds, and rejects only rows or cells exceeding those bounds; focused command and parser tests cover the single-cell, named-range, partial-write, and no-write-on-overflow paths. (internal/sheetsvalues/values.go:65, 26d982231a05)
  • Prior finding resolved by feature-history owner: The maintainer follow-up commit introduces the named-range positional dry-run refusal that keeps the no-network preview contract accurate; the supplied discussion records the intended exit-2 behavior and successful focused/full validation. (internal/cmd/sheets.go:225, 2c888627c72c)
  • Clean merge result: A three-way merge of the PR head with current main produces merged results for all nine changed paths without conflicts; the final diff also passes Git whitespace checks. (internal/cmd/sheets.go:196, 26d982231a05)
  • Feature provenance: History shows Peter Steinberger extracted the Sheets value parser, and current-main blame attributes the command path to the current release snapshot; this is the strongest available ownership trail for the touched command and parser surfaces. (internal/sheetsvalues/values.go:46, 47cb3c6b3058)

Likely related people:

  • steipete: Feature history attributes the extraction of the Sheets value parser to Peter Steinberger, current-main blame attributes the command path to the release snapshot, and he authored the final named-range dry-run correction on this branch. (role: Sheets parser and command-path owner; confidence: high; commits: 47cb3c6b3058, 4747fb05a429, 2c888627c72c; files: internal/cmd/sheets.go, internal/sheetsvalues/values.go, internal/cmd/sheets_range_resolve.go)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (21 earlier review cycles; latest 8 shown)
  • reviewed 2026-08-01T11:54:33.119Z sha 0bee84d :: needs changes before merge. :: [P2] Keep named-range dry runs consistent with the write
  • reviewed 2026-08-01T13:12:19.116Z sha 0bee84d :: needs changes before merge. :: [P2] Keep named-range dry runs consistent with the write
  • reviewed 2026-08-01T14:53:06.598Z sha 0bee84d :: needs changes before merge. :: [P2] Reject unresolved named-range dry-run previews
  • reviewed 2026-08-01T15:18:15.847Z sha 0bee84d :: needs changes before merge. :: [P2] Reject unresolved named-range dry-run previews
  • reviewed 2026-08-02T02:41:17.889Z sha 0bee84d :: needs changes before merge. :: [P2] Keep named-range dry runs consistent with the write
  • reviewed 2026-08-02T05:38:31.111Z sha 2c88862 :: needs maintainer review before merge. :: none
  • reviewed 2026-08-02T07:14:06.220Z sha 2c88862 :: needs maintainer review before merge. :: none
  • reviewed 2026-08-02T07:51:03.542Z sha 93da4f4 :: needs maintainer review before merge. :: none

… range

Address review: finite-range validation now rejects only matrices that
EXCEED the range's row/column bounds instead of requiring exact shape
equality. Partial positional updates (e.g. one value into Sheet1!A1:B2),
which current main and the Values API support, pass through unchanged.
Single-cell literal preservation and the pre-API oversize rejection are
unchanged. Regression tests added for the partial-write case and for
row/column overflow.
@cathrynlavery

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Both blockers addressed in 0bee84d: finite-range validation is now max-bounds (partial writes within a larger finite range pass; only genuine overflow rejects), and the PR body now carries a redacted live-Sheets transcript from a branch-built binary covering the protected, rejected, and partial-write cases. Full suite green.

@clawsweeper

clawsweeper Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 29, 2026
@steipete

steipete commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

Maintainer follow-up: I fixed the remaining named-range dry-run mismatch on the contributor branch in 2c88862.

Positional updates to named or otherwise unresolved ranges now refuse an offline --dry-run preview with exit code 2 and direct users to A1 notation or --values-json. This preserves the repository's no-network dry-run contract while preventing a preview from showing delimiter-split values that the live named-range path would later reinterpret. Shape-independent --values-json named-range previews remain supported.

I also cleared the branch's five lint failures in the touched code/tests.

Proof:

  • go test ./internal/cmd -run 'TestSheetsUpdatePositional|TestSheetsLinksSet' — pass
  • go test ./internal/sheetsvalues — pass
  • Built CLI: named-range positional dry-run exits 2; A1 single-cell dry-run exits 0 and preserves the full comma-bearing value; named-range --values-json exits 0; finite-range overflow exits 2
  • Source-blind behavior contract — all clauses and anti-cheat probes pass
  • make ci — pass (format, lint, deadcode, all Go/Node tests, docs, generated skills)
  • Autoreview — clean, no accepted/actionable findings

This clears the concrete review blocker. My recommendation is LAND: the branch fixes a live-proven neighboring-cell overwrite, preserves partial-write compatibility, and now has accurate dry-run behavior.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Aug 2, 2026
@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Aug 2, 2026
@steipete
steipete merged commit a1637ea into openclaw:main Aug 2, 2026
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P1 Urgent regression or broken agent/channel workflow affecting real users now. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants