feat: v0.4.0 tool batch — labels/archive, attachments, draft revision, free-busy, event search#7
Merged
Merged
Conversation
…, free-busy, event search Gmail (still zero-consent, gmail.modify covers all): - gmail_label: add/remove labels BY NAME on messages or a thread; names resolve case-insensitively, missing add-labels are auto-created, archive=True removes INBOX; posture guard refuses adding TRASH/SPAM (never deletes or spams) - gmail_get_thread now lists attachments; gmail_get_attachment fetches one — text-y files return content, binaries save into the agent workspace (path-sanitized); manifest filesystem capability updated honestly - gmail_list_drafts + gmail_update_draft: find and rewrite a draft in place (headers + thread preserved) — still draft-only, never sends Calendar: - calendar_availability: freeBusy busy blocks over N days - calendar_search: text search across a past+future window 9 -> 15 tools; 56 tests (10 new) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
👀 Quinn is reviewing — verdict (PASS / WARN / FAIL) + findings to follow. |
There was a problem hiding this comment.
QA Audit — PR #7 | feat: v0.4.0 tool batch — labels/archive, attachments, draft revision, free-busy, event search
VERDICT: WARN (non-blocking — CI still queued, re-review on terminal green)
CI Status
- test: ⏳ queued
Diff Review
- 710-line diff across
README.md,__init__.py, and backend modules (gmail.py,gcal.py), plus tests. First 200 lines visible — 510 truncated. - Six new tools:
gmail_label,gmail_get_attachment,gmail_list_drafts,gmail_update_draft,calendar_availability,calendar_search. gmail_labeldeclares TRASH/SPAM refusal and archive-via-INBOX-removal — correct Gmail semantics.gmail_get_attachmentusesos.path.basename()for path sanitization andmessage_id[:8]prefix for collision safety — both correct.
Observations
- LOW:
_TEXTY_EXTSincludes.html/.htm— HTML attachments returned as raw text. Fine for an agent reader, but note that malicious HTML in phishing emails will be surfaced verbatim in the agent context. - LOW: TRASH/SPAM refusal enforcement lives in
gmail.modify_labels(truncated) — cannot verify the guard is implemented. - LOW: Draft header/thread preservation logic is in the truncated portion — cannot verify.
- LOW: Clawpatch structural review unavailable (checkout-cache 502 on SHA resolution).
- Gap: 510/710 diff lines unseen. Review confidence ~65%.
— Quinn, QA Engineer
|
Submitted COMMENT review on #7. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The zero-consent batch: every tool here runs on the scopes existing tokens already carry (
gmail.modify,calendar).Gmail
gmail_label(message_ids | thread_id, add, remove, archive)— labels by NAME (case-insensitive resolve via labels.list; missing add-labels auto-created),archive=Trueremoves INBOX. Posture guard: adding TRASH/SPAM is refused — hygiene yes, deletion never. Completes the triage loop mark-read started.gmail_get_threadnow surfacesattachmentsper message;gmail_get_attachmentfetches one: text-y extensions return content (truncated), binaries save into the agent workspace (filename path-sanitized, collision-safe). Manifestfilesystemcapability updated fromnoneto declare it.gmail_list_drafts+gmail_update_draft(drafts.update preserving To/Subject/In-Reply-To/References + threadId). "Soften that reply" now edits in place instead of duplicating. Still never sends.Calendar
calendar_availability(days)— freeBusy busy blocks; the agent derives free slots.calendar_search(query, days_back, days_ahead)— "when's the dentist?" across past + future.Test
56 passed (10 new: name-resolution/auto-create/batch body, TRASH refusal, unknown-remove hint, archive flag, attachment listing + text-vs-binary + path sanitization, draft list/update header+thread preservation, freeBusy shape, search params), ruff clean, host-free.
Version → 0.4.0.
🤖 Generated with Claude Code