From 223a465781de3c1acbd081adad31fec912ee7e94 Mon Sep 17 00:00:00 2001 From: 732642856 <732642856@qq.com> Date: Fri, 26 Jun 2026 23:33:22 +0800 Subject: [PATCH] feat(skill): add adhana scaffold workflow --- ...ception_technique_gap_matrix_2026_06_26.md | 144 ++++++++++++++++++ scripts/adhana.py | 122 +++++++++++++++ tests/test_adhana.py | 60 ++++++++ 3 files changed, 326 insertions(+) create mode 100644 docs/research/adhana_conception_technique_gap_matrix_2026_06_26.md create mode 100644 scripts/adhana.py create mode 100644 tests/test_adhana.py diff --git a/docs/research/adhana_conception_technique_gap_matrix_2026_06_26.md b/docs/research/adhana_conception_technique_gap_matrix_2026_06_26.md new file mode 100644 index 00000000..05f6a6c0 --- /dev/null +++ b/docs/research/adhana_conception_technique_gap_matrix_2026_06_26.md @@ -0,0 +1,144 @@ +# Adhana / Nisheka / 受孕盘 技法缺口矩阵 + +日期:2026-06-26 +范围:基于 `/Users/wuyongnaren/文件仓库/印度占星文章/受孕/IMG_3216.JPG` 至 `IMG_3222.JPG` 六张截图,核对当前主仓 skill 是否已具备对应技法。 + +## 结论摘要 + +当前 skill **不具备完整的 Adhana / Nisheka / 受孕盘 专项体系**。 + +已有能力主要是基础零件: + +- D12 / Dwadasamsa +- Gulika / Maandi +- Tithi / Vara / Panchanga +- Ghati / Hora / Ghatika 时间单位 +- Special Lagnas(HL / GL / VL / PP / ViL) + +缺失的是把这些零件串成“从出生盘反推受孕盘”的专用 workflow、公式固化、案例验证与解释模板。 + +## 截图涉及的技法拆解 + +| 截图主题 | 技法/规则 | 当前状态 | 证据/落点 | 备注 | +|---|---|---|---|---| +| 受孕盘(2)总体概述 | Adhana / Nisheka / 受孕盘 专项体系 | 缺失 | 全仓未发现 `Adhana`/`Nisheka` 专门模块 | 只有零件,没有整套引擎 | +| 受孕盘(2)总体概述 | 273 天妊娠周期规则 | 缺失 | 未发现专门实现 | 截图里作为核心 shortcut 出现 | +| 受孕盘(2)总体概述 | 男女差异规则 | 缺失 | 未发现专门实现 | 需权威来源核实后接入 | +| 受孕盘(3) | Adhana Lagna(受孕盘上升) | 缺失 | 无 `Adhana Lagna` 命令/输出路径 | 当前只有 HL/GL/VL/PP/ViL | +| 受孕盘(4) | Adhana Candra(受孕盘月亮) | 缺失 | 无 `Adhana Candra` 命令/输出路径 | 当前只有出生盘 Moon 与 Panchanga | +| 受孕盘(4) | 通过 D12 反推受孕盘月亮 | 部分具备 | `scripts/varga.py`, `scripts/divisional_yoga.py` | 有 D12 计算,但没有“反推月亮” workflow | +| 受孕盘(5) | 通过受孕盘上升反推出生盘上升 | 缺失 | 无专门实现 | 截图强调 Badarayana / Narada 传承方法 | +| 受孕盘(5) | Ghati 数换算与上升点回推 | 部分具备 | `scripts/special_lagnas.py`, `scripts/jaimini.py` | 有 Ghati/Ghatika 基础,但不是受孕盘算法 | +| 受孕盘(5) | 7 宫 / Kendra 约束法 | 缺失 | 无专门实现 | 需要封装为规则链 | +| 受孕盘(6) | 步骤总览 / Shortcut 流程 | 缺失 | 无专门 workflow | 可以作为第一版实现目标 | +| 受孕盘(6) | LMP / EDD / 产期倒推 | 缺失 | 无专门实现 | 偏实务流程,适合单独模块 | +| 受孕盘(6) | 出生星期 / 日主日 / 日月差 Ghati 推断 | 部分具备 | `scripts/muhurta.py`, `scripts/tithi_lord.py` | 有 Vara/Tithi,但未串成受孕盘步骤 | +| 受孕盘(7) | 案例法 / 样本推演 | 缺失 | 无 benchmark / oracle case | 需后续建立真实或公开案例集 | +| 全部截图 | Gulika 参与受孕盘计算 | 已具备基础 | `scripts/prashna.py`, `_compute_one_chart.py` | 可作为受孕盘引擎输入件 | +| 全部截图 | D12 / Dwadasamsa | 已具备基础 | `scripts/varga.py`, `scripts/divisional_charts_extended.py` | 当前仅能计算,不会专项解释 | +| 全部截图 | Ghati / Ghatika 时间框架 | 已具备基础 | `scripts/special_lagnas.py`, `scripts/jaimini.py` | 后续应复用,不必重写 | + +## 当前可复用资产 + +### 1. D12 计算 + +- `scripts/varga.py` +- `scripts/divisional_yoga.py` +- `scripts/divisional_charts_extended.py` + +用途: +- 作为 Adhana Candra / 受孕盘月亮反推的基础件 + +### 2. Gulika / Maandi + +- `scripts/prashna.py` +- `scripts/_compute_one_chart.py` + +用途: +- 作为截图案例里受孕盘步骤的敏感点输入 + +### 3. Ghati / Ghatika / Special Lagnas + +- `scripts/special_lagnas.py` +- `scripts/jaimini.py` + +用途: +- 复用 Ghati / Hora / Ghatika 计时骨架 +- 不必重新写底层换算 + +### 4. Tithi / Vara / Panchanga + +- `scripts/muhurta.py` +- `scripts/tithi_lord.py` + +用途: +- 承接截图中“出生星期”“月亮度数”“Tithi 相关约束”的步骤化规则 + +## 真正缺的不是零件,而是四件事 + +1. `adhana.py` 或同等模块 +- 输入:出生时间、出生盘 Moon / Gulika / Asc / D12 +- 输出:Adhana Lagna、Adhana Candra、候选受孕窗口、规则解释链 + +2. 规则来源固化 +- 需要把截图中的 Badarayana / Narada / Saravali 等规则拆成结构化规则 +- 目前还只是文章级线索 + +3. benchmark / case +- 需要公开案例或至少内部样本,验证受孕盘反推是否稳定 + +4. interpretation template +- 即使算出来,也还缺“怎么讲”的解释模板 + +## 最高优先级落地方向 + +### P0 + +实现 `受孕盘步骤总览版`,先不追求全部细枝末节: + +- 输入出生盘 +- 输出: + - D12 + - Gulika + - Ghati-based sensitive timing + - 候选 Adhana Lagna + - 候选 Adhana Candra + - 规则链说明 + +### P1 + +补全截图中的: + +- 273 天规则 +- 7 宫 / Kendra 限制 +- LMP / EDD 反推辅助 + +### P2 + +做案例与解释模板: + +- 公开案例 benchmark +- “受孕盘”专题解释模板 + +## 直接回答“这些截图里的技法,我们有吗?” + +严谨回答: + +- **完整体系:没有** +- **底层零件:大部分有** +- **可立即复用的核心基础:D12 / Gulika / Ghati / Hora / Vara / Tithi** +- **真正缺口:Adhana/Nisheka 专项 workflow 与验证闭环** + +## 下一步建议 + +下一轮直接做: + +1. 建 `tests/test_adhana.py` +2. 写第一版 `scripts/adhana.py` +3. 先落地: + - D12-based candidate logic + - Ghati timing scaffold + - Gulika input + - explanatory trace + +不要先追求“所有古典分歧一次做完”;先把最短闭环版本做出来,再逐条加传统变体。 diff --git a/scripts/adhana.py b/scripts/adhana.py new file mode 100644 index 00000000..1f2f1fbb --- /dev/null +++ b/scripts/adhana.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""First-pass Adhana / conception workflow scaffold. + +This module does not claim final classical closure. It reuses existing skill +building blocks (D12, Gulika, special lagnas, Ghati-based timing sensitivity) +and exposes a structured trace for later classical rule hardening. +""" + +from __future__ import annotations + +from typing import Dict, Any + +from jaimini import calc_special_lagnas_precise +from prashna import calc_gulika_simple +from varga import calc_all_vargas + + +SIGNS = ['Aries','Taurus','Gemini','Cancer','Leo','Virgo', + 'Libra','Scorpio','Sagittarius','Capricorn','Aquarius','Pisces'] + + +def _norm(lon: float) -> float: + return lon % 360.0 + + +def _sign_name(sign_idx: int) -> str: + return SIGNS[sign_idx % 12] + + +def _point_payload(lon: float, source: str, note: str = "") -> Dict[str, Any]: + longitude = _norm(lon) + sign_idx = int(longitude / 30) % 12 + return { + "longitude": round(longitude, 4), + "sign_idx": sign_idx, + "sign": _sign_name(sign_idx), + "degree_in_sign": round(longitude - sign_idx * 30, 4), + "source": source, + "note": note, + } + + +def analyze_adhana_candidates(payload: Dict[str, Any]) -> Dict[str, Any]: + asc_lon = float(payload["asc_lon"]) + sun_lon = float(payload["sun_lon"]) + moon_lon = float(payload["moon_lon"]) + gulika_lon = float(payload.get("gulika_lon", calc_gulika_simple(asc_lon, sun_lon, int(payload.get("weekday", 0))))) + + year = int(payload["year"]) + month = int(payload["month"]) + day = int(payload["day"]) + hour = int(payload["hour"]) + minute = int(payload["minute"]) + second = int(payload.get("second", 0)) + lat = float(payload["lat"]) + lon = float(payload["lon"]) + tz = float(payload["tz"]) + + planet_lons = { + "Sun": sun_lon, + "Moon": moon_lon, + "Rahu": float(payload.get("rahu_lon", 0.0)), + "Ketu": float(payload.get("ketu_lon", 180.0)), + } + vargas = calc_all_vargas(planet_lons, asc_lon, [12]) + d12 = vargas.get("D12_Dwadashamsa", {}) + + asc_sign_idx = int(asc_lon / 30) % 12 + special = calc_special_lagnas_precise( + asc_sign_idx, + year, + month, + day, + hour, + minute + second / 60.0, + lat=lat, + lon=lon, + tz_offset=tz, + second=second, + ) + + gl_sign_idx = special["GL"]["sign_idx"] + hl_sign_idx = special["HL"]["sign_idx"] + d12_moon = d12.get("Moon", {}) + d12_moon_sign_idx = d12_moon.get("sign_idx", int(moon_lon / 30) % 12) + d12_moon_deg = d12_moon.get("degree_in_sign", moon_lon % 30) + d12_moon_lon = d12_moon_sign_idx * 30 + d12_moon_deg + + candidate_lagna_lon = gl_sign_idx * 30 + ((gulika_lon % 24.0) / 24.0) * 30.0 + candidate_moon_lon = _norm(d12_moon_lon + ((gulika_lon - asc_lon) % 360) / 12.0) + + return { + "system": "adhana_scaffold", + "status": "partial_scaffold", + "boundary": "This is not a final classical closure; it is a reusable Adhana scaffold built from validated skill components.", + "inputs": { + "asc_lon": asc_lon, + "sun_lon": sun_lon, + "moon_lon": moon_lon, + "gulika_lon": round(gulika_lon, 6), + "weekday": int(payload.get("weekday", 0)), + }, + "birth_d12": d12, + "special_lagnas": special, + "candidate_adhana_lagna": _point_payload( + candidate_lagna_lon, + "special_lagnas.GL", + note=f"GL sign {_sign_name(gl_sign_idx)} prioritized over HL {_sign_name(hl_sign_idx)} in scaffold mode.", + ), + "candidate_adhana_moon": _point_payload( + candidate_moon_lon, + "D12_moon_plus_gulika_arc", + note="Uses D12 Moon anchor plus a normalized Gulika/Asc arc fraction as first-pass scaffold.", + ), + "rule_trace": [ + "Reused existing D12 calculator instead of inventing a conception-specific divisional engine.", + "Reused precise special lagnas for Ghati-sensitive timing instead of new time math.", + "Reused Gulika as a conception-sensitive point input because the screenshot workflow repeatedly references it.", + "Returned candidate layers with explicit boundary text; no claim of final Adhana/Nisheka authority yet.", + ], + } diff --git a/tests/test_adhana.py b/tests/test_adhana.py new file mode 100644 index 00000000..7c2d37c6 --- /dev/null +++ b/tests/test_adhana.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""Regression tests for the first Adhana / conception workflow scaffold.""" + +from __future__ import annotations + +import os +import sys + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +SCRIPTS = os.path.join(ROOT, "scripts") +sys.path.insert(0, SCRIPTS) + +from adhana import analyze_adhana_candidates + + +def sample_birth_payload(): + return { + "asc_lon": 132.355025, + "sun_lon": 3.5226611111111112, + "moon_lon": 311.78995555555554, + "gulika_lon": 256.581676, + "weekday": 6, + "year": REDACTED_YEAR, + "month": 4, + "day": 17, + "hour": 14, + "minute": 45, + "second": 20, + "lat": 36.466667, + "lon": 114.2, + "tz": 8, + } + + +def test_adhana_scaffold_exposes_reusable_inputs_and_trace(): + result = analyze_adhana_candidates(sample_birth_payload()) + + assert result["system"] == "adhana_scaffold" + assert result["status"] == "partial_scaffold" + assert "rule_trace" in result + assert len(result["rule_trace"]) >= 3 + + +def test_adhana_scaffold_reuses_d12_gulika_and_special_lagnas(): + result = analyze_adhana_candidates(sample_birth_payload()) + + assert result["inputs"]["gulika_lon"] == 256.581676 + assert result["birth_d12"]["Moon"]["sign"] + assert result["special_lagnas"]["GL"]["sign"] + assert result["special_lagnas"]["HL"]["sign"] + + +def test_adhana_scaffold_surfaces_candidate_layers_without_claiming_finality(): + result = analyze_adhana_candidates(sample_birth_payload()) + + assert "candidate_adhana_lagna" in result + assert "candidate_adhana_moon" in result + assert result["candidate_adhana_lagna"]["source"] in {"special_lagnas.GL", "special_lagnas.HL"} + assert result["candidate_adhana_moon"]["source"] == "D12_moon_plus_gulika_arc" + assert "not a final classical closure" in result["boundary"]