feat(consult): annual and timing turns get the shared reading and annual list (product budget decision 2026-10-02)
Annual / timing single-domain turns take the career / marriage / wealth budget: contract + card <= 12,000, total with the checklist <= 18,000. CONSULT_READING_BUDGET_BLOCKED removed; size assertions and the pinned blocker test changed (原值/新值/原因 in the tests and brief 2's progress record); BUG-1160/1161 resolved, BLOCKED.md entry struck through. 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
071a196d11
commit
ec06d422d3
@@ -65,20 +65,10 @@ const domainMethodology: Readonly<Record<ConsultationDomain, { strictRoute: stri
|
||||
children: { strictRoute: "consult-children", eventJudgment: null },
|
||||
};
|
||||
|
||||
/**
|
||||
* BLOCKED on a product decision (TASK-consult-affliction-reading-20261001,
|
||||
* BUG-1160/1161): a single-domain annual or timing turn is already within a few
|
||||
* hundred characters of the 12,000-character model-visible ceiling asserted by
|
||||
* consult-condensed-checklist-20260927 and consult-evidence-card-20260927
|
||||
* (annual up to 11,918 before this brief). The shared reading (733 characters
|
||||
* as a section) and the annual list (334) would take annual to 12,979 and timing
|
||||
* to 12,257, and those assertions are not this brief's to change. Until the
|
||||
* product re-decides the ceiling, a turn whose plan holds only these domains
|
||||
* keeps the pre-brief method: no shared reading, and annual's list is not
|
||||
* delivered (annual stays in domains_without_strict_checklist). Remove a domain
|
||||
* from this set once its budget is decided.
|
||||
*/
|
||||
export const CONSULT_READING_BUDGET_BLOCKED: ReadonlySet<ConsultationDomain> = new Set(["annual", "timing"]);
|
||||
// Annual and timing single-domain turns used to skip the shared reading and the
|
||||
// annual list on a 12,000-character ceiling (BUG-1160/1161). Product decision
|
||||
// 2026-10-02: they take the career / marriage / wealth budget instead (contract
|
||||
// + card <= 12,000, total with the checklist <= 18,000), so every turn gets both.
|
||||
|
||||
/** Domains whose list was written by the affliction-reading brief rather than condensed from the router. */
|
||||
const BRIEF_WRITTEN_DOMAINS: ReadonlySet<ConsultationDomain> = new Set([
|
||||
@@ -209,17 +199,13 @@ export function consultationMethodologyForDomains(
|
||||
};
|
||||
|
||||
// Once per turn, before anything else (T1), however many domains it plans.
|
||||
if (unique.some((domain) => !CONSULT_READING_BUDGET_BLOCKED.has(domain))) {
|
||||
push(CONDENSED_SHARED_READING_TITLE, CONDENSED_SHARED_READING_SOURCE, sharedConsultationReading());
|
||||
}
|
||||
push(CONDENSED_SHARED_READING_TITLE, CONDENSED_SHARED_READING_SOURCE, sharedConsultationReading());
|
||||
push("Shared mandatory baseline", ROUTER_FILE, markdownSection(router, SHARED_BASELINE_HEADING));
|
||||
|
||||
const withoutChecklist: ConsultationDomain[] = [];
|
||||
for (const domain of unique) {
|
||||
const { strictRoute, eventJudgment } = domainMethodology[domain];
|
||||
const condensed = BRIEF_WRITTEN_DOMAINS.has(domain) && CONSULT_READING_BUDGET_BLOCKED.has(domain)
|
||||
? null
|
||||
: condensedConsultationChecklist(domain, { gender });
|
||||
const condensed = condensedConsultationChecklist(domain, { gender });
|
||||
if (condensed) {
|
||||
push(
|
||||
`${consultationDomainDefinition(domain).label} · ${strictRoute} · 普通对话精简清单`,
|
||||
|
||||
@@ -16,10 +16,7 @@ import {
|
||||
CONSULT_BRIEF_CHECKLIST_SOURCE,
|
||||
CONSULTATION_CONDENSED_CHECKLISTS,
|
||||
} from "../src/lib/consultation-condensed-checklist.ts";
|
||||
import {
|
||||
CONSULT_READING_BUDGET_BLOCKED,
|
||||
consultationMethodologyForDomains,
|
||||
} from "../src/lib/consultation-methodology.ts";
|
||||
import { consultationMethodologyForDomains } from "../src/lib/consultation-methodology.ts";
|
||||
import {
|
||||
consultationDomainDefinition,
|
||||
consultationDomainIds,
|
||||
@@ -43,7 +40,10 @@ const golden = JSON.parse(readFileSync(
|
||||
const titles = (domains: ConsultationDomain[]) => consultationMethodologyForDomains(domains)!.sections.map((section) => section.title);
|
||||
|
||||
test("T1: the shared reading is the first section, once per turn, whatever the plan", () => {
|
||||
for (const domain of consultationDomainIds.filter((id) => !CONSULT_READING_BUDGET_BLOCKED.has(id))) {
|
||||
// 原值: consultationDomainIds.filter((id) => !CONSULT_READING_BUDGET_BLOCKED.has(id))(年运、时运除外)
|
||||
// 新值: 全部 12 个领域
|
||||
// 原因: 产品 2026-10-02 决定年运 / 时运按事业 / 婚姻 / 财富同口径计字数(BUG-1160/1161 解除)
|
||||
for (const domain of consultationDomainIds) {
|
||||
const list = titles([domain]);
|
||||
assert.equal(list[0], CONDENSED_SHARED_READING_TITLE, domain);
|
||||
assert.equal(list.filter((title) => title === CONDENSED_SHARED_READING_TITLE).length, 1, domain);
|
||||
@@ -62,16 +62,23 @@ test("T1: the shared reading is the first section, once per turn, whatever the p
|
||||
assert.equal(CONDENSED_SHARED_READING_LINES.length, 7);
|
||||
});
|
||||
|
||||
test("T1/T2 budget blocker is pinned: a single annual or timing turn keeps its pre-brief method", () => {
|
||||
// BLOCKED on the 12,000-character ceiling (see CONSULT_READING_BUDGET_BLOCKED); this
|
||||
// test documents the gap so lifting it is a deliberate change.
|
||||
assert.deepEqual([...CONSULT_READING_BUDGET_BLOCKED].sort(), ["annual", "timing"]);
|
||||
assert.deepEqual(titles(["annual"]), ["Shared mandatory baseline"]);
|
||||
assert.deepEqual(consultationMethodologyForDomains(["annual"])!.domains_without_strict_checklist, ["annual"]);
|
||||
assert.deepEqual(titles(["timing"]), ["Shared mandatory baseline", "时运 · event-timing-strict"]);
|
||||
// 原值: test "T1/T2 budget blocker is pinned: a single annual or timing turn keeps its pre-brief method"
|
||||
// (年运单领域只有 Shared mandatory baseline、年运列在 domains_without_strict_checklist;时运无通用读法)
|
||||
// 新值: 年运、时运单领域轮第一段是通用读法;年运带本产品中文清单,时运带英文路由
|
||||
// 原因: 产品 2026-10-02 决定年运 / 时运字数口径同事业 / 婚姻 / 财富(契约 + 卡 ≤ 12,000,含清单 ≤ 18,000),阻塞解除
|
||||
test("annual and timing single-domain turns get the shared reading, and annual its list (budget decided 2026-10-02)", () => {
|
||||
assert.deepEqual(titles(["annual"]), [CONDENSED_SHARED_READING_TITLE, "Shared mandatory baseline", "年运 · consult-annual · 普通对话精简清单"]);
|
||||
const annual = consultationMethodologyForDomains(["annual"])!;
|
||||
assert.deepEqual(annual.domains_without_strict_checklist, []);
|
||||
assert.equal(annual.sections[2]!.source, CONSULT_BRIEF_CHECKLIST_SOURCE);
|
||||
for (const line of CONSULTATION_CONDENSED_CHECKLISTS.annual!) assert.ok(annual.sections[2]!.text.includes(line), line.slice(0, 20));
|
||||
assert.deepEqual(titles(["timing"]), [CONDENSED_SHARED_READING_TITLE, "Shared mandatory baseline", "时运 · event-timing-strict"]);
|
||||
});
|
||||
|
||||
test("T2: every domain section, in order, and no domain without a list (annual pending the budget)", () => {
|
||||
// 原值: 标题「…(annual pending the budget)」,annual 期望 "",年运 / 时运跳过
|
||||
// 新值: annual / timing 一并核对;annual 期望本产品清单标题
|
||||
// 原因: 产品 2026-10-02 字数口径决定(BUG-1160/1161 解除)
|
||||
test("T2: every domain section, in order, and no domain without a list", () => {
|
||||
const expected: Record<ConsultationDomain, string> = {
|
||||
career: "事业 · career-timing-strict · 普通对话精简清单",
|
||||
marriage: "关系 · relationship-timing-strict · 普通对话精简清单",
|
||||
@@ -82,13 +89,12 @@ test("T2: every domain section, in order, and no domain without a list (annual p
|
||||
family: "家庭 · consult-family · 普通对话精简清单",
|
||||
parents: "父母 · consult-parents · 普通对话精简清单",
|
||||
children: "子女 · consult-children · 普通对话精简清单",
|
||||
annual: "",
|
||||
annual: "年运 · consult-annual · 普通对话精简清单",
|
||||
timing: "时运 · event-timing-strict",
|
||||
general: "综合 · consult-general · 普通对话精简清单",
|
||||
};
|
||||
for (const domain of consultationDomainIds) {
|
||||
const methodology = consultationMethodologyForDomains([domain])!;
|
||||
if (CONSULT_READING_BUDGET_BLOCKED.has(domain)) continue;
|
||||
assert.deepEqual(methodology.sections.map((section) => section.title), [
|
||||
CONDENSED_SHARED_READING_TITLE, "Shared mandatory baseline", expected[domain],
|
||||
], domain);
|
||||
|
||||
@@ -167,7 +167,10 @@ test("only the consultation tool builds the methodology: reports and other surfa
|
||||
assert.deepEqual(condensedUsers, ["lib/consultation-methodology.ts"]);
|
||||
});
|
||||
|
||||
test("size: every single-domain turn stays within 12,000 characters, contract and checklist included", async () => {
|
||||
// 原值: 标题「every single-domain turn stays within 12,000 characters, contract and checklist included」;全部 12 个领域 total ≤ 12,000
|
||||
// 新值: 年运、时运按事业 / 婚姻 / 财富同口径:契约 + 卡 ≤ 12,000、含清单 total ≤ 18,000;其余领域 total 仍 ≤ 12,000
|
||||
// 原因: 产品 2026-10-02 决定(BUG-1160/1161):年运 / 时运单领域轮加通用读法与年运清单后约 12,980,原口径无余量
|
||||
test("size: single-domain turns stay within 12,000 characters with the checklist; annual and timing within 12,000 without it and 18,000 with it", async () => {
|
||||
const serverChart = {
|
||||
name: "public",
|
||||
toolInput: { year: 2000, month: 1, day: 1, hour: 0, minute: 0, city: "fixture", lat: 0, lon: 0, tz: 0, ayanamsa: "raman" },
|
||||
@@ -188,7 +191,13 @@ test("size: every single-domain turn stays within 12,000 characters, contract an
|
||||
const view = await tools["run-jyotish-consultation"].execute!({ question: "q", domains: [domain] } as never, { writer: { custom: async () => {} } } as never);
|
||||
const total = JSON.stringify(view).length;
|
||||
assert.equal(state.modelVisibleChars, total);
|
||||
assert.ok(total <= 12_000, `${chart.id}/${domain}: ${total}`);
|
||||
if (domain === "annual" || domain === "timing") {
|
||||
const contractAndCard = JSON.stringify({ ...(view as Json), methodology: undefined }).length;
|
||||
assert.ok(contractAndCard <= 12_000, `${chart.id}/${domain}: contract + card ${contractAndCard}`);
|
||||
assert.ok(total <= 18_000, `${chart.id}/${domain}: ${total}`);
|
||||
} else {
|
||||
assert.ok(total <= 12_000, `${chart.id}/${domain}: ${total}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -274,7 +274,10 @@ test("the 「本轮技法」 rows are exactly the rows the full result produced
|
||||
});
|
||||
|
||||
test("model-visible size falls to card scale; only the method checklist can push it past 12,000", async () => {
|
||||
const methodHeavy = new Set(["career", "marriage", "wealth"]);
|
||||
// 原值: new Set(["career", "marriage", "wealth"])
|
||||
// 新值: 加 annual、timing(契约 + 卡 ≤ 12,000,含清单 ≤ 18,000)
|
||||
// 原因: 产品 2026-10-02 决定年运 / 时运与事业 / 婚姻 / 财富同口径,通用读法与年运清单下发(BUG-1160/1161)
|
||||
const methodHeavy = new Set(["career", "marriage", "wealth", "annual", "timing"]);
|
||||
for (const chart of golden.charts) {
|
||||
for (const domain of consultationDomainIds) {
|
||||
const { view, state } = await runTool(chart.workflow, [domain]);
|
||||
|
||||
Reference in New Issue
Block a user