Google Docs can hold a tree of tabs, each with its own body and its own
1-based character index space; the legacy top-level `body` only carries
the first tab. `docs get` was silently dropping every other tab's
content, and `docs append` computed its insert index from the first
tab's body and sent the write with no tabId — so on a tabbed doc the
append could land at a wrong offset in the wrong tab.
- Requests now pass includeTabsContent=true (both gws and SDK paths).
- `docs get` returns a `tabs` array (preorder flattening of the
tabs/childTabs tree, nested tabs included); single-tab docs keep the
`body` field so existing callers work, and `--tab <tabId>` reads one
tab. Legacy no-tabs responses are unchanged.
- `docs append` targets exactly one tab: the insert location carries
the tabId, the end index is computed inside that tab's own body, an
unknown `--tab` errors instead of falling back to the first tab, and
a multi-tab doc without `--tab` errors with the tab list rather than
guessing. Tabs are never merged — index spaces are independent.
Adapted from cloudflare/cloudflare-os#450 (gatekeeper-google), which
fixed the same provider behavior: reads must traverse Document.tabs and
every write Location must carry the immutable tabId.
Two pre-existing bare read_text/write_text in the touched test file
gained encoding="utf-8" (windows-footgun sweep rule).