feat(consult): 对话口气改成反差与扮演象的形状
产品判定现有人设(懂行、可靠、说人话的占星师朋友)出来的是顾问报告。
人设改成把人当一个人认真对待、行动力很强、嘴有点毒但靠谱的同事:直接、
有立场、带一点锋利,毒只对处境不对人且每句锋利都要有盘上的证据。
开场从「一句结论 + 2–3 条短要点 + 一句下一步」换成固定形状,三种模式共用:
反差(表面 A 底下 B,命名成一个格局)→ 谁在推、谁在修(大运主星在推,
行运只负责把结果修得体面)→ 别去应 X 的象,去扮演 Y 的象 → 最多三条短行动
(破折号短句,各 ≤ 20 字)。仍无标题、总长 ≤ 400 字。术语当场用引号里的
白话套住。申报时段与无出生分钟两条降级路线形状照给,只把「谁在推谁在修」
换成窗口内稳定层或公开日历,不编月份。
新增希望纪律:盘上有转机且 answer_policy 允许精确应期时说到月份;没有就说
这段时间是拿来干什么的、可以扮演哪个象。禁「一切都会好 / 相信自己 / 加油 /
你值得更好的 / 宇宙自有安排」。
零业务逻辑改动,Skill 版本不变。tsc 0 错、lint 0 error(118 warning 不变)、
npm test 3468→3471 条且 36 条失败与基线 ff0427cf 逐条相同、/ 仍 Static、
首屏 gzip 两侧字节相同。
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
ff0427cf08
commit
84b293fb47
@@ -344,7 +344,10 @@ test("consult route expands an optional entrypoint for both Agent and tool input
|
||||
assert.match(source, /entrypoint: consultationEntrypointSchema\.exclude\(\["birth_time_rectification"\]\)\.optional\(\)/);
|
||||
assert.doesNotMatch(source, /entrypoint: z\.literal\("daily_starlanguage"\)\.optional\(\)/);
|
||||
assert.match(source, /question:\s*resolvedQuestion\.modelQuestion/);
|
||||
assert.match(source, /先用 3–6 句口语直接回答下面的问题[\s\S]*?resolvedQuestion\.modelQuestion/);
|
||||
// 原值: /先用 3–6 句口语直接回答下面的问题[\s\S]*?resolvedQuestion\.modelQuestion/
|
||||
// 新值: /先用不超过 400 字口语直接回答下面的问题[\s\S]*?resolvedQuestion\.modelQuestion/
|
||||
// 原因: 用户回合文案与新开场形状对齐(反差 / 谁推谁修 / 扮演哪个象 / 最多三条行动)。
|
||||
assert.match(source, /先用不超过 400 字口语直接回答下面的问题[\s\S]*?resolvedQuestion\.modelQuestion/);
|
||||
assert.doesNotMatch(source, /JSON\.stringify\(toolInput\)/);
|
||||
assert.match(source, /shouldLoadGeneralDailyPanchanga\(\{/);
|
||||
assert.doesNotMatch(source, /用户明确选择的无出生分钟一般咨询/);
|
||||
|
||||
@@ -18,9 +18,17 @@ test("product voice uses a spoken opener then the skill Level 2 report skeleton"
|
||||
assert.match(voice, /已执行 \/ 阻塞 \/ 不适用/);
|
||||
assert.match(voice, /governed_support_only_candidate_ready/);
|
||||
assert.match(voice, /Skip an executed layer the question needs/);
|
||||
assert.match(voice, /你更适合把已经积累的专业能力做成长期事业/);
|
||||
assert.match(voice, /3–6 heading-free sentences/);
|
||||
assert.match(voice, /one conclusion sentence, then 2–3 short point-sentences/);
|
||||
// 原值: assert.match(voice, /你更适合把已经积累的专业能力做成长期事业/) —— 它是 Good 例。
|
||||
// 新值: 同一句改断言成 Bad 例(下方 voice-opener-shape 测试里锁住它在 Bad 段)。
|
||||
// 原因: 产品判定这句像顾问报告——没有反差、没说谁在推谁在修、没有可扮演的象。
|
||||
// 原值: assert.match(voice, /3–6 heading-free sentences/)
|
||||
// 新值: assert.match(voice, /open with the OPENER SHAPE above, heading-free/)
|
||||
// 原因: 开场从「3–6 句」改成固定形状,句数不再是约束。
|
||||
assert.match(voice, /open with the OPENER SHAPE above, heading-free/);
|
||||
// 原值: assert.match(voice, /one conclusion sentence, then 2–3 short point-sentences/)
|
||||
// 新值: assert.match(voice, /别去应 X 的象,去扮演 Y 的象/)
|
||||
// 原因: 旧形状(结论+要点+下一步)被反差→谁推谁修→扮演象→短行动取代。
|
||||
assert.match(voice, /别去应 X 的象,去扮演 Y 的象/);
|
||||
assert.match(voice, /Spoken-layer total ≤ 400 Chinese characters/);
|
||||
assert.match(voice, /骨架不可省略,但必须以直接回应开场/);
|
||||
|
||||
@@ -55,6 +63,8 @@ test("general and window get voice without the natal Level 2 skeleton", () => {
|
||||
const window = mastra.slice(windowStart, mastra.indexOf("export function getWindowJyotishAgent"));
|
||||
const natal = mastra.slice(natalStart, mastra.indexOf("export function getJyotishAgent"));
|
||||
assert.match(natal, /natalSpokenReportContract/);
|
||||
// 新增: natal 也必须带 productConversationVoice —— 开场形状对三种模式共用。
|
||||
assert.match(natal, /productConversationVoice/);
|
||||
assert.match(general, /productConversationVoice/);
|
||||
assert.doesNotMatch(general, /natalSpokenReportContract/);
|
||||
assert.match(window, /productConversationVoice/);
|
||||
@@ -65,9 +75,59 @@ test("general and window get voice without the natal Level 2 skeleton", () => {
|
||||
test("consult user turn no longer dumps tool JSON that the model would parrot", () => {
|
||||
const chartBranch = route.slice(route.indexOf("const toolInput = consultationInputSchema.parse"));
|
||||
|
||||
assert.match(chartBranch, /先用 3–6 句口语直接回答下面的问题[\s\S]*?resolvedQuestion\.modelQuestion/);
|
||||
// 原值: /先用 3–6 句口语直接回答下面的问题[\s\S]*?resolvedQuestion\.modelQuestion/
|
||||
// 新值: /先用不超过 400 字口语直接回答下面的问题[\s\S]*?resolvedQuestion\.modelQuestion/
|
||||
// 原因: 用户回合文案与新开场形状对齐,约束从句数改成字数加形状。
|
||||
assert.match(chartBranch, /先用不超过 400 字口语直接回答下面的问题[\s\S]*?resolvedQuestion\.modelQuestion/);
|
||||
assert.match(chartBranch, /别去应 X 的象,去扮演 Y 的象/);
|
||||
assert.doesNotMatch(chartBranch, /JSON\.stringify\(toolInput\)/);
|
||||
assert.doesNotMatch(chartBranch, /经过服务端校验的工具参数/);
|
||||
assert.match(route, /文末技法审计表/);
|
||||
assert.match(chartBranch, /await runConsultationWorkflow\(toolInput/);
|
||||
});
|
||||
|
||||
test("the opener is a shape — 反差, 谁推谁修, 扮演哪个象, then at most three actions", () => {
|
||||
assert.match(voice, /OPENER SHAPE \(natal \/ general \/ declared-window 三种模式共用\)/);
|
||||
assert.match(voice, /反差/);
|
||||
assert.match(voice, /表面 A,底下 B/);
|
||||
assert.match(voice, /谁在推、谁在修/);
|
||||
assert.match(voice, /扮演/);
|
||||
assert.match(voice, /最多三条短行动/);
|
||||
assert.match(voice, /≤ 20 Chinese characters/);
|
||||
// 降级路线:申报时段与无出生分钟都不编月份,但「扮演哪个象」照给。
|
||||
assert.match(voice, /申报时段(declared birth window)[\s\S]*?也不写月份。第 3 步照给/);
|
||||
assert.match(voice, /无出生分钟(no birth minute)[\s\S]*?不写月份。第 3 步照给/);
|
||||
});
|
||||
|
||||
test("persona is the sharp-but-reliable colleague, and hope never becomes a platitude", () => {
|
||||
assert.match(voice, /把对面的人当一个人认真对待/);
|
||||
assert.match(voice, /嘴有点毒但靠谱的同事/);
|
||||
assert.match(voice, /毒只对处境,不对人/);
|
||||
// 含糊问题不猜、不反问一串:给默认解读再作答。
|
||||
assert.match(voice, /这句我按『……』理解了,不对你纠正我/);
|
||||
assert.match(voice, /HOPE DISCIPLINE/);
|
||||
assert.match(voice, /answer_policy\.can_answer_precise_timing 允许精确应期时/);
|
||||
assert.match(voice, /不是每个人都有转机,但每个人都有能扮演的象/);
|
||||
// 空话必须留在禁令里,但不得出现在 Good 例里。
|
||||
assert.match(voice, /Never write 一切都会好, 相信自己, 加油, 你值得更好的, or 宇宙自有安排。?/);
|
||||
assert.match(voice, /No 亲爱的, no 感谢你的信任, no emoji/);
|
||||
});
|
||||
|
||||
test("the pinned Good example carries the new shape; the old consultant-report line is now Bad", () => {
|
||||
const goodStart = voice.indexOf("Good (口气与形状的定稿样例");
|
||||
const goodEnd = voice.indexOf("Good (追问轮");
|
||||
assert.ok(goodStart > -1 && goodEnd > goodStart);
|
||||
const good = voice.slice(goodStart, goodEnd);
|
||||
assert.match(good, /今年你的事业是「外松内紧」/);
|
||||
assert.match(good, /推动这一年的是土星,不是木星/);
|
||||
assert.match(good, /去扮演土星的「守」/);
|
||||
assert.match(good, /- 9 月木星换宫之后再谈升职,之前谈是白谈。/);
|
||||
// 拍板样例里不得出现空话安慰;禁令本身仍写在 HOPE DISCIPLINE 段。
|
||||
assert.doesNotMatch(good, /一切都会好|相信自己|加油|宇宙自有安排/);
|
||||
|
||||
assert.match(voice, /Good \(追问轮,用户说「你在说什么鬼」\): 说直接点:这份工作还值得留/);
|
||||
|
||||
const badLine = voice.split("\n").find((line) => line.startsWith("Bad: 你更适合把已经积累的专业能力做成长期事业"));
|
||||
assert.ok(badLine, "旧 Good 例必须改挂在 Bad 上");
|
||||
assert.match(badLine!, /像顾问报告:没有反差,没说谁在推谁在修,没有可扮演的象/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user