4 plans across 3 waves for SSE streaming, agent selector, edit/retry,
slash commands, @mentions, and virtualized message list.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create ChatConversationList with infinite scroll (IntersectionObserver), inline rename/delete confirmation, pin/archive/unarchive actions via DropdownMenu
- Create ChatMessageList with role=log, aria-live, ChatMarkdownMessage for assistant messages, auto-scroll to bottom
- Create ChatPanel right-side drawer shell composing conversation list and message area with width transition (chatOpen ? 380 : 0)
- Integrate ChatPanel and MessageSquare toggle button into Layout.tsx
- Add effect to close PropertiesPanel when chat opens
- Create chatApi with full CRUD + archive/pin/message endpoints
- Create ChatPanelContext with localStorage persistence (nexus:chat-panel-open)
- Create useChatConversations with useInfiniteQuery and conversation mutations
- Create useChatMessages with useInfiniteQuery and useSendMessage
- Wrap app tree with ChatPanelProvider in main.tsx
- Add chatRoutes factory with 11 endpoints (conversations + messages)
- Mount chatRoutes in app.ts after activityRoutes
- Export chatRoutes from routes/index.ts
- Add chat-routes test suite (12 tests, all passing)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Auto-resize textarea from 1 to 6 lines (max-height 160px)
- Enter sends message and clears input
- Shift+Enter inserts newline without sending
- Escape clears input when non-empty, calls onClose when empty
- Disabled state and loading spinner when isSubmitting=true
- Accessible: aria-label on textarea and send button
- 9 tests green (jsdom environment)
- Replace "Cancel" with "Keep conversation" in delete confirmation (Dimension 1)
- Drop font-weight 500 (medium); consolidate to 400 + 600 only (Dimension 4)
- Fix ChatInput padding from py-2.5 (10px) to py-2 (8px) (Dimension 5)
- Name 12px as sm+ token with justification for conversation list item padding (Dimension 5)
- Add noun suffix to all dropdown action labels ("Archive conversation", etc.)
- Add focal point statement to contract
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Planning artifacts (milestones v1.0-v1.2.1, v1.3 queue, PROJECT.md,
STATE.md, config) now live alongside the code they describe.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Import getUIAdapter and resolveAdapterSkillConfig/listAdapterSkillConfigs
- Show adapter type label in parentheses next to agent name in Installed tab selector
- Show adapter type label in install dialog agent list
- Guard handleInstallForAgent: show unsupportedMessage if adapter does not support install
- Dismissible error alert in install dialog for unsupported adapter attempts
- Clear unsupportedMessage on dialog open/close
- Compute COMPATIBLE_ADAPTER_LABELS at module level for Task 2
- Add Model field (both create + edit modes) using CreateConfigValues.model
- Add Toolsets field (both create + edit modes) using extraArgs in create, adapterConfig.toolsets in edit
- Add Persist Session checkbox (edit mode only) wired to adapterConfig.persistSession
- Add Timeout (seconds) field (edit mode only) wired to adapterConfig.timeoutSec
- Restructure component to use fragment with conditional hideInstructionsFile guard
- TypeScript compiles cleanly
- Add gemini_local to AGENT_ADAPTER_TYPES array after hermes_local
- Closes TypeScript gap where gemini_local was valid in UI adapter registry but missing from AgentAdapterType union type
- TypeScript compiles cleanly for @paperclipai/shared and @paperclipai/ui
- SkillCard: add isReadOnly and source props; hide update/rollback/install when isReadOnly
- SkillCard: show Native badge when isReadOnly or source=native
- SkillBrowser: remove agentSkillsDir state and text input from install dialog
- SkillBrowser: add selectedAgentId state for per-agent installed skills view
- SkillBrowser: add agentInstalledSkills query using skillGroupsApi.listAgentSkills
- SkillBrowser: split installed skills into managedSkills/nativeSkills sections
- SkillBrowser: render Managed/Native section headings when nativeSkills.length > 0
- SkillBrowser: uninstall dialog now carries agentId and calls skillRegistryApi.uninstall
- SkillBrowser: install dialog sends agentId directly (no agentSkillsDir text input)
- Add AgentSkillEntry type with skillId, source, installedAt fields
- install() now sends agentId in body not agentSkillsDir
- uninstall() new function that sends agentId as query param
- rollback() now sends agentId in body not agentSkillsDir
- skillGroups.assignGroup/removeGroup no longer accept agentSkillsDir param
- listAgentSkills now returns AgentSkillEntry[] not string[]
- Fix AgentDetail.tsx callers and entry rendering for new AgentSkillEntry type
- Fix SkillDetail.tsx callers to use agentId param
- Add resolveSkillsDirForAgent helper to skill-registry.ts and skill-registry-groups.ts
- Install route accepts agentId in body (not agentSkillsDir)
- Uninstall route accepts agentId as query param; returns 403 for native skills
- Rollback route accepts agentId in body (not agentSkillsDir)
- Group assign/remove routes resolve dir from URL agentId param
- List agent skills route calls syncHermesNativeSkills for hermes_local agents
- skillRegistryRoutes(db) and skillGroupRoutes(db) factory signatures updated
- app.ts passes db to both route factories
- skill-registry-adapter-install.test.ts: 9 tests covering install/uninstall/rollback/assignGroup/removeGroup
- hermes-dual-source.test.ts: 7 tests covering syncHermesNativeSkills idempotency and listAgentSkills object shape
- Fix skill-registry-install.test.ts: update uninstall() callers to pass agentSkillsDir (new required param)
- Fix removeGroup() bug: removed incorrect 'individualSkills' guard that prevented file removal for group-installed skills
(rule 1 auto-fix: group-installed skills were never removed because they appeared in agentSkills with no way to distinguish from direct installs)
- All 16 new tests pass, all existing tests still pass
- Static ADAPTER_SKILL_CONFIGS array with all 10 adapter types
- CONFIG_BY_TYPE Map for O(1) lookup by adapter type string
- FALLBACK_CONFIG for unknown types (supportsInstall: false, never throws)
- resolveAdapterSkillConfig returns correct config for all known adapters
- listAdapterSkillConfigs returns full readonly config array
- All 15 unit tests pass, no regressions in full test suite
- Add AdapterSkillFormat type and AdapterSkillConfig interface to types.ts
- Create stub adapter-skill-config.ts (throws not implemented)
- Re-export new types and functions from index.ts
- Add comprehensive test file covering all 10 adapter types and fallback
- Create StarRating component with interactive/readonly modes, amber stars, size sm/md
- Add PersonalRating type and taskCount/avgCostUsd/lastUsedAt to SkillListItem
- Add getRatings and addRating to skillRegistryApi
- Add Rating System section to DesignGuide with all variants
- Fix SkillCard fixture and DesignGuide examples to include new SkillListItem fields
- Add POST/GET /skill-registry/skills/:sourceId/:slug/ratings routes
- Import skillRatingService in skill-registry routes
- Add upsertCommunityRatingsStub() in fetcher, called after each skill upsert
- Import communityRatings from schema in fetcher
- Update list() and getById() in skill-registry.ts to LEFT JOIN communityRatings
- Include averageRating, ratingCount, taskCount, avgCostUsd, lastUsedAt in SkillListItem
- Add agentSkills usage aggregation via LEFT JOIN + SUM/AVG/MAX
- Add fire-and-forget recordUsageForAgent call in heartbeat after finalizeAgentStatus
- Dynamic import keeps skill-registry-ratings off critical startup path
- All 44 skill-registry tests pass, full server suite (536) green
- Built-in variant: Badge secondary, no dismiss, hover:bg-accent/30
- Custom variant: Badge outline, X dismiss button with spinner, hover:bg-accent/50
- Tooltip on both variants showing name · built-in · N skills or name · N skills
- text-sm font-semibold typography per UI-SPEC (no font-bold or font-medium)
- Create ui/src/api/skillGroups.ts with skillGroupsApi object
- All 14 methods covering group CRUD, members, export/import, agent assignments
- removeGroup uses raw fetch for DELETE-with-body (api.delete has no body support)
- Add skillGroups namespace to ui/src/lib/queryKeys.ts with 6 key factories
- Create server/src/routes/skill-registry-groups.ts with skillGroupRoutes() factory
- All 14 REST routes for group CRUD, members, export/import, and agent assignments
- Import route registered before :groupId param to avoid route collision
- assertBoard on every handler, error classification (400/404/409/500)
- Mount skillGroupRoutes() in app.ts after skillRegistryRoutes()
- Add pendingSkillGroups fire-and-forget reconciliation in index.ts startup