@essrt/physics 11.0.0 → 11.1.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.
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@essrt/physics",
3
- "version": "11.0.0",
3
+ "version": "11.1.0",
4
4
  "description": "ESSRT (Expanding Solar System Resonance Theory) physics core — pure, injectable-constants, no I/O, no globals, no DOM. The complete model incl. fitted coefficients; every published version immutably ships one recorded model identity.",
5
5
  "essrt": {
6
- "modelVersion": "v16.0",
6
+ "modelVersion": "v16.1",
7
7
  "_note": "The model identity this package version ships (IP-unified-architecture §10: package semver tracks the API axis; the model version + CONSTANTS_HASH/COEFFICIENTS_HASH in src/constants/ carry the scientific identity). The version-pinning gate enforces this pairing against public/input/model-version.json."
8
8
  },
9
9
  "type": "module",
@@ -36,7 +36,7 @@
36
36
  export const CONSTANTS_HASH = "726b10e23d8ace09";
37
37
 
38
38
  /** Model version label — single source: public/input/model-version.json (§10 two-axis scheme). */
39
- export const MODEL_VERSION = "v16.0";
39
+ export const MODEL_VERSION = "v16.1";
40
40
 
41
41
  /** Canonical preprint DOI — single source: public/input/model-version.json. */
42
42
  export const PREPRINT_DOI = "10.21203/rs.3.rs-8758810/v4";
@@ -373,15 +373,13 @@ function createDeepOrbitalHistory({
373
373
  return (Pi + u) * R2D;
374
374
  }
375
375
 
376
- /** Equinox-node longitudes only (J2000 ecliptic frame; projected and
377
- * general-precession forms) — the light read used for the node-rate
378
- * finite differences at store time. */
376
+ /** The three of-date longitudes whose node RATES the grid stores (the
377
+ * projected and general-precession equinox longitudes, the perihelion
378
+ * longitude of date) — read from a full sample at the probe state, so the
379
+ * rates are finite differences of exactly the stored quantities. */
379
380
  function eqLonsOnlyDeg(/** @type {number[]} */ s, /** @type {number} */ t) {
380
- const n = orbitNormal(t);
381
- const g = cross(s, n);
382
- const gn = Math.hypot(g[0], g[1], g[2]);
383
- const gu = [g[0] / gn, g[1] / gn, g[2] / gn];
384
- return { proj: Math.atan2(gu[1], gu[0]) * R2D, general: generalPrecessionLonDeg(n, gu) };
381
+ const smp = sampleAt(s, t);
382
+ return { proj: smp.equinoxLonJ2000Deg, general: smp.generalPrecessionLonDeg, peri: smp.periOfDateDeg };
385
383
  }
386
384
 
387
385
  /** One quantity bundle at time t (years from J2000) from spin axis s. */
@@ -449,6 +447,7 @@ function createDeepOrbitalHistory({
449
447
  // built on this rate (earth/year-lengths.cjs).
450
448
  generalPrecessionLonDeg: ((generalPrecessionLonDeg(n, gu) % 360) + 360) % 360,
451
449
  generalPrecessionLonRateDegPerYr: 0, // filled at store time (build's ±2.5-yr central difference)
450
+ periOfDateRateDegPerYr: 0, // filled at store time — the C1 input for periOfDateDeg (the apsidal rate of date)
452
451
  };
453
452
  }
454
453
 
@@ -488,6 +487,12 @@ function createDeepOrbitalHistory({
488
487
  // centuries with steps at the 1700/1800/1900/2000 cell edges
489
488
  // (measured; the levels were the real wobble at 100-yr resolution,
490
489
  // the staircase was this interpolation order).
490
+ // The perihelion longitude of date gets the same C1 treatment (2026-09,
491
+ // owner-found): linear interpolation of periOfDateDeg made the
492
+ // movement's year-over-year apsidal rate — the anomalistic year, the
493
+ // Prec. cell — a staircase of ±0.1 s across the 100-yr cells, reading
494
+ // 365.2596375 d at 2000.0 and 365.2596390 d at 2000.5, and the panel's
495
+ // apsidal beat 111,494 where the registry read 111,548.
491
496
  const storeWithRate = (/** @type {number} */ key, /** @type {number[]} */ sv, /** @type {number} */ tv) => {
492
497
  const smp = sampleAt(sv, tv);
493
498
  const hR = 2.5;
@@ -495,6 +500,7 @@ function createDeepOrbitalHistory({
495
500
  const lm = eqLonsOnlyDeg(rk4(sv, tv, -hR), tv - hR);
496
501
  smp.equinoxLonRateDegPerYr = (((lp.proj - lm.proj + 540) % 360) - 180) / (2 * hR);
497
502
  smp.generalPrecessionLonRateDegPerYr = (((lp.general - lm.general + 540) % 360) - 180) / (2 * hR);
503
+ smp.periOfDateRateDegPerYr = (((lp.peri - lm.peri + 540) % 360) - 180) / (2 * hR);
498
504
  grid.set(key, smp);
499
505
  };
500
506
  storeWithRate(0, s, 0);
@@ -522,7 +528,6 @@ function createDeepOrbitalHistory({
522
528
  if (!a) throw new Error(`deep-orbital-history: ${tYr} outside the built range`);
523
529
  const f = (tYr - k0) / stepYr;
524
530
  const lerp = (/** @type {number} */ x, /** @type {number} */ y) => x + (y - x) * f;
525
- const dAng = (/** @type {number} */ x, /** @type {number} */ y) => x + (((y - x + 540) % 360) - 180) * f;
526
531
  // C1 (cubic Hermite) on a wrapped angle with node rates (deg/yr) —
527
532
  // linear interpolation here made the realized equinox RATE
528
533
  // piecewise-constant per grid cell (the measured per-year
@@ -539,7 +544,8 @@ function createDeepOrbitalHistory({
539
544
  return {
540
545
  epsDeg: lerp(a.epsDeg, b.epsDeg),
541
546
  e: lerp(a.e, b.e),
542
- periOfDateDeg: ((dAng(a.periOfDateDeg, b.periOfDateDeg) % 360) + 360) % 360,
547
+ periOfDateDeg: hermiteAngle(a.periOfDateDeg, b.periOfDateDeg, a.periOfDateRateDegPerYr, b.periOfDateRateDegPerYr ?? a.periOfDateRateDegPerYr),
548
+ periOfDateRateDegPerYr: lerp(a.periOfDateRateDegPerYr, b.periOfDateRateDegPerYr ?? a.periOfDateRateDegPerYr),
543
549
  eSinPeri: lerp(a.eSinPeri, b.eSinPeri),
544
550
  eCosPeri: lerp(a.eCosPeri, b.eCosPeri),
545
551
  inclEclDeg: lerp(a.inclEclDeg, b.inclEclDeg),
@@ -0,0 +1,24 @@
1
+ /**
2
+ * GENERATED — do not edit. Regenerate:
3
+ * node tools/constants/generate.mjs --write
4
+ *
5
+ * Source: data/nbody-secular-series.json — the Sun planetary completion's
6
+ * embedded data (plan 06 I3): planetLamDotJ2000DegPerYr, the planets' J2000
7
+ * sidereal mean motions from the model's own ±10-Myr run (the completion's
8
+ * CARRIERS; the former carriers were the planet records' rounded of-date
9
+ * periods minus p₀ — Venus 4.1″/yr, Jupiter 1.7″/yr off the run's own
10
+ * motion); and eccVectors, the e·e^{iϖ} of Venus, Earth, Mars and Jupiter on
11
+ * a 1-kyr grid over ±50 kyr (ecliptic J2000) — the D'Alembert long-period
12
+ * rows' amplitude and phase of date. Earth's carrier stays the framework
13
+ * sidereal year (the D6 ratio-only doctrine for the run's absolute Earth
14
+ * rate). Two gates guard the chain: check:artifacts pins artifact ↔ engine;
15
+ * generate.mjs check mode pins this embed ↔ artifact. CJS for the .cjs
16
+ * completion consumer.
17
+ */
18
+ 'use strict';
19
+
20
+ const SUN_COMPLETION_ARTIFACT_HASH = "5ad17b275a003f6e";
21
+
22
+ const SUN_COMPLETION_ARTIFACT = Object.freeze({"planetLamDotJ2000DegPerYr":{"mercury":1494.725744748,"venus":585.177909613,"mars":191.402970848,"jupiter":30.348892629,"saturn":12.221520382,"uranus":4.285090582,"neptune":2.18458998},"eccVectors":{"t0Yr":-50000,"stepYr":1000,"bodies":{"venus":{"zQ":[0.0279902,0.0270462,0.0260531,0.0250136,0.0239295,0.0228034,0.0216389,0.0204406,0.0192142,0.0179653,0.0166999,0.0154225,0.0141391,0.0128553,0.0115784,0.0103157,0.009074,0.0078599,0.006678,0.0055331,0.0044289,0.00337,0.0023604,0.0014037,0.0005018,-0.0003439,-0.0011327,-0.0018642,-0.0025389,-0.0031565,-0.0037171,-0.0042205,-0.0046666,-0.0050566,-0.0053911,-0.0056726,-0.0059018,-0.0060797,-0.0062062,-0.0062821,-0.0063089,-0.0062889,-0.0062255,-0.0061207,-0.0059782,-0.0057996,-0.0055879,-0.0053462,-0.0050788,-0.0047909,-0.0044872,-0.0041718,-0.0038483,-0.0035199,-0.0031899,-0.0028619,-0.0025389,-0.0022246,-0.0019216,-0.0016326,-0.0013585,-0.0011005,-0.0008588,-0.0006348,-0.0004296,-0.0002445,-0.0000808,0.000062,0.0001836,0.0002854,0.0003676,0.00043,0.000472,0.0004936,0.0004954,0.000479,0.0004465,0.0003999,0.0003413,0.0002721,0.000194,0.000109,0.00002,-0.0000692,-0.0001549,-0.0002339,-0.0003033,-0.0003614,-0.000406,-0.0004346,-0.0004451,-0.0004351,-0.0004024,-0.0003454,-0.0002637,-0.0001573,-0.000027,0.0001276,0.0003064,0.0005097,0.0007375],"zP":[0.018044,0.0190048,0.0199026,0.0207345,0.0214985,0.0221921,0.0228133,0.023361,0.0238349,0.0242364,0.0245664,0.0248268,0.0250179,0.0251396,0.0251924,0.0251771,0.0250952,0.0249487,0.0247395,0.024469,0.0241382,0.0237481,0.0233005,0.022799,0.0222471,0.0216492,0.0210095,0.0203323,0.0196229,0.0188852,0.0181246,0.0173466,0.0165573,0.0157631,0.0149696,0.0141817,0.0134033,0.0126374,0.0118877,0.0111579,0.0104519,0.0097728,0.0091226,0.0085024,0.0079131,0.0073554,0.0068302,0.0063401,0.005886,0.0054692,0.0050896,0.0047468,0.0044407,0.004171,0.0039381,0.0037416,0.0035814,0.0034562,0.0033649,0.0033046,0.0032728,0.0032669,0.0032846,0.0033239,0.0033824,0.0034567,0.0035432,0.0036382,0.0037379,0.0038402,0.0039424,0.0040437,0.0041416,0.0042336,0.0043171,0.0043902,0.0044512,0.0044998,0.0045358,0.0045583,0.0045673,0.0045609,0.0045385,0.0044992,0.0044432,0.0043714,0.0042846,0.0041835,0.0040683,0.0039395,0.0037975,0.0036443,0.0034811,0.003311,0.0031368,0.0029615,0.0027871,0.002616,0.0024505,0.0022939,0.0021498]},"earth":{"zQ":[0.013227267,0.013012506,0.012834994,0.012696287,0.012597963,0.012540754,0.01252666,0.012549935,0.012604882,0.012690231,0.012800154,0.012934505,0.013090442,0.013266166,0.013451544,0.013642315,0.013829021,0.014004751,0.01416527,0.014306209,0.014427996,0.014517185,0.014571021,0.014583484,0.01454318,0.014451082,0.014306069,0.014099616,0.013836713,0.013514405,0.013124137,0.012669856,0.012147851,0.011555754,0.010903934,0.010193697,0.009426983,0.0086143,0.007749231,0.006839273,0.005893806,0.004915481,0.003921086,0.002917354,0.001909786,0.000909778,-0.000076816,-0.001048344,-0.001988304,-0.002888344,-0.003740032,-0.004530056,-0.005260301,-0.005923768,-0.006513461,-0.007030299,-0.00746818,-0.007819964,-0.008084188,-0.008260875,-0.00834821,-0.008350985,-0.008275204,-0.008118387,-0.007884356,-0.00757642,-0.007194194,-0.006743231,-0.006236619,-0.0056763,-0.005070356,-0.004430986,-0.00375356,-0.003046685,-0.002319076,-0.00157522,-0.000827409,-0.000082833,0.000652857,0.001372028,0.002074185,0.002755866,0.003406986,0.00402808,0.00460898,0.005142789,0.005637646,0.006085386,0.006487544,0.006852803,0.00717117,0.007444843,0.007677336,0.007863353,0.008009495,0.008120645,0.008198929,0.008249784,0.00827192,0.008262513,0.008227021],"zP":[0.00629199,0.006157176,0.006021018,0.005888044,0.005762291,0.005648055,0.005553525,0.00548229,0.005439151,0.005424431,0.005438065,0.005482258,0.005560686,0.005676894,0.005837022,0.006042534,0.006293455,0.006590047,0.006927276,0.007306088,0.007729922,0.008196139,0.008708393,0.009259394,0.009843797,0.010459935,0.01109414,0.011746079,0.012411664,0.013078877,0.013747935,0.014412012,0.015051841,0.015665551,0.016243589,0.016770777,0.017250892,0.017677425,0.018040396,0.018339722,0.018561665,0.018702501,0.018762478,0.018735718,0.018628747,0.018440526,0.018169036,0.017819371,0.017387029,0.01687065,0.016283928,0.015630793,0.014913266,0.014144751,0.013327617,0.012464356,0.011566053,0.010638047,0.009687504,0.008727497,0.007768976,0.006816931,0.005878676,0.004964821,0.004074941,0.003218725,0.00240902,0.001647618,0.000944991,0.000305919,-0.000270521,-0.000782068,-0.00122626,-0.001604285,-0.001905386,-0.00213232,-0.002287543,-0.002367048,-0.002382224,-0.002334107,-0.002223921,-0.002058154,-0.001834453,-0.001554207,-0.001229972,-0.000862036,-0.000458958,-0.000030798,0.000426187,0.000903095,0.001397238,0.00191096,0.002431882,0.002957636,0.003487072,0.004008594,0.004525642,0.005041098,0.005550956,0.006055939,0.006554044]},"mars":{"zQ":[0.0433563,0.03467,0.0258658,0.0170192,0.0082073,-0.0004939,-0.0090076,-0.0172605,-0.0251854,-0.0327154,-0.0397897,-0.0463513,-0.0523471,-0.0577309,-0.0624622,-0.0665068,-0.0698416,-0.0724452,-0.0743037,-0.0754094,-0.0757598,-0.0753669,-0.0742434,-0.07241,-0.0698931,-0.066724,-0.0629392,-0.058577,-0.053681,-0.0482992,-0.0424818,-0.0362828,-0.0297564,-0.0229575,-0.0159422,-0.0087638,-0.0014737,0.0058727,0.0132213,0.0205196,0.0277185,0.0347724,0.0416363,0.0482678,0.0546244,0.0606678,0.0663629,0.071674,0.0765709,0.0810267,0.085017,0.0885174,0.0915066,0.0939667,0.0958802,0.0972347,0.0980194,0.0982305,0.0978673,0.0969283,0.0954136,0.0933238,0.0906673,0.0874561,0.0837052,0.0794336,0.0746638,0.0694224,0.0637356,0.0576332,0.0511496,0.0443223,0.0371937,0.0298083,0.0222154,0.0144652,0.0066091,-0.0013021,-0.0092175,-0.017081,-0.0248374,-0.0324313,-0.0398113,-0.046924,-0.0537171,-0.060141,-0.066145,-0.0716831,-0.0767087,-0.0811772,-0.0850485,-0.0882866,-0.0908567,-0.0927255,-0.0938676,-0.0942613,-0.0938902,-0.0927442,-0.0908235,-0.0881389,-0.0847045],"zP":[0.0897466,0.0918932,0.09322,0.093721,0.0934006,0.0922683,0.090343,0.0876532,0.0842298,0.0801091,0.0753335,0.0699511,0.064016,0.0575862,0.0507249,0.0435004,0.0359792,0.0282273,0.0203139,0.012307,0.0042791,-0.0036983,-0.0115608,-0.0192412,-0.026677,-0.0338101,-0.0405856,-0.0469554,-0.0528697,-0.0582895,-0.0631778,-0.0675048,-0.0712468,-0.0743843,-0.0769046,-0.0787988,-0.0800608,-0.0806874,-0.0806826,-0.0800561,-0.0788225,-0.0769976,-0.0745995,-0.0716471,-0.0681631,-0.0641733,-0.0597044,-0.0547853,-0.0494511,-0.0437376,-0.0376793,-0.031313,-0.0246763,-0.0178092,-0.0107514,-0.0035454,0.0037629,0.0111266,0.0185008,0.0258424,0.0331059,0.0402454,0.0472133,0.0539669,0.0604642,0.0666637,0.0725249,0.0780099,0.0830837,0.0877107,0.0918571,0.0954933,0.0985927,0.1011309,0.1030866,0.104441,0.1051785,0.1052838,0.1047436,0.1035491,0.1016984,0.0991961,0.0960507,0.0922751,0.0878862,0.0829058,0.0773604,0.0712844,0.0647174,0.0577059,0.0503057,0.0425739,0.0345707,0.0263598,0.0180075,0.0095798,0.0011454,-0.0072255,-0.0154599,-0.0234891,-0.0312472]},"jupiter":{"zQ":[0.0409753,0.0433687,0.0456423,0.0477984,0.0498037,0.0516436,0.0532903,0.0546913,0.0558342,0.0567036,0.0573161,0.057663,0.0577405,0.0575449,0.0570533,0.056287,0.0552536,0.0540004,0.0525615,0.050946,0.0491766,0.0472552,0.0452242,0.0431052,0.0409485,0.0388261,0.0367588,0.0347878,0.0329308,0.0312513,0.0297929,0.0285898,0.0276805,0.027063,0.026749,0.0267075,0.0269516,0.027497,0.0283258,0.0294268,0.030747,0.0322622,0.0338998,0.0356259,0.0374175,0.0392265,0.0410199,0.0427079,0.0442559,0.0456258,0.0468048,0.0477873,0.0485481,0.0490863,0.0493524,0.04932,0.0489817,0.0483498,0.0474508,0.0462864,0.0448821,0.0432313,0.0413402,0.0392239,0.036927,0.0345012,0.0319648,0.0293507,0.026667,0.0239268,0.0211542,0.0183921,0.0157132,0.0131488,0.0107451,0.0085068,0.0064494,0.0046131,0.0030061,0.00168,0.0006473,-0.0000718,-0.0005082,-0.0006718,-0.0005465,-0.0001609,0.0004972,0.0013985,0.0025113,0.0037665,0.0050863,0.0064365,0.007773,0.0090802,0.010283,0.0113433,0.0122282,0.0128782,0.0132824,0.013423,0.0133097],"zP":[-0.0343967,-0.0331679,-0.0316586,-0.0298935,-0.027898,-0.025726,-0.0233818,-0.0208861,-0.0182549,-0.0154933,-0.0126481,-0.0097471,-0.0068584,-0.004012,-0.0012369,0.0014519,0.0040408,0.0064707,0.0087255,0.0107573,0.0125406,0.0140643,0.0153359,0.0163587,0.017093,0.0175361,0.0176648,0.0174823,0.017015,0.0163061,0.0154165,0.0143655,0.0131777,0.0118658,0.0104958,0.0091211,0.007783,0.0065585,0.0054776,0.0045665,0.0038381,0.0033371,0.0031166,0.0032035,0.0036307,0.0043725,0.0054131,0.0067327,0.0082968,0.0101046,0.0121388,0.0143914,0.0168005,0.0193307,0.0219615,0.0246359,0.02735,0.0300702,0.0327765,0.0354121,0.0379233,0.0402887,0.0424719,0.0444815,0.0462815,0.0478736,0.0492324,0.0503175,0.0511262,0.0516474,0.0519031,0.0518759,0.0515854,0.0510289,0.0501942,0.0491163,0.0478163,0.0463574,0.0447717,0.0430857,0.041321,0.0394987,0.03767,0.0358646,0.0341508,0.0325953,0.0312215,0.0300563,0.029115,0.028451,0.0280902,0.028059,0.0283637,0.0289847,0.0298923,0.0310308,0.0323937,0.0339708,0.0357433,0.0376723,0.0397061]}}},"meta":{"dumpSha256":"686d6af51a689f7bd64ac1e2d8b26c243a4beccdacd3167adfeeae078e8b990f","source":"data/nbody-secular-series.json verdict.planetLamDot (J2000 sidereal mean motions) + bodies.<X>.zQ/zP at the 1-kyr nodes (ecliptic J2000, verbatim)"}});
23
+
24
+ module.exports = { SUN_COMPLETION_ARTIFACT, SUN_COMPLETION_ARTIFACT_HASH };
@@ -107,6 +107,8 @@
107
107
 
108
108
  'use strict';
109
109
 
110
+ const { SUN_COMPLETION_ARTIFACT } = require('./sun-completion-artifact.cjs');
111
+
110
112
  /** J2000 mean-longitude phase anchors (deg), body order Mercury, Venus,
111
113
  * Earth (EMB), Mars, Jupiter, Saturn — declared epoch constants
112
114
  * (header (ii)); the RATES are injected (framework-derived). */
@@ -130,25 +132,25 @@ const ARG_D0 = 297.8501921;
130
132
  * detrended 0.033 min). Individual coefficients redistribute between the
131
133
  * near-degenerate ±M sideband families; only the composed function ships.
132
134
  *
133
- * PLAN 06 I2 — the LONG-PERIOD rows (the last two): the Earth–Mars–
134
- * Jupiter long inequality 4λ_E − 8λ_Ma + 3λ_J (carrier period 1801 yr;
135
- * the classical ~1783-yr term of the solar theory) and the Venus–Earth
136
- * term 8λ_V − 13λ_E (238 yr), DERIVED on the model's own Wisdom–Holman
137
- * engine (tools/explore/nbody-wh.mjs, the chain artifact's integrator) on
138
- * the campaign's ONE Horizons J2000 seed, Sun + eight planets, DE440
139
- * masses, 1PN, order 2, dt 2 d, −5100..+1100 yr: the EMB's osculating
140
- * mean longitude Ω+ω+M in yearly means, LSQ on [1, T, T²] + cos/sin of
141
- * the arguments on THESE carriers (tools/explore/i2-long-inequality.mjs).
142
- * Measured: 6.27″ / 1.84″; step-converged (dt 1 d: 6.272 / 1.869); the
143
- * integration reproduces DE441's Earth longitude to 0.68″ sd over 6000
144
- * yr with 0.03″ left at the 1783-yr argument. Neither could come from the
145
- * 200-yr D2 window (the term's in-window ramp went to the projected-out
146
- * secular basis; the 240-yr term folded into it). WHY they were missing:
147
- * the certified Sun integrates a smooth tropical year for its mean
148
- * longitude; against Horizons its residual carried exactly this 6″ ripple
149
- * (plan 06 I1 analysis) — with the same phase in the sidereal residual, a
150
- * perturbation of Earth's mean motion, not a frame effect. Sub-0.2″
151
- * candidates left out (2J−5S 0.17″, 5V−8E 0.17″: window-dependent phase).
135
+ * PLAN 06 I2 → I3 — the LONG-PERIOD rows live in LONG_PERIOD_TERMS below
136
+ * (D'Alembert form on the e-vectors of date, derived over ±20 kyr; I3). The
137
+ * I2 record: the Earth–Mars–Jupiter long inequality 4λ_E − 8λ_Ma + 3λ_J
138
+ * (the classical ~1783-yr term) and the Venus–Earth term 8λ_V − 13λ_E
139
+ * (≈239 yr) were first DERIVED as constant rows on the model's own
140
+ * Wisdom–Holman engine over −5100..+1100 yr (6.27″ / 1.84″;
141
+ * tools/explore/i2-long-inequality.mjs). Neither could come from the 200-yr
142
+ * D2 window (the term's in-window ramp went to the projected-out secular
143
+ * basis; the 240-yr term folded into it). WHY they were missing: the
144
+ * certified Sun integrates a smooth tropical year for its mean longitude;
145
+ * against Horizons its residual carried exactly this 6″ ripple (plan 06 I1
146
+ * analysis) — with the same phase in the sidereal residual, a perturbation
147
+ * of Earth's mean motion, not a frame effect. Sub-0.2″ candidates left out
148
+ * (2J−5S 0.17″, 5V−8E 0.17″: window-dependent phase). The CARRIERS moved
149
+ * with I3 from the planet records' rounded of-date periods minus p₀ to the
150
+ * model's own banked J2000 sidereal mean motions (computeCarrierRatesDegPerCy;
151
+ * the 70 short-period literals are KEPT — the two carrier sets share the
152
+ * J2000 anchors and part by ≤ 12″/yr·|k|, i.e. ≤ 0.3°·|k| at the 200-yr
153
+ * window's edges, the same class as the I2 of-date→sidereal move).
152
154
  * @type {Array<[number[], number[], number, number]>}
153
155
  */
154
156
  const TERMS = [
@@ -222,28 +224,128 @@ const TERMS = [
222
224
  [[0, 0, 1, -1, 0, 0], [0, 0, 1, 0, 0, 0], 0.0188, 0.0523],
223
225
  [[0, 2, -2, 0, 0, 0], [0, 0, 1, 0, 0, 0], -0.0421, -0.0340],
224
226
  [[0, 0, 1, -1, 0, 0], [0, 0, -1, 0, 0, 0], -0.0353, -0.0379],
225
- // plan 06 I2 — the long-period rows (see the doc comment above)
226
- [[0, 0, 4, -8, 3, 0], [0, 0, 0, 0, 0, 0], 6.2314, -0.7168],
227
- [[0, 8, -13, 0, 0, 0], [0, 0, 0, 0, 0, 0], 1.8389, 0.1419],
227
+ // plan 06 I3 — the Venus–Earth term 8λ_V − 13λ_E (≈239 yr on the banked
228
+ // carriers): a CONSTANT row, derived on the model's own run over ±3100 yr
229
+ // (i3-long-period-dalembert.mjs `2 20000 3100 4`; the I2 row read 1.84/0.14″
230
+ // on the record carriers over −5100..+1100). The term is formally FIFTH order
231
+ // (Σk = −5) and resonant (divisor 1.5°/yr: e⁵/ν² reaches the arcsecond), so it
232
+ // is a CLUSTER of lines (ϖ/Ω multipliers summing to +5) beating on ~20 kyr —
233
+ // no single-ϖ D'Alembert form holds (the {V,E} form shifted the Sun +0.9″ at
234
+ // J2000 against Horizons' modern window; this row 0.74 → 0.83″ mean with the
235
+ // scatter 0.94 → 0.78″), and the row is a LOCAL description of the
236
+ // Horizons-certified era (≈1″ beyond it).
237
+ [[0, 8, -13, 0, 0, 0], [0, 0, 0, 0, 0, 0], 1.4825, 0.9436],
238
+ ];
239
+
240
+ /**
241
+ * PLAN 06 I3 — the LONG INEQUALITY in D'ALEMBERT form (superseding the
242
+ * constant-amplitude row of I2, 6.23/−0.72″): the Earth–Mars–Jupiter long
243
+ * inequality 4λ_E − 8λ_Ma + 3λ_J (≈1783 yr) as a sum over bodies X of
244
+ * e_X(t)·[a_X·cos(θ + ϖ_X(t)) + b_X·sin(θ + ϖ_X(t))]
245
+ * with e_X, ϖ_X the e-vectors OF DATE (the embedded artifact, ecliptic J2000;
246
+ * D'Alembert: Σk_λ + Σj_ϖ = 0 and the argument has Σk = −1, so +ϖ_X).
247
+ * WHY (measured 2026-10 on the model's inertial Sun against DE441 in the fixed
248
+ * J2000 frame, tools/explore/sun-inertial-vs-de441.cjs): the constant rows left
249
+ * 0.08″ at the 1783-yr period inside ±3000 yr and 3.7″ outside on both sides —
250
+ * the inequality is first order in the eccentricities and its composed
251
+ * amplitude/phase ride the e-vectors of date (the model's own N-body shows the
252
+ * line growing 3.2″ → 9.0″ from −18 to +14 kyr). DERIVED on the model's own
253
+ * Wisdom–Holman run over ±20,000 yr (tools/explore/i3-long-period-dalembert.mjs
254
+ * `2 20000 9100 4`: yearly means of the EMB's osculating mean longitude, a
255
+ * degree-4 secular detrend — diagnostic — plus these columns on the SAME
256
+ * embedded e-vectors; dt 2 d, step-converged against dt 1 d): the 1783-yr band
257
+ * left in the residual 0.05″ inside ±9100 and 0.07/0.05″ outside, the composed
258
+ * J2000 amplitude 6.88″ on ±20 kyr vs 6.89″ on ±9100 (window-independent; the
259
+ * constant row read 6.12 vs 6.89), and the ±9100-fitted rows evaluated over
260
+ * ±20 kyr leave 0.28/0.53″ (rms Δ 0.57″). Against Horizons' modern window the
261
+ * row moves the Sun by −0.36″ at J2000 with the scatter 0.94 → 0.89″ (the I2
262
+ * constant row was derived off-centre, −5100..+1100). The Venus–Earth term is
263
+ * NOT of this form — see its constant row in TERMS. The individual a_X, b_X
264
+ * are NOT physically separable (the three perihelia
265
+ * rotate only 33–80° per 9 kyr, so the columns are near-collinear — the first
266
+ * cut, with the WRONG sign θ − ϖ_X, "fitted" ±9 kyr with coefficients of
267
+ * thousands of ″/e and failed the window test); only the composed function
268
+ * ships, as for the ±M sideband pairs. Beyond ±50 kyr the e-vectors are held at
269
+ * the grid's ends (bounded, the former constant-row class).
270
+ * Extraction-native sign (N-body − smooth), negated in the evaluator.
271
+ * @type {Array<[number[], number, number, number]>} [l-multipliers, bodyIndex (0 Me … 5 S), a (″/e), b (″/e)]
272
+ */
273
+ const LONG_PERIOD_TERMS = [
274
+ [[0, 0, 4, -8, 3, 0], 2, -785.9521, 591.0878], // 4E−8Ma+3J · earth
275
+ [[0, 0, 4, -8, 3, 0], 3, -80.4721, 77.5236], // 4E−8Ma+3J · mars
276
+ [[0, 0, 4, -8, 3, 0], 4, 159.5521, -303.8727], // 4E−8Ma+3J · jupiter
228
277
  ];
278
+ /** body index → the embedded e-vector series' key */
279
+ const ECC_BODY_KEY = [null, 'venus', 'earth', 'mars', 'jupiter', null];
229
280
 
230
281
  const D2R = Math.PI / 180;
231
282
 
283
+ /**
284
+ * The e-vector (e·cos ϖ, e·sin ϖ; ecliptic J2000) of a body at T Julian
285
+ * centuries TT from J2000, from the embedded 1-kyr grid (linear between nodes,
286
+ * held at the grid's ends). The ONE source for every runtime — an
287
+ * artifact-less createModel() and the browser before its series load compute
288
+ * the identical rows.
289
+ * @param {number} bodyIndex 0 Me, 1 V, 2 E, 3 Ma, 4 J, 5 S (only 1–4 are embedded)
290
+ * @param {number} T
291
+ * @returns {[number, number]}
292
+ */
293
+ function eccVectorOfDateEmbedded(bodyIndex, T) {
294
+ const key = ECC_BODY_KEY[bodyIndex];
295
+ if (!key) throw new RangeError(`sun-planetary-completion: no embedded e-vector series for body index ${bodyIndex}`);
296
+ const grid = SUN_COMPLETION_ARTIFACT.eccVectors;
297
+ const b = /** @type {Record<string, {zQ: number[], zP: number[]}>} */ (grid.bodies)[key];
298
+ const x = Math.min(Math.max((T * 100 - grid.t0Yr) / grid.stepYr, 0), b.zQ.length - 1);
299
+ const i = Math.min(Math.floor(x), b.zQ.length - 2), f = x - i;
300
+ return [b.zQ[i] + (b.zQ[i + 1] - b.zQ[i]) * f, b.zP[i] + (b.zP[i + 1] - b.zP[i]) * f];
301
+ }
302
+
303
+ /**
304
+ * The completion's CARRIER rates (deg per Julian century TT) — ONE home for the
305
+ * model wiring and the matched-pair gate. Planets: the model's own banked J2000
306
+ * sidereal mean motions (the embedded artifact; the former carriers were the
307
+ * planet records' rounded of-date periods minus p₀ — Venus 4.1″/yr and Jupiter
308
+ * 1.7″/yr off the run's own motion, 83° of the Venus–Earth argument at ±9000 yr).
309
+ * Earth: the framework sidereal year (the D6 ratio-only doctrine for the run's
310
+ * absolute Earth rate). Moon elongation: sidereal month vs sidereal year.
311
+ * @param {{ meanSiderealYearDays: number, moonSiderealMonthDays: number }} c
312
+ * @returns {{ planets: number[], moonElongation: number }}
313
+ */
314
+ function computeCarrierRatesDegPerCy({ meanSiderealYearDays, moonSiderealMonthDays }) {
315
+ const L = SUN_COMPLETION_ARTIFACT.planetLamDotJ2000DegPerYr;
316
+ const degPerCyOf = (/** @type {number} */ cyclesPerDay) => 360 * 36525 * cyclesPerDay;
317
+ return {
318
+ planets: [L.mercury * 100, L.venus * 100, degPerCyOf(1 / meanSiderealYearDays), L.mars * 100, L.jupiter * 100, L.saturn * 100],
319
+ moonElongation: degPerCyOf(1 / moonSiderealMonthDays - 1 / meanSiderealYearDays),
320
+ };
321
+ }
322
+
232
323
  /**
233
324
  * @param {{ embWobbleArcsec: number,
234
- * carrierRatesDegPerCy: { planets: number[], moonElongation: number } }} opts
325
+ * carrierRatesDegPerCy: { planets: number[], moonElongation: number },
326
+ * eccVectorOfDate?: (bodyIndex: number, T: number) => [number, number],
327
+ * moonElongationDegAtT?: (T: number) => number }} opts
235
328
  * - embWobbleArcsec: the DERIVED Earth-around-EMB wobble amplitude
236
329
  * a_M·μ/AU in arcsec (μ = 1/(1+M_E/M_M));
237
- * - carrierRatesDegPerCy.planets: the six FRAMEWORK mean-longitude
238
- * rates (deg/Julian-century TT), body order Me,V,E,Ma,J,S — one
239
- * revolution per the model's own tropical period records;
330
+ * - carrierRatesDegPerCy.planets: the six mean-longitude rates (deg/
331
+ * Julian-century TT), body order Me,V,E,Ma,J,S — computeCarrierRatesDegPerCy
332
+ * (the model's own banked J2000 sidereal mean motions; Earth the framework
333
+ * sidereal year);
240
334
  * - carrierRatesDegPerCy.moonElongation: the framework Moon
241
- * mean-elongation rate (deg/cy TT) for the EMB-wobble carrier.
242
- * All computed from live constants by the model wiring so the
243
- * carrier↔table matched pair tracks the constants.
335
+ * mean-elongation rate (deg/cy TT) — the EMB-wobble carrier's rate when
336
+ * moonElongationDegAtT is absent;
337
+ * - eccVectorOfDate: the e-vectors of date for the D'Alembert rows (default:
338
+ * the embedded grid — the ONE source; an override is for instruments);
339
+ * - moonElongationDegAtT: the Moon's mean elongation OF DATE (deg) at T —
340
+ * the framework's own argument (ṅ included). The constant-rate carrier
341
+ * D₀ + D₁·T ran ~29° off it at ±9000 yr: the lunar equation (6.44″) read
342
+ * as the largest short-period line left against DE441 at −9000 (2.8″ at
343
+ * 29.53 d; the −9000 bin's scatter 4.13 → 3.62″ on the argument of date).
344
+ * Injected by the model wiring so the carrier↔table matched pair tracks the
345
+ * constants and the embedded artifact.
244
346
  * @returns {{ sunPlanetaryCompletionDeg: (T: number) => number }}
245
347
  */
246
- function createSunPlanetaryCompletion({ embWobbleArcsec, carrierRatesDegPerCy }) {
348
+ function createSunPlanetaryCompletion({ embWobbleArcsec, carrierRatesDegPerCy, eccVectorOfDate = eccVectorOfDateEmbedded, moonElongationDegAtT = undefined }) {
247
349
  if (!Number.isFinite(embWobbleArcsec)) {
248
350
  throw new Error('createSunPlanetaryCompletion: embWobbleArcsec must be a finite number (derived a_M·μ/AU in arcsec)');
249
351
  }
@@ -270,7 +372,15 @@ function createSunPlanetaryCompletion({ embWobbleArcsec, carrierRatesDegPerCy })
270
372
  for (let i = 0; i < 6; i++) th += kl[i] * l[i] + kM[i] * M[i];
271
373
  table += cA * Math.cos(th) + sA * Math.sin(th);
272
374
  }
273
- const D = (ARG_D0 + D1 * T) * D2R;
375
+ // the long-period rows — amplitude and phase on the e-vectors of date
376
+ for (const [kl, X, a, b] of LONG_PERIOD_TERMS) {
377
+ let th = 0;
378
+ for (let i = 0; i < 6; i++) th += kl[i] * l[i];
379
+ const [q, p] = eccVectorOfDate(X, T);
380
+ const e = Math.hypot(q, p), w = Math.atan2(p, q);
381
+ table += e * (a * Math.cos(th + w) + b * Math.sin(th + w));
382
+ }
383
+ const D = moonElongationDegAtT ? moonElongationDegAtT(T) * D2R : (ARG_D0 + D1 * T) * D2R;
274
384
  const arcsec = -table - embWobbleArcsec * Math.sin(D);
275
385
  return arcsec / 3600;
276
386
  }
@@ -284,19 +394,21 @@ function createSunPlanetaryCompletion({ embWobbleArcsec, carrierRatesDegPerCy })
284
394
  const PAIRED_SUN_HARMONICS_SHA256 = 'cbc189cea1c20292'; // eccentricity unification: Step-0 refit → N2/N3 re-derived (fidelity 0.616″, 70 terms)
285
395
 
286
396
  /** sha256/16 of JSON.stringify([...planets, moonElongation]) — the seven
287
- * full-precision carrier rates (deg/cy TT) the TERMS table pairs with:
288
- * the SIDEREAL carriers of plan 06 I2 (record rate − the model's J2000
289
- * precession; Earth the framework sidereal year; the N3 literals kept,
290
- * the two long-period rows derived on these rates). The model wiring
291
- * recomputes the rates live from the planet records, so a planet-period /
292
- * year / month input change moves the carriers automatically while the
293
- * table stays frozen — a silent few-arcsec stale below the api gate's
294
- * ≤12″ backstop. test:model recomputes this fingerprint from live
295
- * constants (identical arithmetic to model.js) and fails on mismatch:
296
- * re-run the extraction chain (tools/explore/n2-sun-framework-carriers.mjs
297
- * → i2-sidereal-carrier-table.mjs for the short-period rows,
298
- * i2-long-inequality.mjs for the long-period rows), re-embed TERMS, and
299
- * update this value. */
300
- const PAIRED_CARRIER_RATES_SHA256 = '2d066e92bae955e4';
397
+ * full-precision carrier rates (deg/cy TT) the tables pair with: since plan
398
+ * 06 I3 the model's own banked J2000 sidereal mean motions for the planets
399
+ * (the embedded sun-completion artifact), Earth the framework sidereal year,
400
+ * the Moon elongation from the sidereal month/year identity
401
+ * (computeCarrierRatesDegPerCy; the N3 short-period literals kept, the
402
+ * LONG_PERIOD_TERMS derived on these rates). The model wiring recomputes
403
+ * the rates live, so a series re-bank, a year or a month input change moves
404
+ * the carriers automatically while the tables stay frozen — a silent
405
+ * few-arcsec stale below the api gate's ≤12″ backstop. test:model recomputes
406
+ * this fingerprint from the live artifact + constants (identical arithmetic)
407
+ * and fails on mismatch: re-run the extraction chain
408
+ * (tools/explore/n2-sun-framework-carriers.mjs → i2-sidereal-carrier-table.mjs
409
+ * for the short-period rows, i3-long-period-dalembert.mjs for the long-period
410
+ * rows), re-embed the tables, and update this value. History: 2d066e92bae955e4
411
+ * was the I2 record-based carrier set. */
412
+ const PAIRED_CARRIER_RATES_SHA256 = '8e11456fcf8db81c';
301
413
 
302
- module.exports = { createSunPlanetaryCompletion, PAIRED_SUN_HARMONICS_SHA256, PAIRED_CARRIER_RATES_SHA256 };
414
+ module.exports = { createSunPlanetaryCompletion, computeCarrierRatesDegPerCy, eccVectorOfDateEmbedded, PAIRED_SUN_HARMONICS_SHA256, PAIRED_CARRIER_RATES_SHA256 };
package/src/model.js CHANGED
@@ -36,7 +36,7 @@ import { createMoonMonthChain } from './moon/month-chain.cjs';
36
36
  import { createChainCycleIntegrator } from './chain-cycles/index.cjs';
37
37
  import { createMoonArguments, jdToDecimalYear } from './moon/arguments.cjs';
38
38
  import { createMoonSeries } from './moon/series.cjs';
39
- import { createSunPlanetaryCompletion } from './eclipse/sun-planetary-completion.cjs';
39
+ import { createSunPlanetaryCompletion, computeCarrierRatesDegPerCy } from './eclipse/sun-planetary-completion.cjs';
40
40
  import { createEclipseFinders } from './eclipse/finders.cjs';
41
41
  import { createBesselian } from './eclipse/besselian.cjs';
42
42
  import { driver2PeriodSecondsAtAge } from './planets/orbit-chain.cjs';
@@ -1276,20 +1276,21 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
1276
1276
  // (the composed table reproduces the N3 one there: JPL 1900–2100
1277
1277
  // all-phase sd unchanged to 0.01″). The parity gate's fingerprint mirrors
1278
1278
  // this arithmetic (test/create-model-parity.test.mjs).
1279
- const degPerCyOf = /** @param {number} cyclesPerDay */ (cyclesPerDay) => 360 * 36525 * cyclesPerDay;
1280
- const carrierPrecessionDegPerCy = degPerCyOf(1 / meanSolarYearDays) - degPerCyOf(1 / meanSiderealYearDays);
1281
- const carrierRatesDegPerCy = {
1282
- planets: [
1283
- degPerCyOf(1 / C.planetOrbitalElements.mercury.solarYearInput) - carrierPrecessionDegPerCy,
1284
- degPerCyOf(1 / C.planetOrbitalElements.venus.solarYearInput) - carrierPrecessionDegPerCy,
1285
- degPerCyOf(1 / meanSiderealYearDays),
1286
- degPerCyOf(1 / C.planetOrbitalElements.mars.solarYearInput) - carrierPrecessionDegPerCy,
1287
- degPerCyOf(1 / C.planetOrbitalElements.jupiter.solarYearInput) - carrierPrecessionDegPerCy,
1288
- degPerCyOf(1 / C.planetOrbitalElements.saturn.solarYearInput) - carrierPrecessionDegPerCy,
1289
- ],
1290
- moonElongation: degPerCyOf(1 / moonSiderealMonthInput - 1 / meanSiderealYearDays),
1291
- };
1292
- const { sunPlanetaryCompletionDeg } = createSunPlanetaryCompletion({ embWobbleArcsec, carrierRatesDegPerCy });
1279
+ // PLAN 06 I3 — the carriers are the model's own banked J2000 sidereal mean
1280
+ // motions (the embedded sun-completion artifact; ONE home,
1281
+ // computeCarrierRatesDegPerCy — the former record-based arithmetic sat
1282
+ // 4.1″/yr off for Venus, 1.7″/yr for Jupiter: 83° of the Venus–Earth
1283
+ // argument at ±9000 yr), Earth the framework sidereal year, the Moon
1284
+ // elongation from the sidereal month/year identity. The long-period rows
1285
+ // ride the embedded e-vectors of date, and the lunar equation rides the
1286
+ // framework's own Moon elongation of date (ṅ included) — the constant-rate
1287
+ // carrier ran ~29° off it at ±9000 yr.
1288
+ const carrierRatesDegPerCy = computeCarrierRatesDegPerCy({ meanSiderealYearDays, moonSiderealMonthDays: moonSiderealMonthInput });
1289
+ const { sunPlanetaryCompletionDeg } = createSunPlanetaryCompletion({
1290
+ embWobbleArcsec,
1291
+ carrierRatesDegPerCy,
1292
+ moonElongationDegAtT: /** @param {number} T */ (T) => moonArgs.argsAt(j2000JD + T * julianCenturyDays).D,
1293
+ });
1293
1294
  const besselian = createBesselian({
1294
1295
  moonFullAtDaysTT: /** @param {number} dDaysTT */ (dDaysTT) => {
1295
1296
  const ev = moonSeries.sceneEvalAt(dDaysTT);
@@ -71,6 +71,7 @@ export function createDeepOrbitalHistory({ zModes, zetaModes, zetaSeries, zSerie
71
71
  epsDeg: number;
72
72
  e: number;
73
73
  periOfDateDeg: number;
74
+ periOfDateRateDegPerYr: number;
74
75
  eSinPeri: number;
75
76
  eCosPeri: number;
76
77
  inclEclDeg: number;
@@ -0,0 +1,38 @@
1
+ export const SUN_COMPLETION_ARTIFACT: Readonly<{
2
+ planetLamDotJ2000DegPerYr: {
3
+ mercury: number;
4
+ venus: number;
5
+ mars: number;
6
+ jupiter: number;
7
+ saturn: number;
8
+ uranus: number;
9
+ neptune: number;
10
+ };
11
+ eccVectors: {
12
+ t0Yr: number;
13
+ stepYr: number;
14
+ bodies: {
15
+ venus: {
16
+ zQ: number[];
17
+ zP: number[];
18
+ };
19
+ earth: {
20
+ zQ: number[];
21
+ zP: number[];
22
+ };
23
+ mars: {
24
+ zQ: number[];
25
+ zP: number[];
26
+ };
27
+ jupiter: {
28
+ zQ: number[];
29
+ zP: number[];
30
+ };
31
+ };
32
+ };
33
+ meta: {
34
+ dumpSha256: string;
35
+ source: string;
36
+ };
37
+ }>;
38
+ export const SUN_COMPLETION_ARTIFACT_HASH: "5ad17b275a003f6e";
@@ -1,43 +1,87 @@
1
1
  /**
2
2
  * @param {{ embWobbleArcsec: number,
3
- * carrierRatesDegPerCy: { planets: number[], moonElongation: number } }} opts
3
+ * carrierRatesDegPerCy: { planets: number[], moonElongation: number },
4
+ * eccVectorOfDate?: (bodyIndex: number, T: number) => [number, number],
5
+ * moonElongationDegAtT?: (T: number) => number }} opts
4
6
  * - embWobbleArcsec: the DERIVED Earth-around-EMB wobble amplitude
5
7
  * a_M·μ/AU in arcsec (μ = 1/(1+M_E/M_M));
6
- * - carrierRatesDegPerCy.planets: the six FRAMEWORK mean-longitude
7
- * rates (deg/Julian-century TT), body order Me,V,E,Ma,J,S — one
8
- * revolution per the model's own tropical period records;
8
+ * - carrierRatesDegPerCy.planets: the six mean-longitude rates (deg/
9
+ * Julian-century TT), body order Me,V,E,Ma,J,S — computeCarrierRatesDegPerCy
10
+ * (the model's own banked J2000 sidereal mean motions; Earth the framework
11
+ * sidereal year);
9
12
  * - carrierRatesDegPerCy.moonElongation: the framework Moon
10
- * mean-elongation rate (deg/cy TT) for the EMB-wobble carrier.
11
- * All computed from live constants by the model wiring so the
12
- * carrier↔table matched pair tracks the constants.
13
+ * mean-elongation rate (deg/cy TT) — the EMB-wobble carrier's rate when
14
+ * moonElongationDegAtT is absent;
15
+ * - eccVectorOfDate: the e-vectors of date for the D'Alembert rows (default:
16
+ * the embedded grid — the ONE source; an override is for instruments);
17
+ * - moonElongationDegAtT: the Moon's mean elongation OF DATE (deg) at T —
18
+ * the framework's own argument (ṅ included). The constant-rate carrier
19
+ * D₀ + D₁·T ran ~29° off it at ±9000 yr: the lunar equation (6.44″) read
20
+ * as the largest short-period line left against DE441 at −9000 (2.8″ at
21
+ * 29.53 d; the −9000 bin's scatter 4.13 → 3.62″ on the argument of date).
22
+ * Injected by the model wiring so the carrier↔table matched pair tracks the
23
+ * constants and the embedded artifact.
13
24
  * @returns {{ sunPlanetaryCompletionDeg: (T: number) => number }}
14
25
  */
15
- export function createSunPlanetaryCompletion({ embWobbleArcsec, carrierRatesDegPerCy }: {
26
+ export function createSunPlanetaryCompletion({ embWobbleArcsec, carrierRatesDegPerCy, eccVectorOfDate, moonElongationDegAtT }: {
16
27
  embWobbleArcsec: number;
17
28
  carrierRatesDegPerCy: {
18
29
  planets: number[];
19
30
  moonElongation: number;
20
31
  };
32
+ eccVectorOfDate?: (bodyIndex: number, T: number) => [number, number];
33
+ moonElongationDegAtT?: (T: number) => number;
21
34
  }): {
22
35
  sunPlanetaryCompletionDeg: (T: number) => number;
23
36
  };
37
+ /**
38
+ * The completion's CARRIER rates (deg per Julian century TT) — ONE home for the
39
+ * model wiring and the matched-pair gate. Planets: the model's own banked J2000
40
+ * sidereal mean motions (the embedded artifact; the former carriers were the
41
+ * planet records' rounded of-date periods minus p₀ — Venus 4.1″/yr and Jupiter
42
+ * 1.7″/yr off the run's own motion, 83° of the Venus–Earth argument at ±9000 yr).
43
+ * Earth: the framework sidereal year (the D6 ratio-only doctrine for the run's
44
+ * absolute Earth rate). Moon elongation: sidereal month vs sidereal year.
45
+ * @param {{ meanSiderealYearDays: number, moonSiderealMonthDays: number }} c
46
+ * @returns {{ planets: number[], moonElongation: number }}
47
+ */
48
+ export function computeCarrierRatesDegPerCy({ meanSiderealYearDays, moonSiderealMonthDays }: {
49
+ meanSiderealYearDays: number;
50
+ moonSiderealMonthDays: number;
51
+ }): {
52
+ planets: number[];
53
+ moonElongation: number;
54
+ };
55
+ /**
56
+ * The e-vector (e·cos ϖ, e·sin ϖ; ecliptic J2000) of a body at T Julian
57
+ * centuries TT from J2000, from the embedded 1-kyr grid (linear between nodes,
58
+ * held at the grid's ends). The ONE source for every runtime — an
59
+ * artifact-less createModel() and the browser before its series load compute
60
+ * the identical rows.
61
+ * @param {number} bodyIndex 0 Me, 1 V, 2 E, 3 Ma, 4 J, 5 S (only 1–4 are embedded)
62
+ * @param {number} T
63
+ * @returns {[number, number]}
64
+ */
65
+ export function eccVectorOfDateEmbedded(bodyIndex: number, T: number): [number, number];
24
66
  /** sha256/16 of JSON.stringify(FITTED_COEFFICIENTS.SUN_LONGITUDE_HARMONICS)
25
67
  * at derivation time — the matched-pair fingerprint asserted by test:model.
26
68
  * Unchanged from v1/v2: SUN_HARMONICS did not move in the D2 or N3
27
69
  * landings. */
28
70
  export const PAIRED_SUN_HARMONICS_SHA256: "cbc189cea1c20292";
29
71
  /** sha256/16 of JSON.stringify([...planets, moonElongation]) — the seven
30
- * full-precision carrier rates (deg/cy TT) the TERMS table pairs with:
31
- * the SIDEREAL carriers of plan 06 I2 (record rate − the model's J2000
32
- * precession; Earth the framework sidereal year; the N3 literals kept,
33
- * the two long-period rows derived on these rates). The model wiring
34
- * recomputes the rates live from the planet records, so a planet-period /
35
- * year / month input change moves the carriers automatically while the
36
- * table stays frozen — a silent few-arcsec stale below the api gate's
37
- * ≤12″ backstop. test:model recomputes this fingerprint from live
38
- * constants (identical arithmetic to model.js) and fails on mismatch:
39
- * re-run the extraction chain (tools/explore/n2-sun-framework-carriers.mjs
40
- * → i2-sidereal-carrier-table.mjs for the short-period rows,
41
- * i2-long-inequality.mjs for the long-period rows), re-embed TERMS, and
42
- * update this value. */
43
- export const PAIRED_CARRIER_RATES_SHA256: "2d066e92bae955e4";
72
+ * full-precision carrier rates (deg/cy TT) the tables pair with: since plan
73
+ * 06 I3 the model's own banked J2000 sidereal mean motions for the planets
74
+ * (the embedded sun-completion artifact), Earth the framework sidereal year,
75
+ * the Moon elongation from the sidereal month/year identity
76
+ * (computeCarrierRatesDegPerCy; the N3 short-period literals kept, the
77
+ * LONG_PERIOD_TERMS derived on these rates). The model wiring recomputes
78
+ * the rates live, so a series re-bank, a year or a month input change moves
79
+ * the carriers automatically while the tables stay frozen — a silent
80
+ * few-arcsec stale below the api gate's ≤12″ backstop. test:model recomputes
81
+ * this fingerprint from the live artifact + constants (identical arithmetic)
82
+ * and fails on mismatch: re-run the extraction chain
83
+ * (tools/explore/n2-sun-framework-carriers.mjs → i2-sidereal-carrier-table.mjs
84
+ * for the short-period rows, i3-long-period-dalembert.mjs for the long-period
85
+ * rows), re-embed the tables, and update this value. History: 2d066e92bae955e4
86
+ * was the I2 record-based carrier set. */
87
+ export const PAIRED_CARRIER_RATES_SHA256: "8e11456fcf8db81c";