mirror of
https://github.com/stablyai/orca.git
synced 2026-10-16 16:03:26 +00:00
Preserve PR generation host ownership
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -284,3 +284,4 @@ Done means: reviewers and future agents can understand the vision, implementatio
|
||||
- [x] 2026-06-13: Extended Tasks source availability reasons so missing provider auth, unavailable source tooling, and unsupported providers can surface as distinct source-host states instead of generic connection/version failures. The checklist row remains partial until runtime/provider preflight feeds these reasons end to end. Verified with focused source-summary tests and targeted oxlint.
|
||||
- [x] 2026-06-13: Fed desktop-owned GitHub/GitLab preflight into Tasks source availability for local and SSH project sources, so missing `gh`/`glab` or missing CLI auth disables the affected provider with source-tool/auth-specific copy. Runtime-owned sources intentionally skip desktop preflight and continue to rely on runtime capability/fetch ownership. Verified with provider availability tests, Tasks source summary tests, TaskPage source-boundary tests, targeted oxlint, and full `pnpm run typecheck`.
|
||||
- [x] 2026-06-13: Electron-verified a local project with local GitHub credentials: added the local Orca worktree to the running dev app, confirmed `gh` auth for `Jinwoo-H`, fetched 10 GitHub work items through explicit `TaskSourceContext { provider: github, hostId: local }`, verified the local source-scoped cache key, and captured the rendered Tasks page showing GitHub issues for the local project.
|
||||
- [x] 2026-06-13: Snapshotted Source Control PR-generation runtime ownership and reused that owner for generation, cancellation, and post-generation git refresh, preventing async PR generation from following a later focused-host switch. Verified with focused Source Control host-boundary tests, targeted oxlint, and `git diff --check`.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
const SOURCE_CONTROL_SOURCE = readFileSync(join(__dirname, 'SourceControl.tsx'), 'utf8')
|
||||
|
||||
function sourceBetween(source: string, startPattern: string, endPattern: string): string {
|
||||
const start = source.indexOf(startPattern)
|
||||
expect(start).toBeGreaterThanOrEqual(0)
|
||||
const end = source.indexOf(endPattern, start + startPattern.length)
|
||||
expect(end).toBeGreaterThan(start)
|
||||
return source.slice(start, end)
|
||||
}
|
||||
|
||||
describe('SourceControl host-context boundaries', () => {
|
||||
it('snapshots PR generation host ownership and reuses it after async branch preparation', () => {
|
||||
const generateSection = sourceBetween(
|
||||
SOURCE_CONTROL_SOURCE,
|
||||
'const handleGeneratePullRequestFieldsForActive = useCallback(',
|
||||
'const handleCancelGeneratePullRequestFieldsForActive = useCallback('
|
||||
)
|
||||
expect(generateSection).toContain('runtimeTargetSettings: activeRepoSettings')
|
||||
expect(generateSection).toContain('settings: context.runtimeTargetSettings')
|
||||
|
||||
const cancelSection = sourceBetween(
|
||||
SOURCE_CONTROL_SOURCE,
|
||||
'const handleCancelGeneratePullRequestFieldsForActive = useCallback(',
|
||||
'const {'
|
||||
)
|
||||
expect(cancelSection).toContain('settings: record.context.runtimeTargetSettings')
|
||||
|
||||
const refreshSection = sourceBetween(
|
||||
SOURCE_CONTROL_SOURCE,
|
||||
'const refreshGitStatusAfterPullRequestGeneration = useCallback(',
|
||||
'useEffect(() => {'
|
||||
)
|
||||
expect(refreshSection).toContain('settings: context.runtimeTargetSettings')
|
||||
expect(refreshSection).not.toContain('settings: activeRepoSettings')
|
||||
})
|
||||
})
|
||||
@@ -969,8 +969,9 @@ function SourceControlInner(): React.JSX.Element {
|
||||
}
|
||||
try {
|
||||
await refreshGitStatusForWorktree({
|
||||
// Why: route git status by the repo OWNER host, not the focused runtime.
|
||||
settings: activeRepoSettings,
|
||||
// Why: generation can finish after the user switches hosts; refresh
|
||||
// the same host that owned the generation request.
|
||||
settings: context.runtimeTargetSettings,
|
||||
worktreeId: context.worktreeId,
|
||||
worktreePath: context.worktreePath,
|
||||
connectionId: context.connectionId,
|
||||
@@ -987,7 +988,6 @@ function SourceControlInner(): React.JSX.Element {
|
||||
}
|
||||
},
|
||||
[
|
||||
activeRepoSettings,
|
||||
fetchUpstreamStatus,
|
||||
isFolder,
|
||||
setGitStatus,
|
||||
@@ -1953,7 +1953,8 @@ function SourceControlInner(): React.JSX.Element {
|
||||
connectionId: getConnectionId(activeWorktreeId) ?? undefined,
|
||||
requestId,
|
||||
repoId: activeRepo.id,
|
||||
branch: branchName
|
||||
branch: branchName,
|
||||
runtimeTargetSettings: activeRepoSettings
|
||||
}
|
||||
const seed = { ...fields }
|
||||
// Why: SourceControl can unmount on tab switches; persisting the running
|
||||
@@ -1967,7 +1968,7 @@ function SourceControlInner(): React.JSX.Element {
|
||||
const result = await generateRuntimePullRequestFields(
|
||||
{
|
||||
// Why: route generation by the repo OWNER host, not the focused runtime.
|
||||
settings: activeRepoSettings,
|
||||
settings: context.runtimeTargetSettings,
|
||||
worktreeId: context.worktreeId,
|
||||
worktreePath: context.worktreePath,
|
||||
connectionId: context.connectionId
|
||||
@@ -2050,8 +2051,9 @@ function SourceControlInner(): React.JSX.Element {
|
||||
return resolvePullRequestGenerationCancel(current)
|
||||
})
|
||||
void cancelRuntimeGeneratePullRequestFields({
|
||||
// Why: route the cancel by the repo OWNER host, not the focused runtime.
|
||||
settings: activeRepoSettings,
|
||||
// Why: the user can switch hosts while generation runs; cancel the
|
||||
// original request owner instead of the current focused host.
|
||||
settings: record.context.runtimeTargetSettings,
|
||||
worktreeId: record.context.worktreeId,
|
||||
worktreePath: record.context.worktreePath,
|
||||
connectionId: record.context.connectionId
|
||||
@@ -2068,12 +2070,7 @@ function SourceControlInner(): React.JSX.Element {
|
||||
}
|
||||
})
|
||||
})
|
||||
}, [
|
||||
activeRepoSettings,
|
||||
activePullRequestGenerationKey,
|
||||
prGenerationRecords,
|
||||
updatePullRequestGenerationRecord
|
||||
])
|
||||
}, [activePullRequestGenerationKey, prGenerationRecords, updatePullRequestGenerationRecord])
|
||||
|
||||
const {
|
||||
aiGenerationEnabled: prAiGenerationEnabled,
|
||||
|
||||
Reference in New Issue
Block a user