feat(gui): Tier stream panels as separate dockable windows (Tier 1-4)

This commit is contained in:
2026-03-01 15:57:46 -05:00
parent a7903d3a4b
commit 2ce7a87069
3 changed files with 132 additions and 85 deletions

108
gui_2.py
View File

@@ -208,6 +208,10 @@ class App:
"Files & Media": True,
"AI Settings": True,
"MMA Dashboard": True,
"Tier 1: Strategy": True,
"Tier 2: Tech Lead": True,
"Tier 3: Workers": True,
"Tier 4: QA": True,
"Discussion Hub": True,
"Operations Hub": True,
"Theme": True,
@@ -1592,6 +1596,26 @@ class App:
if exp:
self._render_mma_dashboard()
imgui.end()
if self.show_windows.get("Tier 1: Strategy", False):
exp, self.show_windows["Tier 1: Strategy"] = imgui.begin("Tier 1: Strategy", self.show_windows["Tier 1: Strategy"])
if exp:
self._render_tier_stream_panel("Tier 1", "Tier 1")
imgui.end()
if self.show_windows.get("Tier 2: Tech Lead", False):
exp, self.show_windows["Tier 2: Tech Lead"] = imgui.begin("Tier 2: Tech Lead", self.show_windows["Tier 2: Tech Lead"])
if exp:
self._render_tier_stream_panel("Tier 2", "Tier 2 (Tech Lead)")
imgui.end()
if self.show_windows.get("Tier 3: Workers", False):
exp, self.show_windows["Tier 3: Workers"] = imgui.begin("Tier 3: Workers", self.show_windows["Tier 3: Workers"])
if exp:
self._render_tier_stream_panel("Tier 3", None)
imgui.end()
if self.show_windows.get("Tier 4: QA", False):
exp, self.show_windows["Tier 4: QA"] = imgui.begin("Tier 4: QA", self.show_windows["Tier 4: QA"])
if exp:
self._render_tier_stream_panel("Tier 4", "Tier 4 (QA)")
imgui.end()
if self.show_windows.get("Theme", False):
self._render_theme_panel()
if self.show_windows.get("Discussion Hub", False):
@@ -2730,60 +2754,6 @@ class App:
imgui.text(f"{stats.get('output', 0):,}")
imgui.end_table()
imgui.separator()
if imgui.collapsing_header("Tier 1: Strategy"):
content = self.mma_streams.get("Tier 1", "")
if imgui.begin_child("##tier1_scroll", imgui.ImVec2(-1, 200), True):
imgui.text_wrapped(content)
try:
at_bottom = imgui.get_scroll_y() >= imgui.get_scroll_max_y() - 10
if at_bottom and len(content) != self._tier_stream_last_len.get("Tier 1", -1):
imgui.set_scroll_here_y(1.0)
self._tier_stream_last_len["Tier 1"] = len(content)
except (TypeError, AttributeError):
pass
imgui.end_child()
if imgui.collapsing_header("Tier 2: Tech Lead"):
content = self.mma_streams.get("Tier 2 (Tech Lead)", "")
if imgui.begin_child("##tier2_scroll", imgui.ImVec2(-1, 200), True):
imgui.text_wrapped(content)
try:
at_bottom = imgui.get_scroll_y() >= imgui.get_scroll_max_y() - 10
if at_bottom and len(content) != self._tier_stream_last_len.get("Tier 2 (Tech Lead)", -1):
imgui.set_scroll_here_y(1.0)
self._tier_stream_last_len["Tier 2 (Tech Lead)"] = len(content)
except (TypeError, AttributeError):
pass
imgui.end_child()
if imgui.collapsing_header("Tier 3: Workers"):
tier3_keys = [k for k in self.mma_streams if "Tier 3" in k]
if not tier3_keys:
imgui.text_disabled("No worker output yet.")
else:
for key in tier3_keys:
ticket_id = key.split(": ", 1)[-1] if ": " in key else key
imgui.text(ticket_id)
if imgui.begin_child(f"##tier3_{ticket_id}_scroll", imgui.ImVec2(-1, 150), True):
imgui.text_wrapped(self.mma_streams[key])
try:
at_bottom = imgui.get_scroll_y() >= imgui.get_scroll_max_y() - 10
if at_bottom and len(self.mma_streams[key]) != self._tier_stream_last_len.get(key, -1):
imgui.set_scroll_here_y(1.0)
self._tier_stream_last_len[key] = len(self.mma_streams[key])
except (TypeError, AttributeError):
pass
imgui.end_child()
if imgui.collapsing_header("Tier 4: QA"):
content = self.mma_streams.get("Tier 4 (QA)", "")
if imgui.begin_child("##tier4_scroll", imgui.ImVec2(-1, 200), True):
imgui.text_wrapped(content)
try:
at_bottom = imgui.get_scroll_y() >= imgui.get_scroll_max_y() - 10
if at_bottom and len(content) != self._tier_stream_last_len.get("Tier 4 (QA)", -1):
imgui.set_scroll_here_y(1.0)
self._tier_stream_last_len["Tier 4 (QA)"] = len(content)
except (TypeError, AttributeError):
pass
imgui.end_child()
# 4. Task DAG Visualizer
imgui.text("Task DAG")
if self.active_track:
@@ -2808,6 +2778,36 @@ class App:
else:
imgui.text_disabled("No active MMA track.")
def _render_tier_stream_panel(self, tier_key: str, stream_key: str | None) -> None:
if stream_key is not None:
content = self.mma_streams.get(stream_key, "")
if imgui.begin_child("##stream_content", imgui.ImVec2(-1, -1)):
imgui.text_wrapped(content)
try:
if len(content) != self._tier_stream_last_len.get(stream_key, -1):
imgui.set_scroll_here_y(1.0)
self._tier_stream_last_len[stream_key] = len(content)
except (TypeError, AttributeError):
pass
imgui.end_child()
else:
tier3_keys = [k for k in self.mma_streams if "Tier 3" in k]
if not tier3_keys:
imgui.text_disabled("No worker output yet.")
else:
for key in tier3_keys:
ticket_id = key.split(": ", 1)[-1] if ": " in key else key
imgui.text(ticket_id)
if imgui.begin_child(f"##tier3_{ticket_id}_scroll", imgui.ImVec2(-1, 150), True):
imgui.text_wrapped(self.mma_streams[key])
try:
if len(self.mma_streams[key]) != self._tier_stream_last_len.get(key, -1):
imgui.set_scroll_here_y(1.0)
self._tier_stream_last_len[key] = len(self.mma_streams[key])
except (TypeError, AttributeError):
pass
imgui.end_child()
def _render_ticket_dag_node(self, ticket: Ticket, tickets_by_id: dict[str, Ticket], children_map: dict[str, list[str]], rendered: set[str]) -> None:
tid = ticket.get('id', '??')
target = ticket.get('target_file', 'general')