HomeDocsTiming & Timelords

Timing & Timelords

Firdaria, decennials, Zodiacal Releasing, time-boundary ownership, and immutable timelord result contracts.

Timelords Backend Standard

Subsystem: moira/profections.py, moira/timelords.py Computational Domains: Profections, Firdaria, Decennials, Zodiacal Releasing Constitutional Phase: 11 — Architecture Freeze and Validation Codex Status: Constitutional

Closed Decennial boundary — 2026-07-27. The complete admitted Decennials contract is L1/L2. Levels 3–4 and named deep-subdivision methods are closed exclusions, not unfinished engine work. The runtime and REST request surface ends at L2. Zodiacal Releasing classifies all twelve places from Fortune, identifies only angular places as peaks, and rejects queries at or beyond the exact full-circuit endpoint.

Phase-2 time-basis correction — 2026-07-25. Decennials now preserves a machine-readable dual-basis receipt. Its periods are measured on the Valens 360-day distribution coordinate, while start_jd/end_jd are explicitly identified as elapsed-Julian-day projections from the natal instant. Annual profection schedule ages are civil-anniversary ages. Zodiacal Releasing profile requests must ask for a level that was generated.

Phase-2 ZR source lock — 2026-07-25. Valens IV.4 now owns the Spirit/Fortune same-sign start shift and the exact 211-month Loosing-of-the-Bond boundary. These rules are covered by a source-locked fixture; the inconsistent intervening numerical table is not treated as an oracle against the source prose.

Dated monthly profection contract — 2026-07-27. The admitted twelve-sign monthly sequence now has an explicit dated projection. Moira partitions the exact elapsed duration between consecutive civil anniversaries into twelve equal-microsecond, half-open intervals in an explicit IANA timezone. The receipt identifies this as a computational projection, not as Valens IV.28's separate luminary-distance method.


Part I — Architecture Standard

§1. Computational Definitions

§1.0 Annual and Monthly Profections

annual_profection() advances the natal Ascendant by one whole sign for each completed year. monthly_profection() advances the resulting longitude by one whole sign for each month index in 0..11.

profection_schedule() owns civil-anniversary age resolution and attaches a query-specific ProfectionChronology. REST callers normalized to UTC supply civil_timezone; explicit IANA zones resolve through the standard-library zoneinfo interface. The request fails closed if the host lacks the requested IANA entry, and the result does not claim an unavailable database version.

The sole admitted dated interval policy is equal_twelfths_of_civil_anniversary_year. It divides elapsed UTC time between the exact local civil anniversary and the following anniversary into twelve integer-microsecond partitions. Boundaries are start-inclusive and end-exclusive. No fixed 30-day, 365.25-day, or civil-calendar-month approximation is admitted.

The chronology method is classified as computational_projection. Valens IV.28's day-Sun/night-Moon distance method is a distinct technique outside this contract; the equal-twelfths policy does not claim historical equivalence.

Authoritative doctrine and boundary details: wiki/01_doctrines/timelords/monthly_profection_chronology_doctrine.md.

§1.1 Firdaria

Firdaria is a Persian/Medieval time-lord technique assigning rulership of life-periods to the seven classical planets and the lunar nodes in a fixed Chaldean-order sequence. It is exposed and validated separately, but it is not part of Moira's admitted Hellenistic profile. The complete cycle spans 75 years.

The authoritative engine is firdaria(natal_jd, is_day_chart). It accepts a Julian Day number and a sect indicator and returns a list of FirdarPeriod records covering the full 75-year cycle from birth. Each record preserves the planet, level, major planet, start and end Julian Day, duration in years, and the sequence kind that generated it.

Sequence kinds (FirdarSequenceKind):

ValueMeaning
DIURNALDay chart: Sun-led sequence
NOCTURNAL_STANDARDNight chart: Moon-led, traditional ordering
NOCTURNAL_BONATTINight chart: Moon-led, Bonatti variant ordering

The sequence_kind field is set only on major-period (level=1) records. Sub-period records do not repeat it; they inherit structural context through their major_planet field.

The nocturnal variant (standard vs. Bonatti) is a doctrinal choice expressed at call time. The default is NOCTURNAL_STANDARD. Both variants share the same computational structure; only the planet ordering changes.

§1.2 Decennials

Decennials is a Hellenistic planetary time-lord technique assigning major life periods to the sect light and then proceeding through the seven classical planets in zodiacal order from that luminary. The admitted Moira doctrine uses 129-month major periods, 30-day schematic months, and a 360-day distribution year. The complete major cycle spans 903 schematic months, or 75 years 3 months in distribution notation.

The authoritative engine is decennials(natal_jd, natal_positions, is_day_chart). It accepts a natal Julian Day, the seven classical longitudes, and a sect indicator and returns a flat list of DecennialPeriod records covering the complete admitted sequence. Each record preserves level, planet, sequence truth, major lineage, parent lineage, duration, sequence kind, and the full time-basis receipt.

Valens distinguishes the 365¼-day universal/lived year from the 360-day distribution year. Moira therefore does not describe a 129-month major as 129 civil-calendar months. The engine:

  1. counts the target instant by elapsed lived days from natal_jd;
  2. locates that elapsed-day coordinate within the 360-day distribution sequence; and
  3. exposes the resulting civil JD/date only as a projection of the symbolic boundary from the natal instant.

The following fields make that distinction inspectable:

SurfaceValue / meaning
DecennialTimeBasis.VALENS_LIVED_DAYS_TO_360_DAY_DISTRIBUTIONFrozen distribution-time doctrine token
DecennialTimeBasis.ELAPSED_JULIAN_DAYS_FROM_NATAL_JDFrozen calendar-projection token
sequence_origin_jdNatal JD from which elapsed lived days are counted
start_distribution_day, end_distribution_dayHalf-open elapsed-day bounds in distribution space
distribution_yearsPeriod duration divided by 360
start_jd, end_jdCalendar projections, not claims of civil-month anniversaries

Sequence kinds (DecennialSequenceKind):

ValueMeaning
DIURNAL_SOLARDay chart: Sun-led sequence
NOCTURNAL_LUNARNight chart: Moon-led sequence

Sequence assembly truth: decennial_sequence_truth() evaluates the Classic 7 dependencies before any period is generated. Its DecennialSequenceAssemblyTruth preserves chart sect, sect light, sequence kind, normalized sect-light longitude, one DecennialSequenceBodyTruth per classical planet, the final sequence when evaluable, and any ambiguous non-sect-light groups.

The sect light is always the first lord. One non-sect-light planet may share its longitude because the starting-lord rule resolves that ordering. Two or more non-sect-light planets at the same longitude are not ordered by a private planet list: the assembly is typed not_evaluable with reason="non_sect_longitude_tie", and decennials() fails closed. Every generated L1/L2 period carries the same evaluated assembly receipt.

Admitted levels and deep doctrine:

DoctrineAdmitted levels
Shared Decennials coreL1 + L2
deep_subdivision_method="valens"Not admitted
deep_subdivision_method="hephaistio"Not admitted

Any request for L3/L4 or either named deep method fails closed. This is the finished contract boundary. A future proposal would be a separate source-admission project, not completion work for this engine release.

§1.4 Valens Distributions (Closed Interpretive Exclusion)

The Valens distributions/transmissions delineation layer is not admitted. The earlier implementation did not preserve the receiver relation needed to select a source item, duplicated incomplete tables, attached effects automatically, and inferred benefic/malefic scores from English keywords. Those behaviours are not source-owned doctrine and have been removed.

This exclusion is separate from the Decennial L1/L2 depth boundary. Neither DecennialPolicy.deep_subdivision_method="valens" nor "hephaistio" is selectable in the admitted runtime. Neither exclusion enables delineations, effects, polarities, or dignity scores.

The interpretive layer has no public export, period/profile field, automatic attachment, REST option, score, aggregate, or dignity bridge. It is not a missing part of the admitted Hellenistic profile. Any future proposal would require its own item-complete source transcription, explicit distributor and receiver semantics, typed unscored result design, and source-owned fixtures. Generic good/bad labels and numerical scores remain outside the admitted design.

The internal arithmetic is doctrinal rather than astronomical:

  • major periods are fixed at 129 months
  • the month basis is fixed at 30 days
  • L2 rotates the minor-month allotments from each major lord
  • no L3/L4 recursion is admitted

§1.3 Zodiacal Releasing

Zodiacal Releasing is a Hellenistic predictive technique that releases from a natal Lot (Spirit or Fortune) through the twelve signs of the zodiac. Periods are assigned by sign in sequence, with duration determined by the sign's MINOR_YEARS value. The technique recurses through four levels of releasing simultaneously.

The authoritative engine is zodiacal_releasing(lot_longitude, natal_jd). It accepts a Lot's ecliptic longitude and a Julian Day number and returns a list of ReleasingPeriod records. Each record preserves the releasing sign, its ruler, the level of releasing, the lot name, duration in years, the Loosing of the Bond flag, the angularity from Fortune, and the year-basis.

MINOR_YEARS: The canonical sign-to-duration mapping is an immutable constant in the module. It assigns years-per-sign based on planetary minor years under the Hellenistic system. This mapping is the foundational arithmetic of the technique and is not configurable at call time.

Valens IV.4 start shift: When Spirit and Fortune occupy the same sign and releasing is requested from Spirit, bodily matters remain with that sign while the activity sequence begins from the following sign. The engine therefore advances the starting sign by one only for this explicitly supplied Spirit/Fortune same-sign case.

Loosing of the Bond: Valens' complete circuit is 17 years 7 months, or 211 symbolic months. After a complete twelve-sign subcycle that began in a sign whose allotment exceeds that circuit, the admitted generator transfers the next period to the opposite sign and marks that receiving period as a Loosing of the Bond. ReleasingPeriod.is_loosing_of_bond preserves this generative event; it is not inferred from an upper/lower-level sign match after the fact.

The source-locked Gemini fixture is exact: inside a 20-year Gemini major, Level 2 reaches its 211-month circuit boundary, transfers to Sagittarius for 12 months, and then uses the final 17 months in Capricorn. The prose and explanatory note govern this fixture; the internally inconsistent numerical table on the intervening annotated-PDF page is not used.

Angularity from Fortune: Each sign's relationship to the natal Lot of Fortune determines its angularity class. Angular signs (1, 4, 7, 10 from Fortune) carry the ANGULAR classification; the following signs carry SUCCEDENT; the remaining carry CADENT. This classification is preserved as an integer (1-based distance) and a typed ZRAngularityClass on each period.

When Fortune is supplied, every period receives an evaluated ZRFortuneAngularityTruth with one of the twelve integer places, one of the three classes, and a peak boolean that is true only for the four angular places. When Fortune is omitted, the raw receipt is typed not_evaluable with reason="fortune_not_supplied"; its Fortune sign, place, class, and peak truth are all None. The legacy ReleasingPeriod.is_peak_period field remains False as a compatibility projection, so callers must use fortune_angularity_truth when they need to distinguish unevaluated from an evaluated non-peak period.

ZRAngularityClass ValueMeaning
ANGULAR1st, 4th, 7th, or 10th sign from Fortune
SUCCEDENT2nd, 5th, 8th, or 11th sign from Fortune
CADENT3rd, 6th, 9th, or 12th sign from Fortune

Levels: Four levels of releasing are computed simultaneously. Level 1 is the outermost (slowest), Level 4 is the innermost (fastest). All four are returned in a single flat list discriminated by the level field.

zr_sequence_profile(periods, level) rejects an empty period list and rejects any requested level absent from the supplied periods. The REST profile_level must therefore be less than or equal to the request's generated levels; an impossible profile request is never serialized as an empty, apparently valid aggregate.

Full-circuit boundary: The twelve MINOR_YEARS values sum to 211 symbolic years. current_releasing() accepts instants inside that half-open interval and rejects an instant exactly at, or later than, its endpoint.

Source receipt: tests/golden/hellenistic_zr_valens_iv4.json, backed by Valens, Anthologies IV.4 (Riley annotated PDF pp. 329, 331, and 333).


§2. Layer Structure

The timelords subsystem is organized into ten layers, each building on the prior according to the constitutional dependency graph.

| Layer | Phase | Firdaria | Decennials | Zodiacal Releasing | |---|---|---|---| | 0 | Core | firdaria() | decennials() | zodiacal_releasing() | | 1 | Truth Preservation | FirdarPeriod | DecennialPeriod | ReleasingPeriod | | 2 | Classification | FirdarSequenceKind | DecennialSequenceKind | ZRAngularityClass | | 3 | Inspectability | is_active_at(), duration properties | lineage helpers, is_active_at(), duration properties | is_active_at(), duration properties | | 4 | Policy | sequence_kind parameter | DecennialPolicy (deep method fixed to None) | lot_name, use_loosing_of_bond | | 5 | Relational Formalization | FirdarMajorGroup, group_firdaria() | DecennialMajorGroup, DecennialPeriodGroup, group_decennials() | ZRPeriodGroup, group_releasing() | | 6 | Relational Hardening | subset properties, chronological guard | recursive containment and chronology guards | containment guard, is_leaf, all_periods_flat() | | 7 | Integrated Local Condition | FirdarConditionProfile, firdar_condition_profile() | DecennialConditionProfile, decennial_condition_profile() | ZRConditionProfile, zr_condition_profile() | | 8 | Aggregate Intelligence | FirdarSequenceProfile, firdar_sequence_profile() | DecennialSequenceProfile, decennial_sequence_profile() | ZRSequenceProfile, zr_sequence_profile() | | 9 | Network Intelligence | FirdarActivePair, firdar_active_pair() | DecennialActivePair, DecennialActivePath, decennial_active_pair(), decennial_active_path() | ZRLevelPair, zr_level_pair() | | 10 | Hardening | validate_firdaria_output() | validate_decennials_output() | validate_releasing_output() |

Valens Distributions: closed exclusion under §1.4. They are not an additional layer on the admitted Decennials or Zodiacal Releasing architecture, and they are not release backlog.


§3. Delegated Assumptions

The timelords subsystem does not compute the following. Callers are responsible for supplying correct values.

For Firdaria:

  • natal_jd: a valid Julian Day number representing the moment of birth
  • is_day_chart: the sect determination (diurnal or nocturnal), computed externally from the chart's sun/ascendant relationship
  • nocturnal variant selection: the caller's choice of NOCTURNAL_STANDARD vs. NOCTURNAL_BONATTI is not validated against any external authority

For Zodiacal Releasing:

  • lot_longitude: the ecliptic longitude of the Lot, computed externally via the Lot formula (typically Asc + Fortune/Spirit − Sun/Moon)
  • natal_jd: a valid Julian Day number representing the moment of birth
  • the Lot used (Spirit vs. Fortune vs. other) is identified only by the lot_name string passed at call time; the subsystem does not verify it

For Decennials:

  • natal_jd: a valid Julian Day number representing the moment of birth
  • natal_positions: the tropical longitudes of the seven classical planets, supplied externally and keyed by canonical planet name
  • is_day_chart: the sect determination (diurnal or nocturnal), computed externally
  • deep-method selection: the caller's choice of None, valens, or hephaistio is validated for internal admissibility only; the subsystem does not infer it from source preference or chart context

§4. Doctrine Surface

The doctrinal choices made by the timelords subsystem are explicit and located.

Profection doctrine and projection policy:

ChoiceLocationDefault
Completed-age basisprofection_schedule()exact civil anniversary
Explicit transport timezonecivil_timezonecaller's natal_dt.tzinfo compatibility path
Monthly interval projectionMonthlyProfectionIntervalPolicyequal_twelfths_of_civil_anniversary_year
Repeated local anniversaryProfectionAmbiguousTimePolicyexplicit earlier_occurrence or later_occurrence; no guessed fold
Boundary membershipProfectionIntervalBoundarySemanticsstart_inclusive_end_exclusive
Method classificationProfectionChronologyMethodcomputational_projection
February 29 anniversaryLeapDayAnniversaryPolicyexplicit selection required

Firdaria doctrine:

ChoiceLocationDefault
Nocturnal ordering variantfirdaria() parameter sequence_kindNOCTURNAL_STANDARD
Sub-period major identificationFirdarPeriod.major_planet fieldalways set
Node treatment_FIRDARIA_NODES constant['North Node', 'South Node']
Luminary classification_FIRDARIA_LUMINARIES constant['Sun', 'Moon']

Zodiacal Releasing doctrine:

ChoiceLocationDefault
Minor years mappingMINOR_YEARS module constantHellenistic standard
Loosing of the BondReleasingPeriod.is_loosing_of_bond fieldcomputed at engine time
Angularity from FortuneReleasingPeriod.angularity_from_fortune fieldcomputed at engine time
use_loosing_of_bond flagReleasingPeriod.use_loosing_of_bond fieldalways preserved

Decennials doctrine:

ChoiceLocationDefault
Starting lord basisDecennialPolicy.start_lord_basissect_light
Sequence modeDecennialPolicy.sequence_modezodiacal_from_sect_light
L2 subdivision modeDecennialPolicy.subperiod_moderotated_minor_months
Major period lengthDecennialPolicy.major_months129
Month basisDecennialPolicy.month_basis_days30
Deep methodDecennialPolicy.deep_subdivision_methodNone; all non-None values rejected

§5. Public Vessels

The following are the constitutional public vessels of the timelords subsystem.

Enumerations:

  • MonthlyProfectionIntervalPolicy — identifies the admitted dated monthly projection
  • ProfectionAmbiguousTimePolicy — explicitly resolves a repeated local anniversary when one occurs
  • ProfectionChronologyMethod — distinguishes computational projection from historical-method claims
  • ProfectionIntervalBoundarySemantics — freezes half-open membership
  • FirdarSequenceKind — discriminates the Firdaria sequence variant
  • TimelordEvaluationStatus — discriminates evaluated from not-evaluable atomic timelord truth
  • DecennialSequenceKind — discriminates the Decennials sequence variant
  • DecennialTimeBasis — names the admitted distribution and projection bases
  • ZRAngularityClass — discriminates the angularity of a releasing period from Fortune

Atomic truth vessels:

  • DecennialSequenceBodyTruth — one classical planet's normalized longitude and forward arc from the sect light
  • DecennialSequenceAssemblyTruth — complete sect-light dependency, ordering, ambiguity, and final-sequence receipt
  • ZRFortuneAngularityTruth — Fortune dependency, place, class, and raw peak truth for one releasing sign

Truth-preservation vessels:

  • MonthlyProfectionInterval — one dated sign/lord step with exact UTC and Julian boundaries
  • ProfectionChronology — annual anchors, timezone provenance, query, active month, and the complete twelve-interval receipt
  • FirdarPeriod — a single Firdaria period at any level
  • DecennialPeriod — a single Decennials period at any admitted level
  • ReleasingPeriod — a single Zodiacal Releasing period at any level

Relational vessels:

  • FirdarMajorGroup — a major Firdaria period with its associated sub-periods
  • DecennialMajorGroup — a major Decennials period with its immediate subordinate periods
  • DecennialPeriodGroup — a recursive Decennials subordinate-period grouping
  • ZRPeriodGroup — a releasing period at any level with its nested sub-groups

Condition vessels:

  • FirdarConditionProfile — integrated doctrinal summary for one FirdarPeriod
  • DecennialConditionProfile — integrated doctrinal summary for one DecennialPeriod
  • ZRConditionProfile — integrated doctrinal summary for one ReleasingPeriod

Aggregate vessels:

  • FirdarSequenceProfile — chart-wide summary of a full Firdaria sequence
  • DecennialSequenceProfile — chart-wide summary of a full Decennials sequence
  • ZRSequenceProfile — sequence-wide summary of releasing periods at a given level

Network vessels:

  • FirdarActivePair — the major/sub lord pair active at a point in time
  • DecennialActivePair — the major/sub pair active at a point in time
  • DecennialActivePath — the full active Decennials lineage at a point in time
  • ZRLevelPair — structural edge between two adjacent releasing levels

Computational functions:

  • profection_chronology(...) — typed dated monthly projection for one query
  • profection_schedule(...) — current annual profection plus its chronology
  • firdaria(natal_jd, is_day_chart, ...) — core Firdaria engine
  • decennial_sequence_truth(natal_positions, is_day_chart) — typed sect-light sequence-assembly receipt
  • decennials(natal_jd, natal_positions, is_day_chart, ...) — core Decennials engine
  • zr_fortune_angularity_truth(period_sign, fortune_sign) — typed Fortune dependency and angular-place receipt
  • zodiacal_releasing(lot_longitude, natal_jd, ...) — core Zodiacal Releasing engine
  • group_firdaria(periods) — relational grouping for Firdaria
  • group_decennials(periods) — relational grouping for Decennials
  • group_releasing(periods) — relational grouping for Zodiacal Releasing
  • firdar_condition_profile(period) — condition profile for a Firdaria period
  • decennial_condition_profile(period) — condition profile for a Decennials period
  • zr_condition_profile(period) — condition profile for a Releasing period
  • firdar_sequence_profile(periods) — aggregate profile for a Firdaria sequence
  • decennial_sequence_profile(periods) — aggregate profile for a Decennials sequence
  • zr_sequence_profile(periods, level) — aggregate profile for a Releasing sequence
  • firdar_active_pair(periods, jd) — network node active at a Julian Day
  • decennial_active_pair(periods, jd) — Decennials major/sub pair active at a Julian Day
  • decennial_active_path(periods, jd) — full Decennials lineage active at a Julian Day
  • zr_level_pair(upper, lower) — network edge between two releasing levels
  • validate_firdaria_output(periods) — invariant guard for Firdaria output
  • validate_decennials_output(periods) — invariant guard for Decennials output
  • validate_releasing_output(periods) — invariant guard for Releasing output

Part II — Terminology Standard

§6. Required Terms

The following terms carry specific meanings within this subsystem and must not be used loosely.

TermNormative Meaning
major periodA FirdarPeriod with level=1; one of the 9 time-lord allocations spanning the full 75-year cycle
sub-periodA FirdarPeriod with level=2; a subdivision of a major period
sequence kindThe FirdarSequenceKind value determining which planet leads the Firdaria sequence
levelAn integer 1–4 in Zodiacal Releasing, or 1–2 in admitted Decennials and Firdaria output, identifying the recursive depth of a period
Loosing of the BondThe opposite-sign transfer after a complete subcycle beginning in a long-period sign; preserved as a boolean on the receiving ReleasingPeriod
angularity from FortuneThe 1-based sign distance of a releasing period's sign from the natal Lot of Fortune; typed as ZRAngularityClass
lotThe natal Lot (Spirit, Fortune, or other) from which releasing proceeds; identified by lot_name only
MINOR_YEARSThe immutable sign-to-duration mapping; the arithmetic basis of the releasing technique
lord typeThe doctrinal classification of a Firdaria planet: luminary, planet, or node; not a concept in Zodiacal Releasing
sect lightThe luminary of sect that leads the admitted Decennials sequence: Sun by day, Moon by night
distribution dayAn elapsed lived-day coordinate interpreted inside the 360-day Decennials distribution model
calendar projectionA JD/date obtained by adding the distribution-day offset to sequence_origin_jd; not a civil-month anniversary claim
deep subdivision methodA compatibility sentinel fixed to None; no selector is admitted and the complete public depth is L1/L2
condition profileA flat doctrinal summary of a single period, integrating all layers from truth preservation through relational hardening
sequence profileA chart-wide or sequence-wide aggregate derived from a full list of condition profiles
active pairThe simultaneous major/sub lord combination at a point in time; a network node in Firdaria
active pathThe full simultaneously active Decennials lineage from major level to deepest active subordinate level
level pairThe structural edge between two adjacent releasing levels at a point in time

§7. Forbidden Conflations

The following pairs must not be equated.

FirdarPeriod and FirdarConditionProfile A FirdarPeriod is the raw truth-preservation vessel. A FirdarConditionProfile is a derived doctrinal summary. One is the source; the other is a projection.

level and depth level is a 1-based integer field on the period vessel. It is not a synonym for recursive depth, tree depth, or nesting order. Level 1 is the outermost; Level 4 is the innermost in Releasing.

major_planet and planet FirdarPeriod.planet is the time-lord for that period. FirdarPeriod.major_planet is the planetary anchor of the major grouping to which a sub-period belongs. For major periods, these are equal. For sub-periods, they differ.

is_loosing_of_bond and is_peak_period is_loosing_of_bond is a doctrinal Hellenistic designation preserved from the engine's opposite-sign transfer. is_peak_period is independently derived from the period's angular place relative to Fortune. Neither flag implies the other.

angularity_from_fortune and ZRAngularityClass angularity_from_fortune is the raw 1-based integer distance. ZRAngularityClass is the typed classification derived from that integer. Both are preserved; neither replaces the other.

FirdarMajorGroup and FirdarSequenceProfile A FirdarMajorGroup is a relational grouping of one major period with its subs. A FirdarSequenceProfile is a chart-wide aggregate across all major periods. One is a local relational structure; the other is a global summary.

sequence_kind (Firdaria) and lot_name (Releasing) These are both doctrinal identifiers for their respective techniques but they govern entirely different subsystems and must not be confused or referenced across domains.

DecennialActivePair and DecennialActivePath The pair is a compatibility surface for the major and first subordinate state. The path is the full constitutional Decennials network surface for all simultaneously active admitted levels. They must not be conflated.


Part III — Invariant Register

§8.1 Vessel Invariants

FirdarPeriod:

  • level is either 1 or 2
  • planet is a recognized classical planet or node name
  • start_jd < end_jd
  • level=1 periods have major_planet == planet
  • level=2 periods have major_planet identifying a recognized level-1 planet

ReleasingPeriod:

  • level is 1, 2, 3, or 4
  • start_jd < end_jd
  • angularity_from_fortune, if set, is an integer in the range [1, 12]
  • angularity_class, if set, is a valid ZRAngularityClass value
  • engine-generated periods carry fortune_angularity_truth; evaluated raw truth exactly matches all compatibility fields
  • a missing Fortune produces raw is_peak_period=None while the compatibility field remains False

DecennialPeriod:

  • construction and admitted engine output allow only level 1 or 2; legacy L3/L4 records are rejected rather than deserialized as valid vessels
  • start_jd < end_jd
  • planet is one of the seven classical planets
  • level=1 periods preserve no major_planet, parent_planet, or ancestor_planets
  • level>=2 periods preserve major_planet, parent_planet, parent_level, and ancestor_planets
  • every admitted period has deep_subdivision_method is None
  • engine-generated periods carry the same evaluated sequence_truth; its sequence, sect, sect light, and sequence kind match period metadata

FirdarMajorGroup:

  • subs contains only FirdarPeriod records with major_planet == self.period.planet
  • subs is in strict chronological order (enforced in __post_init__)
  • no two adjacent subs overlap in Julian Day

DecennialMajorGroup:

  • major is always a DecennialPeriod with level=1
  • subs contains only DecennialPeriod records with level=2
  • sub_groups, if supplied, align one-to-one with subs

DecennialPeriodGroup:

  • period is always a DecennialPeriod with level>=2
  • all nested sub_groups are exactly one level deeper than period
  • all nested sub_groups remain temporally contained within period

ZRPeriodGroup:

  • all sub-groups are temporally contained within self.period (±1e-6 tolerance)
  • level equals self.period.level

FirdarConditionProfile:

  • lord_type is one of 'luminary', 'planet', 'node'
  • years > 0 and days > 0
  • is_node_period is mutually exclusive with lord_type == 'luminary'

ZRConditionProfile:

  • years > 0 and days > 0
  • angularity_class is None if and only if angularity_from_fortune is None

DecennialConditionProfile:

  • years > 0, months > 0, and days > 0
  • lord_type is one of 'luminary' or 'planet'
  • admitted profiles have level <= 2 and deep_subdivision_method is None

DashaActiveLine (dasha domain — not in scope here): see DASHA_BACKEND_STANDARD.md


§8.2 Truth Invariants

  • The MINOR_YEARS mapping is immutable. No function in this subsystem modifies or overrides it at runtime.
  • FirdarPeriod.sequence_kind is None for all level-2 (sub) periods. It is set only on level-1 periods.
  • ReleasingPeriod.is_loosing_of_bond is set by the engine at computation time. It is not a derived property and must not be recomputed from sign names.
  • The sum of all level-1 Firdaria period durations in a complete sequence equals exactly 75 years (modulo floating-point accumulation).
  • The sum of all level-1 Decennials period durations in a complete sequence equals exactly 903 schematic months, or 75 years 3 months, on the admitted 30-day-month / 360-day-year distribution basis.
  • All periods in one Decennials sequence preserve the same time-basis and sequence-origin receipt.
  • All periods in one Decennials sequence preserve one identical evaluated DecennialSequenceAssemblyTruth; a non-sect-light longitude tie prevents period generation.
  • DecennialPeriod.sequence_kind is preserved across all admitted Decennials levels.
  • DecennialPeriod.deep_subdivision_method is None for every admitted runtime output; L3/L4 output validation fails closed.
  • Every engine-generated ReleasingPeriod preserves one ZRFortuneAngularityTruth matching its sign and compatibility projection. Missing Fortune is raw not_evaluable, not an evaluated non-peak result.

§8.3 Aggregate Invariants

FirdarSequenceProfile:

  • luminary_major_count + planet_major_count + node_major_count == major_count
  • len(profiles) == major_count (or greater if sub-profiles are included)
  • total_major_years > 0

DecennialSequenceProfile:

  • luminary_major_count + planetary_major_count == major_count
  • level_count_map[1] == major_count
  • sum(level_count_map.values()) == profile_count
  • deepest_level == max(level_count_map)
  • deepest_level <= 2
  • deep_subdivision_method is None

ZRSequenceProfile:

  • angular_count + succedent_count + cadent_count equals the number of profiles classified relative to Fortune
  • angular_count == peak_period_count
  • period_count == len(profiles)
  • total_years > 0

§8.4 Network Invariants

FirdarActivePair:

  • major_profile is always present
  • sub_profile is None if and only if no sub-period is active at the queried JD
  • is_same_lord is meaningful only when has_sub is True

DecennialActivePair:

  • major_profile is always level 1
  • sub_profile, when present, is always level 2

DecennialActivePath:

  • profiles is never empty
  • the first profile is always level 1
  • levels advance one step at a time
  • admitted paths have deepest_level <= 2 and has_deep_subdivision == False

ZRLevelPair:

  • house_distance is in the range [1, 12]
  • house_distance = (lower_sign_index − upper_sign_index) % 12 + 1
  • signs_are_identical is True if and only if house_distance == 1 and the signs are the same (i.e., the lower level is in the same sign as the upper level)

Part IV — Failure Doctrine

§9.1 Invalid Inputs

Firdaria:

  • Passing a non-finite natal_jd to firdaria() raises ValueError.
  • Passing an unrecognized sequence_kind value raises ValueError.
  • Passing an empty periods list to group_firdaria(), firdar_condition_profile(), or aggregate/network functions raises ValueError.

Zodiacal Releasing:

  • Passing a lot_longitude outside [0, 360) may produce incorrect sign assignments. The subsystem does not clamp or validate this; the caller is responsible.
  • Passing an empty periods list to aggregate or network functions raises ValueError.

Common:

  • Passing a non-finite jd to firdar_active_pair() raises ValueError.
  • Passing a non-finite jd to decennial_active_pair() or decennial_active_path() raises ValueError.

Decennials:

  • Passing a non-finite natal_jd or current_jd raises ValueError.
  • Passing missing or non-finite classical natal longitudes raises ValueError.
  • Passing an unadmitted deep method or unadmitted deep level raises ValueError.

§9.2 Search Exhaustion

  • firdar_active_pair() returns None if no major period is active at the queried JD. This is not an error; it means the queried JD lies outside the 75-year sequence.
  • decennial_active_pair() and decennial_active_path() return None if no major period is active at the queried JD.
  • current_decennials() raises ValueError if the queried JD lies outside the admitted Decennials cycle.
  • ZRPeriodGroup.active_sub_at(jd) returns None if no sub-group contains the JD.

§9.3 Invariant Failure

  • validate_firdaria_output() raises ValueError with a descriptive message if:
    • any level-1 period is out of chronological order
    • any two adjacent level-1 periods overlap
    • any level-2 sub-period references a major_planet that has no corresponding level-1 period in the list
    • any level-2 sub-periods within a major group are out of chronological order or overlap
  • validate_releasing_output() raises ValueError with a descriptive message if:
    • periods at any level are out of chronological order
    • any level-N+1 period is not temporally contained within its enclosing level-N period
  • validate_decennials_output() raises ValueError with a descriptive message if:
    • major periods overlap or are out of order
    • subordinate lineage paths are duplicate, unknown, or escape their parent bounds
    • parent-lineage truth, major truth, sequence truth, or deep-method truth drifts
    • sibling children overlap, go out of order, or fail proportional duration sums
  • FirdarMajorGroup.__post_init__ raises ValueError if subs are not in chronological order.
  • DecennialMajorGroup.__post_init__ and DecennialPeriodGroup.__post_init__ raise ValueError if chronology, level, or containment invariants are broken.
  • ZRPeriodGroup.__post_init__ raises ValueError if any sub-group falls outside the parent period's temporal bounds.

Part V — Determinism Standard

§10. Determinism Guarantees

  • firdaria() is fully deterministic: given the same natal_jd and is_day_chart, the output list is identical in every call with no dependency on external state.
  • zodiacal_releasing() is fully deterministic: given the same lot_longitude and natal_jd, the output list is identical in every call.
  • decennials() is fully deterministic: given the same natal inputs, levels, and policy, the output list is identical in every call.
  • Period lists returned by both engines are in strict chronological order by start_jd within each level. The flat list returned by zodiacal_releasing() is ordered by (level, start_jd).
  • group_firdaria(), group_decennials(), and group_releasing() are deterministic: they produce identical groupings for identical inputs.
  • firdar_active_pair() is deterministic: given the same periods list and jd, the result is always the same.
  • decennial_active_pair() and decennial_active_path() are deterministic for identical periods lists and JDs.
  • All condition, aggregate, and network functions are pure (no side effects, no hidden state).
  • Floating-point accumulation across Firdaria sub-period boundaries may produce end_jd values that differ from the major's end_jd by up to a small epsilon. The containment tolerance in ZRPeriodGroup and DashaActiveLine is 1e-6 JD to accommodate this. This tolerance is the only permitted numeric approximation in the subsystem.

Part VI — Validation Codex

§11. Minimum Validation Commands

The following commands must pass without error on any constitutionally correct installation of this subsystem:

.\.venv\Scripts\python.exe -m pytest tests\unit\test_timelords.py tests\unit\test_hellenistic_source_goldens.py -q

All tests in test_timelords.py must pass. The test suite validates:

  • firdaria(), decennials(), and zodiacal_releasing() correctness
  • Valens IV.4 same-sign Spirit/Fortune start shift and the exact 211-month Gemini Loosing-of-the-Bond fixture
  • source-owned Decennial 129-unit circuit, minor-period allotments, and admitted L1/L2 arithmetic
  • FirdarMajorGroup grouping and group_firdaria() fidelity
  • DecennialMajorGroup and DecennialPeriodGroup grouping and group_decennials() fidelity
  • ZRPeriodGroup nesting and group_releasing() fidelity
  • Chronological ordering guards in FirdarMajorGroup.__post_init__
  • recursive containment and chronology guards in Decennial grouping vessels
  • Containment guards in ZRPeriodGroup.__post_init__
  • Subset properties: luminary_subs, node_subs, planet_subs, is_complete
  • ZRPeriodGroup properties: is_leaf, angularity_class, all_periods_flat()
  • FirdarConditionProfile, DecennialConditionProfile, and ZRConditionProfile field fidelity
  • Lord type classification: luminary / planet / node
  • FirdarSequenceProfile, DecennialSequenceProfile, and ZRSequenceProfile counts, totals, and invariant rejection
  • FirdarActivePair boundary behavior, None return, non-finite JD rejection
  • DecennialActivePair and DecennialActivePath boundary behavior and non-finite JD rejection
  • ZRLevelPair house distance, sign identity, peak pair detection
  • validate_firdaria_output() correctness and rejection cases
  • validate_decennials_output() correctness and rejection cases
  • validate_releasing_output() correctness and rejection cases

§12. Required Validation Themes

Any validation suite for this subsystem must demonstrate the following:

Truth preservation:

  • A FirdarPeriod returned by firdaria() carries planet, level, major_planet, start_jd, end_jd, years, and sequence_kind without truncation or flattening.
  • A ReleasingPeriod returned by zodiacal_releasing() carries sign, ruler, level, lot_name, years, is_loosing_of_bond, and angularity_from_fortune without truncation.
  • A DecennialPeriod carries one consistent time_basis, calendar_projection_basis, sequence_origin_jd, and distribution-day interval without forcing consumers to infer them from JD arithmetic.
  • The Valens IV.4 fixture preserves its source receipt separately from the expected same-sign start shift and exact Loosing-of-the-Bond boundaries.

Relational integrity:

  • All sub-periods in a FirdarMajorGroup have major_planet matching the group's major period's planet.
  • All subordinate periods in a DecennialMajorGroup or DecennialPeriodGroup remain temporally contained inside their parent lineage.
  • All ZRPeriodGroup sub-groups are temporally contained within the parent.

Classification correctness:

  • FirdarSequenceKind discriminates DIURNAL vs. NOCTURNAL variants correctly.
  • DecennialSequenceKind discriminates the diurnal solar vs. nocturnal lunar sequence correctly.
  • ZRAngularityClass discriminates ANGULAR / SUCCEDENT / CADENT based on the 1-based distance from Fortune.

Aggregate integrity:

  • luminary_major_count + planet_major_count + node_major_count == major_count in any FirdarSequenceProfile constructed from a valid sequence.
  • luminary_major_count + planetary_major_count == major_count in any DecennialSequenceProfile constructed from a valid sequence.
  • angular_count + succedent_count + cadent_count equals the number of profiles with a non-null Fortune angularity classification.
  • angular_count == peak_period_count.

Network correctness:

  • firdar_active_pair() returns None for JDs outside the sequence.
  • firdar_active_pair() raises ValueError for non-finite JDs.
  • decennial_active_pair() and decennial_active_path() return None for JDs outside the sequence.
  • decennial_active_path() preserves a contiguous active lineage from L1 to the deepest active admitted level.
  • ZRLevelPair.house_distance is computed as (lower − upper) % 12 + 1.

Hardening:

  • validate_firdaria_output() detects out-of-order level-1 periods.
  • validate_firdaria_output() detects overlapping level-1 periods.
  • validate_firdaria_output() detects sub-periods outside their major group.
  • validate_decennials_output() detects lineage drift, deep-method drift, and proportional-sum failure.
  • validate_releasing_output() detects level-N+1 periods outside level-N boundaries.
  • validate_releasing_output() detects out-of-order periods at any level.

Part VII — Future Boundary

§13. Explicit Non-Goals

The following are explicitly outside the scope of this subsystem as constitutionalized.

Not in scope:

  • Chart calculation. The subsystem does not compute natal positions, house cusps, ascendants, or Lot longitudes. These are delegated to the chart engine.

  • Sect determination. Whether a chart is diurnal or nocturnal is computed externally and passed as is_day_chart. The subsystem does not verify this.

  • Lot formula. The formula for computing the Lot of Fortune or Spirit is not defined here. Only the resulting longitude is consumed.

  • Predictive interpretation. The subsystem produces structural timing data. It does not assess whether a period is favorable, challenging, or significant. Interpretation is a higher-level concern.

  • Tropical vs. sidereal zodiac. Zodiacal Releasing is computed over the zodiac defined by the caller's longitude input. The subsystem does not enforce a zodiacal framework.

  • Multi-lot releasing. This subsystem constitutionalizes releasing from a single Lot per call. Simultaneous releasing from Spirit and Fortune is an aggregation concern above this layer.

  • Primary Directions. This subsystem covers Firdaria, Decennials, and Zodiacal Releasing only. Primary Directions are a separate technique and a separate subsystem.

  • Triacontaeteris. This adjacent 30-year chronocrator family is outside this standard and is not a release blocker or an incomplete part of the admitted Hellenistic contract.

  • Decennial L3/L4. Both Valens and Hephaistio deep-subdivision lineages are closed exclusions. No named deep method is selectable in the admitted engine or REST request surface. A future expansion would require a new admission project.

  • Transit and progression overlay. Correlating time-lord periods with transit or progression charts is a cross-subsystem concern and is not part of this standard.

  • Hellenistic bound lord or triplicity lord at period boundaries. These are additional doctrinal overlays that could be computed from natal positions and period boundaries but are not part of the current Firdaria or Releasing subsystems.

Any future extension that crosses these boundaries requires a new constitutional phase or a separate subsystem constitutionalization, not an in-place amendment to this standard.