feat(web): add Dream Output Viewer

Dreams are currently a black box — to benchmark Tier L models on dreamer
induction quality we need to see what each model produced. This adds a
workspace-scoped /dreams route that surfaces every dream run as a
group of conclusions split into explicit / deductive / inductive
columns, with click-to-expand premise trees.

What's here:

- `lib/dreams.ts`: pure helpers. `clusterConclusionsIntoDreams` groups a
  raw conclusions list into per-pair bursts using a configurable time
  window (default 60s). `expandPremiseTree` walks `reasoning_tree` first
  and falls back to a flat `premises` ID list, with cycle detection and
  a depth cap. Defines an `ExtendedConclusion` type that augments the
  generated schema with `conclusion_type`, `premises`, and
  `reasoning_tree` — Honcho's migration f1a2b3c4d5e6 added those
  columns but `schema.d.ts` doesn't expose them yet, so the UI degrades
  gracefully (unknown types fall into "explicit").

- `api/queries.ts`: new `useDreams` hook that paginates the conclusions
  list endpoint up to a configurable cap (default 400) and hands the
  raw list to the UI for clustering. New `dreams` query key.

- `components/dreams/`:
  - `DreamList.tsx` — route entry. Shows recent dreams as rows with
    timestamp, observer→observed pair, and per-type counts. Selecting
    a row expands an inline detail panel above the list.
  - `DreamDetail.tsx` — three-column view (explicit / deductive /
    inductive). Each inductive conclusion has a "Show premises" button
    that expands the reasoning chain.
  - `PremiseTree.tsx` — recursive premise renderer with type badges,
    cycle indicator, and graceful handling of premises that fall
    outside the loaded page.

- Routing: `routes/workspaces_.$workspaceId_.dreams.tsx` registers the
  page; routeTree.gen.ts regenerated.

- Sidebar: new "Dreams" entry between Conclusions and Webhooks
  (MoonStar icon to distinguish from the dark-mode Moon).

- Breadcrumb: "dreams" added to SECTION_LABELS so the trail resolves.

Tests (vitest, 14 new):
- clustering: empty input; same-pair burst within window; gap exceeds
  threshold → split; different pairs don't merge even with overlapping
  timestamps; custom gap window; newest-first ordering; counts default
  unknown types to explicit.
- premise tree: empty children for no premises; flat list → direct
  children; multi-level reasoning_tree recursion; missing premise
  flagged (not in loaded page); cycle detection halts recursion;
  maxDepth cap; reasoning_tree preferred over flat premises.

Verified manually in the preview: route mounts, sidebar/breadcrumb
resolve, error path renders cleanly, typecheck + lint + dream tests
all clean. The unrelated `app.test.tsx` failure is pre-existing on
main.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Agents
2026-05-24 18:29:26 +01:00
committed by Offending Commit
parent 6960bf4ffe
commit f318555c82
11 changed files with 1140 additions and 0 deletions

View File

@@ -32,5 +32,8 @@ export const QK = {
conclusionsQuery: (wsId: string, q: string, filters: Record<string, unknown>) =>
["conclusions-query", wsId, q, filters] as const,
dreams: (wsId: string, filters: Record<string, unknown>, limit: number) =>
["dreams", wsId, filters, limit] as const,
webhooks: (wsId: string) => ["webhooks", wsId] as const,
};