## Task 4: Channel Content Templates And Object Inspector **Files:** - Create: `apps/web/src/features/workbench/ChannelContent.svelte` - Create: `apps/web/src/features/workbench/ObjectInspector.svelte` - Create: channel components under `apps/web/src/features/workbench/channels/` - Modify: `apps/web/src/features/workbench/ProjectWorkbench.svelte` - Test: `apps/web/src/features/workbench/ChannelContent.test.ts` **Interfaces:** - Consumes: `ProjectWorkspace` - Consumes: selected `WorkbenchChannel` - Produces: `onInspect(item: InspectorItem): void` - Produces: per-channel headings and selectable records. - [ ] **Step 1: Write failing channel content test** Create `apps/web/src/features/workbench/ChannelContent.test.ts`: ```ts import '@testing-library/jest-dom/vitest'; import { fireEvent, render, screen } from '@testing-library/svelte'; import { describe, expect, it } from 'vitest'; import ChannelContent from './ChannelContent.svelte'; import { getProjectWorkspace } from './mockData'; describe('ChannelContent', () => { const workspace = getProjectWorkspace(1); it('renders different templates for system and custom channels', () => { for (const type of ['overview', 'inbox', 'tasks', 'ai_sessions', 'notes_sources', 'cron', 'custom_link'] as const) { const channel = workspace.channels.find((item) => item.type === type); if (!channel) throw new Error(`missing ${type}`); render(ChannelContent, { props: { workspace, channel, onInspect: () => {} } }); } expect(screen.getByText('Open external channel')).toBeInTheDocument(); }); it('sends selected task details to inspector', async () => { let inspectedTitle = ''; const channel = workspace.channels.find((item) => item.type === 'tasks'); if (!channel) throw new Error('missing task channel'); render(ChannelContent, { props: { workspace, channel, onInspect: (item) => { inspectedTitle = item.title; }, }, }); await fireEvent.click(screen.getByRole('button', { name: 'Inspect Confirm homepage information architecture' })); expect(inspectedTitle).toBe('Confirm homepage information architecture'); }); }); ``` - [ ] **Step 2: Run test to verify it fails** Run: ```powershell Set-Location D:\work\senlinai\agent\apps\web npm test -- --run src/features/workbench/ChannelContent.test.ts ``` Expected: FAIL because `ChannelContent.svelte` does not exist. - [ ] **Step 3: Implement `ChannelContent.svelte` dispatcher** Create a dispatcher that selects the channel component by `channel.type`: ```svelte {#if channel.type === 'overview'} {:else if channel.type === 'inbox'} {:else if channel.type === 'tasks'} {:else if channel.type === 'ai_sessions'} {:else if channel.type === 'notes_sources'} {:else if channel.type === 'cron'} {:else} {/if} ``` - [ ] **Step 4: Implement channel components** Each channel component should render its own page template and call `onInspect` for selectable records. Example for `TasksChannel.svelte`: ```svelte

Work Plan

Tasks

{#each tasks as task}

{task.title}

{task.summary}

{task.owner} 路 {task.due} 路 #{task.tag}
{/each}
``` Implement the remaining channel components with the same pattern: - `OverviewChannel.svelte`: metrics for inbox, tasks, AI sessions, notes/sources, cron plans. - `InboxChannel.svelte`: email-like message list with source, title, summary, status, tag, time. - `AISessionsChannel.svelte`: session list plus selected conversation summary area. - `NotesSourcesChannel.svelte`: file-manager-like list of note/file/link records. - `CronChannel.svelte`: scheduled task rows with enabled state, schedule, next run, last result. - `CustomLinkChannel.svelte`: external URL page with `Open external channel` link and copy-style button. - [ ] **Step 5: Implement `ObjectInspector.svelte` and wire it into `ProjectWorkbench.svelte`** Create `ObjectInspector.svelte`: ```svelte ``` Update `ProjectWorkbench.svelte` so `ChannelContent` receives the selected channel and `ObjectInspector` receives selected item. - [ ] **Step 6: Run channel tests** Run: ```powershell Set-Location D:\work\senlinai\agent\apps\web npm test -- --run src/features/workbench/ChannelContent.test.ts src/features/workbench/ProjectWorkbench.test.ts ``` Expected: PASS. - [ ] **Step 7: Commit** Run: ```powershell Set-Location D:\work\senlinai\agent git add apps\web\src\features\workbench git commit -m "feat: add workbench channel templates" ``` ---