Skip to content

fix(sheets): correct Connected Sheets sheet identity and SYNC_ALL extract reads - #1001

Merged
steipete merged 4 commits into
openclaw:mainfrom
ryo-touch:fix/connected-sheets-read-live-findings
Aug 23, 2026
Merged

fix(sheets): correct Connected Sheets sheet identity and SYNC_ALL extract reads#1001
steipete merged 4 commits into
openclaw:mainfrom
ryo-touch:fix/connected-sheets-read-live-findings

Conversation

@ryo-touch

Copy link
Copy Markdown
Contributor

Refs #938

Live validation of the read-only Connected Sheets surface from #989, against a real set of
BigQuery-backed spreadsheets, surfaced two defects. Both are invisible to the current tests
because the fixture does not match what the API actually returns.

Summary

  • resolve a data source's linked sheet by data source id, and treat that sheet's own id as
    authoritative, so sheets datasource list stops reporting sheetId: 0
  • fall back to an unranged, properties-only fetch when a ranged spreadsheets.get cannot supply
    an extract's column count, which unblocks every SYNC_ALL extract
  • make the fixture server range-aware and drop dataSources[].sheetId from the fixture, so both
    paths are exercised the way the live API behaves

Details

datasource list always reported sheetId: 0. Live spreadsheets.get responses do not
populate Spreadsheet.dataSources[].sheetId; it comes back null. sheetsDataSourceToItem emitted
source.SheetId directly. The correct id is already available on the matched sheet, and
datasource table list uses it, so the two code paths now agree.

That same zero value also made findSheetsDataSourceSheet unsafe: it compared
properties.SheetId == source.SheetId before checking the data source id, so in a spreadsheet
containing a tab with sheet id 0, every data source would match that unrelated tab and report its
title and dataExecutionStatus. I could not reproduce this in practice — none of the 59
spreadsheets I scanned has a tab with sheet id 0 — so I am flagging it as latent rather than
observed. The ordering is wrong either way.

datasource table read failed for every SYNC_ALL extract. A SYNC_ALL table carries no
inline column list, so the column count has to come from dataSourceSheetProperties on the
associated DATA_SOURCE sheet. The anchor lookup passes ranges, and a ranged spreadsheets.get
returns only the sheets those ranges intersect, which excludes the DATA_SOURCE sheet:

ranges absent  -> grid sheets + DATA_SOURCE sheets
ranges present -> the anchor's grid sheet only

So dataSourceColumnCount found nothing and the command exited with
cannot determine columns for data-source table.

Proof

  • make ci
  • go test ./internal/cmd -run 'TestSheetsDataSource' -count=1 -v
  • both new assertions were confirmed to fail before their corresponding fix: the sheet-identity
    test reports the decoy tab, and the SYNC_ALL read test reproduces the exact
    cannot determine columns error

Live validation was read-only throughout (--readonly on every invocation; no spreadsheet was
modified):

before after
data sources resolving a real linked sheet id 0 / 56 56 / 56
extracts readable via datasource table read 0 / 54 54 / 54

Corpus: 59 spreadsheets scanned, 21 with Connected Sheets, 54 anchored extracts. Every extract in
it uses SYNC_ALL; there was not a single SELECTED extract, which is why this path failing was
total rather than partial.

Two notes:

  • the SYNC_ALL fallback costs a second spreadsheets.get on that path. Reading all 54 extracts
    back to back tripped Sheets rate limits a few times; pacing the loop cleared it. Worth knowing
    before scripting bulk extract reads.
  • docs/sheets-connected.md presents --extra-scopes .../bigquery.readonly --force-consent as a
    required step. It is not required when the stored token already carries a superset: all of the
    above ran on a token holding cloud-platform and spreadsheets, with no re-consent. That may
    be a cheaper route to a live Connected Sheets environment than provisioning the exact scopes.

ryo-touch and others added 2 commits August 17, 2026 14:10
…ce id

Live spreadsheets.get responses omit Spreadsheet.dataSources[].sheetId, so
`sheets datasource list` reported sheetId 0 for every data source, and the
sheet lookup could latch onto an unrelated tab whose sheet id happens to be 0
and report that tab's title and execution status instead.

Match the linked sheet on its data source id first, fall back to the sheet id
only when the API actually supplied one, and treat the resolved sheet's own id
as authoritative, mirroring what the extract listing already does.

The fixture hardcoded dataSources[].sheetId, which no live response carries;
drop it and add a decoy tab with sheet id 0 so the regression stays covered.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A ranged spreadsheets.get only returns the sheets its ranges intersect, so the
anchor lookup never carries the separate DATA_SOURCE sheet that holds a
SYNC_ALL table's column list. Every extract configured to sync all columns
failed with "cannot determine columns for data-source table".

Fall back to an unranged, properties-only fetch when the ranged response cannot
supply the column count.

The fixture server returned the whole spreadsheet regardless of ranges, and its
only extract used SELECTED columns, so neither half of this path was exercised.
Make the fixture server range-aware and add a SYNC_ALL extract.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@clawsweeper

clawsweeper Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. 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. labels Aug 17, 2026
@clawsweeper

clawsweeper Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed August 22, 2026, 9:30 AM ET / 13:30 UTC.

ClawSweeper review

What this changes

The PR fixes Connected Sheets data-source identity resolution and adds a narrow metadata fetch so SYNC_ALL extracts can be read, with regression fixtures and user guidance.

Regression provenance

Possible regression — probable (reproduction; reviewed change; known regression link). No predecessor PR is attributed.

Merge readiness

Ready for maintainer review

This PR remains necessary: current main still mis-resolves an omitted data-source sheet ID and cannot read SYNC_ALL extracts whose columns live on a separate DATA_SOURCE sheet. The focused patch has no actionable correctness or security finding and is ready for maintainer review.

Priority: P2
Reviewed head: 4d8b7d6467f659f6834a140c214db4c6bc9617ad

Review scores

Measure Result What it means
Overall readiness 🦞 diamond lobster (5/6) The patch is focused, regression-tested, and supported by substantive read-only provider validation.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (live_output): The PR body supplies read-only live validation with before/after outcomes for both repaired Sheets API paths.
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 supplies read-only live validation with before/after outcomes for both repaired Sheets API paths.
Evidence reviewed 5 items Current-main SYNC_ALL failure: Current main returns cannot determine columns immediately when the range-scoped response lacks the linked DATA_SOURCE sheet, with no fallback metadata fetch.
Current-main identity defect: Current main compares SheetId before DataSourceId; an omitted API sheetId becomes zero and can select an unrelated first tab.
Focused repair and regression coverage: The branch first retries only missing column metadata, resolves sheets by data-source ID before a nonzero ID fallback, and adds SYNC_ALL plus decoy-sheet regression cases.
Findings None None.
Security None None.

Live Verification

Command: go test ./internal/cmd -run 'TestSheetsDataSource' -count=1 -v

Result: FAIL (failed) — execution before step 1 run: sh -lc pnpm install --ignore-scripts --frozen-lockfile failed: ! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-11.22.0.tgz

sh -lc pnpm install --ignore-scripts --frozen-lockfile failed: ! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-11.22.0.tgz

Assertions:

  • FAIL expect_output: PASS

How this fits together

Connected Sheets commands fetch spreadsheet metadata and extract anchors from the Sheets API, then derive a bounded values range for CLI output. The linked data-source sheet supplies identity, status, and sometimes the column count needed for that read.

flowchart LR
  A[Google spreadsheet] --> B[Connected Sheets metadata]
  B --> C[Linked data-source sheet]
  B --> D[Extract anchor]
  C --> E[Column count]
  D --> E
  E --> F[Bounded values read]
  F --> G[CLI JSON or table output]
Loading

Before merge

None.

Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Implementation versus coverage production +39 net, docs +2, tests/fixtures +208 net Most of the change is focused regression coverage for the two live API behaviors being corrected.
Live validation corpus 59 spreadsheets; 56/56 identities and 54/54 extracts after fix The supplied read-only provider evidence covers both repaired command paths beyond the fixture.

Technical review

Best possible solution:

Merge the targeted compatibility repair with its regression coverage and the documented pacing guidance for bulk SYNC_ALL reads.

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

Yes—source inspection gives a high-confidence path: a range-scoped lookup omits the DATA_SOURCE sheet needed for SYNC_ALL column counting, and current main returns an error. The PR fixture directly models that path.

Is this the best way to solve the issue?

Yes—the branch keeps the existing CLI contract, uses the API's data-source ID as the primary identity, and requests only missing column metadata when needed.

AGENTS.md: found and applied where relevant.

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

Labels

Label justifications:

  • P2: Connected Sheets reads can report a wrong linked sheet or fail SYNC_ALL extracts, but the affected surface is specialized.
  • 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 supplies read-only live validation with before/after outcomes for both repaired Sheets API paths.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body supplies read-only live validation with before/after outcomes for both repaired Sheets API paths.

Evidence

What I checked:

  • Current-main SYNC_ALL failure: Current main returns cannot determine columns immediately when the range-scoped response lacks the linked DATA_SOURCE sheet, with no fallback metadata fetch. (internal/cmd/sheets_datasource.go:293, ab7e0ed706f9)
  • Current-main identity defect: Current main compares SheetId before DataSourceId; an omitted API sheetId becomes zero and can select an unrelated first tab. (internal/cmd/sheets_datasource.go:426, ab7e0ed706f9)
  • Focused repair and regression coverage: The branch first retries only missing column metadata, resolves sheets by data-source ID before a nonzero ID fallback, and adds SYNC_ALL plus decoy-sheet regression cases. (internal/cmd/sheets_datasource.go:293, 4d8b7d6467f6)
  • Feature-history provenance: The examined current-main files were last changed by the v0.37.0 release commit; the underlying Connected Sheets read feature was merged earlier from the identified feature PR. (internal/cmd/sheets_datasource.go:267, 45b5d766e137)
  • After-fix provider proof: The PR body records read-only validation over 59 spreadsheets, improving linked-sheet resolution from 0/56 to 56/56 and SYNC_ALL extract reads from 0/54 to 54/54. (4d8b7d6467f6)

Likely related people:

  • steipete: Merged the Connected Sheets read surface whose current-main implementation this PR repairs. (role: merged feature author; confidence: high; commits: a4c96debef00, 45b5d766e137; files: internal/cmd/sheets_datasource.go, internal/cmd/sheets_datasource_test.go, docs/sheets-connected.md)

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 (2 earlier review cycles)
  • reviewed 2026-08-17T05:20:59.299Z sha ccc98ef :: needs maintainer review before merge. :: none
  • reviewed 2026-08-17T05:47:45.928Z sha 4d8b7d6 :: needs maintainer review before merge. :: none

ryo-touch and others added 2 commits August 17, 2026 14:42
The unranged fallback added for SYNC_ALL extracts reused the full snapshot
field mask, which also pulls dataSources and dataSourceSchedules even though
only the data-source sheet column definitions are needed. Request just those
columns so the extra call stays small, and describe the call and its pacing
implications in the Connected Sheets guide.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Add a direct table-driven test for findSheetsDataSourceSheet: the fixture no
longer supplies dataSources[].sheetId, so neither the data-source-id-first
ordering nor the sheet-id fallback was exercised through the command surface.

Assert how often the unranged column lookup fires — once for a SYNC_ALL
extract, never for a SELECTED one. Running it unconditionally would not just
cost a request; it would also overwrite a SELECTED table's own column count
and widen the read range.

Also stop calling t.Fatalf from the fixture server's handler goroutine, where
runtime.Goexit turns an assertion into a confusing handler abort, and drop a
redundant PathUnescape: net/http already decodes r.URL.Path, so re-decoding
would reject sheet names containing '%'.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@steipete
steipete merged commit c4952a2 into openclaw:main Aug 23, 2026
7 checks passed
@ryo-touch
ryo-touch deleted the fix/connected-sheets-read-live-findings branch August 24, 2026 00:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. 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