策划链路恢复列布局,澄清卡与输入框不再被静默裁出可视区
现象:立项策划提交需求后,界面永远停在「任务已接收」,澄清问答卡不出现。后端、
模式判定、链路判据、readOnly、数据传递全部正确,卡片也确实渲染了——314px 高、
visible、opacity 1,只是被画在裁剪线外面。实测窄条 top=858 而容器 bottom=788,
超出 384px;scrollHeight 1235 vs clientHeight 734,输入框和状态行也一起在外面。
根因是 #193(5802048c3「Codex/agent chat layout fix」)重写这块布局时:
- 给 .game-workbench-chat .project-supervisor-conversation 加了 display: block,
杀死它从基础规则继承的 display: grid,行模板 minmax(340px,1fr) auto auto auto
整个失效;
- 把消息列表从 flex: 1 1 auto 改成 height: 100%,于是它独吞整列高度;
- 删掉了 .game-workbench-chat .project-supervisor-composer 的 4 条规则,所以列表
上那条 padding-bottom: 196px(本意是给「浮起来的输入框」留位)从来没有对应的
定位规则,那个模型压根没成立过。
容器又是 overflow: hidden,所以排在列表后面的成员全部被无声裁掉。
只给策划链路恢复:`:has(.plan-gdd-surface)` 仅在策划面在场时命中,做游戏与做素材
保持 master 的 block 列原样不动。用 flex 列而不是 grid——子元素个数随「待确认命令」
的有无浮动,固定行模板会错位;而且既有的 .plan-gdd-surface { flex: 0 0 auto } 本来
就是照 flex 写的,容器变成 flex 之后它才第一次真正生效,此前一直是死声明。
另加 overflow-y: auto 兜底:审批卡展开到 52dvh 且窄条同时在场时理论上仍可能超出,
届时给滚动条而不是继承裁剪。这个 bug 的全部代价都来自「悄悄裁掉」。
顺带补一条 appSurface 用例,覆盖「首页做方案 → 自动建项目 → 自动投递 → 工作台出
澄清卡」这条此前零覆盖的路径。必须说明:它拦不住本次这类问题——jsdom 没有布局引擎,
高度恒为 0,裁剪与溢出对它天然不可见。它守的是数据流,不是版面。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1818,7 +1818,6 @@ textarea {
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
|
||||
.supervisor-chat-only-message-list .message--user {
|
||||
align-self: flex-end;
|
||||
border-color: #cfd6df;
|
||||
@@ -1923,7 +1922,6 @@ textarea {
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
|
||||
.local-game-preview-frame {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
@@ -1946,7 +1944,6 @@ textarea {
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.supervisor-chat-only-header {
|
||||
padding: 0 12px;
|
||||
@@ -1970,7 +1967,6 @@ textarea {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.project-supervisor-surface {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(220px, 280px);
|
||||
@@ -6082,9 +6078,7 @@ iframe.preview-frame {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.game-workbench-chat
|
||||
.supervisor-chat-only-runtime-controls
|
||||
.pending-command {
|
||||
.game-workbench-chat .supervisor-chat-only-runtime-controls .pending-command {
|
||||
gap: 12px;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--platform-surface-border);
|
||||
@@ -6149,7 +6143,9 @@ iframe.preview-frame {
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.agent-runtime-status .project-runtime-pending-command .pending-command-actions {
|
||||
.agent-runtime-status
|
||||
.project-runtime-pending-command
|
||||
.pending-command-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
@@ -6165,9 +6161,7 @@ iframe.preview-frame {
|
||||
color: var(--platform-button-primary-text);
|
||||
}
|
||||
|
||||
.game-workbench-chat
|
||||
.agent-runtime-status
|
||||
.project-runtime-pending-command {
|
||||
.game-workbench-chat .agent-runtime-status .project-runtime-pending-command {
|
||||
grid-template-columns: minmax(0, 1fr) 136px;
|
||||
}
|
||||
|
||||
@@ -6206,8 +6200,12 @@ iframe.preview-frame {
|
||||
background: var(--platform-warm-bg);
|
||||
}
|
||||
|
||||
.game-workbench-chat .project-supervisor-surface > .project-runtime-pending-command,
|
||||
.game-workbench-chat .project-supervisor-conversation .project-runtime-pending-command {
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface
|
||||
> .project-runtime-pending-command,
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation
|
||||
.project-runtime-pending-command {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 136px;
|
||||
align-items: center;
|
||||
@@ -6220,7 +6218,10 @@ iframe.preview-frame {
|
||||
background: var(--platform-warm-bg);
|
||||
}
|
||||
|
||||
.game-workbench-chat .project-supervisor-conversation .project-runtime-pending-command > span {
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation
|
||||
.project-runtime-pending-command
|
||||
> span {
|
||||
min-width: 0;
|
||||
margin: 0;
|
||||
overflow-wrap: anywhere;
|
||||
@@ -6229,7 +6230,11 @@ iframe.preview-frame {
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.game-workbench-chat .project-supervisor-conversation .project-runtime-pending-command > span small {
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation
|
||||
.project-runtime-pending-command
|
||||
> span
|
||||
small {
|
||||
display: block;
|
||||
margin-top: 4px;
|
||||
color: var(--platform-text-soft);
|
||||
@@ -6238,7 +6243,10 @@ iframe.preview-frame {
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.game-workbench-chat .project-supervisor-conversation .project-runtime-pending-command .pending-command-actions {
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation
|
||||
.project-runtime-pending-command
|
||||
.pending-command-actions {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 64px);
|
||||
gap: 8px;
|
||||
@@ -6246,7 +6254,11 @@ iframe.preview-frame {
|
||||
flex: 0 0 136px;
|
||||
}
|
||||
|
||||
.game-workbench-chat .project-supervisor-conversation .project-runtime-pending-command .pending-command-actions button {
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation
|
||||
.project-runtime-pending-command
|
||||
.pending-command-actions
|
||||
button {
|
||||
width: 64px;
|
||||
min-width: 64px;
|
||||
max-width: 64px;
|
||||
@@ -6261,7 +6273,11 @@ iframe.preview-frame {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.game-workbench-chat .project-supervisor-conversation .project-runtime-pending-command .pending-command-actions button:last-child {
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation
|
||||
.project-runtime-pending-command
|
||||
.pending-command-actions
|
||||
button:last-child {
|
||||
border-color: var(--platform-button-primary-border);
|
||||
background: var(--platform-button-primary-fill);
|
||||
color: var(--platform-button-primary-text);
|
||||
@@ -7210,7 +7226,6 @@ iframe.preview-frame {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
立项策划前端样式(PlanGddSurface / 阶段进度 / GDD 审批卡 / 交付行 /
|
||||
planning-lane-runtime-strip)。
|
||||
@@ -7223,7 +7238,7 @@ iframe.preview-frame {
|
||||
|
||||
/* 策划区是一个面:阶段进度是标题栏,审批卡是正文。边框和圆角只画在外壳上,里面两块
|
||||
不再各自带框。 */
|
||||
.plan-gdd-surface{
|
||||
.plan-gdd-surface {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
border: 1px solid #cfd7e6;
|
||||
@@ -7232,18 +7247,18 @@ iframe.preview-frame {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gdd-approval-card{
|
||||
.gdd-approval-card {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
padding: 16px 18px 18px;
|
||||
background: #f8fbff;
|
||||
}
|
||||
|
||||
.plan-gdd-surface--with-card .plan-gdd-stage-progress{
|
||||
.plan-gdd-surface--with-card .plan-gdd-stage-progress {
|
||||
border-bottom: 1px solid #dbe4f1;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress{
|
||||
.plan-gdd-stage-progress {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
padding: 10px 12px;
|
||||
@@ -7253,7 +7268,7 @@ iframe.preview-frame {
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__header,
|
||||
.plan-gdd-stage-progress__meta{
|
||||
.plan-gdd-stage-progress__meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
@@ -7263,7 +7278,7 @@ iframe.preview-frame {
|
||||
|
||||
/* 批准后的交付行。它是策划阶段唯一的产物出口,所以给一条分隔线把它和上面的状态
|
||||
区分开,而不是混成第三行元信息。 */
|
||||
.plan-gdd-stage-progress__delivery{
|
||||
.plan-gdd-stage-progress__delivery {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
@@ -7271,20 +7286,20 @@ iframe.preview-frame {
|
||||
border-top: 1px solid #e6ecf5;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery code{
|
||||
.plan-gdd-stage-progress__delivery code {
|
||||
min-width: 0;
|
||||
color: #3c4a5c;
|
||||
font-size: 11px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery-actions{
|
||||
.plan-gdd-stage-progress__delivery-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery-actions button{
|
||||
.plan-gdd-stage-progress__delivery-actions button {
|
||||
min-height: 30px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #cfd7e6;
|
||||
@@ -7295,32 +7310,32 @@ iframe.preview-frame {
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery-actions button:hover:not(:disabled),
|
||||
.plan-gdd-stage-progress__delivery-actions button:focus-visible{
|
||||
.plan-gdd-stage-progress__delivery-actions button:focus-visible {
|
||||
border-color: #1f6feb;
|
||||
color: #1f6feb;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery-actions button:disabled{
|
||||
.plan-gdd-stage-progress__delivery-actions button:disabled {
|
||||
opacity: 0.58;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery-error{
|
||||
.plan-gdd-stage-progress__delivery-error {
|
||||
color: #b42323;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__header strong{
|
||||
.plan-gdd-stage-progress__header strong {
|
||||
color: #27364a;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__header span{
|
||||
.plan-gdd-stage-progress__header span {
|
||||
padding: 3px 8px;
|
||||
border-radius: 999px;
|
||||
background: #eef6ff;
|
||||
color: #1f6feb;
|
||||
}
|
||||
|
||||
.gdd-approval-card__header{
|
||||
.gdd-approval-card__header {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
min-width: 0;
|
||||
@@ -7328,26 +7343,26 @@ iframe.preview-frame {
|
||||
|
||||
.gdd-approval-card h2,
|
||||
.gdd-approval-card h3,
|
||||
.gdd-approval-card p{
|
||||
.gdd-approval-card p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.gdd-approval-card h2{
|
||||
.gdd-approval-card h2 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.gdd-approval-card__header p{
|
||||
.gdd-approval-card__header p {
|
||||
color: #526173;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gdd-approval-card__details-trace{
|
||||
.gdd-approval-card__details-trace {
|
||||
color: #6b7a8c;
|
||||
font-size: 11px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gdd-approval-card__details-trigger{
|
||||
.gdd-approval-card__details-trigger {
|
||||
justify-self: start;
|
||||
min-height: 30px;
|
||||
padding: 0 10px;
|
||||
@@ -7357,12 +7372,12 @@ iframe.preview-frame {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.gdd-approval-card__decisions{
|
||||
.gdd-approval-card__decisions {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.gdd-approval-card__decisions article{
|
||||
.gdd-approval-card__decisions article {
|
||||
display: grid;
|
||||
gap: 3px;
|
||||
padding: 9px 10px;
|
||||
@@ -7371,19 +7386,19 @@ iframe.preview-frame {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.gdd-approval-card__decisions article span{
|
||||
.gdd-approval-card__decisions article span {
|
||||
color: #1f6feb;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.gdd-approval-card__decisions article small{
|
||||
.gdd-approval-card__decisions article small {
|
||||
color: #526173;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gdd-approval-card__actions,
|
||||
.gdd-approval-card__dialog-actions,
|
||||
.gdd-approval-card__recovery{
|
||||
.gdd-approval-card__recovery {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
@@ -7392,7 +7407,7 @@ iframe.preview-frame {
|
||||
|
||||
.gdd-approval-card__actions button,
|
||||
.gdd-approval-card__dialog-actions button,
|
||||
.gdd-approval-card__recovery button{
|
||||
.gdd-approval-card__recovery button {
|
||||
min-height: 32px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #cfd7e6;
|
||||
@@ -7402,17 +7417,17 @@ iframe.preview-frame {
|
||||
}
|
||||
|
||||
.gdd-approval-card__actions button:nth-child(n + 2),
|
||||
.gdd-approval-card__dialog-actions button:first-child{
|
||||
.gdd-approval-card__dialog-actions button:first-child {
|
||||
color: #27364a;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.gdd-approval-card button:disabled{
|
||||
.gdd-approval-card button:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.gdd-approval-card__recovery{
|
||||
.gdd-approval-card__recovery {
|
||||
justify-content: space-between;
|
||||
padding: 9px 10px;
|
||||
border-radius: 7px;
|
||||
@@ -7421,7 +7436,7 @@ iframe.preview-frame {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.gdd-approval-card__error{
|
||||
.gdd-approval-card__error {
|
||||
padding: 9px 10px;
|
||||
border-radius: 7px;
|
||||
color: #991b1b;
|
||||
@@ -7429,7 +7444,7 @@ iframe.preview-frame {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gdd-approval-card__dialog-backdrop{
|
||||
.gdd-approval-card__dialog-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 220;
|
||||
@@ -7439,7 +7454,7 @@ iframe.preview-frame {
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.gdd-approval-card__dialog{
|
||||
.gdd-approval-card__dialog {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
width: min(520px, 100%);
|
||||
@@ -7450,28 +7465,28 @@ iframe.preview-frame {
|
||||
box-shadow: 0 18px 52px rgb(0 0 0 / 18%);
|
||||
}
|
||||
|
||||
.gdd-approval-card__details{
|
||||
.gdd-approval-card__details {
|
||||
max-height: min(760px, calc(100vh - 32px));
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.gdd-approval-card__details header,
|
||||
.gdd-approval-card__details article{
|
||||
.gdd-approval-card__details article {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.gdd-approval-card__details article{
|
||||
.gdd-approval-card__details article {
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.gdd-approval-card__details p{
|
||||
.gdd-approval-card__details p {
|
||||
white-space: pre-line;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gdd-approval-card__dialog textarea{
|
||||
.gdd-approval-card__dialog textarea {
|
||||
width: 100%;
|
||||
min-height: 110px;
|
||||
padding: 9px;
|
||||
@@ -7480,7 +7495,7 @@ iframe.preview-frame {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.gdd-approval-card__dialog-hint{
|
||||
.gdd-approval-card__dialog-hint {
|
||||
padding: 9px 10px;
|
||||
border-radius: 7px;
|
||||
color: #854d0e;
|
||||
@@ -7491,21 +7506,73 @@ iframe.preview-frame {
|
||||
/* 审批卡是这一列里唯一没有天花板的成员:Fast GDD 的决定项越多它越高,能把消息列表和运行
|
||||
时面板一起挤出可视区。和 `.agent-runtime-status` 一样给它自己的上限加内部滚动,而不是
|
||||
让它去挤别人。 */
|
||||
/* 策划链路的会话列比另外两条多一个成员:策划面(阶段进度 + 审批卡)。#193(5802048c3
|
||||
「Codex/agent chat layout fix」)把这个容器从基础规则继承来的 `display: grid` 改成
|
||||
`display: block`、并把消息列表从 `flex: 1 1 auto` 改成 `height: 100%`,于是列表独吞
|
||||
整列高度,排在它后面的策划窄条、待确认命令、输入框和状态行全部被 `overflow: hidden`
|
||||
静默裁掉——组件照常渲染、DOM 里查得到,只是位置落在裁剪线外,屏幕上什么都没有。
|
||||
实测:窄条 top=858 而容器 bottom=788,超出 384px;scrollHeight 1235 vs clientHeight 734。
|
||||
|
||||
同一批改动还删掉了 `.game-workbench-chat .project-supervisor-composer` 的 4 条规则,
|
||||
所以列表上那个 `padding-bottom: 196px`(本意是给「浮起来的输入框」留位)从来没有对应
|
||||
的定位规则,那个模型压根没成立过。
|
||||
|
||||
`:has(.plan-gdd-surface)` 只在策划面在场时命中,做游戏与做素材保持 master 的 block
|
||||
列原样不动。用 flex 列而不是 grid:子元素个数随待确认命令的有无浮动,固定行模板会
|
||||
错位;而且下面那条 `.plan-gdd-surface { flex: 0 0 auto }` 本来就是照 flex 写的,容器
|
||||
变成 flex 之后它才真正生效——在此之前它一直是死声明。 */
|
||||
.game-workbench-chat .project-supervisor-conversation:has(.plan-gdd-surface) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
/* 兜底:正常情况下上面的行分配已经让整列放得下,这条不会产生滚动条。但审批卡展开
|
||||
到 52dvh 且窄条同时在场时仍可能超出,届时给滚动而不是继承 `overflow: hidden`
|
||||
的裁剪——这个 bug 的全部代价就来自「悄悄裁掉」,宁可多一根滚动条。 */
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* 整列里只有消息列表可收缩:其余成员各自有天花板(策划面按内容、窄条 52dvh 且内滚、
|
||||
输入框定高),由列表吸收剩余空间。`height: 100%` 必须撤掉,否则它照旧独吞整列;
|
||||
`padding-bottom` 也一并收回,输入框已经回到文档流里,不再需要给它留空。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation:has(.plan-gdd-surface)
|
||||
.project-supervisor-message-list {
|
||||
flex: 1 1 auto;
|
||||
height: auto;
|
||||
min-height: 96px;
|
||||
padding-bottom: 12px;
|
||||
scroll-padding-bottom: 12px;
|
||||
}
|
||||
|
||||
/* 这三个成员不参与压缩:消息列表变长时不能把它们挤没——它们正是用户唯一需要动手的
|
||||
地方(澄清卡、输入框)。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation:has(.plan-gdd-surface)
|
||||
.planning-lane-runtime-strip,
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation:has(.plan-gdd-surface)
|
||||
.project-supervisor-composer,
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation:has(.plan-gdd-surface)
|
||||
.project-supervisor-workspace-status {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
/* 这个面不参与 flex 压缩。它自己不会长高:标题栏是固定几行,审批卡下面有自己的
|
||||
max-height 和内滚,所以高度天然有界。让它可压缩的话,`overflow: hidden`(画圆角
|
||||
要的)会把底部切掉——批准后交付行正好在那儿,表现是路径和两个按钮凭空消失。 */
|
||||
.game-workbench-chat .plan-gdd-surface{
|
||||
.game-workbench-chat .plan-gdd-surface {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
/* 只有审批卡在场时才需要「标题栏定高 + 正文占余下」的两行轨道。批准后卡片收掉,
|
||||
面里只剩标题栏,这条声明会给它套上一个不存在的第二行。 */
|
||||
.game-workbench-chat .plan-gdd-surface--with-card{
|
||||
.game-workbench-chat .plan-gdd-surface--with-card {
|
||||
min-height: 0;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.game-workbench-chat .gdd-approval-card{
|
||||
.game-workbench-chat .gdd-approval-card {
|
||||
min-height: 0;
|
||||
max-height: clamp(240px, 52dvh, 640px);
|
||||
overflow-y: auto;
|
||||
@@ -7516,7 +7583,7 @@ iframe.preview-frame {
|
||||
/* 上面 24dvh/240px 的天花板是给做游戏链路常驻的调试面板设的。策划链路的窄条只在
|
||||
需要用户动手时出现(澄清卡 / 失败恢复),内容是要读完再回答的题面,给它和审批
|
||||
卡同级的空间。 */
|
||||
.game-workbench-chat .planning-lane-runtime-strip{
|
||||
.game-workbench-chat .planning-lane-runtime-strip {
|
||||
max-height: clamp(240px, 52dvh, 640px);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { ProjectSupervisorComponentProps } from '../../src/features/app-she
|
||||
import { WorkspaceLauncherShell } from '../../src/features/app-shell/WorkspaceLauncher';
|
||||
import {
|
||||
act,
|
||||
agentRuntimeUserInputRequest,
|
||||
App,
|
||||
cleanup,
|
||||
createGameCreationAppManifest,
|
||||
@@ -1611,6 +1612,93 @@ export function registerHomeProjectCreationTests() {
|
||||
).toHaveLength(1);
|
||||
},
|
||||
);
|
||||
|
||||
it('surfaces the planning clarification card after 做方案 creates the project from home', async () => {
|
||||
// 上面那条只断言到「run 起来了、source 对」。真实故障恰好落在它之后:plan 根 run
|
||||
// 停在 waiting-for-user-input 并带回澄清请求,而工作台一直停在前端本地的占位文案,
|
||||
// 澄清卡永远不出现。策划链路现有用例全部走「打开已有项目 + 直接注入 initialRuntime」,
|
||||
// 正好绕开首页自动建项目这条路,所以这个缺口一直没人守。
|
||||
const projectPath = '/tmp/home-planning-clarification';
|
||||
const manifest = createGameCreationAppManifest(
|
||||
'local-project-draft',
|
||||
'home-planning-clarification',
|
||||
);
|
||||
const supervisorHarness = createProjectSupervisorRuntimeHarness({
|
||||
projectPath,
|
||||
expectedRunProfile: 'standard',
|
||||
});
|
||||
let planRootRunId = '';
|
||||
const invoke = vi.fn(
|
||||
async (command: string, args?: Record<string, unknown>) => {
|
||||
if (command === 'pick_local_project_directory') {
|
||||
return projectPath;
|
||||
}
|
||||
if (command === 'is_local_project_directory_non_empty') {
|
||||
return false;
|
||||
}
|
||||
if (command === 'create_automatic_local_game_project') {
|
||||
return {
|
||||
projectPath,
|
||||
manifestPath: `${projectPath}/.agent/manifest.json`,
|
||||
manifest,
|
||||
};
|
||||
}
|
||||
if (command === 'start_game_creator_supervisor_runtime_task') {
|
||||
planRootRunId = String(args?.runId ?? '');
|
||||
}
|
||||
const result = await supervisorHarness.invoke(command, args);
|
||||
if (command !== 'read_game_creator_agent_runtime' || !planRootRunId) {
|
||||
return result;
|
||||
}
|
||||
// 后端此刻的真实形态:pending 是 user.input_request,读命令把澄清请求投影在
|
||||
// 结果的**顶层**(`AgentRuntimeResult.user_input_request`,与 `state` 平级),
|
||||
// 前端的 agentRuntimeStateFromResult 也优先读顶层。放进 state 会被顶层的 null
|
||||
// 盖掉,那是 fixture 写错,不是产品缺陷。
|
||||
const runtimeResult = result as { state: Record<string, unknown> };
|
||||
return {
|
||||
...runtimeResult,
|
||||
state: {
|
||||
...runtimeResult.state,
|
||||
status: 'waiting-for-user-input',
|
||||
phase: 'waiting-for-user-input',
|
||||
},
|
||||
userInputRequest: agentRuntimeUserInputRequest({
|
||||
agentId: 'project-supervisor',
|
||||
sessionId: supervisorHarness.sessionId,
|
||||
runId: planRootRunId,
|
||||
requestId: 'request-plan-round-1',
|
||||
actionId: 'action-plan-round-1',
|
||||
}),
|
||||
};
|
||||
},
|
||||
);
|
||||
window.__TAURI__ = {
|
||||
core: { invoke },
|
||||
event: { listen: supervisorHarness.listen },
|
||||
};
|
||||
renderLauncherAt('/?launcher', 'home', true);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '做方案' }));
|
||||
const promptInput = screen.getByLabelText('创作想法');
|
||||
nativeClipboardMock.text = '2D射击游戏';
|
||||
fireEvent.paste(promptInput);
|
||||
await waitFor(() => {
|
||||
expect(promptInput.textContent).toContain('2D射击游戏');
|
||||
});
|
||||
fireEvent.keyDown(promptInput, { key: 'Enter', code: 'Enter' });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(invoke).toHaveBeenCalledWith(
|
||||
'start_game_creator_supervisor_runtime_task',
|
||||
expect.objectContaining({ source: PROJECT_SUPERVISOR_PLAN_SOURCE }),
|
||||
);
|
||||
});
|
||||
|
||||
const strip = await screen.findByLabelText('立项策划运行状态');
|
||||
expect(
|
||||
within(strip).getByText('首版角色规范图采用哪种美术方向?'),
|
||||
).not.toBeNull();
|
||||
});
|
||||
it('refreshes Direct Codex art commits while the turn is still running and after a later failure', async () => {
|
||||
const projectPath =
|
||||
'C:\\Users\\tester\\Documents\\Genarrative GameAgent\\live-direct-art';
|
||||
|
||||
Reference in New Issue
Block a user