fix: repair cross-skill contract gaps and harden Tracker handling (v1.1.1)
- deploy: create "! Rule Needed" label on first deploy (was promised in frontmatter but never implemented; rule-review depends on it) - rule-review: accept Bootstrap-mode entry (Phase: Bootstrap, no Tracker yet) - survey: create the three artifacts before invoking handoff so handoff's sanity check no longer loops - deploy: name manage_gmail_filter params explicitly (action/criteria/filter_action) - rule-review: quote label query (label:"! Rule Needed") - deploy: renumber execution-flow block to the 7 phases the body runs - survey: frame Tracker About tab as a technical reference - import + rule-review: de-duplicate rule_id before writing to Tracker - survey/import/deploy/rule-review: document XLSX Tracker Drive round-trip - all skills: use session date only in _status.md (no fabricated clock time) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
005c047eb6
commit
8723bb942e
+43
-6
@@ -65,12 +65,13 @@ any new Apps Script code to avoid repeating past mistakes.
|
||||
## Execution Flow
|
||||
|
||||
```
|
||||
Phase 1 → Sanity check and queue load (what's ready to deploy)
|
||||
Phase 1 → Sanity check, queue load, and ensure the ! Rule Needed label exists
|
||||
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
|
||||
Phase 6 → Update apps_script_log.md (only if an Apps Script was deployed)
|
||||
Phase 7 → Update _status.md and close out
|
||||
```
|
||||
|
||||
Phases 2, 3, and 4 are independent — run whichever apply based on what's in the queue.
|
||||
@@ -100,6 +101,25 @@ Present the deployment plan:
|
||||
>
|
||||
> Want to start with the sorting rules? That's the fastest part."
|
||||
|
||||
### Step 1.1 — Ensure the "! Rule Needed" label exists (first deploy)
|
||||
|
||||
This label is how the user flags emails that slip through so `rule-review` can build
|
||||
rules for them later. It is a prerequisite of the `rule-review` skill, and this is the
|
||||
skill responsible for creating it on the first deploy.
|
||||
|
||||
Read the label name from Bible.md if one was customized; default is `! Rule Needed`.
|
||||
Call `list_gmail_labels` and check whether it already exists (a Bootstrap-mode project
|
||||
may have created it during survey — in that case, do nothing).
|
||||
|
||||
If it does NOT exist, ask before creating:
|
||||
> "One quick housekeeping item: I'd like to add a label called '! Rule Needed'. Going
|
||||
> forward, whenever an email doesn't sort the way you'd like, just tag it with that label —
|
||||
> and later I can review what you tagged and build new rules. Can I create it now?"
|
||||
|
||||
Wait for an explicit "yes." If approved, call `manage_gmail_label` with `action: create`
|
||||
and `name: ! Rule Needed`. If declined, note it and continue — the user can create it
|
||||
manually before their first rule-review session.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Deploy Gmail Filter Rules
|
||||
@@ -134,9 +154,12 @@ Wait for answer before proceeding.
|
||||
|
||||
### Step 2.3 — Create filters
|
||||
|
||||
For each gmail_filter_safe rule, call `manage_gmail_filter` with:
|
||||
For each gmail_filter_safe rule, call `manage_gmail_filter` with three parameters:
|
||||
`action` (always `"create"`), `criteria` (an object), and `filter_action` (an object).
|
||||
Note the parameter is named `filter_action`, NOT `actions` — do not confuse it with the
|
||||
`action: "create"` selector.
|
||||
|
||||
**Criteria** (build from Tracker fields):
|
||||
**`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:
|
||||
@@ -146,11 +169,15 @@ For each gmail_filter_safe rule, call `manage_gmail_filter` with:
|
||||
- `has_attachment`: `has:attachment`
|
||||
- Combined signals: join with spaces (AND logic in Gmail search)
|
||||
|
||||
**Actions** (from Tracker fields):
|
||||
**`filter_action`** (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`
|
||||
|
||||
So a typical call is:
|
||||
`action: "create"`, `criteria: { from: "domain.com", subject: "statement" }`,
|
||||
`filter_action: { addLabelIds: ["Label_123"], removeLabelIds: ["INBOX"] }`
|
||||
|
||||
Create one filter per rule. Do not batch multiple rules into one filter — they are
|
||||
harder to manage and delete individually.
|
||||
|
||||
@@ -472,6 +499,16 @@ For rules that failed deployment:
|
||||
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.
|
||||
|
||||
**Google Sheet Tracker:** update rows in place with `modify_sheet_values`.
|
||||
|
||||
**XLSX Tracker (round-trip required):** the file lives in Drive, so editing is not
|
||||
in-place. Download the current file with `get_drive_file_content` (or the Drive
|
||||
download URL), invoke the `xlsx` skill to set `enabled`/`notes` on the affected rows,
|
||||
then write the updated file back to the same Drive location — overwrite the existing
|
||||
file (use `update_drive_file` if available; otherwise re-create it in the same folder
|
||||
and confirm the old copy is replaced, never leaving two Trackers). Verify the row count
|
||||
matches before and after so no rules are dropped in the round-trip.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6 — Update apps_script_log.md
|
||||
@@ -516,7 +553,7 @@ the history is the point.
|
||||
Update `_status.md`:
|
||||
|
||||
```
|
||||
Last Updated: [timestamp]
|
||||
Last Updated: [YYYY-MM-DD — today's date from the session; do not fabricate a clock time]
|
||||
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
|
||||
|
||||
@@ -449,7 +449,7 @@ After all task order folders are created in Drive, give the user clear delivery
|
||||
After all task orders are generated, update `_status.md`:
|
||||
|
||||
```
|
||||
Last Updated: [timestamp]
|
||||
Last Updated: [YYYY-MM-DD — today's date from the session; do not fabricate a clock time]
|
||||
Last Agent: Claude (CoWork) — handoff skill
|
||||
Phase: Handoff in progress
|
||||
Last Completed Step: [N] task order batches created in Drive Task Orders folder.
|
||||
|
||||
+13
-2
@@ -286,6 +286,12 @@ For each note:
|
||||
|
||||
Write all approved (and parked) rules to the Tracker after the queue is complete.
|
||||
|
||||
**Guarantee unique rule_ids before writing.** Read the existing `rule_id` values from the
|
||||
Rules sheet first. For every rule about to be written, if its ID already exists (a
|
||||
subcontractor may reuse IDs across batches, or collide with a prior import), append a
|
||||
numeric suffix (`-2`, `-3`, …) until unique. Never overwrite an existing row or write a
|
||||
duplicate ID.
|
||||
|
||||
### Tracker Column Schema
|
||||
|
||||
```
|
||||
@@ -325,7 +331,12 @@ Always:
|
||||
|
||||
### Writing to XLSX Tracker
|
||||
|
||||
Invoke the xlsx skill to append rows to the Rules sheet. Same field rules apply.
|
||||
The file lives in Drive, so this is a round-trip, not an in-place edit. Download the
|
||||
current file with `get_drive_file_content`, invoke the xlsx skill to append the rows to
|
||||
the Rules sheet (same field rules apply), then upload it back to the same Drive location,
|
||||
replacing the existing file (`update_drive_file` if available; otherwise re-create it in
|
||||
the same folder and confirm the old copy is replaced — never leave two Trackers). Verify
|
||||
the row count grew by exactly the number of rules written.
|
||||
|
||||
### After writing:
|
||||
|
||||
@@ -344,7 +355,7 @@ Invoke the xlsx skill to append rows to the Rules sheet. Same field rules apply.
|
||||
Update `_status.md`:
|
||||
|
||||
```
|
||||
Last Updated: [timestamp]
|
||||
Last Updated: [YYYY-MM-DD — today's date from the session; do not fabricate a clock time]
|
||||
Last Agent: Claude (CoWork) — import skill
|
||||
Phase: Rule Build [or Deploy-ready if all batches are in]
|
||||
Last Completed Step: [N] rules from [batch name] reviewed and loaded.
|
||||
|
||||
+36
-12
@@ -67,12 +67,22 @@ and that requires the user to confirm it before Claude touches anything.
|
||||
## Prerequisites
|
||||
|
||||
Before doing any other work, run Phase 1 (sanity check). This skill requires:
|
||||
- `_status.md` exists with Phase = "Deploy" or "Maintenance" (first deploy must be complete)
|
||||
- `_status.md` exists with Phase = "Deploy", "Maintenance", or "Bootstrap"
|
||||
- `Bible.md` exists with taxonomy and bylaws
|
||||
- Tracker exists (Google Sheet or XLSX)
|
||||
- `! Rule Needed` label exists in Gmail (created automatically by the deploy skill on first deploy)
|
||||
- Tracker exists (Google Sheet or XLSX) — **except in Bootstrap mode**, where no Tracker
|
||||
was created yet (see Bootstrap note below)
|
||||
- `! Rule Needed` label exists in Gmail (created during the first deploy, or during survey
|
||||
in Bootstrap mode)
|
||||
|
||||
If Phase is earlier than "Deploy":
|
||||
**Bootstrap-mode entry:** A project set up in Bootstrap mode (survey with < 15 labels)
|
||||
never ran deploy — its `_status.md` shows `Phase: Bootstrap` and `Bootstrap Mode: TRUE`,
|
||||
and it was intentionally sent here as the return path ("review my rule needed folder").
|
||||
This is valid. If there is no Tracker yet, create one on the first rule that gets approved:
|
||||
confirm the Tracker format (Google Sheet vs. XLSX) with the user per the Bible's open
|
||||
question, build it using the Tracker schema at the end of this skill, then proceed.
|
||||
|
||||
If Phase is "Survey complete" or "Handoff in progress" (a non-bootstrap project whose
|
||||
first deploy hasn't happened yet):
|
||||
> "It looks like your rules haven't been deployed yet. The `! Rule Needed` label gets
|
||||
> created as part of the first deploy — once that's done, I can review flagged emails
|
||||
> with you. Want to finish the deploy first?"
|
||||
@@ -114,11 +124,13 @@ Phase 8 → Update _status.md and brief the user
|
||||
Read `_status.md` from the project Drive folder.
|
||||
|
||||
Check:
|
||||
1. Phase = "Deploy" or "Maintenance"
|
||||
1. Phase = "Deploy", "Maintenance", or "Bootstrap"
|
||||
2. `Bible Location` has a valid Drive URL
|
||||
3. `Tracker Location` has a valid Drive URL or path
|
||||
3. `Tracker Location` has a valid Drive URL or path — OR is "NONE" if `Bootstrap Mode: TRUE`
|
||||
(a bootstrap project has no Tracker yet; that's expected — see Prerequisites)
|
||||
|
||||
If Phase is earlier than "Deploy" → redirect (see Prerequisites above).
|
||||
If Phase is "Survey complete" or "Handoff in progress" (deploy hasn't run and this is not
|
||||
a bootstrap project) → redirect (see Prerequisites above).
|
||||
|
||||
Read `Bible.md` — extract:
|
||||
- The `! Rule Needed` label name (may have been customized; default is `! Rule Needed`)
|
||||
@@ -135,10 +147,13 @@ that name everywhere in this skill. Do not hardcode `! Rule Needed`.
|
||||
Search Gmail for all messages with the `! Rule Needed` label.
|
||||
|
||||
```
|
||||
search_gmail_messages query: "label:! Rule Needed"
|
||||
search_gmail_messages query: label:"! Rule Needed"
|
||||
```
|
||||
|
||||
If the label name has spaces or special characters, quote it appropriately.
|
||||
Because the label name contains a space, the label value must be quoted inside the query
|
||||
(`label:"! Rule Needed"`) — an unquoted `label:! Rule Needed` will not match. Quote the
|
||||
label value whenever the name has spaces or special characters, and substitute the actual
|
||||
label name from Bible.md if it was customized.
|
||||
|
||||
Read message headers only: sender, sender domain, subject, date received, current labels.
|
||||
Do NOT read message bodies — headers are sufficient for pattern identification.
|
||||
@@ -342,11 +357,20 @@ complexity threshold not exceeded, user confirmed the rule.
|
||||
|
||||
Add the rule to the Tracker with enabled=FALSE.
|
||||
|
||||
**First, guarantee a unique rule_id.** Read the existing `rule_id` values from the Rules
|
||||
sheet before writing. If the ID you generated already exists, append a numeric suffix
|
||||
(`-2`, `-3`, …) until it is unique. Two sessions can easily generate the same ID
|
||||
(e.g. `GF-VENDOR-RR-FEDEX`) for different rules — never overwrite or silently collide.
|
||||
|
||||
For a Google Sheet Tracker:
|
||||
Call `append_table_rows` or `modify_sheet_values` to add the row to the Rules sheet.
|
||||
|
||||
For an XLSX Tracker:
|
||||
Invoke the xlsx skill to append the row.
|
||||
For an XLSX Tracker (round-trip required — the file lives in Drive, not locally):
|
||||
Download the current file with `get_drive_file_content`, invoke the xlsx skill to append
|
||||
the row to the Rules sheet, then upload it back to the same Drive location, replacing the
|
||||
existing file (`update_drive_file` if available; otherwise re-create in the same folder and
|
||||
confirm the old copy is replaced — never leave two Trackers). Verify the row count grew by
|
||||
exactly the number of rules added.
|
||||
|
||||
Rule ID format for rule-review-authored rules:
|
||||
```
|
||||
@@ -462,7 +486,7 @@ After completing:
|
||||
Update `_status.md`:
|
||||
|
||||
```
|
||||
Last Updated: [timestamp]
|
||||
Last Updated: [YYYY-MM-DD — today's date from the session; do not fabricate a clock time]
|
||||
Last Agent: Claude (CoWork) — rule-review skill
|
||||
Phase: Maintenance
|
||||
Last Completed Step: Rule review session. [N] clusters reviewed.
|
||||
|
||||
+27
-6
@@ -473,7 +473,7 @@ mpmedia.tv, messagepoint.tv, messagepointmedia.com, messagepoint.media, mpm.to
|
||||
```markdown
|
||||
# Gmail Inbox Architect — Project Status
|
||||
|
||||
**Last Updated:** [YYYY-MM-DD HH:MM UTC]
|
||||
**Last Updated:** [YYYY-MM-DD — today's date from the session; do not fabricate a clock time]
|
||||
**Last Agent:** Claude (CoWork) — survey skill (bootstrap mode)
|
||||
**Phase:** Bootstrap
|
||||
**Last Completed Step:** Bootstrap survey complete. Domain analysis run. Taxonomy v1 preliminary.
|
||||
@@ -704,7 +704,16 @@ If handoff threshold is met:
|
||||
> flat-rate tool'] for the heavy analysis — they can walk through the whole thing,
|
||||
> then bring the results back to me for review. Want me to set that up?"
|
||||
|
||||
Then invoke the `handoff` skill with the current project context.
|
||||
**Before invoking handoff, complete Phase 5 first.** The `handoff` skill's sanity check
|
||||
requires that Bible.md, the Tracker, and `_status.md` already exist in the project folder —
|
||||
if you invoke it before those artifacts are created, its Phase 1 check fails and bounces
|
||||
back here in a loop. So when the handoff threshold is met:
|
||||
1. Skip the Step 4.2 sampling.
|
||||
2. Run **Phase 5** now to create all three artifacts (write `_status.md` with
|
||||
`Phase: Survey complete` and note the pending handoff).
|
||||
3. Then invoke the `handoff` skill with the current project context.
|
||||
|
||||
Phase 6 close-out then covers the handoff delivery instructions.
|
||||
|
||||
**If sampling is appropriate (under 20 labels, manageable message counts):**
|
||||
|
||||
@@ -859,7 +868,11 @@ Create two sheets:
|
||||
- Sheet 2 named **About** — add this text:
|
||||
```
|
||||
This tracker is the source of truth for all Gmail classification rules.
|
||||
|
||||
|
||||
(This tab is a technical reference for the column names below — you never
|
||||
need to edit it. The plain-English view of your rules is what we walk through
|
||||
together in each session.)
|
||||
|
||||
Columns:
|
||||
rule_id — Unique rule identifier
|
||||
enabled — TRUE/FALSE: whether the rule is active
|
||||
@@ -880,11 +893,19 @@ Create two sheets:
|
||||
```
|
||||
|
||||
**If XLSX path:**
|
||||
Invoke the `xlsx` skill to create `Tracker.xlsx` in the project folder with:
|
||||
Invoke the `xlsx` skill to create `Tracker.xlsx` locally with:
|
||||
- Sheet 1 named "Rules" with the header row from the schema above
|
||||
- Sheet 2 named "About" with the column descriptions above
|
||||
Do NOT pre-populate any data rows.
|
||||
|
||||
The `xlsx` skill writes the file to the local workspace, not to Drive. After it's created,
|
||||
upload it into the project Drive folder so every session and tool can reach it: call
|
||||
`create_drive_file` with `file_name: Tracker.xlsx`, the project `folder_id`, and the local
|
||||
file passed via `fileUrl` (e.g. `file:///path/to/Tracker.xlsx`) with
|
||||
`mime_type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`.
|
||||
Record the resulting Drive URL as the Tracker Location — subsequent skills read and
|
||||
round-trip the file from there.
|
||||
|
||||
After creating, share the link:
|
||||
> "Your Tracker is ready — [link]. It's empty right now, which is exactly right.
|
||||
> Rules will be added here as task orders come back, and you'll review each one
|
||||
@@ -899,7 +920,7 @@ Call `create_drive_file` in the project folder with this content:
|
||||
```markdown
|
||||
# Gmail Inbox Architect — Project Status
|
||||
|
||||
**Last Updated:** [YYYY-MM-DD HH:MM UTC]
|
||||
**Last Updated:** [YYYY-MM-DD — today's date from the session; do not fabricate a clock time]
|
||||
**Last Agent:** Claude (CoWork) — survey skill
|
||||
**Phase:** Survey complete
|
||||
**Last Completed Step:** Survey complete. Taxonomy v1 drafted. Bible.md, Tracker, and _status.md created.
|
||||
@@ -1014,7 +1035,7 @@ Documentation: Technical documents, engineering files, signed contracts, specs
|
||||
For Claude's reference when populating the status file:
|
||||
|
||||
```
|
||||
Last Updated: Timestamp this file was written — YYYY-MM-DD HH:MM UTC
|
||||
Last Updated: Date this file was written — YYYY-MM-DD (today's session date; no fabricated clock time)
|
||||
Last Agent: Name/tool that last updated this file
|
||||
Phase: Survey / Bootstrap / Analysis / Rule Build / Deploy / Review / Maintenance
|
||||
Last Completed Step: Plain-English description of what just finished
|
||||
|
||||
Reference in New Issue
Block a user