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:
Jason Stedwell
2026-07-03 23:04:35 -05:00
parent 005c047eb6
commit 8723bb942e
6 changed files with 121 additions and 28 deletions
+43 -6
View File
@@ -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