Skip to content

fix: scope project-path guards to the requested project (shared roots)#181

Merged
khaliqgant merged 2 commits into
mainfrom
fix/list-personas-shared-root
Jun 9, 2026
Merged

fix: scope project-path guards to the requested project (shared roots)#181
khaliqgant merged 2 commits into
mainfrom
fix/list-personas-shared-root

Conversation

@khaliqgant

@khaliqgant khaliqgant commented Jun 9, 2026

Copy link
Copy Markdown
Member

Two related shared-root bugs where IPC handlers inferred the project from a path via global first-match (getProjectIdForPathfindProjectForPath) instead of using the project the user is actually in. When a directory is a registered root of more than one project, first-match picks the wrong one.

Bug 1 — broker:list-personas hard failure

Listing personas / spawning an agent threw Path is outside project roots for project <id>: <cwd> for a valid cwd whenever that directory was a root of multiple projects.

Field repro: /Users/.../AgentWorkforce/workforce is a root of three projects (Proactive Agents, Relay Core, Workforce). From the Workforce project it failed, because the guard resolved the path to the first-listed owner (Proactive Agents) and that id ≠ the requested id.

Fix: extract projectContainsPath(project, targetPath) in cli.ts; the handler looks up the passed projectId and tests the cwd against that project's roots. findProjectForPath now delegates to the helper (first-match behavior preserved for CLI/open flows).

Bug 2 — git:generate-commit-message wrong attribution

Same root cause, milder symptom: the handler used getProjectIdForPath(path), so under a shared root the commit draft was generated by the first-listed project's broker, not the one the user was working in (no error — just wrong context).

Fix: thread projectId from the renderer (DiffPane already has activeProjectId) through git-store → preload → IPC types → handler. The handler verifies projectContainsPath(project, path) and generates the draft with the passed id. Signature is generateCommitMessage(projectId, rootPath, input). The broad assertPathWithinProjects(path) boundary guard is kept.

broker:spawn-agent was audited and does not use this guard (it forwards projectId to brokerManager.spawnAgent and selects the session by id), so it is unaffected.

Tests

  • list-personas shared-root regression: two projects share /tmp/shared; list-personas('project-2', '/tmp/shared') checks projectContainsPath against project-2 and succeeds.
  • generate-commit-message shared-root attribution: uses the passed project-2, and rejects a path outside the passed project.
  • projectContainsPath unit tests: exact root, nested path, sibling-prefix non-match; existing first-match test kept.
  • cli.test.ts 14/14, ipc-handlers.test.ts 8/8, tsc --noEmit clean.

Note

Main-process change — requires a rebuild + restart of Pear to take effect.

🤖 Generated with Claude Code

@codeant-ai

codeant-ai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request refactors project path matching by extracting projectContainsPath and updates the broker:list-personas IPC handler to correctly handle multiple projects sharing the same root. It also optimizes terminal performance by coalescing multiple PTY chunks into a single write, and resolves a terminal focus issue by ensuring xterm is focused exactly once on the first mount of a new runtime. Feedback on the changes suggests addressing a potential bug in projectContainsPath where paths starting with double dots (e.g., ..foo) could be incorrectly flagged as being outside the root directory.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/main/cli.ts
Comment on lines +35 to +36
const pathFromRoot = relative(rootPath, resolved)
return pathFromRoot === '' || (!pathFromRoot.startsWith('..') && !isAbsolute(pathFromRoot))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The check `pathFromRoot.startsWith('..')` can incorrectly return `true` (indicating the path is outside the root) if a subdirectory or file name starts with `..` (for example, a folder named `..foo` inside the project root). To prevent this false positive, we should ensure that `..` is either the entire path segment or followed by a path separator (`/` or `\\``).

    const pathFromRoot = relative(rootPath, resolved)\n    const isOutside = pathFromRoot === '..' || pathFromRoot.startsWith('../') || pathFromRoot.startsWith('..\\\\')\n    return pathFromRoot === '' || (!isOutside && !isAbsolute(pathFromRoot))

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@khaliqgant, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 49 minutes and 26 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 96df309d-3271-4c16-88a2-3a486001390b

📥 Commits

Reviewing files that changed from the base of the PR and between 049cefc and d647e05.

📒 Files selected for processing (9)
  • src/main/__tests__/cli.test.ts
  • src/main/cli.ts
  • src/main/ipc-handlers.test.ts
  • src/main/ipc-handlers.ts
  • src/preload/index.ts
  • src/renderer/src/components/diff/DiffPane.tsx
  • src/renderer/src/lib/ipc-mock.ts
  • src/renderer/src/stores/git-store.ts
  • src/shared/types/ipc.ts
📝 Walkthrough

Walkthrough

This PR refactors path validation logic in the main process by extracting a projectContainsPath helper, updates the broker:list-personas IPC handler to use project-aware path validation, simplifies terminal focus behavior by eliminating delayed focus calls, and optimizes PTY chunk writing by coalescing multiple chunks into single writes.

Changes

Path Validation Refactor & Terminal Runtime Optimizations

Layer / File(s) Summary
Path containment helper and CLI refactoring
src/main/cli.ts, src/main/__tests__/cli.test.ts
New projectContainsPath(project, targetPath) helper resolves and validates whether a path is contained in a project's roots (exactly or nested). findProjectForPath is refactored to delegate its containment checks to this helper. Tests verify exact-root, nested-path, and prefix-sibling matching behavior.
IPC handler path validation with store lookup
src/main/ipc-handlers.ts, src/main/ipc-handlers.test.ts
The broker:list-personas handler now loads the project by id from the store and validates the resolved cwd is within that project's roots via projectContainsPath, throwing if the project is missing or path is outside. Handler tests rewritten to mock store and path containment behavior.
Terminal focus simplification on mount
src/renderer/src/hooks/use-terminal.ts, src/renderer/src/hooks/use-terminal.dom.test.ts
Terminal mount no longer schedules a focus "ladder" of delayed calls; focusTerminal(true) is called exactly once on initial mount. focusTimers state and cleanup loop removed. Regression test verifies focus fires exactly once on fresh runtime with fake timers.
PTY chunk coalescing into single writes
src/renderer/src/lib/terminal-runtime-registry.ts, src/renderer/src/lib/terminal-runtime-registry.dom.test.ts
PTY buffer processing coalesces batches of incoming chunks into a single combined string and performs one write (instead of per-chunk writes), while maintaining per-chunk typing-trace accounting. Test verifies multiple chunks are merged into single ordered write and subsequent flushes without new data do not create additional writes.
Stress test timeout adjustment
src/renderer/src/stores/agent-store.stress.test.ts
Timeout for the large scale simulation test increased from 25 seconds to 60 seconds to reduce CI flakiness.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • AgentWorkforce/pear#158: Both modify PTY chunk processing by coalescing multiple writes into fewer/single writes instead of per-chunk forwarding.
  • AgentWorkforce/pear#164: Both extend the broker:list-personas flow; this PR adds projectContainsPath for cwd validation, while #164 adds optional cwd parameter support to the overall listing flow.

Poem

🐰 Paths are tamed with one neat check,
Focus leaps without the deck of timers ticking,
Chunks now coalesce in flight—
One sweet write instead of many—
The terminal hops along, light and bright! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely summarizes the main fix: scoping project-path guards to the requested project rather than inferring from a path, addressing the shared-roots bug in list-personas.
Description check ✅ Passed The description is comprehensive and directly relates to the changeset, explaining the bugs, root causes, and fixes across both the cli.ts helper extraction and ipc-handlers.ts refactoring.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/list-personas-shared-root

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@codeant-ai

codeant-ai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

@khaliqgant khaliqgant changed the title fix(broker): scope list-personas path guard to the requested project fix: scope project-path guards to the requested project (shared roots) Jun 9, 2026
@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

khaliqgant and others added 2 commits June 9, 2026 10:32
broker:list-personas rejected a valid cwd whenever that directory was a
registered root of more than one project. The guard used
getProjectIdForPath() -> findProjectForPath(), which returns the FIRST
project (in store order) whose roots contain the path, then compared that
to the passed projectId. When a directory is shared as a root across
projects, every project except the first-listed one was wrongly rejected
with "Path is outside project roots".

Scope the check to the project actually requested: extract
projectContainsPath(project, targetPath) in cli.ts and have the handler
look up the passed projectId and test the cwd against that project's own
roots. findProjectForPath now delegates to the helper, preserving
first-match behavior for CLI/open flows.

Adds a regression test for the shared-root case and unit coverage for the
new helper. broker:spawn-agent does not use this guard and is unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
git:generate-commit-message inferred its project via getProjectIdForPath()
(global first-match), so when the working dir was a root shared across
projects the commit draft was generated by the first-listed project's
broker rather than the one the user was working in — wrong attribution
under shared roots.

Thread projectId from the renderer instead: DiffPane passes activeProjectId
through git-store -> preload -> IPC. The handler now looks up the passed
project, verifies projectContainsPath(project, path), and generates the
draft with that id. The broad assertPathWithinProjects(path) boundary guard
is kept.

Signature is generateCommitMessage(projectId, rootPath, input) to match the
IPC handler shape. Adds handler tests for shared-root attribution and for
rejecting a path outside the passed project.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@khaliqgant khaliqgant force-pushed the fix/list-personas-shared-root branch from 35d9e25 to d647e05 Compare June 9, 2026 08:32
@codeant-ai

codeant-ai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

@khaliqgant khaliqgant merged commit 4b20323 into main Jun 9, 2026
3 checks passed
@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@khaliqgant khaliqgant deleted the fix/list-personas-shared-root branch June 9, 2026 08:33
@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

⚠️ pr-reviewer did not push — the PR branch advanced during the review, so fixes were withheld to avoid overwriting newer commits. Re-trigger the review once the branch settles. The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

1 similar comment
@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #181 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

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