Gochara

Jyotisha Decision Intelligence

How the score is built

Below is the working specification for the scoring model, published as it is maintained — the same document the code is reviewed against, not a summary written for this page. It includes the parts that say we cannot support a claim.

The short version: the astronomy is externally verified and accurate to about an arcminute. The interpretation layer on top of it has not been reviewed by a qualified practitioner, and the weights come from a strategy brief that never recorded how they were derived. That is stated here rather than discovered later.

Kept at docs/specs/scoring-model.md in the source repository. If this page and that file ever disagree, the file is correct.

Status: UNVALIDATED. Written 2026-08-27, revised 2026-08-30 for scoring revision 2 (ADR 0010). Roadmap 2.4.

This is the audit trail for every number the interface displays. It exists to be handed to a credentialed Jyotish scholar, so it is written to be falsifiable: each signal states what the engine actually computes, which part of that is classical convention, and which part is an encoding decision we made up.

Nobody qualified has reviewed any value in this document. The "Validated by" column reads nobody throughout. That is the project's largest open risk (roadmap 2.1), and this spec is the artifact that makes it reviewable rather than merely admitted.


1. The formula

Q(t, p, d) = Σᵢ wᵢ(d) · xᵢ(t, p)        for i ∈ {tithi, nakshatra, dashaLord, transit, yogaDosha}

score = round( 100 · clamp₀¹( Q ) )

Implementation: lib/jyotisha/score.ts. Tables: lib/jyotisha/constants.ts.

The central distinction in this document. Classical texts classify — this nakshatra is auspicious, that tithi is rikta. They do not assign cardinal numbers. Every decimal below is ours. So a signal can be simultaneously correctly classified and arbitrarily quantified, and most of them are. When the ordering is classical but the magnitude is invented, this document says so.


2. Signal-by-signal

2.1 Tithi — x_tithi

Computes: lunar day 1–30 → quality. TITHI_QUALITY[tithi.num - 1], default 0.5 if out of range.

The waxing (Shukla) table, by classical five-group cycle:

GroupTithisValuesClassical reading
Nanda1, 6, 110.70, 0.70, 0.72ordinary
Bhadra2, 7, 120.75, 0.78, 0.78favourable
Jaya3, 8, 130.78, 0.82, 0.80favourable
Rikta4, 9, 140.40, 0.40, 0.45avoided for beginnings
Purna5, 10, 150.90, 0.90, 0.92strong

Waning (Krishna, 16–30) is the same table shifted by a flat −0.12, floored at 0.20.

Classical basis: the Nanda/Bhadra/Jaya/Rikta/Purna cycle and the avoidance of rikta tithis are standard and widely published. The engine's grouping matches it exactly.

Ours, not classical:

⚠ Probable defect — Amavasya. Tithi 30 (Amavasya, new moon) inherits Purnima's 0.92 less 0.12 = 0.80, which makes it the highest-scoring of all fifteen waning tithis. Classical practice generally avoids Amavasya for auspicious beginnings while valuing it for ancestral rites. The engine currently recommends it. This looks like an artifact of tithis 15 and 30 sharing one table slot ("Purnima/Amavasya"), not a considered ruling. Flagged for correction pending review.

2.2 Nakshatra — x_nakshatra

Computes: Moon's nakshatra 1–27 → quality. NAKSHATRA_QUALITY[num - 1].

Highest: Pushya 0.95, Rohini 0.92, Hasta 0.88, Anuradha 0.88. Lowest: Ashlesha 0.30, Mula 0.30, Bharani 0.35, Ardra 0.40, Jyeshtha 0.40.

Classical basis: the ranking is consistent with commonly published convention — Pushya and Rohini are widely held as among the most auspicious; Mula, Ashlesha, Jyeshtha and Ardra among the most difficult. Nothing in the ordering looks obviously wrong.

Ours, not classical:

2.3 Dasha lord — x_dashaLord

Computes (revision 2):

quality(lord) = natural(lord) · (1 − FUNCTIONAL_BLEND)
              + standing(lord) · FUNCTIONAL_BLEND

x = 0.6 · quality(Mahadasha lord) + 0.4 · quality(Antardasha lord)

where natural is PLANET_NATURAL_QUALITY (Jupiter 0.95, Venus 0.88, Mercury 0.78, Moon 0.78, Sun 0.60, Mars 0.50, Saturn 0.40, Rahu/Ketu 0.35) and standing is the lord's functional value for this Lagna:

standing = ROLE_VALUE[role] · DIGNITY_FACTOR[dignity]
RoleValueDignityFactor
yogakaraka0.95exalted×1.15
benefic (trikona lord)0.80own sign×1.10
neutral0.50none×1.00
malefic (dusthana lord)0.30debilitated×0.75

FUNCTIONAL_BLEND = 0.5. Falls back to 0.5 when no Dasha period resolves.

Revision 1 used natural alone. That is the version §6.1 called the largest correctness gap, and it is retained only so a reviewer can compare.

Classical basis: the benefic/malefic ordering is standard naisargika (natural) beneficence. Vimshottari itself is implemented correctly — the nine lords total 120 years, seeded from the natal Moon's nakshatra lord.

Classical basis, added in revision 2: the rulerships, the kendra/trikona/dusthana classification, the yogakaraka rule and the exaltation degrees are all standard Parashari. The yogakaraka derivation is tested against the published set — deriving Saturn for Taurus and Libra, Mars for Cancer and Leo, Venus for Capricorn and Aquarius, and none for the other six ascendants, from the rulerships alone.

Ours, not classical:

Still absent:

2.4 Transit / house activation — x_transit

Computes: for each active anchor, place all nine transiting planets into whole-sign houses counted from that anchor, then:

value = Σ strength(p)                    for p in domain-positive houses
      + Σ strength(p) · 0.4              for p in domain-negative houses
      ─────────────────────────────────
        count of planets in either set

Revision 2 reads strength(p) from Ashtakavarga — the planet's own Bhinnashtakavarga bindu count for the sign it is actually transiting, over 8. Revision 1 used the planet's natural beneficence, which is a property of the planet rather than of the transit: Jupiter contributed 0.95 wherever it stood.

Planets in neither set are ignored. If no planet falls in either set, value = 0.5. With reference: "both", the Lagna and Moon readings are averaged.

DomainPositive housesNegative houses
career10, 6, 11, 18, 12
finance2, 11, 5, 96, 8, 12
relationships7, 5, 4, 116, 8, 12

Classical basis: whole-sign houses and Gochara-from-an-anchor are standard. The house significations are conventional (10th career, 2nd/11th wealth, 7th partnership, 6/8/12 the dusthanas). Note career treats the 6th as positive (competition, service) while finance and relationships treat it as negative — defensible, but a deliberate inconsistency a reviewer should confirm.

Ours, not classical:

⚠ An undecided default — the node. ephemeris.ts computes Rahu and Ketu from the mean node (Meeus ch. 47), and the comment beside it shows why: so the calculation "stays analytic". That is an implementation convenience, not a doctrinal choice. Mean and true node differ by up to 1.5° — enough to move a node across a sign boundary and flip a dosha result — and most current Vedic software defaults to the true node while the mean is described as the traditional reading.

This is the same shape as the transit anchor before ADR 0006: a default that happened rather than one that was decided. Unlike the anchor, its impact has not been measured. Added to §6 as a question.

Anchor choice. DEFAULT_TRANSIT_REFERENCE = "moon" (ADR 0006), configurable to lagna or both. Measured: the anchor shifts the score only ~3.7 points on average but changes the displayed band label in 25.9% of cases. Classically defensible, not scholar-ruled. One constant is the whole switch.

2.5 Yoga + Dosha — x_yogaDosha

Computes:

x = max(0, 0.5 · yogaQuality + 0.5 · varaQuality(domain) − sadeSatiPenalty)

where sadeSatiPenalty = 0.25 when active, else 0.

Yoga (YOGA_QUALITY, 1–27): the nine traditionally inauspicious yogas — Vishkumbha, Atiganda, Shoola, Ganda, Vyaghata, Vajra, Vyatipata, Parigha, Vaidhruti — are scored 0.30 or below, the rest 0.78–0.95. The classification matches published convention exactly. The magnitudes are ours.

Vara (VARA_QUALITY): the only table that is genuinely domain-specific. Thursday (Jupiter) is strongest for career 0.90 and finance 0.90; Friday (Venus) strongest for relationships 0.95; Tuesday (Mars) and Saturday (Saturn) weakest for relationships at 0.40. Directionally conventional, numerically ours. Rahu and Ketu are given 0.5 across all domains — unreachable, since no weekday is ruled by a node.

Sade Sati: Saturn transiting the 12th, 1st or 2nd from the natal Moon sign — correctly defined, and correctly pinned to the Moon regardless of the transit anchor setting. The 0.25 penalty magnitude is ours, and it is applied as a flat subtraction with no distinction between the three phases, which classical practice does distinguish.

Not scored: Karana is computed and displayed but never enters the score. Abhijit muhurta is computed and drawn on the planner rail but carries no weight. The Navamsa (D9) was added 2026-08-30 and is likewise displayed only — see below.

2.6 Activity fit — optional, and outside Q

Added 2026-08-30 (ADR 0011). Not a sixth signal. Q(t,p,d) is unchanged; this is a bounded adjustment applied after it, only when the user says what they are about to do.

Computes: the Moon's nakshatra has one of seven classical natures, and each act is suited to some and not others.

NatureNakshatras
DhruvafixedRohini, Uttara Phalguni, Uttara Ashadha, Uttara Bhadrapada
CharamovablePunarvasu, Swati, Shravana, Dhanishta, Shatabhisha
UgrafierceBharani, Magha, Purva Phalguni, Purva Ashadha, Purva Bhadrapada
KshipraswiftAshwini, Pushya, Hasta
MridutenderMrigashira, Chitra, Anuradha, Revati
TikshnasharpArdra, Ashlesha, Jyeshtha, Mula
MishramixedKrittika, Vishakha
delta = round( (fit − 0.5) × 2 × ACTIVITY_MAX_SHIFT )
adjusted = clamp₀¹⁰⁰( domainScore + delta )

ACTIVITY_MAX_SHIFT = 15. Rikta lunar days (the 4th, 9th and 14th of each fortnight) take a further −0.2 on the fit when an act is being begun.

Classical basis: the seven-fold classification and the acts each nature favours are standard and widely published, as is the avoidance of rikta tithis for beginnings.

Ours, not classical:

Why additive and bounded rather than multiplicative. Multiplying would let a badly-suited act crush an otherwise strong moment toward zero, which overstates what this layer knows. The activity says what kind of moment this is; the domain score says whether the moment is good for this person at all. The second is better evidenced, so it stays primary. A hard block stays a hard block — no act is well-timed inside rahukaal.

Measured: over a 30-day range on one chart, choosing an act moved 542 of 721 samples and changed the top-ranked window — "anything" returned 4 September, "signing" 3 September, "travel" 22 September.

2.7 Divisional charts — computed, displayed, deliberately not scored

The Navamsa (D9) divides each sign into nine parts of 3°20′ and reads the part a planet falls in as a sign of its own. It is the most used of the vargas, and classical practice treats it as a second opinion on the strength a planet's Rashi placement implies. A planet in the same sign in both is vargottama.

Classical basis, and a pleasing check. Texts state the rule as three cases by sign quality — movable signs count from themselves, fixed from the 9th, dual from the 5th. A single continuous division of the circle into 108 reproduces all three cases exactly, so the implementation is one line, and the tests assert it agrees with the classical rule for all twelve signs rather than assuming it does.

Nothing here is ours, which is unusual in this document: there are no magnitudes to invent, because the Navamsa is a division rather than a weighting.

And it is not scored. Feeding it into Q(t,p,d) would mean inventing a weight, and this model already carries more invented numbers than validated ones. Displayed depth is honest; scored depth needs a ruling. If a reviewer wants it in the score, §6 is where to say so.

A precision bug found while building it. mod360 used the common ((x % 360) + 360) % 360 idiom, which adds and subtracts 360 even for values already in range. The round trip loses low bits — 3°20′ returns about 1.9 × 10⁻¹⁴ smaller — which is enough to drop a longitude sitting exactly on a sign or nakshatra boundary into the division below it. Boundary assignment here is categorical, not gradual, so an error of that size is not a rounding error in the result. Fixed engine-wide; the external reference tests still pass unchanged.


3. Domain weights

Taken verbatim from Strategy Brief §3.1.

Signalcareerfinancerelationships
tithi0.150.200.25
nakshatra0.200.150.20
dashaLord0.300.300.25
transit0.250.250.20
yogaDosha0.100.100.10
Σ1.001.001.00

relationships is the brief's marriage column, relabelled. Marriage and relationships are not the same question, and no separate column was ever derived. This is a known substitution, not an equivalence.

The brief does not record how these weights were arrived at, and gives no derivation, citation or fitting procedure. They should be treated as one practitioner's judgement rendered to two decimal places.


4. What the engine gets right

Worth stating plainly, so review effort goes to the model rather than the maths:

Consistency is not correctness. All of the above can be true while §2 is wrong.


5. Hard constraints

Rahukaal zeroes the score and sets hardBlock: "rahukaal". The planner drops the slot entirely rather than ranking it low. It is not a weight, and it applies identically to all three domains.

Open question: is a hard zero right? Rahukaal is widely observed for inaugurations; treating it as an absolute veto for, say, a finance review is a stronger claim than the texts require.

Resolved 2026-08-30 — malefic_dasha removed. It was declared in the hardBlock union and asserted in score.ts's header comment, and nothing ever assigned it: the code documented behaviour it did not have.

Removed rather than implemented. Rahukaal earns a veto because it is a crisply defined, universally observed span; there is no equivalent definition of a Dasha bad enough to void a moment outright, and writing one would have meant inventing an unvalidated rule with a harder effect than any weight in the model. A second hard constraint needs a ruling before it needs code.


6. Questions for the reviewer

In rough order of how much score movement rides on the answer.

  1. The functional blend (§2.3). Revision 2 now accounts for functional role and dignity, but weights them 50/50 against natural beneficence. Is that split defensible, and should kendradhipati dosha be applied on top?
  2. The Ashtakavarga mapping (§2.4). Revision 2 reads transit strength from Bhinnashtakavarga bindus. Two questions on top of the tables themselves: is BAV-over-8 the right per-planet reading, and is the 18–40 SAV band the right comparative range?
  3. Transit anchor (ADR 0006). Moon sign, Lagna, or both? A quarter of displayed band labels turn on this.
  4. Amavasya (§2.1). Confirm this is a defect and give the intended value.
  5. The domain weights (§3). Are the brief's five weights per domain defensible? Is a linear weighted sum the right combiner at all, or should some signals gate rather than contribute?
  6. A real relationships column (§3). Marriage muhurta is not general relationship timing.
  7. The magnitudes. For each table in §2 — is the ordering right, and are the gaps meaningful? A reviewer may reasonably say ordering is all that can be defended, in which case we should say so in the UI.
  8. Rahukaal as an absolute veto (§5).
  9. Mean or true node? We use the mean node for implementation convenience and have never measured the difference. Up to 1.5°, and capable of flipping a dosha. See the note in §2.4.
  10. Is a noon chart the right fallback for an unknown birth time? ADR 0008 defaults to local noon, which is the Western convention. Vedic practice references sunrise — where the ascendant equals the Sun's sign — and has a named discipline for the missing-time problem, Nashtajatakam (BPHS ch. 86). Our choice was made without knowing there was a tradition-specific answer.
  11. Missing factors. Which of Tara Bala, drishti, combustion, dignity, Panchaka, or the Sade Sati phases must v1 carry to be honest?
  12. The activity layer (§2.6). Are the seven acts the right set, are their nature profiles defensible, and is 15 points the right ceiling for how much an act may move a personal reading?
  13. Should the Navamsa be scored (§2.7)? It is computed and shown but carries no weight, because a weight would have to be invented. If it belongs in the score, what should it be worth, and against which signal?
  14. Domain count. Three or four — is Health defensible, and at what duty-of-care cost? (v1-scope Q2.)

7. Provenance summary

ComponentClassical basisMagnitudesValidated by
Ephemeris & sidereal framestandardn/a — externally testedpublished references (ADR 0001)
Vimshottari structurestandardexact (120 yr)internal tests
Tithi five-group cyclestandardoursnobody
Nakshatra rankingconventionaloursnobody
Yoga inauspicious setstandardoursnobody
Vara per-domain tabledirectionaloursnobody
Natural planet qualitystandard orderingoursnobody
Functional role & dignitystandard Parashari; yogakaraka derivation tested against the published setoursnobody
House significationsconventionalflatnobody
Ashtakavarga tablesstandard Parashari, transcription verified by totals (337)n/a — countsnobody
Ashtakavarga 18–40 mapping—oursnobody
Navamsa (D9) divisionstandard; verified against the classical three-case rulen/a — not scoredstructurally sound
Sade Sati definitionstandardpenalty oursnobody
Rahukaal segmentsstandardhard veto oursnobody
Whole-sign housesstandard, and latitude-invariantn/astructurally sound
Mean node for Rahu/Ketuan implementation convenience, not a ruling—nobody
Domain weightsBrief §3.1, underivedbrief'snobody
Nakshatra nature groupsstandard seven-fold classificationn/a — categoricalnobody
Activity suitability & 15-point shiftacts-by-nature is classical; the numbers are notoursnobody

8. Change control


9. Revision history

RevisionDateChange
12026-08-16Original five signals. Dasha lord used natural beneficence only; transit counted planets in domain houses at flat weight.
22026-08-30Functional role and dignity added to the Dasha lord; transit strength read from Ashtakavarga. ADR 0010.

The activity layer (§2.6, ADR 0011) is deliberately not a revision: it does not change Q(t,p,d), it adjusts the result afterwards and only on request, and a reading with no activity chosen is byte-identical to one from before it existed.

Measured impact of revision 2 — 408 samples, 5 charts × 3 domains × 30 days:

Every stored score records its revision, so a decision kept under revision 1 remains readable as what the user was actually told.

Reading this before you decide whether to trust the app is the intended order. The Panchang for today needs no account either.