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
@@ -252,7 +252,7 @@ Jyotisha 的可见文案是产品的一部分。正确性红线(真实性、
|
||||
5. **口语化但不轻佻。** 短句、具体事实、少套话。
|
||||
6. **希望纪律。** 占星结果是客观的,表达是主观的。不顺就说不顺,但每次都要说清这段时间能做什么。盘上确有转机、且 `answer_policy.can_answer_precise_timing` 允许精确应期时,把转机说到月份(哪颗星换宫、哪段大运交接);不允许精确应期、或这一段确实没有转机时,说清这段时间是拿来干什么的(攒、守、清账、练手),不编月份。不是每个人都有转机,但每个人这段时间都有能做的事。不写「一切都会好」「相信自己」「加油」「你值得更好的」「宇宙自有安排」。(2026-10-01 起不再用「扮演哪个象」的说法,TASK-consult-plain-answer-20261001 D5。)
|
||||
7. **回答形状:先答,再按对象分段(2026-10-01,BUG-1132,推翻 2026-09-17 的四步开场形状)。** 三种模式(本命 / 无出生分钟 / 申报时段)共用,**不设字数上限,讲清楚为准**,同一件事只说一遍。① **先答**——开场一到三句人话,第一句就是结论,不写标题、不写行动,不给这件事起名字;**开场同样守受冲规则**(2026-10-02,BUG-1177):不替用户断定在不在身边、几段感情、有没有病,不写「距离感明显」「不是能硬扛的类型」这类程度结论,只说哪条线顺、哪条线有压力迹象;② **按对象分段**——问题里点到几个人或几个子问题(妈妈、爸爸、他们怎么对我、什么时候),开场之后每个各写一段,二级标题用问题里的词(`## 你和妈妈`、`## 你和爸爸`、`## 他们怎么对你`);问父母时妈妈和爸爸分开写;只问一个人或一件事时不拆段;③ **每段先说最强的信号、后依据**(2026-10-01 BUG-1164 改,取代「这个人是什么样、你们怎么相处、事情会怎么走」)——先说盘上最强的一两个信号说明了什么,包括这个人在不在你身边、近不近;盘上没有依据的方面不写,不用日常场景凑段落;受冲信号两个及以上时(2026-10-02 产品改口径,盘分不出父母在不在身边、几段感情、有没有病):先说这条线有压力或距离的迹象,括号里给依据,再给现实里可能的范围(「现实里可能是分开、离得远,也可能只是关系紧、话少」),不替用户断定他自己更清楚的事实,也不反过来写「有分量」「站得住」「不是缺位」「底子不差」「关系稳」「能走下去」;段末一句请用户说说实际情况(「实际是哪一种,告诉我一句,我按真实情况再看。」),全篇最多一处;婚姻写「感情这条线上有波折的迹象」而不是「可能不止一段」,健康写「身体这条线有压力的迹象」而不是「底子不差」;**不预设处境**:有没有伴侣、是否已婚、是否在上班、做哪类工作、孩子性别、父母是否在身边都不预设,性别未知时不用「他」「她」称伴侣和孩子;再在括号里给撑住这段判断的盘上依据(宫、宫主、代表星、分盘、大运);问的是别人时写那个人在你盘上对应的宫位与代表星说明了什么,不写那个人的心思(BUG-1070 的目的保留);④ **行动**——一到三条破折号短句,本命解读里只在最后一节出现一次。<br>**人话自检**:把每句话括号里的内容删掉,一个完全不懂占星的人仍能看懂。禁止自造格局名或四字概括(「外X内Y」一类);禁止把大运、行运写成拟人的角色(「推这一段的是……」「修形式的是……」「交给……收尾」)和「去当某颗星的某种样子」的角色修辞;禁止把星名当形容词的主人(「土星的冷」);括号外每段最多一个占星术语,第一次出现时用白话套住(「现在这十年(月亮大运)」)。**推断边界**:空宫不单独下结论,要说它的宫主落在哪、什么状态(BUG-1134)。<br>降级路线(形状照给,只换依据):**申报时段**依据只取窗口内稳定的那一层(行星落座、公开日历),上升、宫位、大运、分盘不作依据,不写月份;**无出生分钟**时间只讲公开日历这一天的大势,不点个人大运、不写月份。<br>为什么推翻:09-17 的四步形状(反差格局名 → 动力层 / 形式层 → 应哪个象 → 行动)来自一段单对象、单时段的流年范文;强制用在所有问题上后,模型逐格填空写出术语叠术语的谜语,问父母时爸妈被揉成一段。
|
||||
8. **事业题看行业与名声,要有盘面依据(2026-10-02,BUG-1176)。** 行业看星的本性(10 宫里的星、10 宫主、AmK、10 宫主在 D9 的定位星;太阳权力公职、月亮公众照护、火星体力竞技工程、水星沟通商业、木星教育法律、金星艺术表演、土星劳动组织、罗睺新技术跨界),先说最强的一两颗;公众型 / 幕后型只在有依据时写(太阳或 10 宫主强在角宫、AL / A10 落角宫、入旺入庙星、`traditional_yogas`;10 宫主落 12 宫且无这些信号才偏幕后)。不写「出头慢、越往后越稳、靠专业交付」这类人人适用的话。卡上的「传统格局,本站未验证,只作参考」只用来说明某颗星有力量,不单独下结论,不算受冲,也不抵消受冲(BUG-1175)。
|
||||
8. **事业题不猜行业,问用户(2026-10-02 产品决定,BUG-1176;取代同日「按星的本性看行业」两行)。** 事业答案只讲盘上的力量、阻力和时间;不替用户断定他做哪一行、是公众型还是幕后型(盘分不出,名人回测里演员、球星、总统的 10 宫系统都读成分析 / 顾问),不写「出头慢、越往后越稳、靠专业交付」这类人人适用的话,除非能指出具体盘面;事业这一段末尾用一句话问「你现在具体做哪一行、什么角色,告诉我一句,我按你的实际工作再看。」,这一句就是全篇唯一一处请用户说实际情况。用户说了自己的工作后,按这份工作读助力、阻力和时间,不说「盘早就显示你会做这一行」,不编依据。卡上的「传统格局,本站未验证,只作参考」只用来说明某颗星有力量,不单独下结论,不算受冲,也不抵消受冲(BUG-1175)。
|
||||
|
||||
## 好 / 坏对照
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
* [--out <dir>] [--repeats 2] [--figures a,b] [--domains parents,marriage,health,career] \
|
||||
* [--model deepseek-flash] [--base-url https://api.deepseek.com] [--concurrency 4] [--dump-cards]
|
||||
* [--correction barack_obama,marilyn_monroe] [--correction-text 我爸其实没怎么管过我]
|
||||
* [--correction-domain career] [--correction-texts "zinedine_zidane=我是足球运动员|barack_obama=我是政治家"]
|
||||
*
|
||||
* --dump-cards writes the model-visible tool result per figure x domain and
|
||||
* calls no model. --correction adds, for each listed figure's parents answer,
|
||||
@@ -130,6 +131,13 @@ function parseArgs(argv: readonly string[]) {
|
||||
recheck: value("recheck"),
|
||||
correction: value("correction")?.split(",").filter(Boolean) ?? [],
|
||||
correctionText: value("correction-text") ?? "我爸其实没怎么管过我",
|
||||
// Follow-up domain (default parents) and optional per-figure texts
|
||||
// "figure=text|figure=text" (career follow-up: the user states the real job).
|
||||
correctionDomain: value("correction-domain") ?? "parents",
|
||||
correctionTexts: Object.fromEntries((value("correction-texts") ?? "").split("|").filter(Boolean).map((pair) => {
|
||||
const at = pair.indexOf("=");
|
||||
return [pair.slice(0, at), pair.slice(at + 1)];
|
||||
})) as Record<string, string>,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -544,22 +552,22 @@ async function main() {
|
||||
return { figure: job.figure.id, domain: job.domain, run: job.run, chars: result.output.length, ...result, output: undefined, checks };
|
||||
});
|
||||
const corrections = await pool(
|
||||
jobs.filter((job) => job.domain === "parents" && args.correction.includes(job.figure.id)),
|
||||
jobs.filter((job) => job.domain === args.correctionDomain && args.correction.includes(job.figure.id)),
|
||||
args.concurrency,
|
||||
async (prior) => {
|
||||
const priorFile = join(args.out, prior.figure.id, `parents-run${prior.run}.md`);
|
||||
const priorFile = join(args.out, prior.figure.id, `${prior.domain}-run${prior.run}.md`);
|
||||
const priorText = readFileSync(priorFile, "utf8");
|
||||
const priorAnswer = priorText.slice(priorText.indexOf("\n---\n\n") + 6).trim();
|
||||
const job: Job = { ...prior, question: args.correctionText, followUp: { priorQuestion: prior.question, priorAnswer } };
|
||||
const job: Job = { ...prior, question: args.correctionTexts[prior.figure.id] ?? args.correctionText, followUp: { priorQuestion: prior.question, priorAnswer } };
|
||||
let result: Awaited<ReturnType<typeof runJob>>;
|
||||
try {
|
||||
result = await runJob(job, resolved);
|
||||
} catch (error) {
|
||||
result = { output: "", failure: error instanceof Error ? error.message : String(error), executed: [], seconds: 0, usage: {}, cardChars: null, visibleChars: null, methodologySections: 0, lookups: 0, finish: null };
|
||||
}
|
||||
const file = join(args.out, job.figure.id, `parents-correction-run${job.run}.md`);
|
||||
const file = join(args.out, job.figure.id, `${job.domain}-correction-run${job.run}.md`);
|
||||
writeFileSync(file, [
|
||||
`# ${job.figure.label} · parents 纠正追问 · run ${job.run}`,
|
||||
`# ${job.figure.label} · ${job.domain} 纠正追问 · run ${job.run}`,
|
||||
"",
|
||||
`- 上一轮:${priorFile}`,
|
||||
`- 追问:${job.question}`,
|
||||
@@ -572,7 +580,7 @@ async function main() {
|
||||
result.output || "(无回答)",
|
||||
"",
|
||||
].join("\n"));
|
||||
console.log(`${job.figure.id} parents correction run${job.run}: ${result.output.length} chars, ${result.seconds.toFixed(0)} s${result.failure ? `, FAILED ${result.failure}` : ""}`);
|
||||
console.log(`${job.figure.id} ${job.domain} correction run${job.run}: ${result.output.length} chars, ${result.seconds.toFixed(0)} s${result.failure ? `, FAILED ${result.failure}` : ""}`);
|
||||
return { figure: job.figure.id, run: job.run, chars: result.output.length, seconds: result.seconds, failure: result.failure, usage: result.usage };
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ConsultationDomain } from "./consultation-domain-registry.ts";
|
||||
import type { ProfileGender } from "./profile-gender.ts";
|
||||
import { AFFLICTION_RANGE_RULE } from "./consultation-thinking-plan.ts";
|
||||
import { AFFLICTION_RANGE_RULE, CAREER_FIELD_ASK_RULE } from "./consultation-thinking-plan.ts";
|
||||
|
||||
/**
|
||||
* Condensed consultation checklists (TASK-consult-evidence-card-v2-20260927
|
||||
@@ -81,14 +81,12 @@ export const CONSULT_BRIEF_CHECKLIST_SOURCE = "consultation checklist (TASK-cons
|
||||
|
||||
export const CONSULTATION_CONDENSED_CHECKLISTS: Readonly<Partial<Record<ConsultationDomain, readonly string[]>>> = {
|
||||
career: [
|
||||
"先讲这张盘一生的事业形态:公众型还是幕后型、靠什么出头(AL 落宫、10 宫与 10 宫主、太阳、入旺入庙星坐角宫);受冲只说阻力和代价,不改写事业形态。",
|
||||
"行业看星的本性:10 宫里的星、10 宫主、AmK,以及 10 宫主在 D9 的定位星。太阳 = 权力、公职、管理;月亮 = 公众、照护、流动;火星 = 体力、竞技、工程、军警;水星 = 沟通、写作、商业、分析;木星 = 教育、法律、顾问、宗教;金星 = 艺术、表演、娱乐、美;土星 = 劳动、组织、长期工程;罗睺 = 新技术、跨界、海外、大众传播。先说最强的一两颗,不平均罗列。",
|
||||
"公众型还是幕后型要有依据:太阳或 10 宫主强且在角宫、AL 或 A10 落角宫、10 宫或命宫有入旺入庙星、`traditional_yogas` 有大格局,偏公众;10 宫主落 12 宫且无上述信号,才偏幕后。没有依据就不写这一句。不写「出头慢、越往后越稳、靠专业交付」这类人人适用的话,除非能指出具体盘面。",
|
||||
CAREER_FIELD_ASK_RULE,
|
||||
"必看:D1 10 宫与 10 宫主、AmK;卡上 d9 段确认 10 宫主与 AmK 的旺弱、Vargottama、D1/D9 反转;D10 上升与 10 宫;AL 与 A10;10 宫 SAV 与木星、土星所在宫的 SAV。",
|
||||
"时间:Vimshottari(MD/AD/PD)与 Narayana 双轨同向才谈应期,看大运主与 10 宫、10 宫主、D10 的关系;每颗星先按功能吉凶定性。",
|
||||
"分三层说,不得合成一句「事业机会」:①机会出现(消息、邀约、初步接洽)②成形(合同、合作、长期项目)③公开落地(发布、到账、被看见、名声)。",
|
||||
"禁写:本命承诺弱时,不得因一段大运或一次行运断言「事业必成」;不得把接触窗写成落地窗。",
|
||||
"AL 落第几宫要说出来(落 10 宫 = 公众形象就是事业);10 宫主、AmK 的受冲按通用读法。",
|
||||
"AL 落第几宫要说出来(说明名声和外界印象这条线有没有力量,不据此断定公众型或幕后型);10 宫主、AmK 的受冲按通用读法。",
|
||||
"卡外按需补取一次:Karakamsha、宫主链、D1→D9→D10 联动、Argala、Chara 大运;KP 精确宫头仍 blocked,只作参考、不作依据。",
|
||||
],
|
||||
marriage: [
|
||||
|
||||
@@ -382,6 +382,21 @@ const ANSWER_FROM_EVIDENCE = "拿到本轮计算结果后直接写给用户的
|
||||
*/
|
||||
export const AFFLICTION_RANGE_RULE = "同一个人或同一件事有两个及以上受冲信号:先说这条线有压力或距离的迹象(括号里写是哪几条),再说现实里可能是什么,给一个范围(例:「现实里可能是分开、离得远,也可能只是关系紧、话少」);不替用户断定他自己更清楚的事实(父母在不在身边、几段婚姻或感情、有没有病),也不反过来写「有分量」「站得住」「不是缺位」「底子不差」「关系稳」「能走下去」;这一段末尾用一句话请用户说说实际情况,全篇这类请求最多一处。";
|
||||
|
||||
/**
|
||||
* Career answers (product decision 2026-10-02 on TASK-consult-career-yoga-
|
||||
* functional-20261002, BUG-1176: "don't guess the field — ask"). The chart
|
||||
* cannot separate a footballer from a consultant or a public figure from a
|
||||
* back-office one (the 10th-house system of the backtest celebrities read as
|
||||
* analysis / advice for actors, athletes and presidents alike), so the answer
|
||||
* talks about strength, resistance and timing and asks what the user does.
|
||||
* Same principle as AFFLICTION_RANGE_RULE. Defined here only; the career
|
||||
* checklist quotes it.
|
||||
*/
|
||||
export const CAREER_FIELD_ASK_RULE = "事业题只讲盘上的力量、阻力和时间:哪几颗星、哪几个宫给事业撑力,阻力在哪,哪段时间推进;不替用户断定他做哪一行、是公众型还是幕后型(盘分不出,用户自己更清楚,同受冲规则);不写「出头慢」「越往后越稳」「靠专业交付」这类人人适用的话,除非能指出具体盘面;事业这一段末尾用一句话问用户实际做什么(例:「你现在具体做哪一行、什么角色,告诉我一句,我按你的实际工作再看。」),这一句就是全篇唯一一处请用户说实际情况,受冲那段不再另问。";
|
||||
|
||||
/** BUG-1176: the user states their work in a follow-up; read the chart relative to it. */
|
||||
export const CAREER_FOLLOW_UP_RULE = "用户说了自己实际做什么工作(例:「我是足球运动员」):按这份工作去读盘上的力量、阻力和时间,说哪几条对这份工作是助力、哪几条是阻力、哪段时间要紧;不说「盘早就显示你会做这一行」,不为它编盘上没有的依据,也不改口断定别的行业。";
|
||||
|
||||
/**
|
||||
* What each per-person section says (TASK-consult-no-presupposition-and-
|
||||
* backtest-20261001 D1/D2/D7, BUG-1164; replaces 「这个人是什么样、你们怎么
|
||||
@@ -431,6 +446,7 @@ export function followUpAnswerShapeInstruction(): string {
|
||||
ANSWER_FROM_EVIDENCE,
|
||||
"这是追问轮:本会话前面已经写过完整解读。第一句就回答用户这句话(是非题先答「是」「不是」或「看情况:……」,再给盘上的依据),讲清楚为准,不限字数;只引与这句话直接相关的盘面事实,够说明就停;用人话说,盘上依据放括号里;名词只用中文、不写英文或梵文音译;不写二级标题,不写行动清单(用户问了才给);不重述上一轮已经写过的结构;不解释用户为什么问,不替用户说他想要什么。",
|
||||
FOLLOW_UP_CORRECTION_RULE,
|
||||
CAREER_FOLLOW_UP_RULE,
|
||||
`只有用户明确换了领域或要求完整看一下,才回到完整形状:口语开场、按对象分段,再接二级标题(## ${REPORT_HEADING.support}、## ${REPORT_HEADING.timing}、## ${REPORT_HEADING.action})。`,
|
||||
"不要写「统一参数与原始结构」,不要写技法审计表,不要写思考过程清单,不要复述内部 JSON 字段。",
|
||||
].join("");
|
||||
|
||||
@@ -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