refactor: 收口缺失创作状态回退

This commit is contained in:
2026-06-04 02:12:52 +08:00
parent e6e0f93102
commit 5ba5ca6bf8
6 changed files with 350 additions and 80 deletions

View File

@@ -20,6 +20,7 @@
- 背景:平台入口在受保护数据失效后会清空当前用户私有作品、草稿、运行态和生成状态,但哪些 `SelectionStage` 可保留、哪些必须回首页曾以内联长否定串散在 `PlatformEntryFlowShellImpl.tsx` - 背景:平台入口在受保护数据失效后会清空当前用户私有作品、草稿、运行态和生成状态,但哪些 `SelectionStage` 可保留、哪些必须回首页曾以内联长否定串散在 `PlatformEntryFlowShellImpl.tsx`
- 决策:新增 `src/components/platform-entry/platformSelectionStageModel.ts`,以 `resolveSelectionStageAfterProtectedDataLoss(stage)` 收口受保护数据失效后的 stage 去留判定。模型内部使用 `satisfies Record<SelectionStage, boolean>` 全量分类,新增 stage 时必须明确保留或回首页。壳层仍负责检测权限变化、清 state 和调用 `setSelectionStage` - 决策:新增 `src/components/platform-entry/platformSelectionStageModel.ts`,以 `resolveSelectionStageAfterProtectedDataLoss(stage)` 收口受保护数据失效后的 stage 去留判定。模型内部使用 `satisfies Record<SelectionStage, boolean>` 全量分类,新增 stage 时必须明确保留或回首页。壳层仍负责检测权限变化、清 state 和调用 `setSelectionStage`
- 追加决策:缺失草稿 / 作品 / run 时的阶段回退也归入 `platformSelectionStageModel.ts`,由 `resolveSelectionStageAfterMissingCreationState(params)` 统一判断 big-fish、match3d、square-hole、visual-novel 和 baby-object-match 的 result / runtime / gallery-detail 是否还能被当前状态支撑。壳层只汇总布尔事实并按输出 stage 跳转big-fish、match3d、square-hole 的草稿事实固定来自 `Boolean(session?.draft)`visual-novel 的 session draft 与 work draft 可独立支撑结果页baby-object-match runtime 缺 draft 时直接回首页。
- 影响范围:退出登录、鉴权上下文收回、平台入口公开页 / 工作台 / 结果页 / 生成页 / 运行态的阶段恢复规则,以及后续新增 `SelectionStage` - 影响范围:退出登录、鉴权上下文收回、平台入口公开页 / 工作台 / 结果页 / 生成页 / 运行态的阶段恢复规则,以及后续新增 `SelectionStage`
- 验证方式:`npm run test -- src/components/platform-entry/platformSelectionStageModel.test.ts`、针对新 Module 与壳层执行 ESLint、`npm run typecheck``npm run check:encoding` - 验证方式:`npm run test -- src/components/platform-entry/platformSelectionStageModel.test.ts`、针对新 Module 与壳层执行 ESLint、`npm run typecheck``npm run check:encoding`
- 关联文档:`docs/technical/【前端架构】PlatformSelectionStageModel收口计划-2026-06-04.md` - 关联文档:`docs/technical/【前端架构】PlatformSelectionStageModel收口计划-2026-06-04.md`

View File

@@ -53,7 +53,7 @@ AI 文字游戏模板接入以 [AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_
平台入口错误 / 完成弹窗的文案归一、来源格式、候选择一、dismiss key 与任务完成文案收口到 `src/components/platform-entry/platformDialogStateModel.ts`,规则见 [【前端架构】PlatformDialogStateModel收口计划-2026-06-03.md](./technical/【前端架构】PlatformDialogStateModel收口计划-2026-06-03.md)。 平台入口错误 / 完成弹窗的文案归一、来源格式、候选择一、dismiss key 与任务完成文案收口到 `src/components/platform-entry/platformDialogStateModel.ts`,规则见 [【前端架构】PlatformDialogStateModel收口计划-2026-06-03.md](./technical/【前端架构】PlatformDialogStateModel收口计划-2026-06-03.md)。
平台入口受保护数据失效后的 stage 去留判定收口到 `src/components/platform-entry/platformSelectionStageModel.ts`,壳层只执行缓存清空和必要跳转,规则见 [【前端架构】PlatformSelectionStageModel收口计划-2026-06-04.md](./technical/【前端架构】PlatformSelectionStageModel收口计划-2026-06-04.md)。 平台入口受保护数据失效后的 stage 去留判定,以及缺失草稿 / 作品 / run 时的阶段回退,收口到 `src/components/platform-entry/platformSelectionStageModel.ts`,壳层只执行缓存清空、布尔事实汇总和必要跳转,规则见 [【前端架构】PlatformSelectionStageModel收口计划-2026-06-04.md](./technical/【前端架构】PlatformSelectionStageModel收口计划-2026-06-04.md)。
小游戏 runtime client 的路径编码、JSON 请求、runtime guest auth 与 retry 选项收口到 `src/services/runtimeRequest.ts`Match3D、SquareHole、Big Fish、Bark Battle、Puzzle 公开 / 推荐运行态请求、Jump Hop / Wooden Fish 正式 run 请求和 Visual Novel 局部 JSON runtime 请求已先迁移,规则见 [【前端架构】RuntimeClientFamily收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91RuntimeClientFamily%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。 小游戏 runtime client 的路径编码、JSON 请求、runtime guest auth 与 retry 选项收口到 `src/services/runtimeRequest.ts`Match3D、SquareHole、Big Fish、Bark Battle、Puzzle 公开 / 推荐运行态请求、Jump Hop / Wooden Fish 正式 run 请求和 Visual Novel 局部 JSON runtime 请求已先迁移,规则见 [【前端架构】RuntimeClientFamily收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91RuntimeClientFamily%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。

View File

@@ -4,20 +4,24 @@
`PlatformEntryFlowShellImpl.tsx` 在受保护数据失效后会清空当前用户的私有作品、运行态、草稿 notice 和生成状态。清理完成后,壳层还要判断当前 `SelectionStage` 是否还能继续展示:公开首页、公开详情、工作台入口等阶段可保留;结果页、生成页、运行态、个人反馈等依赖私有数据或运行态快照的阶段必须回到首页。 `PlatformEntryFlowShellImpl.tsx` 在受保护数据失效后会清空当前用户的私有作品、运行态、草稿 notice 和生成状态。清理完成后,壳层还要判断当前 `SelectionStage` 是否还能继续展示:公开首页、公开详情、工作台入口等阶段可保留;结果页、生成页、运行态、个人反馈等依赖私有数据或运行态快照的阶段必须回到首页。
前该规则以内联长否定串维护在壳层 **Implementation** 内。新增玩法 stage 或调整登录态行为时,维护者必须在巨型壳层中查找白名单,缺少独立测试面 外,平台壳还曾在多个 `useEffect` 中分别判断 big-fish、match3d、square-hole、visual-novel、baby-object-match 缺少草稿、作品或 run 时应回工作台、结果页还是首页。这类“当前 stage 已不能被现有状态支撑”的规则同样属于 stage 纯判定,不应散在壳层
此前这些规则以内联长否定串或多段相似 effect 维护在壳层 **Implementation** 内。新增玩法 stage 或调整登录态行为时,维护者必须在巨型壳层中查找白名单和状态缺失回退,缺少独立测试面。
## 决策 ## 决策
新增 `src/components/platform-entry/platformSelectionStageModel.ts` 作为 Platform Selection Stage **Module**。其公开 **Interface** 为: 新增 `src/components/platform-entry/platformSelectionStageModel.ts` 作为 Platform Selection Stage **Module**。其公开 **Interface** 为:
- `resolveSelectionStageAfterProtectedDataLoss(stage)`:输入当前 `SelectionStage`,输出受保护数据失效后应停留的 stage可保留则原样返回否则返回 `platform` - `resolveSelectionStageAfterProtectedDataLoss(stage)`:输入当前 `SelectionStage`,输出受保护数据失效后应停留的 stage可保留则原样返回否则返回 `platform`
- `resolveSelectionStageAfterMissingCreationState(params)`:输入当前 `SelectionStage` 与各玩法“是否有 session / draft / run / work / formPayload”等可渲染事实输出状态缺失后应停留的 stage仍可展示则原样返回。
`PlatformEntryFlowShellImpl.tsx` 仍作为副作用 **Adapter**:负责检测受保护数据从可读变为不可读、清空各玩法缓存、重置生成和错误状态,并只在模型输出与当前 stage 不一致时调用 `setSelectionStage(nextStage)` `PlatformEntryFlowShellImpl.tsx` 仍作为副作用 **Adapter**:负责检测受保护数据从可读变为不可读、清空各玩法缓存、重置生成和错误状态,或把当前 React state 汇总为布尔事实,并只在模型输出与当前 stage 不一致时调用 `setSelectionStage(nextStage)`
## 约定 ## 约定
- 新增 `SelectionStage` 时,必须判断它在退出登录或鉴权上下文收回后是否仍可展示,并在本 **Module** 的全量 `Record<SelectionStage, boolean>` 与测试中列明。 - 新增 `SelectionStage` 时,必须判断它在退出登录或鉴权上下文收回后是否仍可展示,并在本 **Module** 的全量 `Record<SelectionStage, boolean>` 与测试中列明。
- 公开列表、公开详情和创作工作台入口可保留;依赖当前用户私有数据、生成 session、运行态 run 或个人资料的 stage 默认回 `platform` - 公开列表、公开详情和创作工作台入口可保留;依赖当前用户私有数据、生成 session、运行态 run 或个人资料的 stage 默认回 `platform`
- 缺失状态回退只读取壳层传入的布尔事实,不直接读取玩法 session / work / run 对象。big-fish、match3d、square-hole 的草稿事实必须来自 `Boolean(session?.draft)`visual-novel 的 session draft 与 work draft 可独立支撑结果页baby-object-match runtime 缺 draft 时不看 formPayload直接回 `platform`
-**Module** 不清理 state、不调用路由、不触发登录弹窗只表达纯 stage 决策。 -**Module** 不清理 state、不调用路由、不触发登录弹窗只表达纯 stage 决策。
## 验收 ## 验收

View File

@@ -540,7 +540,10 @@ import {
buildPuzzleResultProfileId, buildPuzzleResultProfileId,
buildPuzzleResultWorkId, buildPuzzleResultWorkId,
} from './platformPuzzleIdentityModel'; } from './platformPuzzleIdentityModel';
import { resolveSelectionStageAfterProtectedDataLoss } from './platformSelectionStageModel'; import {
resolveSelectionStageAfterMissingCreationState,
resolveSelectionStageAfterProtectedDataLoss,
} from './platformSelectionStageModel';
import { PlatformTaskCompletionDialog } from './PlatformTaskCompletionDialog'; import { PlatformTaskCompletionDialog } from './PlatformTaskCompletionDialog';
import { PlatformWorkDetailView } from './PlatformWorkDetailView'; import { PlatformWorkDetailView } from './PlatformWorkDetailView';
import { usePlatformCreationAgentFlowController } from './usePlatformCreationAgentFlowController'; import { usePlatformCreationAgentFlowController } from './usePlatformCreationAgentFlowController';
@@ -8861,88 +8864,53 @@ export function PlatformEntryFlowShellImpl({
); );
useEffect(() => { useEffect(() => {
if (selectionStage === 'big-fish-result' && !bigFishSession?.draft) { const nextSelectionStage = resolveSelectionStageAfterMissingCreationState({
setSelectionStage( stage: selectionStage,
bigFishSession ? 'big-fish-agent-workspace' : 'platform', bigFish: {
); hasSession: Boolean(bigFishSession),
} hasSessionDraft: Boolean(bigFishSession?.draft),
if (selectionStage === 'big-fish-runtime' && !bigFishRun) { hasRun: Boolean(bigFishRun),
setSelectionStage(bigFishSession?.draft ? 'big-fish-result' : 'platform'); },
} match3d: {
}, [bigFishRun, bigFishSession, selectionStage, setSelectionStage]); hasSession: Boolean(match3dSession),
hasSessionDraft: Boolean(match3dSession?.draft),
hasRun: Boolean(match3dRun),
},
squareHole: {
hasSession: Boolean(squareHoleSession),
hasSessionDraft: Boolean(squareHoleSession?.draft),
hasRun: Boolean(squareHoleRun),
},
visualNovel: {
hasSession: Boolean(visualNovelSession),
hasSessionDraft: Boolean(visualNovelSession?.draft),
hasWork: Boolean(visualNovelWork),
hasWorkDraft: Boolean(visualNovelWork?.draft),
hasRun: Boolean(visualNovelRun),
},
babyObjectMatch: {
hasDraft: Boolean(babyObjectMatchDraft),
hasFormPayload: Boolean(babyObjectMatchFormPayload),
},
});
useEffect(() => { if (nextSelectionStage !== selectionStage) {
if (selectionStage === 'match3d-result' && !match3dSession?.draft) { setSelectionStage(nextSelectionStage);
setSelectionStage(
match3dSession ? 'match3d-agent-workspace' : 'platform',
);
}
if (selectionStage === 'match3d-runtime' && !match3dRun) {
setSelectionStage(match3dSession?.draft ? 'match3d-result' : 'platform');
}
}, [match3dRun, match3dSession, selectionStage, setSelectionStage]);
useEffect(() => {
if (selectionStage === 'square-hole-result' && !squareHoleSession?.draft) {
setSelectionStage(
squareHoleSession ? 'square-hole-agent-workspace' : 'platform',
);
}
if (selectionStage === 'square-hole-runtime' && !squareHoleRun) {
setSelectionStage(
squareHoleSession?.draft ? 'square-hole-result' : 'platform',
);
}
}, [selectionStage, setSelectionStage, squareHoleRun, squareHoleSession]);
useEffect(() => {
if (
selectionStage === 'visual-novel-result' &&
!visualNovelSession?.draft &&
!visualNovelWork?.draft
) {
setSelectionStage(
visualNovelSession ? 'visual-novel-agent-workspace' : 'platform',
);
}
if (selectionStage === 'visual-novel-runtime' && !visualNovelRun) {
setSelectionStage(
visualNovelSession?.draft || visualNovelWork?.draft
? 'visual-novel-result'
: 'platform',
);
}
if (selectionStage === 'visual-novel-gallery-detail' && !visualNovelWork) {
setSelectionStage('platform');
}
}, [
selectionStage,
setSelectionStage,
visualNovelRun,
visualNovelSession,
visualNovelWork,
]);
useEffect(() => {
if (
selectionStage === 'baby-object-match-result' &&
!babyObjectMatchDraft
) {
setSelectionStage(
babyObjectMatchFormPayload ? 'baby-object-match-workspace' : 'platform',
);
}
if (
selectionStage === 'baby-object-match-runtime' &&
!babyObjectMatchDraft
) {
setSelectionStage('platform');
} }
}, [ }, [
babyObjectMatchDraft, babyObjectMatchDraft,
babyObjectMatchFormPayload, babyObjectMatchFormPayload,
bigFishRun,
bigFishSession,
match3dRun,
match3dSession,
selectionStage, selectionStage,
setSelectionStage, setSelectionStage,
squareHoleRun,
squareHoleSession,
visualNovelRun,
visualNovelSession,
visualNovelWork,
]); ]);
const startBigFishRun = useCallback(async () => { const startBigFishRun = useCallback(async () => {

View File

@@ -1,7 +1,11 @@
import { describe, expect, test } from 'vitest'; import { describe, expect, test } from 'vitest';
import type { SelectionStage } from './platformEntryTypes'; import type { SelectionStage } from './platformEntryTypes';
import { resolveSelectionStageAfterProtectedDataLoss } from './platformSelectionStageModel'; import {
type MissingCreationStateParams,
resolveSelectionStageAfterMissingCreationState,
resolveSelectionStageAfterProtectedDataLoss,
} from './platformSelectionStageModel';
describe('platformSelectionStageModel', () => { describe('platformSelectionStageModel', () => {
test('keeps public and workspace stages after protected data loss', () => { test('keeps public and workspace stages after protected data loss', () => {
@@ -72,4 +76,203 @@ describe('platformSelectionStageModel', () => {
); );
}); });
}); });
test('resolves missing session draft result stages', () => {
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'big-fish-result',
bigFish: { hasSession: true, hasSessionDraft: false, hasRun: false },
}),
),
).toBe('big-fish-agent-workspace');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'big-fish-result',
bigFish: { hasSession: false, hasSessionDraft: false, hasRun: false },
}),
),
).toBe('platform');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'match3d-result',
match3d: { hasSession: true, hasSessionDraft: false, hasRun: false },
}),
),
).toBe('match3d-agent-workspace');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'square-hole-result',
squareHole: {
hasSession: true,
hasSessionDraft: false,
hasRun: false,
},
}),
),
).toBe('square-hole-agent-workspace');
}); });
test('resolves missing session run stages', () => {
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'big-fish-runtime',
bigFish: { hasSession: true, hasSessionDraft: true, hasRun: false },
}),
),
).toBe('big-fish-result');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'big-fish-runtime',
bigFish: { hasSession: true, hasSessionDraft: false, hasRun: false },
}),
),
).toBe('platform');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'match3d-runtime',
match3d: { hasSession: true, hasSessionDraft: true, hasRun: false },
}),
),
).toBe('match3d-result');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'square-hole-runtime',
squareHole: {
hasSession: true,
hasSessionDraft: true,
hasRun: false,
},
}),
),
).toBe('square-hole-result');
});
test('resolves visual novel and baby object missing state stages', () => {
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'visual-novel-result',
visualNovel: {
hasSession: true,
hasSessionDraft: false,
hasWork: false,
hasWorkDraft: false,
hasRun: false,
},
}),
),
).toBe('visual-novel-agent-workspace');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'visual-novel-runtime',
visualNovel: {
hasSession: true,
hasSessionDraft: false,
hasWork: true,
hasWorkDraft: true,
hasRun: false,
},
}),
),
).toBe('visual-novel-result');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'visual-novel-gallery-detail',
visualNovel: {
hasSession: false,
hasSessionDraft: false,
hasWork: false,
hasWorkDraft: false,
hasRun: false,
},
}),
),
).toBe('platform');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'baby-object-match-result',
babyObjectMatch: { hasDraft: false, hasFormPayload: true },
}),
),
).toBe('baby-object-match-workspace');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'baby-object-match-runtime',
babyObjectMatch: { hasDraft: false, hasFormPayload: true },
}),
),
).toBe('platform');
});
test('keeps stages when required creation state exists', () => {
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'big-fish-result',
bigFish: { hasSession: true, hasSessionDraft: true, hasRun: false },
}),
),
).toBe('big-fish-result');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'big-fish-runtime',
bigFish: { hasSession: true, hasSessionDraft: true, hasRun: true },
}),
),
).toBe('big-fish-runtime');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'visual-novel-gallery-detail',
visualNovel: {
hasSession: false,
hasSessionDraft: false,
hasWork: true,
hasWorkDraft: false,
hasRun: false,
},
}),
),
).toBe('visual-novel-gallery-detail');
expect(
resolveSelectionStageAfterMissingCreationState(
buildMissingCreationStateParams({
stage: 'platform',
}),
),
).toBe('platform');
});
});
function buildMissingCreationStateParams(
overrides: Partial<MissingCreationStateParams> = {},
): MissingCreationStateParams {
return {
stage: 'platform',
bigFish: { hasSession: false, hasSessionDraft: false, hasRun: false },
match3d: { hasSession: false, hasSessionDraft: false, hasRun: false },
squareHole: { hasSession: false, hasSessionDraft: false, hasRun: false },
visualNovel: {
hasSession: false,
hasSessionDraft: false,
hasWork: false,
hasWorkDraft: false,
hasRun: false,
},
babyObjectMatch: { hasDraft: false, hasFormPayload: false },
...overrides,
};
}

View File

@@ -57,3 +57,97 @@ export function resolveSelectionStageAfterProtectedDataLoss(
): SelectionStage { ): SelectionStage {
return PROTECTED_DATA_LOSS_STABLE_STAGE_BY_STAGE[stage] ? stage : 'platform'; return PROTECTED_DATA_LOSS_STABLE_STAGE_BY_STAGE[stage] ? stage : 'platform';
} }
type SessionDraftRunState = {
hasSession: boolean;
hasSessionDraft: boolean;
hasRun: boolean;
};
type VisualNovelCreationState = {
hasSession: boolean;
hasSessionDraft: boolean;
hasWork: boolean;
hasWorkDraft: boolean;
hasRun: boolean;
};
type BabyObjectMatchCreationState = {
hasDraft: boolean;
hasFormPayload: boolean;
};
export type MissingCreationStateParams = {
stage: SelectionStage;
bigFish: SessionDraftRunState;
match3d: SessionDraftRunState;
squareHole: SessionDraftRunState;
visualNovel: VisualNovelCreationState;
babyObjectMatch: BabyObjectMatchCreationState;
};
export function resolveSelectionStageAfterMissingCreationState(
params: MissingCreationStateParams,
): SelectionStage {
const { stage } = params;
if (stage === 'big-fish-result' && !params.bigFish.hasSessionDraft) {
return params.bigFish.hasSession ? 'big-fish-agent-workspace' : 'platform';
}
if (stage === 'big-fish-runtime' && !params.bigFish.hasRun) {
return params.bigFish.hasSessionDraft ? 'big-fish-result' : 'platform';
}
if (stage === 'match3d-result' && !params.match3d.hasSessionDraft) {
return params.match3d.hasSession ? 'match3d-agent-workspace' : 'platform';
}
if (stage === 'match3d-runtime' && !params.match3d.hasRun) {
return params.match3d.hasSessionDraft ? 'match3d-result' : 'platform';
}
if (stage === 'square-hole-result' && !params.squareHole.hasSessionDraft) {
return params.squareHole.hasSession
? 'square-hole-agent-workspace'
: 'platform';
}
if (stage === 'square-hole-runtime' && !params.squareHole.hasRun) {
return params.squareHole.hasSessionDraft
? 'square-hole-result'
: 'platform';
}
if (
stage === 'visual-novel-result' &&
!params.visualNovel.hasSessionDraft &&
!params.visualNovel.hasWorkDraft
) {
return params.visualNovel.hasSession
? 'visual-novel-agent-workspace'
: 'platform';
}
if (stage === 'visual-novel-runtime' && !params.visualNovel.hasRun) {
return params.visualNovel.hasSessionDraft || params.visualNovel.hasWorkDraft
? 'visual-novel-result'
: 'platform';
}
if (stage === 'visual-novel-gallery-detail' && !params.visualNovel.hasWork) {
return 'platform';
}
if (
stage === 'baby-object-match-result' &&
!params.babyObjectMatch.hasDraft
) {
return params.babyObjectMatch.hasFormPayload
? 'baby-object-match-workspace'
: 'platform';
}
if (
stage === 'baby-object-match-runtime' &&
!params.babyObjectMatch.hasDraft
) {
return 'platform';
}
return stage;
}