feat(wsl-mover): refuse edits to a project a WSL move is taking (D1b-5c-2) (#28761)

* feat(wsl-mover): refuse edits to a project a WSL move is taking, and drop its background bookkeeping quietly (D1b-5c-2)

* fix(wsl-mover): hide only local rows of a moved project; the host's own row keeps its id (D1b-5c-2)

* fix(wsl-mover): refuse a user's unread toggle, fence branch deletes, host setups and issue commands; settings unfreeze once the host owns a repo (D1b-5c-2)

* test(wsl-mover): the fence e2e refuses edits to moving projects and drops their bookkeeping quietly (D1b-5c-2)

* refactor(wsl-mover): name the update type the fence inspects (D1b-5c-2)

* test(wsl-mover): run the fence tests that open a real store in the Node runtime (D1b-5c-2)

* fix(wsl-mover): a host setup's own repo stays frozen once the host owns it; e2e pins the quiet drop (D1b-5c-2)
This commit is contained in:
Neil
2026-10-14 12:13:28 -07:00
committed by GitHub
parent 872012f42c
commit b0308f24ef
33 changed files with 1139 additions and 31 deletions
@@ -34,6 +34,11 @@ import {
countRepoWorkspacesWithMetadata,
describeProjectRemovalRefusal
} from './project-removal-impact'
import {
assertWslMoveHostSetupIdWritable,
assertWslMoveHostSetupWritable,
assertWslMoveReposWritable
} from '../persistence/moving-wsl-projects/wsl-move-scope-guard'
type RuntimeProjectHostSetupDependencies = {
getStore: () => RuntimeStore | null
@@ -73,6 +78,8 @@ export class RuntimeProjectHostSetupController {
if (!store?.updateProject) {
throw new Error('runtime_unavailable')
}
const existing = store.getProjects?.().find((entry) => entry.id === projectId)
assertWslMoveReposWritable(store, existing?.sourceRepoIds ?? [])
const project = store.updateProject(projectId, updates)
if (!project) {
throw new Error(`Project not found: ${projectId}`)
@@ -91,6 +98,7 @@ export class RuntimeProjectHostSetupController {
if (!store?.createProjectHostSetup) {
throw new Error('runtime_unavailable')
}
assertWslMoveHostSetupWritable(store, args)
const result = store.createProjectHostSetup(args)
if (!result) {
throw new Error(`Project not found: ${args.projectId}`)
@@ -139,6 +147,7 @@ export class RuntimeProjectHostSetupController {
if (!store?.updateProjectHostSetup) {
throw new Error('runtime_unavailable')
}
assertWslMoveHostSetupIdWritable(store, args.setupId)
const result = store.updateProjectHostSetup(args)
if (!result) {
throw new Error(`Project host setup not found: ${args.setupId}`)
@@ -160,6 +169,7 @@ export class RuntimeProjectHostSetupController {
if (!store?.deleteProjectHostSetup) {
throw new Error('runtime_unavailable')
}
assertWslMoveHostSetupIdWritable(store, args.setupId)
if (args.force === false) {
this.assertSetupRemovalIsUnused(store, args.setupId)
}
@@ -238,6 +248,11 @@ export class RuntimeProjectHostSetupController {
if (!store) {
throw new Error('runtime_unavailable')
}
assertWslMoveHostSetupWritable(store, {
projectId: args.projectId,
hostId: getRepoExecutionHostId(initialRepo),
repoId: initialRepo.id
})
let repo = initialRepo
let setup = getProjectHostSetupForRepo(this.listSetups(), repo)
if (setup.projectId !== args.projectId) {