@essrt/physics 23.3.2 → 23.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +6 -1
  2. package/package.json +2 -2
  3. package/src/constants/coefficients.d.ts +5 -1
  4. package/src/constants/coefficients.js +3 -2
  5. package/src/constants/generated.d.ts +2 -3
  6. package/src/constants/generated.js +3 -4
  7. package/src/constants/units.cjs +4 -1
  8. package/src/deltat/deep-time.cjs +37 -72
  9. package/src/index.js +35 -48
  10. package/src/model/cardinal-instants.js +101 -0
  11. package/src/model/context.js +54 -0
  12. package/src/model/deep-time-chain.js +79 -0
  13. package/src/model/delta-t.js +38 -0
  14. package/src/model/derived-constants.js +58 -0
  15. package/src/model/earth-scalars.js +47 -0
  16. package/src/model/inv-plane-elements.js +56 -0
  17. package/src/model/lunar-theory.js +216 -0
  18. package/src/model/moon-epoch.js +28 -0
  19. package/src/model/one-source-movement.js +192 -0
  20. package/src/model/planet-elements-of-date.js +61 -0
  21. package/src/model/planet-records.js +63 -0
  22. package/src/model/planet-spin-channel.js +41 -0
  23. package/src/model/published-periods.js +38 -0
  24. package/src/model/sun-and-eclipses.js +199 -0
  25. package/src/model/surface.js +330 -0
  26. package/src/model/time-axis.js +24 -0
  27. package/src/model/year-day-lengths.js +42 -0
  28. package/src/model.js +62 -1612
  29. package/src/moon/arguments.cjs +27 -43
  30. package/src/planets/chain-artifact.js +2 -2
  31. package/src/planets/keplerian-chain.cjs +1 -1
  32. package/types/constants/coefficients.d.ts +5 -1
  33. package/types/constants/generated.d.ts +2 -3
  34. package/types/constants/units.d.cts +3 -0
  35. package/types/deltat/deep-time.d.cts +18 -24
  36. package/types/index.d.ts +1 -1
  37. package/types/model/cardinal-instants.d.ts +14 -0
  38. package/types/model/context.d.ts +87 -0
  39. package/types/model/deep-time-chain.d.ts +288 -0
  40. package/types/model/delta-t.d.ts +11 -0
  41. package/types/model/derived-constants.d.ts +25 -0
  42. package/types/model/earth-scalars.d.ts +14 -0
  43. package/types/model/inv-plane-elements.d.ts +6 -0
  44. package/types/model/lunar-theory.d.ts +72 -0
  45. package/types/model/moon-epoch.d.ts +10 -0
  46. package/types/model/one-source-movement.d.ts +74 -0
  47. package/types/model/planet-elements-of-date.d.ts +9 -0
  48. package/types/model/planet-records.d.ts +7 -0
  49. package/types/model/planet-spin-channel.d.ts +29 -0
  50. package/types/model/published-periods.d.ts +7 -0
  51. package/types/model/sun-and-eclipses.d.ts +52 -0
  52. package/types/model/surface.d.ts +279 -0
  53. package/types/model/time-axis.d.ts +12 -0
  54. package/types/model/year-day-lengths.d.ts +8 -0
  55. package/types/model.d.ts +9 -81
  56. package/types/moon/arguments.d.cts +5 -11
  57. package/types/planets/keplerian-chain.d.cts +3 -1
@@ -1,11 +1,10 @@
1
1
  /**
2
2
  * Deep-time LOD / ΔT core — THE shared implementation (Phase 8.4, slice 3).
3
3
  *
4
- * The angular-momentum-conservation LOD (Layer 1/2), the H(t) identity, the
5
- * mass-loss year chain, the Simpson ΔT integrator with the H/5 ecliptic
6
- * "missing motion" integrand, the corrected-LOD composite, the Actual-LOD
7
- * Fourier ripple, and the dLOD/dt driver decomposition (tidal / GIA /
8
- * stack / resonator channels).
4
+ * The angular-momentum-conservation LOD (Layer 1/2), the composed precession
5
+ * rate, the mass-loss year chain, the Simpson ΔT integrator with the ecliptic
6
+ * "missing motion" integrand, the corrected-LOD composite, and the dLOD/dt
7
+ * driver decomposition (tidal / GIA / stack / resonator channels).
9
8
  *
10
9
  * INJECTED, by design:
11
10
  * - moonDistanceMetresAtAge — the 8.2 moon month-chain (each engine's own
@@ -44,11 +43,11 @@ const { createComposedPrecession } = require('../earth/precession-composed.cjs')
44
43
  * @property {number} aLockMetres - tidal-lock distance (LOD denominator → 0)
45
44
  * @property {number} aMoonNowMetres - Farhat polynomial anchor
46
45
  * @property {number} alpha1PerMa - the LLR recession rate (the J2000 slope of the cited history)
47
- * @property {number} lodNowH13Seconds - ω₀, the J2000 day length (the SI day since plan 09; identifier kept)
46
+ * @property {number} lodNowH13Seconds - ω₀, the J2000 day length (the SI day; identifier kept)
48
47
  * @property {number} meanSiderealYearJ2000Seconds
49
48
  * @property {number} solarMassLossFracPerYear
50
49
  * @property {number} precessionSolarShareJ2000 - f_S, the solar fraction of the J2000
51
- * precession torque (derive-params) — the unit H(t) = 13·T_p,composed needs it
50
+ * precession torque (derive-params) — the composed precession rate needs it
52
51
  */
53
52
 
54
53
  /**
@@ -59,23 +58,20 @@ const { createComposedPrecession } = require('../earth/precession-composed.cjs')
59
58
  * @property {(year: number) => number} cycleLodSumAt - gated δLOD sum (incl. swing)
60
59
  * @property {(year: number) => number} swingLodAt - gated swing δLOD alone
61
60
  * @property {(year: number) => number} swingLodRateAt - gated analytic swing rate
62
- * @property {() => number} precessionPeriodJ2000YearsFn - the model's DERIVED
63
- * J2000 axial precession period: the certified year-length laws' beat at
64
- * 2000, sid/(sid − trop) ≈ 25,771.4 yr (plan 06 S5 — one J2000 precession
65
- * reading; the same anchor the hybrid obliquity self-anchors on). Read
61
+ * @property {() => number} precessionPeriodJ2000YearsFn - the model's J2000 axial
62
+ * precession period, 1,296,000/p_A = 25,771.575 yr (the IAU 2006 general
63
+ * precession; the same anchor the hybrid obliquity self-anchors on). Read
66
64
  * LAZILY on the first composed-rate use, never at construction: every
67
65
  * runtime's year laws read THIS factory's bases.
68
66
  * @property {() => number} nodalPeriodYearsFn - the period of Earth's orbit
69
67
  * plane's nodal regression on the invariable plane, 1,296,000/|s₃| with s₃
70
68
  * the dominant ζ mode of the banked deep secular modes (≈ 68,751 yr). An
71
69
  * ORBITAL quantity (μ-tier: it does not follow Earth's spin), the reference
72
- * the solar day's "ecliptic missing motion" term rides (plan 06 T2 item —
73
- * formerly the spin unit's H/5, 67,063 yr, 2.5 % off and scaling with the
74
- * spin at deep time). Lazy, like the precession anchor.
70
+ * the solar day's "ecliptic missing motion" term rides. Lazy, like the
71
+ * precession anchor.
75
72
  * @property {(tMa: number) => number} [lEmAtAgeKgm2S] - OPTIONAL time-dependent
76
73
  * Earth-Moon angular momentum. Absent → the J2000 constant: conservation
77
- * (plan 12 option A — the Driver-1½ solar-channel budget is deleted;
78
- * measured: conservation on the cited history reproduces Farhat's own LOD
74
+ * (measured: conservation on the cited history reproduces Farhat's own LOD
79
75
  * to 0.01 h at 100 Ma, 0.14 h at 2.46 Ga).
80
76
  * @property {(tMa: number) => number|null} [moonDistanceSlopeMetresPerMaAtAge] -
81
77
  * OPTIONAL analytic slope of the distance history (metres per Ma, positive
@@ -84,7 +80,7 @@ const { createComposedPrecession } = require('../earth/precession-composed.cjs')
84
80
  * @property {(tMa: number) => number|null} [meanObliquityCosRatioAtAge] -
85
81
  * OPTIONAL cos ε̄(t)/cos ε̄(0) of the cited mean obliquity (earth/mean-
86
82
  * obliquity-history) — the factor the precession RATE of date carries on the
87
- * constant (plan 12 §8 option (a)); absent → 1, the constant alone, bit-identical.
83
+ * constant; absent → 1, the constant alone, bit-identical.
88
84
  */
89
85
 
90
86
  /** @param {DeepTimeLodDeps} deps */
@@ -117,26 +113,12 @@ function createDeepTimeLod(deps) {
117
113
  return (s === null) ? null : s / 3600;
118
114
  }
119
115
 
120
- // (Plan 09 step 7a deleted the FROZEN ERA CLOCK's public counter
121
- // `eraClockHAtAge` — H_era(t) = H₀·LOD(t)/LOD₀, plan 06 D8's second named
122
- // counter — with its year twins; step 7b deleted the unit itself, `hAtAge`
123
- // = H_era/[f_S + (1 − f_S)(a₀/a_M)³] — H(t) was 13.011 composed precession
124
- // periods, a fit constant's multiple of T_p(t), never a period of anything
125
- // the model computes. The physics it scaled is the composed precession
126
- // below: ψ̇(t) and T_p(t) = 1,296,000/ψ̇ are the published quantities.)
127
- // The `…FromLod` twins take an ALREADY-COMPUTED LOD(t): the Simpson ΔT
128
- // integrand below evaluated the LOD four times and the tropical year twice
129
- // per node through these helpers (measured 8.8 → 4.8 ms per cardinal panel
130
- // year with the model's ΔT memo). Same operations, same inputs — every
131
- // value bit-identical (11,958-value sweep, 0 differences).
132
-
133
- // The composed lunisolar precession (plan 06 D6 → Phase 3 → S5; plan 12 §8):
134
- // the CONSTANT's scaling [ω(t)/ω₀]·p₀·[f_S + (1 − f_S)(a₀/a_M(t))³] and the
135
- // RATE of date, that × cos ε̄(t)/cos ε̄(0) on the cited mean obliquity; p₀ the
136
- // model's J2000 rate 1,296,000/axial0 (the IAU 2006 general precession since
137
- // plan 09). ONE formula home: earth/precession-composed, built here on this
138
- // factory's own LOD, recession and obliquity histories; the anchor resolves
139
- // lazily on the first rate use.
116
+ // The composed lunisolar precession: the CONSTANT's scaling
117
+ // [ω(t)/ω₀]·p₀·[f_S + (1 − f_S)(a₀/a_M(t))³] and the RATE of date, that ×
118
+ // cos ε̄(t)/cos ε̄(0) on the cited mean obliquity; p₀ the model's J2000 rate
119
+ // 1,296,000/axial0 (the IAU 2006 general precession). ONE formula home:
120
+ // earth/precession-composed, built here on this factory's own LOD, recession
121
+ // and obliquity histories; the anchor resolves lazily on the first rate use.
140
122
  const composed = createComposedPrecession({
141
123
  p0ArcsecPerYr: () => 1296000 / deps.precessionPeriodJ2000YearsFn(),
142
124
  solarShare: K.precessionSolarShareJ2000,
@@ -148,11 +130,10 @@ function createDeepTimeLod(deps) {
148
130
  meanObliquityCosRatioAtAge: deps.meanObliquityCosRatioAtAge,
149
131
  });
150
132
 
151
-
152
133
  /** THE PRECESSION RATE OF DATE ψ̇(t), ″/yr — the constant's scaling
153
134
  * p₀·[ω/ω₀]·[f_S + (1 − f_S)(a₀/a_M)³] × cos ε̄(t)/cos ε̄(0), ε̄ the cited mean
154
- * obliquity (plan 12 §8 option (a); the chain held cos ε̄ at J2000 before —
155
- * 2.5 % of rate at 2.46 Ga, 2e-7 at 10 kyr). p₀ the J2000 anchor (S5).
135
+ * obliquity (its factor is 2.5 % of the rate at 2.46 Ga, 2e-7 at 10 kyr);
136
+ * p₀ the J2000 anchor.
156
137
  * @param {number} t_Ma @returns {number|null} */
157
138
  function lunisolarPrecessionRateArcsecPerYrAtAge(t_Ma) {
158
139
  return composed.composedRateArcsecPerYrAtAge(t_Ma);
@@ -192,23 +173,18 @@ function createDeepTimeLod(deps) {
192
173
  // a(t) = a₀·(1−Δm)): T ∝ M⁻² ⇒ T(t) = T₀·(1−Δm)² — the SAME Driver-2
193
174
  // law the planet chains use (orbit-chain driver2PeriodSecondsAtAge).
194
175
  // The previous (1 − 2Δm) was this law's first-order Taylor — the one
195
- // form in the model inconsistent with it (measured on the retired day-count
196
- // identity of the era counter: with the product form the counter's
197
- // H_era·(days/yr)·(AU₀/AU)² held exactly — a tautology of spin scaling ∘
198
- // Kepler, deleted with the counter and the unit at plan 09 steps 7a/7b).
176
+ // form in the model inconsistent with it.
199
177
  return K.meanSiderealYearJ2000Seconds * (1 - mass_loss_fraction) * (1 - mass_loss_fraction);
200
178
  }
201
179
 
202
180
  /** Tropical year of date, seconds — the sidereal year less the equinox's
203
181
  * own motion over one year: one turn per the composed lunisolar precession
204
182
  * period T_p(t), 1/T_trop = 1/T_sid + ψ̇(t)/(1,296,000″ · Julian-year s),
205
- * ψ̇(t) the RATE of date (with the cited mean obliquity's cosine, plan 12 §8).
206
- * Plan 09 step 5d: it was the unit's calendar convention sid·(1 − 13/H(t))
207
- * — plan 06 D2 had kept it as a named device — 0.086 % slow on the equinox
208
- * term (1.0 s of year at J2000), and the deep JD↔year calendar integrates
209
- * THIS. The SAME operations as layer0's tropicalYearSecondsCore (the
210
- * layer0 gate holds the twins bit-identical). Past the tidal chain's domain
211
- * the J2000 rate stands in. @param {number} t_Ma @returns {number} */
183
+ * ψ̇(t) the RATE of date (with the cited mean obliquity's cosine). The deep
184
+ * JD↔year calendar integrates THIS. The SAME operations as layer0's
185
+ * tropicalYearSecondsCore (the layer0 gate holds the twins bit-identical).
186
+ * Past the tidal chain's domain the J2000 rate stands in.
187
+ * @param {number} t_Ma @returns {number} */
212
188
  function tropicalYearSecondsAtAge(t_Ma) {
213
189
  return tropicalYearSecondsFromLod(t_Ma, lodSecondsAtAge(t_Ma));
214
190
  }
@@ -235,10 +211,6 @@ function createDeepTimeLod(deps) {
235
211
  return tropicalYearSecondsAtAge(t_Ma) / LOD_s;
236
212
  }
237
213
 
238
- // (Plan 09 step 7a: the frozen era clock's year twins on H_era —
239
- // T_sid·(1 − 13/H_era) and its day count, the bases the deleted cardinal
240
- // record and year-length combs were fitted against — are deleted.)
241
-
242
214
  /**
243
215
  * The solar day's "ecliptic missing motion" correction, seconds: the mean
244
216
  * solar day is counted against the Sun on the ECLIPTIC, whose plane turns
@@ -247,8 +219,7 @@ function createDeepTimeLod(deps) {
247
219
  * (≈ 3.44 ms at J2000). T_s₃ is an orbital quantity: constant at every
248
220
  * epoch (μ-tier), so the term rides only LOD_mean and the year length at
249
221
  * deep time. ONE home for the three runtimes' `h5Correction` twins (the
250
- * identifier keeps its name; the divisor is the nodal period since the
251
- * plan 06 T2 restatement, formerly the spin unit's H/5).
222
+ * identifier keeps its historical name; the divisor is the nodal period).
252
223
  * @param {number} t_Ma @returns {number|null} seconds (null past tidal lock)
253
224
  */
254
225
  function eclipticLodCorrectionSecondsAtAge(t_Ma) {
@@ -305,10 +276,6 @@ function createDeepTimeLod(deps) {
305
276
  return tidal + deps.cycleLodSumAt(year);
306
277
  }
307
278
 
308
- // (Plan 09: the "Actual LOD" — the tidal mean × the retired sidereal-year
309
- // comb's ripple — is deleted with the comb; the ripple was the sidereal
310
- // year's λ̇ variation misattributed to the day length.)
311
-
312
279
  /**
313
280
  * dLOD/dt driver decomposition, ms/century per channel.
314
281
  * tidal: Moon-recession (Farhat da/dt, LLR-anchored) · gia: α(t) numeric
@@ -331,12 +298,11 @@ function createDeepTimeLod(deps) {
331
298
  const I_E = alpha * K.mEarthAloneKg * K.rEarthMetres * K.rEarthMetres;
332
299
  const year = 2000 - t_Ma * 1e6;
333
300
 
334
- // The cited history's slope (plan 12 option A): the engine's
335
- // moonDistanceSlopeMetresPerMaAtAge when it provides one (the Hermite's
336
- // analytic derivative — C1, smooth), else a ±1-kyr central difference on
337
- // the distance itself. t_Ma > 0 = past; forward-time sign flip. At J2000
338
- // the slope IS the LLR observation (the history's boundary condition):
339
- // +3.82 cm/yr ✓
301
+ // The cited history's slope: the engine's moonDistanceSlopeMetresPerMaAtAge
302
+ // when it provides one (the Hermite's analytic derivative — C1, smooth),
303
+ // else a ±1-kyr central difference on the distance itself. t_Ma > 0 =
304
+ // past; forward-time sign flip. At J2000 the slope IS the LLR observation
305
+ // (the history's boundary condition): +3.82 cm/yr ✓
340
306
  let slopePerMa = deps.moonDistanceSlopeMetresPerMaAtAge ? deps.moonDistanceSlopeMetresPerMaAtAge(t_Ma) : null;
341
307
  if (slopePerMa === null || slopePerMa === undefined) {
342
308
  const H_MA = 1e-3;
@@ -387,19 +353,18 @@ function createDeepTimeLod(deps) {
387
353
  return {
388
354
  lodSecondsAtAge, lodSecondsAtAgeWithAlpha, lodHoursAtAge,
389
355
  lunisolarPrecessionRateArcsecPerYrAtAge, lunisolarPrecessionPeriodYearsAtAge,
390
- // the constant's scaling alone (the hybrid's integrand) and the rate's obliquity factor (plan 12 §8)
356
+ // the constant's scaling alone (the hybrid's integrand) and the rate's obliquity factor
391
357
  lunisolarTorqueRateArcsecPerYrAtAge, lunisolarTorquePeriodYearsAtAge, precessionObliquityFactorAtAge,
392
- // the composition's terms (plan 06 Phase 3 S3, the lunisolar surface): (a₀/a_M)³ and f_S + (1 − f_S)(a₀/a_M)³
358
+ // the composition's terms (the lunisolar surface): (a₀/a_M)³ and f_S + (1 − f_S)(a₀/a_M)³
393
359
  lunarTorqueFactorAtAge: composed.lunarTorqueFactorAtAge,
394
360
  precessionTorqueTermAtAge: composed.torqueTermAtAge,
395
361
  siderealYearSecondsAtAge, tropicalYearSecondsAtAge, tropicalYearDaysAtAge,
396
- // the same law on a caller-supplied LOD (the browser's L1-α sensitivity sweep; plan 09 step 7c)
362
+ // the same law on a caller-supplied LOD (the browser's L1-α sensitivity sweep)
397
363
  tropicalYearSecondsFromLod,
398
- // the solar day's ecliptic missing-motion term on the nodal period (plan 06 T2 item; one home)
364
+ // the solar day's ecliptic missing-motion term on the nodal period (one home)
399
365
  eclipticLodCorrectionSecondsAtAge,
400
366
  yearInDaysAtAge, deltaTRawSecondsAtAge, lodSecondsWithCorrectionsAtAge,
401
367
  dLodDtDecompositionAtAge,
402
- // (plan 09 step 7a: the frozen era clock's counter and bases left with the last comb)
403
368
  };
404
369
  }
405
370
 
package/src/index.js CHANGED
@@ -61,7 +61,7 @@ const NEVER_INJECTABLE = Object.keys(REFERENCE_DATA);
61
61
 
62
62
  /**
63
63
  * Generated at build time from `public/input/astro-reference.json` (plus the
64
- * deep-time block the generator assembles; model-parameters.json is deleted, plan 11)
64
+ * deep-time block the generator assembles)
65
65
  * (§2g) by `tools/constants/generate.mjs`. 324 values across 15 blocks.
66
66
  *
67
67
  * Free parameters and measured anchors only. Validation targets are excluded by
@@ -95,29 +95,21 @@ export { FITTED_COEFFICIENTS, COEFFICIENTS_HASH } from './constants/index.js';
95
95
  export { createEpochPrimitives } from './layer0/index.js';
96
96
  export { deriveEpochParams } from './layer0/derive-params.js';
97
97
  export { createDerivedViews } from './layer1/index.js';
98
- // (Plan 09 step 7a: the Phase 7 integrated-phase machinery `createPhaseMachinery`
99
- // — the ∫dt/H_era table and the cycle counters every comb read — and the
100
- // frozen cardinal record evaluator `createCardinalModel` (the §10 derived
101
- // form on the deleted CARDINAL_POINT_* coefficients) are DELETED; the
102
- // cardinal instants are createModel().cardinal, the one Sun's crossings.)
103
98
  // The deep-time calendar (year ↔ JD under the drifting year length) — ONE
104
- // implementation for both engines since the year/day collapse (formerly the
105
- // PHASE-B-DUPLICATE family). CJS on purpose: tools/lib requires the same
99
+ // implementation for both engines. CJS on purpose: tools/lib requires the same
106
100
  // file via the exports-map subpath; re-exported here so bundled ESM
107
101
  // consumers need only the package root.
108
102
  export { createDeepCalendar } from './phase/deep-calendar.cjs';
109
- // Plan 13 B1: the civil calendar ↔ JD (Meeus ch. 7 with the 1582-10-15
110
- // reform) and the angle constants/wraps — ONE home; the browser's eighteen
111
- // calendar copies and 27 local D2R constants import these.
103
+ // The civil calendar ↔ JD (Meeus ch. 7 with the 1582-10-15 reform) and the
104
+ // angle constants/wraps — ONE home for every runtime.
112
105
  export { GREGORIAN_START, GREGORIAN_START_JD, calendarToJD, jdToCalendar, jdToDecimalYear, dayFractionToHMS, julianCalendarToJD, jdToJulianCalendar } from './time/calendar.cjs';
113
106
  export { DEG2RAD, RAD2DEG, ARCSEC_PER_TURN, ARCSEC_PER_RAD, wrap360, wrap180, wrap180Closed, wrap2pi, wrapPi } from './math/angles.cjs';
114
- // Plan 13 B2: THE deep-time chain assembly — the GIA α channel, the Layer-0
115
- // bundle, the cited Moon-distance history, the ΔT cycle stack, |s₃|, the
116
- // LOD/ΔT core, the lunar month chain and the mean*AtAge family, assembled
117
- // ONCE from the generated constants; the Node twin and the browser destructure it.
107
+ // THE deep-time chain assembly — the GIA α channel, the Layer-0 bundle, the
108
+ // cited Moon-distance history, the ΔT cycle stack, |s₃|, the LOD/ΔT core, the
109
+ // lunar month chain and the mean*AtAge family, assembled ONCE from the
110
+ // generated constants; the Node twin and the browser destructure it.
118
111
  export { createDeepTimeChain, MOON_ECC_SENSITIVITY_PERIGEE, MOON_ECC_SENSITIVITY_NODE } from './deltat/deep-time-chain.js';
119
- // Plan 13 B3: the J2000 mass chain and the Moon's J2000 periods (one home for
120
- // three copies each) and the unit constants.
112
+ // The J2000 mass chain, the Moon's J2000 periods and the unit constants — ONE home.
121
113
  export { computeMassChainJ2000, computeMoonPeriodsJ2000 } from './earth/mass-chain.cjs';
122
114
  export { SECONDS_PER_DAY, DAYS_PER_JULIAN_YEAR, JULIAN_CENTURY_DAYS, SECONDS_PER_JULIAN_YEAR } from './constants/units.cjs';
123
115
  // D4b: the one-source cardinal structure — the EoC layer (year lengths,
@@ -127,7 +119,6 @@ export { createCardinalStructure } from './cardinal/one-source-structure.cjs';
127
119
  // Phase 8.2 — the lunar machinery, extracted layer by layer (survey order:
128
120
  // eccentricity channel → month chain → cycle tables → arguments → series →
129
121
  // apparent). Same CJS + root re-export convention.
130
- // (plan 09 step 6: createMoonEccChannel — the H/3 eccentricity law — is deleted; Earth's e of date is the N-body series on every path)
131
122
  export { createMoonMonthChain } from './moon/month-chain.cjs';
132
123
  export { createChainCycleIntegrator } from './chain-cycles/index.cjs';
133
124
  export { createMoonArguments } from './moon/arguments.cjs';
@@ -137,26 +128,26 @@ export { createMoonApparent } from './moon/apparent.cjs';
137
128
  // sample) and the offset-circle wheel-angle solver: the scene twins' one placement.
138
129
  export { computeEarthFrameOfDate, solveWheelAngleForLongitude, computeSceneWorldFrameJ2000, SCENE_EQUINOX_VIEW_AZIMUTH_DEG } from './earth/frame-of-date.cjs';
139
130
  // Phase 8.3 — the planet machinery, extracted by LAW over body records
140
- // (survey order: geometry → channels → chains). The ψ/K amplitude laws
141
- // (planets/fibonacci-laws), the record-based orientation forms
142
- // (planets/orientation) and the ascending-node integrator
143
- // (planets/asc-node-integrator) are DELETED at plan 07 R5/R6: the planets'
144
- // elements of date have one home, the N-body chain.
131
+ // (survey order: geometry → channels → chains). The planets' elements of date
132
+ // have one home, the N-body chain.
145
133
  export { derivePlanetGeometry, scaffoldOrbitInputs } from './planets/geometry.cjs';
146
134
  // (plan 09 step 6: eccentricityFromCycles / computeEccentricityIntegrated — the H/16 law-of-cosines eccentricity — are deleted; no runtime read them)
147
135
  export * as planetOrbitChain from './planets/orbit-chain.cjs';
148
136
  // P5/K4.6c — the engine-D Keplerian chain (pure evaluator + the embedded
149
137
  // governed artifact; the browser flag path consumes exactly these).
150
138
  export { computeSecularShape } from './planets/secular-shape.cjs';
151
- export { buildPlanetChainsFromArtifactData, computePlanetElementsAtYear, computeHeliocentricEclipticFromElements, computePoissonArgRad, computeOsculatingElements, solveKeplerRad, computeApsidalSecularDegPerYr, ANCHOR_EPOCH_YEAR, ANCHOR_EPOCH_JD } from './planets/keplerian-chain.cjs';
139
+ // `computeApsidalTangentDegPerYr` is the chain's ±150-yr central tangent of the perihelion
140
+ // longitude (the panels' "Prec." cell — osculating, NOT the ±1-kyr secular stencil of the
141
+ // "Secular" cell); `computeApsidalSecularDegPerYr` is its former name, kept as a deprecated
142
+ // alias on the API axis.
143
+ export { buildPlanetChainsFromArtifactData, computePlanetElementsAtYear, computeHeliocentricEclipticFromElements, computePoissonArgRad, computeOsculatingElements, solveKeplerRad, computeApsidalSecularDegPerYr, computeApsidalSecularDegPerYr as computeApsidalTangentDegPerYr, ANCHOR_EPOCH_YEAR, ANCHOR_EPOCH_JD } from './planets/keplerian-chain.cjs';
152
144
  export { computeEquatorNodeOriginSFrameDeg, convertNodeSFrameToEquatorOriginDeg } from './planets/inv-plane-frame.cjs';
153
145
  export { createSecularSeriesOverride } from './planets/secular-series.cjs';
154
- // Plan 06 Phase 7 — the planets' spin channel (the precession constant from
155
- // each planet's own torques, the spin integrated on its own ζ plane history).
146
+ // The planets' spin channel (the precession constant from each planet's own
147
+ // torques, the spin integrated on its own ζ plane history).
156
148
  export { computePlanetPrecessionConstant, createPlanetSpinChannel, createPlanetSpinChannelFromArtifacts, computeObliquityJ2000Deg } from './planets/spin-channel.cjs';
157
149
  export { CHAIN_ARTIFACT, CHAIN_ARTIFACT_HASH } from './planets/chain-artifact.js';
158
- // Engine-switch Stage B, T5d-(d): the deep-time Earth-z channel (the deep
159
- // lunar-chain modulation rides it; era consumers stay on the H/3 channel).
150
+ // The deep-time Earth-z channel (the deep lunar-chain modulation rides it).
160
151
  export { createDeepEccChannel } from './moon/deep-ecc-channel.cjs';
161
152
  export { DEEP_MODES_ARTIFACT, DEEP_MODES_ARTIFACT_HASH } from './moon/deep-modes-artifact.cjs';
162
153
  // Stage C-3: the ONE home of the obliquity-hybrid / deep-orbital-history
@@ -166,28 +157,25 @@ export { createDeepOrbitalHistory } from './earth/deep-orbital-history.cjs';
166
157
  export { createSiderealYearChannel } from './earth/sidereal-year-channel.cjs';
167
158
  // S2: THE ONE of-date year-length family (years + precession beats, SI seconds)
168
159
  export { createYearLengths, computeMeanTropicalYearJ2000Days, ONE_FAMILY_WINDOW_YEARS } from './earth/year-lengths.cjs';
169
- // Plan 06 D6: THE ONE home of the composed lunisolar precession rate ψ̇(t)
170
- // (spin ω(t) × [solar torque + lunar torque on the recession history]) —
171
- // leg-1's physical rate; the structural H(t)/13 clock is its named diagnostic.
160
+ // THE ONE home of the composed lunisolar precession rate ψ̇(t) (spin ω(t) ×
161
+ // [solar torque + lunar torque on the recession history]) — falsification
162
+ // leg 1's physical rate.
172
163
  export { computeSolarTorqueShare, createComposedPrecession } from './earth/precession-composed.cjs';
173
- // Plan 12 §8 option (a): the cited mean obliquity of date — the second column read from the
174
- // Earth–Moon history; the precession RATE of date carries its cos ε̄(t)/cos ε̄(0) on the constant.
164
+ // The cited mean obliquity of date — the second column read from the Earth–Moon
165
+ // history; the precession RATE of date carries its cos ε̄(t)/cos ε̄(0) on the constant.
175
166
  export { createMeanObliquityHistory } from './earth/mean-obliquity-history.cjs';
176
167
  // (planets/predict.cjs — the planet predictive-precession feature basis — was
177
168
  // retired at plan 06 R8 with PREDICT_COEFFS_PHYSICAL.)
178
169
  // L10 — the composition front door: one law set, N body records. Thin by
179
170
  // design; engines keep their direct call sites (see planets/model.cjs).
180
171
  export { createPlanetModel } from './planets/model.cjs';
181
- // plan 11 step 6 — the planets' presentation names, the last leaf of the
182
- // deleted model-parameters.json (code, not an input: not injectable, not hashed).
172
+ // the planets' presentation names (code, not an input: not injectable, not hashed).
183
173
  export { PLANET_DISPLAY_NAMES } from './planets/display-names.cjs';
184
174
  // Phase 8.4 — the climate/ΔT machinery, extracted layer by layer.
185
175
  export { createDeltaTCycles } from './deltat/cycles.cjs';
186
176
  export { createDeepTimeLod } from './deltat/deep-time.cjs';
187
- // plan 12 (option A): the Earth–Moon distance history is a CITED PHYSICAL
188
- // INPUT (Farhat et al. 2022, the AstroGeo22 ephemeris) read as a shape on the
189
- // model's J2000 anchor; the fitted quartic, the rock-fitted regime spline and
190
- // the solar-channel budget are deleted.
177
+ // The Earth–Moon distance history is a CITED PHYSICAL INPUT (Farhat et al.
178
+ // 2022, the AstroGeo22 ephemeris) read as a shape on the model's J2000 anchor.
191
179
  export { createMoonDistanceHistory } from './deltat/moon-distance-history.cjs';
192
180
  export { MOON_DISTANCE_ARTIFACT, MOON_DISTANCE_ARTIFACT_HASH } from './deltat/moon-distance-artifact.cjs';
193
181
  export { deltaTEspenakMeeusCanonSeconds } from './deltat/historical.cjs';
@@ -199,9 +187,6 @@ export { createEclipseFinders } from './eclipse/finders.cjs';
199
187
  // (reference/published-curves MIGRATED to @essrt/reference at the 4.0.0
200
188
  // major — the published model package carries no comparison references;
201
189
  // the K2 one-way wall is package-structural.)
202
- // Phase 9 — S-P8: the fitted sun-longitude harmonic stack (three copies → one).
203
- // (plan 09 step 5a: createSunLongitudeCorrection — the Step-0 Sun comb's evaluator,
204
- // retired from the Sun node at plan 06 R4 — is deleted with the comb and its fitter.)
205
190
 
206
191
  /**
207
192
  * Build a model bound to a set of constants.
@@ -270,15 +255,12 @@ export const createModel = (constants = GENERATED, opts = {}) => {
270
255
  constants: ctx,
271
256
  hash,
272
257
 
273
- // Plan 09: the fit-era lattice identities H/13, H/3, H/16
274
- // (`computeLatticePeriodsYears`, DEVICE tier) left this surface — the
275
- // published periods are `epoch.axialPrecessionYearsAtYear` and the
258
+ // The published periods are `epoch.axialPrecessionYearsAtYear` and the
276
259
  // lunisolar surface's apsidal and perihelion-of-date periods; the
277
- // counterfactual gate now reads the obliquity anchor through the assembly.
260
+ // counterfactual gate reads the obliquity anchor through the assembly.
278
261
 
279
262
  /**
280
- * Earth eccentricity at a year — the Phase-6 promise, fulfilled by the
281
- * §7a assembly (law-of-cosines on the integrated H/16 phase).
263
+ * Earth eccentricity at a year — the one-source series through the §7a assembly.
282
264
  * @param {number} year
283
265
  * @returns {number}
284
266
  */
@@ -294,6 +276,11 @@ export const createModel = (constants = GENERATED, opts = {}) => {
294
276
  coefficientsHash: COEFF_HASH,
295
277
  counterfactual: hash !== CONSTANTS_HASH,
296
278
  preprintDoi: PREPRINT_DOI,
279
+ // Which evaluator serves Earth's orbit elements away from J2000: the banked
280
+ // N-body series (every published surface passes it) or the embedded 18-term
281
+ // mode table (the bare package — exact at J2000, e RMS 3.6e-3 vs La2010a
282
+ // over 500 kyr where the series reads 2.5e-5). A stored result names it.
283
+ earthElements: opts.secularSeriesArtifact ? 'secular-series' : 'mode-table',
297
284
  }),
298
285
 
299
286
  // The assembled surfaces (§7a step 1): epoch, earth, lengths, cardinal, moon.
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Cardinal instants — the apparent Sun (completed, aberrated, nutated) and the Newton crossings.
3
+ *
4
+ * One slice of `assembleModel` (../model.js): receives the context the earlier slices built, returns the bindings the later ones read.
5
+ */
6
+
7
+ /** @param {import('./published-periods.js').Ctx} ctx @returns the bindings the later slices read */
8
+ export function assembleCardinalInstants(ctx) {
9
+ const {
10
+ C, F, currentAUDistance, eclipseFinders, j2000JD, jdTTFromUT, julianCenturyDays, moonArgs, sunEccentricityAt,
11
+ sunPlanetaryCompletionDeg, yearLengthsM,
12
+ } = ctx;
13
+ /** The completed certified Sun (finder Sun − the derived planetary
14
+ * completion) at a UT model-JD — the same longitude the scene renders
15
+ * inside the overlay window; MEAN GEOMETRIC, mean equinox of date.
16
+ * @param {number} jdUT @returns {number} */
17
+ const sunLonCompletedDegAtJdUT = (jdUT) => eclipseFinders.sunLonDegAt(jdUT)
18
+ - sunPlanetaryCompletionDeg((jdTTFromUT(jdUT) - j2000JD) / julianCenturyDays);
19
+ /** The APPARENT Sun the cardinal instants are defined on (an equinox is
20
+ * the apparent Sun crossing the equator — the USNO/Meeus instants are
21
+ * apparent): the completed geometric Sun minus the aberration constant,
22
+ * plus the nutation in longitude. Both derived, zero new constants —
23
+ * κ = 2π·a/(c·T_sid·√(1−e²)) from the AU, c, the one-family sidereal year
24
+ * and the Sun's e (20.50″ at J2000); Δψ from the four IAU 1980 leading
25
+ * terms on the model's OWN lunar node, mean Sun and mean Moon (the
26
+ * framework arguments), the same family the registry's JPL Sun
27
+ * instrument bridges with. @param {number} jdUT @returns {number} */
28
+ /** The Sun's derived aberration constant of date, arcsec — κ = 2π·a/(c·T_sid·√(1−e²))
29
+ * from the AU, c, the one-family sidereal year and the Sun's e (20.50″ at
30
+ * J2000); ONE home for the cardinal instants and the eclipse location tier.
31
+ * @param {number} year @returns {number} */
32
+ const sunAberrationArcsecAt = (year) => {
33
+ const e = sunEccentricityAt(year);
34
+ return (2 * Math.PI * currentAUDistance
35
+ / (C.physicalConstants.speedOfLight * yearLengthsM.siderealYearSecondsAtYear(year) * Math.sqrt(1 - e * e)))
36
+ * (648000 / Math.PI);
37
+ };
38
+ /** @param {number} jdUT @returns {number} */
39
+ const sunApparentLonDegAtJdUT = (jdUT) => {
40
+ const jdTT = jdTTFromUT(jdUT);
41
+ const year = 2000 + (jdTT - j2000JD) / 365.25;
42
+ const kappaArcsec = sunAberrationArcsecAt(year);
43
+ const a = moonArgs.argsAt(jdTT);
44
+ const d2r = Math.PI / 180;
45
+ const Om = (a.Lp - a.F) * d2r, Ls = (a.Lp - a.D) * d2r, Lm = a.Lp * d2r;
46
+ const NU = C.physicalConstants.nutationLeadingTermsArcsec;
47
+ const dPsiArcsec = NU.psiOmega * Math.sin(Om) + NU.psi2Ls * Math.sin(2 * Ls)
48
+ + NU.psi2Lm * Math.sin(2 * Lm) + NU.psi2Omega * Math.sin(2 * Om);
49
+ return sunLonCompletedDegAtJdUT(jdUT) + (dPsiArcsec - kappaArcsec) / 3600;
50
+ };
51
+ /** @param {string} type @returns {number} */
52
+ const cardinalTargetDeg = (type) => {
53
+ const t = { VE: 0, SS: 90, AE: 180, WS: 270 }[type];
54
+ if (t === undefined) throw new RangeError(`cardinal type must be VE|SS|AE|WS, got ${type}`);
55
+ return t;
56
+ };
57
+ const CARDINAL_SI_YEAR_D = 365.2422;
58
+ /** The crossing NEAREST a seed instant — the unique root within ±½ tropical
59
+ * year of the seed (the wrapped longitude difference is the Newton residual).
60
+ * Plan 06 R4c: the seed is a JD because the caller's year may live on a
61
+ * different axis than the model year — the simulator's cardinal panel
62
+ * labels its year with the displayed CALENDAR date (the Julian calendar
63
+ * before 1582, 365.25-d years) while `year` below is the model year (the SI
64
+ * axis, 365.2422-d count from J2000); the two part by 0.0078 d/yr, 114 yr at
65
+ * −5.34 Myr, where the panel showed the events of −5341772 for a date in
66
+ * −5341886 (owner). Seeding at the calendar year's midpoint returns that
67
+ * year's own events at every epoch. @param {number} jdSeedUT @param {string} type @returns {number} */
68
+ const cardinalCrossingNearJdUT = (jdSeedUT, type) => {
69
+ const target = cardinalTargetDeg(type);
70
+ const RATE = 360 / CARDINAL_SI_YEAR_D;
71
+ let jd = jdSeedUT;
72
+ for (let i = 0; i < 20; i++) {
73
+ const d = ((((sunApparentLonDegAtJdUT(jd) - target) + 540) % 360 + 360) % 360) - 180;
74
+ jd -= d / RATE;
75
+ if (Math.abs(d) < 1e-10) break;
76
+ }
77
+ return jd - F.DT_ANCHOR.deltaTStartSeconds / 86400;
78
+ };
79
+ /** The TRUE-UT JD at which the APPARENT Sun's longitude of date equals
80
+ * the cardinal target in the given year — Newton on the crossing (the
81
+ * Sun's rate 360°/tropical year; a handful of steps from the tropical-year
82
+ * seed). Replaces the fitted cardinal model's instants (R1). Plan 06 R3
83
+ * item 2: the Newton root lives on the FINDER axis (the curve-only ΔT the
84
+ * eclipse finders certify), and the returned instant is that root minus the
85
+ * deltaTStart bridge — true UT = TT − (deltaTStart + curve), the same
86
+ * bridge the besselian and the registry instruments apply. Before this the
87
+ * published instants were 54.55 s (0.9 min) late. Against Horizons over
88
+ * ±3000 yr the remaining offset is the Sun's (plan 06 I2 measured).
89
+ * `year` is the MODEL year (the SI axis) — see cardinalCrossingNearJdUT.
90
+ * @param {number} year @param {string} type @returns {number} */
91
+ const cardinalCrossingJdUT = (year, type) => {
92
+ const target = cardinalTargetDeg(type);
93
+ // seed: Jan 1.5 of the year (J2000 = 2000 Jan 1.5) + the mean date of the
94
+ // March equinox (day 79.3) + the quarter-turns to the target
95
+ const seed = j2000JD + (year - 2000) * CARDINAL_SI_YEAR_D + 79.3 + (target / 360) * CARDINAL_SI_YEAR_D;
96
+ return cardinalCrossingNearJdUT(seed, type);
97
+ };
98
+
99
+ return { cardinalCrossingJdUT, cardinalCrossingNearJdUT, cardinalTargetDeg, sunAberrationArcsecAt, sunApparentLonDegAtJdUT };
100
+ }
101
+ /** @typedef {import('./published-periods.js').Ctx & ReturnType<typeof assembleCardinalInstants>} Ctx */
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The model assembly's shared context — the types the slices of `assembleModel` (../model.js) pass along.
3
+ *
4
+ * Each slice takes the context the earlier slices built (`import('./<previous>.js').Ctx`, an intersection
5
+ * that grows slice by slice) and returns the bindings the later ones read; the composer merges them
6
+ * into ONE object, so every closure sees the same instance of every memo and sampler. The inputs
7
+ * below are the composer's parameters; `late` carries the handful of bindings a slice reads at CALL
8
+ * time that a later slice defines — the composer fills each one as the owning slice returns, so a
9
+ * reader finds every forward dependency of the assembly in these seven lines and in the composer.
10
+ */
11
+
12
+ /**
13
+ * RESEARCH OVERRIDES for Earth's orbit laws (doc 109 §7): an alternative e(t), de/dt(t) and
14
+ * ϖ_of-date(t) flow through every consumer (the eclipse Sun, the Moon's E-factor, the cardinal
15
+ * points) exactly as the shipped laws do. `{}` = the shipped laws. Not a counterfactual in the §2d
16
+ * sense (no hash change) — callers must say when they used it; the generators refuse to --write
17
+ * under an override.
18
+ * @typedef {{ eccentricityAt?: (year: number) => number, eccentricityRateAt?: (year: number) => number, perihelionLongitudeDegAt?: (year: number) => number }} Laws
19
+ */
20
+
21
+ /**
22
+ * `giaEllipticityOfDate: false` builds the one-source history WITHOUT the J₂(t)/J₂₀ factor of date
23
+ * (the ice-driven GIA channel, which rides the climate formula's own post-MPT layer): the orbital
24
+ * FORCING alone. The T1 exporter derives the climate lines' obliquity rate on it, so the lines
25
+ * cannot depend on their own fit (v23.0; measured 3e-5 of the rate, 2–3 yr of period). Default true =
26
+ * the shipped physics.
27
+ * @typedef {{ giaEllipticityOfDate?: boolean }} Options
28
+ */
29
+
30
+ /**
31
+ * The forward bindings — what an early slice reads at call time from a later one. Typed by the
32
+ * members actually read, so the composer's assignment is checked against each owner's surface.
33
+ * @typedef {object} LateBindings
34
+ * @property {() => number} certifiedAxialPrecessionJ2000Years owner: year-day-lengths — read by deep-time-chain
35
+ * @property {{ epsAt(year: number): number, eAt(year: number): number, periOfDateDegAt(year: number): number, precessionOfDateFactorsAt(year: number): { solarTorque: number, ellipticity: number }, axialPrecessionYearsLunisolarJ2000: number }} oneSourceM owner: one-source-movement — read by deep-time-chain and earth-scalars
36
+ * @property {{ anomalisticYearSecondsAtYear(year: number): number }} yearLengthsM owner: one-source-movement — read by year-day-lengths
37
+ * @property {(year: number) => number} sunMeanLongitudeDegAt owner: sun-and-eclipses — read by lunar-theory (the arguments' Sun)
38
+ * @property {(year: number) => number} publishedAxialPrecessionYearsAtYear owner: published-periods — read by lunar-theory (the dynamical rate of date)
39
+ * @property {(year: number) => number} publishedSiderealYearSecondsAtYear owner: published-periods — read by year-day-lengths
40
+ * @property {(year: number) => number} sunAberrationArcsecAt owner: cardinal-instants — read by sun-and-eclipses (the besselian's apparent Sun)
41
+ */
42
+
43
+ /**
44
+ * The composer's inputs — the first slice's context.
45
+ * @typedef {object} ModelInputs
46
+ * @property {Readonly<Record<string, any>>} C the frozen constants context
47
+ * @property {Readonly<Record<string, any>>} F the fitted coefficients
48
+ * @property {Laws} laws
49
+ * @property {any} secularSeriesArtifact the governed N-body secular series (the API/Node path; null for the bare package)
50
+ * @property {Options} options
51
+ * @property {LateBindings} late
52
+ */
53
+
54
+ export {};
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The deep-time chain — ONE assembly (createDeepTimeChain destructured), the climate L1 layer and the realized pole rate over a window.
3
+ *
4
+ * One slice of `assembleModel` (../model.js): receives the context the earlier slices built, returns the bindings the later ones read.
5
+ */
6
+ import { evalClimateL1OrbitalPermil } from '../climate/l1-orbital.cjs';
7
+ import { createDeepTimeChain } from '../deltat/deep-time-chain.js';
8
+ import { MOON_DISTANCE_ARTIFACT } from '../deltat/moon-distance-artifact.cjs';
9
+ import { DEEP_MODES_ARTIFACT } from '../moon/deep-modes-artifact.cjs';
10
+
11
+ /** @param {import('./derived-constants.js').Ctx} ctx @returns the bindings the later slices read */
12
+ export function assembleDeepTimeChain(ctx) {
13
+ const { C, F, late, startmodelYear } = ctx;
14
+ // The GIA α channel (the lagged response to the L1 ice history, with the R2
15
+ // lattice pin and the exact-argument memo), the Layer-0 bundle, the cited
16
+ // Earth–Moon distance history (plan 12 option A), the ΔT cycle stack (all
17
+ // channels ON here), |s₃|, the LOD/ΔT core and the lunar month chain are
18
+ // assembled once in deltat/deep-time-chain.js from this context's constants
19
+ // and fitted coefficients (so a counterfactual context flows through them);
20
+ // the Node twin and the browser destructure the same module.
21
+ const chain = createDeepTimeChain({
22
+ constants: C, fitted: F, deepModes: DEEP_MODES_ARTIFACT, moonDistanceArtifact: MOON_DISTANCE_ARTIFACT,
23
+ ageAnchorYear: startmodelYear,
24
+ });
25
+ const { alphaGia, earthMoiFactorAtAge, EPOCH_PARAMS, recession, dtCycles, dtCycleLodCorrectionSum, s3ArcsecPerYr, deepLod, deepEcc, moonChain } = chain;
26
+ const CLIMATE_REGIME = F.CLIMATE_FORMULA_COEFFS.regimes['lr04-post-mpt'];
27
+ /** The climate formula's L1 (unlagged) — the orbital δ¹⁸O layer itself. @param {number} year @returns {number} */
28
+ const evalClimateL1 = (year) => evalClimateL1OrbitalPermil(year, {
29
+ l1Terms: CLIMATE_REGIME.L1,
30
+ yStdDenormalization: CLIMATE_REGIME.denormalization.y_std,
31
+ });
32
+ const moonDistanceMetresAtAge = recession.distanceMetresAtAge;
33
+ /** The published surfaces' km reading — NaN beyond the cited history's span (the API's
34
+ * validity span lies inside it; the deep charts stop where the input stops).
35
+ * @param {number} year @returns {number} */
36
+ const moonDistanceKmAtYearOrNaN = (year) => { const m = moonDistanceMetresAtAge(yearToTMa(year)); return m === null ? NaN : m / 1000; };
37
+
38
+ /** THE REALIZED POLE RATE OVER A WINDOW, ″/yr — the mean over [yearFrom, yearTo] of the rate the spin
39
+ * integration actually turns the pole at: the inertial secular rate of date × the solar-torque factor at
40
+ * e(t) × J₂(t)/J₂₀ × cos ε(t)/cos ε₀ (ds/dt = α (ŝ·n̂)(ŝ×n̂): the azimuthal rate about n̂ is α cos ε).
41
+ * The secular rate here is the CONSTANT's scaling (lunisolarTorqueRate…), not the published rate of
42
+ * date: the hybrid's own ε(t) carries the ONE cosine, so the cited mean obliquity's factor (plan 12 §8)
43
+ * does not enter twice — inside the ζ-series span the hybrid IS the model's obliquity of date.
44
+ * Measured (2026-10): the dominant obliquity line of the model's own ε(t) over the last 5 Myr sits at
45
+ * this mean minus |s₃| (40,938 fitted vs 40,936 predicted), NOT at the J2000 beat (41,098) — the pole
46
+ * turned faster in the past (spin +0.06 ″/yr over 5 Myr, lower mean obliquity +0.05, higher mean
47
+ * eccentricity +0.015); La2004's own series reads the same (40,917). The climate records' preferred
48
+ * "+0.12…+0.20 ″/yr on the obliquity lines" is this window mean (50.515 over the LR04 record).
49
+ * Reads the one-source history and p₀ through `late` (one-source-movement.js, year-day-lengths.js —
50
+ * evaluated at call time) and the deep-time LOD.
51
+ * `ellipticity: false` leaves the J₂(t)/J₂₀ factor out: that factor is the ice-driven GIA channel, which
52
+ * rides the climate formula's own post-MPT layer — the one piece that would make the climate LINES
53
+ * depend on their own fit (measured: its LR04-window mean moved 1 − 3e-5 → 1 across one refit,
54
+ * 1.4e-3 ″/yr, 1 yr of period). The line derivation (the T1 exporter) excludes it; the published
55
+ * realized period and the hybrid verdict's gate keep the full rate.
56
+ * @param {number} yearFrom @param {number} yearTo @param {number} [stepYears=500]
57
+ * @param {{ellipticity?: boolean}} [opts] @returns {number} */
58
+ const spinAxisInertialRateMeanArcsecPerYr = (yearFrom, yearTo, stepYears = 500, opts = {}) => {
59
+ const useEllipticity = opts.ellipticity !== false;
60
+ const lo = Math.min(yearFrom, yearTo), hi = Math.max(yearFrom, yearTo);
61
+ const cosEps0 = Math.cos(late.oneSourceM.epsAt(2000) * Math.PI / 180);
62
+ const kInertial = late.certifiedAxialPrecessionJ2000Years() / late.oneSourceM.axialPrecessionYearsLunisolarJ2000;
63
+ let sum = 0, n = 0;
64
+ for (let y = lo; y <= hi; y += stepYears) {
65
+ const r = deepLod.lunisolarTorqueRateArcsecPerYrAtAge(yearToTMa(y));
66
+ const psiDot = (r === null ? 1296000 / late.certifiedAxialPrecessionJ2000Years() : r) * kInertial;
67
+ const f = late.oneSourceM.precessionOfDateFactorsAt(y);
68
+ sum += psiDot * f.solarTorque * (useEllipticity ? f.ellipticity : 1) * Math.cos(late.oneSourceM.epsAt(y) * Math.PI / 180) / cosEps0;
69
+ n++;
70
+ }
71
+ return sum / n;
72
+ };
73
+
74
+ /** @param {number} year @returns {number} */
75
+ const yearToTMa = (year) => (2000 - year) / 1e6;
76
+
77
+ return { EPOCH_PARAMS, alphaGia, chain, deepEcc, deepLod, dtCycleLodCorrectionSum, dtCycles, earthMoiFactorAtAge, evalClimateL1, moonChain, moonDistanceKmAtYearOrNaN, moonDistanceMetresAtAge, s3ArcsecPerYr, spinAxisInertialRateMeanArcsecPerYr, yearToTMa };
78
+ }
79
+ /** @typedef {import('./derived-constants.js').Ctx & ReturnType<typeof assembleDeepTimeChain>} Ctx */