SHADBALA_BACKEND_STANDARD - TheDaniel166/moira GitHub Wiki
Shadbala Backend Standard
Status: Current contract, adversarial repairs 9 October 2026
Authority: moira/shadbala.py
Source: Selected Raman 1996 and BPHS Santhanam component rules; see source and compatibility receipt.
Part I β Architecture Standard
1. Governing Principle
The Shadbala subsystem is an astronomical-truth-first computation of the six sources of planetary strength (bala) used in classical Vedic astrology.
Source attribution is component-specific. Selected Saptavargaja, Kala and war rules have independently transcribed arithmetic witnesses. Retained thresholds, ingress-based Abda/Masa, osculating Chesta and sign-based Drig are identified separately; neither named Saptavargaja scale claims an entire textbook worked chart.
2. Layer Structure
The subsystem is organised into twelve constitutional phases. Each phase consumes only outputs produced by earlier phases. No phase reaches upward.
Phase 0 β Core computation (sthana_bala, dig_bala, kala_bala, chesta_bala,
naisargika_bala, drig_bala, shadbala)
Phase 1 β Truth preservation (SthanaBala, KalaBala, PlanetShadbala,
ShadbalaResult)
Phase 2 β Classification (ShadbalaTier)
Phase 3 β Inspectability (PlanetShadbala.strength_ratio)
Phase 4 β Policy surface (ShadbalaPolicy)
Phase 5 β Relational formalization (GrahaYuddha, graha_yuddha_pairs)
Phase 6 β Relational hardening (GrahaYuddha.__post_init__ invariants)
Phase 7 β Local condition (ShadbalaConditionProfile,
shadbala_condition_profile)
Phase 8 β Aggregate intelligence (ShadbalaChartProfile,
shadbala_chart_profile)
Phase 9 β Network intelligence (ShadbalaNetworkProfile,
shadbala_network_profile)
Phase 10 β Full-subsystem hardening (PlanetShadbala.__post_init__,
ShadbalaResult.__post_init__,
validate_shadbala_output)
Phase 11 β Architecture freeze (this document)
Phase 12 β Public API curation (__all__, module docstring)
Layer boundary rules
- A phase-N function may consume vessels from any phase below N.
- A phase-N function may not mutate a lower-phase vessel.
- A phase-N function may not silently switch doctrine.
- A phase-N function may not bypass or re-derive a computation already produced by a lower phase.
3. Admitted Computation Surface
The following core computations are admitted and constitutionally frozen:
| Function | Sub-component | Raman Ch. |
|---|---|---|
sthana_bala |
Positional Strength (5 sub-components) | Ch. 2β3 |
dig_bala |
Directional Strength | Ch. 3 |
kala_bala |
Temporal Strength (6 sub-components) | Ch. 4 |
chesta_bala |
Motional Strength | Ch. 6 (non-luminaries), Ch. 10 Β§Β§136β137 (luminaries) |
| Naisargika Bala | Natural/Fixed Strength (constant) | Ch. 5 |
drig_bala |
Aspectual Strength | Ch. 6 |
shadbala |
Grand total (all 7 planets) | Ch. 1 |
bhava_dig_bala |
Bhava Digbala (house directional strength) | Part II |
bhava_drishti_bala |
Bhava Drishti Bala (aspect on bhava madhya) | Part II |
bhava_bala |
Bhava Bala grand total (all 12 houses) | Part II |
4. Computational Policies
Chesta Bala
Retained motion convention (not selected by the Saptavargaja scale):
- Sun: Chapter X (Β§136, pp. 101β103). Sayana (tropical) longitude + 90Β°, reduced to β€ 180Β° and divided by 3 Shashtiamsas. Maximum 60 Sha at Cancer ingress (northern solstice), 0 Sha at Capricorn ingress (southern solstice), 30 Sha at equinoxes.
- Moon: Chapter X (Β§137, pp. 101β103). Elongation |lon_Moon β lon_Sun|, reduced to β€ 180Β° and divided by 3 Shashtiamsas. Maximum 60 Sha at Full Moon (opposition), 0 Sha at New Moon (conjunction), 30 Sha at quarters.
- Five non-luminaries (Mars, Mercury, Jupiter, Venus, Saturn): Chapter VI (Chesta Bala or Motional Strength, pp. 64β79). Derived from Chesta Kendra = (Seeghrochcha β (mean_lon + true_lon) / 2) mod 360Β°, reduced to β€ 180Β° and divided by 3 Shashtiamsas. For superior planets (Mars, Jupiter, Saturn), Seeghrochcha is the Sun's longitude and mean longitude is the planet's mean orbital longitude evaluated from the strict orbital core. For inferior planets (Mercury, Venus), Seeghrochcha is the planet's heliocentric longitude and the mean planet is the Sun.
- Speed-ratio fallback: preserved for callers without positions or ephemeris access (retrograde gives 60 Sha; standstill gives 0 Sha).
Explicit geometry and source components
Full calculation requires immutable ShadbalaContext: UT epoch, named ayanamsa,
seven apparent geocentric sidereal longitudes, seven true-equatorial tropical
declinations, Chesta inputs, local apparent solar fraction, sunrise/set/next
sunrise, named year/month/day/hour lords and provenance. derive_shadbala_context
and Moira.shadbala_context bind the serving reader for all dependencies.
Supplied contexts perform no hidden ephemeris lookup. Missing polar solar events
remain inspectable and raise ShadbalaContextError for full strength.
Saptavargaja defaults to raman_1996; bphs_santhanam_27 changes only the seven
awards. Both use the explicit Raman D1-only Moolatrikona convention, actual D1
degrees, and D1 compound relationships. Temporary friendship is houses
2,3,4,10,11,12. Source D7 counts from own/seventh for odd/even signs, D12 from
own sign, and D30 uses unequal planetary spans. Public generic harmonic
selectors are separate. SaptavargajaEntry preserves each sign/lord/state/award.
Mercury receives both odd-sign Ojayugma contributions like Sun/Mars/Jupiter/Saturn.
Nathonnatha is linear in apparent solar hour angle; Mercury always receives60.
Paksha uses continuous SunβMoon phase, with Moon doubling. The named Moira
nature convention treats Moon as benefic on [84,264) degrees and Mercury as
malefic when sharing a D1 sign with Sun/Mars/Saturn or a malefic Moon. A supplied
context may explicitly select Mercury benefic/malefic. These endpoint and
association choices are declared interpretations, not an undisputed universal.
Tribhaga divides actual day/night arcs in thirds: Mercury/Sun/Saturn by day,
Moon/Venus/Mars by night; Jupiter always 60. Half-open boundaries assign the
new third. Ayana applies (24 + signed_declination)*60/48; Sun is doubled,
Mercury uses absolute declination, Moon/Saturn reverse sign. Declinations beyond
24 degrees retain the formula's signed result rather than an undocumented cap.
Kala Bala β Yuddha Bala (Graha Yuddha)
Only Mars/Mercury/Jupiter/Venus/Saturn participate, at separation strictly below
one degree. Raman 1996 articles 76β77 select lesser normalized longitude and
abs(raw_aggregate_difference)/abs(source_disc_diameter_difference). Raw
aggregate is Sthana+Dig+Kala through Hora, excluding Ayana. Fixed source disc
values are9.4,6.6,190.4,16.6,158.0 arcseconds respectively; they are not modern
observed angular diameters. Winner gains and loser loses the same Kala amount;
Chesta is unchanged.
moira_simultaneous_raman_raw_pairs_v1 evaluates every pair once against
immutable pre-war components, accumulates all credits/debits, and retains
signed net values. Exact equal longitude pairs have a stable lexical label
and zero adjustment. These tie/multi-way choices are Moira composition rules;
the inspected source passages prescribe two-body behavior only. WarResolution
is canonical for final totals, chart/network/Bhava/full and Lagna consumers.
Drig Bala
Sign-based Vedic aspect doctrine (not degree-based):
- 4th/8th aspects of Mars score Β½ weight; 7th aspect scores full weight.
- Saturn's 3rd/10th aspects score Β½ weight; 7th scores full weight.
- Jupiter's 5th/9th aspects score Β½ weight; 7th scores full weight.
- All other planetβplanet aspects (7th house opposition) score full weight.
Kala Bala β Abda and Masa
Located by bisection on the Sun's actual apparent sidereal longitude from the
kernel (moira.planets.planet_at), pinning the Sankranti JD to 1-second
precision. Not from mean-motion approximation.
Bhava Bala (Raman Part II)
Three components per house, summed to total_shashtiamsas:
- Bhavadhipati Bala β the total Shadbala piαΉαΈa of the house lord. The
lord is the classical lord of the rasi holding the bhava madhya (no nodal
lordships). The chart's jd and ayanamsa are taken from the supplied
ShadbalaResultso the two computations cannot disagree. - Bhava Digbala β the madhya rasi's locomotion class fixes the strong house (nara β H1, jalachara β H4, keeta β H7, chatushpada β H10); 60 Sha there, β10 Sha per house of shortest circular distance, 0 opposite. Half-sign splits: Sagittarius 1st half nara / 2nd half chatushpada; Capricorn 1st half chatushpada / 2nd half jalachara.
- Bhava Drishti Bala β the bhava madhya is the aspected point, all seven
classical planets aspecting, using the same sign-based aspect doctrine as
Drig Bala (shared core:
_sign_aspect_drig_sha).
Bhava madhya policy (explicit): the chart's house cusps are taken as the
madhya reference points, mirroring the module-wide house doctrine used by
dig_bala; equal houses from the Ascendant are the fallback when cusps are
unavailable. Houses are ranked 1β12 by total strength (ties broken by lower
house number).
No required/threshold marker exists for houses: the tradition defines required Rupas for planets only, so Bhava Bala is reported as raw strength plus rank β no pass/fail is invented.
Ishta / Kashta Phala (BPHS Ch. 27)
Exposed as P3 inspectability properties on PlanetShadbala, derived β never
stored β from the vessel's own displayed components:
ishta_phala= β(Uchcha Bala Γ Chesta Bala)kashta_phala= β((60 β Uchcha) Γ (60 β Chesta))
Both on the 0β60 Shashtiamsa scale. Policy: the displayed Chesta Bala is used; war adjustments leave the displayed Chesta unchanged.
Graha Yuddha transfer disclosure
GrahaYuddha.adjustment_shashtiamsas carries the actual resolved Kala amount.
Detection-only pairs carry None. Deprecated chesta_transferred remains a
legacy construction field and is never populated by current calculation.
REST retains shashtiamsas_transferred, with adjustment_component=kala_yuddha.
The full ledger exposes raw totals, bases, Chesta, credits/debits and net values.
Part II β Vessel Inventory
Core vessels (Phase 1)
| Vessel | Frozen | Slots | Notes |
|---|---|---|---|
SthanaBala |
β | β | Five sub-components + total |
KalaBala |
β | β | Six sub-components + total |
PlanetShadbala |
β | β | All 6 bala + totals + is_sufficient |
ShadbalaResult |
β | β | Full chart: jd, ayanamsa_system, planets |
BhavaBala |
β | β | One house: 3 components + totals + rank |
BhavaBalaResult |
β | β | All 12 houses + strongest/weakest |
Constitutional-layer vessels
| Vessel | Phase | Notes |
|---|---|---|
ShadbalaTier |
P2 | SUFFICIENT / INSUFFICIENT class constants |
GrahaYuddha |
P5/P6 | War-pair record: victor, loser, separation_deg |
ShadbalaPolicy |
P4 | ayanamsa_system governance |
ShadbalaConditionProfile |
P7 | Per-planet condition summary |
ShadbalaChartProfile |
P8 | Aggregate chart strength summary |
ShadbalaNetworkProfile |
P9 | Strength ranking + war network |
Part III β Public API
The following names are exported via __all__ and constitute the stable
public surface of this module.
Constants
NAISARGIKA_BALAβ natural fixed strength values (Shashtiamsas)REQUIRED_RUPASβ minimum Rupa thresholds per planet (Parashara)MEAN_DAILY_MOTIONβ classical mean daily motions (Β°/day)
Vessels
ShadbalaTier,SthanaBala,KalaBala,PlanetShadbala,ShadbalaResultShadbalaPolicy,GrahaYuddhaShadbalaConditionProfile,ShadbalaChartProfile,ShadbalaNetworkProfile
Functions
sthana_bala,dig_bala,kala_bala,chesta_bala,drig_balashadbalaβ full chart computation (all 7 planets)hora_lord_atβ planetary hora lord at a birth momentgraha_yuddha_pairsβ public war-pair detectionshadbala_condition_profile,shadbala_chart_profile,shadbala_network_profilevalidate_shadbala_output
Part IV β Invariant Register
GrahaYuddha
victorβ{Mars, Mercury, Jupiter, Venus, Saturn}loserβ{Mars, Mercury, Jupiter, Venus, Saturn}victor β loser- Detected separation is
0 <= separation_deg < 1.0; the legacy vessel still permits1.0, but canonical ledger validation rejects such a fabricated detection.
PlanetShadbala
total_shashtiamsas = sthana_bala.total + dig_bala + kala_bala.total + chesta_bala + naisargika_bala + drig_balatotal_rupas = total_shashtiamsas / 60.0is_sufficient β total_rupas β₯ required_rupas
ShadbalaResult
ayanamsa_systemmust be non-empty.jdmust be a finite float.
validate_shadbala_output checks
- Each
planets[key].planet == key. total_rupas β total_shashtiamsas / 60(tolerance 1e-6).is_sufficientconsistent withtotal_rupasvsrequired_rupas.
Part V β Delegation Boundaries
| Responsibility | Delegated to |
|---|---|
| Vedic dignity rank | moira.vedic_dignities |
| Varga sign indices | moira.varga |
| Panchanga elements (Vara, Paksha) | moira.panchanga |
| Sunrise / sunset | moira.rise_set |
| Orbital elements (mandoccha) | moira.orbits |
| Sidereal conversion (tropical β sidereal) | moira.sidereal |
| Kernel state vectors | moira.spk_reader |
The core shadbala() function does not perform sidereal conversion. The
caller is responsible for supplying sidereal longitudes.
Part VI β Failure Doctrine
| Condition | Behavior |
|---|---|
tithi_number not in [1, 30] |
ValueError via shadbala() |
Required planet absent from sidereal_longitudes or planet_speeds |
KeyError propagated |
ShadbalaResult.ayanamsa_system empty |
ValueError in __post_init__ |
ShadbalaResult.jd non-finite |
ValueError in __post_init__ |
GrahaYuddha invariant breach |
ValueError in __post_init__ |
validate_shadbala_output inconsistency |
ValueError |
shadbala_network_profile with empty planets |
ValueError |
Part VII β Validation Notes
The following are verified by the test suite (tests/unit/test_shadbala.py,
92 tests as of P11 freeze):
- All NAISARGIKA_BALA, REQUIRED_RUPAS, MEAN_DAILY_MOTION canonical values.
chesta_bala: Raman Ch. X luminary solstices/elongations, Raman Ch. VI non-luminary Chesta Kendra, and backward-compatible speed-ratio cases.drig_bala: Jupiter/Saturn 7th-sign opposition, Mars special aspects, no-aspect β 0.kala_bala: local solar time, continuous phase/nature, actual thirds, declination rules and explicit AMVH inputs.sthana_bala: sub-component sum equals total.dig_bala: float in [0, 60]; at strong cusp β maximum.shadbalaintegration: 7 planets present; total_rupas = total_shashtiamsas / 60; is_sufficient correct; invalid tithi raises.- Vessel invariants: all vessels frozen, slots=True.
__all__surface: all exported names importable.validate_shadbala_output: valid result does not raise; planet-key mismatch raises.
The repair acceptance adds independent pair arithmetic, permutations, corrupted-ledger rejection and real May2000/December2020 chart/full/Lagna HTTP witnesses. See the linked current validation receipt.
Document produced at constitutional freeze (P11), April 2026.
REST admission and reader ownership β 8 October 2026
All six chart/result/profile/network/condition/Bhava/full routes use the
owning engine's reader-bound Shadbala call. They expose requested/applied
ayanamsa and requested/resolved/effective house systems in policy_receipt,
including actual polar fallback. Unknown house systems reject; registered
names and codes are admitted. That admission checkpoint did not change numerical Bala rules; the subsequent October9 repair above does. See the
VED-005 admission standard and its
verification receipt.
Direct-call and REST migration β 9 October 2026
shadbala(..., context=ctx) and kala_bala(..., context=ctx) now reject missing,
partial or contradictory context. sthana_bala requires all seven D1 positions
through sidereal_longitudes. Dated facade callers supply observer coordinates
or a context; REST derives one per request. REST strength planets are now
apparent geocentric positions; observer location controls houses and solar
geometry. Older topocentric REST positions were incompatible with that contract.
Output validation checks typed components, sums, Rupas, thresholds, context,
Saptavargaja evidence and every war ledger entry. Negative Ayana requires its
declination context; nonzero Yuddha requires its canonical ledger. Existing
legacy manually constructed zero-war results remain structurally admissible.
An internally inconsistent service result is a server error, not client 422.
Polar full-strength unavailability is typed 422 shadbala_context_unavailable;
Lagna keeps its independent evidence and explicit unavailable strength basis.
The public surface also includes ShadbalaContext, ShadbalaContextError,
derive_shadbala_context, SaptavargajaEntry, saptavargaja_breakdown and
WarResolution. Exact exports are tested. Required Rupas retain their existing
values, including Sun 6.5, as a separate Moira threshold convention.
Second adversarial pass: composition and receipt validation
Derived contexts declare vara_basis="civil_utc_midnight" and vara_jd_utc.
This preserves dated Panchanga's UTC weekday convention while all geometry
continues to use UT1. Dated adapters pass the original UTC JD; direct UT1
context derivation uses the time owner's inverse. The context checks that
the UTC evidence converts to its exact UT1 epoch and selects its Vara lord.
Legacy synthetic contexts retain vara_basis="supplied" with no UTC claim.
This does not attribute a UTC-midnight convention to a classical source;
ingress-based Abda/Masa conventions remain separately declared.
Context-backed validation recomputes Uchcha, Ojayugma, Drekkana and Drig from the accepted positions, as well as the existing Kala, Chesta, Saptavargaja and war checks. Positional ranges and discrete awards are enforced. Balanced component changes cannot pass merely by preserving sums. House-independent positional calculation and validation share one formula owner. Kendradi membership and Dig's range are checked, but their exact values cannot be reconstructed without house evidence, which is not carried in this context. Legacy context-free results receive structural validation; neither kind of supplied receipt proves the observational authenticity of caller data.
After compatibility checking, Lagna and Bhava consumers use the accepted context positions before discrete sign, Navamsa, house or aspect decisions. The 1e-9-degree comparison tolerance is unchanged. Lagna retains missing bodies and caller-supplied nodes; context evidence does not fill input gaps.