MUHURTA_DOSHA_STANDARD - TheDaniel166/moira GitHub Wiki

Muhurta dosha and Parihara standard

Date: 9 October 2026. Owner: VED-009, moira/muhurta_dosha.py and its private dated composer. This contract admits six source-selected restrictions and three opt-in exceptions across Python and REST.

The source record identifies inspected editions, printed/file pages, scan hashes, table disagreements and derived interpretations. The validation receipt separates textual, numerical and transport evidence.

1. Finite source policy

Policy field / profile Admitted meaning
vishanadi_profile="mc_vivaha_49_51.v1" (default) MC Avasthi 2004, Vivaha 49-51, all 27 stellar offsets; Mula 56, Purva Bhadrapada 16.
kp_185_single_mula.v1 Kalaprakasika, Iyer 1982, printed 185 main table; Mula 20, Purva Bhadrapada 6. Other offsets agree with MC.
kp_185_dual_mula.v1 KP main table plus its separately stated Mula alternative: retain both windows at 20 and 56.
vishanadi_clock="mc_avasthi_scaled_start_fixed_width.v1" (default) Avasthi's commentary and worked Rohini example: scale the start by the actual star duration; retain four fixed ghatis of width.
normalized_nakshatra_sixtieths.v1 Explicit derived alternative: scale both start and width by the actual duration. It is not attributed to Avasthi's worked example.
gandanta_profile="mc_vivaha_43_fixed_ghati.v1" (default) Each side of the selected join: nakshatra 2 ghatis, tithi 1 ghati, Lagna 0.5 ghati.
bphs_santhanam_92_fixed_ghati.v1 Santhanam II 92.2-4: nakshatra 2 ghatis, tithi 2 ghatis, Lagna 0.5 ghati on each side.
mc_shubhashubha_9_yamaghanta.v1 Weekday/nakshatra pair; Sunday-first one-based stars 10,16,6,19,3,4,13.
mc_shubhashubha_37_sixteenths.v1 Daytime Yamaghanta, distinct from the weekday/star yoga. Sunday-first one-based daylight sixteenths 10,8,6,4,2,14,12. No nighttime extension.

One fixed ghati is 1,440 seconds (24 minutes). For parent start A, duration D in UT1 days and table offset q, Vishanadi starts at A+q*D/60. The default ends four fixed ghatis later (+4/60 days); the alternative ends at A+(q+4)*D/60. Fixed-width windows may continue into the next star; they retain their original parent identity and are never clipped to that star. All offsets are elapsed ghatis, not one-based ordinal numbers.

Gandanta joins are Ashlesha/Magha, Jyeshtha/Mula, Revati/Ashwini; Cancer/Leo, Scorpio/Sagittarius, Pisces/Aries for Lagna; and the last/first portions around every fifth tithi. Both full- and new-moon joins are included. Temporal windows use solved parent events, never a fixed-degree substitute. Clip to the parent when it is shorter than the declared width, retaining both window and unclipped_window as evidence.

2. Cancellation is a separate, opt-in finding

parihara_profiles=() is the default. Selecting a profile never deletes the restriction, alters its source, or implies overall suitability.

Optional profile Exact scope and prerequisites
kp_195_seven_star_tyajya_exemption.v1 KP tables only. Witness parent is Ardra, Shravana, Mrigashira, Swati, Uttara Ashadha, Rohini or Anuradha. Parent identity survives any carryover. The same exception is excluded for the MC table.
mc_shubhashubha_37_necessary_first_half.v1 Daytime Yamaghanta only. Caller explicitly declares necessary_activity=True, and instant is within the first temporal half of that sixteenth. Missing necessity is unknown, not affirmative. It never cancels weekday/star Yamaghanta.
mc_avasthi_vivaha_43_abhijit.v1 Avasthi's commentary, not the Sanskrit verse. MC Gandanta only, during [sunrise+7*daylight/15, sunrise+8*daylight/15). It is excluded for the BPHS profile. This geometric exception does not alter the existing named-Abhijit Wednesday eligibility rule.

Each PariharaEvidence carries its profile, retained witness index, source citations, optional window and named nullable prerequisites. Its state is not_selected, excluded, not_applicable, not_satisfied, unavailable, uncertain or applied. All prerequisites and the restriction witness must be affirmative before it can be applied. uncertain retains numerical-band ambiguity; unavailable identifies missing prerequisites. Both retain nullable truth values and their supporting evidence. An explicitly false prerequisite establishes not_satisfied even when another prerequisite is unknown.

3. Input and result ownership

detect_muhurta_doshas(sun_sidereal_longitude, moon_sidereal_longitude, *, jd_ut1, weekday=None, lagna_sidereal_longitude=None, phase_spans=(), sunrise_day=None, sunset=None, necessary_activity=None, policy=None) is kernel-free. Longitudes are finite sidereal degrees in [0,360); the direct method does not convert frames. Indices are zero-based: Sunday=0, Ashwini=0, month tithi=0..29, Aries=0. The weekday belongs to the owning sunrise date.

Optional DoshaPhaseSpan(kind, index, interval) accepts nakshatra, tithi or Lagna full parents with immutable ShuddhiInterval/ShuddhiBoundary UT1 endpoints. Per-family spans must be ordered, contiguous and consecutive, cover the instant and include its supplied longitude's possible parent. Endpoint brackets must be separated. Astronomical identity remains caller-owned: structural checks cannot certify supplied roots. At most 64 spans are accepted, each at most three days, with at most one hour of uncertainty per boundary. The sunrise interval is at most two days, contains the instant and strictly encloses the sunset brackets when sunset is supplied.

Fixed-width Vishanadi requires enough preceding parent context to exclude 96-minute carryover. Missing context makes absence unknown. A currently affirmative witness can still establish detection, while incomplete coverage prevents an unwarranted affirmative neutralization. Missing temporal Gandanta evidence disables that restriction if the current identity is relevant; an unrelated star/tithi/sign can still establish its absence. Missing Lagna longitude leaves Lagna Gandanta unavailable.

Every assessment contains six ordered MuhurtaDoshaFinding results, policy, actual inputs, source/clock citations and excluded rule identifiers. detected and neutralized are independent nullable booleans:

  • clear: the selected restriction is absent; both booleans are false.
  • detected: at least one raw witness is affirmative; neutralization is false or unknown according to the separate exception evidence.
  • neutralized: detected remains true and every potentially active witness has an affirmative in-scope exception, with no missing coverage.
  • uncertain / unavailable: detection is unknown because of numerical bands or missing required evidence respectively; neutralization is unknown.

All products carry activity_suitability="not_evaluated". The package does not replace existing legacy Gandanta, Tara/Chandra, Shuddhi, weighted-score or sampled-search contracts.

4. Reader-bound sunrise day

muhurta_doshas_for_date(local_date, latitude, longitude, *, timezone, necessary_activity=None, policy=None, reader=None) accepts Gregorian years 2..9998, latitude (-90,90), longitude [-180,180] and an explicit supported timezone. Invalid/skipped civil dates fail before reader discovery. The facade borrows its existing reader; standalone calls require an explicit reader or active reader context. Caller readers are never closed or replaced.

Policy admits the existing named ayanamsa registry (default Lahiri), the existing three sunrise conventions (default Rashtriya upper limb), and root tolerance 0.01..1 seconds (default 0.1). True sidereal Sun/Moon and local Lagna use the same frame. Solar anchors reuse the named-Muhurta owner. The requested local sunrise through the next civil date's sunrise owns the product; no missing-sunrise 24-hour fallback is invented.

Full Moon/tithi parents are searched within three days on either side; Lagna parents within one day. Discovery steps are one hour and three minutes respectively, with at most 24 adaptive subdivisions, 64 bisections per root and 16,384 phase evaluations per family. Invalid/nonmonotonic signals or unresolved full events fail rather than publishing sampled boundaries. Cells split at all astronomical, restriction and selected exception edges. At most 512 merged transition bands and 511 cells are returned.

Root endpoints retain numerical lower/upper brackets. Exact endpoints obey [start,end); nonzero uncertainty bands make no categorical claim. day.at(jd_ut1) returns a representative cell assessment, whose input instant remains its original interior sample, or None outside coverage/in an uncertainty band. It does not recompute positions at the query instant. Membership states are constant within the cell outside the boundary bands.

Day status is available, partial or unavailable with explicit reasons. Missing owned sunrise(s) prevents a day. Missing sunset disables dependent windows. At/above the ecliptic polar circle, Lagna timing is unavailable while other components remain evaluated. Selecting the necessary-work exception without declaring necessity produces a partial result. Kernel identity and reader binding are retained. UT1 JDs are not relabeled as UTC timestamps.

5. Public and REST contracts

Fifteen identical owning exports are curated through moira, moira.vedic and moira.facade: twelve policy/evidence/day vessels plus the catalogue, direct and dated functions. Moira exposes those same three operations.

Route Contract
GET /v1/muhurta/doshas/catalogue Twelve named profile records, six detectors and explicit exclusions; kernel-free.
POST /v1/muhurta/doshas/direct Pure supplied-input assessment.
POST /v1/muhurta/doshas/day Synchronous read-only one-day composition using the serving engine's reader.

Models reject unknown fields, unnamed/duplicate profiles, numeric booleans, coerced numeric strings, non-finite numbers, malformed dates and contradictory nested spans before resource work. Typed responses preserve every engine witness, predicate and nullable field. Serializers project dataclasses and do not recompute astrology. Invalid inputs return the canonical 422 envelope; coverage failures use muhurta_date_outside_coverage, missing resources use 503 muhurta_resource_unavailable, with the existing request-ID contract.

This minimal example intentionally omits temporal evidence; it demonstrates identity detection without claiming that every component was evaluated:

from moira import detect_muhurta_doshas, muhurta_dosha_catalogue

catalogue = muhurta_dosha_catalogue()
assert len(catalogue.profiles) == 12
result = detect_muhurta_doshas(0.0, 45.0, jd_ut1=2451545.0, weekday=5)
yama = next(f for f in result.findings if f.rule_id == "yamaghanta_yoga")
assert yama.detected is True and yama.neutralized is False
assert result.activity_suitability == "not_evaluated"

6. Explicit remaining scope

This admission completes the finite six-detector/three-exception package. Weekday/tithi/sign Tyajya, Abhukta Mula, angular Gandanta variants, the full twenty-one-dosha catalogue and universal auspicious-yoga precedence remain research extensions. Planetary strength/aspect/Navamsa-dependent exceptions belong to VED-010; complete purpose elections belong to VED-011. Ritual performance and predictive efficacy are not inferred from computed windows. These exclusions do not assert that classical sources are unavailable.