Add rpa-bot-handoff skill: ops guide for bot handover

The skill scans a bot with subagents (never runs it) and writes
HANDOVER.md, an 11-section ops guide in the operator's order: where is
what, how to run, how long to wait, after the run, how to see an
exception, exception list, how you will know, how to tell us, don'ts,
issues seen before. Dev material (check against 12 failure classes from
Tebra Auto Post, gaps with file:line, incidents) goes to HANDOVER-DEV.md.

Also adds ADR-0004, glossary terms, five fixture bots and a handoff eval
runner (--resume, --regrade) with results from 47 runs of the earlier
13-section version. The grader still expects that structure and must be
updated before the next eval run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
VasanthandClaude Opus 5.5 committed 2026-10-28 15:01:42 +05:30
1 parent 3d2db6aca6
commit 3942fad6cd
143 files changed
+11815 -2

No files matched your search

@@ -0,0 +1,164 @@
# Mail intake bot - ops handover
Version: none shown by the bot (code as of commit 2e13216) · Written 2026-10-23 · Escalation: RPA dev team, Teams channel **#rpa-support**
## 1. What the bot does
Every 10 minutes Windows Task Scheduler starts the bot. It reads the **unread** emails in the referrals mailbox, saves every attachment, checks that it is a PDF of 20 MB or less, and copies it to the **shared intake folder**. Each attachment becomes one item in the bot's queue with a status and a note. Input: emails with PDF attachments. Output: PDF files in the shared intake folder, plus one line per item in the log file `logs/intake.log`. It drives no desktop apps or websites. It only talks to the mailbox and the shared folder.
## 2. How it works
```
Windows Task Scheduler (every 10 min)
└─ starts → intake bot (no window) ──reads──> referrals mailbox (unread mail only)
│
├─ saves attachments → bot's temp folder (dev only)
├─ copies PDFs → shared intake folder (ops can open)
├─ records items → queue database (dev only)
└─ writes → logs/intake.log (ops can open)
```
- **Task Scheduler** starts the bot. The bot has no screen, so you never see it running.
- **Referrals mailbox:** the bot reads unread mail only. **Reading a mail marks it as read**, so the bot never sees it again.
- **Temp folder:** every attachment is saved here first. Quarantined files stay here. Ops cannot open it.
- **Shared intake folder:** good PDFs end up here. This is the bot's output.
- **Queue database:** one row per attachment (sender, subject, status, note). Only dev can open it.
- **logs/intake.log:** one line per item processed, plus errors. This is ops' main window into the bot.
**One run, step by step:**
1. Check that no item from an earlier run is still "Processing". If one is, **stop the whole run** (see E02).
2. Sign in to the mailbox: 3 tries, 30 seconds apart.
3. For every unread mail: save each attachment and add it to the queue as **New**. The mail is now marked read.
4. For each New item, oldest first: mark it **Processing**, check it, copy it to the shared folder, then set its final status and note.
5. Write one log line per item: `item <number> -> <status> (<note>)`.
## 3. Before a run
The bot runs by itself, so "before a run" means "keep these true all the time":
- [ ] The settings file is in the bot folder. It holds the mailbox address, user and password and the shared-folder path. If the mailbox password expires or changes, dev must update this file (E01).
- [ ] The bot folder has its `logs` folder, plus the `data` folder holding the queue database and a `tmp` folder. The bot does not create these itself. If one is missing, the run crashes before it writes anything (E10).
- [ ] The bot machine can reach the shared intake folder (E05).
- [ ] **Only one machine runs the bot.** Two copies would read the same mailbox and split or duplicate the work.
- Rules for senders of referrals (tell the referral sources):
- Send **PDF only, 20 MB or less**. Good: `referral.pdf` at 3 MB. Bad: `referral.docx`, a phone photo `.jpg`, or a 35 MB scan (all go to Quarantined, E03).
- **No password-protected PDFs** (E04).
- Give each attachment its **own file name**. Bad: two mails that both attach `scan.pdf` - the second one overwrites the first (E08).
- Logos and images in email signatures count as attachments too. They show up as Quarantined. That is noise, not a lost referral.
## 4. During a run
- **Do not end the bot's task in Task Scheduler and do not restart the machine while a run is going.** If the bot stops halfway through an item, that item stays "Processing" and **every later run stops at once** until dev clears it (E02).
- To stop the bot, ask dev to **disable** the scheduled task. Disabling stops future runs without cutting a run in half.
- Do not open, move or rename files in the shared intake folder while they are being copied.
- A run normally takes seconds, or about 1.5 minutes when the mailbox is slow to answer. The bot has **no watchdog**: if the mailbox or the shared folder stops responding, the run can hang with no time limit (E09).
## 5. Where to look when something goes wrong
Ops can open `logs/intake.log` and the shared intake folder. The queue database is dev only.
| Question | Where to look |
|---|---|
| Did the run finish? | `logs/intake.log`. The bot writes **no** "run started" or "run finished" line. A run with no new mail writes nothing at all, so a silent log does not tell you whether the bot is healthy (Fix #10). |
| Which items failed? | `logs/intake.log` → search for `-> Failed`, `-> Quarantined` and `encrypted` |
| Why did one item fail? | The same log line. The reason is in brackets at the end, e.g. `item 312 -> Quarantined (not a PDF or over 20 MB)` |
| Is the bot blocked? | `logs/intake.log` → `Previous item still Processing - aborting` repeated every 10 minutes (E02) |
| Can it reach the mailbox? | `logs/intake.log` → `IMAP connect failed (1/3)`, `(2/3)`, `(3/3)` (E01) |
| Did the bot already retry? | Only mailbox sign-in is retried (the `(n/3)` lines). **Items are never retried.** |
| Did the PDF reach the shared folder? | The shared intake folder. Look for the attachment's file name. The log shows the item number only, not the file name (Fix #11). |
| Who sent the item? | Not visible to ops. Sender and subject are only in the queue database. Ask dev with the item number. |
| Which version is running? | The bot shows no version. Ask dev for the commit it runs (section 10). |
## 6. Statuses
The bot has no screen, so statuses have no colour. You see them in `logs/intake.log` as `-> <status> (<note>)`.
| Status | Note written | Meaning | What ops does |
|---|---|---|---|
| New | (empty) | Saved from the mailbox, waiting for processing. You see it only if a run stopped early. | Nothing. The next run picks it up. |
| Processing | (unchanged) | The bot is working on it right now. **If it is still Processing after the run, it blocks every later run.** | Nothing during a run. If it stays, see E02. |
| Done | `<n> pages saved` | PDF checked and copied to the shared intake folder | Nothing |
| Done | `encrypted - not readable` | **Needs follow-up.** Password-protected PDF. It was **not** copied to the shared folder, even though the status says Done. | E04 |
| Quarantined | `not a PDF or over 20 MB` | **Needs follow-up** (unless it is a signature image). Not copied to the shared folder. | E03 |
| Failed | `share unreachable: <error text>` | **Needs follow-up.** The copy to the shared folder failed. **The bot never retries it.** | E05 |
## 7. Exception catalogue
| ID | What you see | How the bot identifies it | Where it is recorded | Type | Who acts | What to do | Escalate when |
|---|---|---|---|---|---|---|---|
| E01 | New referrals are not reaching the shared folder. The log shows `IMAP connect failed (1/3)` up to `(3/3)` at every 10-minute run. | It tries to sign in to the mailbox 3 times, 30 seconds apart. After the 3rd failure the run ends. | Log: one warning line per try with the mailbox's error text. **The final "gave up" is not logged** (Fix #3). Nothing is queued, and unread mail stays unread (not lost). | System | Bot, then Ops / Dev | Read the error text. Words like "authentication", "login failed" or "password" mean the mailbox password expired or changed: go to dev. Network words like "getaddrinfo failed" or "timed out" mean the machine has no network: check the bot machine's network and wait for the next run. | Password-type error at any time, or network errors on 3 runs in a row (30 min). Send: times of the first and last `(3/3)` lines and the error text (never the password). |
| E02 | The log shows `Previous item still Processing - aborting` every 10 minutes, and no new referrals arrive. | At the start of every run the bot checks whether any item is still Processing. If one is, it stops at once, before it opens the mailbox. | Log: one error line per run. The blocking item is in the queue database only. | System | **Dev** | Ops cannot clear this (database only). New mail is safe: it stays unread in the mailbox and is picked up once dev clears the blocked item. | Always, at the **first** occurrence. Send: time of the first abort line, and the last `item <n> ->` line before it. The blocking item is usually the next number. |
| E03 | Log: `-> Quarantined (not a PDF or over 20 MB)` | The file name does not end in `.pdf`, or the file is bigger than 20 MB | Log line. The file stays in the bot's temp folder and is not copied to the shared folder. | Business | Ops | If it was a signature image or logo, do nothing. If it was a real referral, ask the sender to resend it as a PDF of 20 MB or less. Ops cannot find out the sender alone, so ask dev with the item number. | You need the original file or the sender's details: send the item number and log time. |
| E04 | Log: `-> Done (encrypted - not readable)`. The referral is missing from the shared folder although the status says Done. | The PDF is password-protected | Log line. The file is **not** copied to the shared folder. | Business | Ops | Ask the sender for an unprotected copy. Get the sender's details from dev with the item number. | You need the original file: send the item number and log time. |
| E05 | Log: `-> Failed (share unreachable: ...)` | Copying to the shared intake folder gives an error (folder offline, no permission, disk full) | Log line, with the error text in brackets | System | Ops, then Dev | Check that the shared folder opens from the bot machine and has free space. Check whether a half-copied file with that name is in the shared folder; if so, tell dev. **The bot will not retry this item.** | Always: only dev can put the item back in the queue. Send: item number(s), log time, the error text. |
| E06 | The run stops with no log line for an item, then E02 starts at the next run. | A damaged PDF, or a file that disappeared from the temp folder, makes the bot crash mid-item | **Nothing in the log** for the crash (Fix #3, #4). The item stays Processing. | System | Dev | Same as E02 | Always. Send: the time E02 started. |
| E07 | A sender says they sent a referral, but nothing appears in the log or the shared folder. | Mail with no attachment, or an attachment without a file name, is skipped | **Nowhere.** The mail is marked read and no item is created (Fix #8). | Business | Ops | Check the referrals mailbox for that mail. If it has no attachment, ask the sender to resend with the PDF attached. If it does have a PDF, go to dev. | The mail has a PDF attachment but no item. Send: the mail's received time (not its content). |
| E08 | Two items both show `Done`, but the shared folder has only one file, or the file has the wrong content. | No check. Two attachments with the same file name overwrite each other. | Log: two Done lines. Only one file survives. | System | Dev | Ask dev to recover the overwritten referral from the mailbox. Remind senders to use unique file names. | Always. Send: both item numbers and log times. |
| E09 | Referrals stop arriving with no error in the log, and no `Previous item still Processing` lines either. | No check. The mailbox or the shared folder stopped responding mid-run, and the bot waits with no time limit. | Nothing (Fix #9, #10) | System | Dev | Ops cannot tell this apart from "no new mail" in the log. If senders confirm mail was sent more than 30 minutes ago and nothing arrived, escalate. | 30 minutes with known mail and no log lines. Send: the time of the last log line. |
| E10 | No log lines at all from any run, even when mail is waiting. | The settings file, the `data` or `tmp` folder, the queue database or the `logs` folder is missing, or the temp folder is full | Nothing (the crash happens before or outside logging) | System | Dev | Check that `logs/intake.log` still exists in the bot folder, then escalate. Mail read during a crash in step 3 may be marked read but never queued (lost from the bot's view). | Always. Send: the time of the last log line, and any change to the machine since then (moves, cleanups, password changes). |
## 8. What the bot recovers by itself
| Problem | What the bot does | Limit | After the limit |
|---|---|---|---|
| Mailbox sign-in fails | Waits 30 s and tries again | 3 tries (about 1.5 minutes) | Run ends with nothing logged. The next scheduled run 10 minutes later tries again (E01). |
| Items left New (run stopped before processing them) | Picked up by the next run | Every 10 minutes | - |
| Anything else | **Nothing.** Failed, Quarantined and encrypted items are never retried. A Processing item left by a crash blocks all runs until dev clears it. | - | E02, E05 |
How long to wait before acting: **one or two scheduled runs (10-20 minutes)** for mailbox errors. **Do not wait** for E02: escalate at the first abort line.
## 9. Known incidents
Newest first. The three "fix" changes in the history are notes in the code only. **The behaviour did not change**, so all three can still happen.
| When / version | What ops saw | Cause | What to do now | Ops could handle? |
|---|---|---|---|---|
| Logged as fixed 2026-10-23 | The mailbox password expired and every run failed silently | Mailbox password expiry. The per-try warnings were in the log, but the final failure was not. | Watch for `IMAP connect failed (3/3)` with a password-type error and escalate (E01). The final failure is still not logged. | Partly |
| Logged as fixed 2026-10-23 | Password-protected PDFs reached the shared folder empty | Encrypted PDFs | Today they are marked `Done (encrypted - not readable)` and **not** copied. Follow E04. | Partly |
| Logged as fixed 2026-10-23 (seen in the log 2026-09-04) | The bot was blocked for a whole day after a crash left one item in Processing. Ops reset it by hand. | A crash mid-item leaves it Processing, and every run then stops | Still happens. Ops no longer has database access, so escalate at the first `Previous item still Processing` line (E02). | Partly |
## 10. Releases and version check
- How an update arrives: dev replaces the bot's code on the bot machine. There is no launcher or auto-update.
- How to confirm it applied: the bot shows no version anywhere. Ask dev to confirm the commit running on the machine (Fix #13).
- If the version did not change: report it in #rpa-support. Only one machine may run the bot (section 3), so there is never a second copy to keep in step.
## 11. Escalating to dev
Post in the Teams channel **#rpa-support**. Send: the exception ID from section 7 (e.g. "E02"), the item number(s), the time of the log line(s), and the matching lines copied from `logs/intake.log`.
Never send: passwords, the settings file, sender addresses, email subjects, or attachment contents.
## 12. Failure-class check
- F1 covered in section 3 (settings file, folders, database, share access) and E10.
- F2 not applicable: the bot drives no desktop windows. It works with a mailbox and a file share only.
- F3 covered in E09 (no time limit on the mailbox or the share) and Fix #9. No screens to wait for.
- F4 covered in section 3 sender rules, E03 (signature images), E07 (no attachment) and E08 (same file name).
- F5 covered in E07 and E10 (mail marked read, nothing recorded) and Fix #8.
- F6 covered in E05 (a half-copied file may be in the share after Failed).
- F7 covered in section 6 and E04 (encrypted shown as Done) and Fix #5.
- F8 covered in E02 (every run aborts with no limit), E09 (hang, no watchdog) and section 8. There is no auto-rerun loop.
- F9 covered in section 4 (never end the task mid-run; disable it instead).
- F10 covered in E02 and E06.
- F11 covered in section 5 and Fix #3, #10, #11, #12 (crashes not logged, sender and file name only in the database).
- F12 covered in section 10 and Fix #13 (no version shown).
## 13. Fix before handover (dev team)
| # | Gap | Why it hurts ops | Where (file:line) |
|---|---|---|---|
| 1 | The three "fix" commits (9e47ec2, 9f400df, 2e13216) only add comments. No behaviour changed. | Ops and dev believe these incidents are closed | `intake.py:89-91` |
| 2 | A stale Processing row blocks every run, the blocking id is not logged, and releasing it needs a database edit | Ops has no database access, so every crash becomes a dev call plus lost hours | `intake.py:74-76` |
| 3 | Uncaught errors are never written to the log: "Mailbox unreachable", PDF read errors, file errors. They go only to the console, which nobody sees. | Ops cannot see why a run died | `intake.py:37`, `intake.py:71-88` |
| 4 | A damaged PDF crashes the run (the PDF read is outside any error handling), leaving the item Processing | One bad attachment stops all intake (E06 → E02) | `intake.py:61` |
| 5 | An encrypted PDF is stored as `Done` and not copied | Reads as success but needs follow-up (F7) | `intake.py:62-63` |
| 6 | Failed items are never retried, because only New items are picked | A short share outage needs a dev database edit | `intake.py:78` |
| 7 | Attachment file names are used as-is: the same name overwrites the earlier file in temp and in the share, and names are not sanitised (path characters) | Silent loss of a referral; security risk | `intake.py:50`, `intake.py:65` |
| 8 | Fetching marks mail read before it is committed (one commit after all mails). Mails with no attachment leave no record. | A crash during fetch loses mail from the bot's view; "missing referral" questions cannot be answered | `intake.py:44-54` |
| 9 | No timeout on the mailbox connection or the share copy, and no watchdog | A run can hang without any sign | `intake.py:31`, `intake.py:65` |
| 10 | No "run started / finished / N new mails" log line | A silent log means either "healthy, no mail" or "dead": ops cannot tell | `intake.py:71-84` |
| 11 | The item log line has no file name, sender or subject reference, and the README's `queue_viewer.xlsx` is not in the repo and reads the database | Ops cannot match a log line to a mail or a file in the share | `intake.py:84`, `README.md:6` |
| 12 | The code does not create `data/`, `data/tmp/`, `logs/` or the `queue` table | A fresh or cleaned machine crashes silently (E10) | `intake.py:17-18`, `intake.py:23`, `intake.py:73` |
| 13 | No version string anywhere | Ops cannot confirm an update applied | repo-wide |
| 14 | `logs/intake.log` holds a sender email address, in a line format the current code does not write | Personal data in a file ops reads and may paste into tickets; suggests an older build ran at some point | `logs/intake.log:6` |
| 15 | Quarantined files stay in the temp folder, out of ops' reach, and signature images create Quarantined noise | Ops cannot inspect or forward a quarantined file | `intake.py:46-60` |