From 7f2ddecffbb29a0345d7a4f00d5755b19cffa58f Mon Sep 17 00:00:00 2001 From: Vasanth Date: Fri, 16 Oct 2026 13:59:26 +0530 Subject: [PATCH] No-AI skill tracer: SKILL.md, theme presets, sample data, Seam 1 page check - rpa-dashboard-no-ai/SKILL.md: trigger description and the workflow in spec order (scan, report/keep-or-restyle, colours, stack, sections, build, wire, verify). - templates/themes.md: Tebra Sky and Superbill Ember, light and dark blocks. - templates/palette.py: derives a custom palette from one brand hex and checks text contrast in light and dark. - dashboard.html: built-in sample data so a page with no bot works on first open; cleared batches in the donut; component tokens so Ember is a token-only swap; accessible names for KPI cards, nav, steps, log, search and the dark toggle. - bridge.py: placeholders inside string literals, so it passes the lint hook unfilled. - tests/page_check: Seam 1 harness (fake Qt bridge, light/dark/narrow). - tests/evals: Seam 2 runner and fixture a-empty. Co-Authored-By: Claude Opus 5.5 --- rpa-dashboard-no-ai/SKILL.md | 121 +++++++++++++ rpa-dashboard-no-ai/templates/bridge.py | 2 +- rpa-dashboard-no-ai/templates/contract.md | 1 + rpa-dashboard-no-ai/templates/dashboard.html | 149 ++++++++++------ rpa-dashboard-no-ai/templates/palette.py | 100 +++++++++++ rpa-dashboard-no-ai/templates/themes.md | 99 +++++++++++ tests/README.md | 29 ++++ tests/evals/run_eval.py | 100 +++++++++++ tests/fixtures/a-empty/README.md | 4 + tests/page_check/conftest.py | 79 +++++++++ tests/page_check/test_contract.py | 169 +++++++++++++++++++ tests/test_palette.py | 45 +++++ tests/test_templates.py | 24 +++ 13 files changed, 865 insertions(+), 57 deletions(-) create mode 100644 rpa-dashboard-no-ai/SKILL.md create mode 100644 rpa-dashboard-no-ai/templates/palette.py create mode 100644 rpa-dashboard-no-ai/templates/themes.md create mode 100644 tests/README.md create mode 100644 tests/evals/run_eval.py create mode 100644 tests/fixtures/a-empty/README.md create mode 100644 tests/page_check/conftest.py create mode 100644 tests/page_check/test_contract.py create mode 100644 tests/test_palette.py create mode 100644 tests/test_templates.py diff --git a/rpa-dashboard-no-ai/SKILL.md b/rpa-dashboard-no-ai/SKILL.md new file mode 100644 index 0000000..dcfdcd6 --- /dev/null +++ b/rpa-dashboard-no-ai/SKILL.md @@ -0,0 +1,121 @@ +--- +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. It runs the bot as a child process and tails its output. | +| `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 ``, stack ``, colours + `
`." 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. +- **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 +`` 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 ""`, paste the + tokens it prints, and show the user its contrast table. +4. Desktop: also copy `templates/bridge.py` next to the page, and fill + `{{BOT_MODULE}}`, the `STEPS` list (the same steps as the page), `{{ORG}}` and + `{{APP_NAME}}`. +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: in `bridge.py`, set `BOT_CMD` to start the bot as a child process. + Fill `STEP_MARKERS` and `FRIENDLY_RULES` from lines the bot really prints. Use + specific substrings (for example `[step 3]`, not a bare word); the first match + wins. Unmatched error lines must always reach the log. + - Web: the backend serves `GET {API_BASE}/dashboard`, `GET {API_BASE}/run/status` + (returning `{running, events[]}`) and `POST {API_BASE}/`. + - 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; 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. diff --git a/rpa-dashboard-no-ai/templates/bridge.py b/rpa-dashboard-no-ai/templates/bridge.py index 58767fe..179501a 100644 --- a/rpa-dashboard-no-ai/templates/bridge.py +++ b/rpa-dashboard-no-ai/templates/bridge.py @@ -12,7 +12,7 @@ from PyQt6.QtWebChannel import QWebChannel HTML_PATH = Path(__file__).with_name("dashboard.html") BOT_CMD = [sys.executable, "-m", "{{BOT_MODULE}}"] # child process -STEPS = {{STEPS_PY}} # same list as STEPS in dashboard.html +STEPS = ["{{STEP_1}}", "{{STEP_2}}"] # same list as STEPS in dashboard.html STEP_MARKERS = [("[step 1]", 0, 10), ("[all done]", len(STEPS) - 1, 100)] # (substring, step idx, pct) FRIENDLY_RULES = [("[login] done", "Logged in.", "success")] # (substring, friendly msg | None, type) diff --git a/rpa-dashboard-no-ai/templates/contract.md b/rpa-dashboard-no-ai/templates/contract.md index e6a648b..9e33309 100644 --- a/rpa-dashboard-no-ai/templates/contract.md +++ b/rpa-dashboard-no-ai/templates/contract.md @@ -4,6 +4,7 @@ All updates use one envelope: `{"event": "", "data": {...}}`. - **Desktop (PyQt):** Python calls `window.__pyMsg(json)` via `runJavaScript` (see `bridge.py`). - **Web:** the page polls `GET {API_BASE}/dashboard` (returns `dashboard_data`) and `GET {API_BASE}/run/status` → `{"running": bool, "events": [envelope, ...]}`. Poll fast (2s) only while running. +- **No bot yet:** with `SAMPLE_DATA = true`, the page answers its own data actions with sample envelopes. ## Bot/backend → page diff --git a/rpa-dashboard-no-ai/templates/dashboard.html b/rpa-dashboard-no-ai/templates/dashboard.html index 3224758..a40fcae 100644 --- a/rpa-dashboard-no-ai/templates/dashboard.html +++ b/rpa-dashboard-no-ai/templates/dashboard.html @@ -3,7 +3,7 @@ Generic RPA dashboard (no AI). Derived from Tebra ERA (reference/tebra_dashboard.html). One file: works inside PyQt6 QWebEngineView (QWebChannel bridge) OR served by any web backend (falls back to polling GET {{API_BASE}}/dashboard and /run/status). - Replace every {{PLACEHOLDER}}. Theme = the :root / body.dark token blocks only. + Replace every {{...}} placeholder. Theme = the body / body.dark token blocks only (see themes.md). --> @@ -12,14 +12,18 @@ {{APP_NAME}}