Self-healing agent (supervisor, recovery, login fixes, operator mail) and Portal sage redesign
Snapshot of D:\Ecw Process a11c9ff (2026-10-30). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fafa5285eb
commit
d500f750da
26 files changed
+1704
-357
No files matched your search
+91
-1
@@ -40,11 +40,50 @@ Repo: `D:\Ecw Process`, git branch `master`, **no remote** (never pushed).
|
||||
|
||||
```bash
|
||||
python run.py # the bot (logs into LIVE eCW)
|
||||
python agent.py # the agent: the whole day's queue, self-healing (below)
|
||||
python tests/test_<name>.py # one test file, prints "N/M passed"
|
||||
run_web.bat # results portal, http://127.0.0.1:8000
|
||||
start_ecw_chrome.bat # Chrome the bot attaches to (BROWSER_CDP_URL)
|
||||
```
|
||||
|
||||
**The agent (2026-10-30, operator: "we are an agent, not a bot — observe,
|
||||
fix, continue, and mail me what happened").** `python agent.py`
|
||||
(`flows/supervisor.py`) runs the bot as a child process, pass after pass,
|
||||
until every claim in the day's Medcor Ready queue has a result. Pass 1
|
||||
downloads the live queue; a later pass takes only the claims still
|
||||
pending — the queue file minus every `CV_ChargeSummary` row since the
|
||||
agent started, a "Bot could not ..." Review not counting — through
|
||||
`RESUME_CLAIM_IDS_FILE` (live mode, live Charge Summary, no TEST label,
|
||||
no second export). After each pass, by exit code (`next_action`):
|
||||
login failure (1, 6) → retry after 10 then 20 min, the 3rd in a row stops
|
||||
the agent (the client's account must not be restricted); restricted (4),
|
||||
screen changed (7), config (2) → stop at once; stuck page (9), stall (8),
|
||||
claims error (5) → fresh Chrome + login in 1 min; guard wait (3) → wait;
|
||||
a clean pass leaving the same claims pending → stop ("left for a
|
||||
person"); 15 passes a day at most. VERIFY only: refuses to start with
|
||||
`SAVE_CORRECTIONS=1`; forces `QUIET_BOXES=1`, `SHOW_EACH_CLAIM=0`,
|
||||
`CLAIM_PROCESS_LIMIT=0`. Every failure and the end are mailed
|
||||
(`core/notify.py`, from the 2FA mailbox's account over SMTP — `SMTP_*`
|
||||
default to `IMAP_*`, port 465; **`NOTIFY_EMAIL_TO` blank = no mail, and it
|
||||
is blank on this PC until the operator gives the address**). A mail
|
||||
carries no claim number (6+ digit runs masked) and only login / error
|
||||
page PNGs (`notify._EMAILABLE`) — never a claim screen or page HTML.
|
||||
Inside a pass, `flows/recovery.py`: a claim the bot could not search or
|
||||
read → login page on screen = session over (exit 9); else Escape, close
|
||||
Patient Information, clear the screen, reopen the claim search if still
|
||||
blocked, and try the claim once more; 2 claims in a row still failing
|
||||
after recovery → exit 9 (live 2026-10-29: a Dental claim's sliding fee
|
||||
check left Patient Information open and 18 claims went "Bot could not
|
||||
search" one after another). Login: the security image page's Continue is
|
||||
clicked by the bot (`login.continue_security_image`, a person only when no
|
||||
Continue/OK is found; the page is saved as `security_image_page` the first
|
||||
time); a 2FA link approved but not picked up in `OTP_PICKUP_SECONDS` (60)
|
||||
→ Resend OTP + approve the new mail, `OTP_PICKUP_RESENDS` (2) times
|
||||
(live 2026-10-29 night: three logins lost to mail 6 to 8.5 min late with
|
||||
Resend still on screen). The "Chrome open" and security image boxes are
|
||||
quiet with `QUIET_BOXES=1` (a `[BOX]` log line); CAPTCHA and manual 2FA
|
||||
boxes still show — they need a person. **None of this has run live yet.**
|
||||
|
||||
**Watching a run live (2026-10-22, `8af5c14`):** `start_ecw_chrome.bat`
|
||||
opens Google Chrome with its own profile `D:\EcwChrome` (`CDP_PROFILE_DIR`),
|
||||
debug port 9222 on 127.0.0.1, the eCW proxy (claude.ai / anthropic.com go
|
||||
@@ -305,6 +344,9 @@ that box and on the per-claim save box means Cancel.
|
||||
| `core/page_utils.py` | `shot()` with a FAILURE tag (`is_failure_tag`: failed / missing / not_ / no_ / unconfirmed ...) also saves the page's DOM + frames beside the png as `<HHMMSS>_<tag>.html` (`SAVE_DOM_ON_FAILURE=1`, at most `SAVE_DOM_LIMIT=30` a run; 2026-10-21) — no more hand-copying DevTools into Dom.txt. `visible()` = instant check; `appears()` = real wait (Playwright 1.62's `is_visible(timeout)` never waits); `click_topmost()` clicks the copy on top when dialogs stack (never `.first`) |
|
||||
| `core/fallback.py` + `selectors/fallbacks.py` | Fallback selectors (2026-10-21): the run-critical selectors are CHAINS — primary first, then alternatives taken from the live DOM (ng-click / ng-model / type+value, plain CSS) — joined as a CSS list, so every call site falls back with no change: password field, Log In, Claim No, Lookup, UB Cancel (`closeUBClaimScreen()`, never the X or OK), Dental Cancel (`closeDntl()`), Prog. Notes (`#UBClaimProgressNoteBtn`, `claimProgressNoteBtn<ts>`). `report()` logs `[SELECTOR] fallback: <name> — <primary> not found, matched <alt>` once a run (pre-flight and login call it) |
|
||||
| `pages/preflight.py` | Pre-flight selector check (2026-10-21): the claims search page before the first claim, the claim form on the first claim of each screen type (UB / HCFA / Dental: Cancel, CPT tab, rows with code / fee / POS / M1). Missing → `[PREFLIGHT] FAIL <names>`, page shot + DOM saved, run stops with **exit 7** (`PREFLIGHT_STOP=0` only warns). No CPT row on a claim → its row checks wait for the next; 3 in a row = rows missing |
|
||||
| `flows/supervisor.py` + root `agent.py` | The agent (2026-10-30, §2): passes of the bot as a child process until nothing is pending; `next_action(code, pending, state)` is the whole retry policy, `pending(queue, rows)` the resume list |
|
||||
| `flows/recovery.py` | A stuck screen inside a pass (§2): `recover()` (logout check, Escape + Patient Information close + clear, reopen search) and `run_claim()` (one retry per claim, 2 in a row → `PageStuck`, exit 9) |
|
||||
| `core/notify.py` | The agent's mail (§2): `incident()` / `summary()`; claim numbers masked, login / error PNGs only; never fatal |
|
||||
| `core/watchdog.py` | Claim watchdog (2026-10-22): `watching(limit)` around the claim loop, `beat(where)` at each claim step and every message box, `check()` raises `Stalled` → exit 8; on a stall it closes this process's Playwright driver (`node.exe`) so the frozen call returns, and exits 8 itself if the main thread never comes back |
|
||||
| `core/run_events.py` | A Run's timed events → `Logs\events_<run>.jsonl` (`start`, `emit`, `warning`, `claim_error`, `run_error` with traceback, `login_attempt_start/end`, `login_step`); never raises, never writes an OTP code / password / username |
|
||||
| `core/browser.py` | `launch()`: Playwright Chromium with the eCW proxy, or (`BROWSER_CDP_URL`) attach to the operator's Chrome — `clear_ecw_data()` at attach and close, `cdp_ready()` checked before login |
|
||||
@@ -583,6 +625,22 @@ the Portal (restarted 2026-10-26, [portal] terminal tab).
|
||||
header `X-Run-Token` must match the token in the page; else 403),
|
||||
`GET /api/bot/status`. Spec / plan:
|
||||
`docs/superpowers/specs/2026-10-14-start-bot-from-web-page-design.md`.
|
||||
- **Sage redesign (2026-10-30, the operator-approved mockup, live on
|
||||
Dokploy that day from `portal-20261030-ui.zip`).** `base.html`: the navy
|
||||
header became a sage side menu (`<aside class="side">`: brand, mode pill,
|
||||
links with CSS-mask icons, the user's name over their role, Sign out);
|
||||
breadcrumb and footer in the page column; Outfit + Inter from Google
|
||||
Fonts; the old CSS variable names kept with sage / lime / Pass green /
|
||||
Fail orange / Review blue values, so every page follows. Dashboard:
|
||||
"Good morning|afternoon|evening, <first name>" + claim search, 4 tiles
|
||||
with %, the lime **Agent run** card (the old Bot run card, same ids and
|
||||
script) beside **Results by day**, **Top reasons today** beside **Runs
|
||||
today** (`app._runs_today`: today's rows grouped by `run_at`, newest
|
||||
first — no extra query). Sign in: sage panel + "Welcome back" card.
|
||||
Not built: Queue / Pending tiles (the Portal cannot see the bot PC's
|
||||
queue file — the agent would have to write the queue size to the DB).
|
||||
The mockup canvas: claude.ai artifact "Charge Validation Portal Mockups"
|
||||
(private to the operator).
|
||||
|
||||
---
|
||||
|
||||
@@ -647,6 +705,13 @@ the Portal (restarted 2026-10-26, [portal] terminal tab).
|
||||
- 2026-10-14 #20 final (operator): ONLY the codes the operator gave — the 41 injection codes (IUD / implant, inhalation and oral J-codes included, as listed) and 96372 as the one admin code. No other code is added or counted; no client confirmation needed.
|
||||
- 2026-10-08 Results go to SQL Server `MECARE331\MECARE331`, DB `Charge_Validation`, in the Charge Summary format (incl. PATIENT, Account Number, Guarantor Name); FastAPI page for now, the full portal later.
|
||||
|
||||
- 2026-10-30 The bot becomes an agent: technical failures (login, session, stuck screen, browser) are the agent's to recover from without a person; condition or process mistakes stay the operator's to point out. Mail the operator what happened, what the agent did and whether it worked.
|
||||
- 2026-10-30 Agent mail: from the bot mailbox over SMTP; screenshots of login / error pages only, never a claim screen; no claim numbers.
|
||||
- 2026-10-30 The security image page's Continue is clicked by the bot.
|
||||
- 2026-10-30 Login failures: at most 3 in a row (10 / 20 min apart), then stop and mail — protect the client's eCW account.
|
||||
- 2026-10-30 Bulk runs show no message boxes; the full day's queue (no `CLAIM_PROCESS_LIMIT`) must finish the same day.
|
||||
- 2026-10-30 Portal look: the approved mockup — sage side menu, lime highlight, Outfit + Inter, Dashboard greeting / tiles / Agent run / Results by day / Top reasons / Runs today, two-panel Sign in (no Ecare/Portal toggle: the back end has none).
|
||||
|
||||
### Waiting on a ruling
|
||||
1. An admin code / G2025 that the Fee Schedule prices at **0.00** after being added (pinned in tests).
|
||||
2. `medicare_telehealth` with G2025 **unconfirmed** leaves other rows; `priced_line_check` may then check an unchecked priced row (pinned in tests).
|
||||
@@ -688,7 +753,11 @@ the Portal (restarted 2026-10-26, [portal] terminal tab).
|
||||
|
||||
History: `git log --oneline`.
|
||||
|
||||
Last code commits: `0c2fca8` (2026-10-28, vaccine_z23_pointer #45 /
|
||||
Last code commits: `78409f0` (2026-10-30, Portal sage redesign — §5;
|
||||
deployed to Dokploy from the working tree before this commit, same
|
||||
files), `24c9ce4` (2026-10-30, the self-healing agent: supervisor,
|
||||
recovery, security image Continue, Resend pickup, operator mail — §2,
|
||||
§10), `0c2fca8` (2026-10-28, vaccine_z23_pointer #45 /
|
||||
t1017_non_billable #46 — §4), `d1aa6da` (2026-10-28, login waits for a late
|
||||
security image page — §10), `97d4d74` (2026-10-28, Charge Summary notes a payer the
|
||||
sheet and eCW disagree on — §5), `aaab1ff` (2026-10-28, lab_codes #3/#4,
|
||||
@@ -825,6 +894,27 @@ test claim ids — new posts must not (§7).
|
||||
|
||||
## 10. Open items
|
||||
|
||||
- **Agent (2026-10-30), not yet run live.** To do: `NOTIFY_EMAIL_TO` in
|
||||
`.env` (the operator's address) and one test mail; a first `python
|
||||
agent.py` to see the security image Continue click on the real page
|
||||
(its HTML is saved as `security_image_page` — tighten the selector from
|
||||
it) and a late-mail Resend pickup. Not built: the agent's status in the
|
||||
Portal (it runs on the bot PC; the Dokploy Portal sees only the
|
||||
database — a status / queue-size row would carry it), Queue / Pending
|
||||
tiles.
|
||||
- **29/10 live queue (690 claims).** 208 got a result in two runs (17:18
|
||||
126, 19:29 82); the rest were not reached: Ctrl-C would not stop a
|
||||
run blocked in a Playwright call (the tab was closed instead), a stuck
|
||||
Patient Information dialog cost 18 claims (now `recovery.py`), and three
|
||||
logins that night failed on 2FA mail 6 to 8.5 min late (now the Resend
|
||||
pickup). 482 claims of that day's queue were never checked.
|
||||
- **Tests:** `test_cdp_browser.py` 2 of 11 fail on this PC since
|
||||
2026-10-29 (the Chrome it opens has a command line PowerShell cannot
|
||||
read — the same `[BROWSER] Could not read the command line` line live
|
||||
runs print); environment, not code — look at it before trusting the
|
||||
proxy check. `test_msgbox.py` now pins `QUIET_BOXES` off (this PC's
|
||||
`.env` has it on).
|
||||
|
||||
- **Stability (review of 25 runs, 20–26/10, 2026-10-26).** After the eCW
|
||||
login the run is steady: the last five full runs read 50/50 with no
|
||||
bot error and the same results run to run. The weak part is getting
|
||||
|
||||
Reference in new issue
Block a user