- templates/bot_runner.py (new, no Qt): runs the bot as a child process (unbuffered, UTF-8), tails its output, keeps raw lines in bot_raw.log, and turns lines into step/log/status events. Step markers and friendly rules use specific substrings, first match wins; unmatched error lines are always shown, other unmatched lines hidden. Dry run: python dashboard/bot_runner.py prints the events the page would get. - bridge.py: delegates to bot_runner, one run at a time, restores the saved dark mode on every page load (fixes sample-data mode in PyQt), adds load_latest_report / download_report slots the page calls. - SKILL.md: skip the stack question for a PyQt project; desktop wiring steps from the bot's real output; verify steps for the host. - tests: assert-based self-check for the line logic and run loop; Seam 1 run replay (status dot, Run button, steps, log) and wired-page mode; fixture b-pyqt-bot and its Seam 2 eval (all 14 checks pass). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
140 lines
8.2 KiB
Markdown
140 lines
8.2 KiB
Markdown
---
|
|
name: rpa-dashboard-no-ai
|
|
description: Builds a working dashboard page for an RPA bot that does not use AI. It always includes a sidebar and top bar with a dark toggle and status dot, KPI cards, a batch status donut, a run panel with steps and a live log, and a report table with search and Excel export. The page is wired to the bot through one data contract, or runs on sample data when there is no bot yet. Supports a desktop path (PyQt6 with an embedded page) and a web path. Use when the user asks for an "RPA dashboard", "automation dashboard", "bot dashboard", a dashboard "without AI", or a status/run/report page for a bot. For bots that use an LLM or OCR extraction, use rpa-dashboard-ai instead.
|
|
---
|
|
|
|
# RPA dashboard (no AI)
|
|
|
|
Everything this skill needs is bundled in `templates/`. Never read the original
|
|
source projects.
|
|
|
|
| File | What it is |
|
|
|---|---|
|
|
| `templates/dashboard.html` | The single-file page: theme tokens, shell, KPI, donut, run panel, report, sample data. Works in PyQt (QWebChannel) or on the web (polling). |
|
|
| `templates/bridge.py` | Minimal PyQt6 host: the window, the bridge slots, and the saved dark-mode choice. |
|
|
| `templates/bot_runner.py` | The bot wiring, without Qt. It runs the bot as a child process, tails its output, and turns lines into step and log events. |
|
|
| `templates/contract.md` | The data contract: events the bot sends, actions the page sends. |
|
|
| `templates/themes.md` | Theme presets (Tebra Sky, Superbill Ember) and the custom-colour steps. |
|
|
| `templates/palette.py` | Derives a custom palette from one brand hex and checks contrast. |
|
|
| `templates/reference/` | Raw Tebra extracts. Use them only to port optional sections. |
|
|
|
|
Follow the steps in order. Ask one question at a time, and wait for the answer.
|
|
If the user's request already answers a question, don't ask it again.
|
|
|
|
## 1. Scan the project
|
|
|
|
Before asking anything, look at the project:
|
|
- **Frontend:** `*.html` files outside `node_modules`, `.venv` and build output; a
|
|
`web/`, `frontend/` or `static/` folder; `package.json` with react, vue, angular or
|
|
svelte; a PyQt `QWebEngineView`. For any you find, note the location, the stack and
|
|
the main colour tokens (CSS custom properties or the Tailwind theme).
|
|
- **Bot:** the entry point (for example `main.py`, a `__main__` module or a run
|
|
script), what it prints (step markers, status and error lines), and how it starts.
|
|
|
|
## 2. Report the frontend, then ask keep or restyle
|
|
|
|
- **No frontend:** say "No existing frontend found." and go to step 3. Don't
|
|
describe a frontend that isn't there.
|
|
- **Frontend found:** say "Frontend found at `<path>`, stack `<stack>`, colours
|
|
`<main tokens>`." Then ask: **keep its look**, or **restyle** it?
|
|
- Keep: skip step 3. Build the page with the project's own tokens and fonts, and
|
|
change none of its existing styles.
|
|
- Restyle: go to step 3. Change only the theme tokens, never layout or logic.
|
|
|
|
## 3. Ask for colours
|
|
|
|
Skip this if the user chose to keep the existing look. Offer:
|
|
1. **Tebra Sky**: blue glass cards on a sky gradient.
|
|
2. **Superbill Ember**: flat surfaces with a red-orange brand gradient.
|
|
3. **Custom**: the user gives one brand hex colour.
|
|
|
|
## 4. Ask desktop or web
|
|
|
|
Ask only if there is no frontend. If there is one, use its stack.
|
|
Don't ask if the project already uses PyQt (`PyQt6` or `PyQt5` in its requirements,
|
|
`pyproject.toml` or imports): choose desktop and say so.
|
|
- **Desktop:** a PyQt6 window with the page embedded. The page talks to Python
|
|
through a bridge, so no web server is needed.
|
|
- **Web:** the same page, served by a backend that it polls.
|
|
|
|
## 5. Ask which optional sections to build
|
|
|
|
Always built: the shell (sidebar, top bar, dark toggle, status dot), KPI cards,
|
|
the status donut, the run panel and the report table.
|
|
|
|
Ask which extras to add (choose any, or none): **checkpoint tracker**,
|
|
**admin/roles screen**, **login page**. Build only the ones chosen. Unchosen
|
|
sections must leave no markup, script or style behind, so delete their
|
|
`<!-- OPTIONAL: ... -->` markers.
|
|
|
|
## 6. Build
|
|
|
|
1. Copy `templates/dashboard.html` into the project:
|
|
- Desktop: put it next to the host, for example `dashboard/dashboard.html`.
|
|
- Web: put it in the backend's static folder. With no backend yet, use
|
|
`dashboard/dashboard.html`.
|
|
2. Fill every `{{...}}` placeholder:
|
|
|
|
| Placeholder | Value |
|
|
|---|---|
|
|
| `APP_NAME`, `APP_SUBTITLE` | The project's name and a short tagline. |
|
|
| `LOGO_SRC` | The logo's path, or empty if there is none. |
|
|
| `STEPS_JSON` | The run steps as a JSON list, from the bot's real stages, for example `["Initializing","Login","Process items","Completed"]`. |
|
|
| `REPORT_COLUMNS_JSON` | `[{"key":..., "label":...}]`. It must include a column with key `status`, which shows the bucket pill. |
|
|
| `API_BASE` | Web only, for example `/api`. Leave it empty for desktop. |
|
|
|
|
3. Apply the theme by replacing the `body{...}` and `body.dark{...}` token blocks
|
|
with the preset from `templates/themes.md`. For Ember, also add its font link.
|
|
For a custom colour, run `python templates/palette.py "<hex>"`, paste the
|
|
tokens it prints, and show the user its contrast table.
|
|
4. Desktop: also copy `templates/bridge.py` and `templates/bot_runner.py` next to
|
|
the page. Fill `{{ORG}}` and `{{APP_NAME}}` in `bridge.py`, and `{{BOT_MODULE}}` in
|
|
`bot_runner.py` (with no bot yet, use the module the bot will have, for example `bot`).
|
|
5. Search the output for `{{`. None may be left.
|
|
|
|
## 7. Wire the data
|
|
|
|
The contract is in `templates/contract.md`: one envelope, `{event, data}`, in
|
|
both directions.
|
|
- **No bot yet:** keep `SAMPLE_DATA = true` and the `SAMPLE DATA` block. The page
|
|
answers its own data actions, so it opens with sample batches and report rows,
|
|
and Run plays a demo run. Tell the user which events their bot must send later.
|
|
- **Bot exists:** set `SAMPLE_DATA = false` and delete the `SAMPLE DATA` block. Then:
|
|
- Desktop: all the wiring is in `bot_runner.py`.
|
|
1. Get the bot's real output: run it once (for example `python -m bot`), or read
|
|
its `print` and logging calls. Never invent lines it doesn't print.
|
|
2. Set `BOT_CMD` to start the bot as a child process, and `BOT_CWD` to the folder
|
|
it runs from.
|
|
3. Set `STEPS_JSON` in the page to the bot's real stages. Fill `STEP_MARKERS` with
|
|
`(substring, step label, pct)`: one specific substring per stage (for example
|
|
`[step 3]`, never a bare word like `login`), each label exactly one of the
|
|
page's STEPS, and pct rising to 100 on the bot's last line. The first match wins.
|
|
4. Fill `FRIENDLY_RULES` with `(substring, plain-English message, type)` for the
|
|
lines an operator should see. Unmatched lines are hidden, except error lines
|
|
(any line with a word from `ERROR_WORDS`), which are always shown as they are.
|
|
Add the bot's own failure words to `ERROR_WORDS` if it uses others.
|
|
5. Dry run without the window: `python dashboard/bot_runner.py`. It prints each
|
|
event the page would get. Check that the steps arrive in order and end at
|
|
100, and that the bot's error lines appear as `error` log events.
|
|
- Web: the backend serves `GET {API_BASE}/dashboard`, `GET {API_BASE}/run/status`
|
|
(returning `{running, events[]}`) and `POST {API_BASE}/<action-with-dashes>`.
|
|
- Apply the contract's derived rules: batch state from Pending plus date, and
|
|
report buckets from status.
|
|
|
|
## 8. Verify
|
|
|
|
Open the page. On desktop run the host (`python dashboard/bridge.py`), click Run,
|
|
and check that the Run button stays disabled until the bot finishes, and that the
|
|
dark-mode choice is still set after you close and reopen the window. Otherwise
|
|
open the file or the served URL.
|
|
With sample data, opening the file in a browser is enough. Check:
|
|
- the light theme, the dark theme (use the toggle), and a window 820px wide or less;
|
|
- KPI cards, donut and legend, the Run tab's steps and log, and the Report tab's
|
|
rows and pills all show data;
|
|
- no `{{` placeholders are left and the console shows no script errors.
|
|
|
|
If Python Playwright is installed, take headless screenshots of each check and
|
|
look at them. Otherwise, ask the user to open the page. Finish by telling the user
|
|
where the files are, which theme and sections were built, and whether the page is
|
|
on sample data or wired to the bot.
|