Skip to content

fix(channels): reuse local folders, stop git-init prompt on scratch tasks#2793

Open
raquelmsmith wants to merge 5 commits into
mainfrom
posthog-code/channel-local-folder-reuse
Open

fix(channels): reuse local folders, stop git-init prompt on scratch tasks#2793
raquelmsmith wants to merge 5 commits into
mainfrom
posthog-code/channel-local-folder-reuse

Conversation

@raquelmsmith

Copy link
Copy Markdown
Member

What & why

Follow-up to #2735 (generic chat box with lazy repo attach). Fixes two local-mode regressions reported in channel tasks.

1. Reuse local folders instead of cloning from remote

When the agent decided it needed a repo, the channel system prompt sent it straight to list_reposclone_repo, i.e. cloning from remote GitHub even though the user already has the repo checked out locally.

AgentService now fetches the user's previously-used local folders (FoldersService.getFolders) for channel sessions and embeds them in the channel system prompt. Guidance is reordered to:

  1. Reuse a folder already on disk (cd into it).
  2. If unsure / none match → ask the user (via AskUserQuestion) which folder, or for a local path.
  3. Only as a last resort, clone from remote — after confirming with the user.

2. No more spurious "Initialize Git Repository?" dialog

Opening a repo-less channel task popped the native "This folder is not a git repository / initialize?" dialog. Root cause: the synthetic scratch workspace had folderId: "" (falsy), so navigationTaskBinder.ensureWorkspaceForTask's guard missed and it registered the empty scratch dir as a folder (→ FoldersService.addFolder → git-init dialog), plus wrote a bogus workspace row.

Scratch workspaces are now marked with isScratch and short-circuited in the task binder, so they are never registered or git-init'd. The dialog now only fires when a real folder is selected for a coding task.

Changes

  • packages/shared/src/workspace-domain.tsisScratch? on workspaceSchema
  • packages/workspace-server/.../workspace/workspace.tsbuildScratchWorkspace sets isScratch: true
  • packages/ui/.../navigation/taskBinderImpl.ts — short-circuit scratch workspaces
  • packages/workspace-server/.../agent/agent.ts — inject FOLDERS_SERVICE, fetch known local folders in channel mode, embed in the channel prompt

Testing

  • @posthog/workspace-server unit tests (516) pass; added isScratch assertions + foldersService mock
  • ✅ Typecheck clean for touched packages (shared, core, agent, workspace-server); pre-existing unrelated @posthog/ui errors in WebsiteLayout.tsx / InteractiveFileDiff.tsx exist on the base branch
  • ⏳ In-app E2E recommended: channel → analysis prompt (no git dialog, no folder registered) → coding prompt (agent lists local folders / asks before cloning)

Created with PostHog Code

Add a 2x4 grid of starter-prompt cards below the input on the
project-bluebird channels new-task screen. Each card mirrors the
SuggestedTaskCard look (icon badge + title + description); clicking one
fills the composer with a multi-line template that ends in a "User
input:" block of fill-in lines.

- New CHANNEL_TASK_SUGGESTIONS data + SuggestedPromptCard component
- TaskInput renders the channel suggestions OR SuggestedTasksPanel
  (never both), so the codebase-discovery/SDK-health cards don't show
  on channels
- Raise the input block when suggestions are present so the longer list
  isn't squished; extra gap above the suggestions
- Fill via setPendingContent so template line breaks survive
- Fix: clear the editor draft before onTaskCreated navigates, so a
  submitted prompt doesn't persist into the next new task

Generated-By: PostHog Code
Task-Id: 56abea18-4f33-45cb-ae43-55182b861d46
editor.clear() only ran inside the onTaskReady callback; for repo-less
channel tasks the callback can navigate/unmount the editor before the
persisted draft is wiped, so a submitted prompt reappeared on the next
new task. Clear drafts[sessionId] directly in the guaranteed
result.success block, which always runs and survives the unmount.

Generated-By: PostHog Code
Task-Id: 56abea18-4f33-45cb-ae43-55182b861d46
"Fix a bug" and "Build a new feature" start in plan mode; the analysis
suggestions start in auto mode. Selecting a card applies its mode via
setConfigOption (guarded by isValidConfigValue, mirroring initialMode).

Generated-By: PostHog Code
Task-Id: 56abea18-4f33-45cb-ae43-55182b861d46
The input was raised to 38% whenever suggestions were provided, but the
cards only render while the editor is empty — so once the user typed,
the cards vanished yet the input stayed raised. Gate the position on the
same editorIsEmpty condition so it recenters to 50% as the user types.

Generated-By: PostHog Code
Task-Id: 56abea18-4f33-45cb-ae43-55182b861d46
…asks

Follow-up to #2735 (generic chat box with lazy repo attach). Two local-mode
regressions:

1. The channel system prompt sent the agent straight to list_repos/clone_repo,
   cloning from remote even when the user already has the repo checked out
   locally. AgentService now fetches the user's previously-used local folders
   and embeds them in the channel prompt, with guidance to reuse a local match
   (or ask the user for a path) first and only clone from remote as a last
   resort, after confirming.

2. Opening a repo-less channel task popped the native "initialize git?" dialog:
   the synthetic scratch workspace has folderId "" (falsy), so the navigation
   task binder's guard missed and it registered the empty scratch dir as a
   folder. Mark scratch workspaces with isScratch and short-circuit so they are
   never registered or git-init'd. The dialog now only fires when a real folder
   is selected for a coding task.

Generated-By: PostHog Code
Task-Id: d7d5491e-f66a-4848-9620-98006834f3d6
@github-actions

github-actions Bot commented Jun 20, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit 03be99a.

@raquelmsmith raquelmsmith marked this pull request as ready for review June 20, 2026 00:08
@greptile-apps

greptile-apps Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/workspace-server/src/services/agent/agent.test.ts:179-181
**`localFoldersBlock` branch never exercised in tests**

The mock always resolves to `[]`, so the conditional path in `buildSystemPrompt` that generates the local-folder list (`localFolders.length > 0`) is never reached. The codebase prefers parameterised tests — a case with one or more mock `RegisteredFolder` entries (covering `exists: true`, `exists: false`, and the `remoteUrl` being null/non-null) would verify that the folder list text is correctly assembled and injected, and that folders with `exists: false` are filtered out as intended.

Reviews (1): Last reviewed commit: "fix(channels): reuse local folders, stop..." | Re-trigger Greptile

Comment on lines +179 to +181
foldersService: {
getFolders: vi.fn().mockResolvedValue([]),
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 localFoldersBlock branch never exercised in tests

The mock always resolves to [], so the conditional path in buildSystemPrompt that generates the local-folder list (localFolders.length > 0) is never reached. The codebase prefers parameterised tests — a case with one or more mock RegisteredFolder entries (covering exists: true, exists: false, and the remoteUrl being null/non-null) would verify that the folder list text is correctly assembled and injected, and that folders with exists: false are filtered out as intended.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/workspace-server/src/services/agent/agent.test.ts
Line: 179-181

Comment:
**`localFoldersBlock` branch never exercised in tests**

The mock always resolves to `[]`, so the conditional path in `buildSystemPrompt` that generates the local-folder list (`localFolders.length > 0`) is never reached. The codebase prefers parameterised tests — a case with one or more mock `RegisteredFolder` entries (covering `exists: true`, `exists: false`, and the `remoteUrl` being null/non-null) would verify that the folder list text is correctly assembled and injected, and that folders with `exists: false` are filtered out as intended.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@raquelmsmith raquelmsmith requested a review from charlesvien June 20, 2026 00:41
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