fix(consult): marriage card drops the 7th-house "(对宫主)" twin rows to stay inside the 12,000-character budget (BUG-1185)

For house 7 the event lord and the opposite lord are the same planet, so
every double-transit hit arrived twice. With the corrected aspect count the
Taylor marriage turn reached 12,040 characters (budget 12,000, test
consult-condensed-checklist "size"). The card now keeps the "(宫主)" row and
drops its "(对宫主)" twin; values stay engine values (the "nothing rewritten"
contract holds), the budget assertion is unchanged (BUG-1155 precedent:
compress the format, not the budget). Taylor marriage 12,040 -> under 11,922.

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:
Jesse_Chen
2026-10-02 14:50:35 +08:00
co-authored by Claude Opus 5.5
parent 79efaf83f4
commit 8ae4cef7a6
2 changed files with 22 additions and 2 deletions
+14 -1
View File
@@ -378,6 +378,19 @@ function copy(value: unknown): Json | undefined {
return value !== undefined && isJson(value) ? structuredClone(value) : undefined;
}
// For house 7 the engine's event-house lord and opposite-house lord are the
// same planet, so each hit arrives twice ("X(宫主)" and "X(对宫主)") with the
// same layer and PAC. Keep the "(宫主)" row and drop its twin: the card keeps
// engine values only, and the 7th lord is the opposite lord by definition
// (BUG-1185: the corrected aspect count adds 7th-house rows).
function dropOppositeLordTwins(rows: JsonRecord[]): JsonRecord[] {
const normalized = (row: JsonRecord) => JSON.stringify({
...row, target: typeof row.target === "string" ? row.target.replaceAll("(对宫主)", "(宫主)") : row.target,
});
const plain = new Set(rows.filter((row) => !String(row.target ?? "").includes("(对宫主)")).map(normalized));
return rows.filter((row) => !String(row.target ?? "").includes("(对宫主)") || !plain.has(normalized(row)));
}
function pickKeys(source: unknown, keys: readonly string[]): JsonRecord {
const from = record(source);
const out: JsonRecord = {};
@@ -857,7 +870,7 @@ function domainSection(
const ul = pickKeys(karakas.UL, KARAKA_TARGET_KEYS);
section.double_transit = {
...(typeof double.date === "string" ? { date: double.date } : {}),
house_7: conclusions.filter((row) => row.house === 7).map((row) => pickKeys(row, DOUBLE_TRANSIT_ROW_KEYS)),
house_7: dropOppositeLordTwins(conclusions.filter((row) => row.house === 7).map((row) => pickKeys(row, DOUBLE_TRANSIT_ROW_KEYS))),
...(nonEmpty(dk) ? { DK: dk } : {}),
...(nonEmpty(ul) ? { UL: ul } : {}),
...(typeof record(karakas.DK).method === "string" ? { karaka_method: record(karakas.DK).method as string } : {}),
@@ -162,8 +162,15 @@ test("marriage: 5H / 5L, day / night, Punarphoo, Double Transit on 7H / 7L / DK
claim_boundary: punarphoo.claim_boundary,
}, `${where} Punarphoo`);
const double = layers.double_transit as Json;
const seventh = (double.conclusions as Json[]).filter((row) => row.house === 7)
// 原值: 引擎第 7 宫每一行原样上卡
// 新值: 与某行只差「(对宫主)」/「(宫主)」、其余字段相同的「(对宫主)」行不上卡(保留「(宫主)」那一行)
// 原因: 第 7 宫的事件宫主与对宫主是同一颗星,两行重复;BUG-1185 相位改从 1 数后第 7 宫命中变多,
// 泰勒婚姻轮超出 12,000 字符预算 40 字,按 BUG-1155 先例压缩格式、不改预算断言;卡上仍只放引擎原值
const rows = (double.conclusions as Json[]).filter((row) => row.house === 7)
.map((row) => pick(row, ["layer", "target", "strength", "jupiter_pac", "saturn_pac"]));
const asLord = (row: Json) => JSON.stringify({ ...row, target: String(row.target).replaceAll("(对宫主)", "(宫主)") });
const plainKeys = new Set(rows.filter((row) => !String(row.target).includes("(对宫主)")).map(asLord));
const seventh = rows.filter((row) => !String(row.target).includes("(对宫主)") || !plainKeys.has(asLord(row)));
assert.deepEqual(dig(section.double_transit, "house_7"), seventh, `${where} 7H / 7L double transit`);
for (const key of ["DK", "UL"]) {
assert.deepEqual(