feat(skill): add adhana scaffold workflow
This commit is contained in:
@@ -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
|
||||
|
||||
不要先追求“所有古典分歧一次做完”;先把最短闭环版本做出来,再逐条加传统变体。
|
||||
@@ -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.",
|
||||
],
|
||||
}
|
||||
@@ -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"]
|
||||
Reference in New Issue
Block a user