Skip to content

Comments

feat: project sessions, notes, and per-repo branch timelines#244

Draft
matt2e wants to merge 26 commits intomainfrom
project-ai
Draft

feat: project sessions, notes, and per-repo branch timelines#244
matt2e wants to merge 26 commits intomainfrom
project-ai

Conversation

@matt2e
Copy link
Contributor

@matt2e matt2e commented Feb 24, 2026

Summary

  • Adds project sessions with an MCP server exposing start_repo_session and add_project_repo tools, enabling AI agents to coordinate work across multiple repos in a project
  • Adds project notes (always produced by project sessions) and per-repo branch timelines so session progress is visible in the UI
  • Fixes a ref-update race condition when adding repos to projects: removes the redundant fetch inside create_worktree_at_path (superseded by fetch_for_worktree) and swallows git CAS race errors (incorrect old value provided) that were incorrectly treated as fatal

Test plan

  • Create a project, add a repo, verify worktree setup succeeds even when concurrent fetches are in flight
  • Start a project session and verify it produces a note and shows progress in the branch card timeline
  • Verify add_project_repo MCP tool correctly rejects monorepo adds without a subpath
  • Verify project session prompt textarea auto-resizes

🤖 Generated with Claude Code

matt2e and others added 26 commits February 24, 2026 15:21
- Add ProjectNote model with project-scoped notes for cross-cutting context
- Add project_notes table to SQLite schema with cascade delete
- Add reason column to project_repos for tracking why repos are attached
- Add start_project_session command for project-level sessions
- Add create_project_note, list_project_notes, delete_project_note commands
- Build project session context with repo listing, existing notes, and
  chronological branch timeline summaries grouped by repository
- Inject project notes into branch-level timeline context
- Add project note extraction to session_runner post-completion hooks
- Add ProjectNote and ProjectSessionResponse types to frontend
- Add project session UI with prompt input, notes display, and deletion
- Bump schema version (wipe-and-recreate on mismatch)
… section

- Remove createNote parameter from startProjectSession, always pass true
  so every project session generates a note
- Remove session running state from prompt input — the textarea is always
  available, allowing multiple concurrent project sessions
- Track active sessions in a Set<string> instead of a single ID
- Reload notes immediately after starting a session so the stub appears
  as a 'Generating note…' card with a spinner in the notes section
- Support multiple concurrent generating notes via filter instead of find
- Remove unused Loader2 import, .running CSS state, and spin animation
… add_project_repo tools

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
These files were written locally but never committed before the rebase
moved the directory from staged/ to apps/mark/, leaving the pub mod
declarations in lib.rs dangling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix project sessions appearing completed immediately by saving the
  initial note stub with empty title/content (matching branch note
  behavior) so the generating state is correctly detected
- MCP add_project_repo now blocks until worktree is set up, detect_actions
  has run, and all prerun setup actions have completed
- Emit project-repo-added Tauri event from MCP handler so ProjectHome
  reactively reloads when a repo is added via MCP without manual refresh
- Remove debug log statements from project_mcp.rs, session_commands.rs,
  session_runner.rs, ProjectSection.svelte, and acp-client/driver.rs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- start_repo_session: add `return_info` param so parent session can
  specify what the child should return; child prompt is suffixed with
  the instruction; last assistant message is returned as `output` in
  the result JSON
- add_project_repo: emit `project-repo-added` Tauri event at each
  stage (repo created, worktree ready, prerun actions done) so the UI
  updates progressively without requiring a manual reload

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ards

When a project session adds a repo via MCP with a reason, save it to the
DB and display it as the first item in the branch card timeline — styled
with an info (blue) color theme and an Info icon. Hovering reveals an X
button on the right to dismiss it, which clears the reason from the DB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Before creating the repo, run the monorepo check. If the score is >= 20
and no subpath was provided, return an error telling the agent it must
re-call the tool with a subpath pointing to the specific service or
package root (e.g. "packages/api"). Also expose `subpath` as an explicit
MCP parameter so agents can supply it directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…+subpath

Add subpath parameter to StartRepoSessionParams and update the repo lookup
to match on both github_repo and subpath exactly, so multiple copies of the
same repo with different subpaths are disambiguated correctly. Calls now fail
immediately with a clear error listing available repo+subpath combos if no
match is found. Also sets the working directory to include the subpath.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d unread tracking

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the implicit return-only behaviour with an explicit
`expected_outcome` field (`return_output_only`, `note_in_repo`,
`commit`). When `note_in_repo` or `commit` is requested the agent
receives the same action-prefix prompt used by branch sessions, a Note
or Commit stub is created in the DB (linked via session_id so the
branch card timeline picks it up automatically), and commit sessions
capture the pre-HEAD SHA so the post-completion hook can resolve the
new SHA. Expand the log line to include all params including the full
instructions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…h cards live

When start_repo_session creates a note/commit artifact, it now emits a
session-status-changed event with status "running" and branch_id,
project_id, session_type fields. BranchCard listens for running events
matching its branch and calls loadTimeline() immediately, so the pending
stub appears without a reload. App.svelte registers the session in
sessionRegistry and projectStateStore so the project spinner activates
and cleanup on completion works correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
start_repo_session now builds the same <branch-history> and project
information context that user-triggered branch sessions receive.
Looks up the worktree path for local branches (falling back to the
clone path) and calls the now pub(crate) build_branch_context /
build_remote_branch_context helpers from session_commands. The prompt
structure matches build_full_prompt: <action> block with action
instructions + project info, <branch-history> block, then user
instructions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the blanket `git fetch origin` in `ensure_local_clone` with a
new `fetch_for_worktree` helper that fetches only `base_branch` and
`branch_name`. The full fetch updated every remote-tracking ref via
compare-and-swap, which caused spurious "incorrect old value provided"
failures (and a needless HTTPS retry) when another worktree or process
had already updated some refs in the shared clone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tart_repo_session call

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
base_branch is stored in the DB with an "origin/" prefix but git fetch
expects the bare ref name. Without stripping, fetch ran:
  git fetch origin origin/main
which failed with "couldn't find remote ref origin/main".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…o on completion

- Clarify note_in_repo and commit expected_outcome descriptions with usage guidance
- Explain that existing notes are accessible by name in the instructions field
- Add guidance on reason field for add_project_repo (describe repo, not todos)
- Return created note info in the same format as session-start notes when a note_in_repo session completes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ponse

The note is now returned separately in the `note` field, so the raw
agent output no longer needs to include the content after the `---`
separator.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…essions

Ensures project sessions always have a real working directory by creating
the project-scoped worktree root (~/.staged/workspaces/local/projects/<id>/)
at project creation time, and falling back to it instead of /tmp when the
project has no repos attached yet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…f-race errors

fetch_for_worktree already fetches the base branch with SSH→HTTPS fallback
before create_worktree_at_path is called, so the second best-effort fetch
inside create_worktree_at_path was redundant and could cause duplicate
ref-update races.

Also swallow "incorrect old value provided" errors in fetch_for_worktree:
this is a CAS race where a concurrent fetch already updated the tracking ref,
leaving it at least as up-to-date as needed, so the error is non-fatal.

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>
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