fix(专业发展): 「发布专业发展」直达表单,所属栏目不再问两遍
build / build-push (push) Successful in 1m27s

用户反馈:说「我要发布专业发展」没直接出表单,先被反问「要选哪个栏目」,
答完出来表单,「所属栏目」却还是空的要再选一次 —— 一件事问了两遍。

两处根因:
1) profession.publish 的说明只写了「调用前必须确认所属栏目 moduleId 与标题」,
   漏了公告 / 宿舍 / 活动 / 作业四个发布工具都有的那句「缺失就直接调用本工具,
   系统会弹出完整表单让用户填写,不要用文字反复追问」—— 模型读到「必须确认」
   就照字面先去口头确认了;
2) 「发布专业发展」不在裸意图直达表里,这句必然要过一轮模型。

改动:
- 工具说明按另外四个发布工具的同款句式补齐(说明词是模型唯一的施工图);
- IntentShortcut 新增「发布专业发展记录」意图(仅教职工),说「我要发布专业发展」
  直接弹表单;栏目是学校自建的、各校 id 不同,所以**不预置**,
  由用户就在表单里选 —— 这正是「直接出表单选栏目」;
- 契约测试 everyPublishToolTellsTheModelNotToKeepAskingInWords:凡是名字以
  .publish 结尾的工具,说明里必须带「不要用文字反复追问」(漏写会被测出来);
- IntentDirectFormTest 补两条:教职工直达出表单(含栏目下拉与代取地址、且不预置
  栏目)、学生落回模型。

配套(前端 86e3a10):即便真的先问了一轮再弹表单,对话里定好的值也会被对齐到
选项取值(数字 71 → "71",名称「数学」→ SUB02),表单里不再重复问。
This commit is contained in:
lijing
2026-10-14 11:35:43 +08:00
parent 42a7a8030d
commit c3477c6588
4 changed files with 120 additions and 1 deletions
@@ -474,6 +474,43 @@ class ModuleFormParityTest {
AgentOrchestrator.pathPrefix("profession", "http://base.yunhaixingtong.com/profession"));
}
/* ==================== 发布类工具的「说明词」不变量 ==================== */
/**
* 凡是「叫什么就发什么」的发布工具({@code *.publish}),说明里都必须有
* 「缺失就直接调用本工具…不要用文字反复追问」。
*
* <p>起因(用户反馈:「我说我要发布专业发展,没到表单,先让我选哪个栏目,答完表单里
* 又要选一次所属栏目,一件事问了两遍」):五个发布工具里有四个都写了这句,
* 唯独 {@code profession.publish} 只写了「调用前必须确认所属栏目 moduleId 与标题」——
* 模型读到「必须确认」,于是先反问用户要发到哪个栏目,答完才弹表单。
*
* <p>这类问题的根子在**说明词**而不是代码:工具说明是模型唯一的施工图,
* 「必须确认」后面缺了那句「缺失就直接调用」,模型就只好照字面去口头确认。
* 因此在契约测试里钉住「只写 {@code xxx.publish} 的都要带上这句」,
* 将来新增发布工具漏写会被直接测出来。
*
* <p>为什么是「名字以 {@code .publish} 结尾」而不是「所有 fullForm 工具」:
* {@code notice.saveDraft} / {@code homework.schedule} 这类变体不在此列 ——
* 它们是「同一个发布动作的另一种落点」,由发布工具自己的说明指向它们,
* 单独调用时也不该反过来抢走发布意图(用户说「发布作业」要落到 {@code homework.publish})。
*/
@Test
void everyPublishToolTellsTheModelNotToKeepAskingInWords() {
int checked = 0;
for (ToolDef def : registry.all()) {
if (!def.getName().endsWith(".publish")) {
continue;
}
checked++;
assertTrue(def.getDescription() != null && def.getDescription().contains("不要用文字反复追问"),
"发布工具 " + def.getName() + " 的说明缺少「不要用文字反复追问」——"
+ "模型会照字面先反问用户要发到哪个栏目/填什么,把一件事拆成两轮。"
+ "实际说明:" + def.getDescription());
}
assertEquals(5, checked, "注册表里应有 5 个发布工具(公告/宿舍/活动/作业/专业发展)");
}
/* ==================== 辅助 ==================== */
/** 字典返回对象里「值 / 显示名」取的是哪两个键(optionsKeys 的结果) */