No-AI desktop path: PyQt bot wired to the page
- 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>
This commit is contained in:
1 parent
3eb3fdf00e
commit
162edd41df
17 files changed
+753
-47
No files matched your search
@@ -11,7 +11,8 @@ 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/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. |
|
||||
@@ -50,6 +51,8 @@ Skip this if the user chose to keep the existing look. Offer:
|
||||
## 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.
|
||||
@@ -84,9 +87,9 @@ sections must leave no markup, script or style behind, so delete their
|
||||
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` next to the page, and fill
|
||||
`{{BOT_MODULE}}`, the `STEPS` list (the same steps as the page), `{{ORG}}` and
|
||||
`{{APP_NAME}}`.
|
||||
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
|
||||
@@ -97,10 +100,22 @@ both directions.
|
||||
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.
|
||||
- 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
|
||||
@@ -108,7 +123,10 @@ both directions.
|
||||
|
||||
## 8. Verify
|
||||
|
||||
Open the page. On desktop run the host; otherwise open the file or the served URL.
|
||||
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
|
||||
|
||||
Reference in new issue
Block a user