Files
VasanthandClaude Opus 5.5 3942fad6cd 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>
2026-10-28 15:01:42 +05:30

168 lines
18 KiB
Markdown

# Mail intake bot - ops handover
Version: none shown by the bot (current code = commit 7d6daa4) · Written 2026-10-23 · Escalation: RPA dev team, Teams channel **#rpa-support**
## 1. What the bot does
Every 10 minutes (Windows Task Scheduler) the bot reads the **unread** emails in the referrals mailbox. It saves every attachment, checks that it is a PDF under 20 MB, and copies it to the **shared intake folder**, where the referrals team picks it up. Each attachment becomes one numbered item in the bot's queue with a status (Done, Failed, Quarantined...). The bot drives no windows and no desktop apps: it talks to the mailbox and the shared folder directly. Its only output is the PDFs in the intake folder and the log file `logs/intake.log`.
## 2. How it works
```
Task Scheduler (every 10 min)
└─ starts → intake bot (no window)
├─ reads unread mail ──> Referrals mailbox (marks the mail as read)
├─ saves attachments → bot folder data/tmp
├─ records each item → queue database (data/queue.db - dev only)
├─ copies good PDFs → Shared intake folder
└─ writes → logs/intake.log (one line per item)
```
- **Task Scheduler** starts the bot every 10 minutes. There is no app window to watch.
- **Intake bot** does one pass and exits. If the previous pass left an item half-done, it refuses to start (E03).
- **Referrals mailbox**: the bot only looks at unread mail. Once it has read an email, that email is never looked at again, even if something went wrong.
- **data/tmp**: working copy of every attachment. Ops cannot reach it.
- **Queue database**: one row per attachment with sender, subject, file, status and note. Ops cannot open it. Only the dev team can read or change it.
- **Shared intake folder**: the result. A referral that is not here was not delivered.
- **logs/intake.log**: the only place ops can see what happened to each item.
**One run, step by step:**
1. Stop at once if any item from an earlier run is still "Processing" (E03).
2. Sign in to the mailbox (3 tries, 30 s apart).
3. For every unread email: mark it read, save each attachment, add a "New" item per attachment.
4. For every "New" item, oldest first: set it to "Processing", check it, copy it to the intake folder, then set Done / Failed / Quarantined.
5. Write one line per item to the log: `item <number> -> <status> (<note>)`.
## 3. Before a run
- [ ] The bot machine can open the shared intake folder and reach the mailbox.
- [ ] The settings file (`.env`) is in the bot folder and holds the mailbox address, user, password and the intake folder location. Ops never opens or sends it. If it is missing or the mailbox password expired, every run fails (E01, E02).
- [ ] The `data` folder exists in the bot folder, with the queue database and an empty `tmp` folder inside. The bot does not create them; without them the run stops at once and writes nothing to the log (E09).
- [ ] When the mailbox password is changed or about to expire, tell the dev team first so they update the settings file.
- [ ] Input rules for senders (share these with the referral senders):
- Attach the referral as a **PDF**. Bad: a Word file or a phone photo. Good: `referral.pdf`.
- **Under 20 MB** per file.
- **No password** on the PDF. A protected PDF is not delivered, although it is marked Done (E06).
- Give each file a **distinct name**. Bad: every referral named `scan.pdf`. Good: `referral_2026-10-23_01.pdf`. Same-named files overwrite each other (E08).
- Put the referral in an attachment. Text in the email body is ignored (E10).
- [ ] Logos and pictures in email signatures are attachments too. They will show as Quarantined. That is expected.
- [ ] The bot has no version display. See section 10.
## 4. During a run
- Do not move, rename or open files in the bot folder while it runs.
- Do not mark emails in the referrals mailbox as read by hand: the bot only picks up unread mail. An email someone opened is skipped for good.
- To stop the bot: **disable its task in Task Scheduler** (ask the dev team if you have no access to the bot machine), then wait until the log has no new lines for 2 minutes. **Never end the bot's process while it is working on an item** - the item stays "Processing" and blocks every later run (E03).
- A run looks stuck when the log repeats "Previous item still Processing - aborting" every 10 minutes (E03), or when the log has no new line for more than 30 minutes while mail is arriving (E09). The bot has **no time limit and no watchdog**: it never gives up by itself. Escalate at that point.
## 5. Where to look when something goes wrong
Ops can open: the shared intake folder and `logs/intake.log`. Everything else needs the dev team.
| Question | Where to look |
|---|---|
| Did the bot run? | `logs/intake.log`: a new line about every 10 minutes when mail arrives. No line for a quiet mailbox is normal. |
| Did a run stop early? | `logs/intake.log`: "IMAP connect failed (3/3)" with no item lines after it (E01/E02), or "Previous item still Processing - aborting" (E03). |
| Which items failed? | `logs/intake.log`: search for `-> Failed`, `-> Quarantined` and `encrypted - not readable`. |
| Why did one item fail? | The note in brackets at the end of that log line. |
| Which email / sender was it? | **Not visible to ops.** The log shows only the item number. Ask the dev team in #rpa-support with the item number. |
| Was the referral delivered? | Look for the file in the shared intake folder. |
| Did the bot already retry? | Only the mailbox sign-in is retried ("IMAP connect failed (1/3)", "(2/3)", "(3/3)"). Nothing else is ever retried. |
| Which version is running? | Not shown. Ask the dev team (section 10). |
## 6. Statuses
The bot has no screen, so statuses have no colour. Ops sees them in the log line `item <number> -> <status> (<note>)`.
| Status (note) | Colour | Meaning | What ops does |
|---|---|---|---|
| New | none, not in the log | Attachment saved, waiting to be copied in this run | nothing |
| Processing | none, not in the log | Being checked and copied right now. **If it stays, it blocks every later run.** | If "Previous item still Processing - aborting" appears, escalate (E03) |
| Done ("<n> pages saved") | none | PDF copied to the intake folder | nothing |
| Done ("encrypted - not readable") | none | **Needs follow-up.** Password-protected PDF. It was **not** copied to the intake folder, although it says Done. | E06 |
| Failed ("share unreachable: ...") | none | Could not copy to the intake folder. **Never retried.** | E07 |
| Quarantined ("not a PDF or over 20 MB") | none | Not copied: wrong file type or too big | 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 | Log: "IMAP connect failed (1/3)" ... "(3/3)" with a network message (e.g. "getaddrinfo failed"), then nothing more for that run | It cannot reach the mailbox. It tries 3 times, 30 s apart, then gives up on this run | Log warning lines only. The final "gave up" is not logged | System | Bot, then Ops | Wait for the next run (10 min). Check whether the bot machine has network | "(3/3)" appears in 3 runs in a row (about 30 min). Send: times of the lines and `logs/intake.log` |
| E02 | Same "IMAP connect failed" lines, but the message mentions login, authentication or credentials | The mailbox rejects the user or password (for example the password expired) | Log warning lines only | System | Dev | Nothing ops can fix: the password is in the settings file | At once. Send: time of the first line and `logs/intake.log`. Never send the password in chat |
| E03 | Log: "Previous item still Processing - aborting" every 10 minutes; no new files arrive in the intake folder | At start it finds an item still "Processing" from an earlier run and stops before reading mail | Log error line, repeated each run | System | Dev | Nothing is lost: new mail stays unread in the mailbox and is picked up once the block is cleared. Note the last `item <number> ->` line before the first abort: the blocked item is usually the next number. Check whether that file already reached the intake folder and tell dev | At the first abort line. Send: time of the first abort, the last item number before it, whether the file is in the intake folder, `logs/intake.log` |
| E04 | A run stops in the middle: the next item number never gets a log line, and the next run shows E03 | Not detected. An attachment the bot cannot read (a damaged PDF, or a file named `.pdf` that is not really a PDF) makes the bot crash mid-item | Nothing in the log; leads to E03 | System | Dev | Same as E03 | Same as E03 |
| E05 | Log: `-> Quarantined (not a PDF or over 20 MB)` | The file name does not end in `.pdf`, or the file is over 20 MB | Log line; file not in the intake folder | Business | Ops (with Dev to identify the email) | If it is a signature logo or picture (most cases), nothing. Otherwise ask dev in #rpa-support for the sender and subject of the item, then ask the sender to resend it as a PDF under 20 MB | You cannot tell whether it was a real referral - send the item number and time |
| E06 | Log: `-> Done (encrypted - not readable)` | The PDF is password-protected | Log line; **file not in the intake folder** although it says Done | Business | Ops (with Dev to identify the email) | Ask dev for the sender and subject of the item, then ask the sender to resend without a password | Always, to get the sender. Send the item number and time |
| E07 | Log: `-> Failed (share unreachable: ...)`, often for several items in a row | Copying to the intake folder fails (folder offline, no permission, full disk) | Log line; file not in the intake folder | System | Ops, then Dev | Check that the intake folder opens from the bot machine; if not, raise it with IT. Failed items are **never retried** by the bot | Always, once the folder works again: dev must re-queue the failed items. Send the item numbers and times |
| E08 | A sender says they sent two referrals but only one arrived, or a file in the intake folder suddenly has different content | Not detected. Two attachments with the same file name overwrite each other, in the bot folder and in the intake folder | Nothing; both items show Done | System | Dev | Ask senders to use distinct file names (section 3) | When a referral is reported missing. Send the approximate send time and the file name if known |
| E09 | The log has no new line for over 30 minutes while referrals are arriving, and no E01/E03 lines | Not detected. The bot either hangs waiting for the mailbox or the intake folder (it has no time limit), or stops at start because the `data` folder or the settings file is missing | Nothing in the log | System | Dev | Check whether the intake folder still opens. Nothing else ops can do | After 30 minutes. Send the time of the last log line |
| E10 | A sender says they sent a referral but nothing arrived and no new item appears in the log | The email had no attachment (referral typed in the body, or a link). The bot marks it read and moves on | Nothing | Business | Ops | Ask the sender to resend with the referral attached as a PDF | Sender insists it had an attachment - send the approximate send time |
| E11 | Referrals sent around the time of a crash (E04 or a restart) never appear, and the log has no items for them | Not detected. The bot marks emails read while downloading and only records them at the end of the download; a crash in between loses them | Nothing | System | Dev | Ask the sender to resend | Always. Send the approximate time window |
## 8. What the bot recovers by itself
| Problem | What the bot does | Limit | After the limit |
|---|---|---|---|
| Mailbox unreachable or sign-in rejected | Tries again after 30 s | 3 tries, about 1.5 minutes | This run stops. The next scheduled run (10 min later) starts over |
| New mail missed by a stopped run | The next run reads all mail still unread | every 10 minutes | - |
| Anything else (copy failed, item stuck in Processing, hang) | **Nothing.** No retry, no restart, no watchdog | - | Stays as it is until the dev team acts |
## 9. Known incidents
The three fixes in the history only added a note to the code; the bot's behaviour did not change with them. What is described below is how the bot behaves today.
| When / version | What ops saw | Cause | What to do now | Ops could handle? |
|---|---|---|---|---|
| Logged 2026-10-23 (commit 7d6daa4) | Every run failed and nobody noticed | The mailbox password expired | The sign-in error now shows in the "IMAP connect failed" lines. Watch for them and escalate (E02). Tell dev before the password changes | Partly |
| Logged 2026-10-23 (commit 0749014) | Password-protected PDFs reached the intake folder empty | The bot could not read them | They are no longer copied, but they still show **Done** (E06). Search the log for "encrypted" | Partly |
| Logged 2026-10-23 (commit ae3d441) | No referrals delivered for a whole day | A crash left one item in Processing; every later run stopped (E03). Ops reset it by hand in the database | Still possible. Ops now has no database access: spot the abort line and escalate at once (E03) | Partly |
| 2026-09-04 (log) | Mailbox sign-in failed with a network error, then two runs in a row stopped with "Previous item still Processing" | Network lookup failure, then a stuck item | E01, then E03 | Yes, with E01/E03 |
## 10. Releases and version check
- How an update arrives: the dev team copies the new bot files onto the bot machine by hand. There is no launcher and no automatic update.
- How to confirm it applied: the bot shows no version anywhere. Ask the dev team to confirm in #rpa-support which version is on the machine.
- If the version did not change: report it in #rpa-support. Ops does not copy bot files.
## 11. Escalating to dev
Post in the Teams channel **#rpa-support** to the RPA dev team.
Send: the exception ID from section 7, the item number(s) from the log, the time of the first bad log line, whether the file is in the intake folder, and `logs/intake.log`.
Never send: passwords, the settings file (`.env`), patient details, sender names or email subjects in chat.
## 12. Failure-class check
- F1 covered in section 3 (settings file, `data` folder) and E02, E09.
- F2 not applicable: the bot drives no windows; it talks to the mailbox and the shared folder directly.
- F3 covered in E01, E09 (no time limit on mailbox or folder) and Fix #6. Screen timing is not applicable.
- F4 covered in section 3 input rules and E05, E08, E10.
- F5 covered in E06 (Done without delivery) and E11 (emails marked read but never recorded); Fix #3, #5.
- F6 covered in E03 (check whether the file already reached the intake folder before dev re-queues) and Fix #1.
- F7 covered in section 6 and E06; Fix #3.
- F8 covered in section 8 and E03 (abort repeats every 10 min forever), E09 (hang, no watchdog); Fix #1, #6.
- F9 covered in section 4 (disable the scheduled task; never end the process mid-item).
- F10 covered in E03/E04; Fix #1, #2.
- F11 covered in section 5 (queue and sender not visible to ops) and Fix #4, #7, #8.
- F12 covered in section 10; Fix #11.
## 13. Fix before handover (dev team)
| # | Gap | Why it hurts ops | Where (file:line) |
|---|---|---|---|
| 1 | Any item left "Processing" makes every later run abort, forever. No timeout, no auto-reset, and the item is not named in the log | One crash stops all intake until dev edits the database (incident ae3d441, "fix" was a comment only) | `intake.py:74-76`, `intake.py:89` |
| 2 | Reading the PDF is not protected: a damaged or fake PDF crashes the run mid-item (also a missing file at `p.stat()`) | Causes E03; ops sees no reason in the log | `intake.py:59-61`, `intake.py:79-81` |
| 3 | Password-protected PDFs are stored as status Done | Ops thinks the referral was delivered | `intake.py:62-63` |
| 4 | The final "Mailbox unreachable" error and any crash traceback go to the console, not to `logs/intake.log` | Ops sees a run stop with no reason | `intake.py:37`, `intake.py:23-24`, `intake.py:87-88` |
| 5 | Mail is fetched (marked read) before its queue rows are committed; a crash in between loses the email. Emails with no attachment are marked read with no log line | Referrals silently lost (E10, E11) | `intake.py:43-54` |
| 6 | No timeout on the mailbox connection or on the copy to the share; no watchdog | A hang stops intake with no log line (E09) | `intake.py:31`, `intake.py:65` |
| 7 | Log lines show only the item number - no file name, no sender/subject reference | Ops cannot act on E05/E06 without dev | `intake.py:84` |
| 8 | README says ops view the queue in `queue_viewer.xlsx`, but that file is not in the repo and reads the database ops cannot open | Ops has no view of statuses except the log | `README.md:6` |
| 9 | Failed items are never retried; only "New" items are processed | A short share outage needs dev to re-queue every item (E07) | `intake.py:78` |
| 10 | Attachments are saved and copied under their original name: same names overwrite each other in `data/tmp` and in the share; the name is not cleaned (path characters) | Lost referrals (E08); a crafted file name could write outside the folder | `intake.py:50-51`, `intake.py:65` |
| 11 | No version string anywhere; deploy is a manual copy | Ops cannot check which build runs (F12) | `intake.py` (whole file) |
| 12 | The bot does not create `data/`, `data/tmp` or the queue table; the share defaults to a hard-coded server path when the setting is missing | A fresh or rebuilt machine fails at start with nothing in the log | `intake.py:17-19`, `intake.py:73` |
| 13 | A `BOT_WAS_RUN` file is written in the bot folder at every start; purpose not documented | Ops may wonder whether to delete it | `intake.py:72` |
| 14 | The mailbox sign-in waits 30 s after the last failed try as well | Each failed run takes 30 s longer than needed (minor) | `intake.py:36` |
| 15 | `logs/intake.log` has no rotation, and holds a sender email address in an older line format the current code no longer writes | Log grows forever; personal data sits in a file ops is asked to send to dev | `intake.py:23`, `logs/intake.log:6` |