Version: 1.1 Date: 2026-09-27 Status: Current implementation truth; REST admitted
The Moira alternate-dasha backend is a Vedic time-lord subsystem for
non-Vimshottari dasha systems currently implemented in moira/dasha_systems.py.
It preserves Ashtottari and Yogini sequence truth, year-basis policy, ayanamsa
policy, nested sub-period arithmetic, local period profiles, and sequence
profiles.
This document governs Ashtottari and Yogini only. The separately owned Kalachakra profile and Chara profiles use their own sign-period contracts; they are not selectors in this eight-lord subsystem.
An alternate dasha period in Moira is:
One time interval in an implemented non-Vimshottari dasha sequence.
| Field | Meaning |
|---|---|
system |
ashtottari or yogini |
level |
1-based hierarchy level; 1 is Mahadasha |
lord |
Ashtottari planetary lord or Yogini name |
start_jd |
Julian Day when the period begins |
end_jd |
Julian Day when the period ends |
sub |
Nested sub-periods, when requested |
An Ashtottari sequence in Moira is:
A 108-year cycle with eight lords, entered by the Moon’s birth nakshatra.
The current lord sequence is:
Sun, Moon, Mars, Mercury, Saturn, Jupiter, Rahu, Venus
The current year allocations sum to 108:
| Lord | Years |
|---|---|
| Sun | 6 |
| Moon | 15 |
| Mars | 8 |
| Mercury | 17 |
| Saturn | 10 |
| Jupiter | 19 |
| Rahu | 12 |
| Venus | 21 |
BPHS chapter 46, verses 17–22 begin the allocation at Ardra and alternate groups of four and three counting places:
| Lord | Nakshatras |
|---|---|
| Sun | Ardra, Punarvasu, Pushya, Ashlesha |
| Moon | Magha, Purva Phalguni, Uttara Phalguni |
| Mars | Hasta, Chitra, Swati, Vishakha |
| Mercury | Anuradha, Jyeshtha, Mula |
| Saturn | Purva Ashadha, Uttara Ashadha, Abhijit, Shravana |
| Jupiter | Dhanishtha, Shatabhisha, Purva Bhadrapada |
| Rahu | Uttara Bhadrapada, Revati, Ashwini, Bharani |
| Venus | Krittika, Rohini, Mrigashira |
Each four-place group assigns one quarter of its lord’s Mahadasha to each place; each three-place group assigns one third. The first-period balance therefore includes complete places already traversed within the current lord’s group as well as the elapsed fraction of the active place.
The BPHS passage requires 28 places but does not state Abhijit’s zodiacal boundaries. Moira names its separate traditional convention explicitly: Abhijit spans 6°40’–10°53’20” sidereal Capricorn, combining the last quarter of Uttara Ashadha with the first fifteenth of Shravana. This boundary must not be attributed to the wording of BPHS 46.17–22.
A Yogini sequence in Moira is:
A 36-year cycle with eight Yoginis, entered by adding three to the one-based birth-nakshatra number and reducing to a one-through-eight remainder.
With Moira’s zero-based index, the equivalent expression is:
(nakshatra_index + 3) % 8
The current Yogini sequence is:
Mangala, Pingala, Dhanya, Bhramari, Bhadrika, Ulka, Siddha, Sankata
The current year allocations sum to 36:
| Yogini | Years | Planet |
|---|---|---|
| Mangala | 1 | Moon |
| Pingala | 2 | Sun |
| Dhanya | 3 | Jupiter |
| Bhramari | 4 | Mars |
| Bhadrika | 5 | Mercury |
| Ulka | 6 | Saturn |
| Siddha | 7 | Venus |
| Sankata | 8 | Rahu |
Both implemented systems use proportional subdivision:
sub_years = (sub_lord_years / system_total_years) * parent_period_years
For Yogini, the first Mahadasha is shortened by the fraction of the Moon’s birth nakshatra already elapsed. For Ashtottari, the first Mahadasha balance uses the Moon’s progress through the active three- or four-place lord group.
The normative computational readings are the Sanskrit verses in Brihat Parashara Hora Shastra, chapter 46:
Digital Sanskrit witnesses used for collation:
These are edition/transcription witnesses, not an independent manuscript stemma or modern critical edition. Translation headings and commentary do not override the Sanskrit computational statements. The exact Abhijit span is a separately provenance-labelled later convention, historically discussed with the Muhurta-Mala rule in Burgess and Whitney’s notes to the Surya Siddhanta.
The backend is organized around the current constitutional phases declared in
moira/dasha_systems.py:
P1 - Truth preservation (AlternateDashaPeriod)
P2 - Classification constants (AlternateDashaSystem)
P3 - Inspectability (years, is_terminal)
P4 - Policy surface (AshtottariPolicy, YoginiPolicy)
P7 - Local condition profile (AlternatePeriodProfile)
P8 - Aggregate sequence profile (AlternateDashaSequenceProfile)
P10 - Hardening (__post_init__ guards, validate_alternate_dasha_output)
P12 - Public API curation (__all__, root/vedic/facade exports)
Layer boundary rules:
ashtottari(...) and yogini_dasha(...) consume the natal Moon’s tropical
longitude and natal Julian Day.AlternateDashaPeriod vessels.AshtottariPolicy currently exposes:
| Field | Default | Meaning |
|---|---|---|
year_basis |
julian_365.25 |
Year-length convention |
ayanamsa_system |
Lahiri |
Ayanamsa used for Moon nakshatra conversion |
bypass_eligibility |
False |
Explicitly compute without an engine eligibility determination |
lagna_sign_index |
None |
Legacy Ascendant sign input; insufficient by itself for BPHS eligibility |
Current implementation truth:
lagna_sign_index is supplied while bypass_eligibility=False, the
engine raises rather than treating the incomplete legacy field as proof.bypass_eligibility=True for
first admission or expose the engine’s current rejection honestly.YoginiPolicy currently exposes:
| Field | Default | Meaning |
|---|---|---|
year_basis |
julian_365.25 |
Year-length convention |
ayanamsa_system |
Lahiri |
Ayanamsa used for Moon nakshatra conversion |
Supported year bases:
julian_365.25savana_360tropical_365.2422sidereal_365.2564All public names are declared in moira/dasha_systems.py.
| Name | Meaning |
|---|---|
AlternateDashaSystem |
Supported system labels |
ASHTOTTARI_YEARS |
Ashtottari lord-year table |
ASHTOTTARI_SEQUENCE |
Ashtottari lord order |
ASHTOTTARI_NAKSHATRA_LORD |
27-entry ordinary-nakshatra projection of the BPHS mapping; computation separately admits Abhijit |
ASHTOTTARI_TOTAL |
Ashtottari total cycle years |
YOGINI_YEARS |
Yogini year table |
YOGINI_SEQUENCE |
Yogini order |
YOGINI_PLANETS |
Yogini-to-planet mapping |
YOGINI_TOTAL |
Yogini total cycle years |
| Vessel | Primary fields |
|---|---|
AlternateDashaPeriod |
system, level, lord, start/end JD, sub-periods |
AshtottariPolicy |
year basis, ayanamsa, eligibility flags |
YoginiPolicy |
year basis, ayanamsa |
AlternatePeriodProfile |
system, lord, planet, duration, node/luminary flags |
AlternateDashaSequenceProfile |
system, total years, Mahadasha count, profiles |
| Function | Signature | Meaning |
|---|---|---|
ashtottari |
(moon_tropical_lon, natal_jd, levels=2, policy=None) -> list[AlternateDashaPeriod] |
Compute Ashtottari periods |
yogini_dasha |
(moon_tropical_lon, natal_jd, levels=2, policy=None) -> list[AlternateDashaPeriod] |
Compute Yogini periods |
alternate_period_profile |
(period) -> AlternatePeriodProfile |
Build local period profile |
alternate_sequence_profile |
(periods) -> AlternateDashaSequenceProfile |
Build sequence profile |
validate_alternate_dasha_output |
(periods) -> None |
Validate Mahadasha-level output |
ashtottari and yogini.[1, 4].The subsystem fails loudly on:
AlternateDashaPeriod.systemstart_jd >= end_jdvalidate_alternate_dasha_outputlagna_sign_index
without bypassing eligibilityThe alternate-dasha backend is currently validated through:
tests/unit/test_dasha_systems.pytests/unit/test_api_surface_adversarial_audit.pytests/unit/test_public_doctrine_surfaces.pyThe following claims are currently verified:
validate_alternate_dasha_output(...) accepts valid sequences and catches
invalid lord or gap/overlap structures.moira, moira.vedic, and
moira.facade.The minimum verification slice for this standard is:
.\.venv\Scripts\python.exe -m py_compile moira\dasha_systems.py tests\unit\test_dasha_systems.py
.\.venv\Scripts\python.exe -m pytest tests\unit\test_dasha_systems.py tests\unit\test_public_doctrine_surfaces.py -q
.\.venv\Scripts\python.exe -m pytest tests\unit\test_api_surface_adversarial_audit.py -q
The admitted REST surface provides both direct-computation and chart-backed sequence/profile routes for Ashtottari and Yogini, plus period-profile projection.
Direct-computation routes accept:
Chart-backed routes derive the tropical Moon longitude and natal Julian Day through the server’s sidereal chart context and return that provenance with the result.
Ashtottari REST admission must preserve the current eligibility truth: the
complete BPHS 46.17 and 46.23 applicability context is not represented, so the
transport should either require bypass_eligibility=True or expose the current
engine rejection for lagna_sign_index without bypass.
The VED-005 admission standard now owns strict finite inputs, typed switches/depth/sign indices and supplied period tree admission. Chart-backed requests with no nested policy use their selected chart ayanamsa for the actual period calculation. Supplied policy/chart frame mismatches still reject. Periods retain the existing numerical year-basis and historical applicability semantics.
Generated periods carry full_start_jd and full_end_jd. Children subdivide
that full doctrinal interval before clipping to the visible parent; the first
visible child may have a different lord than its parent. Birth balance and
clipped horizon are intersections, not new clocks. Intervals are half-open.
The metadata must be supplied together and contain the visible interval;
legacy manually constructed periods with neither field use their visible span.
Alternate periods additionally carry paired year_days/year_basis provenance;
legacy unknown metadata stays unknown and the legacy .years property remains
Julian. REST carries these fields through sequence, current and recursive
period input/output. Existing clocks and tolerances are unchanged. The corrected
Einstein fixture independently checks general precession, frame and birth
progress rather than replacing a scalar from current runtime output alone.
See repair validation.
The second adversarial repair uses the shared full-parent/child intersection validator. Known full children must lie within known full parents, and visible children must be their full spans intersected with the visible parent. Unknown legacy provenance remains unknown. Recursive REST period admission now delegates to the engine’s tree validator with an explicit partial-child-list mode, preserving existing period-profile requests. Both modes enforce full containment, clipping, ordering and uniform year metadata; generated output additionally requires complete visible coverage. A nested savana parent with a Julian child rejects before period-profile computation.