boardx / boardx/workspacex

HMW 工作坊画布模板在devapp完全渲染失败(0个##分区)——真实模型复现未能重现,需接入实际运行审计定位真因

Open
#3,544 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
0
Forks
0
Avg merge
1h 7m
Merged PRs (30d)
969

Description

## 症状(人类实测,devapp 真实浏览器 + 真实模型)

用户请求 HMW(How Might We)头脑风暴,模型回复里带了一个 ```canvas 围栏(`checkCanvasFence` 能解析出 `模板: hmw`——报错文案里点名了"模板「hmw」",说明这一行确实写对了),但前端报错:

> 无法渲染此工作坊画布模板(围栏格式有误:模板「hmw」的围栏里没有任何「## 分区」标题,画布无处可放便签。)

模型输出的原始内容是 8 条"我们可以如何……为……以便……"三段式陈述,格式规整,但**完全没有任何 `## 分区` 标题**——`parseTemplateText()` 的 `sections` 是空 Map,触发 `apps/web/lib/canvas/canvas-fence.ts` 43 行那条硬报错。

## 本轮做了什么:真实模型复现(未能重现该症状)

用生产代码的真实路径复现:`buildBuiltinSections()`(`apps/api/src/domain/canvas/builtin-template-config.ts`)把 hmw 的 fabric spec 推演成 DB 形态的 `SectionDef[]`,喂给 `buildCanvasTemplateGuidance()`(`apps/api/src/application/agent-run/canvas-template-guidance.ts`——**这就是 `execute-run.ts` 注入 chat system prompt 用的那个函数,不是另编的一份**),拼出真实会发给模型的 system prompt,直接打真实 DashScope `qwen3.8-max`(`.env.local` 凭据),跑了两组不同措辞:

1. "我们的问题是:……帮我用 HMW(How Might We)方法产出一版问题陈述和头脑风暴的 8 个想法。"
2. "……帮我做一次 HMW 头脑风暴,给我 8 条'我们可以如何……为……以便……'这样的陈述。"(刻意模仿人类截图里描述的措辞,测试"模型会不会把 8 条陈述本身当成 8 个分区、而不用 `## 想法N` 包起来"这个猜想)

**两次模型输出都完整写出了 `模板: hmw` + 3 个表头字段(我们可以如何/为给/以便)+ 8 个 `## 想法N` 分区**,`parseTemplateText` 解析出 8 个非空分区、3 个表头字段全部命中,`checkCanvasFence` 判定通过——**均未复现人类截图里"0 个分区"的完全失败**。

## 诚实的结论:本轮排除了什么,没排除什么

**排除**:`buildCanvasTemplateGuidance()` 的措辞本身没有系统性地诱导模型漏写 `## 分区`——在干净的单轮 system+user 对话里,`qwen3.8-max` 2/2 次都正确遵循格式。这不是一个"提示词永远教不会模型"的 A 型问题(至少在这次测试的条件下不是)。

**没有排除、且是本轮最值得怀疑的两个方向**:

1. **canvas 指引可能根本没被注入这次真实对话**。`buildCanvasTemplateGuidance` 只在 `deps.canvasTemplates.listPublished(orgId, userId)` 返回非空列表时才拼出指引(`execute-run.ts` 709-717 行),空列表直接返回 `null`,**不注入任何提示、也不报错**——模型此时只能凭通用知识猜"HMW 大概长什么样",猜出来的自然是教科书式的"We can...for...so that..."列表,不会知道这个仓库自己发明的 `## 分区` 语法。而**19 个内置模板的"发布"动作是一次性 backfill 脚本**(`apps/api/scripts/backfill-canvas-builtin-templates.ts`),本仓源码里搜不到任何"新建组织自动跑一遍这个脚本"的钩子(在 `apps/api/src/application/identity`、`onboarding` 等目录下都没有引用点)。**如果人类那次实测用的组织是在最近一次手动跑 backfill 之后新建的,这个组织的 canvas 模板库可能整个是空的**,那么 chat 对所有 19 个模板(不只 hmw)都拿不到任何结构化指引——这与"journey-map 结构基本对、只是表头列空白"和"hmw 完全没有 `## 分区`"这两个不同严重程度的症状**不完全吻合**(如果两者都完全没指引,journey-map 也不该有正确的分区结构),所以这条假设需要针对**这次具体的 run** 核实,不能靠本轮的干净复现替代。
2. **真实 chat 的 system prompt 比本轮复现拥挤得多**。`buildSystemPrompt()`(`execute-run.ts` 584-596 行)把 `canvasGuidance` 和 `run.instructions`、全部挂载 skill 的正文、`VISUALIZATION_GUIDANCE` 拼在一起;本轮复现只喂了 `canvasGuidance` 一段、零上下文干扰。更长、更拥挤的提示词让模型在次要格式要求上打折扣是常见现象,但本轮没有资源去搭一个"全量 system prompt"的等价复现来验证这一点。

## 根因分类:**待定(本轮不下结论)**

不是"两者都有问题"的 C 型草率合并——是**本轮证据不足以在 A/B/C 之间选一个**:guidance 措辞本身经过实测是有效的(不支持纯 A 型"提示词没讲清楚"),也没有找到解析器代码层面的确凿 bug(不支持纯 B 型——`parseTemplateText` 对 0 个 `## ` 标题的处理本身是符合预期的诚实报错,不是解析器读错了模型明明写对的内容)。真正没有回答的问题是**这次真实 run 里模型实际看到了什么 system prompt、实际吐出了什么**——这两件事本轮完全靠猜。

## 建议下一轮怎么做

1. **优先**:找到人类那次实测对应的 `agent_run_steps` 审计记录(`execute-run.ts` 里 F15 那段落库的 `inputFullContent`/`outputFullContent`,逐字节记录了"模型看到了什么、完整说了什么"),核对当时的 system prompt 里到底有没有 `CANVAS_GUIDANCE_HEADER`(`## 工作坊协作画布(canvas 围栏)`)这一段——有就排除假设①,去查假设②;没有就坐实假设①,同时说明 journey-map 那次为什么结构基本对(可能是另一次 run,用的是已经 backfill 过的组织)。
2. **结构性加固**(不管这次具体因为哪个假设成立,独立成立的一个健壮性缺口):`backfill-canvas-builtin-templates.ts` 目前只能靠人手动跑,新建组织不会自动获得 19 个内置模板的发布状态。建议评估是否要把这一步接入组织创建流程(或者在 `listPublished` 返回空列表时的降级路径上,至少对 19 个内置 key 有一个兜底行为,而不是"这个组织好像从来没配置过任何模板")。
3. 关联 issue #3542(journey-map 表头字段精确匹配无兜底)——如果假设①被排除(这次 run 确实拿到了指引),journey-map 那次的表头空白大概率就是 #3542 描述的那个代码缺口触发的;HMW 这次的完全失败无论如何都不能用 #3542 解释(0 个分区是结构性缺失,不是某个分区/字段查找 miss)。

## 复现脚本与证据

复现脚本调用了生产代码里的 `buildBuiltinSections` / `buildCanvasTemplateGuidance` / `parseTemplateText` / `templateToModel`(均为逐字 import,未复制第二份实现),直接对真实 DashScope 端点发起请求,两组完整的 system prompt / 模型原始输出 / 解析结果已在诊断过程中留存,可在下一轮按需重新生成(复现方法:`buildCanvasTemplateGuidance([{key:"hmw", displayName:..., sections: buildBuiltinSections({fields:['我们可以如何','为给','以便'], sections:[...]}).map(...)}])` 拼 system,`fetch` DashScope `/chat/completions`,用 `parseTemplateText` 解析回来)。

---
来源:devapp 实测工作坊画布模板功能,人类提供截图证据(HMW 完全渲染失败 + 原始模型输出)。

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the matching agent_run_steps audit record and the F15 persistence code in apps/api/src/application/agent-run/execute-run.ts; compare the recorded system prompt and model output with the canvas guidance header. Then inspect listPublished, apps/api/scripts/backfill-canvas-builtin-templates.ts, and the organization creation paths. Done means identifying which prompt or template-publication condition caused the missing sections and recording a confirmed remediation scope.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
full-stack
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.