From 487f8405966c5f45b1ed9964ae78c81e7a0fbed5 Mon Sep 17 00:00:00 2001 From: Vojtech Rysanek Date: Thu, 21 May 2026 18:21:33 +0400 Subject: [PATCH] =?UTF-8?q?fix(web):=20GWS=20verify=20step=20=E2=80=94=20d?= =?UTF-8?q?rop=20fragile=20JSON-parse=20+=20add=20anti-footgun=20guidance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Step 8 of the Google Workspace connector prompt told Claude to call `gws drive files list` + `gws chat spaces list` and parse counts out of the JSON response. In practice Claude improvised a `python3 -c 'f"… {len(d.get(\"files\",[]))}…"'` snippet that fails in two ways: f-string expressions reject backslashes pre-3.12 (SyntaxError), and gws can emit a banner ahead of the JSON body (JSONDecodeError on `json.load(sys.stdin)`). Treat exit code 0 from each gws call as success, drop the ` drive file(s), chat space(s) visible` counts (consistent with the Step 0 precheck), and explicitly warn off the two anti-patterns. Summary-grep prefix `✅ Google Workspace ready —` is preserved so the install-summary still picks the line up. --- CHANGELOG.md | 10 ++++++++++ app/web/connector_prompts.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 584c6a7..afcab69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,6 +87,16 @@ CalVer image tags (`stable-YYYY.MM.N`, `dev-YYYY.MM.N`) are produced for every C standard step-lede size instead of the previous 13px chip. ### Fixed +- Google Workspace connector prompt's Step 8 verify no longer asks + Claude to parse a row count out of `gws drive files list` / `gws + chat spaces list` JSON. Claude would improvise a `python3 -c 'f"… + {len(d.get(\"files\",[]))}…"'` snippet that fails two ways: f-string + expressions reject backslashes in Python <3.12 (`SyntaxError`), and + `gws` can emit a banner before the JSON body (`json.JSONDecodeError`). + Step 8 now treats exit code 0 as success, drops the ` drive + file(s), chat space(s) visible` counts, and explicitly warns + against both anti-patterns. The summary-grep prefix (`✅ Google + Workspace ready —`) is preserved. - Install-script Step 2 + Step 9 restart cue + post-install `/home` hero now reference `~/Desktop/` to match the `/home` "Step 2 — pick a folder" recommendation users actually run (`mkdir -p diff --git a/app/web/connector_prompts.py b/app/web/connector_prompts.py index 971388f..21e3232 100644 --- a/app/web/connector_prompts.py +++ b/app/web/connector_prompts.py @@ -343,7 +343,7 @@ _GWS_PROMPT_TAIL_TEMPLATE = """ 7. Find where gws stored my credentials (`gws auth status` should show the path; typically ~/.config/gws/ on Unix, %APPDATA%\\gws\\ on Windows). chmod 600 on Unix; on native Windows, restrict ACLs to my user with `icacls "$creds_path" /inheritance:r /grant:r "$env:USERNAME:F"` — file is already in my user profile so this needs no admin. -8. Verify with two low-impact reads, one per scope group: `gws drive files list --params '{{"pageSize": 1}}'` (Drive scope landed) and `gws chat spaces list --params '{{"pageSize": 1}}'` (Chat scope landed). If both return 200 with valid JSON, print `✅ Google Workspace ready — connected as . drive file(s), chat space(s) visible.` (exact prefix — the final summary grep for it). On any failure, print `❌ Google Workspace setup failed: , HTTP/status . .` and stop. Never echo tokens, file/message metadata, or scope strings to chat. +8. Verify with two low-impact reads, one per scope group: `gws drive files list --params '{{"pageSize": 1}}'` (Drive scope landed) and `gws chat spaces list --params '{{"pageSize": 1}}'` (Chat scope landed). Treat exit code 0 from each invocation as success — do NOT pipe gws output into `python3 -c 'f"..."'` (f-string expressions reject backslashes in Python <3.12, so escaping `\\"files\\"` inside a shell-quoted f-string raises SyntaxError) and do NOT call `json.load(sys.stdin)` on the raw stream (gws may emit log lines or a banner before the JSON body, which trips `JSONDecodeError`). If you really need to count rows for diagnostics, write the stdout to a temp file first and parse it with a plain `json.loads(open(path).read())` inside a `try/except`. If both calls exit 0, print `✅ Google Workspace ready — connected as . Drive + Chat scopes verified.` (exact prefix — the final summary grep for it). On any failure, print `❌ Google Workspace setup failed: , exit . .` and stop. Never echo tokens, file/message metadata, or scope strings to chat. 9. Remind me how to revoke later: `gws auth logout` clears local creds; the OAuth grant also appears at https://myaccount.google.com/permissions for Google-side revocation."""