feat(narayana-rath): follow book p.43 for dual lords and node years (BUG-1227~1229)
Independent Staging Quality Gate / validate (push) Failing after 16m17s
Independent Staging Quality Gate / publish (push) Skipped

Round-7 option A is text-first, so Scorpio and Aquarius lords, the Ketu-only degree reversal, and node exaltation years now live in the Rath display layer. Scoring files stay unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-10-04 18:37:34 +08:00
co-authored by Cursor
parent 64c652eea2
commit baf4ae8b34
15 changed files with 604 additions and 84 deletions
@@ -592,7 +592,7 @@ function baseNatal(natal: Record<string, unknown>, gaps: string[]) {
* report. Product 2026-10-03: card budget 12,500, with the method checklist
* 18,500 (was 12,000 / 18,000, BUG-1160/1161).
*/
const RATH_MD_CARD_KEYS = ["sign", "start_age", "end_age"] as const;
const RATH_MD_CARD_KEYS = ["sign", "start_age", "end_age", "dual_lord_basis", "dual_lord_basis_en"] as const;
function baseTiming(timing: Record<string, unknown>, gaps: string[]) {
const sub = record(timing.dasha_sub_periods);
+2 -1
View File
@@ -350,7 +350,8 @@ const timingKeys = new Set([
"algorithmlabel",
// BUG-1218: the Sanjay Rath Narayana beside it (display only): label, start
// sign, deciding level and the running MD.
"rath", "seedsign", "strengthleveldecided",
// BUG-1227: Scorpio / Aquarius MDs also carry the one dual-lord sentence.
"rath", "seedsign", "strengthleveldecided", "duallordbasis", "duallordbasisen",
]);
const validationKeys = new Set([
@@ -43,12 +43,18 @@ function assertRathMd(workflow: Json, domain: ConsultationDomain, where: string)
const timing = card(workflow, domain).base.timing as Json;
const shown = timing.narayana_rath as Json;
assert.ok(shown, `${where} narayana_rath`);
// Short form only: label, start sign, running MD sign and ages (red line 2).
// Short form: label, start sign, running MD sign and ages. Scorpio / Aquarius
// also carry the one dual-lord sentence (round-7, BUG-1227).
assert.deepEqual(Object.keys(shown), ["algorithm", "seed_sign", "md"], where);
assert.equal(shown.algorithm, rath.algorithm_label);
assert.equal(shown.algorithm, "Sanjay Rath 版(并列参考,未进打分与时间轴结论)");
assert.equal(shown.algorithm, "Sanjay Rath 版(并列参考,未进打分与时间轴结论;按原书 p.43 正文(第七轮裁定))");
assert.equal(shown.seed_sign, rath.seed_sign);
assert.deepEqual(shown.md, { sign: md.sign, start_age: md.start_age, end_age: md.end_age }, where);
const expectedMd: Json = { sign: md.sign, start_age: md.start_age, end_age: md.end_age };
if (typeof md.dual_lord_basis === "string") {
expectedMd.dual_lord_basis = md.dual_lord_basis;
expectedMd.dual_lord_basis_en = md.dual_lord_basis_en;
}
assert.deepEqual(shown.md, expectedMd, where);
// No sub-periods on the card.
assert.equal(JSON.stringify(shown).includes("antardasha"), false, where);
// The legacy Narayana is unchanged and still labelled.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long