Skip to content

feat(chat): projects + Move-to-project (Phase 4)#273

Merged
blove merged 16 commits into
mainfrom
claude/chat-projects-impl
May 13, 2026
Merged

feat(chat): projects + Move-to-project (Phase 4)#273
blove merged 16 commits into
mainfrom
claude/chat-projects-impl

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented May 12, 2026

Summary

Phase 4 introduces Projects as a first-class navigation surface in @ngaf/chat. The sidenav gains a Projects section between the primary slot and Recent threads. Projects can be created (inline), renamed (inline), and deleted (with confirmation). Threads can be associated with a project at creation time AND moved between projects via a per-row submenu. Selecting a project filters the visible threads.

Spec: docs/superpowers/specs/2026-05-12-chat-projects-design.md
Plan: docs/superpowers/plans/2026-05-12-chat-projects.md

New primitives

  • ChatProjectListComponent — sibling of chat-thread-list. Inline "+ New project" → inline-create input. Hover-revealed kebab → Rename / Delete (destructive). Reuses existing chat-overflow-menu + chat-confirm-dialog primitives. Optimistic rename + delete with rollback.

Extended

  • Thread.projectId?: string | null — optional association field.
  • ThreadActionAdapter.moveToProject?(threadId, projectId | null) => Promise<void>. Optimistic-hide pattern on the current view.
  • ChatThreadListComponent — new projects input. New moveMenuOpenForId signal + moveMenuItems computed. Active-mode menu gains "Move to project" entry (between unpin and archive). Second <chat-overflow-menu> instance renders the move submenu (anchored to the same kebab) with items [No project, ...projects]. The submenu reuses the existing primitive.
  • ChatSidenavComponent — three new inputs (projects, selectedProjectId, projectActions); two new outputs (projectSelected, newProjectRequested). Renders the Projects section between primary slot and Recent block. Forwards projects to both inner chat-thread-list instances.

Public API additions

  • ChatProjectListComponent
  • Project type
  • ProjectActionAdapter type

Example wiring (examples-chat-angular)

  • ProjectsService (new) — localStorage-backed. LangGraph has no native projects API; consumers with real backends bring their own adapter.
  • ThreadsServicetoThread reads metadata.projectId; create accepts optional projectId; new moveToProject method PATCHes thread metadata.
  • demo-shellselectedProjectId signal (persisted), visibleThreads computed filters by project, projectActions adapter, threadActions.moveToProject, project handlers.

Test plan

  • nx run chat:test — 583/583 pass (existing + 10 chat-project-list + 5 thread-list move-to-project + 4 sidenav projects = 19 new tests)
  • nx run chat:build — clean
  • nx lint chat — clean
  • nx run examples-chat-angular:build — clean
  • API docs regenerated
  • Browser-verified via Chrome MCP:
    • Projects section renders with "+ New project" affordance
    • Click + New project → inline input, focused; Enter creates row; project auto-selected (highlighted)
    • Threads filter by selected project (new chat created while Personal selected → appears in filtered Recent)
    • Thread kebab menu in active mode: Rename / Pin / Move to project / Archive / Delete (correct order; Pin from Phase 3d coexists cleanly)
    • Click "Move to project" → main menu closes, submenu opens with No project + Personal
    • Click "No project" → thread vanishes from Personal filter (moved to no-project)
    • Delete project via kebab → destructive confirm dialog → confirm → project gone, selection cleared, threads return (filter inactive)
    • Reload persists projects (localStorage) and selection (PalettePersistence)

Out of scope (deferred follow-ups)

  • Per-project instructions / system prompt
  • Per-project attached files
  • Project sharing / membership / roles
  • Project icon / color customization

🤖 Generated with Claude Code

@vercel
Copy link
Copy Markdown

vercel Bot commented May 12, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cacheplane Ready Ready Preview, Comment May 13, 2026 0:20am

Request Review

blove and others added 16 commits May 12, 2026 17:15
Full Projects scope: Project type + ProjectActionAdapter; new
chat-project-list primitive; chat-sidenav Projects section with
"+ New project"; thread-project association via Thread.projectId?;
"Move to project" thread row action via a second overflow-menu
submenu. Example wires localStorage-backed ProjectsService.
Defers per-project instructions / files / sharing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
14 tasks across type extensions, new chat-project-list primitive
(styles + component + spec), chat-thread-list move-to-project
submenu, chat-sidenav Projects section, ProjectsService
(localStorage), ThreadsService projectId mapping, demo-shell
wiring, API docs regen, and manual browser verification.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pin (Phase 3d, PR #267) landed first. Updates Task 6's chat-thread-list
patches so "Move to project" inserts alongside existing pin/unpin
entries instead of replacing them. Tasks 1, 7, 8, 10-13 remain valid.

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

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@blove blove force-pushed the claude/chat-projects-impl branch from 464550f to 6d2254c Compare May 13, 2026 00:17
@blove blove merged commit 335be83 into main May 13, 2026
14 checks passed
blove added a commit that referenced this pull request May 13, 2026
Three changes bundled per follow-up review notes:

1. examples/chat/smoke/CHECKLIST.md — adds 'Projects' and 'Move thread
   to project' sections covering PR #273 (Phase 4) end-to-end: inline
   create / rename / delete, filter behaviour, submenu wiring, idempotent
   moves, persistence across reload.

2. examples/chat/python/src/streaming/envelope_tool.py — Pydantic
   model_validator on A2uiEnvelope rejects envelopes with zero or
   multiple discriminators set. Catches LLM outputs that pass strict-
   mode validation but emit ambiguous shapes; two new tests cover the
   rejected cases.

3. examples/chat/angular/src/app/shell/threads.service.ts — fallback
   for threads without metadata.title changes from 'Thread 019e1e98...'
   (raw id slice) to a graceful 'Untitled'. Backend writes the title
   on the first user message; threads created via '+ New chat' and
   abandoned previously appeared with their raw id prefix in the
   sidenav.
blove added a commit that referenced this pull request May 13, 2026
Three changes bundled per follow-up review notes:

1. examples/chat/smoke/CHECKLIST.md — adds 'Projects' and 'Move thread
   to project' sections covering PR #273 (Phase 4) end-to-end: inline
   create / rename / delete, filter behaviour, submenu wiring, idempotent
   moves, persistence across reload.

2. examples/chat/python/src/streaming/envelope_tool.py — Pydantic
   model_validator on A2uiEnvelope rejects envelopes with zero or
   multiple discriminators set. Catches LLM outputs that pass strict-
   mode validation but emit ambiguous shapes; two new tests cover the
   rejected cases.

3. examples/chat/angular/src/app/shell/threads.service.ts — fallback
   for threads without metadata.title changes from 'Thread 019e1e98...'
   (raw id slice) to a graceful 'Untitled'. Backend writes the title
   on the first user message; threads created via '+ New chat' and
   abandoned previously appeared with their raw id prefix in the
   sidenav.
blove added a commit that referenced this pull request May 13, 2026
…278)

Three changes bundled per follow-up review notes:

1. examples/chat/smoke/CHECKLIST.md — adds 'Projects' and 'Move thread
   to project' sections covering PR #273 (Phase 4) end-to-end: inline
   create / rename / delete, filter behaviour, submenu wiring, idempotent
   moves, persistence across reload.

2. examples/chat/python/src/streaming/envelope_tool.py — Pydantic
   model_validator on A2uiEnvelope rejects envelopes with zero or
   multiple discriminators set. Catches LLM outputs that pass strict-
   mode validation but emit ambiguous shapes; two new tests cover the
   rejected cases.

3. examples/chat/angular/src/app/shell/threads.service.ts — fallback
   for threads without metadata.title changes from 'Thread 019e1e98...'
   (raw id slice) to a graceful 'Untitled'. Backend writes the title
   on the first user message; threads created via '+ New chat' and
   abandoned previously appeared with their raw id prefix in the
   sidenav.
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.

1 participant