fix(sheets): correct Connected Sheets sheet identity and SYNC_ALL extract reads - #1001
fix(sheets): correct Connected Sheets sheet identity and SYNC_ALL extract reads#1001ryo-touch wants to merge 4 commits into
Conversation
…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>
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: needs maintainer review before merge. Reviewed August 17, 2026, 1:47 AM ET / 05:47 UTC. ClawSweeper reviewWhat this changesThis PR resolves a Connected Sheet by data-source ID and fetches unscoped column metadata when a SYNC_ALL extract lacks inline columns. Merge readiness✅ Ready for maintainer review Keep open: current main still has both Connected Sheets read defects, while this focused PR supplies a source-aligned fix, regression coverage, and credible live after-fix validation. No blocking patch finding was identified. Priority: P2 Review scores
Verification
How this fits togetherThe Sheets CLI queries Google Sheets metadata to list Connected Sheets data sources and locate extract anchors before issuing a bounded values read. The linked data-source sheet supplies status and, for SYNC_ALL extracts, the column definitions needed to form that read. flowchart LR
A[Sheets CLI command] --> B[Google Sheets metadata]
B --> C[Linked data-source sheet]
C --> D[Extract column count]
D --> E[Bounded values request]
E --> F[CLI JSON or table output]
Before mergeNone. Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Land the scoped fix after required checks complete, retaining the additional metadata request only for extracts whose range-scoped response cannot provide columns. Do we have a high-confidence way to reproduce the issue? Yes—current main visibly lacks the SYNC_ALL metadata fallback and uses the absent top-level sheet ID before data-source identity; the branch adds focused fixtures for both paths and reports live before/after validation. Is this the best way to solve the issue? Yes—the conditional, properties-only fallback preserves SELECTED extract behavior while obtaining the one missing metadata value for SYNC_ALL extracts. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against eb85a99366eb. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (1 earlier review cycle)
|
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>
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
authoritative, so
sheets datasource liststops reportingsheetId: 0spreadsheets.getcannot supplyan extract's column count, which unblocks every
SYNC_ALLextractdataSources[].sheetIdfrom the fixture, so bothpaths are exercised the way the live API behaves
Details
datasource listalways reportedsheetId: 0. Livespreadsheets.getresponses do notpopulate
Spreadsheet.dataSources[].sheetId; it comes back null.sheetsDataSourceToItememittedsource.SheetIddirectly. The correct id is already available on the matched sheet, anddatasource table listuses it, so the two code paths now agree.That same zero value also made
findSheetsDataSourceSheetunsafe: it comparedproperties.SheetId == source.SheetIdbefore checking the data source id, so in a spreadsheetcontaining 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 59spreadsheets 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 readfailed for everySYNC_ALLextract. ASYNC_ALLtable carries noinline column list, so the column count has to come from
dataSourceSheetPropertieson theassociated
DATA_SOURCEsheet. The anchor lookup passesranges, and a rangedspreadsheets.getreturns only the sheets those ranges intersect, which excludes the
DATA_SOURCEsheet:So
dataSourceColumnCountfound nothing and the command exited withcannot determine columns for data-source table.Proof
make cigo test ./internal/cmd -run 'TestSheetsDataSource' -count=1 -vtest reports the decoy tab, and the SYNC_ALL read test reproduces the exact
cannot determine columnserrorLive validation was read-only throughout (
--readonlyon every invocation; no spreadsheet wasmodified):
datasource table readCorpus: 59 spreadsheets scanned, 21 with Connected Sheets, 54 anchored extracts. Every extract in
it uses
SYNC_ALL; there was not a singleSELECTEDextract, which is why this path failing wastotal rather than partial.
Two notes:
SYNC_ALLfallback costs a secondspreadsheets.geton that path. Reading all 54 extractsback to back tripped Sheets rate limits a few times; pacing the loop cleared it. Worth knowing
before scripting bulk extract reads.
docs/sheets-connected.mdpresents--extra-scopes .../bigquery.readonly --force-consentas arequired step. It is not required when the stored token already carries a superset: all of the
above ran on a token holding
cloud-platformandspreadsheets, with no re-consent. That maybe a cheaper route to a live Connected Sheets environment than provisioning the exact scopes.