feat(consult): career answers don't guess the field — strength/resistance/timing + one ask; follow-up reads a stated job (BUG-1176 decision); goldens regenerated; rubric round-4 pass lines; backtest script career follow-up
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ffafa28b79
commit
6a02e5e91e
@@ -129,13 +129,9 @@ test("T3: career, marriage and wealth each carry their affliction line", () => {
|
||||
assert.ok(CONSULTATION_CONDENSED_CHECKLISTS.marriage!.some((line) => line.includes("感情这条线上有波折的迹象") && line.includes("不断定有几段") && line.includes("不预设用户现在有伴侣或单身")));
|
||||
assert.ok(!CONSULTATION_CONDENSED_CHECKLISTS.marriage!.join("\n").includes("可能不止一段"));
|
||||
assert.ok(CONSULTATION_CONDENSED_CHECKLISTS.wealth!.some((line) => line.startsWith("8 宫也管版税、继承、意外之财")));
|
||||
// 原值: career / marriage / wealth 都是 5–8 行
|
||||
// 新值: marriage / wealth 仍 5–8 行;career 5–9 行
|
||||
// 原因: TASK-consult-career-yoga-functional-20261002 T4 定稿给事业清单加两行(行业、公众 / 幕后的依据,BUG-1176),定稿文本不得改意思
|
||||
for (const domain of ["career", "marriage", "wealth"] as const) {
|
||||
const lines = CONSULTATION_CONDENSED_CHECKLISTS[domain]!;
|
||||
const max = domain === "career" ? 9 : 8;
|
||||
assert.ok(lines.length >= 5 && lines.length <= max, domain);
|
||||
assert.ok(lines.length >= 5 && lines.length <= 8, domain);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -19,7 +19,12 @@ import {
|
||||
CONDENSED_SHARED_READING_LINES,
|
||||
CONSULTATION_CONDENSED_CHECKLISTS,
|
||||
} from "../src/lib/consultation-condensed-checklist.ts";
|
||||
import { natalAnswerShapeBody } from "../src/lib/consultation-thinking-plan.ts";
|
||||
import {
|
||||
CAREER_FIELD_ASK_RULE,
|
||||
CAREER_FOLLOW_UP_RULE,
|
||||
followUpAnswerShapeInstruction,
|
||||
natalAnswerShapeBody,
|
||||
} from "../src/lib/consultation-thinking-plan.ts";
|
||||
import {
|
||||
consultationWorkflowResponseSchema,
|
||||
toAgentConsultationContext,
|
||||
@@ -79,10 +84,27 @@ test("shared reading: traditional yogas only show strength", () => {
|
||||
assert.ok(CONDENSED_SHARED_READING_LINES.includes("`traditional_yogas` 只用来说明力量,不单独下结论,不算受冲,也不抵消受冲。"));
|
||||
});
|
||||
|
||||
test("career list: field by planet nature, public only with chart evidence (T4 text)", () => {
|
||||
test("career: no field / public verdict, ask what the user does (product decision 2026-10-02)", () => {
|
||||
const career = CONSULTATION_CONDENSED_CHECKLISTS.career!;
|
||||
assert.ok(career.includes("行业看星的本性:10 宫里的星、10 宫主、AmK,以及 10 宫主在 D9 的定位星。太阳 = 权力、公职、管理;月亮 = 公众、照护、流动;火星 = 体力、竞技、工程、军警;水星 = 沟通、写作、商业、分析;木星 = 教育、法律、顾问、宗教;金星 = 艺术、表演、娱乐、美;土星 = 劳动、组织、长期工程;罗睺 = 新技术、跨界、海外、大众传播。先说最强的一两颗,不平均罗列。"));
|
||||
assert.ok(career.includes("公众型还是幕后型要有依据:太阳或 10 宫主强且在角宫、AL 或 A10 落角宫、10 宫或命宫有入旺入庙星、`traditional_yogas` 有大格局,偏公众;10 宫主落 12 宫且无上述信号,才偏幕后。没有依据就不写这一句。不写「出头慢、越往后越稳、靠专业交付」这类人人适用的话,除非能指出具体盘面。"));
|
||||
assert.equal(career[0], CAREER_FIELD_ASK_RULE);
|
||||
assert.equal(CONSULTATION_CONDENSED_CHECKLISTS.career!.filter((line) => line === CAREER_FIELD_ASK_RULE).length, 1);
|
||||
for (const phrase of ["不替用户断定他做哪一行、是公众型还是幕后型", "「出头慢」「越往后越稳」「靠专业交付」", "事业这一段末尾用一句话问用户实际做什么", "这一句就是全篇唯一一处请用户说实际情况"]) {
|
||||
assert.ok(CAREER_FIELD_ASK_RULE.includes(phrase), phrase);
|
||||
}
|
||||
const text = career.join("\n");
|
||||
assert.doesNotMatch(text, /行业看星的本性|公众型还是幕后型要有依据|公众形象就是事业/);
|
||||
// The rule is defined once (thinking plan) and only quoted by the career list.
|
||||
const plan = readFileSync(new URL("../src/lib/consultation-thinking-plan.ts", import.meta.url), "utf8");
|
||||
const list = readFileSync(new URL("../src/lib/consultation-condensed-checklist.ts", import.meta.url), "utf8");
|
||||
assert.ok(plan.includes("export const CAREER_FIELD_ASK_RULE = "));
|
||||
assert.equal(list.includes("不替用户断定他做哪一行"), false);
|
||||
});
|
||||
|
||||
test("follow-up: a stated job is read against the chart, nothing invented", () => {
|
||||
const followUp = followUpAnswerShapeInstruction();
|
||||
assert.ok(followUp.includes(CAREER_FOLLOW_UP_RULE));
|
||||
assert.match(CAREER_FOLLOW_UP_RULE, /按这份工作去读盘上的力量、阻力和时间/);
|
||||
assert.match(CAREER_FOLLOW_UP_RULE, /不为它编盘上没有的依据/);
|
||||
});
|
||||
|
||||
test("opener keeps the affliction rule (T5 text)", () => {
|
||||
|
||||
@@ -79,16 +79,12 @@ test("each condensed list is 5–8 lines", () => {
|
||||
// 原值:全部清单 5–8 行,且只有 career / marriage / wealth 三份;
|
||||
// 新值:这三份仍 5–8 行;另有 TASK-consult-affliction-reading-20261001 定稿的 8 份(2–6 行,按任务书原文,不凑行数),
|
||||
// 只有 timing 没有本地清单;原因:该任务书 T2 / 决策 D5 补齐清单,定稿文本不得改意思。
|
||||
// 原值:career / marriage / wealth 5–8 行;新值:marriage / wealth 5–8 行、career 5–9 行;
|
||||
// 原因:TASK-consult-career-yoga-functional-20261002 T4 定稿给事业清单加两行(BUG-1176),定稿文本不凑行数。
|
||||
for (const domain of ["career", "marriage", "wealth"] as const) {
|
||||
const lines = CONSULTATION_CONDENSED_CHECKLISTS[domain]!;
|
||||
const max = domain === "career" ? 9 : 8;
|
||||
assert.ok(lines.length >= 5 && lines.length <= max, `${domain}: ${lines.length} lines`);
|
||||
assert.ok(lines.length >= 5 && lines.length <= 8, `${domain}: ${lines.length} lines`);
|
||||
}
|
||||
for (const [domain, lines] of Object.entries(CONSULTATION_CONDENSED_CHECKLISTS)) {
|
||||
const max = domain === "career" ? 9 : 8;
|
||||
assert.ok(lines!.length >= 2 && lines!.length <= max, `${domain}: ${lines!.length} lines`);
|
||||
assert.ok(lines!.length >= 2 && lines!.length <= 8, `${domain}: ${lines!.length} lines`);
|
||||
}
|
||||
assert.deepEqual(Object.keys(CONSULTATION_CONDENSED_CHECKLISTS).sort(), [
|
||||
"annual", "career", "children", "education", "family", "general", "health", "marriage", "migration", "parents", "wealth",
|
||||
@@ -100,7 +96,10 @@ test("the writer's prompt carries the condensed list with the three layers and t
|
||||
// 原值: career: ["接触", "结构性机会", "公开落地", …]
|
||||
// 新值: 三层改为「机会出现 / 成形 / 公开落地」,加「事业形态」行;不得再有「面试」「职位」
|
||||
// 原因: 产品 2026-10-02 改口径(名人回测对照组误报 1→15;盘分不出父母在不在、几段感情、有没有病);第 3 层的「面试 / 正式职位」把读者设成求职者(BUG-1168)
|
||||
career: ["接触", "机会出现", "成形", "公开落地", "事业形态", "事业必成", "d9 段", "KP 精确宫头仍 blocked"],
|
||||
// 原值(2): career 必含「事业形态」
|
||||
// 新值(2): 改为必含「不替用户断定他做哪一行」(CAREER_FIELD_ASK_RULE)
|
||||
// 原因(2): 产品 2026-10-02「行业不猜,问用户」,删掉「先讲一生事业形态:公众型还是幕后型」(BUG-1176)
|
||||
career: ["接触", "机会出现", "成形", "公开落地", "不替用户断定他做哪一行", "事业必成", "d9 段", "KP 精确宫头仍 blocked"],
|
||||
marriage: [
|
||||
"心动接触", "关系成对", "社会法律落地",
|
||||
"5 宫主大运 ≠ 法律婚", "金星过本命月亮 ≠ 心动月", "Punarphoo 不得写成结婚", "土星回到本命月亮是观察项,不是结婚",
|
||||
|
||||
@@ -109,8 +109,11 @@ test("2026-10-02: the shared reading quotes the range rule; parents, marriage, h
|
||||
assert.match(health, /身体这条线有压力的迹象/);
|
||||
assert.match(health, /不写「底子不差」/);
|
||||
const career = CONSULTATION_CONDENSED_CHECKLISTS.career!;
|
||||
assert.ok(career[0]!.startsWith("先讲这张盘一生的事业形态:公众型还是幕后型"));
|
||||
assert.match(career.join("\n"), /受冲只说阻力和代价,不改写事业形态/);
|
||||
// 原值: career[0] 以「先讲这张盘一生的事业形态:公众型还是幕后型」开头;含「受冲只说阻力和代价,不改写事业形态」
|
||||
// 新值: career[0] 是 CAREER_FIELD_ASK_RULE(只讲力量、阻力、时间;不断定行业与公众 / 幕后;段末问一句实际做什么)
|
||||
// 原因: 产品 2026-10-02 决定「行业不猜,问用户」(TASK-consult-career-yoga-functional-20261002,BUG-1176;第三轮回测行业对 3/18)
|
||||
assert.ok(career[0]!.startsWith("事业题只讲盘上的力量、阻力和时间"));
|
||||
assert.match(career.join("\n"), /不替用户断定他做哪一行、是公众型还是幕后型/);
|
||||
assert.doesNotMatch(career.join("\n"), /面试|职位|简历/);
|
||||
// The shape and the voice example carry no presence verdict.
|
||||
assert.doesNotMatch(productConversationVoice, /他可能不常在你身边,或者有一段时间不在|如果实际情况不是这样/);
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user