Skip to content

feat: v0.4.0 tool batch — labels/archive, attachments, draft revision, free-busy, event search#7

Merged
mabry1985 merged 1 commit into
mainfrom
feat/gmail-triage
Jul 3, 2026
Merged

feat: v0.4.0 tool batch — labels/archive, attachments, draft revision, free-busy, event search#7
mabry1985 merged 1 commit into
mainfrom
feat/gmail-triage

Conversation

@mabry1985

Copy link
Copy Markdown
Contributor

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=True removes INBOX. Posture guard: adding TRASH/SPAM is refused — hygiene yes, deletion never. Completes the triage loop mark-read started.
  • Attachmentsgmail_get_thread now surfaces attachments per message; gmail_get_attachment fetches one: text-y extensions return content (truncated), binaries save into the agent workspace (filename path-sanitized, collision-safe). Manifest filesystem capability updated from none to declare it.
  • Draft revisiongmail_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

…, 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>
@protoquinn

protoquinn Bot commented Jul 3, 2026

Copy link
Copy Markdown

👀 Quinn is reviewing — verdict (PASS / WARN / FAIL) + findings to follow.

@mabry1985 mabry1985 merged commit cced08d into main Jul 3, 2026
1 check passed
@mabry1985 mabry1985 deleted the feat/gmail-triage branch July 3, 2026 18:27

@protoquinn protoquinn Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_label declares TRASH/SPAM refusal and archive-via-INBOX-removal — correct Gmail semantics.
  • gmail_get_attachment uses os.path.basename() for path sanitization and message_id[:8] prefix for collision safety — both correct.

Observations

  • LOW: _TEXTY_EXTS includes .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

@protoquinn

protoquinn Bot commented Jul 3, 2026

Copy link
Copy Markdown

Submitted COMMENT review on #7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant