diff --git a/apps/web/src/components/hud/HUD.tsx b/apps/web/src/components/hud/HUD.tsx
index b9078ab..33a7428 100644
--- a/apps/web/src/components/hud/HUD.tsx
+++ b/apps/web/src/components/hud/HUD.tsx
@@ -73,7 +73,7 @@ export function HUD({ className = "" }: HUDProps): React.JSX.Element {
const handleAddWidget = (widgetType: WidgetRegistryKey): void => {
const widgetConfig = WIDGET_REGISTRY[widgetType];
- const widgetId = `${widgetType.toLowerCase()}-${String(Date.now())}`;
+ const widgetId = `${widgetConfig.name}-${String(Date.now())}`;
// Find the next available position
const maxY = currentLayout?.layout.reduce((max, w): number => Math.max(max, w.y + w.h), 0) ?? 0;
diff --git a/apps/web/src/components/hud/WidgetRenderer.test.tsx b/apps/web/src/components/hud/WidgetRenderer.test.tsx
new file mode 100644
index 0000000..00ef010
--- /dev/null
+++ b/apps/web/src/components/hud/WidgetRenderer.test.tsx
@@ -0,0 +1,37 @@
+import { render, screen } from "@testing-library/react";
+import { describe, it, expect, vi } from "vitest";
+import { WidgetRenderer } from "./WidgetRenderer";
+import type { WidgetPlacement } from "@mosaic/shared";
+
+vi.mock("@/components/widgets", () => ({
+ TasksWidget: ({ id }: { id: string }): React.JSX.Element =>
Tasks Widget {id}
,
+ CalendarWidget: ({ id }: { id: string }): React.JSX.Element => Calendar Widget {id}
,
+ QuickCaptureWidget: ({ id }: { id: string }): React.JSX.Element => (
+ Quick Capture Widget {id}
+ ),
+ AgentStatusWidget: ({ id }: { id: string }): React.JSX.Element => (
+ Agent Status Widget {id}
+ ),
+}));
+
+function createWidgetPlacement(id: string): WidgetPlacement {
+ return {
+ i: id,
+ x: 0,
+ y: 0,
+ w: 2,
+ h: 2,
+ };
+}
+
+describe("WidgetRenderer", () => {
+ it("renders hyphenated quick-capture widget IDs correctly", () => {
+ render();
+ expect(screen.getByText("Quick Capture Widget quick-capture-123")).toBeInTheDocument();
+ });
+
+ it("renders hyphenated agent-status widget IDs correctly", () => {
+ render();
+ expect(screen.getByText("Agent Status Widget agent-status-123")).toBeInTheDocument();
+ });
+});
diff --git a/apps/web/src/components/hud/WidgetRenderer.tsx b/apps/web/src/components/hud/WidgetRenderer.tsx
index 9555aed..83a11b0 100644
--- a/apps/web/src/components/hud/WidgetRenderer.tsx
+++ b/apps/web/src/components/hud/WidgetRenderer.tsx
@@ -50,8 +50,12 @@ export function WidgetRenderer({
isEditing = false,
onRemove,
}: WidgetRendererProps): React.JSX.Element {
- // Extract widget type from ID (e.g., "tasks-123" -> "tasks")
- const widgetType = widget.i.split("-")[0] as keyof typeof WIDGET_COMPONENTS;
+ // Extract widget type from ID by removing the trailing unique suffix
+ // (e.g., "agent-status-123" -> "agent-status").
+ const separatorIndex = widget.i.lastIndexOf("-");
+ const widgetType = (
+ separatorIndex > 0 ? widget.i.substring(0, separatorIndex) : widget.i
+ ) as keyof typeof WIDGET_COMPONENTS;
const WidgetComponent = WIDGET_COMPONENTS[widgetType];
const config = WIDGET_CONFIG[widgetType] || { displayName: "Widget", description: "" };
diff --git a/docs/tasks.md b/docs/tasks.md
index ff581b5..c6cae5f 100644
--- a/docs/tasks.md
+++ b/docs/tasks.md
@@ -381,3 +381,5 @@
| ORCH-OBS-002 | done | Add web proxy route for recent orchestrator events (`/api/orchestrator/events/recent`) | #411 | web | feature/mosaic-stack-finalization | ORCH-OBS-001 | | orch | 2026-02-17T16:28Z | 2026-02-17T16:31Z | 5K | 4K |
| ORCH-OBS-003 | done | Add repo-level monitor script (`scripts/agent/orchestrator-events.sh`) for recent/watch modes | #411 | tooling | feature/mosaic-stack-finalization | ORCH-OBS-001 | | orch | 2026-02-17T16:31Z | 2026-02-17T16:36Z | 8K | 5K |
| ORCH-OBS-004 | done | Add tests/docs updates for recent events and operator command usage | #411 | orchestrator,docs | feature/mosaic-stack-finalization | ORCH-OBS-001 | | orch | 2026-02-17T16:36Z | 2026-02-17T16:40Z | 8K | 6K |
+| ORCH-OBS-005 | done | Fix HUD widget ID generation/parsing for hyphenated widget types (`quick-capture`, `agent-status`) | #411 | web | feature/mosaic-stack-finalization | ORCH-OBS-004 | | orch | 2026-02-17T16:42Z | 2026-02-17T16:48Z | 8K | 6K |
+| ORCH-OBS-006 | done | Add `WidgetRenderer` regression tests for hyphenated widget IDs | #411 | web | feature/mosaic-stack-finalization | ORCH-OBS-005 | | orch | 2026-02-17T16:48Z | 2026-02-17T16:50Z | 5K | 3K |