Astro Composer — Research and Convention Register
Status: Research appendix to the high-level design · Updated: 2026-10-24
This register records the rules the composer must pin, where implementations disagree, what the binder can supply, and how the result is validated. It lets a reviewer challenge a rule before it becomes a fixture.
Verdict. The composer is viable for natal charts, vargas and Vimshottari. Panchang and muhurta need rise/set first; transit scans need a timeseries read. Twenty convention rows must be pinned before the first fixture, and the register — not the tests — keeps two screens agreeing about the same birth data.
Six figures carry the parts that prose handles badly:
- Who owns which answer — the seam, and the three gaps in it (§2).
- One sky, two house frames — whole sign against cusps (§3.1).
- One ruler, three readings — nakshatra, pada and the dasha balance (§3.2, §3.5).
- One longitude, sixteen charts — varga mapping worked on Aries (§3.4).
- Five limbs, two rulers and a sunrise — tithi, karana, nakshatra, yoga and vara (§3.6).
- What a panchang day costs — batching, priced in binder calls (§5.2).
How to read this
| If you want to… | Read | The question it answers |
|---|---|---|
| Challenge a rule before it ships | §3, §4 | What is the quantity, and which convention pins it? |
| Implement one layer | §2, §3, §5 | What does the binder already give me? |
| Review the binder contract | §5, §8 | Which gap blocks which layer, and what settles it? |
| Check the evidence | §6, §7, §9 | What is prior art, how is it validated, what was read? |
Sections: 1 method · 2 baseline · 3 domain ledger · 4 convention register · 5 binder fit · 6 prior art · 7 validation · 8 experiments · 9 sources. Each §3 topic states what we need, the options, the chosen convention, why and the source.
1. Question and method
The question was narrow: can a chart composition layer sit on top of Astro Binder without reopening the astronomy contract, and what exactly would it own?
The method followed from it:
- Read the binder design and its component designs to fix the semantic boundary.
- Using published definitions, list every quantity a chart, panchang, dasha, transit, compatibility or muhurta response needs.
- Assign each quantity to astronomy (binder), base semantics (binder) or composition (composer).
- Find the seams where the binder contract cannot answer a composition question.
- Compare with prior art to separate real ambiguities from settled convention.
- Turn the ambiguities into a pinned register, then into a validation plan.
Encyclopaedias gave orientation only. Numeric rules are attributed to their traditional texts and need a fixture; a web page does not settle them.
2. What the baseline already provides
The composer reads one binder snapshot per chart; three inputs are still missing.
Rise/set, a timeseries read and cusp-based house placement are not on the wire yet. Reference design, not current repository behaviour.
| Composer output | Needs from the binder | Already available? |
|---|---|---|
| Body longitude and speed | positions |
Yes |
| Sign, degree in sign | positions |
Yes |
| Nakshatra, pada | positions |
Yes |
| Retrograde state | positions |
Yes |
| House cusps, ascendant, midheaven | houses |
Yes |
| Which house holds a body | cusps + placement; sign ids for whole sign | Cusps yes, cusp placement not exposed (gap 3) |
| Aspect geometry | positions + orb profile |
Semantics owns it, response does not expose it |
| Sunrise and sunset | rise/set | No (gap 1) |
| Many instants at once | batch or timeseries | No (gap 2) |
| Declination | ecliptic latitude + obliquity | No |
The first seven rows are reads; the rest are calls the composer must make. The last four explain why the HLD proposes small binder extensions, not a larger composer.
3. Domain ledger
Each quantity is what the rulebook will encode: an index, a fraction or a table lookup over a binder longitude. None is astronomy.
| Layer | Answers | The trap that breaks it |
|---|---|---|
| Chart frame §3.1 | which house holds a body | mixing whole-sign and cusp frames in one chart |
| Nakshatra and pada §3.2 | which segment of the zodiac a body sits in | recomputing what the binder already returned |
| Dignity and combustion §3.3 | how strong a body is | treating a variant table as a constant |
| Divisional charts §3.4 | sixteen derived charts | chaining one varga into another |
| Vimshottari §3.5 | when a period runs | year length and a rounded Moon longitude |
| Panchang §3.6 | the five limbs of a day | taking the tithi at local midnight |
| Transits §3.7 | what is active now | implicit ashtakavarga reductions |
| Ashtakoota §3.8 | how two charts match | a score without its doshas |
| KP §3.9 | star, sub and sub-sub lord | an unpinned sub division count |
| Muhurta §3.10 | when to act | one algorithm for every purpose |
3.1 Chart frame
What we need. Houses for a chosen reference: usually the ascendant (lagna), sometimes the Moon (gochara, Sade Sati) or the Sun (some vargas). The binder gives the angle; the composer picks the frame, places bodies and orders the chart.
At lagna 17° Leo, the Sun at 5° Leo is house 1 by whole sign and house 12 by cusps; Mars at 3° Virgo is house 2 and house 1. Equal cusps keep the figure legible; unequal systems move boundaries further.
Options.
- Whole sign. House 1 is the lagna’s sign, house 2 the next:
((bodySign − lagnaSign) mod 12) + 1. The Vedic default. - Cusp based. The cusp interval containing the longitude, walked forward and wrapped at 360°. Placidus, Koch, equal and Sripati produce it; KP uses it.
Chosen. The profile declares one system; a chart never mixes them. Whole-sign occupancy is composer arithmetic on two sign ids. Cusp occupancy is interval arithmetic owned by binder semantics, so a cusp profile cannot name a house until placement is exposed.
Why. Cusps can put a body in a different house from its sign — Sun in Leo house 12, Mars in Virgo house 1 — so a whole-sign drawing is wrong. At high latitude a body can be in house 2 while in the lagna’s sign. The composer never infers the system from the drawing.
Source. §9, Swiss Ephemeris programming interface (house systems, house position); C3.
3.2 Nakshatra and pada
What we need. The nakshatra and pada holding a body: 27 nakshatras of 13°20′ (13.3333°), each in four padas of 3°20′ (3.3333°):
nakshatra = floor(siderealLongitude / 13.3333…)
pada = floor((siderealLongitude mod 13.3333…) / 3.3333…) + 1
Options. Recompute both, or use the binder’s values.
Chosen. Use the binder’s values; the composer never recomputes them.
Why. Recomputing invites boundary disagreement. Padas feed the Vimshottari balance and the KP sub-lord division, both starting from the same 13°20′ segment.
One ruler, three readings: 27 nakshatras against 12 signs, one nakshatra in four padas, and the same fraction as the Vimshottari balance. A Moon at 8°20′ is 62.5% through Ashwini, so 62.5% of Ketu’s seven years is spent at birth: 4.4 elapsed, 2.6 remaining.
Source. §9, Astrology semantics (the base layer the composer consumes); §3.5; §3.9.
3.3 Dignity and combustion
What we need. Dignity, combustion and planetary war. They need sign ownership, exaltation degrees, moolatrikona ranges and distance from the Sun.
Options. One table in code, or versioned rulebook data.
Chosen. Every threshold lives in the rulebook, and the response names it.
- Dignity is a table: own sign, exalted, debilitated, moolatrikona, friend, neutral, enemy. Ownership follows classical lordships; exaltation and debilitation are single degrees; moolatrikona is a range inside the own sign.
- Combustion is a distance threshold from the Sun. It differs per planet and, in some schools, between direct and retrograde motion.
- Planetary war applies to two non-luminous planets within one degree; the common rule takes the lower longitude as victor.
Why. Each is a table with variant editions, so a constant would freeze one school’s choice.
Source. C12 (dignity), C13 (combustion orbs).
3.4 Divisional charts
What we need. Sixteen Shodasavarga charts. Each divides a sign into equal parts (except D30) and maps each part to a sign.
Options.
- Chain one varga into another, or map every varga from D1.
- Parashara, Raman or KP starting rules for D10, D16, D20, D40 and D45, and different treatments of D30.
Chosen. Every varga is computed from the D1 longitude, never from another varga. Starting rules are a rulebook table per varga.
| Varga | Parts | Common starting rule |
|---|---|---|
| D1 rasi | 1 | The sign itself |
| D2 hora | 2 | Halves map only to Cancer and Leo, reversed in even signs |
| D3 drekkana | 3 | First part same sign, then the 5th and 9th from it |
| D4 chaturthamsha | 4 | Same sign, then the 4th, 7th and 10th |
| D7 saptamsha | 7 | Odd signs start from the sign, even signs from the 7th |
| D9 navamsha | 9 | Movable same sign, fixed the 9th, dual the 5th |
| D10 dashamsha | 10 | Odd signs from the sign, even signs from the 9th |
| D12 dwadashamsha | 12 | From the sign itself |
| D16 shodashamsha | 16 | Movable Aries, fixed Leo, dual Sagittarius |
| D20 vimshamsha | 20 | Movable Aries, fixed Sagittarius, dual Leo |
| D24 chaturvimshamsha | 24 | Odd signs Leo, even signs Cancer |
| D27 saptavimshamsha | 27 | Fire Aries, earth Cancer, air Libra, water Capricorn |
| D30 trimshamsha | 30 | Unequal parts: 5, 5, 8, 7, 5 degrees, reversed in even signs |
| D40 khavedamsha | 40 | Odd signs Aries, even signs Libra |
| D45 akshavedamsha | 45 | Movable Aries, fixed Leo, dual Sagittarius |
| D60 shashtiamsha | 60 | Counted from the sign itself |
All sixteen charts are pure mappings from one D1 longitude. Worked on Aries: D9 in nine parts of 3°20′ (part 1 keeps the sign, so it is vargottama), D10 in ten parts of 3°, and D30’s unequal 5/5/8/7/5 division.
Why. Vargas map one longitude, so they are pure and cheap: sixteen charts for nine bodies is arithmetic, not I/O. Starting rules vary by edition and software, so they are a rulebook entry, not a code branch. A D9 returning the D1 sign is vargottama; it falls out of the mapping for movable signs and must not be special-cased.
Source. §9, Brihat Parashara Hora Shastra (varga definitions; editions differ, so E3 needs a named edition) and the Varga entry; C9, C10, C11.
3.5 Vimshottari dasha
What we need. Dated periods at two, three or four levels. The sequence is fixed and sums to 120 years:
| Lord | Ketu | Venus | Sun | Moon | Mars | Rahu | Jupiter | Saturn | Mercury |
|---|---|---|---|---|---|---|---|---|---|
| Years | 7 | 20 | 6 | 10 | 7 | 18 | 16 | 19 | 17 |
Nakshatra lords follow the same order from Ketu at Ashwini. At birth the Moon sits inside one nakshatra, so the first mahadasha is partly spent:
elapsed = (moonLongitude mod 13.3333…) / 13.3333…
firstLord = nakshatraLord(moonNakshatra)
balance = (1 − elapsed) × years(firstLord) × yearLength
The first period ends at birth + balance and nominally starts at birth − elapsed × years × yearLength. Antardashas begin with the mahadasha lord and follow the sequence, each lasting years(subLord) / 120 × duration(mahadasha); pratyantardashas subdivide the same way. Periods tile the timeline with no gaps or overlaps, a cheap and strong invariant. The §3.2 figure’s third band shows Ketu’s spent and remaining parts.
Options. Year lengths of 365.25, 360 or 365.2425 days; rounded or full-precision Moon longitude.
Chosen. Year length is a profile field, default 365.25. The balance uses the binder’s full-precision longitude.
Why. Over 120 years the year-length difference reaches months. At 0.55 arcsec per second of time, one arcsecond moves a dasha boundary about two seconds, so reproducibility needs full precision.
Source. §9, Dasha entry; §3.2; C4, C5.
3.6 Panchang
What we need. Five limbs for a local day, plus the instant each ends. All reduce to the Sun–Moon elongation e = (moon − sun) mod 360 and the sidereal Moon longitude:
| Limb | Definition | Index |
|---|---|---|
| Tithi | 12° of elongation | floor(e / 12) + 1, 1–30 |
| Vara | Weekday, sunrise to sunrise | Derived from the sunrise instant |
| Nakshatra | 13°20′ of sidereal Moon | floor(moon / 13.3333…) |
| Yoga | 13°20′ of (sun + moon) mod 360 |
floor((sun + moon) / 13.3333…) |
| Karana | 6° of elongation, half a tithi | floor(e / 6) + 1, 1–60 |
Elongation decides tithi and karana; a 13°20′ segment decides nakshatra and yoga; sunrise decides vara. The lower band shows a tithi that is never current at sunrise (kshaya) and one that is current at two consecutive sunrises (adhika).
Options. Take the tithi at local midnight or at sunrise. Set the day boundary at sunrise, midnight or noon. Report kshaya and adhika tithis, collapse them, or error.
Chosen. Hindu sunrise defines the day; the day’s tithi is the one running at sunrise. Kshaya and adhika are reported explicitly. Karana cycles through seven movable and four fixed names, sixty per lunar month. The engine returns crossing instants, not just indices, because users need “tithi ends at 14:32”.
Why. A midnight tithi disagrees with published almanacs on some days. Tithi is not a clock unit: a varying elongation rate makes it last roughly 20 to 27 hours. It can be kshaya (starts after one sunrise, ends before the next, so the day list skips it) or adhika/vriddhi (present at two consecutive sunrises, so it repeats); the response must represent this, not deduplicate it. Panchang alone hard-depends on binder rise/set, for definitional reasons: without sunrise there is no vara and no correct day tithi.
Source. §9, Panchangam and Tithi entries; C6, C7, C8.
3.7 Transits, Sade Sati and ashtakavarga
What we need. What is active now: gochara, Sade Sati and ashtakavarga scores.
Options.
- Gochara house readings per planet, with or without vedha (obstruction) points that cancel a good transit.
- Sade Sati from the Moon sign, or from the 45° of zodiac before the Moon.
- Ashtakavarga reductions: none, trikona or ekadhipatya shodhana.
Chosen.
- Gochara compares a transiting body’s sign to the natal Moon sign. Classical readings give favourable and unfavourable houses per planet; vedha is an optional first-slice table.
- Sade Sati follows the profile’s definition. The Moon-sign reading is Saturn through the 12th, 1st and 2nd signs from the natal Moon, roughly 7½ years at ~2½ years per sign; the 45° reading starts months earlier.
- Ashtakavarga assigns benefic points (bindus) to signs from eight contributors — seven planets and the lagna — using fixed house-offset tables. Each planet’s twelve-sign pattern is its Bhinna Ashtakavarga (BAV); the seven BAVs sum to the Sarvashtakavarga (SAV), 337 bindus in the standard scheme.
- Reductions change scores, so they are a rulebook feature flag, never an implicit default.
Why. A score without its basis is not comparable, and reductions silently change scores. The 337 total catches table typos: one mistyped contribution breaks it.
Source. §9, Sade Sati entry; C15, C16, C17. Composition is I/O-bound here: a year of daily transits is 365 instants, each a binder read.
3.8 Ashtakoota matching
What we need. A compatibility score for two charts: eight kootas, 36 points.
| Koota | Max | Basis |
|---|---|---|
| Varna | 1 | Moon-sign class |
| Vashya | 2 | Sign group and attraction |
| Tara | 3 | Count of nakshatras between the two Moons |
| Yoni | 4 | Animal symbol of the nakshatra |
| Graha Maitri | 5 | Sign-lord friendship |
| Gana | 6 | Deva, manushya, rakshasa class |
| Bhakoot | 7 | Sign distance between the Moons |
| Nadi | 8 | Nadi class of the nakshatra |
Options. Return the score alone, or with per-koota verdicts. Apply no cancellations, or the Nadi and Bhakoot exceptions several schools define.
Chosen. Return both the score and the per-koota verdict; cancellations are explicit rulebook entries.
Why. The traditional threshold is 18 of 36, but the kootas are not additive in meaning. Nadi and Bhakoot doshas have cancellation rules, and a score without the dosha list misleads.
Source. §9, Astrological compatibility entry; C18.
3.9 Krishnamurti Paddhati
What we need. The KP lord hierarchy — star, sub and sub-sub lord — plus significators.
Options. Keep the Lahiri whole-sign profile, or use KP: the KP ayanamsa (krishnamurti in the binder), Placidus cusps and a finer hierarchy.
Chosen.
- Star lord is the nakshatra lord.
- Sub lord divides the 13°20′ nakshatra into nine parts proportional to the Vimshottari years, starting from the star lord; Ashwini’s first sub is Ketu’s, and the sequence follows the dasha order.
- Sub-sub lord repeats the division inside a sub. KP readings use the hierarchy to decide “will this happen”.
- Significators come from cusp sub-lords and house occupancy: a composition over cusps and planets, not a new astronomical input.
Why. The mechanism is clear; the bookkeeping is not. Sources quote the sub division total inconsistently — 243 by nine-way division, other counts elsewhere — so the count and the treatment of sign-crossing subs need a primary KP source.
Source. E4; C19.
3.10 Muhurta
What we need. An auspicious window: a muhurta is 48 minutes (thirty per day). Practical selection is a filter over a date range.
Options. One universal algorithm, or versioned rulebooks per purpose.
Chosen. Versioned muhurta packs. A pack filters on acceptable tithi, nakshatra, yoga and vara for the purpose, a suitable lagna, and exclusion of inauspicious day divisions such as Rahu kala, Yamaganda and Gulika, plus panchaka periods. Abhijit muhurta, around local noon, is a common inclusion.
Why. The rules are purpose-specific and numerous: a wedding pack and a travel pack are different rulebooks over the same panchang facts. Packs keep the engine honest and the disagreement auditable.
Source. C20; each pack carries its own table.
4. Convention register
Each row is a place where two competent implementations can differ. The rulebook pins one choice per row, and the response names it.
| # | Convention | Options seen | Decision |
|---|---|---|---|
| C1 | Ayanamsa | Lahiri, Raman, KP, Fagan–Bradley | Profile field; binder applies it |
| C2 | Node type | Mean, true | Profile field; affects nakshatra boundaries |
| C3 | House frame | Whole sign, equal, Placidus, Sripati, Koch, Campanus | Profile field; never mixed |
| C4 | Dasha year | 365.25, 360, 365.2425 days | Profile field, default 365.25 |
| C5 | Dasha depth | 2, 3, 4 levels | Request field with a cap |
| C6 | Sunrise definition | Hindu (disc centre, no refraction), astronomical | Profile field; panchang uses Hindu |
| C7 | Day boundary | Sunrise, midnight, noon | Panchang uses sunrise |
| C8 | Kshaya/adhika tithi | Report, collapse, error | Report explicitly |
| C9 | Varga schemes | Parashara, Raman, KP variants for D10/D16/D20/D40/D45 | Rulebook table per varga |
| C10 | D30 divisions | 5/5/8/7/5, reversed in even signs | Rulebook table |
| C11 | Varga recursion | From D1 only | Fixed by design |
| C12 | Dignity table | Classical lordships, moolatrikona ranges | Rulebook table |
| C13 | Combustion orbs | Per planet, retrograde variants | Rulebook table |
| C14 | Aspect set | Vedic drishti, Western orbs, KP | Profile field |
| C15 | Sade Sati basis | Moon sign, 45° before Moon | Profile field |
| C16 | Vedha | Included, excluded | Optional table |
| C17 | Ashtakavarga reductions | None, trikona, ekadhipatya | Rulebook feature flag |
| C18 | Koota cancellations | None, Nadi/Bhakoot exceptions | Rulebook table |
| C19 | KP sub division count | 243 by nine-way division; other counts quoted | Primary source required |
| C20 | Muhurta exclusions | Rahu kala, Yamaganda, Gulika, panchaka | Per-pack table |
The register is the review artefact: a pull request that changes an engine number without touching a row here is a defect, even if the tests pass.
5. Binder fit analysis
The binder answers most reads. Three gaps decide the delivery order.
5.1 Capability matrix
| Needed capability | Binder today | Fit |
|---|---|---|
| Positions for one instant | POST /v1/positions |
Direct |
| Houses and angles | POST /v1/houses |
Direct |
| Signs, nakshatras, padas | In positions |
Direct |
| Motion state | In positions |
Direct |
| Aspects | In semantics, not on the wire | Seam |
| House placement | In semantics, not on the wire | Seam |
| Sunrise/sunset | Out of scope for the first slice | Gap |
| Many instants | One instant per call | Gap |
| Declination | Not in contract | Optional gap |
| Provenance | meta block |
Direct |
5.2 What the gaps cost
A panchang day needs sunrise and four or five elongation boundaries: tithi end, nakshatra end, yoga end, karana end, next sunrise. Bisection over a 24-hour window takes about 17 evaluations of both bodies per boundary:
17 iterations × 2 bodies = 34 calls per boundary
5 boundaries ≈ 170 calls per panchang day
With includeSpeed and a Newton step, convergence takes three to five evaluations, or roughly 20–50 calls. A timeseries endpoint returning a grid plus speeds does the day in two or three calls. A 30-day muhurta scan and a year of transits scale the same way, into thousands.
Five boundary solves priced in binder calls. Bisection misses the ≤ 50-call budget by more than three times; a timeseries read beats it by an order of magnitude.
So batching is a phase 3 gate, not an optimisation. Without it, panchang is expensive and scans are impractical; avoiding the cost would mean interpolating an ephemeris inside the composer — the boundary the design exists to hold.
5.3 Proposed additions
| Addition | Shape | Used by | Phase |
|---|---|---|---|
POST /v1/rise-set |
Bodies, observer, events, horizon set to hindu or astronomical |
Panchang, muhurta, upagraha | Composer phase 2 |
POST /v1/timeseries |
Bodies, start, end, step, includeSpeed | Transits, muhurta | Composer phase 3 |
houses block on positions |
{ "system": "whole_sign" }; per-body house |
Chart core, KP | Composer phase 0/1 |
aspects block |
Bodies plus named orb profile | Yogas, matching, western | Composer phase 3 |
| Declination | declination per body, or obliquity in meta |
Western parallels | Optional |
The rise/set definition is not an implementation detail. Swiss Ephemeris separates astronomical sunrise (upper limb, refracted) from the Hindu definition (disc centre at the horizon, no refraction, geocentric, solar latitude ignored), and exposes the latter as a dedicated flag. Panchang uses the Hindu day, so the endpoint must carry the definition in the request and echo it in provenance; otherwise a boundary is off by minutes and nobody notices.
5.4 Alternatives considered
| Option | Why it was rejected |
|---|---|
| Composer calls Swiss Ephemeris directly | Duplicates provider routing and the licence decision; two sources of “where” |
| Fold composition into the binder | Contradicts the binder’s stated out-of-scope list and grows a service whose value is a narrow contract |
| Composer as a library inside each product service | Loses central versioning and provenance; every service would pin a different rulebook |
| Composer computes its own positions for panchang only | The narrow exception would be the first duplicate, and would drift at boundaries |
| Persist charts in the composer | Makes a stateless calculator into an owner of personal data with no product reason |
The chosen shape — a stateless composition service that reads the binder — is the only one where the astronomy contract stays closed and the conventions have a single home.
6. Prior art
- PyJHora ports Vedic Astrology: An Integrated Approach and Jagannatha Hora in Python, with roughly 6,800 tests and a Lahiri default. It shows a large but tractable feature surface, and that almost every test assumes a fixed ayanamsa — the implicit default this design refuses. AGPL-3.0: behavioural reference only, with no code or table copied without legal review.
- Jagannatha Hora is what most users compare against, so fixtures should reproduce its conventions; differences should trace to a register row, not a bug.
- Commercial astrology APIs expose one endpoint per feature with a plan-based quota, supporting the HLD’s small endpoint set: callers expect a feature endpoint, not a general expression language.
- Swiss Ephemeris is not prior art for composition. It supplies houses and rise/set primitives, says nothing about vargas, dashas or panchang, and defines rise/set and polar-circle behaviour precisely enough for the binder to own once.
7. Validation plan
Validation asks three things: is the arithmetic right, is the convention intended, and is the service reproducible. Sections 7.1–7.2 cover arithmetic, 7.3–7.6 convention and boundaries, 7.7–7.8 reproducibility and cost, 7.9 negative paths.
7.1 Formula tests. Pure unit tests per engine: tithi index across a lunation, pada boundaries, Vimshottari balance at a nakshatra start and end, D9 vargottama for a movable sign, D30 unequal divisions in odd and even signs.
7.2 Invariants. Cheap properties that catch table typos:
- SAV totals 337 bindus for every chart.
- Vimshottari periods tile 120 years continuously, in order, with no gap or overlap at any level.
- Every body belongs to exactly one house in both frame conventions.
- Tithi index is in 1–30, pada in 1–4, nakshatra in 0–26.
- A varga mapping is total: every one of the 30° of a sign maps to exactly one sign.
- Sub-period boundaries nest inside their parent period.
7.3 Boundary tests. Longitudes exactly on 30°, 13°20′, 3°20′ and tithi multiples; a body on a cusp; a retrograde station; birth on a dasha boundary. Half-open intervals must match binder semantics so a sign never differs between services.
7.4 Golden fixtures. Charts from a few birth data points across cities, epochs, both hemispheres and one polar case, rendered under each profile and stored as JSON with the four version identifiers. A fixture diff is a review gate. Include a Lahiri whole-sign chart, a KP chart with Placidus cusps, and a DST-ambiguous birth time resolved by the caller.
7.5 Almanac comparison. Compare panchang tithi, nakshatra, yoga, karana and sunrise with a published almanac for 30 consecutive days in two cities: sunrise within a minute, indices exact, kshaya and adhika days in the same places.
7.6 Cross-service consistency. For the same instant and body, chart sign and nakshatra must equal the binder’s, and panchang sunrise must equal the rise/set response. Divergence is a boundary violation, not rounding.
7.7 Determinism. The same request in two JVM instances with different locale and timezone settings must produce byte-identical output. Any clock, hash-order or locale dependency fails.
7.8 Performance. Load tests against a binder stub at the section 14 targets, plus one real-binder test to measure boundary-solve cost and how urgent batching is.
7.9 Negative tests. Unknown profile, unknown rulebook, unsupported layer, polar Placidus, ephemeris range edge, missing observer for houses, and allowPartial.
8. Experiments before implementation
| # | Experiment | Question it settles |
|---|---|---|
| E1 | Time a boundary solve against the real binder, bisection versus Newton | Whether panchang can ship before timeseries |
| E2 | Compare three reference implementations on 100 random charts | Which layers need fixtures rather than trust |
| E3 | Implement the varga table and diff all sixteen against one reference | Which starting rules are actually in use |
| E4 | Read a primary KP source for sub and sub-sub boundaries | Convention C19 |
| E5 | Render a Placidus chart above the polar circle through the binder | How the composer reports the refusal |
| E6 | Measure a full 16-varga, three-level dasha response | Whether the 64 KB target holds |
E1 and E2 are the gates: E1 decides the phase 2 dependency, E2 decides how much of the fixture set can be automated rather than hand-checked.
9. Sources
Accessed 2026-10-24. Encyclopaedic sources gave orientation; numeric rules are attributed to the traditional texts and must be confirmed against a primary edition during E3/E4.
- Swiss Ephemeris programming interface — rise/set definitions (
SE_BIT_HINDU_RISING), house systems, polar-circle behaviour, house position: https://www.astro.com/swisseph/swephprg.htm - Swiss Ephemeris licence and general information: https://www.astro.com/swisseph/swephinfo_e.htm
- Astro Binder design, including the semantics boundary and canonical contract: …/…/ephemeris/binder/README.md
- Astrology semantics — the base layer the composer consumes: …/…/ephemeris/binder/astrology-semantics/README.md
- Panchangam — limbs, almanac practice, regional variation: https://en.wikipedia.org/wiki/Panchangam
- Tithi — 12° elongation and lunar-day variability: https://en.wikipedia.org/wiki/Tithi
- Dasha — Vimshottari as the prevalent system, 120-year cycle: https://en.wikipedia.org/wiki/Dasha_(astrology)
- Varga — sixteen divisions and Shodasavarga: https://en.wikipedia.org/wiki/Varga_(astrology)
- Sade Sati — Saturn through the 12th, 1st and 2nd from the Moon: https://en.wikipedia.org/wiki/Sade_Sati
- Astrological compatibility — synastry background and the Vedic koota tradition: https://en.wikipedia.org/wiki/Astrological_compatibility
- PyJHora — feature surface, test count, Lahiri default, AGPL-3.0 licence: https://github.com/naturalstupid/PyJHora
- Prokerala astrology API documentation — commercial endpoint-per-feature shape: https://api.prokerala.com/docs
- Brihat Parashara Hora Shastra — varga definitions and ashtakavarga contribution tables; editions differ, so a named edition is required for E3.