Repository navigation
hellenistic_completion_roadmap_pre_engine_gates
Current roadmap. Active work now follows the six engine gates in HELLENISTIC_ENGINE_GATES_2026-07.md. Its Phase 2 is the doctrine-decision gate and is not the historical “Bounds Expansion and Halb” phase retained below.
Phase-1 correction (2026-07-25). The roadmap body remains historical. Whole-sign direction and overcoming are now implemented and tested. The Decennials public computation boundary ends at L2. The source-reconstructed Gundel/Harley Hermetic name-and-face catalog is a research-only closed product exclusion from package-root, facade, and registered REST surfaces. See the current backend standards rather than the old status tables below. Status language in the archived body is historical and must not create roadmap work.
Phase-2 doctrine correction (2026-07-25). The former “exact-two-of-three” Halb plan was rejected after a source pass.
is_in_halb()now implements the al-Qabisi/Bonatti sect-relative hemisphere rule; Hayz adds the planet's own sign gender. Mars is feminine and Mercury is neutral. Missing Sun or Mercury phase truth is no longer fabricated. Annual profection schedules use completed civil anniversaries, and Decennials transport preserves its dual time-basis receipt. Valens IV.4 now source-locks the Spirit/Fortune same-sign start shift and exact 211-month Loosing-of-the-Bond behavior. The conflicted lots have source-specific names and explicit projector/arc policies. The Harley MS 3731 Hermetic names and planetary faces are reconstructed from Gundel's identified edition, while their unsupported fixed-star assignments fail closed.
Note (2026-05-29 code verification): A documentation + code verification pass against this roadmap (cross-referenced with WESTERN_HELLENISTIC_GAP_TRACKER.md and FEATURE_AUDIT_2026.md) found that many items listed as "Partial" or "Absent" below are now implemented in the live codebase (e.g., first-class triplicity/bound/face in EssentialDignityKind, PLANETARY_JOYS + is_in_joy, PTOLEMAIC/CHALDEAN bounds tables + doctrine support, is_in_halb + SCORE_HALB, oriental_occidental(), is_besieged(), AspectDomain.WHOLE_SIGN + find_whole_sign_aspects()). The roadmap text below is retained for historical reference but is partially outdated.
This is an additive roadmap governing the closure of partial and absent Hellenistic astrology features in Moira.
Moira already implements the structural pillars of Hellenistic technique: sect, lots, whole sign houses, zodiacal releasing, profections, firdaria, antiscia, essential dignities (domicile/exaltation), fixed stars with parans and heliacal visibility, and degree-based Ptolemaic aspects. What remains are doctrinal refinements and small subsystems that complete the Hellenistic apparatus to the level where the tradition can be practised without silent gaps.
The work is grouped into four phases of increasing interpretive depth. Each phase is independently shippable and testable.
Companion documents:
- DIGNITIES_BACKEND_STANDARD
- EGYPTIAN_BOUNDS_BACKEND_STANDARD
- TIMELORDS_BACKEND_STANDARD
- VALIDATION_ASTROLOGY
| Feature | Module |
|---|---|
| Sect (diurnal/nocturnal, sect light, hayz) | moira/dignities.py |
| Lots (~430 named, day/night reversal) |
moira/lots.py, moira/nine_parts.py
|
| Whole Sign Houses | moira/houses.py |
| Essential dignities (domicile, exaltation, detriment, fall, peregrine) | moira/dignities.py |
| Triplicity rulers (Dorotheus, scored in longevity) | moira/longevity.py |
| Face/decan rulers (Chaldean, scored in longevity) | moira/longevity.py |
| Egyptian bounds (full table, profiling, network) | moira/egyptian_bounds.py |
| Profections (annual + monthly, classical rulers) | moira/profections.py |
| Zodiacal releasing (Fortune, Spirit, Eros, Necessity) | moira/timelords.py |
| Firdaria (diurnal, nocturnal, Bonatti) | moira/timelords.py |
| Antiscia + contra-antiscia | moira/antiscia.py |
| Aspects (Ptolemaic five, applying/separating, patterns) | moira/aspects.py |
| Fixed stars (Behenian, Royal, parans, heliacal) | multiple modules |
| Solar condition (cazimi, combust, under the beams) | moira/dignities.py |
| Mutual reception (domicile + exaltation) | moira/dignities.py |
Note: Several items below have been implemented since this roadmap was drafted. See code verification in WESTERN_HELLENISTIC_GAP_TRACKER.md.
| Feature | What exists | What is missing (per original) | Verification Status |
|---|---|---|---|
| Bounds/terms | Egyptian bounds only | Ptolemaic terms, Chaldaean terms |
Corrected: source-transmitted PTOLEMAIC_BOUNDS plus explicit CHALDEAN_DAY_BOUNDS and CHALDEAN_NIGHT_BOUNDS in egyptian_bounds.py
|
| Essential dignity enum | Domicile, exaltation, detriment, fall, peregrine | Triplicity, bound, face as first-class EssentialDignityKind members |
Implemented: TRIPLICITY, BOUND, FACE in EssentialDignityKind + scoring in dignities.py/longevity.py |
| Hayz | is_in_hayz() |
Source-correct Halb/Hayz provenance and Mercury evaluability | Implemented: named al-Qabisi/Bonatti doctrine, sect-relative Halb, gender-added Hayz, explicit Mercury truth |
| Planetary condition | Cazimi, combust, under the beams | Oriental/occidental (morning/evening star), besieging | Implemented: oriental_occidental(), is_besieged() + conditions |
| Aspect direction | Sinister/dexter exists in primary directions | Not in the general aspect engine | Partial: direction logic present; full general engine + overcoming needs confirmation |
| Feature | Doctrinal significance | Verification Status |
|---|---|---|
| Planetary joys | Foundational to Hellenistic house rationale | Implemented: PLANETARY_JOYS + is_in_joy() + JOY condition |
| Overcoming (katarchein) | The zodiacal-superiority doctrine | Not yet located in general code (timelords or aspects) |
| Whole-sign aspects | Sign-based aspect mode distinct from degree-based | Implemented: AspectDomain.WHOLE_SIGN + find_whole_sign_aspects() |
| Besieging (enclosure) | Malefic enclosure condition | Implemented: is_besieged() |
Admitted values:
- Egyptian (Ptolemy's preferred table, already implemented)
- Ptolemaic (Ptolemy's own alternative table, Tetrabiblos I.21)
- Chaldean (from the Yavanajataka / pre-Ptolemaic tradition)
The bounds doctrine axis determines which table is used for bound rulership lookup. All three systems assign the same five rulers (Mercury, Venus, Mars, Jupiter, Saturn) across the same 30-degree sign span, but in different segment arrangements.
Admitted values:
-
Dorotheus (day/night/participating, already implemented in
longevity.py) - Ptolemy (day/night only, no participating ruler)
- Morinus (alternative assignment)
- Lilly (early modern variant)
The triplicity scheme axis is relevant once triplicity becomes a first-class essential dignity rather than a scoring-only concept.
Admitted values:
- Degree-based (current implementation, exact longitude separation with orb)
- Sign-based / whole-sign (sign-count determines aspect type, no orb)
Both modes yield the same five Ptolemaic aspects. The distinction is whether planets in the same sign are conjunct regardless of degree separation and whether a planet at 29 degrees Aries and 1 degree Leo form a trine.
Admitted values:
- Classical / Ptolemaic (based on rising before/after the Sun)
- Bonatti (adds sign-based nuance)
The oriental/occidental axis is relevant for planetary condition and accidental dignity scoring.
Verification note (2026-05-29): Per code review, the bulk of the tasks in Phases 1-4 below have been completed in the live code (see updated "Current Moira State" above and WESTERN_HELLENISTIC_GAP_TRACKER.md). The detailed task lists are retained for reference. Remaining work is now concentrated on confirmed gaps from FEATURE_AUDIT_2026.md (aphesis/distributions, Triacontaeteris, synastry depth, full ACG, etc.).
Scope: Promote triplicity, bound, and face to first-class essential dignity kinds, and implement planetary joys as an accidental condition.
Modules: moira/dignities.py, moira/longevity.py
Tasks:
-
Extend
EssentialDignityKindwithTRIPLICITY = "triplicity",BOUND = "bound",FACE = "face". -
Add scoring constants
SCORE_TRIPLICITY = 3,SCORE_BOUND = 2,SCORE_FACE = 1tomoira/dignities.py(migrated fromlongevity.pyinline values). -
Add
PLANETARY_JOYSlookup dict tomoira/dignities.py:PLANETARY_JOYS: dict[str, int] = { "Mercury": 1, "Moon": 3, "Venus": 5, "Mars": 6, "Sun": 9, "Jupiter": 11, "Saturn": 12, }
-
Add
is_in_joy(planet: str, house: int) -> boolfunction. -
Add
JOY = "joy"toAccidentalConditionKindwithSCORE_JOY = 3and polaritySTRENGTHENING. -
Wire triplicity/bound/face detection into
calculate_dignities()so the result vessel reports the full five-level essential dignity state. -
Ensure
dignity_score_at()inlongevity.pydelegates to the same constants rather than hardcoding weights.
Acceptance criteria:
-
calculate_dignities(Body.JUPITER, lon=15.0, ...)for Jupiter at 15 degrees Aries reportsTRIPLICITYas an essential dignity (Jupiter is day triplicity ruler of fire signs in the Dorotheus scheme). -
is_in_joy("Mars", 6)returnsTrue. -
is_in_joy("Mars", 5)returnsFalse. - All existing dignity and longevity tests continue to pass.
Constitutional target: P1 for planetary joys; existing dignity subsystem remains at its current constitutional level.
Do not: Modify egyptian_bounds.py, aspects.py, or timelords.py
during this phase.
Scope: Add Ptolemaic and Chaldean term tables alongside the existing Egyptian bounds, and implement the halb condition.
Modules: moira/egyptian_bounds.py (renamed or generalized),
moira/dignities.py
Tasks:
-
PTOLEMAIC,CHALDEAN_DAY, andCHALDEAN_NIGHTare admitted alongside the Egyptian default. The day/night split preserves the source-required Saturn/Mercury sect ordering. -
Add
PTOLEMAIC_BOUNDStable (Tetrabiblos I.21):Aries: Jupiter 0-6, Venus 6-14, Mercury 14-21, Mars 21-26, Saturn 26-30 Taurus: Venus 0-8, Mercury 8-15, Jupiter 15-22, Saturn 22-26, Mars 26-30 ... -
Add the source-derived
CHALDEAN_DAY_BOUNDSandCHALDEAN_NIGHT_BOUNDStables from Ptolemy's 8-7-6-5-4 construction. -
EgyptianBoundsPolicy.__post_init__accepts the four explicit doctrines and rejects the former ambiguouschaldeanvalue. -
Route
egyptian_bound_of()andbound_ruler()through the policy doctrine to select the correct table. -
Implement
is_in_halb()inmoira/dignities.pyunder the admitted al-Qabisi/Bonatti doctrine. A diurnal planet requires the upper hemisphere by day and lower hemisphere by night; a nocturnal planet requires the inverse. Hayz adds placement in a sign of the planet's own gender. -
Add
HALB = "halb"toAccidentalConditionKindwithSCORE_HALB = 1and polaritySTRENGTHENING. -
Add
IN_HALBtoSectStateKind.
Acceptance criteria:
-
egyptian_bound_of(15.0, policy=BoundsPolicy(doctrine=PTOLEMAIC))returns Venus for 15 degrees Aries (Ptolemaic: Venus rules 6-14). -
egyptian_bound_of(15.0, policy=BoundsPolicy(doctrine=EGYPTIAN))returns Mercury for 15 degrees Aries (Egyptian: Mercury rules 12-20). -
is_in_halb("Moon", ...)returnsTruefor Moon above the horizon in a night chart, independently of sign gender. -
is_in_hayz("Moon", ...)additionally requires a feminine sign. - All existing Egyptian bounds tests pass without modification.
Constitutional target: P1 for Ptolemaic and Chaldean bounds.
Do not: Modify aspects.py or timelords.py during this phase.
Scope: Add oriental/occidental classification, besieging detection, and sinister/dexter aspect direction to the general aspect engine.
Modules: moira/dignities.py, moira/aspects.py
Tasks:
-
Implement
oriental_occidental(planet: str, planet_lon: float, sun_lon: float, planet_speed: float) -> str:- Superior planets (Mars, Jupiter, Saturn): oriental when rising before the Sun (planet longitude < sun longitude in zodiacal order), occidental when rising after.
- Inferior planets (Mercury, Venus): oriental when morning star (heliacal rising precedes the Sun), occidental when evening star.
- Luminaries: not applicable.
-
Add
ORIENTAL = "oriental"andOCCIDENTAL = "occidental"toAccidentalConditionKindwith scores:SCORE_ORIENTAL = 2(for superior planets when oriental, inferior when occidental) andSCORE_OCCIDENTAL = -2(reverse). -
Implement
is_besieged(planet_lon: float, chart_positions: dict, orb: float = 12.0) -> bool | tuple[str, str]:- A planet is besieged when its nearest neighbours by ecliptic longitude on both sides are malefics (Mars, Saturn) within the specified orb.
- Return the pair of besieging malefics, or False.
-
Add
BESIEGED = "besieged"toAccidentalConditionKindwithSCORE_BESIEGED = -5and polarityWEAKENING. -
Add
AspectDirection(StrEnum)tomoira/aspects.py:class AspectDirection(StrEnum): SINISTER = "sinister" # forward in zodiacal order DEXTER = "dexter" # backward in zodiacal order
-
Add
direction: AspectDirection | Nonefield toAspectData. -
Compute direction at detection time: if body1 is zodiacally behind body2, the aspect is dexter from body1's perspective (the ray is cast backward).
-
Add
overcoming(body1_lon: float, body2_lon: float) -> str | None:- A planet overcomes another when it is in the 10th-sign position relative to it (i.e., it casts a dexter square).
- Returns the name of the overcoming relationship or None.
Acceptance criteria:
- Jupiter at 100 degrees with Sun at 120 degrees: oriental (rising before the Sun).
- Venus as morning star (longitude less than Sun, positive speed toward Sun): oriental.
- Mars at 15 degrees Aries, Moon at 17 degrees Aries, Saturn at 13 degrees Aries: Moon is besieged between Mars and Saturn.
- Aspect between planet at 10 degrees Aries and planet at 10 degrees Leo: dexter trine from the perspective of the Leo planet, sinister from the Aries planet.
- Planet at 10 degrees Cancer overcomes a planet at 10 degrees Aries (10th-sign square).
- All existing aspect tests pass.
Constitutional target: P1 for oriental/occidental, besieging, and aspect direction.
Do not: Modify egyptian_bounds.py, timelords.py, or house
computation during this phase.
Scope: Add a whole-sign (sign-based) aspect detection mode as an alternative geometry alongside degree-based detection.
Module: moira/aspects.py
Tasks:
-
Add
WHOLE_SIGN = "whole_sign"toAspectDomain. -
Implement
find_whole_sign_aspects(positions: dict) -> list[AspectData]:- Compute the sign index (0-11) for each body.
- Determine aspect by sign-count difference:
- 0 signs: conjunction
- 2 or 10 signs: sextile
- 3 or 9 signs: square
- 4 or 8 signs: trine
- 6 signs: opposition
- Aversion (1, 5, 7, 11 signs apart): no Ptolemaic aspect.
-
Whole-sign aspects have no orb -- they are either present or absent. Set
orb = 0.0andexactness = 1.0on the result vessel. -
Whole-sign aspects still carry sinister/dexter direction (from Phase 3).
-
Add
whole_sign: bool = Falseparameter toAspectPolicyto enable whole-sign mode as an alternative to degree-based detection.
Acceptance criteria:
- Mars at 29 degrees Aries and Jupiter at 1 degree Leo: whole-sign trine (4 signs apart), but no degree-based trine within standard orb.
- Sun at 1 degree Aries and Moon at 29 degrees Aries: whole-sign conjunction.
- Venus at 15 degrees Taurus and Saturn at 15 degrees Cancer: whole-sign sextile (2 signs apart).
- Venus at 15 degrees Taurus and Mars at 15 degrees Gemini: aversion (1 sign apart), no whole-sign aspect.
- All existing degree-based aspect tests pass unchanged.
Constitutional target: P1 for whole-sign aspects.
| Phase | Depends on | Touches |
|---|---|---|
| Phase 1 | None |
dignities.py, longevity.py
|
| Phase 2 | None |
egyptian_bounds.py, dignities.py
|
| Phase 3 | Phase 1 (for enum patterns) |
dignities.py, aspects.py
|
| Phase 4 | Phase 3 (sinister/dexter) | aspects.py |
Phases 1 and 2 are independent and can be implemented in parallel. Phase 3 requires Phase 1 for enum extension patterns. Phase 4 requires Phase 3 for aspect direction infrastructure.
- Unit tests: domicile/exaltation/triplicity/bound/face lookup for all 12 signs, 7 classical planets.
- Joy table: exhaustive 7-planet x 12-house matrix.
- Regression: all existing
test_dignities.pyandtest_longevity.pytests must pass.
- Ptolemaic bounds: tabular test against Tetrabiblos I.21 (Hephaistion reconstruction, Robbins translation).
- Chaldean bounds: tabular test against Pingree, Yavanajataka (1978).
- Halb/Hayz: exhaustive day/night, diurnal/nocturnal, hemisphere, and sign gender matrices, including Mercury's neutral/non-evaluable Hayz truth.
- Regression: all existing
test_egyptian_bounds.pytests must pass.
- Oriental/occidental: test against ephemeris data for known morning/ evening star configurations (e.g., Venus as morning star on a known date).
- Besieging: synthetic chart positions with known malefic enclosures.
- Sinister/dexter: verify direction for aspects in all four quadrants.
- Overcoming: verify 10th-sign square detection.
- Regression: all existing
test_aspects.pytests must pass.
- Whole-sign: synthetic tests for all five Ptolemaic aspects by sign count.
- Aversion: 1, 5, 7, 11 sign separations yield no aspect.
- Edge cases: bodies at 0 and 29 degrees of same sign (conjunction), bodies at 29 degrees and 1 degree of adjacent signs (no conjunction).
- Regression: all existing degree-based aspect tests must pass.
-
Should
EgyptianBoundsDoctrinebe renamed toBoundsDoctrine(orTermsDoctrine) when Ptolemaic and Chaldean are added, or should the Egyptian prefix be kept for backward compatibility? -
Should
dignity_score_at()remain inlongevity.pyor migrate todignities.pynow that the scoring constants are being formalized there? -
Should oriental/occidental for inferior planets (Mercury, Venus) use elongation-based classification (> 0 degrees elongation = morning star) or heliacal-event-based classification (has the planet had its last heliacal rising)?
-
Should whole-sign aspects produce the same
AspectDatavessel as degree-based aspects, or a distinctWholeSignAspectDatavessel? -
What score should be assigned to overcoming? Classical sources treat it as a qualitative relational condition rather than a point-based dignity. It may belong in a relational layer rather than the accidental condition enum.
-
Should Dorotheus-style triplicity be the only scheme at Phase 1, or should the triplicity axis be parameterized from the start?
- Ptolemy, Tetrabiblos, trans. F. E. Robbins (Loeb Classical Library, 1940). Bounds tables: I.20-21. Triplicity: I.18. Oriental/occidental: I.24.
- Dorotheus of Sidon, Carmen Astrologicum, trans. D. Pingree (1976). Triplicity rulers (day/night/participating): I.1.
- Vettius Valens, Anthology, trans. M. Riley (2010). Zodiacal releasing: IV.4. Antiscia: II.37. Overcoming: multiple.
- Hephaistion of Thebes, Apotelesmatics, Book I. Egyptian bounds reconstruction.
- Chris Brennan, Hellenistic Astrology: The Study of Fate and Fortune (Amor Fati, 2017). Planetary joys: Ch. 5. Profections: Ch. 9. Sect: Ch. 7. Overcoming: Ch. 11. Whole-sign aspects: Ch. 11.
- D. Pingree, The Yavanajataka of Sphujidhvaja (Harvard, 1978). Chaldean bounds.
- al-Qabisi, Introduction to Astrology, and Guido Bonatti, Book of Astronomy, in Benjamin Dykes's English translations. Sect-relative Halb and Hayz conditions.
- Porphyry, Introduction to the Tetrabiblos, excerpts preserving Antiochus. Planetary gender, including feminine Mars and neutral Mercury.
- Robert Hand, "Whole Sign Houses: The Oldest House System" (ARHAT, 2000). Whole-sign aspect rationale.
- Existing Moira modules:
moira/dignities.py,moira/longevity.py,moira/egyptian_bounds.py,moira/aspects.py.