Skip to content

feat(agent-projects): project-scoped Agent Mode — Agent Home PR2#2604

Draft
Emt-lin wants to merge 3 commits into
v4-previewfrom
feat/agent-home-pr2
Draft

feat(agent-projects): project-scoped Agent Mode — Agent Home PR2#2604
Emt-lin wants to merge 3 commits into
v4-previewfrom
feat/agent-home-pr2

Conversation

@Emt-lin

@Emt-lin Emt-lin commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Project-scoped Agent Mode (PR2a/PR2b): sessions, landing, and chat history are now scoped per project, with GLOBAL_SCOPE as the implicit global workspace; entering a project gets its own landing, header, and composer flow.
  • Project instructions & context pipeline: project.md stays the single source of truth with a marker-gated AGENTS.md mirror; the first prompt inlines a <project_context> block with absolute paths; context materialization is single-flight per project with retry/edit refresh for empty landings.
  • Project landing spine: new AgentLandingStack (hero + composer + shelf), project landing tabs (Project Chats / Context) aligned with the global landing, standalone zero-chat context card, and a collapsible project header above the tab strip.
  • Unified todo lists: one backend-agnostic todo pipeline across claude/codex/opencode feeding the project info popover, with per-session todo-id tracking and plan-clear symmetry.
  • Recent chats UX: running spinner on backgrounded rows, live done-dot handoff with dual-id row matching, MRU-sorted project list, and memo-stable row callbacks (rename/cancel/save scoped to the editing row).
  • Composer status: project-context loading moved off the floating card onto a composer status icon with queue-and-hold sends while context materializes.
  • Fix: clear the in-flight loading flag when the composer remounts on the landing→conversation flip — previously the Thinking spinner / stop button stuck forever after every session's first message and follow-up sends were parked in the queue (regression test included).
  • Context cache via the vault adapter: the project-context materializer now writes its .context-cache/ snapshots through Obsidian's vault adapter (and resolves add-dir roots via FileSystemAdapter.getFullPath) instead of node:fs/node:path, removing the import/no-nodejs-modules lint exception. Cache location/format and the paths the agent sees (absolute folder/note paths, .context-cache pointers, additionalDirectories) are unchanged; existing caches stay valid.
  • Content-conversion preview: the capped preview now makes its cut-off explicit and actionable.

Test plan

  • npx jest src/agentMode — 86 suites / 1152 tests pass
  • New regression test: first-message turn resolving after composer remount still clears draft.loading
  • eslint + prettier --check clean on changed files
  • Context cache refactor: src/context + src/agentMode + src/search green; src/context production code has zero Node builtins
  • Manual: send first message from global landing and a project landing — Thinking spinner and stop button clear when the turn ends
  • Manual: project create/enter/exit round-trip keeps the global shelf tab and MRU order
  • Manual: todo popover reflects backend todo updates across claude/codex/opencode

@gitguardian

gitguardian Bot commented Jun 12, 2026

Copy link
Copy Markdown

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
While these secrets were previously flagged, we no longer have a reference to the
specific commits where they were detected. Once a secret has been leaked into a git
repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@Emt-lin Emt-lin force-pushed the feat/agent-home-pr2 branch from 3d2233b to 4f67c7f Compare June 13, 2026 06:05
Emt-lin added 3 commits June 13, 2026 14:22
Turn Agent Mode "projects" into Claude Projects-style workspaces: entering
a project gives a scoped workspace with its own sessions, chat history, and
materialized context, while the global workspace becomes one special scope
(GLOBAL_SCOPE sentinel) sharing the same code path.

Session scope
- AgentSessionManager keys sessions by an immutable projectId with per-scope
  MRU, resolveSessionCwd, getSessionsForScope, and enterProject/exitProject;
  the active-session invariant (active.projectId === activeProjectId) keeps
  existing UI helpers untouched.
- Backend restarts / in-place replacement inherit the replaced session's
  projectId; project scope reuses the warm process instead of adopting the
  vault-root probe session.

Context materialization
- New projectContextMaterializer + contextCacheStore + manifestBuilder
  capture a project's context once per session, single-flight per project,
  written to a project-local cache.
- The first prompt inlines a <project_context> block with absolute paths;
  the composer shows a context status icon and queues sends while context
  is still materializing, refreshing an empty landing after Retry/Edit.

Instructions mirror
- project.md stays the single source of truth, with a marker-gated AGENTS.md
  mirror generated by ensureAgentsMirror; a built-in policy is layered into
  every project's instructions and template-variable hints are dropped.

Landing & project UI
- AgentLandingStack spine with project landing state, project header, Welcome
  card, Project Chats tab variant, and project CRUD (anchored create popover,
  edit modal, overflow menu); shelf lists cap at 5 behind a View-all popover.

History scope
- Agent chat history is scope-keyed (a scope switch can't flash or stick the
  previous scope's chats); native session history is scoped to projects and
  resumed transcripts hydrate from the session's scope cwd. Legacy chats with
  no projectId resolve to GLOBAL_SCOPE.

Todo / plan
- Unified backend todo lists across claude/codex/opencode feed the project
  info popover, with per-session todo-id tracking and symmetric plan clear;
  parse claude's real TaskCreate result and steer agents to plan todos.

Project list UX
- MRU-sorted project list (touched on enter), running spinner on backgrounded
  recent-chat rows, live done-dot handoff with dual-id row matching, the
  global shelf tab kept selected across project round-trips, inline row
  actions, and memo-stable rename/cancel/save handlers.

Fixes
- Clear the in-flight loading flag when the composer remounts on the
  landing->conversation flip (first message no longer sticks the Thinking
  spinner / stop button), and cap content-conversion preview render so large
  snapshots don't freeze the modal.

Tests
- 27 new suites covering session scope, context materializer, cache store,
  AGENTS.md mirror, todo-plan pipeline, landing UI, and the new hooks.
… actionable

When the content-conversion preview is truncated, mark the cut at the end of the
rendered slice with a labelled divider and a "Copy full content" pill button, so
it reads as truncated (not the natural end) and the full text is one click away
without scrolling back to the header — the GitHub "Load diff" / Carbon overflow
pattern. Share the copy-with-feedback handler between the header button and the
marker button (it always copies the full content, never the truncated preview),
and fire the icon-reset timer on the button's own window for popout safety.
…ter, not node:fs

Replace the node:fs/node:path implementation of the project-context cache
layer with Obsidian's vault adapter, so src/context holds no Node builtins
and the eslint import/no-nodejs-modules exception for these files is removed.

- contextCacheFs: createNodeContextCacheFs (node:fs) -> createVaultContextCacheFs(app),
  backed by vault.adapter. mkdirRecursive creates ancestors segment-by-segment;
  list returns entry basenames (the adapter returns full vault-relative paths);
  remove swallows missing-file errors to stay idempotent.
- contextCacheStore: drop node:path, join cache paths with a local POSIX helper.
- projectContextMaterializer: drop node:path; derive the vault-relative cache dir
  from the project record; resolve add-dir absolute paths via
  FileSystemAdapter.getFullPath (instanceof-guarded); in-cwd check via
  forward-slash prefix compare.
- Delete the import/no-nodejs-modules exception block in eslint.config.mjs.

Cache location/filenames/content and the paths the agent sees (absolute
folder/note paths, .context-cache pointers, additionalDirectories) are
unchanged; existing caches stay valid. Adds contextCacheFs unit tests and
extends the obsidian mock with getFullPath/list/remove.
@Emt-lin Emt-lin force-pushed the feat/agent-home-pr2 branch from 4f67c7f to 2f099f3 Compare June 13, 2026 15:26
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