panchang-ts 3.1.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,9 +42,11 @@ sources, and exposed through the public API. Click a row to jump to its usage ex
42
42
  | **Vimshottari Dasha** | Maha → Antar → Pratyantar (3-level) breakdown from birth | [↓](#12-vimshottari-dasha) |
43
43
  | **Personal Transits** | Chandra Balam, Tarabala (9-tara cycle), Sade Sati (Saturn arc) | [↓](#13-personal-transits) |
44
44
  | **Birth Chart (Kundli)** | Lagna (sidereal), Bhava under 3 house systems, D1 / D2 / D3 / D7 / D9 / D10 / D12 / D30 charts, Planetary Dignity | [↓](#14-birth-chart-kundli) |
45
- | **Compatibility & Doshas** | Ashtakoot Guna Milan (36-point), Mangal Dosha, Kaal Sarp Dosha (12 subtypes), Pitru Dosha | [↓](#15-compatibility--doshas) |
46
- | **Aspects & Strength** | Drishti (graha aspects), Shadbala (six-fold strength) | [↓](#16-aspects--strength) |
47
- | **Dasha Systems** | Vimshottari (Maha→Antar→Pratyantar), Ashtottari, Yogini, Chara (Jaimini) | [↓](#17-dasha-systems) |
45
+ | **Compatibility & Doshas** | Ashtakoot Guna Milan (36-point), Pathu Porutham (Tamil 10-fold), Mangal Dosha, Kaal Sarp Dosha (12 subtypes), Pitru Dosha | [↓](#15-compatibility--doshas) |
46
+ | **Aspects & Strength** | Drishti (graha aspects), Shadbala (six-fold strength), Ashtakavarga (Bhinnashtaka + Sarvashtaka), Yogas (25 named), Karakas, Bhava Bala, Argala | [↓](#16-aspects--strength) |
47
+ | **Annual & Sensitive Layers** | Varshaphala (Tajik annual chart + 27 Sahams), Tithi Pravesha, Arudha padas, Hora/Ghati/Bhava/Sripati lagnas, Upagrahas (Gulika, Mandi, Dhuma, Vyatipata, Parivesha, Indrachapa, Upaketu) | [↓](#16-aspects--strength) |
48
+ | **KP & Prashna** | KP sub-lord at any longitude, cuspal sub-lords (Placidus-KP), KP significators, Prashna (horary) chart | [↓](#16-aspects--strength) |
49
+ | **Dasha Systems** | Vimshottari (Maha→Antar→Pratyantar), Ashtottari, Yogini, Chara (Jaimini), Narayan (Jaimini with padi direction) | [↓](#17-dasha-systems) |
48
50
  | **Muhurta Engine** | Configurable scoring + 13 stock occasions (vivah, griha pravesh, namakarana, …) | [↓](#18-muhurta-engine) |
49
51
  | **Calendar Conversion** | Gregorian↔Hindu, Kali Yuga year, Hindu New Year, yearly Ekadashi / Sankranti / festival listings | [↓](#19-calendar-conversion) |
50
52
  | **Localization** | English + Hindi (Devanagari) on every returned name | [↓](#20-localization) |
@@ -225,7 +227,7 @@ Pratah / Sayahna Sandhya, and nakshatra-keyed Amrit Kala.
225
227
  const r = getDailyPanchang(date, loc, { timezone: 330 })!;
226
228
 
227
229
  r.brahmaMuhurta; // two muhurtas before sunrise
228
- r.abhijitMuhurta; // 8th day-muhurta universally auspicious
230
+ r.abhijitMuhurta; // 8th day-muhurta, or null on Wednesday (Buddha-vara, Drik convention)
229
231
  r.vijayaMuhurta; // 11th day-muhurta — auspicious for success
230
232
  r.godhuliMuhurta; // "cow-dust" — sunset muhurta
231
233
  r.nishitaMuhurta; // midnight muhurta (Shivaratri)
@@ -530,9 +532,10 @@ ayanamsa positional arg.
530
532
 
531
533
  ## 15. Compatibility & Doshas
532
534
 
533
- **Ashtakoot Guna Milan** (36-point marriage compatibility), **Mangal Dosha** (Manglik
534
- with cancellations), **Kaal Sarp Dosha** (12 named subtypes by Rahu's house), and
535
- **Pitru Dosha** (ancestral affliction triggers).
535
+ **Ashtakoot Guna Milan** (36-point marriage compatibility), **Pathu Porutham**
536
+ (Tamil 10-fold counterpart see ["Pathu Porutham" in §16](#pathu-porutham-tamil-10-fold-marriage-matching)),
537
+ **Mangal Dosha** (Manglik with cancellations), **Kaal Sarp Dosha** (12 named subtypes
538
+ by Rahu's house), and **Pitru Dosha** (ancestral affliction triggers).
536
539
 
537
540
  ```typescript
538
541
  import {
@@ -600,14 +603,578 @@ const bala = computeShadbala(birth, loc);
600
603
  Both functions return additive surface — they do **not** modify the
601
604
  `getDailyPanchang` / birth-chart pipelines. Call them on demand.
602
605
 
606
+ ### Ashtakavarga
607
+
608
+ **Ashtakavarga** (BPHS Ch. 66) — per-graha 12-rashi bindu grids
609
+ (Bhinnashtaka) and the summed Sarvashtaka grid. Each cell counts how many
610
+ of the 8 contributors (the 7 visible grahas + the lagna) donate a benefic
611
+ dot to that rashi for the given receiver.
612
+
613
+ ```typescript
614
+ import { computeRashiChart, computeAshtakavarga } from 'panchang-ts';
615
+
616
+ const chart = computeRashiChart(birth, loc);
617
+ const av = computeAshtakavarga(chart);
618
+
619
+ av.sarvashtaka;
620
+ // → 12-cell grid (Mesha … Meena), each 0..56, total 336.
621
+
622
+ av.bhinnashtaka.Jupiter;
623
+ // → Jupiter's 12-cell grid; total = 56 (chart-invariant per BPHS).
624
+ // Other invariant totals: Sun=47, Moon=49, Mars=39, Mercury=54,
625
+ // Venus=52, Saturn=39.
626
+
627
+ // Opt in to Trikona + Ekadhipatya Sodhana reductions (BPHS Ch. 67):
628
+ const reduced = computeAshtakavarga(chart, { reductions: true });
629
+ reduced.reduced!.sarvashtaka; // post-reduction Sarvashtaka
630
+ reduced.reduced!.bhinnashtaka.Jupiter; // post-reduction Bhinnashtaka
631
+ ```
632
+
633
+ The BENEFIC_OFFSETS lookup table is the canonical BPHS Ch. 66 form used by
634
+ every public Ashtakavarga calculator (ProKerala, AstroSage, PyJHora). Rahu
635
+ and Ketu are not Ashtakavarga receivers or contributors in the classical
636
+ Parashara scheme.
637
+
638
+ ### Yogas (named classical combinations)
639
+
640
+ **Yogas** (BPHS Chs. 36–43) — detect ~25 classical combinations from a
641
+ natal chart against a fixed declarative catalog. Each entry returns a
642
+ `name`, a `type` (one of `mahapurusha | lunar | solar | raja | dhana |
643
+ special | cancellation | negative`), and one-or-more `reasons[]` strings
644
+ describing why the rule matched.
645
+
646
+ ```typescript
647
+ import { computeRashiChart, computeNavamsa, computeYogas } from 'panchang-ts';
648
+
649
+ const chart = computeRashiChart(birth, loc);
650
+ const yogas = computeYogas(chart);
651
+ // → [{ name: 'Gajakesari', type: 'lunar',
652
+ // reasons: ['Jupiter in 4th from Moon (kendra)'] }, …]
653
+
654
+ // Filter by type — restricts evaluation to a subset of the catalog.
655
+ const raja = computeYogas(chart, { types: ['raja', 'dhana'] });
656
+
657
+ // Vargottama needs the D9 — pass it via options.
658
+ const d9 = computeNavamsa(birth, loc);
659
+ const all = computeYogas(chart, { navamsa: d9 });
660
+ ```
661
+
662
+ The catalog covers Pancha Mahapurusha (Ruchaka / Bhadra / Hamsa / Malavya
663
+ / Sasha), lunar yogas (Gajakesari, Sunapha, Anapha, Durudhura, Kemadruma),
664
+ solar yogas (Budha-Aditya, Veshi, Vasi, Ubhayachari), Raja yogas (generic
665
+ kendra/trikona-lord rule, Dharma-Karmadhipati, Vipareeta Raja, Lakshmi),
666
+ Dhana yogas (2–11, 5–9, Vasumati), Vargottama, Yogakaraka, Neecha Bhanga,
667
+ and Daridra. Yoga names are English/transliterated proper nouns and are
668
+ intentionally **not** locale-resolved — `'Gajakesari'` reads the same in
669
+ `'en'` and `'hi'`.
670
+
671
+ Adding a new yoga is a data-only change in
672
+ [src/jyotish/yogasCatalog.ts](src/jyotish/yogasCatalog.ts) — the engine
673
+ is a thin loop over the catalog. Each rule receives the chart plus
674
+ precomputed `dignity` / `aspects` (and optionally a D9 chart) and returns
675
+ a `YogaMatch | null`.
676
+
677
+ ### Jaimini Karakas
678
+
679
+ **Karakas** (Jaimini *Upadesa Sutras* Ch. 1, Parashara variant) — the 7
680
+ Chara Karakas ranked by descending degree-in-rashi of the visible grahas.
681
+ Atmakaraka (highest) signifies the Self; Darakaraka (lowest) signifies
682
+ spouse.
683
+
684
+ ```typescript
685
+ import { computeRashiChart, computeJaiminiKarakas } from 'panchang-ts';
686
+
687
+ const chart = computeRashiChart(birth, loc);
688
+ const k = computeJaiminiKarakas(chart);
689
+ k.Atmakaraka; // graha at the highest degree-in-rashi (e.g. 'Saturn')
690
+ k.Amatyakaraka; // 2nd-highest
691
+ k.Darakaraka; // graha at the lowest degree-in-rashi
692
+ ```
693
+
694
+ The 7 visible grahas are ranked — Rahu and Ketu are not included (this is
695
+ the **7-Karaka Parashara variant**, not the reversed-Rahu 8-Karaka Jaimini
696
+ variant). On the rare exact tie in degree-in-rashi, the canonical order
697
+ Sun → Moon → Mars → Mercury → Jupiter → Venus → Saturn breaks the tie
698
+ (stable sort) — the earlier graha wins the more-significant Karaka role.
699
+
700
+ Karaka names are English/transliterated proper nouns and intentionally
701
+ **not** locale-resolved.
702
+
703
+ ### Bhava Bala
704
+
705
+ **Bhava Bala** (BPHS Ch. 27) — four-source house strength for the 12 bhavas
706
+ of a natal chart, in Virupas (60 V = 1 Rupa). Built on top of `computeShadbala`
707
+ — the natural-strength table, drishti weights, and benefic/malefic
708
+ classification are all shared.
709
+
710
+ ```typescript
711
+ import { computeBhavaBala } from 'panchang-ts';
712
+
713
+ const bhavaBala = computeBhavaBala(birth, loc);
714
+ bhavaBala.houses.length; // 12 (one entry per bhava, index 0 = bhava 1)
715
+ bhavaBala.houses[0].total; // 1st-bhava total in Virupas
716
+ bhavaBala.houses[9].bhavadhipati; // 10th-bhava lord's Shadbala total
717
+ // → each entry: { bhavadhipati, dik, drik, sthana, total }
718
+ ```
719
+
720
+ `bhavadhipati` is the total Shadbala of the rashi-lord of the bhava cusp;
721
+ `dik` is a fixed directional value from a simplified cardinal-anchor table
722
+ (cardinal bhavas anchor at 60 / 0 / 15 / 30 V; intermediates linearly
723
+ interpolated around the wheel — not the canonical BPHS Ch. 27 numbers);
724
+ `drik` is the net aspect strength on the cusp from the 7 visible grahas
725
+ (benefics +, malefics −, clamped ≥ 0); `sthana` sums the natural strength
726
+ of grahas occupying the bhava (Mercury counted as benefic per BPHS — the
727
+ "associated benefic" nuance is intentionally out of scope). Rahu and Ketu
728
+ do not contribute. `total` is the arithmetic sum of the four components.
729
+
730
+ ### Varshaphala (Tajik annual horoscope)
731
+
732
+ **Varshaphala** is the Tajik solar-return chart for a given age of the
733
+ native, with the classical analytical layer — Muntha, year lord
734
+ (Varsha Pati), and the 27 core Sahams — already computed.
735
+
736
+ ```typescript
737
+ import { computeVarshaphala } from 'panchang-ts';
738
+
739
+ const birth = new Date('1995-08-15T05:30:00Z');
740
+ const loc = { latitude: 28.6139, longitude: 77.2090 };
741
+
742
+ const varsha = computeVarshaphala(birth, 30, loc); // 30th solar return
743
+ varsha.solarReturnInstant; // exact UTC moment Sun returns to natal lon
744
+ varsha.varshaLagna.rashi.name; // ascendant rashi at the SR instant
745
+ varsha.muntha.rashi; // (natalLagnaRashi + 30) mod 12
746
+ varsha.muntha.lord; // rashi-lord of muntha rashi
747
+ varsha.muntha.house; // muntha's house from varsha lagna (1..12)
748
+ varsha.yearLord; // strongest of 4 candidates by Shadbala
749
+ varsha.isDayBirth; // Sun above horizon at SR instant?
750
+
751
+ // 27 Sahams (Punya, Vidya, …, Tapas) — each: { longitude, rashi, rashiName, house }
752
+ varsha.sahams.Punya.longitude;
753
+ varsha.sahams.Punya.house; // Punya's house from varsha lagna
754
+ varsha.sahams.Vivaha.rashi; // Vivaha (marriage) Saham rashi
755
+ ```
756
+
757
+ **Solar-return search.** A Newton-style refinement around `birth +
758
+ N × 365.25636 days` finds the UTC instant where sidereal Sun returns
759
+ to its natal longitude (within 0.0001° / ~9 arcseconds). Convergence
760
+ is 3–5 iterations on cooperative inputs.
761
+
762
+ **Year lord (Varsha Pati).** Picked as the planet with the highest
763
+ total Shadbala among:
764
+ 1. Varsha lagna lord
765
+ 2. Muntha lord
766
+ 3. Lord of the Sun's rashi at the varsha instant
767
+ 4. Triraashi Pati (3-rashi-trine ruler) of the varsha lagna's element,
768
+ per the Tajik day/night table (fire→Sun day / Jupiter night;
769
+ earth→Venus / Moon; air→Saturn / Mercury; water→Venus / Mars)
770
+
771
+ **Sahams scope.** This is the **27-Saham core set** — Punya, Vidya,
772
+ Yasas, Mitra, Karma, Vivaha, Putra, Roga, Marana, Rajya, Raja, Bandhu,
773
+ Dharma, Gnati, Apamrityu, Bhratri, Matri, Pitri, Sama, Bandhana,
774
+ Karyasiddhi, Vyapara, Sastra, Asha, Labha, Susha, Tapas. The extended
775
+ 50-Saham list (Mahaprasna, Adhana, Krodha, Kali, …) is deferred to a
776
+ later release. Day/night X-Y operand swap follows **Neelakantha**'s
777
+ *Tajika Neelakanthi*; 9 Sahams (Punya, Vidya, Karma, Putra, Roga,
778
+ Gnati, Bhratri, Matri, Pitri) flip on night birth. Other Tajik
779
+ commentators (Hari Hara) define different swap subsets — documented
780
+ in [src/jyotish/sahamsTables.ts](src/jyotish/sahamsTables.ts).
781
+
782
+ **Sourcing:** Neelakantha *Tajika Neelakanthi* (1587 CE); B.V. Raman
783
+ *Annual Horoscope*; Sanjay Rath *Crux of Vedic Astrology* Tajik
784
+ appendix; PVR Narasimha Rao *Tajik notes* (Saptarishis Astrology).
785
+ Saham names are English/transliterated proper nouns and intentionally
786
+ **not** locale-resolved (same convention as Yoga names).
787
+
788
+ ### Tithi Pravesha (annual soli-lunar return)
789
+
790
+ **Tithi Pravesha** is the South-Indian annual chart cast at the moment
791
+ in year-N when *both* (a) the sidereal Sun is in its natal sidereal
792
+ sign **and** (b) the Sun-Moon angular separation equals the natal
793
+ separation. The tithi is preserved exactly — `praveshTithi` always
794
+ equals `natalTithi`.
795
+
796
+ ```typescript
797
+ import { computeTithiPravesha } from 'panchang-ts';
798
+
799
+ const tp = computeTithiPravesha(
800
+ new Date('1995-08-15T05:30:00Z'),
801
+ 30, // 30th annual cycle
802
+ { latitude: 28.6139, longitude: 77.2090 }, // New Delhi
803
+ );
804
+ tp.praveshInstant; // exact UTC moment
805
+ tp.natalTithi === tp.praveshTithi; // always true
806
+ tp.varshaLagna.rashi.name; // ascendant at pravesha
807
+ tp.planets; // 9-graha placements
808
+ tp.bhava.houses; // 12 cusps under configured house system
809
+ ```
810
+
811
+ **Algorithm.** The implementation follows **PVR Narasimha Rao's
812
+ redefinition** (Saptarishis Astrology) rather than the older calendar-
813
+ anniversary heuristic:
814
+
815
+ 1. Compute the natal Sun-Moon angular separation `Δ_natal`.
816
+ 2. Locate the **solar-return instant** for the requested year (re-uses
817
+ the Varshaphala Newton search).
818
+ 3. Newton-iterate on the Moon-Sun phase deviation until
819
+ `(Moon − Sun) mod 360°` equals `Δ_natal` to better than 0.0001°.
820
+ 4. If Sun's rashi at that instant differs from natal Sun's rashi
821
+ (closest tithi-match landed across a sign boundary), shift by one
822
+ synodic month (~29.5 days) toward the solar-return centre and
823
+ re-iterate. Adjacent tithi-matches are 29.53 days apart and the
824
+ Sun-in-natal-sign window is 30.4 days wide, so exactly one
825
+ neighbour falls in the natal sign for every fixture.
826
+
827
+ The pravesha instant can therefore be up to ~30 days before or after
828
+ the calendar anniversary depending on where the natal moon was in the
829
+ synodic cycle.
830
+
831
+ **Sourcing:** Sanjay Rath, *Tithi Pravesha* (srath.com); PVR Narasimha
832
+ Rao, *Re-Defining Tithi Pravesha Chart* (Saptarishis Astrology Vol. 8).
833
+
834
+ ### Arudha Lagna + 12 Arudha Padas
835
+
836
+ The **Arudha pada** of a bhava is the rashi reached by counting from the
837
+ bhava's lord the same number of houses as the lord is from the bhava
838
+ itself. Each Arudha is the *image / reflection* of its bhava — Bhava 1's
839
+ Arudha is **Arudha Lagna (AL)**, the social / public-facing self
840
+ (distinct from Lagna, which is the inner / soul-rooted self).
841
+
842
+ ```typescript
843
+ import { computeRashiChart, computeArudhas } from 'panchang-ts';
844
+
845
+ const chart = computeRashiChart(
846
+ new Date('1995-08-15T05:30:00Z'),
847
+ { latitude: 28.6139, longitude: 77.2090 },
848
+ );
849
+ const arudhas = computeArudhas(chart);
850
+ arudhas.length; // 12
851
+ arudhas[0]!.bhava; // 1 — this is Arudha Lagna (AL)
852
+ arudhas[0]!.arudhaRashi; // 0..11
853
+ arudhas[0]!.arudhaRashiName; // localized rashi name
854
+ arudhas[0]!.arudhaLord; // rashi-lord of arudha rashi
855
+ arudhas[6]!.bhava; // 7 — Darapada (spouse pada)
856
+ ```
857
+
858
+ **Algorithm.** Per Jaimini *Upadesa Sutras* Ch. 1 (Sanjay Rath
859
+ commentary):
860
+
861
+ 1. For each bhava `B`, find the rashi the bhava's lord *occupies*.
862
+ 2. Compute `D` = inclusive distance from the bhava to its lord (1..12,
863
+ so lord-in-own-bhava → D=1).
864
+ 3. Standard rule: count another `D` houses from the lord →
865
+ `arudha = (lordRashi + D − 1) mod 12`.
866
+ 4. **Two exceptions** to avoid the Arudha collapsing onto the bhava
867
+ itself or its 7th:
868
+ - `D == 1` (lord in own bhava) → Arudha = **10th** from lord
869
+ (`lordRashi + 9 mod 12`).
870
+ - `D == 7` (lord in 7th from bhava) → Arudha = **4th** from lord
871
+ (`lordRashi + 3 mod 12`).
872
+
873
+ `arudhaLord` is the rashi-lord of the *Arudha rashi itself* (not the
874
+ original bhava's lord) — useful for analysing the pada's significations
875
+ directly.
876
+
877
+ **Sourcing:** Jaimini, *Upadesa Sutras* Ch. 1; Sanjay Rath, *Jaimini
878
+ Maharishi's Upadesa Sutras* (commentary); BPHS Ch. 29.
879
+
880
+ ### Special Lagnas (Hora / Ghati / Bhava / Sripati)
881
+
882
+ Time-derived sensitive lagnas used in classical timing analysis. Each
883
+ advances at a different rate from the sunrise on or before the birth
884
+ instant.
885
+
886
+ ```typescript
887
+ import {
888
+ computeHoraLagna, computeGhatiLagna, computeBhavaLagna, computeSripatiLagna,
889
+ } from 'panchang-ts';
890
+
891
+ const birth = new Date('1995-08-15T05:30:00Z');
892
+ const loc = { latitude: 28.6139, longitude: 77.2090 };
893
+
894
+ const hora = computeHoraLagna(birth, loc); // 1 rashi / 1 hour from sunrise
895
+ const ghati = computeGhatiLagna(birth, loc); // 1 rashi / 1 ghatika (24 min)
896
+ const bhava = computeBhavaLagna(birth, loc); // 1 rashi / 5 ghatikas (2 hours)
897
+ const sripati = computeSripatiLagna(birth, loc); // Sripati cusp 1 = natal lagna
898
+ hora.rashi.name; // each returns a `LagnaInfo` with rashi / nakshatra / pada
899
+ ```
900
+
901
+ | Lagna | Rate | Period |
902
+ |-------|------|--------|
903
+ | Hora | 30°/hour (1 rashi / 1 hour) | 12 hours |
904
+ | Ghati | 75°/hour (1 rashi / 24 min) | 4 h 48 min |
905
+ | Bhava | 15°/hour (1 rashi / 2 hours) | 24 hours |
906
+ | Sripati | n/a (= natal lagna) | n/a |
907
+
908
+ > **Note.** Hora Lagna advances at 30°/hour (1 rashi / hour) per BPHS
909
+ > Ch. 4 and *Phaladeepika* Ch. 1 — twice the rate of Bhava Lagna,
910
+ > which advances at 15°/hour (1 rashi / 5 ghatikas). The two are
911
+ > numerically distinct timing anchors, not interchangeable. Sripati
912
+ > Lagna currently returns the natal ascendant (Sripati cusp-1 by
913
+ > construction); the bhava-midpoint form is a future extension.
914
+
915
+ **Sourcing:** BPHS Ch. 4; *Phaladeepika* Ch. 1; Sripati, *Sripati Paddhati*.
916
+
917
+ ### Upagrahas (sub-grahas as positions)
918
+
919
+ The 7 upagrahas are sensitive points used in Vedic and Tajik analysis.
920
+ The library returns each one as a **longitude** + rashi + house — the
921
+ position-form, distinct from Phase-2 Gulika *Kalam* (the time-form).
922
+
923
+ ```typescript
924
+ import { computeUpagrahas } from 'panchang-ts';
925
+
926
+ const u = computeUpagrahas(
927
+ new Date('1995-08-15T05:30:00Z'),
928
+ { latitude: 28.6139, longitude: 77.2090 },
929
+ );
930
+ u.gulika.longitude; // sidereal degrees
931
+ u.gulika.rashi; // 0..11
932
+ u.gulika.rashiName; // localized
933
+ u.gulika.house; // whole-sign from natal lagna
934
+ u.mandi.longitude; // Saturn-segment midpoint
935
+ u.dhuma.longitude; // Sun + 133°20'
936
+ u.upaketu.longitude; // Sun + ~150° (after the chain)
937
+ ```
938
+
939
+ **Gulika & Mandi.** Day birth: divide sunrise → sunset into 8 equal
940
+ segments; the day-lord rotation Sun → Moon → Mars → Mercury → Jupiter
941
+ → Venus → Saturn places Saturn at one segment per weekday. Gulika is
942
+ the **rising ascendant at the *start*** of Saturn's segment; Mandi is
943
+ the **rising ascendant at the *midpoint***. Night birth: same procedure
944
+ on the sunset → next-sunrise window, with the rotation starting from
945
+ the planet 5 weekdays from the day-lord (Phaladeepika Ch. 5).
946
+
947
+ **Sun-derived upagrahas.** Fixed offsets from sidereal Sun:
948
+
949
+ | Upagraha | Formula |
950
+ |----------|---------|
951
+ | Dhuma | `Sun + 133°20'` |
952
+ | Vyatipata | `360° − Dhuma` |
953
+ | Parivesha | `Vyatipata + 180°` |
954
+ | Indrachapa | `360° − Parivesha` |
955
+ | Upaketu | `Indrachapa + 16°40'` |
956
+
957
+ `Dhuma + Vyatipata ≡ 360°` and `Parivesha + Indrachapa ≡ 360°` are
958
+ structural invariants that hold for every chart.
959
+
960
+ **Sourcing:** BPHS Ch. 5; Sanjay Rath, *Brihat Nakshatra* (upagraha
961
+ section); Phaladeepika Ch. 5.
962
+
963
+ ### Argala (Jaimini intervention)
964
+
965
+ Per-bhava arc-influence rules from Jaimini *Upadesa Sutras* Ch. 1 and
966
+ BPHS Ch. 51. Planets in the 2nd, 4th, or 11th from a bhava form
967
+ **Argala** (intervention / help); planets in the 3rd, 10th, or 12th
968
+ form **Virodhargala** (counter-intervention).
969
+
970
+ ```typescript
971
+ import { computeRashiChart, computeArgala } from 'panchang-ts';
972
+
973
+ const chart = computeRashiChart(
974
+ new Date('1995-08-15T05:30:00Z'),
975
+ { latitude: 28.6139, longitude: 77.2090 },
976
+ );
977
+ const argala = computeArgala(chart);
978
+ argala[0]!.bhava; // 1
979
+ argala[0]!.argala; // PlanetPlacement[] in 2nd / 4th / 11th from lagna
980
+ argala[0]!.virodhargala; // PlanetPlacement[] in 3rd / 10th / 12th from lagna
981
+ ```
982
+
983
+ **Structural invariant.** Each planet contributes to **exactly 6 of
984
+ the 12 bhavas** — 3 Argala + 3 Virodhargala. The 2/4/11 and 3/10/12
985
+ offsets are mutually exclusive, so a planet's house position
986
+ deterministically partitions the bhava wheel into a 6-cell influence
987
+ set.
988
+
989
+ All 9 grahas (Sun..Saturn + Rahu + Ketu) participate. Benefic / malefic
990
+ distinction is not applied — the caller can filter the returned lists
991
+ by graha if their tradition requires it. The 5th-from-bhava ("primary
992
+ Argala") and 9th ("primary Virodhargala") are not included in this
993
+ simplified BPHS Ch. 51 form.
994
+
995
+ **Sourcing:** Jaimini, *Upadesa Sutras* Ch. 1; BPHS Ch. 51.
996
+
997
+ ### Pathu Porutham (Tamil 10-fold marriage matching)
998
+
999
+ Tamil/Kerala marriage compatibility test, scored across **10 koots**.
1000
+ Used instead of Ashtakoot in Tamil Nadu, Kerala, and parts of Karnataka.
1001
+ Each koot is binary-scored (pass / fail) per the AstroVed / Drik Tamil
1002
+ convention; the aggregate score is the count of passing koots in 0..10.
1003
+ Three koots (Yoni, Rajju, Vedha) are **strong vetoes** — if any fails,
1004
+ `recommended` flips to false regardless of the count.
1005
+
1006
+ ```typescript
1007
+ import { computePathuPorutham } from 'panchang-ts';
1008
+
1009
+ const result = computePathuPorutham(
1010
+ { rashi: 4, nakshatra: 9 }, // Boy: Magha / Leo
1011
+ { rashi: 0, nakshatra: 1 }, // Girl: Bharani / Aries
1012
+ );
1013
+ result.totalPasses; // 0..10
1014
+ result.recommended; // boolean (no veto + ≥5 passes)
1015
+ result.poruthams[4]!.name; // 'Yoni' (a veto-level koot)
1016
+ result.poruthams[8]!.veto; // true if Rajju fails
1017
+ ```
1018
+
1019
+ **Koot catalog:**
1020
+
1021
+ | Koot | Tests | Veto |
1022
+ |----------------|-----------------------------------------------------|:----:|
1023
+ | Dina | Boy→Girl nakshatra distance mod 9 ∈ {1, 3, 5, 7} | no |
1024
+ | Gana | Reuses Phase 29 NAKSHATRA_GANA — Manushya↔Rakshasa fails | no |
1025
+ | Mahendra | Distance ∈ {4, 7, 10, 13, 16, 19, 22, 25} | no |
1026
+ | Sthree Deergha | Boy→Girl nakshatra distance > 9 | no |
1027
+ | Yoni | Reuses Phase 29 NAKSHATRA_YONI / YONI_SCORE | yes |
1028
+ | Rashi | Distance not in doshic set ({2,12}, {6,8}) | no |
1029
+ | Rashyathipathi | Rashi-lord friendship (Naisargika Maitri) | no |
1030
+ | Vasya | Reuses Phase 29 RASHI_VASHYA / VASHYA_SCORE | no |
1031
+ | Rajju | Same Rajju (Pada/Kati/Nabhi/Kantha/Sira) fails | yes |
1032
+ | Vedha | Same Vedha pair fails | yes |
1033
+
1034
+ Pathu Porutham and Ashtakoot consume the same `NatalMoon` shape
1035
+ (`{ rashi, nakshatra }`) — call both side-by-side to surface both
1036
+ North-Indian and South-Indian compatibility views.
1037
+
1038
+ **Sources.** *Jathaka Tatva* (Tamil); AstroVed.com 10-Porutham reference;
1039
+ ProKerala's free Pathu Porutham implementation; drikpanchang.com Tamil
1040
+ porutham panel.
1041
+
1042
+ ### Narayan Dasha (Jaimini sign-dasha with padi direction)
1043
+
1044
+ Jaimini sign-based dasha that incorporates the **vishama-pada / sama-pada**
1045
+ parity rule per Sanjay Rath's *Narayana Dasa* (Sagar Publications). Cycle
1046
+ direction depends on which parity-class the lagna's rashi falls into:
1047
+
1048
+ - **Vishama-pada** lagna in {Aries, Taurus, Gemini, Libra, Scorpio,
1049
+ Sagittarius} → cycle proceeds **forward** (zodiacal).
1050
+ - **Sama-pada** lagna in {Cancer, Leo, Virgo, Capricorn, Aquarius,
1051
+ Pisces} → cycle proceeds **backward** (anti-zodiacal).
1052
+
1053
+ ```typescript
1054
+ import { computeNarayanDasha } from 'panchang-ts';
1055
+
1056
+ const narayan = computeNarayanDasha(
1057
+ new Date('1995-08-15T05:30:00Z'),
1058
+ { latitude: 28.6139, longitude: 77.2090 },
1059
+ );
1060
+ narayan.direction; // 'forward' | 'backward'
1061
+ narayan.startingRashi; // lagna rashi (0..11)
1062
+ narayan.mahaDashas[0]!.rashi; // same as startingRashi
1063
+ narayan.mahaDashas[0]!.lord; // sign-lord of starting rashi
1064
+ narayan.mahaDashas[0]!.years; // 7, 8, or 9 per modality
1065
+ ```
1066
+
1067
+ Years per rashi follow the same Movable 9 / Fixed 8 / Dual 7 scheme as
1068
+ Chara Dasha. The Mahadasha sequence covers ~96 years (sum of all 12
1069
+ rashi durations). Lord assignment is the rashi's natural lord (Mars for
1070
+ Aries / Scorpio, Venus for Taurus / Libra, etc.). Antardasha breakdown
1071
+ is not exposed — the Mahadasha alone is the dominant Jaimini timing
1072
+ layer for Narayan analysis.
1073
+
1074
+ **Difference from Chara Dasha** (already shipped): Chara always advances
1075
+ forward from lagna; Narayan applies the parity-based direction. For
1076
+ vishama-pada lagnas the two systems' Mahadasha sequence is identical.
1077
+
1078
+ **Sources.** Sanjay Rath, *Narayana Dasa* (Sagar Publications);
1079
+ *Jaimini Upadesa Sutras* Ch. 2.
1080
+
1081
+ ### KP sub-lord layer
1082
+
1083
+ K.S. Krishnamurti's KP-Paddhati uses a 9-fold subdivision of each
1084
+ nakshatra (243 sub-divisions across the zodiac), proportional to the
1085
+ Vimshottari dasha years of the 9 planets. The sub-lord at any longitude
1086
+ is one of the 9 KP planets (Sun..Saturn + Rahu + Ketu).
1087
+
1088
+ ```typescript
1089
+ import {
1090
+ computeKpSubLord, computeKpCuspalSubLords, computeKpSignificators,
1091
+ computeRashiChart,
1092
+ } from 'panchang-ts';
1093
+
1094
+ // 1. Sub-lord at any sidereal longitude.
1095
+ const info = computeKpSubLord(45.5); // 15°30' Taurus
1096
+ info.signLord; // 'Venus' (rashi lord of Taurus)
1097
+ info.starLord; // 'Moon' (nakshatra lord of Rohini)
1098
+ info.subLord; // KP sub-lord — depends on degree
1099
+
1100
+ // 2. Cuspal sub-lords for the 12 Placidus-KP cusps.
1101
+ const cusps = computeKpCuspalSubLords(
1102
+ new Date('1995-08-15T05:30:00Z'),
1103
+ { latitude: 28.6139, longitude: 77.2090 },
1104
+ );
1105
+ cusps.cusps[0]!.subLord; // sub-lord of cusp 1 (ascendant)
1106
+ cusps.cusps[6]!.subLord; // sub-lord of cusp 7 (descendant)
1107
+
1108
+ // 3. Significators — for each planet, the houses it signifies via the
1109
+ // 4-fold KP rule (occupant + star-lord-occupant + owner + star-lord-owner).
1110
+ const chart = computeRashiChart(birth, location);
1111
+ const sig = computeKpSignificators(chart);
1112
+ sig.byPlanet.Sun; // [houses Sun signifies]
1113
+ sig.byHouse[10]; // [planets that signify the 10th house]
1114
+ ```
1115
+
1116
+ `computeKpCuspalSubLords` always uses the Placidus-KP house system —
1117
+ the cuspal scheme KP analysis is built on. Whole-sign and equal-house
1118
+ cusps fall on rashi boundaries by construction and lose the cuspal-sub-
1119
+ lord granularity that drives KP timing analysis.
1120
+
1121
+ **Sources.** K.S. Krishnamurti, *Krishnamurti Paddhati* (5 vols);
1122
+ KP Astrology online references.
1123
+
1124
+ ### Prashna foundation (horary chart)
1125
+
1126
+ Cast a chart for the precise moment a question is asked, with the
1127
+ querent's location as the geographic anchor. Prashna analysis proceeds
1128
+ on the resulting chart in the same way as a natal chart — houses,
1129
+ planets, dignity, dashas all apply to the question being asked.
1130
+
1131
+ ```typescript
1132
+ import { computePrashnaChart, computeKpCuspalSubLords } from 'panchang-ts';
1133
+
1134
+ // Question asked at a specific UTC moment from Mumbai.
1135
+ const chart = computePrashnaChart(
1136
+ new Date('2026-05-09T14:30:00Z'),
1137
+ { latitude: 19.0760, longitude: 72.8777 },
1138
+ );
1139
+ chart.lagna.rashi.name; // ascendant of the prashna
1140
+ chart.bhava.system; // 'placidus-kp' (KP horary anchor) by default
1141
+ chart.planets[1]!.house; // Moon's house — primary mind significator
1142
+
1143
+ // KP cuspal sub-lord analysis on the prashna cusps:
1144
+ const cusps = computeKpCuspalSubLords(
1145
+ new Date('2026-05-09T14:30:00Z'),
1146
+ { latitude: 19.0760, longitude: 72.8777 },
1147
+ );
1148
+ ```
1149
+
1150
+ The returned shape is identical to a natal `BirthChart`. The dedicated
1151
+ function is intent-named so callers' analysis context is explicit at
1152
+ the call site, and so future Prashna-specific layers (Ruling Planets,
1153
+ horary numbers 1..249, significator-driven event timing) can land
1154
+ additively in this module.
1155
+
1156
+ **Default house system.** Defaults to `'placidus-kp'` — KP horary's
1157
+ standard cuspal scheme. Pass `{ houseSystem: 'whole-sign' }` for
1158
+ traditional Vedic Prashna.
1159
+
1160
+ **Out of scope** (deferred to a later phase):
1161
+ - Ruling Planets (5-fold lord set used to refine timing in KP horary).
1162
+ - Horary number mapping (KP 1..249 number → cusp sub-lord table).
1163
+ - Significator-driven event timing (dasha-walk against significator sets).
1164
+
1165
+ **Sources.** B. Suryanarain Rao, *Prasna Marga*; K.S. Krishnamurti,
1166
+ *Horary Astrology* (KP Reader VI); Sanjay Rath, *Horary Astrology*
1167
+ (srath.com).
1168
+
603
1169
  ## 17. Dasha Systems
604
1170
 
605
- Four classical dasha systems are exposed:
1171
+ Five classical dasha systems are exposed:
606
1172
 
607
1173
  ```typescript
608
1174
  import {
609
1175
  computeVimshottariDashaFromBirth, computeVimshottariPratyantar,
610
1176
  computeAshtottariDasha, computeYoginiDasha, computeCharaDasha,
1177
+ computeNarayanDasha,
611
1178
  } from 'panchang-ts';
612
1179
 
613
1180
  const birth = new Date('1995-08-15T05:30:00Z');
@@ -628,18 +1195,26 @@ const yog = computeYoginiDasha(birth, moonLon);
628
1195
  yog.mahaDashas[0].yogini; // 'Dhanya' (Magha → nakshatra 10, 10 % 8 = 2)
629
1196
  yog.mahaDashas[0].lord; // 'Jupiter' (Dhanya's planet)
630
1197
 
631
- // 4. Chara (Jaimini, sign-based, 9-8-7 years per modality)
1198
+ // 4. Chara (Jaimini, sign-based, 9-8-7 years per modality, forward only)
632
1199
  const cha = computeCharaDasha(birth, loc);
633
1200
  cha.mahaDashas[0].rashi; // lagna's rashi
634
1201
  cha.mahaDashas[0].lord; // sign-lord planet
635
1202
  cha.mahaDashas[0].years; // 9 (movable) | 8 (fixed) | 7 (dual)
1203
+
1204
+ // 5. Narayan (Jaimini, sign-based, parity-based direction per Sanjay Rath)
1205
+ const nar = computeNarayanDasha(birth, loc);
1206
+ nar.direction; // 'forward' (vishama-pada) | 'backward' (sama-pada)
1207
+ nar.startingRashi; // lagna rashi
1208
+ nar.mahaDashas[0].rashi; // == startingRashi
1209
+ nar.mahaDashas[1].rashi; // depends on direction
636
1210
  ```
637
1211
 
638
1212
  **Sourcing:** Vimshottari per Parashara (BPHS Ch. 51); Ashtottari per Satya Acharya;
639
1213
  Yogini per Sanjay Rath (1999) / Charak; Chara per Jaimini Sutras Ch. 1 (9-8-7 years
640
- variant). Documented limitations: Chara uses the forward zodiacal direction
641
- unconditionally (Sundar / Achyutananda variant); the reverse-direction rule for
642
- even-rashi lagnas is not currently exposed.
1214
+ variant); Narayan per Sanjay Rath, *Narayana Dasa* (Sagar Publications) — vishama /
1215
+ sama-pada parity rule. Documented limitations: Chara uses the forward zodiacal
1216
+ direction unconditionally (Sundar / Achyutananda variant); the parity-based variant
1217
+ ships separately as `computeNarayanDasha`.
643
1218
 
644
1219
  ## 18. Muhurta Engine
645
1220
 
@@ -1088,12 +1663,18 @@ getUpcomingSolarEclipse, getUpcomingLunarEclipse, getEclipseDuringDay
1088
1663
  // Jyotish
1089
1664
  computePlanetaryPositions, GRAHA_ABBR
1090
1665
  computeVimshottariDasha, computeVimshottariDashaFromBirth, computeVimshottariPratyantar
1091
- computeAshtottariDasha, computeYoginiDasha, computeCharaDasha
1666
+ computeAshtottariDasha, computeYoginiDasha, computeCharaDasha, computeNarayanDasha
1092
1667
  computeChandraBalam, computeTarabala
1093
1668
  computeLagna, computeBhava, computeRashiChart, computeNavamsa, computeDivisionalChart
1094
- computeAspects, computeShadbala
1095
- computeAshtakoot, computeMangalDosha, computeKaalSarp, computePitruDosha
1669
+ computeHoraLagna, computeGhatiLagna, computeBhavaLagna, computeSripatiLagna
1670
+ computeAspects, computeShadbala, computeBhavaBala, computeAshtakavarga
1671
+ computeYogas, computeJaiminiKarakas
1672
+ computeVarshaphala, computeTithiPravesha, computeArudhas, computeUpagrahas, computeArgala
1673
+ computeAshtakoot, computePathuPorutham
1674
+ computeMangalDosha, computeKaalSarp, computePitruDosha
1096
1675
  computeSadeSati, computeDignity
1676
+ computeKpSubLord, computeKpCuspalSubLords, computeKpSignificators
1677
+ computePrashnaChart
1097
1678
 
1098
1679
  // Muhurta engine
1099
1680
  scoreMuhurta, findAuspiciousDates, STOCK_MUHURTA_RULES