Architecture¶
Three kinds of process. The window draws and never waits. A supervisor owns everything slow. Plugins and services run in supervised worker processes and reach the outside world only through calls the supervisor is willing to answer.
┌──────────────────────────────────────────────────────────────┐
│ UI process — Qt. Draws. Never blocks. │
│ shell · workflow view · episode editor · command palette │
└───────────────┬──────────────────────────────▲───────────────┘
│ asks │ progress, results
┌───────────────▼──────────────────────────────┴───────────────┐
│ Supervisor — owns every long-running thing │
│ task registry · capability gate · show store (one writer) │
└───────────────────────────┬──────────────────────────────────┘
│ every call a plugin makes
┌───────────────────────────▼──────────────────────────────────┐
│ Workers — one per plugin, one per job. Killable. │
│ RSS import · transcription · audio & mixdown · model calls │
└──────────────────────────────────────────────────────────────┘
Components¶
| Component | Lives in | Responsibility |
|---|---|---|
| Shell | UI | Window, sidebar, header bar, navigation |
| Workflow view | UI | Draws activities and their states; opens steps |
| Episode editor | UI | Tracks, chapters, transcript; one widget tree, keyboard-first |
| Command registry | UI | Every action by id; the palette and menus are views of it |
| Task registry | Supervisor | Starts, reports, cancels; the Tasks screen is its mirror |
| Capability gate | Supervisor | Answers a plugin's calls only where manifest and user agree |
| Show store | Supervisor | The only writer to the show file |
| Workflow engine | Supervisor | Activities, workflows, completion; pure logic, no Qt |
| Plugin host | Worker | One process per active plugin; dies alone |
| Services | Worker | Transcription, audio, model calls — reached like any capability |
Why it cannot hang¶
Four rules, enforced by the structure rather than by everyone's discipline:
- The UI process contains no plugin code and makes no network call.
- Anything that might take longer than a frame is a task: it has an id, reports progress and can be cancelled. The Tasks screen is the task registry drawn.
- The show file has exactly one writer, so the window never waits on a lock.
- A worker that stops answering is killed and reported. Its plugin is marked unhealthy; the window does not notice.
The one exception, named. The editor's waveform drawing and the player's audio callback run in the UI process because they must. They touch no file and no network — they read decoded samples a worker prepared. Everything else slow is outside.
The boundary is a protocol¶
Workers speak to the supervisor over a line-delimited message protocol on a pipe, not by sharing Python objects. That costs a serialisation step and buys three things: a plugin crash cannot corrupt the application's memory, a plugin can be killed at any instant, and a plugin need not be written in Python.
Related¶
- The show file — the data model
- The workflow engine — activities, workflows, commands
- Language models · Transcription
- Permissions — what the capability gate enforces