Skip to content

feat(home): new home layout with SVG assets, tile board, and per-route panel state#3368

Open
rafavalls wants to merge 49 commits into
mainfrom
rafavalls/new-home
Open

feat(home): new home layout with SVG assets, tile board, and per-route panel state#3368
rafavalls wants to merge 49 commits into
mainfrom
rafavalls/new-home

Conversation

@rafavalls
Copy link
Copy Markdown
Collaborator

@rafavalls rafavalls commented May 14, 2026

What is this contribution about?

Redesigns the home page with a new tile board system, SVG decorative assets (replacing PNGs, with light/dark variants), and a per-route tasks panel state. The tasks panel now defaults open on home (wide 560 px) and independently tracks open/close state from the chat routes. Preset cards in the tasks panel get a bordered style with numbered step badges to guide users through the brand → landing → monitoring flow. Tile icons are replaced by IntegrationIcon sourced from WELL_KNOWN_AGENT_TEMPLATES, and three new templates (brand-context, landing-page, system-health) are registered there.

Screenshots/Demonstration

UI changes affect the home page layout, sidebar width, preset card thumbnails, tile icons, and background decorations. Screenshots should show light + dark mode.

How to Test

  1. Run bun run dev and navigate to the home route.
  2. Verify the background corner SVGs render in light and dark mode.
  3. Open the tasks panel — it should be wide (560 px) and default to preset cards.
  4. Click "Extract brand context" — a tile should be pinned to the board and the chat should open.
  5. Navigate to a chat task route; the panel should switch to the task list at normal width (340 px).
  6. Toggle the panel closed on home, navigate to chat and back — the home panel should remember its closed state.

Migration Notes

No database migrations required. Old PNG assets under public/home/ are deleted; new SVGs replace them.

Review Checklist

  • PR title is clear and descriptive
  • Changes are tested and working
  • Documentation is updated (if needed)
  • No breaking changes

Summary by cubic

Redesigned the Home page with a server‑backed 3‑column tile board and a preset tasks system that auto‑pins tiles when started. Added onboarding agents and tools (brand context, system health, and web developer) with improved install flows and inline HTML previews.

  • New Features

    • Home tile board: drag/resize/remove; per‑user/per‑org state in KV via /api/:org/home-board; tiles auto‑pin on POST /preset-tasks/:id/start; icons use IntegrationIcon.
    • Preset tasks: backend registry at /preset-tasks lists five cards (New chat, Extract brand context, Create landing page, Set up error monitoring, Import Deco); /start seeds a thread and returns taskId; DBOS workflow tracks brand‑context completion; shared install dialogs and OAuth handshake for GitHub and System Health.
    • Agents:
      • brand-context: setup and confirm modes with built‑in tools (brand_context_setup, update_brand_context, reextract_brand_context, confirm_brand).
      • system-health: idempotent install; new automation tools to create health checks (schedule/subscribe) and manage triggers.
      • web-developer: built‑in tools (write_html_page, read_html_page, list_html_pages, delete_html_page); chat shows inline HTML previews.
    • Tasks panel: per‑route open/close; defaults open and 560 px wide on Home (340 px in chat).
    • Background/UI: SVG corner assets (light/dark), fixed while content scrolls; chat input dark‑mode background set to bg-card.
    • Visibility: lightweight probes for Deco sites and GitHub installation to gate card visibility without failing the page.
  • Bug Fixes

    • Brand‑context: sanitize long/dirty fields in prompts, clearer errors when extraction fails, and guards to ensure a brand exists before confirm mode.
  • Migration

    • Assets: PNGs under public/home/ replaced with SVGs.
    • Persistence: Home board now uses server‑side storage (KV). No action needed.

Written for commit b505e81. Summary will update on new commits.

@github-actions
Copy link
Copy Markdown
Contributor

🧪 Benchmark

Should we run the Virtual MCP strategy benchmark for this PR?

React with 👍 to run the benchmark.

Reaction Action
👍 Run quick benchmark (10 & 128 tools)

Benchmark will run on the next push after you react.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 2026

Release Options

Suggested: Minor (2.327.0) — based on feat: prefix

React with an emoji to override the release type:

Reaction Type Next Version
👍 Prerelease 2.326.4-alpha.1
🎉 Patch 2.326.4
❤️ Minor 2.327.0
🚀 Major 3.0.0

Current version: 2.326.3

Note: If multiple reactions exist, the smallest bump wins. If no reactions, the suggested bump is used (default: patch).

rafavalls and others added 28 commits May 15, 2026 02:52
Adds an opt-in tile-based home board alongside today's chat-centric
home. Users keep the existing simple home until they explicitly switch;
once switched, the home becomes a 12-column snap grid where tiles can
be added, dragged, resized to four presets (S/M/L/W), and removed.

The board is per-user-per-org via localStorage today; the
[board, setBoard] hook signature is intentionally sync-friendly so a
future server backing store is a swap-in.

Tile content is mocked end-to-end in this commit (12 tile types
across essentials/activity/stats/shortcuts/data/workflow). Real
plumbing for agent/MCP-contributed tiles will replace the static
catalog in a follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HomePage now reads the user's home board and renders either the
existing simple home or the new TileBoard. A "Customize" button is
portalled into Toolbar.Right; clicking it from simple mode opens an
intro dialog (Stay simple / Start blank / Try the tile board), and
from tiles mode toggles edit chrome (Add tile, Reset, Switch back to
simple, Done). Mobile collapses to a stacked read-only view.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Covers the cases most likely to break under user input: compaction
ordering, side-by-side packing, collision push-down, resize that
displaces neighbours, x-clamping, and free-slot search.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Visual review against the rendered starter board showed:
- Quick chat (L: 6×4) was too tall — textarea dominated empty space
- Shortcuts buttons used aspect-square + small icons, wasting room
- Workspace stats clustered at the top with empty space below
- Connections preview icons were undersized (size-7) for an M tile
- Welcome (W: 12×3) felt over-padded for a hero strip

Changes:
- Row height 96 → 80 px (tighter overall vertical rhythm)
- L preset 6×4 → 6×3; W preset 12×3 → 12×2 (less vertical bloat)
- Starter board snaps to 4/4/4 + 6/6 + 4/4/4 columns for clean alignment
- Welcome: horizontal layout (text left, actions right)
- Quick chat: tighter footer, send button h-7
- Shortcuts default size L (6×3), 2×2 grid that fills the tile
- Stats: 2×2 cards that fill the tile, bigger numbers (text-2xl)
- Connections preview icons size-7 → size-9
- Tile internal padding p-4 → p-3.5, gap-3 → gap-2.5
- Inter-tile gutter p-1.5 → p-1 for a tighter bento feel

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops the simple/tiles mode split. There is now one home: chat composer
and agents strip render on top exactly as they do today, and a
customisable tile board renders below that — but only when the user
has at least one tile pinned. New users see today's home unchanged;
power users get a dashboard that grows with them.

- Removes the intro dialog and the "switch to simple / tiles" actions.
- HomeBoard schema bumps to v2 and drops the `layout` field. v1 boards
  with empty tiles arrays migrate cleanly to empty v2 boards (which
  render identically to today's home).
- Starter board now focuses on dashboard tiles only — drops Welcome,
  Quick chat, and Recent agents (those duplicate the top region).
- Toolbar Customize button toggles edit mode for the tile area only;
  chat + agents are never edited.
- Empty-state hint sits below the agents row when there are no tiles
  and the user isn't on the deco-import path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Top padding 10 → 16, post-greeting margin 8 → 10, agents-row gap 8 → 10,
and 12 of margin / 10 of bottom padding around the tile board so it
doesn't crowd the agents row above. Mirrors the same on mobile.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Earlier "tighten bento" pass overshot — tiles felt cramped. Brings
back:
  - Row height 80 → 96 px
  - Inter-tile gutter p-1 → p-1.5
  - Tile internal padding p-3.5 → p-4 (gap-2.5 → gap-3)
  - Tile header icon size-5 plain → size-6 with bg-muted
  - Card border tone border/80 → border (back to full opacity)

Keeps the structural improvements that helped (Welcome horizontal
hero, Stats 2×2 chips, Shortcuts default L, Connections size-9
preview icons) — those weren't the problem.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Desktop pt-16 → pt-24 (96px), mobile pt-16 → pt-20.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop the "Mock" badge and the unused Badge import — tiles speak for
  themselves; mocked sources are still labelled in the catalog
- Tighten icon→title gap (gap-2 → gap-1.5) and drop the muted-bg
  square behind the icon — leans on the title weight, not chrome
- TileFrame padding p-4 → p-5 and gap-3 → gap-4 across the board
- Recent tasks + Linear issues use a hairline divider per row instead
  of a flat list, with rounded-full pill status chips
- Stats / Connections sub-cards rounded-md → rounded-lg, py-2 → py-3
- Shortcuts buttons p-3 → p-4, gap-2 → gap-3 (more breathing room
  inside each shortcut card)
- Calendar items gap-2 → gap-3, dot mt-1 → mt-1.5 to align with title
- Quick chat inner gap-2 → gap-3
- Welcome hero p-5 → p-6, gap-1 → gap-2 between header chip and title

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- TileFrame inner gap-4 → gap-5 (16 → 20px) so the title clearly
  separates from the content beneath it
- Starter board: swap the GitHub/Linear/Calendar row with the
  Notes/Shortcuts row so the wide L+L pair sits in the middle —
  narrow rows above/below frame a wider centerpiece, which reads
  more bento than three same-sized rows in a row

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tiles felt boxy and noisy. Pivots to a quieter "feels-tappable" card
with chromeless content:

- Tile cards: bg-muted/30 (no border) replaces bg-background + border.
  In edit mode they get a visible border that pops on hover. Rounds
  bumped rounded-[0.75rem] → rounded-2xl.
- Header icon: muted-bg square gone — replaced with a small bordered
  bg-background container, slightly smaller title (13px) with tight
  tracking. Less visual weight, more readable.
- Stats: drop the chip cards. Each stat is just typography — large
  tabular-nums value + colored delta (emerald up / rose down / muted
  flat) + small muted label below.
- Connections overview: same treatment — Active/Inactive/Errors as
  three clean stat columns with colored dots; preview icons sit in
  bg-background mini chips.
- Recent tasks: drop dividers + pills. Each row is a colored status
  dot + title + muted status label aligned right.
- Linear issues: drop chip backgrounds; ID becomes a colored mono
  label inline with the issue title.
- GitHub activity: drop dividers; tighter line-spacing.
- Calendar: time on the left as fixed-width tabular muted label,
  title aligned baseline — reads like a real schedule.
- Notes: textarea gets a real bg-background card so it's clearly
  editable inside the muted tile.
- Shortcuts: each shortcut is a bg-background card with a soft border
  that pops to primary on hover.
- Page: agents → tiles gap mt-12 → mt-20.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 12-col grid was too granular for the bento — sizes ended up as
fractions of fractions and tiles felt small. Collapses the grid to 3
columns max with five named sizes that read like real bento blocks:

  S  1×1   small square
  M  1×2   single column, double tall (lists)
  L  2×1   landscape (charts, dual-pane)
  XL 2×2   chunky square (hero charts)
  W  3×1   full-width strip (banners)

Row height jumps 96 → 200 px so a 1×1 is a real card. v2 boards
auto-migrate: tile x and w are scaled by 1/4, h capped at 2 (was 3).
The previous starter's M/L/W tiles map cleanly to the new presets.

Adds the Reliability Agent tile (`agent.reliability`) — a 14-day
errors-over-time area chart with today's count, delta vs yesterday
(emerald if down, rose if up), and the running total. Default size
XL; supports L / XL / W. Lives in the new "agent" source category
so we can attribute later contributions.

Starter board:
  Recent tasks (1×2)        | Reliability Agent (2×2)
  Connections (2×1)         | Stats (1×1)
  GitHub (1×1)              | Linear (1×1)         | Today (1×1)

Tests rewrote to use the new 1–3 col widths and 1–2 row heights.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three customise-mode UX issues were dragging the experience down:

1. Drag preview was the wrong size. The DragOverlay used 100cqw, but
   it portals to document.body so container queries don't resolve —
   tiles ended up squished. We now capture the live cellWidth and
   cellHeight from the board element on drag start and feed absolute
   pixels (minus the inter-tile gutter) to DragOverlay so the dragged
   tile stays the same size as the source.

2. Edit mode now renders a real CSS-grid skeleton behind the tiles —
   3 columns of dashed-border cells across the full board height —
   instead of a generic dot pattern. Users can see exactly where
   things will snap. Skeleton sits at z-0 and is pointer-events-none
   so it doesn't interfere with drag.

3. Dropping a tile on top of another now swaps them when the sizes
   match (clean visual exchange) and otherwise places the dragged
   tile at the occupant's anchor and slides the occupant downward —
   smoother than the old "always push down on collision" behaviour.

Bonus: tiles transition left/top/width/height with a 200ms ease-out
when neighbours reflow, so swap and resize feel cleaner. Transition
is suppressed while a tile is actively being dragged so its
pointer-following transform reads as immediate.

Adds a unit test for the same-size swap path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously the edit-mode skeleton drew a 1×1 dashed rect at every
(x, y) cell, including cells already covered by a tile. Because tiles
have bg-muted/30 (translucent), the skeleton's inner divider lines
bled through tall tiles like a 1×2 Workspace stats — looking like the
tile contained two stacked cards. The fix is to compute which cells
are covered and skip them. The skeleton is now exactly the set of
empty drop targets, aligned to the same coordinate system as tiles
so they visually match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two issues, one critical:

1. Rendered more hooks than during the previous render (crash).
   BoardTile invoked the tile renderer as `def.render(props)` — a plain
   function call. That folds the renderer's hooks into BoardTile's hook
   tally. Different tile types have different hook counts (Reliability
   uses useId, Welcome uses useState + useSession, etc.), and any time
   re-render flow caused a transient mismatch the tally drifted and
   React threw. Renderers now mount as real components — `<Renderer
   instance={tile} isEditMode={...} />` — so each renderer's hooks
   live in its own fiber boundary. Same fix in registry's
   renderTileContent helper, which the mobile view + DragOverlay use.

2. Couldn't drop a tile into a far-away empty cell. moveTile piped
   through compactBoard, which floats every tile up to row 0 — so a
   tile dropped at row 5 instantly snapped back to row 0. Compaction
   is removed from move/insert/resize/remove. The user's chosen layout
   is preserved. Collisions still resolve (push-down for non-matching
   sizes; clean swap for same-size occupants), but only the affected
   tiles move.

Test for "remove leaves the gap" updated to match the new behaviour.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two small but visible tweaks:

- Row height 200 → 240 px so a 1×1 reads as a real card (~7:4 instead
  of ~17:8). 1×2 is now 240×480 and 2×2 is 854×480 — proportions
  closer to what a dashboard card should feel like.
- Every tile in the catalog now declares M (1 col × 2 rows) as a
  supported size — Stats, Connections, Shortcuts, Reliability Agent,
  Analytics Chart, and Quick chat were missing it. The size dropdown
  now surfaces a "Tall" option on tiles where it previously didn't
  appear.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds agent.app-frame, a tile that uses TileFrame's standard header
(icon + title + optional action) and below that renders an iframe
with smaller padding (-mx-3 -mb-3 against TileFrame's p-5) so the
embedded view feels like an inset surface, not a paragraph of text.

The iframe is sandbox="" (no scripts, no same-origin, no forms), with
a srcDoc-embedded mock of a "Stripe payments" dashboard — KPIs and
recent charges. Theme-aware via prefers-color-scheme so it reads
correctly in light and dark.

Purpose: a placeholder for the MCP-app contribution path. When apps
ship their own tiles, they'll plug into the same TileFrame header and
render their own UI inside the iframe slot. This commit proves the
chrome split (header padding ≠ content padding) and the sandboxed
embedding model.

Catalog category: data; supported sizes M/L/XL/W (default XL).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Last refactor removed compaction everywhere so the user could place
tiles wherever they dropped — but that left big vertical gaps when a
single tile was dragged to the bottom of the board. Restore
compaction as the default "tidy up" pass after every move/insert/
resize/remove. The same-size swap path still skips compaction (its
result is gap-free by construction), so dropping one M tile on top of
another reads as a clean exchange instead of both floating to the top.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Desktop pt-24 → pt-40 (96 → 160 px), mobile pt-20 → pt-28
(80 → 112 px). With the reduced number of tiles in the new starter
and the taller cells, the chat area was sitting too high; this brings
it down so the greeting + composer + agents read as a centered hero
above the board.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The agents row below the chat used a different visual language from
the tile board — small icon-on-top buttons in a 100px slot with no
chrome. Now each agent (and the Create / See all buttons) renders as
a 136px-wide card matching the bento system: rounded-2xl, bg-muted/30
with hover state, transparent border that pops on hover, p-4 padding,
icon top-left, label below at text-[13px] tracking-tight.

The row gap goes 1.5 → 2; max-h drops 52 → 32 so only one card-row
shows on desktop. Skeleton matches the new shape.

Net effect: chat → agents → tile board reads as one coherent visual
language down the page instead of three different design eras.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Promotes agents from the row above the chat into the tile board so
the home is one design system end-to-end.

- New AgentCardTile renderer. No iframe, no view — just a clickable
  card with icon, title, and description that navigates to a fresh
  chat thread (passing virtualmcpid so the chat surface knows which
  agent to wire up).
- TileDefinition gains a `defaultConfig` field. Catalog entries can
  bake config (templateId / title / icon / description) into the
  instance the user adds.
- Catalog registers one entry per WELL_KNOWN_AGENT_TEMPLATES under a
  new "Agents" category so users can pin specific agents from the
  Add-tile sheet.
- Starter board seeds three agent cards (Site Editor, Image Creator,
  Web Researcher) sandwiched between the dashboard tiles.
- AgentsList row removed from the home — chat sits directly above
  the tile board now.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two changes to make agents feel alive when they show up on the home:

- Agent cards move to row 0 of the starter board so the very first
  thing the user sees below the chat is "what my agents are working
  on". Three cards across at M (1×2) so they're properly readable.
- AgentCardTile now renders a list of recent tasks (mocked today,
  wired to live agent activity later) when the tile has vertical
  room (h ≥ 2). Each task is a colored status dot + truncated title;
  status colors match the design language used elsewhere
  (primary / amber / rose / emerald). When the agent has no tasks,
  the card falls back to its description.
- Catalog seeds mock task lists for Site Editor, Site Diagnostics,
  Image Creator, and Self-healing Storefront so the catalog preview
  reflects what the card will look like once added.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two issues with the catalog drawer:

1. The ScrollArea sat inside a flex-1 wrapper without min-h-0, so in
   a flex-col parent it kept its content-height and never actually
   scrolled past the visible area. Wrap it in a `flex-1 min-h-0`
   container so the inner ScrollArea root gets a definite height and
   the content scrolls to the bottom — including the agents and the
   workflow categories that were previously cut off.

2. Visual refresh:
   - Header gets a tighter, smaller title + subtitle and a focused-on-
     open search input.
   - Each catalog row is now a 10×10 icon container in a soft card
     with hover state (border-primary/40, bg-muted/40), 13px
     tracking-tight title, 12px muted description.
   - Source badge moves from outline to a colored pill (primary tint
     for agents, amber for MCP) so the catalog reads at a glance.
   - Category headers use a small uppercase-tracking-wider treatment
     with a count chip on the right.
   - Spacing between sections gap-6 → gap-7, page bottom padding
     bumped so the last group doesn't sit flush against the edge.

Agents already lived in the catalog (registered in TILE_CATALOG via
AGENT_CARD_ENTRIES); they now appear visibly in the "Agents" section
near the top of the sheet.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Strips every mocked tile and wires the kept ones to real Studio sources:

- RecentTasksTile reads from useTasks({ owner: "me", status: "open" })
  and now reuses lib/task-status.ts (getStatusConfig) for icon/label/
  color instead of a hand-rolled status map. Same surface as the
  tasks panel so a status update drifts in one place, not two.
- RecentAgentsTile reads from useVirtualMCPs() and uses AgentAvatar
  (the canonical agent visual used by the sidebar and tasks panel)
  instead of IntegrationIcon. AgentCardTile too.
- StatsTile counts active agents, total agents, active connections,
  and errored connections from the same hooks.
- Removed renderers: GithubActivityTile, LinearIssuesTile,
  CalendarTile, AnalyticsChartTile, ReliabilityAgentTile,
  AppFrameTile — all mock-only.
- Studio data tiles (recent-tasks, recent-agents, connections-
  overview, stats) attributed to source: "agent", sourceId:
  "studio-agent" via a shared STUDIO_AGENT_SOURCE constant.

Cleanup from review:
- Shared agent seeds (title/icon/description) moved to agent-seeds.ts
  and consumed by both registry and starter so the catalog preview
  stays in sync with placed instances.
- agentCardType(id) helper replaces inline `agent.card.${id}`
  template strings.
- TileSlot component encapsulates the TileErrorBoundary + Suspense +
  renderer-or-helper triplet that lived in three places (BoardTile,
  mobile view, DragOverlay).
- Magic numbers extracted: RECENT_AGENT_LIMIT, RECENT_TASK_LIMIT,
  CONNECTION_PREVIEW_LIMIT.

Each tile renders inside a Suspense fallback'd by TileSkeleton, so
slow Studio queries only block their own tile, not the whole board.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Category headers and the size pill in the catalog were rendered
uppercase. Removed the uppercase + wide-tracking treatment so they
match the rest of the design system (sentence case, tracking-tight).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The composer at the top of the home already covers this surface;
duplicating it as a pinnable tile added a second textarea with the
same destination. Drops the renderer, the catalog entry, and the
Lightning01 / useState imports they were the only consumers of.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Studio's data tiles (Recent tasks, Recent agents, Connections,
Workspace stats) now wear the same agent-card chrome as the
template tiles: avatar top-left, agent name as a small muted
eyebrow, view name as the primary title, body below. Defines a
STUDIO_AGENT identity (Stars01 / violet) so all four read as views
of one agent.

- New AgentTileFrame: avatar + optional action chip on top, eyebrow
  (agent name) + title (view name) below, body fills the rest.
- AgentCardTile reuses the same frame with eyebrow={false} so it
  doesn't render "Image Creator / Image Creator" — title is the
  agent name, body is the description, layout matches.
- System tiles that don't belong to an agent (Notes, Shortcuts,
  Unknown) keep a slimmer SystemTileFrame with the small icon +
  inline title — no avatar, no eyebrow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…it modals

Two regressions from the migration to tiles-only home:

1. New users landed on an empty board with a "Pin tiles to your home"
   banner instead of the default tile set. The home is supposed to
   start populated. useHomeBoard's first-load path (no localStorage
   value) now seeds with createStarterBoard() instead of an empty
   board. Boards explicitly cleared by the user (tiles: []) are
   respected and stay empty.

2. Agent-card clicks were going straight to a fresh chat thread with
   ?virtualmcpid=<templateId>, but unrecruited templates have no live
   vMCP — the chat surface spun on "starting task". Restores the
   original AgentsList click logic via a new AgentRecruitProvider
   that mounts every recruit/import modal once at the home and
   exposes openAgent(templateId). AgentCardTile dispatches:
     - site-editor → ImportFromDecoDialog
     - site-diagnostics / ai-image / ai-research / lean-canvas →
       their RecruitModal, OR navigate to the existing matching vMCP
       when one is already installed (via useNavigateToAgentThread)
     - studio-pack → StudioPackRecruitModal
     - self-healing-storefront → SelfHealingRepoFlow
   Custom (non-template) agent.card tiles still navigate directly.

HomePage wraps its content in AgentRecruitProvider so context is
available to every tile.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
rafavalls and others added 14 commits May 15, 2026 02:52
…ata tiles

Two fixes per design feedback on the rendered home:

- Agent cards in the starter board drop M (1×2) → S (1×1). At S the
  AgentTileFrame fits cleanly: avatar + name only, no description.
  The cards no longer dwarf the data tiles below them.
- New AgentDataTileFrame for tiles attributed to an agent that have
  body content (Recent tasks, Recent agents, Connections, Workspace
  stats). Header is the same compact pattern SystemTileFrame uses —
  small AgentAvatar (xs/24px) inline with the view title — so the
  data area has maximum room. The big-avatar AgentTileFrame stays for
  agent.card tiles where the agent is the content.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two changes to the Add-tile sheet:

- New "Studio Agent" category renders Recent tasks, Recent agents,
  Connections, and Workspace stats in their own group with the Studio
  Agent avatar (xs Stars01/violet) on every row. Catalog rows now
  render def.icon directly so the agent avatars look right inline —
  the previous <img>-fallback wrapper is gone.
- Catalog goes from a static export to a useTileCatalog() hook. On
  top of the static set it adds, for every active installed virtual
  MCP:
    - one agent-card entry pointing at the agent itself, and
    - one tile per layout tab (`metadata.ui.layout.tabs`) and one per
      pinned view (`metadata.ui.pinnedViews`)
  When the user adds one of those UI tiles, AgentToolViewTile renders
  it: an agent-attributed card that, on click, opens a thread with
  ?virtualmcpid=<agent>&main=<tab> so they land on the exact tab the
  agent's settings layout would land on. Same `?main=` model the chat
  surface already speaks.
- STUDIO_AGENT identity moved out of renderers.tsx into agent-seeds.ts
  so the registry, the renderers, and any future consumer share the
  same icon + name.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pinned dynamic tiles (one per installed agent and one per agent UI
view) carry a unique type like agent.tool-view.<id>.<tab> or
agent.card.installed.<id>. Those types aren't in the static
TILE_CATALOG, so after persistence + reload getTileDefinition
returned undefined and the board rendered UnknownTile ("Tile type X
isn't installed") even though the catalog had just generated it.

Add a prefix-matching fallback to getTileDefinition that returns a
minimal synthetic def for the two dynamic prefixes so TileSlot can
still route to AgentToolViewTile / AgentCardTile and the per-tile
size menu has supportedSizes to draw from. The instance's stored
config carries everything the renderer needs (agent id, title, icon,
mainTabId, etc.), so the synthetic def's title/description/icon
fields are intentionally empty.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The tool-view tile was a placeholder that said "Open the X view from
Y" — it didn't actually render the agent's UI. Now it embeds
AppViewContent (the same renderer the chat surface uses for layout
tabs and pinned views) so the agent's UI shows up directly in the
tile body.

Catalog wiring: dynamic tool-view entries now carry the resolved
(connectionId, toolName, args) on their defaultConfig so the renderer
can call the right tool without extra metadata lookups:
  - layout tabs: connectionId = view.appId, toolName = tab.id,
    args = view.args
  - pinned views: connectionId = view.connectionId,
    toolName = view.toolName

The `Open` action in the header still navigates to the full view in
the chat surface (?virtualmcpid=...&main=<tab>) for users who want
the fullscreen experience. Default size bumps L/XL/W with default XL
since the embedded UI needs room.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tool-view tiles pinned before connectionId/toolName were stored on
config still rendered the "Open <view>" placeholder because their
config carried only mainTabId. Add a resolveToolTarget helper that:

  1. Returns config.connectionId/toolName when present (new pins).
  2. Otherwise parses pinned-view tab ids of the form
     `app:<connectionId>:<toolName>`.
  3. Otherwise looks up the agent's live `metadata.ui.layout.tabs`
     for a tab with id === mainTabId and reads view.appId / view.args.

AgentToolViewTile now calls useVirtualMCPs and feeds the resolved
target into AppViewContent, so an existing Monitor / pinned-view
tile renders its actual UI on the next reload — no re-pinning
required.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The home tile system grew sprawling: 17 files, ~3.3k insertions, dnd
grid, dynamic agent catalog, recruit provider, tile-add sheet, edit
mode. Most was unused (`SHOW_HOME_TILES = false`) so the surface area
never paid off.

This rewrite collapses the system around the design intent: a side
Tasks panel of preset cards that, on click, start a preconfigured
chat and surface a matching tile on the home page once the work is
running.

- Tasks panel: 5 preset cards (New chat, Extract brand context,
  Create landing page, Set up error monitoring, Import Deco site)
  with colored thumbnail badges matching the Figma reference. New
  chat keeps its existing behavior; the three tile-producing presets
  call a small `startPresetTask` helper that primes autosend with a
  tailored prompt, activates the matching home tile, and navigates
  to the new thread. Import Deco opens the existing import dialog.
- Home tiles: only three, mapped 1:1 to the three preset tasks
  (brand context, landing page, error monitoring). Responsive
  1/2/3-column grid; each tile shows a running skeleton or a mock
  ready-state preview and clicks back to the chat that produced it.
  Activation persists per-org in localStorage.
- Home page: chat composer untouched on top, tile grid below when
  activated. Added a subtle SVG-tile background pattern and the
  capybara peeking from the corner of the chat composer.
- Deleted: agent-recruit-provider, agent-seeds, grid-utils +tests,
  tile-add-sheet, tile-config-update-context, tile-error-boundary,
  tile-slot, constants, seed, use-home-board.
- Reverted: agents-list styling drift, localstorage key churn for
  removed tile-board/notes/pinned slots.

Net change vs main: ~470 lines instead of 3.3k.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Course-correct from the over-aggressive cleanup. The dnd tile-board is
back, the 5 side-panel task cards now use the Figma-exported PNG
illustrations as their thumbnails, and the home page renders the real
Figma background tile pattern.

Tile system:
- TileBoard with dnd-kit (drag, resize, remove, edit mode) restored.
- Three preset tile types — studio.brand-context, studio.landing-page,
  studio.error-monitoring — each with its own renderer that flips
  between a running skeleton and a representative ready-state preview.
  Tiles carry the task id of the chat that spawned them so a click
  lands back in that thread.
- Catalog shrunk to those three only; agent-recruit, dynamic agent
  catalog, agent-seeds, tile-add-sheet stay deleted.
- start-preset-task primes autosend with the prompt and pins the
  matching tile to the user's board before navigating.

Tasks panel:
- Five preset cards: New chat, Extract brand context, Create landing
  page, Set up error monitoring, Import Deco site. Each renders the
  Figma PNG thumbnail (public/home/task-*.png) instead of a CSS
  recreation. Import Deco still opens the existing import dialog.
- Clicking a tile-producing preset adds the matching tile to the home
  board via useHomeBoard.addTile and starts the chat.

Home page:
- Background uses the real Figma tile-pattern PNG, mirrored top/bottom.
- Capybara peeks from the corner of the chat composer.
- Customize toolbar (edit mode + clear) restored, gated to when the
  board has tiles.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nd wide sidebar

- Replace all PNG home assets with SVG equivalents (crisp at any zoom,
  light/dark variants for background corners)
- Redesign background: corner-anchored SVGs (top-left / bottom-right)
  instead of the tiled PNG strip
- Fix scroll container so corner art stays fixed while content scrolls;
  vertically center input when no tiles are present
- Tile icons now use IntegrationIcon + WELL_KNOWN_AGENT_TEMPLATES metadata
  (colored icon system) instead of hardcoded Untitled UI icons
- Add brand-context / landing-page / system-health to WELL_KNOWN_AGENT_TEMPLATES
- Bump tile drag-handle and menu-button to size-8 / icon-16 for larger hit targets
- Tasks panel: remove empty-state; default to preset cards on home, task
  list in chat; per-route open/close state (home vs chat independent)
- Wide sidebar mode (560 px) on home, normal (340 px) in chat routes
- Preset cards: bordered style, h-11 w-16 thumbnails, numbered step badges
- Fix chat input dark-mode background (bg-card instead of dark:bg-muted)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Format: split long function parameter in tasks-section.tsx
- Lint: wrap ternary className with cn() in home-page/index.tsx
- Knip: delete unused agents-list component, remove unused exports
  (MOBILE_BREAKPOINT_COLS, pixelDeltaToCellDelta, TILE_CATALOG export,
  useTileConfigUpdate) and unused function bodies

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Transitioned to a 3-column grid layout with five preset tile sizes.
- Removed unused tile types and related files, including tests and context providers.
- Updated tile rendering logic to use a suspense boundary for better loading states.
- Cleaned up constants and types, eliminating unnecessary properties.
- Adjusted the home board logic to streamline tile management and initialization.

This refactor focuses on enhancing maintainability and performance by reducing complexity in the tile system.
@pedrofrxncx pedrofrxncx force-pushed the rafavalls/new-home branch from 6dbfcfb to 8162aea Compare May 15, 2026 05:53
- Introduced a new `PresetTaskStore` for managing task states in KV storage.
- Added `PresetTaskRegistry` to handle task definitions and their visibility.
- Created API routes for preset tasks, including endpoints for starting and dismissing tasks.
- Integrated brand-context workflow with DBOS for managing the lifecycle of brand-context tasks.
- Updated the application context to include preset task dependencies.
- Enhanced the home tile system to support new preset tasks, allowing users to initiate tasks directly from the UI.

This implementation enhances the user experience by providing a structured way to manage and interact with preset tasks, improving overall functionality and maintainability.
…ynamic instructions

- Added `brand-context` agent to manage brand setup and confirmation workflows, including functions to retrieve and update brand information.
- Implemented `system-health` agent for monitoring site health, integrating with existing connection management.
- Created `dynamic-instructions` registry to provide context-sensitive prompts based on organizational state.
- Enhanced API routes to support new agents and their functionalities, including home board management and preset task integration.
- Established a robust system for handling brand context and health monitoring, improving user experience and operational efficiency.

This implementation lays the groundwork for more interactive and responsive agent behaviors, enhancing the overall functionality of the application.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

16 issues found across 63 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/mesh/src/agents/system-health.ts">

<violation number="1" location="apps/mesh/src/agents/system-health.ts:76">
P2: `ensureSystemHealthConnection` is not truly idempotent under concurrent calls; the check-then-create sequence can create duplicate system-health connections for one organization.</violation>
</file>

<file name="apps/mesh/src/web/components/home/tiles/tile-error-boundary.tsx">

<violation number="1" location="apps/mesh/src/web/components/home/tiles/tile-error-boundary.tsx:24">
P2: This error boundary never resets after a crash, so a tile can remain permanently stuck on the fallback until remount. Add a reset mechanism (for example, reset when a `resetKey` prop changes).</violation>
</file>

<file name="apps/mesh/src/agents/dynamic-instructions.ts">

<violation number="1" location="apps/mesh/src/agents/dynamic-instructions.ts:33">
P2: Use an explicit null check when resolving instructions; the current truthy check incorrectly ignores valid empty-string results.</violation>
</file>

<file name="apps/mesh/src/storage/home-board.ts">

<violation number="1" location="apps/mesh/src/storage/home-board.ts:123">
P1: `pickAutoPinSlot` has a hardcoded row cap and may return an unchecked occupied position once `y` reaches 1024.</violation>
</file>

<file name="apps/mesh/src/web/lib/query-keys.ts">

<violation number="1" location="apps/mesh/src/web/lib/query-keys.ts:89">
P2: `homeBoard` query key is missing a user dimension even though the cached data is per-user, which can cause cross-user cache reuse within the same org.</violation>
</file>

<file name="apps/mesh/src/tools/github/has-installation.ts">

<violation number="1" location="apps/mesh/src/tools/github/has-installation.ts:51">
P2: This check only inspects the first page of GitHub installations, so it can incorrectly return `false` when the matching org appears on later pages.</violation>
</file>

<file name="apps/mesh/src/web/hooks/use-auto-install-system-health.ts">

<violation number="1" location="apps/mesh/src/web/hooks/use-auto-install-system-health.ts:60">
P1: The start condition can permanently block auto-install when `org` is not ready on first render. Include `org` in the gate before setting `startedRef`.</violation>
</file>

<file name="apps/mesh/src/web/hooks/use-tasks-panel-state.tsx">

<violation number="1" location="apps/mesh/src/web/hooks/use-tasks-panel-state.tsx:34">
P2: `chatOpen` is derived from `tasks.length` only at initial mount, so route transitions after task-list changes can show the chat panel closed even when open tasks exist.</violation>
</file>

<file name="apps/mesh/src/api/routes/deco-sites.ts">

<violation number="1" location="apps/mesh/src/api/routes/deco-sites.ts:462">
P0: Hardcoded deco.cx email bypasses per-user identity and makes authorization/data lookups run as a fixed account.</violation>
</file>

<file name="apps/mesh/src/api/routes/decopilot/built-in-tools/brand-context-confirm.ts">

<violation number="1" location="apps/mesh/src/api/routes/decopilot/built-in-tools/brand-context-confirm.ts:140">
P1: Handle `extractBrandFromDomain` exceptions and return a structured tool error instead of letting the tool throw.</violation>

<violation number="2" location="apps/mesh/src/api/routes/decopilot/built-in-tools/brand-context-confirm.ts:195">
P2: Verify the organization still has a primary brand before marking the brand-context preset as completed.</violation>
</file>

<file name="apps/mesh/src/preset-tasks/brand-context-workflow.ts">

<violation number="1" location="apps/mesh/src/preset-tasks/brand-context-workflow.ts:74">
P2: Guard timeout/error writes so only the active workflow run can update preset state; otherwise stale workflows can overwrite newer run results.</violation>
</file>

<file name="apps/mesh/src/agents/brand-context.ts">

<violation number="1" location="apps/mesh/src/agents/brand-context.ts:54">
P1: Untrusted brand fields are injected into the system prompt without sanitization, enabling prompt-injection via extracted website content.</violation>
</file>

<file name="apps/mesh/src/api/routes/preset-tasks.ts">

<violation number="1" location="apps/mesh/src/api/routes/preset-tasks.ts:272">
P1: Require authentication on the dismiss route; it currently allows unauthenticated callers to modify org-scoped preset task state.</violation>
</file>

<file name="apps/mesh/src/api/app.ts">

<violation number="1" location="apps/mesh/src/api/app.ts:437">
P2: Token persistence misses client credentials sent via HTTP Basic auth, which causes stored tokens to be non-refreshable (`clientId` remains null).</violation>

<violation number="2" location="apps/mesh/src/api/app.ts:539">
P1: Persisting downstream tokens in the shared oauth-proxy handler allows token writes on the legacy unscoped path, which can bypass org-scoped authorization checks.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/mesh/src/api/routes/deco-sites.ts
Comment thread apps/mesh/src/storage/home-board.ts
Comment thread apps/mesh/src/web/hooks/use-auto-install-system-health.ts
Comment thread apps/mesh/src/api/routes/decopilot/built-in-tools/brand-context-confirm.ts Outdated
Comment thread apps/mesh/src/agents/brand-context.ts Outdated
Comment thread apps/mesh/src/tools/github/has-installation.ts Outdated
const [homeOpen, setHomeOpen] = useState<boolean>(() =>
onHome ? resolveTasksOpen(search.tasks, true) : true,
);
const [chatOpen, setChatOpen] = useState<boolean>(() =>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: chatOpen is derived from tasks.length only at initial mount, so route transitions after task-list changes can show the chat panel closed even when open tasks exist.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mesh/src/web/hooks/use-tasks-panel-state.tsx, line 34:

<comment>`chatOpen` is derived from `tasks.length` only at initial mount, so route transitions after task-list changes can show the chat panel closed even when open tasks exist.</comment>

<file context>
@@ -12,27 +12,32 @@ interface TasksPanelState {
+  const [homeOpen, setHomeOpen] = useState<boolean>(() =>
+    onHome ? resolveTasksOpen(search.tasks, true) : true,
   );
+  const [chatOpen, setChatOpen] = useState<boolean>(() =>
+    !onHome
+      ? resolveTasksOpen(search.tasks, tasks.length > 0)
</file context>

Comment thread apps/mesh/src/preset-tasks/brand-context-workflow.ts
Comment thread apps/mesh/src/api/app.ts
- Added a new `web-developer` agent that facilitates the creation of static HTML pages, allowing users to write, read, list, and delete pages stored in object storage.
- Implemented dynamic instructions for the web-developer agent to provide context-sensitive prompts based on the user's brand information.
- Created built-in tools for the web-developer agent, including `write_html_page`, `read_html_page`, `list_html_pages`, and `delete_html_page`, enhancing the agent's functionality.
- Updated API routes to integrate the web-developer agent and its tools, ensuring seamless interaction within the application.
- Enhanced the chat interface to support HTML page previews, improving user experience during page creation.

This implementation expands the capabilities of the application by enabling users to generate and manage web content directly through the chat interface.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 16 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/mesh/src/api/routes/decopilot/built-in-tools/web-developer.ts">

<violation number="1" location="apps/mesh/src/api/routes/decopilot/built-in-tools/web-developer.ts:159">
P2: `list_html_pages` only returns the first 100 objects, so results become incomplete once a thread has >100 pages.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/mesh/src/api/routes/decopilot/built-in-tools/web-developer.ts
- Introduced a `sanitizeBrandField` function to clean and limit the length of brand-related fields, improving data presentation.
- Updated the `formatConfirmModePrompt` function to utilize the new sanitization logic for brand details.
- Enhanced error handling in the brand extraction process, providing clearer feedback when extraction fails.
- Added checks to ensure brand context exists before proceeding with confirmation workflows, improving robustness.

These changes enhance the user experience by ensuring cleaner data display and more informative error messages during brand context operations.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/mesh/src/agents/brand-context.ts">

<violation number="1" location="apps/mesh/src/agents/brand-context.ts:50">
P1: `sanitizeBrandField` does not neutralize `<`/`>`, so untrusted brand content can inject `</brand>` and escape the protected block in the prompt. Escape angle brackets (and `&`) before interpolation.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Comment thread apps/mesh/src/agents/brand-context.ts
pedrofrxncx and others added 3 commits May 15, 2026 09:19
- Restore real auth checks in deco-sites.ts profile/list/connection routes;
  the dev-only hardcoded email was an oversight from local-auth debugging.
- Remove OAuth-proxy downstream-token persistence and the supporting
  Basic-auth/form-body credential capture from app.ts; this is a separate
  concern from the home redesign and will be re-landed in its own PR.
- Drop the rAF-coalesced streaming and finish-handoff dedupe from
  use-thread-chat.ts; same — chat-stream perf belongs in its own PR.
- Drop the thread→virtual_mcp_id drift guard from dispatch-run.ts.
- Revert the user-ask refactor (react-hook-form draft split + decoder
  helper + tests) so the home PR doesn't bundle that change.

These pieces stay in the working tree for the author to land separately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…LoC)

Multi-perspective code review surfaced ~600 LoC of duplication and dead
indirection in the home redesign. This consolidates the easy wins.

Frontend
- Extract InstallFlowDialog shell + runOAuthHandshake helper; delete
  install-{github,system-health}-dialog wrapper files and shrink both
  auto-install hooks to their distinctive create-connection step.
- Delete the tile registry/TileDefinition indirection: there was one
  TileDefinition for one tile type. TileSlot now renders <PresetTile/>
  directly; supportedSizes falls through to ALL_SIZES.

mesh-sdk
- Add preset-tasks.ts module with PresetTaskAction/Status/State/Step,
  VisiblePresetTask, StartPresetTaskResult, etc. Both FE and BE now
  import from here, fixing real FE↔BE drift (FE was missing
  dbosWorkflowId and steps fields).
- Extract createWellKnownAgentPrefix({prefix}) → {is, get} factory and
  defineWellKnownAgentVMCP() helper for the 12-field entity envelope;
  collapse 4 duplicate prefix pairs and 3 VirtualMCPEntity factories.

Backend
- Extract built-in-tools/brand-context-helpers.ts: requireOrgId,
  requireFirecrawlKey, requireOrgBrand, brandSnapshot — replaces the
  repeated 4-step auth/firecrawl/brand envelope across brand-context
  setup and confirm tools.
- Delete agents/dynamic-instructions.ts registry. Direct calls to
  resolveBrandContextPrompt / resolveWebDeveloperPrompt in dispatch-run
  replace the side-effecting register/resolve pattern; the two boot-time
  register* calls in app.ts go away.
- Add kvGet/kvSet helpers in storage/kv.ts so HomeBoardStore and
  PresetTaskStore stop hand-rolling the same get/set + cast ceremony.
- Narrow several incidental exports to internal types
  (BrandExtractedSignal, BrandContextWorkflow{Input,Outcome},
  PresetBodyProps, PresetTaskStep, PresetTaskStepStatus).

No behavior changes. Typecheck, lint, and fmt pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…s and connection management

- Introduced `getSystemHealthAgentConnectionId` function to resolve the agent's connection ID, enabling automation setup.
- Added `createSystemHealthTools` for creating health automation, allowing users to schedule recurring runs or subscribe to events.
- Updated `ensureSystemHealthAgent` to include UI configurations for application errors.
- Enhanced API routes to integrate system health tools, improving the agent's functionality and user experience.
- Added tests for new user-ask response handling and schemas, ensuring robust input validation.

These changes expand the capabilities of the system health agent, facilitating better monitoring and automation of site health checks.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 32 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/mesh/src/web/hooks/use-oauth-handshake.ts">

<violation number="1" location="apps/mesh/src/web/hooks/use-oauth-handshake.ts:87">
P2: `onPersistFallback` can run twice when the first fallback call throws, causing duplicate side effects.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

);
if (!response.ok) {
if (opts.onPersistFallback) {
await opts.onPersistFallback(connectionId, token);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: onPersistFallback can run twice when the first fallback call throws, causing duplicate side effects.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mesh/src/web/hooks/use-oauth-handshake.ts, line 87:

<comment>`onPersistFallback` can run twice when the first fallback call throws, causing duplicate side effects.</comment>

<file context>
@@ -0,0 +1,108 @@
+      );
+      if (!response.ok) {
+        if (opts.onPersistFallback) {
+          await opts.onPersistFallback(connectionId, token);
+        } else {
+          const body = (await response.json().catch(() => ({}))) as {
</file context>

Tip: Review your code locally with the cubic CLI to iterate faster.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants