feat: add YAML frontmatter to deploy skill
This commit is contained in:
+598
-23
@@ -1,28 +1,603 @@
|
||||
# deploy
|
||||
---
|
||||
name: deploy
|
||||
description: >
|
||||
Activates approved rules from the Tracker in Gmail. Use when the user says "deploy the
|
||||
rules", "turn on the rules", "make the rules live", "activate my Gmail rules", "set up the
|
||||
filters", or "I'm ready to go live". Implements gmail_filter_safe rules via Google Workspace
|
||||
MCP directly, walks the user through installing apps_script_needed rules via Google Apps
|
||||
Script with a step-by-step walkthrough, and parks studio_candidate rules for future use.
|
||||
Also creates the "! Rule Needed" label on first deploy. Runs after import approves rules.
|
||||
Part of the Gmail Inbox Architect plugin.
|
||||
---
|
||||
|
||||
## Trigger
|
||||
Use this skill when approved rules are ready to be implemented in Gmail, the user says
|
||||
"deploy the rules", "create the filters", "let's push this batch", or a specific rule
|
||||
set has been approved through the `import` review process.
|
||||
# deploy — Gmail Inbox Architect
|
||||
|
||||
## Purpose
|
||||
Implements approved rules from the Tracker into Gmail. This means:
|
||||
- Gmail filters via Google Workspace MCP (Claude executes directly)
|
||||
- Apps Script deployment via step-by-step user walkthrough (Claude guides, user executes)
|
||||
## What This Skill Does
|
||||
|
||||
## Non-Technical User Standard
|
||||
This skill must never assume the user knows what a Gmail filter is, what Apps Script is,
|
||||
or how to navigate Google's admin interfaces. Every instruction must be written in plain
|
||||
English with numbered steps, screenshots described in words, and explicit "click X, then Y"
|
||||
guidance.
|
||||
Takes approved rules from the Tracker and makes them live. There are three deployment
|
||||
paths depending on the rule type:
|
||||
|
||||
## Bulk Operation Rule (North Star)
|
||||
For operations involving hundreds or thousands of existing emails (mass label changes,
|
||||
backfills, restructuring), Claude must:
|
||||
1. Recommend the lowest-cost path first (Gmail UI, a pre-built script, or a task order
|
||||
to a lower-cost agent)
|
||||
2. Guide the user through that path OR produce a task order that handles it
|
||||
3. Never burn Claude tokens on mechanical, row-by-row email operations
|
||||
- **Gmail sorting rules** (`gmail_filter_safe`) — Claude creates these directly via its
|
||||
Gmail connection. Fast, no user action required beyond confirming.
|
||||
- **Automation scripts** (`apps_script_needed`) — Claude writes a script, walks the user
|
||||
through installing it in Google Apps Script, guides the test run, and reviews the logs.
|
||||
- **Studio candidates** (`studio_candidate`) — acknowledged and parked. No deployment
|
||||
until Studio support is added to this plugin.
|
||||
|
||||
## Skill Stub — Implementation Pending
|
||||
Full SKILL.md to be written in build session. Load CW-020_Concept.md for scope and design intent.
|
||||
Nothing goes live without explicit user confirmation. All deployed rules are marked active
|
||||
in the Tracker after successful deployment.
|
||||
|
||||
This skill is entirely self-contained. All templates, script patterns, and walkthrough
|
||||
steps are embedded below.
|
||||
|
||||
---
|
||||
|
||||
## When This Skill Is Triggered
|
||||
|
||||
- User says: "deploy the rules", "turn on the rules", "set up the filters",
|
||||
"let's push this batch", "go live", "activate the rules"
|
||||
- Import skill directs the user here after the review queue is complete
|
||||
- User says: "the script is ready to deploy", "install the automation"
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before deploying, verify:
|
||||
- `_status.md` exists with Phase = "Rule Build" or "Deploy-ready"
|
||||
- Tracker exists with at least one rule where `enabled = FALSE` and `deployability` is set
|
||||
- Bible.md exists (needed to confirm label taxonomy before creating filters)
|
||||
|
||||
Read the `apps_script_log.md` file from the project folder if it exists. This file tracks
|
||||
previous script deployments and known issues for this project. Reference it before writing
|
||||
any new Apps Script code to avoid repeating past mistakes.
|
||||
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **Google Workspace MCP** — for Gmail filter creation, label ID lookup, and Gmail search
|
||||
during post-deploy verification
|
||||
- **No other external dependencies** — Apps Script code is generated inline
|
||||
|
||||
---
|
||||
|
||||
## Execution Flow
|
||||
|
||||
```
|
||||
Phase 1 → Sanity check and queue load (what's ready to deploy)
|
||||
Phase 2 → Deploy gmail_filter_safe rules (Claude executes via Gmail connection)
|
||||
Phase 3 → Generate and deploy apps_script_needed rules (walkthrough)
|
||||
Phase 4 → Acknowledge studio_candidate rules (park, no action)
|
||||
Phase 5 → Update Tracker (mark deployed rules as enabled=TRUE)
|
||||
Phase 6 → Update _status.md and close out
|
||||
```
|
||||
|
||||
Phases 2, 3, and 4 are independent — run whichever apply based on what's in the queue.
|
||||
It is valid to do Phase 2 only (no Apps Script rules in this batch), or Phase 3 only.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — Sanity Check and Queue Load
|
||||
|
||||
Read `_status.md` and the Tracker.
|
||||
|
||||
From the Tracker, load all rules where `enabled = FALSE`. Group by deployability:
|
||||
|
||||
- `gmail_filter_safe` → Phase 2 queue
|
||||
- `apps_script_needed` → Phase 3 queue
|
||||
- `studio_candidate` → Phase 4 queue
|
||||
|
||||
Also load any rules where `enabled = FALSE` and `deployability` is blank — treat these
|
||||
as needing a deployability decision. Ask Claude which path they belong on before proceeding.
|
||||
|
||||
Present the deployment plan:
|
||||
> "Here's what's ready to go live:
|
||||
>
|
||||
> [N] sorting rules — I can create these directly in Gmail right now.
|
||||
> [N] automation script rules — these need a small script installed in Google Apps Script.
|
||||
> [N] parked rules — saved for a future step.
|
||||
>
|
||||
> Want to start with the sorting rules? That's the fastest part."
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Deploy Gmail Filter Rules
|
||||
|
||||
### Step 2.1 — Present for final confirmation
|
||||
|
||||
Before creating any filters, show a clean summary. Group rules by target label.
|
||||
|
||||
> "Here are the [N] sorting rules I'm about to create. Take a look before I turn them on:
|
||||
>
|
||||
> **Finance/AMEX** — email from americanexpress.com with 'statement' in the subject
|
||||
> **Vendors/Shipping** — email from ups.com, fedex.com — automatically filed, marked as read
|
||||
> **Clients/Transit** — any email where [client domain] is sender or recipient
|
||||
> [... etc]
|
||||
>
|
||||
> Once I create these, new email will start sorting automatically. Ready?"
|
||||
|
||||
Wait for explicit confirmation. Do not proceed without it.
|
||||
|
||||
### Step 2.2 — Look up label IDs
|
||||
|
||||
Call `list_gmail_labels` to get the Gmail label ID for each target label.
|
||||
Gmail filters require label IDs, not label names.
|
||||
|
||||
Map each `base_label` value in the queue to its corresponding label ID.
|
||||
|
||||
If a label is missing (not found in Gmail):
|
||||
> "I can't find the label '[label name]' in Gmail — it may not have been created yet.
|
||||
> Do you want me to create it now, or skip this rule for now?"
|
||||
|
||||
Wait for answer before proceeding.
|
||||
|
||||
### Step 2.3 — Create filters
|
||||
|
||||
For each gmail_filter_safe rule, call `manage_gmail_filter` with:
|
||||
|
||||
**Criteria** (build from Tracker fields):
|
||||
- `from_domain`: build as `from:domain.com` — multiple domains use OR logic:
|
||||
`{from:domain1.com from:domain2.com}`
|
||||
- `to_or_cc_domain` (participant pattern): combine as:
|
||||
`{from:domain.com to:domain.com}`
|
||||
- `subject_contains`: `subject:keyword` — multiple keywords joined with OR or AND
|
||||
based on the rule's intent (default OR unless notes specify otherwise)
|
||||
- `has_attachment`: `has:attachment`
|
||||
- Combined signals: join with spaces (AND logic in Gmail search)
|
||||
|
||||
**Actions** (from Tracker fields):
|
||||
- `addLabelIds`: the label ID from Step 2.2
|
||||
- `markAsRead`: TRUE if `mark_read = TRUE`
|
||||
- Skip inbox (archive): set `removeLabelIds: ["INBOX"]` if `archive = TRUE`
|
||||
|
||||
Create one filter per rule. Do not batch multiple rules into one filter — they are
|
||||
harder to manage and delete individually.
|
||||
|
||||
After each successful creation, note it. If a creation fails, log the error and continue
|
||||
with the remaining rules — do not abort the entire batch.
|
||||
|
||||
### Step 2.4 — Post-deploy verification
|
||||
|
||||
After all filters are created, run a quick spot-check. For 2-3 of the higher-volume rules,
|
||||
call `search_gmail_messages` using the same query and confirm Gmail returns the expected
|
||||
threads. This validates the filter syntax fired correctly.
|
||||
|
||||
Report back:
|
||||
> "Done — [N] sorting rules are now active in Gmail. New email matching these patterns
|
||||
> will be sorted automatically from this point forward.
|
||||
>
|
||||
> [If any failed:] [N] rules couldn't be created — [plain English reason]. Want to
|
||||
> troubleshoot those now or skip them?"
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — Apps Script Deployment
|
||||
|
||||
Apps Script handles rules that Gmail's native filters can't: attachment filename patterns,
|
||||
body text signals, multi-condition logic.
|
||||
|
||||
### Step 3.1 — Read the issue log
|
||||
|
||||
Before writing any code, check for `apps_script_log.md` in the project Drive folder.
|
||||
If it exists, read it. Note any previous errors or patterns to avoid.
|
||||
|
||||
### Step 3.2 — Generate the script
|
||||
|
||||
Write a complete, runnable Google Apps Script file from the apps_script_needed rules
|
||||
in the Tracker. The script must be syntactically correct, well-commented, and ready
|
||||
to paste without modification.
|
||||
|
||||
**Script architecture:**
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Gmail Classification Script
|
||||
* Project: Gmail Inbox Architect — [account]
|
||||
* Generated: [date]
|
||||
* Rules covered: [comma-separated list of rule_ids]
|
||||
*
|
||||
* BEFORE RUNNING:
|
||||
* 1. Set DRY_RUN = true for your first test run
|
||||
* 2. Review the execution log after the test
|
||||
* 3. Set DRY_RUN = false only after confirming the test looks correct
|
||||
*
|
||||
* Issue log: apps_script_log.md in your project Drive folder
|
||||
*/
|
||||
|
||||
// ─── CONFIGURATION ────────────────────────────────────────────────────────────
|
||||
const DRY_RUN = true; // true = log only, no changes. Set false after testing.
|
||||
const MAX_THREADS = 50; // Threads to process per rule per run (raise if needed)
|
||||
const LOOKBACK_HOURS = 2; // Only check email newer than this many hours
|
||||
// ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
function runClassification() {
|
||||
const startTime = new Date();
|
||||
Logger.log('=== Gmail Classification Run ===');
|
||||
Logger.log('Mode: ' + (DRY_RUN ? 'DRY RUN (no changes)' : 'LIVE'));
|
||||
Logger.log('Started: ' + startTime.toISOString());
|
||||
|
||||
const rules = buildRules();
|
||||
let totalLabeled = 0;
|
||||
const errors = [];
|
||||
|
||||
for (const rule of rules) {
|
||||
try {
|
||||
const count = applyRule(rule);
|
||||
totalLabeled += count;
|
||||
if (count > 0) {
|
||||
Logger.log('[' + rule.id + '] Applied to ' + count + ' thread(s)');
|
||||
}
|
||||
} catch (e) {
|
||||
const msg = '[' + rule.id + '] ERROR: ' + e.message;
|
||||
Logger.log(msg);
|
||||
errors.push(msg);
|
||||
}
|
||||
}
|
||||
|
||||
Logger.log('---');
|
||||
Logger.log('Total threads processed: ' + totalLabeled);
|
||||
Logger.log('Errors: ' + errors.length);
|
||||
Logger.log('Finished: ' + new Date().toISOString());
|
||||
|
||||
if (errors.length > 0) {
|
||||
Logger.log('ERROR DETAILS:');
|
||||
errors.forEach(e => Logger.log(e));
|
||||
}
|
||||
}
|
||||
|
||||
function applyRule(rule) {
|
||||
// Build time-bounded query so we only process recent email
|
||||
const cutoff = new Date(Date.now() - LOOKBACK_HOURS * 60 * 60 * 1000);
|
||||
const after = Utilities.formatDate(cutoff, 'UTC', 'yyyy/MM/dd');
|
||||
const query = rule.query + ' after:' + after;
|
||||
|
||||
const threads = GmailApp.search(query, 0, MAX_THREADS);
|
||||
if (threads.length === 0) return 0;
|
||||
|
||||
const label = rule.labelName
|
||||
? GmailApp.getUserLabelByName(rule.labelName)
|
||||
: null;
|
||||
|
||||
if (rule.labelName && !label) {
|
||||
throw new Error('Label not found: ' + rule.labelName +
|
||||
' — create this label in Gmail first');
|
||||
}
|
||||
|
||||
let count = 0;
|
||||
for (const thread of threads) {
|
||||
const subject = thread.getFirstMessageSubject();
|
||||
|
||||
if (DRY_RUN) {
|
||||
Logger.log(' [DRY RUN] Would label "' + subject + '" → ' + rule.labelName);
|
||||
} else {
|
||||
if (label) label.addToThread(thread);
|
||||
if (rule.archive) thread.moveToArchive();
|
||||
if (rule.markRead) thread.markRead();
|
||||
Logger.log(' Labeled: "' + subject + '" → ' + rule.labelName);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function buildRules() {
|
||||
// Each entry below is one rule from the Tracker.
|
||||
// query: Gmail search query that identifies matching threads
|
||||
// labelName: exact Gmail label path (must exist in Gmail already)
|
||||
// archive: move out of inbox after labeling
|
||||
// markRead: mark as read after labeling (use sparingly)
|
||||
return [
|
||||
[RULES_ARRAY — generated per rule below]
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
**Query building per rule type:**
|
||||
|
||||
For each `apps_script_needed` rule in the Tracker, build a `query` string:
|
||||
|
||||
- `from_domain` only: `"from:domain.com"`
|
||||
- `from_domain` + `subject_contains`: `"from:domain.com subject:keyword"`
|
||||
- `has_attachment` = TRUE: append `"has:attachment"`
|
||||
- `body_signal` (body text): use bare keyword (Gmail search searches body by default):
|
||||
`"from:domain.com invoice"` — note this in the rule's comment
|
||||
- Attachment filename pattern: Gmail search does not support filename regex natively;
|
||||
use `"has:attachment from:domain.com"` as the filter and note in comments that
|
||||
the Apps Script `getAttachments()` check refines this. Add attachment name check
|
||||
inline using `thread.getMessages()[0].getAttachments()` pattern match if the rule
|
||||
requires filename specificity.
|
||||
|
||||
**Attachment filename check pattern (embed when needed):**
|
||||
|
||||
```javascript
|
||||
// Check attachment filename pattern
|
||||
const messages = thread.getMessages();
|
||||
let hasMatchingAttachment = false;
|
||||
for (const msg of messages) {
|
||||
for (const att of msg.getAttachments()) {
|
||||
if (/\.(stp|step)$/i.test(att.getName())) {
|
||||
hasMatchingAttachment = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasMatchingAttachment) break;
|
||||
}
|
||||
if (!hasMatchingAttachment) continue; // skip thread
|
||||
```
|
||||
|
||||
**After writing the script:**
|
||||
|
||||
Show it to Claude for review before presenting to the user:
|
||||
> "Here's the script I've written. It covers [N] rules. Take a look — I'll walk you
|
||||
> through installing it once you're ready."
|
||||
|
||||
Then present the script to the user in a code block they can copy.
|
||||
|
||||
### Step 3.3 — Installation walkthrough
|
||||
|
||||
Walk the user through step by step. Use numbered steps, plain English.
|
||||
|
||||
> "Here's how to install this. It sounds more technical than it is — just follow
|
||||
> the steps and let me know if anything looks different from what I describe.
|
||||
>
|
||||
> **Step 1 — Open Google Apps Script**
|
||||
> Go to script.google.com. You may need to sign in with your Google account.
|
||||
>
|
||||
> **Step 2 — Create a new project**
|
||||
> Click the blue '+ New project' button in the top left.
|
||||
> You'll see a page with some starter code already in it.
|
||||
>
|
||||
> **Step 3 — Replace the existing code**
|
||||
> Click anywhere in the code editor. Press Ctrl+A (Windows) or Cmd+A (Mac) to
|
||||
> select everything. Then delete it. Paste the script I gave you above.
|
||||
>
|
||||
> **Step 4 — Name the project**
|
||||
> Click 'Untitled project' at the top left and rename it to:
|
||||
> 'Gmail Classifier — [account]'
|
||||
> Then press Enter.
|
||||
>
|
||||
> **Step 5 — Save**
|
||||
> Press Ctrl+S (Windows) or Cmd+S (Mac). You should see the save icon stop spinning.
|
||||
>
|
||||
> Let me know when you've done these steps and I'll walk you through the test run."
|
||||
|
||||
Wait for confirmation before continuing.
|
||||
|
||||
### Step 3.4 — Test run walkthrough
|
||||
|
||||
> "Now let's test it. The script is set to 'dry run' mode right now — it will tell
|
||||
> you what it *would* do without actually changing anything.
|
||||
>
|
||||
> **Step 6 — Run the test**
|
||||
> At the top of the script editor, you'll see a dropdown that says 'runClassification'.
|
||||
> Make sure that's selected, then click the triangle (▶) Run button.
|
||||
>
|
||||
> **Step 7 — Authorize the script**
|
||||
> A popup will appear asking for permission. Click 'Review permissions', choose your
|
||||
> Google account, then click 'Allow'. This lets the script read your Gmail.
|
||||
> (This only happens the first time.)
|
||||
>
|
||||
> **Step 8 — View the logs**
|
||||
> After the run finishes, click 'Execution log' at the bottom of the screen.
|
||||
> You'll see a list of what the script found.
|
||||
>
|
||||
> Copy everything from the execution log and paste it back to me."
|
||||
|
||||
Wait for the user to paste the logs.
|
||||
|
||||
### Step 3.5 — Review the test logs
|
||||
|
||||
Read the pasted execution log. Check for:
|
||||
|
||||
- **Errors**: any `[ERROR]` lines → diagnose and fix the script
|
||||
- **Unexpected matches**: threads labeled that shouldn't be → tighten the query
|
||||
- **Missing matches**: expected threads not found → check the query or LOOKBACK_HOURS
|
||||
- **Label not found errors**: the Gmail label doesn't exist yet → create it first
|
||||
|
||||
If the log looks clean:
|
||||
> "The test looks good — the script found [N] threads that match the rules, and nothing
|
||||
> looks out of place. Ready to go live?
|
||||
>
|
||||
> Here's what you need to change: open the script, find the line that says
|
||||
> `const DRY_RUN = true;` near the top, and change `true` to `false`. Save it.
|
||||
> That's the only change."
|
||||
|
||||
If there are issues, fix the script, show the corrected version, and repeat from Step 3.4.
|
||||
|
||||
### Step 3.6 — Set up the trigger
|
||||
|
||||
After the user confirms DRY_RUN = false:
|
||||
|
||||
> "Last step — let's set it to run automatically.
|
||||
>
|
||||
> **Step 9 — Open triggers**
|
||||
> In the script editor, click the clock icon on the left sidebar (it looks like a
|
||||
> stopwatch). Or go to Extensions → Apps Script (if you're in Google Sheets) → Triggers.
|
||||
>
|
||||
> Actually, since you're already in the editor: look for 'Triggers' in the left sidebar.
|
||||
> It's the icon that looks like an alarm clock. Click it.
|
||||
>
|
||||
> **Step 10 — Add a trigger**
|
||||
> Click '+ Add Trigger' in the bottom right.
|
||||
>
|
||||
> Set these options:
|
||||
> - Function to run: runClassification
|
||||
> - Deployment: Head
|
||||
> - Event source: Time-driven
|
||||
> - Type of time-based trigger: Hour timer
|
||||
> - Every: [1 hour is a good starting point — suggest 15 minutes if the user
|
||||
> wants near-real-time; suggest 6 hours if they prefer low noise]
|
||||
>
|
||||
> Click Save.
|
||||
>
|
||||
> The script will now run automatically on that schedule."
|
||||
|
||||
### Step 3.7 — Escalation path
|
||||
|
||||
At any point in the walkthrough where the user is uncertain or stuck:
|
||||
|
||||
> "If any of this feels unclear or you want someone to help install it, this is a
|
||||
> great time to loop in one of your team's AI experts or technical contacts.
|
||||
> The script and all these instructions are saved in your project Drive folder —
|
||||
> they'll have everything they need to get it set up."
|
||||
|
||||
Log this suggestion in `apps_script_log.md` as a note if the user escalates.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — Studio Candidates
|
||||
|
||||
After handling the two active deployment paths, acknowledge parked rules:
|
||||
|
||||
> "[N] rules are saved for a future step — these are cases where the pattern is
|
||||
> too fuzzy for the current tools to handle reliably. They're in your Tracker and
|
||||
> won't be lost. When we add Studio support to this system, we'll come back to them."
|
||||
|
||||
No action required. These remain in the Tracker with `enabled = FALSE` and
|
||||
`deployability = studio_candidate`.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5 — Update Tracker
|
||||
|
||||
After successful deployment, update each deployed rule in the Tracker:
|
||||
- Set `enabled = TRUE`
|
||||
- Append to `notes`: "Deployed [date] via [gmail_filter / apps_script v[N]]"
|
||||
|
||||
For rules that failed deployment:
|
||||
- Leave `enabled = FALSE`
|
||||
- Append to `notes`: "Deploy attempted [date] — failed: [reason]"
|
||||
|
||||
For Apps Script rules deployed via script: update all rules covered by the script
|
||||
to `enabled = TRUE` together, since they go live as a bundle when DRY_RUN is set false.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6 — Update apps_script_log.md
|
||||
|
||||
After any Apps Script deployment (successful or not), update or create
|
||||
`apps_script_log.md` in the project Drive folder.
|
||||
|
||||
**File format:**
|
||||
|
||||
```markdown
|
||||
# Apps Script Log
|
||||
## Project: [Gmail account]
|
||||
## Purpose: Read this file before writing any new Apps Script for this project.
|
||||
## Reference it to avoid repeating past mistakes.
|
||||
|
||||
---
|
||||
|
||||
## Script v[N] — [date]
|
||||
|
||||
**Rules covered:** [comma-separated rule_ids]
|
||||
**Status:** [Testing / Active / Retired]
|
||||
**DRY_RUN disabled:** [date]
|
||||
**Trigger:** Every [N] hours
|
||||
|
||||
### Known issues
|
||||
[List any errors encountered during testing or after going live]
|
||||
|
||||
### Resolutions
|
||||
[What was changed to fix each issue]
|
||||
|
||||
### Notes
|
||||
[Anything the next session should know before touching this script]
|
||||
```
|
||||
|
||||
If the file already exists, append a new version block. Do not overwrite old entries —
|
||||
the history is the point.
|
||||
|
||||
---
|
||||
|
||||
## Phase 7 — Update _status.md and Close Out
|
||||
|
||||
Update `_status.md`:
|
||||
|
||||
```
|
||||
Last Updated: [timestamp]
|
||||
Last Agent: Claude (CoWork) — deploy skill
|
||||
Phase: [Deploy / Maintenance — depending on whether all rules are now live]
|
||||
Last Completed Step: [N] gmail_filter_safe rules created. [N] apps_script_needed rules
|
||||
deployed via Apps Script v[N]. [N] studio_candidate rules parked.
|
||||
Pending Work: [NONE / or: [N] rules failed deployment — see notes]
|
||||
Handoff Target: NONE
|
||||
Notes: [Apps Script log updated. Tracker updated. Any escalations noted.]
|
||||
```
|
||||
|
||||
Close out with the user:
|
||||
|
||||
**If everything deployed successfully:**
|
||||
> "You're live. Here's what's now running:
|
||||
>
|
||||
> ✅ [N] sorting rules active in Gmail — new email will be sorted automatically
|
||||
> ✅ [N] automation script rules running every [N] hours — checking for matching patterns
|
||||
> 🅿️ [N] rules parked for future Studio support
|
||||
>
|
||||
> If you notice anything sorting incorrectly, say 'review a rule' and I'll help
|
||||
> adjust it. If email stops sorting the way you expect, say 'check the script' and
|
||||
> I'll look at the logs."
|
||||
|
||||
**If some rules failed:**
|
||||
> "Most rules are live. [N] couldn't be deployed right now — [plain English summary].
|
||||
> Want to troubleshoot those now or come back to them later?"
|
||||
|
||||
---
|
||||
|
||||
## Handling Bulk Backfill Requests
|
||||
|
||||
If the user asks to apply labels to thousands of existing emails (not just new ones
|
||||
going forward), this is a separate operation from filter deployment. Apply the North
|
||||
Star rule:
|
||||
|
||||
1. **Lowest-cost path first.** If the volume is manageable (under 500 threads per label),
|
||||
Claude can run the Apps Script with a larger `MAX_THREADS` value and a wider lookback
|
||||
window. Explain this option.
|
||||
|
||||
2. **For large volumes** (thousands of threads), produce a task order to a lower-cost
|
||||
agent. Do not burn Claude tokens on mechanical row-by-row operations.
|
||||
|
||||
3. **Never auto-backfill.** Always confirm with the user before bulk-applying labels
|
||||
to existing email.
|
||||
|
||||
---
|
||||
|
||||
## Non-Technical User Language Rules
|
||||
|
||||
Never use: filter, API, MCP, schema, regex, Apps Script (except when naming the product
|
||||
explicitly), boolean, deploy, trigger (use "schedule" instead)
|
||||
|
||||
Substitute:
|
||||
- "Gmail filter" → "sorting rule"
|
||||
- "Apps Script" → "automation script" (or "Google's automation tool" on first mention)
|
||||
- "trigger" → "schedule" or "automatic schedule"
|
||||
- "deploy" → "turn on" or "go live"
|
||||
- "boolean" → "yes/no"
|
||||
- "query" → "search pattern"
|
||||
|
||||
Number every step in the walkthrough. Confirm before proceeding to the next major step.
|
||||
|
||||
---
|
||||
|
||||
## Safety Rules (Hardcoded — Cannot Be Overridden)
|
||||
|
||||
1. **Explicit confirmation before any Gmail mutation.** Present the full list of rules
|
||||
to be deployed and wait for a clear "yes" before creating any filter or running
|
||||
any live script.
|
||||
|
||||
2. **DRY_RUN = true in every generated script.** Never generate a script with
|
||||
DRY_RUN = false. The user sets this manually after reviewing test logs.
|
||||
|
||||
3. **No filter creation without a valid label ID.** If a label doesn't exist in Gmail,
|
||||
stop and ask. Do not create filters pointing to non-existent labels.
|
||||
|
||||
4. **No bulk backfill without explicit request and confirmation.** Filters and scripts
|
||||
apply to new email only by default. Backfilling existing email requires a separate
|
||||
explicit decision.
|
||||
|
||||
5. **Tracker updated after deployment.** Every deployed rule must be marked enabled=TRUE.
|
||||
Every failed rule must have its failure noted. No silent state drift.
|
||||
|
||||
6. **apps_script_log.md always updated.** Never complete an Apps Script deployment
|
||||
without updating the log file. The log is how future sessions avoid repeating mistakes.
|
||||
|
||||
Reference in New Issue
Block a user