Files
Rpa_Skills/tests/evals/results/handoff/h-mail-intake-full-r1.md
T
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

24 KiB

Mail intake bot - ops handover

Version: none (the project has no version number - see section 13, item 11) · 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 every unread email in the referrals mailbox, saves each attachment, and checks that it is a PDF of 20 MB or less that can be opened. Good PDFs are copied to the shared intake folder. Every attachment becomes one item in the bot's queue with a status and a note, which ops read in the queue viewer workbook. The bot has no window of its own and does not drive any desktop app. It only talks to the mailbox and the shared intake folder.

2. How it works

Windows Task Scheduler (every 10 minutes)
   └─ starts → Mail intake bot (no window, runs a few seconds to minutes)
                   ├─ reads  → referrals mailbox (unread mail only; marks it read)
                   ├─ saves  → data/tmp/  (a working copy of every attachment)
                   ├─ copies → shared intake folder (good PDFs only)
                   ├─ writes → the queue (one item per attachment: status + note)
                   │              └─ ops read it in queue_viewer.xlsx (Data > Refresh)
                   └─ writes → logs/intake.log
  • Task Scheduler decides when the bot runs. Nothing runs between the 10-minute starts.
  • The bot is a background script. There is no screen to watch while it works.
  • Referrals mailbox: the bot only sees mail that is still unread. As soon as it reads a mail, the mail is marked read and the bot never looks at it again.
  • data/tmp/ holds a copy of every attachment the bot downloaded. Files are never deleted from here.
  • Shared intake folder: where the good PDFs end up. The file keeps the name it had in the email.
  • The queue is the bot's list of items. Ops see it through queue_viewer.xlsx (columns id, sender, subject, status, note).
  • logs/intake.log is the bot's only log file. One line per finished item, plus warnings and errors.

One run, step by step:

  1. The bot checks the queue. If any item is still Processing from an earlier run, it writes an error to the log and stops. It does not read mail (see E02).
  2. It signs in to the mailbox. If that fails it tries 3 times, 30 seconds apart (see E01).
  3. It reads every unread mail. Each attachment is saved to data/tmp/ and added to the queue as New.
  4. It takes each New item in order and sets it to Processing.
  5. It checks the file: PDF, 20 MB or less, not password-protected.
  6. It copies the file to the shared intake folder and sets the final status and note.
  7. It writes one log line per item: item <id> -> <status> (<note>).

The log has no "run started" or "run finished" line.

3. Before a run

The bot runs by itself, so "before a run" means "before you hand the machine over, and after any change to it".

  • The scheduled task for the bot exists and is enabled in Task Scheduler, set to every 10 minutes.
  • The settings file .env is in the bot's folder and has the mailbox server, mailbox user, mailbox password and shared-folder entries. If an entry is missing, every run crashes and nothing is written to the log (E06).
  • The folders data/, data/tmp/ and logs/ exist in the bot's folder, and the queue file is in data/. The bot does not create them. If one is missing, every run crashes silently (E06).
  • The machine can reach the shared intake folder. Open it in Explorer as the account the scheduled task runs as. If you can't, items end as Failed (E05).
  • The mailbox password has not expired. When it expires, the log fills with "IMAP connect failed" warnings (E01). Ask the RPA dev team when it is next due.
  • What the bot accepts. Ops can't control what senders send, but this tells you what to expect:
    • Accepted: a PDF ending in .pdf (any case), 20 MB or less, with no password. Example: referral_1023.pdf, 2 MB.
    • Quarantined: anything else, including Word files, photos, signature logos and PDFs over 20 MB. Example: scan.jpg or image001.png from an email signature.
    • Lost or overwritten: two attachments with the same file name. The second one overwrites the first in the shared intake folder (E08).

4. During a run

  • Don't open new mail in the referrals mailbox. Opening a mail in Outlook or webmail marks it read, and the bot then skips it for good (E07). If you opened one by mistake, mark it unread again. The next run picks it up.
  • Don't move, rename or open files in data/tmp/. Each queue item points at its file there.
  • Don't edit or rename files in the shared intake folder while the bot is copying. A run is usually short, but there is no "finished" signal.
  • To stop the bot: in Task Scheduler, disable the bot's task. This stops future runs. Don't use "End" on a run that is in progress: stopping it mid-item leaves that item in Processing, and that blocks every later run (E02). If you don't have access to Task Scheduler, ask in #rpa-support.
  • A run looks stuck when:
    • the log shows ERROR Previous item still Processing - aborting again every 10 minutes, or
    • the queue viewer shows an item in Processing for more than 10 minutes.
  • The bot does not recover from this by itself. There is no watchdog and no time limit: the block lasts until a developer releases it. Escalate straight away (E02).

5. Where to look when something goes wrong

Ops can open: the queue viewer (queue_viewer.xlsx), the shared intake folder, and the logs/ folder. Ops cannot open the queue database itself.

Question Where to look
Is the bot running at all? logs/intake.log: the time of the last line. Runs with no new mail write nothing, so a quiet log alone is not an error. Send a test mail with a small PDF to the referrals mailbox. Within about 10 minutes, a new item <id> -> Done line should appear.
Did the last run finish? There is no "finished" line. If no item in the queue viewer is in Processing and the log does not repeat Previous item still Processing, the last run finished.
Which items failed? Queue viewer → Data > Refresh → status column: Failed and Quarantined, and also Done items whose note says encrypted - not readable (these were not delivered, E04).
Why did one item fail? Queue viewer → note column. Then logs/intake.log, search for item <id> ->.
Did the bot already retry? Mailbox sign-in: lines IMAP connect failed (1/3), (2/3), (3/3) in logs/intake.log. Items are never retried: Failed and Quarantined items stay that way.
Is the file really in the shared intake folder? Open the shared intake folder and look for the file name from the item. Compare the page count with the note (<n> pages saved).
A referral never showed up in the queue See E07. The bot keeps no record of mail it read without queueing anything.
Which version is running? You can't see it. The project has no version number (section 10).

6. Statuses

The bot sets no colours. The queue viewer shows the status as plain text in the status column.

Status (note) Colour Meaning What ops does
New (empty note) none Attachment saved and queued, not yet checked. Nothing. It is handled in the same run or the next one. If it is still New after 20 minutes, see E02 and E01.
Processing (empty note) none The bot is working on this item right now. Nothing for the first 10 minutes. Still Processing after 10 minutes = the bot crashed on this item and every later run is blocked → E02.
Done - "<n> pages saved" none Copied to the shared intake folder. Nothing.
Done - "encrypted - not readable" none Needs follow-up. The PDF is password-protected. The status says Done, but the file was not copied to the shared intake folder. E04: ask the sender for a copy without a password.
Failed - "share unreachable: <reason>" none The copy to the shared intake folder failed. The bot never tries again. E05.
Quarantined - "not a PDF or over 20 MB" none Not a PDF, or larger than 20 MB. Not copied. The bot never tries again. E03: usually nothing for signature logos. For a real referral, ask the sender for a PDF under 20 MB.

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 No new items arrive. The log shows WARNING IMAP connect failed (1/3), (2/3), (3/3) and then nothing more for that run. Signing in to the mailbox fails. It tries 3 times, waiting 30 seconds after each try. After the third failure the run stops. That last failure is not written to the log. logs/intake.log warning lines only. The text after the colon gives the reason: "getaddrinfo failed" means network or name lookup; an authentication or login message means a wrong or expired password, or a locked account. System Bot, then Dev Wait for the next run (10 minutes later). A one-off network blip clears by itself. If the reason mentions login or authentication, the mailbox password has probably expired or the account is locked. Three runs in a row (about 30 minutes) each end at (3/3), or any login/authentication reason. Send: the time of the first (1/3) line, the reason text from the warning (never the password), and logs/intake.log.
E02 Nothing new for a long time. The log shows ERROR Previous item still Processing - aborting every 10 minutes. One item in the queue viewer is stuck in Processing. At the start of every run, the bot looks for any item still in Processing. If it finds one, it stops at once without reading mail. This happens after a crash in the middle of an item, for example on a damaged PDF, a missing file in data/tmp/, or someone ending the task. logs/intake.log error line; the queue viewer status column. System Dev The bot will not clear this by itself, and ops can't release it (it needs the database). Note the id, sender and subject of the Processing item. Check whether its file is already in the shared intake folder. Meanwhile, new mail waits safely in the mailbox as unread. Always, as soon as you see the line twice. Send: the item id, the time the first error line appeared, whether the file is in the shared intake folder, and logs/intake.log.
E03 Item Quarantined, note not a PDF or over 20 MB. The file name does not end in .pdf, or the file is larger than 20 MB. Queue viewer status and note; log line item <id> -> Quarantined. Business Ops Look at the subject and sender. Signature logos and inline pictures (for example image001.png) also land here: ignore them. For a real referral, ask the sender to resend it as a PDF under 20 MB. The resend arrives as a new item. The file really is a PDF under 20 MB and was still quarantined. Send: the item id and the file name.
E04 Item Done, note encrypted - not readable, and the file is not in the shared intake folder. The PDF is password-protected. The bot stops there and does not copy it, but it records the status as Done. Queue viewer note column only. The status column alone looks like success. Business Ops Ask the sender for a copy without a password. The new copy arrives as a new item. Check for these every day by filtering the note column on "encrypted". Never needed for the item itself. The misleading status is on the dev list (section 13).
E05 Item Failed, note share unreachable: <reason>. Copying the file to the shared intake folder fails: folder offline, no permission, disk full, or a file with the same name is locked. Queue viewer status and note; log line item <id> -> Failed. System Ops, then Dev 1. Check that you can open the shared intake folder and that it has free space. 2. Look for the file there: a partial copy can be left behind. 3. The bot never retries a Failed item, so ask dev to put it back to New once the folder works again. Don't ask the sender to resend: that creates a duplicate. Always, to re-queue it. Also escalate straight away if several items fail in a row. Send: the item ids, the reason text from the note, and the time.
E06 The log stops completely: no new lines at all, not even warnings, although new mail with attachments is waiting. The bot crashes at start-up because something it needs is missing: an entry in the settings file, the data/ or logs/ folder, or the queue file. It writes nothing to the log. Nowhere ops can see. Only in Task Scheduler's "Last Run Result" for the task. System Dev Check that the scheduled task is enabled (section 3). Send a small test PDF to the mailbox. If no item line appears within 20 minutes, escalate. Always. Send: the time of the last log line, and the Task Scheduler "Last Run Result" if you can see it.
E07 A sender says they sent a referral, but there is no item for it in the queue viewer. No check. The bot only reads unread mail and marks it read straight away. A mail that someone opened first, a mail with no attachment, or a run that crashed while reading mail all leave no item and no log line. Nowhere. Business / System Ops, then Dev 1. If you can see the mailbox, find the mail. If it is there with an attachment, mark it unread: the next run picks it up. 2. If it has no attachment, ask the sender to attach the PDF. 3. Otherwise escalate. The mail is unread with an attachment and still not queued after 20 minutes, or several referrals are missing. Send: the time sent and the subject (no patient details in chat).
E08 Two items show Done, but the shared intake folder holds only one file, or the file doesn't match one of the senders. No check. The bot saves files under the name from the email, so a second attachment with the same name overwrites the first, both in data/tmp/ and in the shared intake folder. Queue viewer (two items, same file name in the subject or sender context); shared intake folder. System Ops, then Dev Ask the sender whose file was overwritten to resend it with a different file name. Always. Send: both item ids and the file name.

8. What the bot recovers by itself

Problem What the bot does Limit After the limit
Mailbox sign-in fails Tries again after 30 seconds 3 tries, about 90 seconds in total The run stops silently. The next scheduled run tries again 10 minutes later, forever, with no alert (E01).
Run stopped before items were handled New items left over are picked up Next scheduled run n/a
Unread mail not yet read Stays unread in the mailbox Until a run gets past sign-in n/a

The bot does not recover from any of these: an item stuck in Processing (E02), a Failed or Quarantined item (never retried), a crash at start-up (E06), or a missing referral (E07). Ops can wait out an E01 for about 30 minutes before escalating. For everything else, act as soon as you see it.

9. Known incidents

All three are recorded in the project history on 2026-10-23. Each was marked "fixed", but the bot's behaviour did not change: the fix records contain notes only. Treat all three as still open.

When / version What ops saw Cause What to do now Ops could handle?
2026-10-23 / no version No new referrals all day. No errors except the repeating "IMAP connect failed" warnings. The mailbox password had expired. The bot only writes warnings and never logs that it gave up. E01: three runs in a row ending at (3/3), or any login reason, → escalate for a password reset. Still not fixed. Partly: the warnings are visible, but nothing alerts anyone.
2026-10-23 / no version Referrals showed Done but never reached the shared intake folder (password-protected PDFs). Password-protected PDFs are recorded as Done with the note "encrypted - not readable", and not copied. E04: filter the note column on "encrypted" every day and ask senders for an unlocked copy. Still not fixed. Partly: possible only if ops reads the note, not the status.
2026-10-23 / no version Nothing reached the shared intake folder for a whole day. The log repeated "Previous item still Processing - aborting". The bot crashed in the middle of one item. That item stayed in Processing and blocked every later run. Ops reset it by hand. E02: escalate on the second error line. Still not fixed. Partly: ops can spot it quickly with this doc, but releasing it needs dev (database).

10. Releases and version check

  • How an update arrives: there is no updater. A developer replaces the bot's files in its folder, and the next scheduled run uses the new files.
  • How to confirm it applied: ops can't. The bot has no version number and doesn't write one to the log. Ask the developer to confirm in #rpa-support which change went in, and check that the next runs write normal item <id> -> ... lines.
  • If the behaviour didn't change after an update: report it in #rpa-support with the time of the update and a log line that shows the old behaviour.
  • Only one machine should run the bot's scheduled task. Two machines reading the same mailbox would split the mail between them.

11. Escalating to dev

Post in Teams #rpa-support. Send:

  • the exception ID from section 7 (for example "E02")
  • the item id(s) from the queue viewer
  • the time of the first related log line
  • the logs/intake.log file (attach it; don't paste lines that contain sender addresses)
  • whether the file is in the shared intake folder

Never send: passwords, the .env settings file, patient details, attachments, or the contents of referrals in chat.

12. Failure-class check

  • F1 Missing prerequisite: covered in section 3 (settings file, folders, queue file, folder access, password expiry), E06, and section 13 items 5 and 13.
  • F2 Wrong window / focus: not applicable. The bot drives no desktop app or window; it only talks to the mailbox and the file share.
  • F3 Target slower or different than expected: covered in E01 (mailbox, 3 tries x 30 s) and E05 (shared folder). There are no screen timeouts. Section 13 item 14 covers the lack of time limits.
  • F4 Input read differently: covered in section 3 (accepted and quarantined examples, same-name files), section 4 (opening mail marks it read), E03, E07 and E08.
  • F5 Marked done when nothing was done: covered in E04 (Done without copying) and E07 (mail marked read with no item). Section 13 items 3 and 7.
  • F6 Action happened but not confirmed: covered in E02 (file may already be in the shared folder; check before re-queueing) and E05 (partial copy; don't ask for a resend).
  • F7 Business exception shown as success: covered in section 6 (Done - "encrypted - not readable" = needs follow-up), E04, and section 13 item 3.
  • F8 Endless re-runs / watchdog: covered in section 8 (mailbox retries forever, every 10 minutes, with no alert), E01 and E02. There is no watchdog. Section 13 items 1 and 4.
  • F9 Stopping the wrong way: covered in section 4 (disable the task; never end a run mid-item).
  • F10 One stuck item blocks the queue: covered in E02, section 4 and section 6 (Processing). Section 13 item 1.
  • F11 Cause hidden from ops: covered in E06 (crash cause only in Task Scheduler) and E07. Section 13 items 4, 5, 9, 10 and 12.
  • F12 Update didn't arrive: covered in section 10 (no version, no updater; one machine only). Section 13 item 11. The part about shared resources being rewritten on start is not applicable: the bot rewrites nothing shared on start.

13. Fix before handover (dev team)

# Gap Why it hurts ops Where (file:line)
1 One item left in Processing aborts every later run. There is no stale timeout, no auto-reset and no alert. Commit 4d3e78c only added a comment. The bot stops for hours or days. Ops can't release it without the DB. intake.py:74-76, intake.py:78-80, intake.py:89
2 process() has no handling for a damaged or unreadable PDF (PdfReader) or a missing temp file (p.stat()). The run crashes and leaves the row Processing, which causes #1. Turns one bad attachment into a full outage. intake.py:59, intake.py:61
3 An encrypted PDF returns "Done" without copying. It should be its own status (for example Quarantined or Failed). Commit 4beebcc only added a comment. Undelivered referrals look like successes. intake.py:62-63, intake.py:90
4 The final mailbox failure (RuntimeError("Mailbox unreachable")) is never caught or logged. A login failure is not told apart from a network failure. There is no alert. Commit 115f761 only added a comment. Silent outage when the password expires (incident 1). intake.py:34-37, intake.py:77, intake.py:91
5 Unhandled exceptions and tracebacks go to stderr only, not to logs/intake.log. A missing env var (KeyError), a missing folder, or a missing table crash with no log line. The cause is visible only in Task Scheduler, which ops may not have access to (not confirmed). intake.py:23-24, intake.py:31-32, intake.py:73, intake.py:87-88
6 Mail is fetched with RFC822, which marks it read on the server, but the rows are committed only after the whole loop. A crash during the fetch loses referrals with no trace. Referrals vanish (E07). intake.py:44, intake.py:54
7 Mail with no attachment, or mail read by a person first, leaves no record anywhere. Ops can't prove whether a referral was received. intake.py:42, intake.py:46-49
8 The attachment name is used as-is for data/tmp and the share. Same names overwrite each other, and the name is not sanitised (a path like ..\ can write outside the folder). Lost or swapped referrals (E08); a security risk. intake.py:50, intake.py:65
9 Failed and Quarantined are never retried, and re-queueing needs a DB edit that ops can't make. Every share outage needs dev time (E05). Add a re-queue option in the viewer or a retry for Failed. intake.py:66-67, intake.py:78
10 queue_viewer.xlsx, the ops screen named in the README, is not in the repo. Its columns and refresh source can't be checked. Ops' only view of the queue is unversioned. README.md:6
11 No version string anywhere, and none written to the log. Ops can't confirm an update applied (F12). intake.py:1-2, intake.py:71
12 No "run started / run finished" log line, and no count of mails read. Ops can't tell a healthy quiet run from a dead bot. intake.py:71-84
13 .env (mailbox credentials) and logs/intake.log are tracked in git since the initial import. The log contains a sender email address. Rotate the mailbox password, remove both files from history, and add them to .gitignore. Credential and personal-data exposure. .env, logs/intake.log:6
14 No timeout on the IMAP connection or on the share copy, beyond the OS defaults. A hung run holds an item in Processing and causes #1. intake.py:31, intake.py:65
15 No lock against overlapping runs. Two runs can pick up the same New rows if Task Scheduler starts one while another is still running. Duplicate copies; confusing statuses. intake.py:74, intake.py:78
16 Nothing creates data/, data/tmp/, logs/ or the queue table. On a fresh machine, sqlite silently creates an empty queue.db and the run fails. Setup on a new machine fails silently (E06). intake.py:17-18, intake.py:23, intake.py:73
17 Every MIME part with a filename is queued, including inline signature images, which are then Quarantined. Clutter that hides real quarantines. intake.py:46-53
18 data/tmp/ is never cleaned up. The disk slowly fills with copies of referrals (personal data at rest). intake.py:50-51
19 The share path falls back to a hard-coded default when INTAKE_SHARE is unset. A misconfigured machine copies to an unexpected location. intake.py:19
20 Confirm whether ops can open Task Scheduler (the task's history and the Disable option). Sections 4 and E06 depend on it. Ops may not be able to stop the bot or see crash results. n/a (access question)