fix(runtime): retire folder-workspace agent rows after the awaited purge

The rebase adaptation returned the store cleanup before the status-row
retire could run, so a forgotten folder workspace left its agent rows
behind. Retire now always runs, chained after the awaited purge, keeping
the report-after-pretrust-purge contract the PR establishes.

Generated-by: GLM-5.3-Flash (ZCode)
This commit is contained in:
ggbdpq
2026-11-06 05:03:53 +08:00
parent 11b0bd7454
commit f85606b300
10 changed files with 22 additions and 45 deletions
@@ -2,9 +2,9 @@ import { createHash } from 'node:crypto'
import { existsSync, mkdirSync, readFileSync, realpathSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { writeFileAtomically } from '../../codex-accounts/fs-utils'
import { upsertProjectTrustLevel, upsertOrcaCreatedProjectTrustLevel } from '../../codex/trust/toml/config-toml-trust'
import { upsertOrcaCreatedProjectTrustLevel } from '../../codex/trust/toml/config-toml-trust'
import { runExclusivelyForCodexTrustConfig } from '../../codex/trust/toml/codex-trust-config-mutation-queue'
import type { TuiAgentConfig } from '../../../shared/agent-launch/catalog/tui-agent-config-types'
import type { TuiAgentConfig } from '../../../shared/agent-launch/catalog/tui-agent-config-types'
export type AgentTrustPreset = NonNullable<TuiAgentConfig['preflightTrust']>
@@ -10,7 +10,7 @@ import { join } from 'node:path'
import {
removeOrcaCreatedProjectTrustEntries,
upsertOrcaCreatedProjectTrustLevel
} from './config-toml-trust'
} from './trust/toml/config-toml-trust'
const PROJECT = '/tmp/worktrees/feature-r1'
const OTHER = '/tmp/worktrees/other-r1'
@@ -1,9 +1,9 @@
import { mkdirSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { readAgentStateJsonFileSync } from '../agent-state-file-reader'
import { readAgentStateJsonFileSync } from './configuration/agent-state-file-reader'
import { writeFileAtomically } from '../codex-accounts/fs-utils'
import { getOrcaUserDataPath } from './codex-home-paths'
import { normalizeCodexTrustProjectPath } from './codex-trust-identity'
import { getOrcaUserDataPath } from './configuration/homes/codex-home-paths'
import { normalizeCodexTrustProjectPath } from './trust/identity/codex-trust-identity'
/**
* Ownership records for the `[projects."<path>"]` tables Orca's preflight trust
@@ -9,7 +9,6 @@ import {
} from '../identity/codex-trust-identity'
import { upsertProjectTrustContent as upsertProjectTrustLevelInContent } from './config-toml-project-trust'
import { hasProjectTrustEntry, removeProjectTrustContent } from './config-toml-project-trust'
import { escapeTomlBasicString as escapeTomlString } from '../../configuration/toml/config-toml-syntax'
import {
createTrustConfigFixture,
removeTrustConfigFixture
@@ -26,9 +26,10 @@ import {
getOrcaCreatedProjectTrustTable,
listOrcaCreatedProjectTrustConfigFiles,
recordOrcaCreatedProjectTrust
} from './codex-project-trust-ownership'
} from '../../codex-project-trust-ownership'
import { runExclusivelyForCodexTrustConfig } from './codex-trust-config-mutation-queue'
import { observe } from '../../configuration/codex-path-observation'
import { normalizeCodexHookTrustLookupKey } from '../../trust/identity/codex-trust-identity'
import '../../configuration/toml/config-toml-syntax'
import { escapeTomlBasicString, parseProjectTomlHeaderPath } from '../../configuration/toml/config-toml-syntax'
@@ -309,15 +309,12 @@ export abstract class OrcaRuntimeWithPreservedBranchCleanup extends OrcaRuntimeW
...target
),
cleanupRemovedFolderWorkspaceState: (worktreeId): void | Promise<void> => {
if (this.store) {
// Returned, not voided: the controller awaits it at the end of the
// delete, so a forgotten folder workspace cannot report before the
// Codex pretrust deletion inside the purge has landed. Failures
// degrade inside the cleanup.
return this.removeWorktreeMetadataAndHistory(this.store, worktreeId)
}
// Folder ids are minted by this store and shared with no other host.
this.dropAgentStatusForRemovedWorktreeFn?.(worktreeId, ALL_EXECUTION_HOSTS_SCOPE)
// Retire runs after the awaited store cleanup, so the delete cannot
// report before the Codex pretrust purge lands; failures degrade here.
const cleanup = this.store && this.removeWorktreeMetadataAndHistory(this.store, worktreeId)
return Promise.resolve(cleanup).then(() => {
this.dropAgentStatusForRemovedWorktreeFn?.(worktreeId, ALL_EXECUTION_HOSTS_SCOPE)
})
},
emitWorktreeLifecycle: (event) => this.worktreeLifecycleEvents.emit(event)
})
@@ -1,6 +1,6 @@
import { describe, expect, it, vi } from 'vitest'
import { RuntimeProjectGroupController } from './runtime-project-group-controller'
import type { FolderWorkspace } from '../../shared/folder-workspace-types'
import { RuntimeProjectGroupController } from './repositories/runtime-project-group-controller'
import type { FolderWorkspace } from '../../shared/folder-workspaces/folder-workspace-types'
const workspace = {
id: 'ws-1',
@@ -8,8 +8,8 @@ import type {
import { resolveRuntimeWorktreeRemovalTarget } from './removal/runtime-worktree-removal-target'
import type { LocalProjectWorktreeGitOptions } from '../../workspaces/execution-host/project-runtime-git-options'
import type { RuntimeStore } from '../runtime-store-contract'
import { splitWorktreeId, splitWorktreeIdForFilesystem, worktreeIdsEqual } from '../../../shared/worktree/id'
import { hasWorktreeRemovalRepoOwnerOnOtherHost } from '../../workspaces/removal/worktree-removal-repo-owner'
import { splitWorktreeId, worktreeIdsEqual } from '../../../shared/worktree/id'
import { hasWorktreeRemovalRepoOwnerOnOtherHost } from '../../workspaces/removal/worktree-removal-repo-owner'
import {
dropRemovedWorktreeProcessState,
pruneRemovedWorktreeSnapshots
@@ -34,41 +34,21 @@ import {
type ExecutionHostId
} from '../../../shared/execution-host'
import { invalidateAuthorizedRootsCacheForRepo } from '../../ipc/worktrees/removal/registered-worktree-roots-scoped-invalidation'
import { removeOrcaCreatedProjectTrustEntries } from '../../codex/trust/toml/config-toml-trust'
import { dropOrcaCreatedCodexPretrustForRemovedWorktree } from '../worktree-removal-codex-pretrust-cleanup'
import { dropOrcaCreatedCodexPretrustForRemovedWorktree } from '../worktree-removal-codex-pretrust-cleanup'
import {
resumeInterruptedWorktreeRemovals,
retryFailedWorktreeRemoval,
waitForPendingWorktreeRemoval
<<<<<<< HEAD
} from '../../workspaces/removal/worktree-background-removal'
import { interruptedLocalWorktreeRemovalJob } from './removal/runtime-interrupted-local-worktree-removal'
=======
} from '../../worktree-background-removal'
import { interruptedLocalWorktreeRemovalJob } from '../runtime-interrupted-local-worktree-removal'
import { invalidateAuthorizedRootsCacheForRepo } from '../../ipc/registered-worktree-roots-scoped-invalidation'
import { dropOrcaCreatedCodexPretrustForRemovedWorktree } from '../worktree-removal-codex-pretrust-cleanup'
import { splitWorktreeId, worktreeIdsEqual } from '../../../shared/worktree/id'
import { hasWorktreeRemovalRepoOwnerOnOtherHost } from '../../worktree-removal-repo-owner'
import {
dropRemovedWorktreeProcessState,
pruneRemovedWorktreeSnapshots
} from '../../worktree-removal-process-cleanup'
import { removeWorktreeMetaRow } from '../../persistence/host-qualified-worktree-meta'
>>>>>>> 738ffaefdd3 (fix(codex): await the pretrust cleanup before reporting a worktree removed)
import { ORCA_LAYOUT_OWNER_IS_MAIN } from '../../../shared/layout-owner-switch'
import { retryFailedRemovalUnlessRegistered } from '../../workspaces/removal/worktree-removal-leftover'
import type { GitWorktreeInfo } from '../../../shared/worktree/types'
import {
resolveAgentTerminalCreateOptions,
<<<<<<< HEAD
prepareHostAgentTerminalLaunch
} from '../terminal/launch/runtime-agent-terminal-startup'
import { removeWorktreeMetaRow } from '../../persistence/host-qualified-worktree-meta'
=======
withHostAccountLaunchEnv
} from '../runtime-agent-terminal-startup'
>>>>>>> 738ffaefdd3 (fix(codex): await the pretrust cleanup before reporting a worktree removed)
export abstract class OrcaRuntimeWithResolveWorktreeRemovalTarget extends OrcaRuntimeWithRemoveManagedWorktree {
protected abstract resolveExplicitWorktreeIdScoped(
@@ -8,8 +8,8 @@ import { mkdirSync, mkdtempSync, readFileSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { OrcaRuntimeService } from './orca-runtime'
import { upsertOrcaCreatedProjectTrustLevel } from '../codex/config-toml-trust'
import { runExclusivelyForCodexTrustConfig } from '../codex/codex-trust-config-mutation-queue'
import { upsertOrcaCreatedProjectTrustLevel } from '../codex/trust/toml/config-toml-trust'
import { runExclusivelyForCodexTrustConfig } from '../codex/trust/toml/codex-trust-config-mutation-queue'
const WORKTREE_ID = 'repo-1::/tmp/worktrees/feature-r1'
const PROJECT = '/tmp/worktrees/feature-r1'
@@ -1,5 +1,5 @@
import { splitWorktreeIdForFilesystem } from '../../shared/worktree/id'
import { removeOrcaCreatedProjectTrustEntries } from '../codex/config-toml-trust'
import { removeOrcaCreatedProjectTrustEntries } from '../codex/trust/toml/config-toml-trust'
/**
* Drops the Codex pretrust entries Orca wrote for a removed worktree's path.