移除退役策划 V2 运行态刷新入口
Project CI / Repository checks (pull_request) Failing after 2m22s
Project CI / Frontend tests (pull_request) Failing after 3m7s
Project CI / Native shell tests (pull_request) Failing after 3m47s
Project CI / Backend tests (pull_request) Successful in 6m38s

删除旧版策划状态随项目总控运行态刷新的专用 effect

移除仅服务该 effect 的 planningLane 判定模块
This commit is contained in:
2026-09-14 06:30:07 +00:00
parent 9fc28790a4
commit 7eb2326a76
2 changed files with 0 additions and 95 deletions
-34
View File
@@ -229,7 +229,6 @@ import {
parseRememberInput,
} from './features/project-workspace/memoryCommands';
import { pendingCommandDetail } from './features/project-workspace/pendingCommandPresentation';
import { planningStateNeedsRuntimeRefresh } from './features/project-workspace/planningLane';
import {
type PlanningApprovalCommandResultV2,
planningMessagesToChatMessages,
@@ -1202,39 +1201,6 @@ export function App({
void hydratePlanGddState(targetProjectPath);
}, [hydratePlanGddState, localProject?.projectPath]);
useEffect(() => {
// 存在性判据故意走 `status`(必选字段,为 `undefined` 当且仅当 runtime 为 null)而不是整个
// 对象:依赖里只挖 phase/status/updatedAt 三个标量,是为了只在监工状态真的动了时
// 重灌。把 `projectSupervisorRuntime` 本体写进依赖会让每一轮轮询新建的对象身份都触发一次
// hydrate,白烧 IPC。
if (
!localProject?.projectPath ||
projectSupervisorRuntime?.status === undefined
) {
return;
}
// 后端 hydrate 会抢项目写锁并扫 authority,不是纯内存读。没有这道门,做游戏和做
// 素材链路的每一拍监工心跳都会去抢一次项目写锁——而那两条链路根本不产生策划状态。
// 策划状态读 ref 而不进依赖:hydrate 成功就会换一个 `planGddState` 对象身份,写进
// 依赖等于 hydrate 触发 hydrate。
if (
!planningStateNeedsRuntimeRefresh(
projectSupervisorRuntime?.source,
planGddStateRef.current,
)
) {
return;
}
void hydratePlanGddState(localProject.projectPath);
}, [
hydratePlanGddState,
localProject?.projectPath,
projectSupervisorRuntime?.phase,
projectSupervisorRuntime?.source,
projectSupervisorRuntime?.status,
projectSupervisorRuntime?.updatedAt,
]);
useEffect(() => {
const hydrateOnResume = () => {
if (document.visibilityState === 'hidden' || !localProject?.projectPath) {
@@ -1,61 +0,0 @@
import { PROJECT_SUPERVISOR_PLAN_SOURCE } from '../../app/constants';
import type { AgentRuntimeState, PlanGddStateViewV1 } from '../../app/types';
/**
* 当前总控 run 是否属于立项策划链路。
*
* 判据是 run 的 `source`,不是 `planGddState`:做游戏链路在策划批准之后照样带着
* 一份 approved 的策划状态,但它的总控 run 是 autonomous 源,必须继续拿完整面板。
*/
export function isPlanningLaneRuntime(
runtime: AgentRuntimeState | null | undefined,
) {
return isPlanningLaneSource(runtime?.source);
}
/**
* 同一个判据的标量入口。
*
* `App.tsx` 里那条按监工状态重灌策划状态的 effect,依赖里只放 phase/status/updatedAt
* 这类标量——轮询每拍都会新建 runtime 对象,把本体写进依赖会让每一拍都重跑。要在那
* 条 effect 里用上链路判据,就只能拿 `source` 这一个标量进去。
*/
export function isPlanningLaneSource(source: string | null | undefined) {
return source === PROJECT_SUPERVISOR_PLAN_SOURCE;
}
/** 策划状态里还会继续变的那几个态。`approved` / `rejected` 是终态。 */
const PLAN_GDD_LIVE_STATES: ReadonlySet<PlanGddStateViewV1['state']> = new Set([
'draft',
'ready_for_approval',
'revision_requested',
]);
/**
* 监工状态每次变动时,要不要重新 hydrate 策划状态。
*
* hydrate 不是纯内存读:后端会抢项目写锁、扫 authority、必要时修投影。把它挂在
* 「任意 run 的任意一次更新」上,等于让做游戏和做素材链路的每一拍心跳都去抢一次
* 项目写锁。
*
* 但也不能简单地只看 `isPlanningLaneRuntime`:审批卡的可见性判据是
* `displayGdd && (pendingApproval || recoveryPending)`,跟当前 run 的 source 无关,
* 而非策划分支的监工面板还要靠 `planGddState.pendingApproval` 点亮等待审批位。所以
* 策划状态自身还没落定时,即便当前 run 不是策划链路也必须继续跟。
*/
export function planningStateNeedsRuntimeRefresh(
runtimeSource: string | null | undefined,
planGddState: PlanGddStateViewV1 | null | undefined,
) {
if (isPlanningLaneSource(runtimeSource)) {
return true;
}
if (!planGddState) {
return false;
}
return Boolean(
planGddState.pendingApproval ||
planGddState.recoveryPending ||
PLAN_GDD_LIVE_STATES.has(planGddState.state),
);
}