Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,14 @@ Configure a broker in TopicGate Desktop for read-only use, or use the authorized

TopicGate snapshots return the latest value it observed and retained, not authoritative broker history.

For individual receipts, enable **Stored observations → History settings → Record new
events for this broker**. Recording is off by default for every broker. The separate
**Event history** page and read-only `get_topic_history` tool provide cursor-paginated
history with recording and retention limitations. Adjust history age/count/size limits
independently from latest state; large limits may slow startup and queries.
See [observation history and retention](docs/OBSERVATION_HISTORY.md).
For individual receipts, open **History** in the workspace and use **Record messages**
for the displayed broker. Recording status appears before Search; enabling or disabling
recording leaves retention limits and saved receipts unchanged. Recording is off by
default for every broker. **History** and the read-only `get_topic_history` tool provide
cursor-paginated receipts with recording and retention limitations. Adjust limits under
**Stored observations → History settings** independently from latest values; large
limits may slow startup and queries.
See [observation history and retention](docs/OBSERVATION_HISTORY.md).

- **Live** values arrived in the current observation session.
- **Cached** or **stored** values came from local persistence.
Expand All @@ -84,6 +86,12 @@ See [observation history and retention](docs/OBSERVATION_HISTORY.md).

Only the active broker is continuously connected. Check freshness, provenance, truncation, dropped-message count, and completeness when interpreting a snapshot.

Desktop starts with a simplified workspace. **View → Advanced mode** restores
snapshot diagnostics, storage administration, diagnostic profiles and specialist
fields. History and recording remain available in both modes. This saved GUI
preference does not change broker operations or MCP authorization; see the
[desktop mode matrix](docs/DESKTOP_UX.md#simplified-and-advanced-mode).

## Health expectations

Define what healthy means for your broker and topics: an established connection, an expected status payload, a temperature range, or a maximum observation age. Desktop brings broker checks, topic checks, evidence, and failure history into one health view.
Expand All @@ -92,7 +100,7 @@ Define what healthy means for your broker and topics: an established connection,

*Sample health overview. A connected broker can still have failed or unknown checks; the connection badge alone does not establish health.*

Use the broker's **Health → Expectations** tab for connection checks, or a topic's **Settings → Expectations** tab for topic conditions. Configure expectations after adding a subscription that covers the topic.
Use **Health → Expectations** to browse all rules for the selected broker, with **All / Broker / Topic** scopes. Open a rule to edit it with its target selected, or use **Topic expectations** beside the selected topic. Configure expectations after adding a subscription that covers the topic. See the [desktop workspace guide and UX screenshots](docs/DESKTOP_UX.md).

<details>
<summary>See the broker expectation editor</summary>
Expand Down
283 changes: 283 additions & 0 deletions docs/DESKTOP_UX.md

Large diffs are not rendered by default.

29 changes: 23 additions & 6 deletions docs/OBSERVATION_HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,24 @@ before broker deletion; a drain timeout aborts deletion.

## Opt-in and independent retention

Open **Stored observations → History settings**, select a broker, check
**Record new events for this broker (opt-in)** and apply. The shared history
Open **History**, select a broker, and choose
**Record messages**. Its status is shown before Search. This action
enables or disables recording for future receipts without changing retention limits.
To adjust limits, enable **View → Advanced mode**, then open
**Stored observations → History settings**, select the broker,
edit the controls, and choose **Apply history settings**. The shared history
limits start at seven days, 100,000 events per broker, no per-topic cap, and
256 MiB of stored payloads globally. Age and per-topic caps can be left blank.
256 MiB of stored payloads globally. Use **Unlimited** for age or per-topic caps.
Age and payload limits have unit selectors; batch size and the idle interval appear
directly with the other settings. There is no local Advanced toggle. Saved changes show confirmation on the page.
Large history retention limits may slow startup and history queries.

**Search** starts a fresh query including newly saved events.
**Next page** continues the current query's fixed boundary. Event history is oldest
first; latest stored state has independent sorting and result limits. These views
do not replace **Health → Failure history**. See the [desktop guide](DESKTOP_UX.md)
for screenshots.

The size budget counts stored payload bytes, not database file bytes, indexes,
or filesystem allocation. Zero-byte events still count toward event limits.
Policy changes validate before persistence. Pruning applies age, per-topic count,
Expand Down Expand Up @@ -74,12 +86,17 @@ coverage. Settings summaries and eviction generations apply globally where label

## Desktop pages

**Latest stored state** shows one persisted value per topic. **Event history**
shows individual receipts using the same bounded query as MCP. Search or
Refresh snapshot starts over; Next page continues the committed snapshot.
**Stored observations → Latest stored values** (Advanced mode) shows one persisted
value per topic. The main History destination and recording controls are available
in both presentation modes.
The workspace **History** tab shows individual receipts using the same bounded query
as MCP. **Record messages** enables or disables recording for its displayed broker
without changing retention. Search starts over; Next page continues the committed snapshot.
Changing brokers or filters resets the cursor. Payloads are displayed as plain
text or base64, with provenance and truncation details on selection.

These screenshots show the earlier dialog layout; message history now lives in the workspace.

![Latest stored state and separate event history with recording limitations.](images/observation-history-after.png)

![Per-broker recording opt-in and independent history limits.](images/observation-history-settings.png)
Binary file removed docs/images/desktop-app.png
Binary file not shown.
Binary file removed docs/images/desktop-first-run-checklist.png
Binary file not shown.
Binary file removed docs/images/observation-history-after.png
Binary file not shown.
Binary file removed docs/images/observation-history-before.png
Binary file not shown.
Binary file removed docs/images/observation-history-settings.png
Binary file not shown.
Binary file removed docs/images/plugin_in_codex.png
Binary file not shown.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ where = ["src"]
topicgate = [
"assets/*.png",
"assets/*.svg",
"assets/icons/*.svg",
"infrastructure/database/alembic.ini",
"infrastructure/database/alembic/*.py",
"infrastructure/database/alembic/*.mako",
Expand Down
7 changes: 0 additions & 7 deletions src/topicgate/assets/delete.svg

This file was deleted.

4 changes: 0 additions & 4 deletions src/topicgate/assets/edit.svg

This file was deleted.

19 changes: 19 additions & 0 deletions src/topicgate/assets/icons/broker.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions src/topicgate/assets/icons/close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions src/topicgate/assets/icons/create.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions src/topicgate/assets/icons/delete.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions src/topicgate/assets/icons/edit.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/topicgate/assets/icons/help.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions src/topicgate/assets/icons/observer-tree.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions src/topicgate/assets/icons/settings.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/topicgate/gui/components/about_dialog.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from importlib.metadata import PackageNotFoundError, version

from topicgate.gui.icons import IconName, icon

from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
QDialog,
Expand Down Expand Up @@ -89,6 +91,7 @@ def __init__(self, parent: QWidget | None = None) -> None:
layout.addWidget(license_label)

buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
buttons.button(QDialogButtonBox.StandardButton.Close).setIcon(icon(IconName.CLOSE))
buttons.rejected.connect(self.reject)
layout.addWidget(buttons)

Expand Down
Loading