DASHA_BACKEND_STANDARD - TheDaniel166/moira GitHub Wiki

Dasha Backend Standard

Subsystem: moira/dasha.py Computational Domain: Vimshottari Dasha Constitutional Phase: 11 — Architecture Freeze and Validation Codex Status: Constitutional


Part I — Architecture Standard

§1. Computational Definitions

§1.1 Vimshottari Dasha

Vimshottari Dasha is the canonical Jyotish time-lord technique. Nine planetary lords are assigned periods in a fixed sequence totaling 120 years. The entry point into the sequence is determined by the natal Moon's nakshatra (lunar mansion) and the fraction of that nakshatra already elapsed at birth, which produces a partial first Mahadasha (major period).

The authoritative engine is vimshottari(moon_tropical_lon, natal_jd). It accepts the Moon's tropical longitude, a Julian Day number, and an optional levels parameter controlling how many recursive levels of sub-periods are computed. It returns a flat list of DashaPeriod records covering the full 120-year sequence from birth at all requested levels.

Dasha lords and their year allocations (VIMSHOTTARI_YEARS):

Planet Years
Ketu 7
Venus 20
Sun 6
Moon 10
Mars 7
Rahu 18
Jupiter 16
Saturn 19
Mercury 17

The sequence repeats cyclically. Total = 120 years.

Recursive levels (Dasha hierarchy):

Level Name
1 Mahadasha (major)
2 Antardasha (sub)
3 Pratyantardasha (sub-sub)
4 Sookshma
5 Prana

Sub-period durations at each level are proportional to the lord's share of the parent period. Level 1 periods sum to the lord's full VIMSHOTTARI_YEARS allocation (adjusted for the birth nakshatra fraction in the first Mahadasha). At each deeper level, the sub-lord's proportion of the parent is its VIMSHOTTARI_YEARS divided by 120, applied to the parent's duration.

Year basis: Two year-basis doctrines exist for converting Julian Day durations to calendar years. The year_basis field on DashaPeriod identifies which was used. This is a doctrinal flag preserved from the engine; both doctrines use the same proportional structure.

Lord types (DashaLordType):

Value Planets
LUMINARY Sun, Moon
INNER Mercury, Venus, Mars
OUTER Jupiter, Saturn
NODE Rahu, Ketu

Lord type is a structural classification based on the planet's astronomical category within Jyotish doctrine. It is not a dignity or condition assessment.


§2. Layer Structure

The dasha subsystem is organized into ten layers, each building on the prior according to the constitutional dependency graph.

Layer Phase Vessel / Function
0 Core vimshottari()
1 Truth Preservation DashaPeriod
2 Classification DashaLordType
3 Inspectability is_active_at(), duration properties, current_dasha()
4 Policy levels parameter, year_basis
5 Relational Formalization DashaActiveLine, dasha_active_line()
6 Relational Hardening temporal containment guard, lord_types, is_node_chain, is_complete
7 Integrated Local Condition DashaConditionProfile, dasha_condition_profile()
8 Aggregate Intelligence DashaSequenceProfile, dasha_sequence_profile()
9 Network Intelligence DashaLordPair, dasha_lord_pair()
10 Hardening validate_vimshottari_output()

§3. Delegated Assumptions

The dasha subsystem does not compute the following. Callers are responsible for supplying correct values.

  • moon_tropical_lon: the tropical longitude of the natal Moon, computed externally from an ephemeris
  • natal_jd: a valid Julian Day number representing the moment of birth
  • Ayanamsa application: the subsystem receives a tropical longitude and applies the configured ayanamsa internally to derive the sidereal position for nakshatra assignment; the ayanamsa choice is a system-level configuration, not a per-call parameter
  • levels: how many recursive levels of sub-periods to compute; the caller controls depth; the subsystem does not enforce a maximum

§4. Doctrine Surface

The doctrinal choices made by the dasha subsystem are explicit and located.

Choice Location Default
Dasha sequence order VIMSHOTTARI_SEQUENCE module constant Ketu-Venus-Sun-Moon-Mars-Rahu-Jupiter-Saturn-Mercury
Year allocations VIMSHOTTARI_YEARS module constant Canonical 120-year totals
Nakshatra-to-lord mapping NAKSHATRA_LORD module constant 27 nakshatras mapped to 9 lords cyclically
Year basis DashaPeriod.year_basis field Preserved from engine; two doctrines supported
Levels computed vimshottari() levels parameter Caller-controlled
Lord type classification DashaLordType enum, DashaConditionProfile.lord_type field LUMINARY / INNER / OUTER / NODE

§5. Public Vessels

The following are the constitutional public vessels of the dasha subsystem.

Enumerations:

  • DashaLordType — classifies a dasha lord as LUMINARY, INNER, OUTER, or NODE

Truth-preservation vessels:

  • DashaPeriod — a single Vimshottari period at any level

Relational vessels:

  • DashaActiveLine — the full chain of active periods from Mahadasha to the deepest active level at a point in time

Condition vessels:

  • DashaConditionProfile — integrated doctrinal summary for one DashaPeriod

Aggregate vessels:

  • DashaSequenceProfile — chart-wide summary of a full Mahadasha sequence

Network vessels:

  • DashaLordPair — the Mahadasha/Antardasha lord pair derived from a DashaActiveLine

Computational functions:

  • vimshottari(moon_tropical_lon, natal_jd, ...) — core Vimshottari Dasha engine
  • current_dasha(moon_tropical_lon, natal_jd, current_jd) — convenience function returning the active period chain at a given Julian Day
  • dasha_active_line(active_periods) — relational line from a list of active periods
  • dasha_condition_profile(period) — condition profile for one Dasha period
  • dasha_sequence_profile(periods) — aggregate profile for a Mahadasha sequence
  • dasha_lord_pair(line) — network pair from a DashaActiveLine
  • validate_vimshottari_output(periods) — invariant guard for Vimshottari output

Part II — Terminology Standard

§6. Required Terms

The following terms carry specific meanings within this subsystem and must not be used loosely.

Term Normative Meaning
Mahadasha A DashaPeriod with level=1; one of the nine 120-year sequence allocations
Antardasha A DashaPeriod with level=2; a sub-period within a Mahadasha
Pratyantardasha A DashaPeriod with level=3
Sookshma A DashaPeriod with level=4
Prana A DashaPeriod with level=5
level The 1-based integer depth of a DashaPeriod; 1 is the outermost
lord The planet assigned to a DashaPeriod; drawn from the nine Vimshottari lords
lord type The DashaLordType classification of a lord: LUMINARY, INNER, OUTER, or NODE
nakshatra The lunar mansion (1 of 27) in which the natal Moon resides; determines entry point into the Dasha sequence
nakshatra fraction The proportion of the birth nakshatra already elapsed at birth; determines the duration of the first (partial) Mahadasha
year basis The doctrinal convention used to convert Julian Day differences to calendar years; preserved as a string on DashaPeriod
active line A DashaActiveLine; the chain of periods active at a specific moment, from Mahadasha down to the deepest computed level
depth The number of non-None levels populated in a DashaActiveLine; equivalent to the level of the deepest active period
condition profile A flat doctrinal summary of a single DashaPeriod, integrating all layers
sequence profile A chart-wide aggregate across all Mahadasha-level periods and their condition profiles
lord pair The Mahadasha/Antardasha combination at a moment; a network node derived from a DashaActiveLine

§7. Forbidden Conflations

The following pairs must not be equated.

DashaPeriod and DashaConditionProfile A DashaPeriod is the raw truth-preservation vessel from the engine. A DashaConditionProfile is a derived doctrinal summary. One is the source; the other is a projection of it.

level and depth level is the field on a single DashaPeriod. depth is the property on a DashaActiveLine counting how many levels are populated. They are related but not interchangeable.

lord_type and planet name DashaLordType classifies a planet into a structural category. It is not the planet name and must not be used to identify a specific planet. Two planets can share a lord type (e.g., Rahu and Ketu are both NODE).

is_node_chain and is_node_dasha DashaActiveLine.is_node_chain is True only when every non-None level in the line has a node lord. DashaConditionProfile.is_node_dasha is True only when that specific period's lord is a node. One is a chain-level property; the other is a period-level property.

DashaActiveLine and DashaLordPair A DashaActiveLine is the full active period chain up to five levels deep. A DashaLordPair is the network projection of that chain down to only the Mahadasha and Antardasha lords. One is the full structural record; the other is a two-node network edge.

DashaSequenceProfile and DashaActiveLine A DashaSequenceProfile is a chart-wide aggregate over all Mahadasha periods. A DashaActiveLine is a point-in-time slice of the active period chain. One is a global summary; the other is a temporal snapshot.

nakshatra and birth_nakshatra nakshatra is an astronomical concept (27 lunar mansions). birth_nakshatra on DashaConditionProfile is the specific nakshatra the natal Moon occupied. Only Mahadasha-level condition profiles carry a meaningful birth_nakshatra; sub-period profiles carry None.

year_basis and duration year_basis is a doctrinal identifier for the year-conversion convention. It is not a duration and must not be used in arithmetic. Duration in years is stored in DashaPeriod.years; duration in days in DashaPeriod.days.


Part III — Invariant Register

§8.1 Vessel Invariants

DashaPeriod:

  • level is an integer ≥ 1
  • planet is a recognized Vimshottari lord name
  • start_jd < end_jd
  • years > 0 and days > 0
  • parent_planet, if set, identifies a recognized Vimshottari lord

DashaActiveLine:

  • mahadasha is always present and non-None
  • Each subsequent level field is None unless the preceding level is also non-None (no gaps: pratyantardasha cannot be set if antardasha is None)
  • All present periods are in strict level order: Mahadasha contains Antardasha contains Pratyantardasha contains Sookshma contains Prana (±1e-6 tolerance)
  • Temporal containment is enforced in __post_init__: each child's start_jd ≥ parent's start_jd − 1e-6, and child's end_jd ≤ parent's end_jd + 1e-6

DashaConditionProfile:

  • lord_type is a valid DashaLordType value or None
  • years > 0 and days > 0
  • is_node_dasha and is_luminary_dasha are mutually exclusive (both cannot be True)
  • birth_nakshatra and nakshatra_fraction are both None or both non-None

§8.2 Truth Invariants

  • VIMSHOTTARI_YEARS is immutable. No function modifies or overrides it at runtime.
  • VIMSHOTTARI_SEQUENCE is immutable. The order of the nine lords is fixed.
  • DashaPeriod.planet is validated against VIMSHOTTARI_SEQUENCE in __post_init__. A DashaPeriod with an unrecognized planet name cannot be constructed.
  • The first Mahadasha in any vimshottari() output may be shorter than its canonical VIMSHOTTARI_YEARS allocation due to the birth nakshatra fraction.
  • Sub-period durations are proportional to the lord's share of the parent. This proportionality is preserved in DashaPeriod.years without rounding.

§8.3 Aggregate Invariants

DashaSequenceProfile:

  • luminary_count + inner_count + outer_count + node_count == mahadasha_count
  • profile_count == len(profiles) == mahadasha_count
  • total_years > 0
  • total_years ≤ VIMSHOTTARI_TOTAL (120 years); may be less if the first Mahadasha is partial

§8.4 Network Invariants

DashaLordPair:

  • maha_profile is always present
  • antar_profile is None if and only if the source DashaActiveLine has no Antardasha
  • is_same_lord is meaningful only when has_antar is True
  • both_are_nodes implies involves_node; involves_node does not imply both_are_nodes

Part IV — Failure Doctrine

§9.1 Invalid Inputs

  • Passing a non-finite moon_tropical_lon to vimshottari() raises ValueError.
  • Passing a non-finite natal_jd to vimshottari() raises ValueError.
  • Constructing a DashaPeriod with an unrecognized planet name raises ValueError (enforced in DashaPeriod.__post_init__).
  • Constructing a DashaActiveLine with a None Mahadasha raises TypeError.
  • Constructing a DashaActiveLine with a level gap (e.g., Pratyantardasha set but Antardasha None) raises ValueError.
  • Constructing a DashaActiveLine where a child period falls outside its parent's temporal bounds (beyond the ±1e-6 tolerance) raises ValueError.

§9.2 Search Exhaustion

  • current_dasha() returns an empty list if the queried current_jd falls outside the computed 120-year period range. This is not an error.
  • dasha_active_line() receiving an empty list raises ValueError.

§9.3 Invariant Failure

  • validate_vimshottari_output() raises ValueError with a descriptive message if:
    • any two adjacent level-1 periods (Mahadashas) overlap in Julian Day
    • any level-1 period is out of chronological order relative to its predecessor
    • any sub-period at any level is not temporally contained within its parent
    • any sub-periods within a parent are out of chronological order or overlap
  • DashaSequenceProfile.__post_init__ raises ValueError if the sum luminary_count + inner_count + outer_count + node_count does not equal mahadasha_count.

Part V — Determinism Standard

§10. Determinism Guarantees

  • vimshottari() is fully deterministic: given the same moon_tropical_lon, natal_jd, and levels, the output list is identical in every call with no dependency on external state beyond the configured ayanamsa.
  • The flat list returned by vimshottari() is ordered by (level, start_jd).
  • All nine Mahadasha periods and all their sub-periods appear in chronological order within their level.
  • dasha_active_line(), dasha_condition_profile(), dasha_sequence_profile(), and dasha_lord_pair() are pure functions with no side effects.
  • Floating-point accumulation across deeply nested sub-periods may produce end_jd values that differ from the parent's end_jd by a small epsilon. The containment tolerance of ±1e-6 JD in DashaActiveLine.__post_init__ accommodates this. This is the only permitted numeric approximation in the subsystem.
  • The ayanamsa value used to convert tropical Moon longitude to sidereal longitude for nakshatra assignment is drawn from the system-level configured ayanamsa. It is not a per-call parameter. Two calls with the same inputs but different ayanamsa configurations may produce different nakshatra assignments and therefore different Dasha sequences. This is a system-level dependency, not a non-determinism in the subsystem itself.

Part VI — Validation Codex

§11. Minimum Validation Commands

The following commands must pass without error on any constitutionally correct installation of this subsystem:

python -m pytest tests/unit/test_dasha.py -v

All tests in test_dasha.py must pass. The test suite validates:

  • vimshottari() structural correctness (level distribution, sequence order)
  • DashaPeriod field fidelity and __post_init__ guards
  • DashaActiveLine construction, depth property, as_list() round-trip
  • DashaActiveLine temporal containment rejection
  • lord_types, is_node_chain, is_complete properties
  • DashaConditionProfile field fidelity, level_name, birth_nakshatra, nakshatra_fraction, exclusivity invariant
  • DashaSequenceProfile counts, canonical lord distribution, total_years bounds, invariant rejection
  • DashaLordPair construction, has_antar, is_same_lord, involves_node, both_are_nodes
  • validate_vimshottari_output() correctness, overlap detection, sub-containment detection

§12. Required Validation Themes

Any validation suite for this subsystem must demonstrate the following:

Truth preservation:

  • A DashaPeriod from vimshottari() carries planet, level, parent_planet, start_jd, end_jd, years, days, year_basis, and birth_nakshatra (for the first Mahadasha) without truncation or flattening.

Relational integrity:

  • A DashaActiveLine constructed from active periods preserves mahadasha through the deepest active level without reordering.
  • Temporal containment is enforced: a child period outside its parent's bounds causes ValueError at construction time.

Classification correctness:

  • DashaLordType.NODE applies to Rahu and Ketu and only to Rahu and Ketu.
  • DashaLordType.LUMINARY applies to Sun and Moon and only to Sun and Moon.
  • is_luminary_dasha and is_node_dasha are mutually exclusive.

Aggregate integrity:

  • luminary_count + inner_count + outer_count + node_count == mahadasha_count in any DashaSequenceProfile constructed from a valid sequence.
  • total_years ≤ 120.0 for any valid sequence.

Network correctness:

  • DashaLordPair.is_same_lord is True when Mahadasha and Antardasha lords are identical.
  • DashaLordPair.involves_node detects node lords at either level.
  • DashaLordPair raises ValueError if constructed from an invalid DashaActiveLine.

Hardening:

  • validate_vimshottari_output() detects overlapping Mahadashas.
  • validate_vimshottari_output() detects sub-periods outside their parent.
  • validate_vimshottari_output() passes silently on valid output.

Part VII — Future Boundary

§13. Explicit Non-Goals

The following are explicitly outside the scope of this subsystem as constitutionalized.

Not in scope:

  • Chart calculation. The subsystem does not compute natal Moon positions, house cusps, or ascendants. These are delegated to the chart engine.

  • Ayanamsa selection. The ayanamsa used to derive the sidereal Moon longitude is a system-level configuration. The subsystem consumes a tropical longitude and applies the configured ayanamsa internally, but the selection of which ayanamsa to use is outside this standard.

  • Nakshatra calculation beyond birth entry. The subsystem uses the natal nakshatra only to determine the Dasha sequence entry point and the first Mahadasha's partial duration. Ongoing transit-based nakshatra tracking is not part of this subsystem.

  • Predictive interpretation. The subsystem produces structural timing data. It does not assess whether a Dasha lord is beneficial or malefic, strong or weak. Interpretation is a higher-level concern.

  • Ashtottari Dasha or other Dasha systems. This subsystem constitutionalizes Vimshottari Dasha only. Other Jyotish Dasha systems (Ashtottari, Yogini, etc.) are separate techniques requiring separate constitutionalization.

  • Graha Bala or Shadbala. Planetary strength assessment is a separate dignities or condition subsystem concern and is not part of this standard.

  • Transit and progression overlay. Correlating Dasha periods with transit or natal chart positions is a cross-subsystem concern and is not part of this standard.

  • Conditional Dasha activation. Whether a Dasha lord is considered "activated" by transit triggers or other conditional doctrines is an interpretive layer above this standard.

  • Dasha rectification. The subsystem does not provide tools for adjusting birth time based on Dasha periods. That is a separate diagnostic concern.

Any future extension that crosses these boundaries requires a new constitutional phase or a separate subsystem constitutionalization, not an in-place amendment to this standard.