@elite-dangerous-almanac/core 0.2.5 → 0.2.7

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 (153) hide show
  1. package/PROVENANCE/i18n/SOURCES.md +199 -113
  2. package/PROVENANCE/materials/SOURCES.md +22 -0
  3. package/PROVENANCE/ships/SOURCES.md +254 -59
  4. package/README.md +17 -11
  5. package/assets/ships/LakonMiner/schematic-bottom.svg +5 -3
  6. package/assets/ships/LakonMiner/schematic-top.svg +2 -4
  7. package/dist/{chunk-XM4VA2WE.js → chunk-4U7KYQGK.js} +1 -1
  8. package/dist/{chunk-XM4VA2WE.js.map → chunk-4U7KYQGK.js.map} +1 -1
  9. package/dist/{chunk-7EWZGDWY.js → chunk-7S7ZTZZY.js} +1 -1
  10. package/dist/chunk-A5TCT2AJ.js +1 -0
  11. package/dist/{chunk-AIEC3LBT.js.map → chunk-A5TCT2AJ.js.map} +1 -1
  12. package/dist/chunk-A7IVMYNF.js +1 -0
  13. package/dist/chunk-A7IVMYNF.js.map +1 -0
  14. package/dist/{chunk-2OBUSQA7.js → chunk-AAU7OM47.js} +1 -1
  15. package/dist/{chunk-2OBUSQA7.js.map → chunk-AAU7OM47.js.map} +1 -1
  16. package/dist/{chunk-KPJ77VPS.js → chunk-BJU27V6C.js} +1 -1
  17. package/dist/{chunk-KPJ77VPS.js.map → chunk-BJU27V6C.js.map} +1 -1
  18. package/dist/{chunk-DSMLYA2M.js → chunk-BMQM4JBL.js} +1 -1
  19. package/dist/{chunk-DSMLYA2M.js.map → chunk-BMQM4JBL.js.map} +1 -1
  20. package/dist/chunk-C3LLPLLD.js +1 -0
  21. package/dist/chunk-C3LLPLLD.js.map +1 -0
  22. package/dist/chunk-EHFHRQEP.js +1 -0
  23. package/dist/{chunk-GLWPSVFV.js.map → chunk-EHFHRQEP.js.map} +1 -1
  24. package/dist/{chunk-YCGISPDR.js → chunk-ETWMPMZP.js} +1 -1
  25. package/dist/{chunk-3NPVWPOV.js → chunk-F7VWRDSL.js} +1 -1
  26. package/dist/chunk-F7VWRDSL.js.map +1 -0
  27. package/dist/{chunk-4CBMQULR.js → chunk-FMA36V6A.js} +1 -1
  28. package/dist/{chunk-4CBMQULR.js.map → chunk-FMA36V6A.js.map} +1 -1
  29. package/dist/chunk-IZIIGK3W.js +1 -0
  30. package/dist/{chunk-TW7LUBHD.js.map → chunk-IZIIGK3W.js.map} +1 -1
  31. package/dist/chunk-KBCA4GEZ.js +1 -0
  32. package/dist/chunk-KLC5XT6F.js +1 -0
  33. package/dist/chunk-KLC5XT6F.js.map +1 -0
  34. package/dist/chunk-M6J7KP7G.js +1 -0
  35. package/dist/chunk-M6J7KP7G.js.map +1 -0
  36. package/dist/chunk-MRLUWHGI.js +1 -0
  37. package/dist/{chunk-FF2X4K5P.js.map → chunk-MRLUWHGI.js.map} +1 -1
  38. package/dist/chunk-MVBVXK3G.js +1 -0
  39. package/dist/chunk-MVBVXK3G.js.map +1 -0
  40. package/dist/{chunk-HBQELOBY.js → chunk-NZXSIHAW.js} +1 -1
  41. package/dist/{chunk-HBQELOBY.js.map → chunk-NZXSIHAW.js.map} +1 -1
  42. package/dist/{chunk-IWFQ4ZKF.js → chunk-OFZGNWBT.js} +1 -1
  43. package/dist/chunk-PF3HZ73R.js +1 -0
  44. package/dist/{chunk-ITKZKREP.js.map → chunk-PF3HZ73R.js.map} +1 -1
  45. package/dist/chunk-QJECDMQQ.js +1 -0
  46. package/dist/{chunk-LZYHBFJC.js.map → chunk-QJECDMQQ.js.map} +1 -1
  47. package/dist/chunk-T7IQHFQ2.js +1 -0
  48. package/dist/chunk-T7IQHFQ2.js.map +1 -0
  49. package/dist/chunk-TSEDU73T.js +1 -0
  50. package/dist/chunk-TSEDU73T.js.map +1 -0
  51. package/dist/chunk-XFDMCPDW.js +1 -0
  52. package/dist/{chunk-GRSNX36B.js.map → chunk-XFDMCPDW.js.map} +1 -1
  53. package/dist/chunk-XRGECU7S.js +1 -0
  54. package/dist/chunk-XRGECU7S.js.map +1 -0
  55. package/dist/{chunk-OLKNYGGT.js → chunk-XSLPWM5N.js} +1 -1
  56. package/dist/chunk-XSN53F7W.js +1 -0
  57. package/dist/{chunk-DBGXZF7O.js.map → chunk-XSN53F7W.js.map} +1 -1
  58. package/dist/chunk-ZEN5K3GE.js +1 -0
  59. package/dist/{chunk-WR6ZFHTO.js.map → chunk-ZEN5K3GE.js.map} +1 -1
  60. package/dist/chunk-ZZTDEDXJ.js +1 -0
  61. package/dist/{chunk-FA5JVXVG.js.map → chunk-ZZTDEDXJ.js.map} +1 -1
  62. package/dist/equipment/index.js +1 -1
  63. package/dist/equipment/upgrade-costs.js +1 -1
  64. package/dist/equipment/upgrade-costs.js.map +1 -1
  65. package/dist/i18n/experimental-effect-descriptions.d.ts +21 -6
  66. package/dist/i18n/experimental-effect-descriptions.js +1 -1
  67. package/dist/i18n/experimental-effects.js +1 -1
  68. package/dist/i18n/index.d.ts +0 -2
  69. package/dist/i18n/index.js +1 -1
  70. package/dist/i18n/materials.d.ts +7 -6
  71. package/dist/i18n/materials.js +1 -1
  72. package/dist/i18n/micro-resources.d.ts +7 -6
  73. package/dist/i18n/micro-resources.js +1 -1
  74. package/dist/i18n/modules.d.ts +10 -7
  75. package/dist/i18n/modules.js +1 -1
  76. package/dist/i18n/pre-engineered.js +1 -1
  77. package/dist/materials/index.js +1 -1
  78. package/dist/materials/materials-all.js +1 -1
  79. package/dist/materials/materials-encoded.js +1 -1
  80. package/dist/materials/materials-manufactured.js +1 -1
  81. package/dist/materials/materials.js +1 -1
  82. package/dist/materials/micro-resources-all.js +1 -1
  83. package/dist/materials/micro-resources.js +1 -1
  84. package/dist/ships/blueprint-costs.js +1 -1
  85. package/dist/ships/blueprint-journal.js +1 -1
  86. package/dist/ships/build-metrics.js +1 -1
  87. package/dist/ships/engineering-options.d.ts +12 -6
  88. package/dist/ships/engineering-options.js +1 -1
  89. package/dist/ships/engineering.js +1 -1
  90. package/dist/ships/gunsights.d.ts +2 -2
  91. package/dist/ships/gunsights.js +1 -1
  92. package/dist/ships/index.d.ts +5 -5
  93. package/dist/ships/index.js +1 -1
  94. package/dist/ships/loadout-calculations.d.ts +11 -2
  95. package/dist/ships/loadout-calculations.js +1 -1
  96. package/dist/ships/loadout-validation.js +1 -1
  97. package/dist/ships/modules-all.d.ts +2 -2
  98. package/dist/ships/modules-all.js +1 -1
  99. package/dist/ships/modules-core.d.ts +3 -3
  100. package/dist/ships/modules-core.js +1 -1
  101. package/dist/ships/modules-hardpoint.d.ts +1 -1
  102. package/dist/ships/modules-internal.d.ts +1 -1
  103. package/dist/ships/modules-internal.js +1 -1
  104. package/dist/ships/modules-utility.d.ts +1 -1
  105. package/dist/ships/modules.d.ts +9 -6
  106. package/dist/ships/modules.js +1 -1
  107. package/dist/ships/pre-engineered-stats.js +1 -1
  108. package/dist/ships/pre-engineered.js +1 -1
  109. package/dist/ships/ship-loadout.d.ts +65 -23
  110. package/dist/ships/ship-loadout.js +1 -1
  111. package/dist/ships/weapons.js +1 -1
  112. package/package.json +1 -9
  113. package/dist/chunk-3NPVWPOV.js.map +0 -1
  114. package/dist/chunk-5QSCLEEB.js +0 -1
  115. package/dist/chunk-5QSCLEEB.js.map +0 -1
  116. package/dist/chunk-5VBB5CTV.js +0 -1
  117. package/dist/chunk-5VBB5CTV.js.map +0 -1
  118. package/dist/chunk-5ZVYRX6Z.js +0 -1
  119. package/dist/chunk-5ZVYRX6Z.js.map +0 -1
  120. package/dist/chunk-AIEC3LBT.js +0 -1
  121. package/dist/chunk-DAQ3PJ4R.js +0 -1
  122. package/dist/chunk-DAQ3PJ4R.js.map +0 -1
  123. package/dist/chunk-DBGXZF7O.js +0 -1
  124. package/dist/chunk-DCB4COCL.js +0 -1
  125. package/dist/chunk-DCB4COCL.js.map +0 -1
  126. package/dist/chunk-FA5JVXVG.js +0 -1
  127. package/dist/chunk-FF2X4K5P.js +0 -1
  128. package/dist/chunk-G2VSQFD6.js +0 -1
  129. package/dist/chunk-G2VSQFD6.js.map +0 -1
  130. package/dist/chunk-GLWPSVFV.js +0 -1
  131. package/dist/chunk-GRSNX36B.js +0 -1
  132. package/dist/chunk-ITKZKREP.js +0 -1
  133. package/dist/chunk-J4PCK4RV.js +0 -1
  134. package/dist/chunk-J4PCK4RV.js.map +0 -1
  135. package/dist/chunk-JO52LYO3.js +0 -1
  136. package/dist/chunk-KJFUNIIY.js +0 -1
  137. package/dist/chunk-KJFUNIIY.js.map +0 -1
  138. package/dist/chunk-LZYHBFJC.js +0 -1
  139. package/dist/chunk-OJC6AUL7.js +0 -1
  140. package/dist/chunk-OJC6AUL7.js.map +0 -1
  141. package/dist/chunk-TW7LUBHD.js +0 -1
  142. package/dist/chunk-WR6ZFHTO.js +0 -1
  143. package/dist/i18n/engineering-groups.d.ts +0 -21
  144. package/dist/i18n/engineering-groups.js +0 -1
  145. package/dist/i18n/engineering-groups.js.map +0 -1
  146. package/dist/i18n/ships.d.ts +0 -36
  147. package/dist/i18n/ships.js +0 -1
  148. package/dist/i18n/ships.js.map +0 -1
  149. /package/dist/{chunk-7EWZGDWY.js.map → chunk-7S7ZTZZY.js.map} +0 -0
  150. /package/dist/{chunk-YCGISPDR.js.map → chunk-ETWMPMZP.js.map} +0 -0
  151. /package/dist/{chunk-JO52LYO3.js.map → chunk-KBCA4GEZ.js.map} +0 -0
  152. /package/dist/{chunk-IWFQ4ZKF.js.map → chunk-OFZGNWBT.js.map} +0 -0
  153. /package/dist/{chunk-OLKNYGGT.js.map → chunk-XSLPWM5N.js.map} +0 -0
@@ -16,6 +16,8 @@ Referred to throughout by source name; the pin is here, once.
16
16
  | EDCD/Coriolis — the application, for its formulas | commit `68c042ca6e3db62372cbbb2077cf972345511712` | 2026-08-01 UTC |
17
17
  | msarilar/EDEngineer `EDEngineer/Resources/Data/blueprints.json` | SHA-256 `787e6bd0579264d7b4615a281318792cb212285786f4ae07f61ec1cc464cdec0` — read from the branch tip, so pinned by digest | 2026-08-08 UTC |
18
18
  | Elite Dangerous in-game verification | game version `4.4.0.3`; direct in-game observation | 2026-08-14 UTC |
19
+ | Elite Dangerous in-game purchase capture | no game version recorded; nine `ModuleBuyAndStore` journal entries from market `128666762`, 17:34-17:37, at a 10% and a 2.5% outfitting discount | 2026-08-30 UTC |
20
+ | Elite Dangerous in-game outfitting observation | no game version recorded; direct in-game observation that outfitting offers no non-SCO size-8 frame shift drive | 2026-08-30 UTC |
19
21
 
20
22
  Every `eddb.js` derivation uses the baseline snapshot unless its catalogue note names
21
23
  the Vessel Hangar snapshot.
@@ -140,9 +142,16 @@ identity from FDevIDs, stats and slots from coriolis-data, joined on `symbol`.
140
142
  are omitted. Hull identity is already the map key; display names, slot keys and
141
143
  hardpoint counts are recoverable from `ships.jsonc`; all other acquisition and
142
144
  presentation metadata is unnecessary for projection and is dropped.
143
- - **Precision:** offsets remain at their observed numeric precision. Exact zero and tiny
144
- near-zero values both describe centerline mounts; the residuals are numeric precision,
145
- not meaningful sub-millimetre displacements to interpret or normalize.
145
+ - **Precision:** the offsets come from 32-bit-float model geometry, so decimal digits
146
+ below that grid describe nothing the source resolves. 196 of the 458 non-zero recorded
147
+ numbers are plainly a 32-bit float printed to ten decimals (`1.3350000381` is 1.335,
148
+ `-4.1649999619` is -4.165) and the rest sit within half a 32-bit-float step of one, so
149
+ each number is stored as the shortest rounding of its recorded decimal that still
150
+ lands on the same 32-bit float. 436 of the 468 shorten under that rule and none moves
151
+ by a full 32-bit-float step; the largest movement is 1.6 µm, the Cutter's
152
+ `48.7663916349` written `48.76639`. Exact zero and tiny near-zero values both describe
153
+ centerline mounts; the residuals are numeric precision, not meaningful sub-millimetre
154
+ displacements to interpret or normalize.
146
155
  - **Manual corrections:** none. All 48 hulls and all 234 of their hardpoint slot keys join
147
156
  one-to-one without correction.
148
157
 
@@ -344,7 +353,7 @@ FDevIDs, stats from coriolis-data and EDSY, joined on `symbol`.
344
353
  `id,symbol,category,name,mount,guidance,ship,class,rating,entitlement`, supplemented
345
354
  for the six bundle-granted Vessel Hangars by the pinned CAPI response below.
346
355
  - **Identity derivation:** the acquired FDevIDs module records are kept in CSV order
347
- within each category file. The catalogue contains 484 internal records and **1199**
356
+ within each category file. The catalogue contains 484 internal records and **1194**
348
357
  records across all four categories. The CSV's numeric `id`
349
358
  column is dropped — modules are keyed by `symbol` — and rows marked `removed` are
350
359
  excluded because they are not current outfitting modules. `class` is FDevIDs' `class` — the
@@ -377,7 +386,7 @@ FDevIDs, stats from coriolis-data and EDSY, joined on `symbol`.
377
386
  II's `Int_MkIIAgileBoost_Engine_*` thrusters.
378
387
  - **A fuel tank is the one module built for two kinds of mount:** it is `fuelTank`
379
388
  and also fits any optional slot large enough, exactly as the game sells it.
380
- - **`kind` is the ordinary engineering-menu family.** The 1005 records mapped by
389
+ - **`kind` is the ordinary engineering-menu family.** The 1000 records mapped by
381
390
  `engineering-options.jsonc` repeat that map's group key in the compact on-disk `kind`
382
391
  field. The remaining 194 records carry no `kind` because they have no ordinary
383
392
  engineering menu; this includes the five Enzyme/AX weapons, the fixed Mining Laser and
@@ -386,7 +395,7 @@ FDevIDs, stats from coriolis-data and EDSY, joined on `symbol`.
386
395
  Guardian families and coverage are documented under Engineering options below; this
387
396
  field is a projection of that map, not a separate classification source.
388
397
  - **`familyId` groups every outfitting list.** Every record in all four catalogues
389
- carries the id of the family its outfitting list shows it under: 521 core modules in
398
+ carries the id of the family its outfitting list shows it under: 516 core modules in
390
399
  8 families, 484 internal modules in 32, 159 hardpoints in 25, and 35 utility fittings
391
400
  in 12. No family crosses an outfitting category. The ids and their canonical English
392
401
  names are `module-families.jsonc`, below; localized labels are
@@ -398,7 +407,7 @@ FDevIDs, stats from coriolis-data and EDSY, joined on `symbol`.
398
407
  family where their function differs. A core record's family follows from its `slot`,
399
408
  which is on every one of them, so the two never disagree.
400
409
  - **`supercruiseOvercharge` — the SCO drive line.** The 36
401
- `Int_Hyperdrive_Overcharge_*` records carry `true`; the 36 plain drives of the same
410
+ `Int_Hyperdrive_Overcharge_*` records carry `true`; the 31 plain drives of the same
402
411
  sizes and ratings, and every other record in all four catalogues, omit it.
403
412
  - **Source:** FDevIDs `outfitting.csv`, which sells the two drive lines under distinct
404
413
  symbol families and names the Overcharge one `Frame Shift Drive (SCO)`. No registry
@@ -408,13 +417,44 @@ FDevIDs, stats from coriolis-data and EDSY, joined on `symbol`.
408
417
  above, and it is applied once here so that consumers read a datum instead of
409
418
  matching `Int_Hyperdrive_Overcharge` themselves — which a pre-engineered or fitted
410
419
  article's symbol does not always let them do. Stored as a sparse flag rather than a
411
- `true`/`false` pair on all 72 drives, following `alwaysPowered` and
420
+ `true`/`false` pair on all 67 drives, following `alwaysPowered` and
412
421
  `guardianZoneResistance`.
413
422
  - **Nothing else is derived from it.** The two lines share every jump constant this
414
423
  catalogue carries (`optMass`, `maxFuel`, `fuelMul`, `fuelPower`, and the
415
- size-determined `fsdHeatRate` above), so no calculation reads the flag; the
424
+ `fsdHeatRate`, which is a function of a drive's size alone — 10, 14, 18, 27, 37, 43
425
+ and 50 for sizes 2 to 8, identical on the plain and SCO lines at every size), so no
426
+ calculation reads the flag; the
416
427
  overcharged supercruise behaviour the drives are named for has no published figures
417
428
  and none are stored.
429
+ - **`cabinCapacity` — a passenger cabin's berths.** The 23 `passengerCabins` records
430
+ carry it; every other record in all four catalogues omits it, and no cabin carries a
431
+ zero. It is the module's own seat count, not the ship's.
432
+ - **Source:** coriolis-data
433
+ `modules/internal/{economy,business,first,luxury}_passenger_cabin.json` (`passengers`)
434
+ and EDSY `eddb.js` (`cabincap`, whose `fdattr` is the journal's `CabinCapacity`), from
435
+ the snapshots pinned above. The two agree on every one of the 14 Mk I cabins, so
436
+ neither is preferred; the nine Mk II cabins rest on EDSY alone, which is where their
437
+ masses come from as well. FDevIDs publishes no capacity column.
438
+ - **Values:** Mk I economy 2/4/8/16/32 by size 2–6, business 3/6/10/16 by size 3–6,
439
+ first 3/6/12 by size 4–6 and luxury 4/8 by size 5–6. Mk II economy 3/6/12/24/48 by
440
+ size 2–6 and Mk II business 4/9/15/24 by size 3–6 — half again the Mk I cabin of the
441
+ same class and size, bar the size-3 business cabin, whose 3 berths become 4 rather
442
+ than 4.5.
443
+ - **Stored per record rather than derived from size and rating.** A Mk II cabin runs one
444
+ rating better than the Mk I cabin of the same class — Mk II economy is `D` where Mk I
445
+ economy is `E`, and Mk II business `C` where Mk I business is `D` — so one
446
+ size-and-rating rule cannot produce both lines.
447
+ - **The four passenger classes are not carried as a field, and are not lost.** EDSY
448
+ publishes one (`cabincls`, values `E`/`B`/`F`/`L`), which this catalogue does not
449
+ copy: the symbol already states the class, uniformly across both lines. The symbol's
450
+ `_ClassN` suffix — not the `class` field, which is the slot size — is 1/2/3/4 for
451
+ economy/business/first/luxury on all 23 records, which is what the English `name` and
452
+ EDSY's `cabincls` both agree with; the `rating` field is what does not state it, for
453
+ the reason above. The Mk I line runs all four, the Mk II line economy and business
454
+ only.
455
+ - **EDSY's five `Int_PassengerCabin_Size{2..6}_Class0` "Prisoner Cells" rows are not
456
+ carried**, capacity or otherwise: EDSY has them commented out with a null `fdid`, and
457
+ the inclusion rule below excludes an identity no registry offers to players.
418
458
  - **`grantOnly` — the articles that arrive granted rather than sold.** Fifteen records
419
459
  carry `true`: the nine `*_free` starter fittings (power plant, thrusters, drive, life
420
460
  support, distributor, sensors, fuel tank, shield generator, cargo rack) and the six
@@ -432,12 +472,11 @@ FDevIDs, stats from coriolis-data and EDSY, joined on `symbol`.
432
472
  twin bar the price (§Prices), so a screen offering both would show one article twice,
433
473
  once unpriced.
434
474
  - **It is not a statement about price, and the flag is not extended on a missing one.**
435
- Eleven further records carry no `cost` — the five size-8 drives, the three Mk II
436
- Vessel Hangars, the two unsold Corrosion Resistant Cargo Racks and the 1B shield
437
- generator and none is flagged. The two racks are the closest case and still fail
438
- the rule: no source states them as a hull or bundle grant, and each is its own
439
- identity at a capacity no other rack carries, not a second identity for something a
440
- station already sells.
475
+ Three further records carry no `cost` — the two unsold Corrosion Resistant Cargo
476
+ Racks and the 1B shield generator and none is flagged. The two racks are the
477
+ closest case and still fail the rule: no source states them as a hull or bundle
478
+ grant, and each is its own identity at a capacity no other rack carries, not a second
479
+ identity for something a station already sells.
441
480
 
442
481
  ### `module-families.jsonc` — the family ids and their English names
443
482
 
@@ -591,14 +630,11 @@ Thirteen stored fields supply the base values referenced by engineering recipes:
591
630
  - **`EnergyPerRegen` needs no stored value.** All 57 shield generators carry
592
631
  `distributorDraw`, and EDSY (`genpwr`) and coriolis (`distdraw`) both confirm it is the
593
632
  same stat under the journal's other name.
594
- - **Nine figures no third-party registry lists, derived from the family rule.** Eight
595
- records: the three `*_free` starter fittings (thrusters, drive, sensors — the sensors
596
- contribute both a `scannerRange` and a `scanAngle`) and the five plain size-8 drives.
633
+ - **Four figures no third-party registry lists, derived from the family rule.** Three
634
+ records: the `*_free` starter fittings (thrusters, drive, sensors — the sensors
635
+ contribute both a `scannerRange` and a `scanAngle`).
597
636
  Each `*_free` record is byte-identical to its priced twin apart from the missing
598
- `cost`, so it takes that twin's value. A drive's heat rate is a function of its **size
599
- alone** across all 66 records EDSY does carry — 10, 14, 18, 27, 37, 43 for sizes 2 to
600
- 7, identical between the plain and SCO lines at every size — and the size-8 SCO drives
601
- are 50, so the size-8 plain drives take 50. Stated as derivation, not as a reading.
637
+ `cost`, so it takes that twin's value. Stated as derivation, not as a reading.
602
638
  The Mk II supercharge-optimised size-8 SCO drive is **not** among them: EDSY publishes
603
639
  its `fsdheat: 50` outright, spelling the symbol
604
640
  `Int_Hyperdrive_Overcharge_Size8_Class5_Overchargebooster_MkII` where the outfitting
@@ -649,8 +685,8 @@ Two starter capacities are derived rather than read:
649
685
  2^size across all eight sizes of both families, with no exception.
650
686
 
651
687
  **In-game coverage, stated separately from registry coverage.** In-game verification
652
- covers **1193/1199** catalogue identities. Numeric verification covers **952/1199**
653
- non-armour modules, and the other **241/1199** verified identities are the ship-specific
688
+ covers **1188/1194** catalogue identities. Numeric verification covers **947/1194**
689
+ non-armour modules, and the other **241/1194** verified identities are the ship-specific
654
690
  armour modules; their class, mass, hull boost and resistances retain their registry
655
691
  provenance rather than being described as game-verified. The six bundle-granted Vessel
656
692
  Hangars rely on the public registry and CAPI evidence below. Their stats match their
@@ -658,8 +694,8 @@ ordinary twins, but they have not been independently checked in the module panel
658
694
 
659
695
  Every numeric field available through in-game verification was compared. Exact
660
696
  full-field coverage includes `powerDraw`
661
- 831/837, `bootTime` 827/833, power-plant output and efficiency 43/43 each, every FSD
662
- field 72/72, every thruster heat-rate record 40/40, all six distributor fields 49/49,
697
+ 826/832, `bootTime` 822/828, power-plant output and efficiency 43/43 each, every FSD
698
+ field 67/67, every thruster heat-rate record 40/40, all six distributor fields 49/49,
663
699
  sensor range and angle 41/41, shield mass/strength curves 57/57, shield regeneration
664
700
  57/57, shield-cell timing/reinforcement/heat 40/40, fuel-scoop rate 40/40,
665
701
  interdictor range/facing 20/20, cargo capacity 16/16, fuel capacity 9/9, hull
@@ -667,7 +703,7 @@ reinforcement 30/30, module protection 20/20, shield addition 10/10, Guardian ju
667
703
  boost 5/5, weapon armour piercing 157/157, burst rounds 18/18, burst rate 16/16 and
668
704
  rounds per shot 19/19. `powerDraw` and `bootTime` have no discrepancies at all.
669
705
 
670
- In-game verification did not yield the 1173 store prices, hardpoint reserve ammo (120),
706
+ In-game verification did not yield the 1176 store prices, hardpoint reserve ammo (120),
671
707
  projectile speed (111), rail-gun charge time (3), or the 23 hardpoint scanners'
672
708
  range/angle/time fields. Twenty-one hardpoint maximum-range values, ECM heat and reload,
673
709
  the 241 armour modules, blueprint grade rolls and crafting costs remain unverified too.
@@ -724,8 +760,8 @@ external readings of an unmodified weapon's folded figure. On a beam laser the f
724
760
  trivial because `damage` is already per second; the huge and medium gimballed beams have
725
761
  no separate journal `Damage` reading.
726
762
 
727
- **Every module in every catalogue carries at least one stat** (1199/1199), and no
728
- record holds only a lone `mass`. 244 of the 833 `bootTime` values are `0` (every hardpoint
763
+ **Every module in every catalogue carries at least one stat** (1194/1194), and no
764
+ record holds only a lone `mass`. 244 of the 828 `bootTime` values are `0` (every hardpoint
729
765
  among them); they are stored rather than omitted, because an absent field means
730
766
  absent.
731
767
 
@@ -835,7 +871,7 @@ heuristic does not keep rediscovering them:
835
871
  distributor integrity otherwise tracks 0.80× the A-rated standard ladder, which would
836
872
  put size 5 near 85; EDSY states 99 for both sizes. The duplicate is in the game data.
837
873
  - **`Int_DroneControl_Recon_Size5_Class1` `bootTime` really is 9.85** — the only
838
- non-integer boot time in all 1199 records, where its three family siblings are exactly 10.
874
+ non-integer boot time in all 1194 records, where its three family siblings are exactly 10.
839
875
  EDSY gives `boottime:9.85`.
840
876
 
841
877
  ### Prices — `cost` on modules, `hullCost` / `retailCost` on hulls
@@ -850,18 +886,22 @@ the Lynx Highliner, which has no coriolis entry.
850
886
  Ship-specific **armour** is priced from each hull's `bulkheads` upstream, joined on hull
851
887
  and bulkhead name because those records carry no symbol upstream.
852
888
 
853
- - **All 48 hulls are priced. 1173 of 1199 modules are.** The 26 without a price are the
854
- fifteen grant/starter `*_free` variants, the five size-8 frame shift drives, the three Mk II
855
- Vessel Hangars, the two unsold Corrosion Resistant Cargo Racks (both Community Goal
856
- rewards) and `Int_ShieldGenerator_Size1_Class4` no registry publishes a figure for
857
- them. **`cost` is omitted, never set to 0**: `0` is a real price (the starter
889
+ - **All 48 hulls are priced. 1176 of 1194 modules are.** The 18 without a price are the
890
+ fifteen grant/starter `*_free` variants, the two unsold Corrosion Resistant Cargo Racks
891
+ (both Community Goal rewards) and `Int_ShieldGenerator_Size1_Class4` no registry
892
+ publishes a figure for them. The three Mk II Vessel Hangars are no longer among them:
893
+ they are priced from an in-game purchase capture, below.
894
+ **`cost` is omitted, never set to 0**: `0` is a real price (the starter
858
895
  Lightweight Alloy bulkhead costs nothing), while omission means unknown.
859
896
  - **Sixteen duplicated symbols take the first occurrence's price.** Where coriolis-data
860
897
  holds a symbol twice, the "first occurrence wins" rule that governs `mass` governs
861
898
  `cost` too; taking the _second_, unpriced record would leave them at `0`. The sixteen:
862
- `Hpt_HeatSinkLauncher_Turret_Tiny` 3500 — confirmed independently against a real
863
- journal, which prices the fitted module at 3071 = 3500 less the 12.25% outfitting
864
- discount that export was taken at; `Int_Hyperdrive_Size5_Class5` 5 103 953;
899
+ `Hpt_HeatSinkLauncher_Turret_Tiny` 3500 — confirmed independently against Frontier's
900
+ own journals, which price the fitted module at 3072 at a 12.25% discount
901
+ (`journal-the-deep-black.jsonc` and `journal-caspian-explorer.jsonc`, twice each). The
902
+ **3071** in `slef-the-deep-black.jsonc` is an EDSY export's own arithmetic over its own
903
+ cost table, not a game reading, and the two disagree by a credit here; §Prices read from
904
+ an in-game purchase capture turns on the difference; `Int_Hyperdrive_Size5_Class5` 5 103 953;
865
905
  `Int_CargoRack_Size5_Class1` 111 566 and `_Size6_Class1` 362 591;
866
906
  `Int_DetailedSurfaceScanner_Tiny` 250 000; `Hpt_MultiCannon_Fixed_Medium` 38 000;
867
907
  `Hpt_Railgun_Fixed_Medium` 412 800; `Hpt_BasicMissileRack_Fixed_Medium` 512 400;
@@ -877,8 +917,11 @@ and bulkhead name because those records carry no symbol upstream.
877
917
  registries price they agree exactly (`_Size1_Class1` 6250, `_Size4_Class1` 94 330), and
878
918
  the only corrosion racks FDevIDs `outfitting.csv` lists at all are those two plus
879
919
  `_Size1_Class2` itself — so it is the last of the purchasable ones. It is certainly not
880
- free: the Deep Black's journal buys the size-4 at 82 775 = 94 330 less that export's
881
- 12.25% discount.
920
+ free: `journal-the-deep-black.jsonc` carries the size-4 at `Value: 82 774` under a
921
+ 12.25% discount. (That reading sits a credit below what 94 330 predicts under the
922
+ step-wise discount rule in §Prices read from an in-game purchase capture, and is
923
+ recorded there as a known residual. Earlier revisions of this file quoted **82 775**
924
+ here as a journal reading; it is the arithmetic, not the capture.)
882
925
  - **Read that 12 560 as a 10-granular figure, not a to-the-credit one.** EDSY publishes
883
926
  module costs at **10-credit granularity**, which is measured rather than assumed. Two
884
927
  observations, both scoped to `eddb.module` — EDSY's outfitting table, where module
@@ -908,9 +951,13 @@ and bulkhead name because those records carry no symbol upstream.
908
951
  where both registries publish a multiple of 10 still differ by 10
909
952
  (`Int_FighterBay_Size{6,7}_Class1`, `Int_PassengerCabin_Size6_Class1`), which no
910
953
  rounding explains: whatever the real price is, at least one of the two registries is
911
- wrong about it by five credits or more, and neither says which. So treat 12 560 as the
912
- best published figure at 10-credit resolution, not as an accuracy guarantee; only an
913
- in-game reading settles the last digits. Every EDSY-sourced price in this catalogue
954
+ wrong about it by five credits or more, and neither says which. Two of the three are
955
+ now settled by in-game readings, and coriolis is exactly right in both:
956
+ `Int_FighterBay_Size7_Class1` is 2 369 320 and `Int_FighterBay_Size6_Class1` is
957
+ 1 869 340, so EDSY's 2 369 330 is the wrong member of that pair (see "Prices read from
958
+ an in-game purchase capture" below). So treat 12 560 as
959
+ the best published figure at 10-credit resolution, not as an accuracy guarantee; only
960
+ an in-game reading settles the last digits. Every EDSY-sourced price in this catalogue
914
961
  carries the same granularity, so this record is no less exact than the rest of them.
915
962
  - **The size-5 and size-6 Corrosion Resistant Cargo Racks have no list price to
916
963
  publish**, and their absent `cost` means _no list price exists_, not _none has been
@@ -958,9 +1005,84 @@ and bulkhead name because those records carry no symbol upstream.
958
1005
  thermal −0.2, explosive 0.5, draw 0.6. The cargo hatch (`ModularCargoBayDoor`) takes
959
1006
  the 0.6 MW draw Coriolis hard-codes for it (`ModuleUtils.cargoHatch`), since it is
960
1007
  fitted to every hull and cannot be removed.
961
- - **Not modelled:** passenger capacity and fighter-bay/rebuild counts. The
962
- **Merc-Coin** price of the pre-engineered variants is carried, but on the variant
963
- rather than the module — see `mercCoinCost` in the pre-engineered section.
1008
+ - **Not modelled:** fighter-bay/rebuild counts. The **Merc-Coin** price of the
1009
+ pre-engineered variants is carried, but on the variant rather than the module — see
1010
+ `mercCoinCost` in the pre-engineered section.
1011
+
1012
+ ### Prices read from an in-game purchase capture
1013
+
1014
+ Nine `ModuleBuyAndStore` journal entries, all from market `128666762` within four minutes
1015
+ on **2026-08-30 UTC** and supplied by the repository owner, price three module records no
1016
+ registry carries and confirm or correct six that were already priced. The capture was
1017
+ taken at a **10% and a 2.5% discount**, so each `BuyPrice` is the list price with both
1018
+ discounts applied. A journal `BuyPrice` is what the commander was actually charged, which
1019
+ is the objection that disqualifies a `Loadout` `Value` of unknown provenance (§the size-5
1020
+ and size-6 racks): here the discount is stated rather than solved for.
1021
+
1022
+ - **The game subtracts a truncated discount at each step; it does not truncate the
1023
+ product.** Each discount takes `floor(price x rate)` off the running price, so
1024
+ `paid = ceil(ceil(list x 0.9) x 0.975)`, and the two orders give the same answer for
1025
+ every row here. This is measured, not assumed: scored against **every** `Loadout`
1026
+ `Value` in `fixtures/ships/journal-*.jsonc` that a catalogue price and a standard
1027
+ discount can reproduce (455 readings), the step-wise rule matches 304, a single
1028
+ `ceil(list x 0.8775)` 275, `round` 230 and `floor` 92. Restricting to 2.5%-only
1029
+ readings gives the same ordering. **Do not derive a price from a single control**: two
1030
+ readings were originally used here and both were unrepresentative, which is how an
1031
+ earlier revision of this section published a truncation rule and eight wrong figures.
1032
+ - **`Hpt_HeatSinkLauncher_Turret_Tiny` is the reading that settles the last credit.** Its
1033
+ list price is 3500, both registries agree, and `3500 x 0.8775 = 3071.25`. Frontier's own
1034
+ journals read **3072** — `fixtures/ships/journal-the-deep-black.jsonc` and
1035
+ `journal-caspian-explorer.jsonc`, twice each — which excludes truncation and
1036
+ round-to-nearest alike. The **3071** quoted elsewhere in this file is not a game reading:
1037
+ it comes from `fixtures/ships/slef-the-deep-black.jsonc`, an EDSY SLEF export whose
1038
+ `Value`s are EDSY's own arithmetic. The two documents disagree wherever they overlap
1039
+ (3071/3072, 82 775/82 774, 195 191/195 195), so a third-party export is not admissible
1040
+ as evidence of what the game charged.
1041
+
1042
+ | Symbol | Paid | List price | Was |
1043
+ | ---------------------------------------- | ---------- | ---------- | --------------------- |
1044
+ | `Int_FighterBayMk2_Size5_Class1` | 697 076 | 794 387 | unpriced |
1045
+ | `Int_FighterBayMk2_Size6_Class1` | 2 263 678 | 2 579 689 | unpriced |
1046
+ | `Int_FighterBayMk2_Size7_Class1` | 2 869 128 | 3 269 661 | unpriced |
1047
+ | `Int_FighterBay_Size7_Class1` | 2 079 079 | 2 369 320 | 2 369 320 (confirmed) |
1048
+ | `Int_Hyperdrive_Overcharge_Size8_Class1` | 6 000 827 | 6 838 548 | 6 838 550 (EDSY) |
1049
+ | `Int_Hyperdrive_Overcharge_Size8_Class2` | 18 002 479 | 20 515 645 | 20 515 650 (EDSY) |
1050
+ | `Int_Hyperdrive_Overcharge_Size8_Class3` | 18 002 479 | 20 515 645 | 20 515 650 (EDSY) |
1051
+ | `Int_Hyperdrive_Overcharge_Size8_Class4` | 18 002 479 | 20 515 645 | 20 515 650 (EDSY) |
1052
+ | `Int_Hyperdrive_Overcharge_Size8_Class5` | 54 007 436 | 61 546 935 | 61 546 940 (EDSY) |
1053
+
1054
+ - **Seven of the nine readings pin one integer; two do not, and are settled by other
1055
+ evidence.** A one-credit band of paid price spans `400/351 = 1.14` credits of list price,
1056
+ so a reading admits one or two candidates.
1057
+ - `Int_FighterBayMk2_Size5_Class1` is pinned at 794 387 by the capture **and**
1058
+ independently by a second reading this repository already held: `Value: 774 528` at
1059
+ 2.5%, in both `journal-the-deep-black.jsonc` and `journal-caspian-explorer.jsonc`. Two
1060
+ captures at different discounts, one answer.
1061
+ - `Int_FighterBayMk2_Size6_Class1` admits 2 579 689 and 2 579 690. It takes **2 579 689**
1062
+ from the family rule below, which is a derivation and not a reading.
1063
+ - `Int_FighterBay_Size7_Class1` admits 2 369 319 and 2 369 320, and **keeps coriolis's
1064
+ 2 369 320** — the reading confirms the published figure rather than moving it, and
1065
+ settles one of the three registry pairs §Prices flags as differing by 10. Its sibling
1066
+ `Int_FighterBay_Size6_Class1` (1 869 340) is confirmed outright by four corvette
1067
+ readings at two different discounts.
1068
+ - **The Mk II bays are `floor(Mk I x 1.38)` at every size.** The rule reproduces both
1069
+ independently pinned values exactly — `floor(575 643 x 1.38) = 794 387` and
1070
+ `floor(2 369 320 x 1.38) = 3 269 661` — which is what licenses it to choose 2 579 689 for
1071
+ the size-6 bay. Stated as derivation for that one record, and as an observation for the
1072
+ other two.
1073
+ - **The size-8 SCO drives are priced identically to their size-7 siblings.** All four
1074
+ distinct readings land exactly on coriolis's size-7 figures (6 838 548, 20 515 645,
1075
+ 61 546 935), and EDSY's size-8 numbers are those same figures rounded to 10. The
1076
+ catalogue previously carried the EDSY rounding; it now carries the readings.
1077
+ - **A known residual.** `Int_CorrosionProofCargoRack_Size4_Class1` at 94 330 predicts
1078
+ 82 775 under this rule where `journal-the-deep-black.jsonc` reads **82 774**. It is one
1079
+ of a minority of records whose catalogue list price appears to sit a credit or two above
1080
+ the game's, and it is recorded here rather than explained away — it is not evidence for
1081
+ truncation, which the corpus rejects 304 to 92.
1082
+ - **What would supersede these figures:** a purchase or outfitting reading at 0% discount,
1083
+ which needs no model at all. Until then they are readings through one measured
1084
+ arithmetic rule, which is a weaker claim than a direct quote and a stronger one than a
1085
+ registry's rounded figure.
964
1086
 
965
1087
  ### Armour, and the fields kept deliberately
966
1088
 
@@ -1050,7 +1172,11 @@ Records not in coriolis-data / FDevIDs at the acquired revisions:
1050
1172
  bays at half the mass (10/20/30 t, integrity 60/80/120, power
1051
1173
  0.25/0.35/0.35 MW). The three Mk I **Fighter Hangar** records are named **Mk I Vessel
1052
1174
  Hangar** (same symbols and stats; the Operations update renamed them and let them
1053
- deploy the Nomad).
1175
+ deploy the Nomad). Their prices — which no registry carries, EDSY having no record of
1176
+ the Mk II bays at all — are read from the in-game purchase capture in §Prices: 794 387,
1177
+ 2 579 689 and 3 269 661. Each Mk II bay is `floor(Mk I x 1.38)`; that is an observation
1178
+ about the size-5 and size-7 figures, whose readings pin them outright, and the
1179
+ derivation that settles the size-6 figure, whose reading admits two candidates.
1054
1180
  - **Six bundle-granted variants are separate identities.** The pinned CAPI response
1055
1181
  lists `Int_FighterBay{,Mk2}_Size{5,6,7}_Class1_Free` as modules with `bundle: true`
1056
1182
  and the grant tokens `ELITE_V_MKIFIGHTERBAY_FREE` / `ELITE_V_MKIIFIGHTERBAY_FREE`.
@@ -1063,8 +1189,10 @@ Records not in coriolis-data / FDevIDs at the acquired revisions:
1063
1189
  zero is the bundle charge, not a standard purchase price for a separately sold
1064
1190
  module.
1065
1191
  - **Mk II passenger cabins** (`Int_MkII_PassengerCabin_Size{2..6}_Class{1,2}`) — identity
1066
- records from FDevIDs, with mass added (2.5/5/10/20/40 t by size) and the two size-6
1067
- records' `class` corrected from 5 to 6.
1192
+ records from FDevIDs, with mass (2.5/5/10/20/40 t by size) and `cabinCapacity` added
1193
+ from EDSY, the only registry that publishes stats for them — coriolis-data carries no
1194
+ record at all — and the two size-6 records' `class` corrected from 5 to 6. The
1195
+ capacities and how they relate to the Mk I cabins' are under `cabinCapacity` above.
1068
1196
  - **Corrosion Resistant Cargo Racks** `Int_CorrosionProofCargoRack_Size{5,6}_Class1`
1069
1197
  (capacity 32/64) and the built-in **Cargo Hatch** `ModularCargoBayDoor` (power 0.6 MW)
1070
1198
  — live EDSY records (not commented out, unlike the 1B shield generator below) that the
@@ -1080,6 +1208,35 @@ Records not in coriolis-data / FDevIDs at the acquired revisions:
1080
1208
  carries it `cost: NaN` annotated "never released". A variant that never reached
1081
1209
  players is not a player-facing outfitting record, so it goes the way of the other
1082
1210
  non-purchasable internal variants that rule excludes.
1211
+ - **Plain size-8 Frame Shift Drives are not carried: outfitting does not sell them.**
1212
+ `Int_Hyperdrive_Size8_Class{1..5}` are excluded on direct in-game observation
1213
+ (2026-08-30 UTC, §the pinned sources) that no non-SCO size-8 drive is offered. The five
1214
+ `Int_Hyperdrive_Overcharge_Size8_Class{1..5}` records are the size-8 drives the game
1215
+ does sell. Only one hull in the catalogue carries a size-8 frame-shift mount at all —
1216
+ the Caspian Explorer (`Explorer_NX`), every other size-8-capable hull including the
1217
+ Panther Clipper Mk II mounting a size 7 — and `default-loadouts.jsonc` ships that hull
1218
+ with `Int_Hyperdrive_Overcharge_Size8_Class1`, so the one stock size-8 drive in the
1219
+ data is an SCO drive.
1220
+ - **The case rests on the observation, not on the registries, and is weaker than the
1221
+ precedent it follows.** FDevIDs `outfitting.csv` does carry these five rows — which is
1222
+ why they were in the catalogue, and it means the Inclusion rule below, read literally,
1223
+ admits them. What overrides it is this catalogue's own rule that in-game verification
1224
+ governs where a registry disagrees. The other two registries are consistent but not
1225
+ probative: coriolis-data has no record, which is also true of the Mk II Vessel Hangars
1226
+ and the size-5/6 Corrosion Resistant Cargo Racks that _are_ carried; EDSY carries the
1227
+ five commented out, which is also true of `Int_ShieldGenerator_Size1_Class4` below,
1228
+ carried as real. `Int_CorrosionProofCargoRack_Size2_Class1` is the stronger case — no
1229
+ FDevIDs row at all and an explicit EDSY "never released" — so this exclusion is the
1230
+ same _kind_ of judgement on thinner evidence, and a contrary in-game reading should
1231
+ reverse it.
1232
+ - **The 2026-08-14 in-game audit's totals counted these five as verified, and are
1233
+ restated.** That audit reported `identityMatches` 1193 of 1199 with 952 non-armour
1234
+ modules checked numerically, and "every FSD field 72/72" — figures that could not have
1235
+ been true of five records the game does not offer. The corrected accounting is 1188
1236
+ identity matches, 947 non-armour modules and 67/67 FSD fields, with
1237
+ `registryOnlyIdentities` unchanged at 6; `fixtures/ships/module-stats.jsonc` carries
1238
+ the same numbers. This is a manual correction to previously published provenance, not
1239
+ a re-derivation from a new capture.
1083
1240
  - **1B Shield Generator** (`Int_ShieldGenerator_Size1_Class4`) — a gap in FDevIDs, not
1084
1241
  in the game: every other shield-generator size carries all five ratings, and size 1
1085
1242
  ran E/D/C/A with **B missing**. The module is real, so the record is carried with the
@@ -1477,8 +1634,19 @@ up straight through with no disambiguation at all. Both paths are evidence that
1477
1634
  - **Availability is a property of the module, not of the blueprint.** A Pulse Laser and a
1478
1635
  Rail Gun both take the Efficient blueprint but offer different experimental effects, so
1479
1636
  "which experimentals go with blueprint X" has no single answer. Modules are therefore
1480
- grouped (48 groups covering 1005 ordinary engineering menus) and each group lists the
1637
+ grouped (48 groups covering 1000 ordinary engineering menus) and each group lists the
1481
1638
  `blueprints` and `experimentals` it offers.
1639
+ - **A group carries no display name.** The grouping is this repository's own partition of
1640
+ the modules sharing one menu; the game publishes no engineering-group label, heading
1641
+ each menu with the module's outfitting family instead. EDSY's `mtype-*` strings, which
1642
+ this file previously stored as group names, are outfitting labels reached by a name
1643
+ join — which is why they disagreed with `module-families.jsonc` in 22 places on wording
1644
+ (`cannons` Russian "Пушки" against the family's "Орудия", `moduleReinforcements`
1645
+ Brazilian Portuguese title case against the family's sentence case). Consumers name a
1646
+ group by joining a module's `familyId` to `module-families.jsonc`. The two partitions
1647
+ do not coincide exactly: 47 of the 48 groups sit wholly inside one family, while
1648
+ `heatSinkLaunchers` covers both `heatsinkLaunchers` and `causticSinkLaunchers`, and the
1649
+ `fsd` and `hullReinforcements` families are each split across two groups.
1482
1650
  - **Source:** EDSY `eddb.js`, whose module-group tables carry each group's `blueprints`
1483
1651
  and `expeffects` lists and which modules belong to each group, and whose module records
1484
1652
  carry the per-module `noblueprints` / `noexpeffects`
@@ -1486,7 +1654,7 @@ up straight through with no disambiguation at all. Both paths are evidence that
1486
1654
  `modifications/modules.json`, which carries the same per-group lists keyed by the
1487
1655
  journal `BlueprintName`s this catalogue joins on.
1488
1656
  - **Coverage: every retained group EDSY's `mtype` table gives a `blueprints:` key.** After
1489
- the corrections below, that is 48 groups over 1005
1657
+ the corrections below, that is 48 groups over 1000
1490
1658
  modules, including
1491
1659
  bulkheads (the 241 ship armour records), life
1492
1660
  support, sensors, the Detailed Surface Scanner, refineries, AFMUs, fuel
@@ -1579,13 +1747,12 @@ up straight through with no disambiguation at all. Both paths are evidence that
1579
1747
  fixed Expanded Cargo Rack reward identity. Four Operations keys _are_ named by a
1580
1748
  group, because they are recipes a player applies — see "Four Operations recipes are
1581
1749
  listed by a menu" below.
1582
- - **14 modules are bound by the family rule, not by a source row.** EDSY has no live
1583
- entry for `Int_Hyperdrive_Size8_Class{1..5}` or `Int_ShieldGenerator_Size1_Class4`
1584
- (both present but commented out, and both naming their `mtype` `cfsd` and `isg`),
1585
- nor for eight of the `*_free` starter fittings. Each takes its family's group, on the
1586
- same rule the stats above use: a `*_free` variant is its priced twin bar the price,
1587
- and a size-8 drive is a drive. `Int_FuelTank_Size1_Class3_free` is not bound because
1588
- fuel tanks are not engineerable.
1750
+ - **9 modules are bound by the family rule, not by a source row.** EDSY has no live
1751
+ entry for `Int_ShieldGenerator_Size1_Class4` (present but commented out, and naming
1752
+ its `mtype` `isg`), nor for eight of the `*_free` starter fittings. Each takes its
1753
+ family's group, on the same rule the stats above use: a `*_free` variant is its priced
1754
+ twin bar the price. `Int_FuelTank_Size1_Class3_free` is not bound because fuel tanks
1755
+ are not engineerable.
1589
1756
  - **Corpus evidence does not override `noblueprints`.** Two corpus builds declare
1590
1757
  `Weapon_Efficient` on the Mk II Plasma Shock Accelerator, while EDSY denies that module
1591
1758
  every blueprint (`noblueprints: {'*'}`). Coriolis publishes only the group-level menu
@@ -1642,7 +1809,7 @@ up straight through with no disambiguation at all. Both paths are evidence that
1642
1809
  five module mappings and the corresponding projected `kind` fields in
1643
1810
  `modules-hardpoint.jsonc`.
1644
1811
  - **An empty experimental menu is still distinct from no menu.** 27 of the 48 groups offer
1645
- no experimental at all, so 368 of the 1005 grouped modules have an empty experimental
1812
+ no experimental at all, so 368 of the 1000 grouped modules have an empty experimental
1646
1813
  list while retaining blueprints.
1647
1814
  - **Key form:** the Anti-Guardian blueprint is listed under `GuardianModule_Sturdy`, the id
1648
1815
  a Loadout writes and the one EDSY uses — the same and only spelling `blueprints.jsonc`
@@ -1729,6 +1896,34 @@ up straight through with no disambiguation at all. Both paths are evidence that
1729
1896
 
1730
1897
  ## Pre-engineered modules
1731
1898
 
1899
+ ### A tech-broker unlock may be sold under its own name
1900
+
1901
+ Nineteen of the tech-broker variants are not sold as the plain base module. Each carries
1902
+ one of three markers, supplied by repository-owner in-game verification (2026-08-30 UTC);
1903
+ no registry publishes them, and the game exposes no immutable identifier for its
1904
+ outfitting strings.
1905
+
1906
+ | Marker | Variants | Name |
1907
+ | --- | ---: | --- |
1908
+ | `Sirius` | 1 + 2 | Sirius Heat Sink Launcher, Sirius AX Missile Rack |
1909
+ | `Azimuth` | 2 | Azimuth Enhanced AX Multi-Cannon |
1910
+ | `Modified` | 2 + 2 + 2 | Modified Guardian Plasma Charger / Gauss Cannon / Shard Cannon |
1911
+ | `V1` | 6 + 1 + 1 | Frame Shift Drive (SCO) V1, Detailed Surface Scanner V1, Seeker Missile Rack V1 |
1912
+
1913
+ `Sirius` and `Azimuth` are the manufacturers that sell the unlock; `V1` marks a first
1914
+ fixed revision. The marker is a property of the **tech-broker** route, not of the module:
1915
+ `Hpt_Guardian_ShardCannon_Fixed_Medium` is a Modified Guardian Shard Cannon bought from a
1916
+ broker and a plain Guardian Shard Cannon earned from a community goal, and the two rows
1917
+ differ only by `acquisition`. The same holds for `Hpt_BasicMissileRack_Fixed_Medium`,
1918
+ whose thermal-cascade tech-broker row is a Seeker Missile Rack V1 while its three
1919
+ community-goal rows are plain. Two tech-broker rows carry no marker at all and keep their
1920
+ base module's name: the Mining Laser and the size-5 Frame Shift Drive.
1921
+
1922
+ This repository's own fixtures already described several of these under the corrected
1923
+ names — `pre-engineered.jsonc` calls one row "the tech-broker 'Modified Guardian Shard
1924
+ Cannon'" and another "a V1 FSD" — while `name` carried the plain module's. The data now
1925
+ agrees with the prose.
1926
+
1732
1927
  ### Festive variants
1733
1928
 
1734
1929
  - **File:** `pre-engineered.jsonc`. Three grade-5 records pair
package/README.md CHANGED
@@ -140,9 +140,9 @@ data-free leaf modules under `ships/jump-range`, `ships/power`, `ships/shields`,
140
140
  `ships/resistances`.
141
141
 
142
142
  `build.validation()` reports validity and operational completeness. `cargoCapacity`,
143
- `fuelCapacity` and `unladenMass` always have an answer, because no article the
144
- catalogue cannot weigh reaches a build; the eight metrics that depend on build state
145
- (`mobilityMetrics`, `mobilityCapacitorMetrics`, `shieldMetrics`,
143
+ `passengerCapacity`, `fuelCapacity` and `unladenMass` always have an answer, because no
144
+ article the catalogue cannot weigh reaches a build; the eight metrics that depend on
145
+ build state (`mobilityMetrics`, `mobilityCapacitorMetrics`, `shieldMetrics`,
146
146
  `shieldCapacitorMetrics`, `shieldRecovery`, `heatMetrics`, `distributorMetrics` and
147
147
  `standardLoad`) are nullable and each has a `…Result` counterpart naming what is
148
148
  missing, switched off, shed or unpowered. `parseSlef`
@@ -168,19 +168,18 @@ pinned sources carry no translation instead of silently substituting English:
168
168
  ```ts
169
169
  import {
170
170
  getBlueprintName,
171
- getEngineeringGroupName,
172
171
  getMaterialName,
173
172
  getMicroResourceName,
174
173
  getModuleName,
175
- getShipName,
174
+ getOutfittingFamilyName,
176
175
  } from '@elite-dangerous-almanac/core/i18n';
177
176
 
178
177
  getModuleName('Int_Hyperdrive_Size6_Class5', 'de-DE'); // -> "Frameshiftantrieb"
179
178
  getBlueprintName('FSD_LongRange', 'fr-FR'); // -> "Portée FSD améliorée"
180
179
  getMaterialName('GridResistors', 'de'); // -> "Gitterwiderstände"
181
180
  getMicroResourceName('graphene', 'fr'); // -> "Graphène"
182
- getShipName('empire_trader', 'fr'); // -> "Imperial Clipper"
183
- getEngineeringGroupName('frameShiftDrives', 'de'); // -> null
181
+ getOutfittingFamilyName('shieldGenerators', 'de'); // -> "Schildgeneratoren"
182
+ getOutfittingFamilyName('xenoScanners', 'de'); // -> null
184
183
  ```
185
184
 
186
185
  The functions return an explicit source value verbatim, so a source-backed spelling may
@@ -189,10 +188,17 @@ catalogues carry English, French, German, Portuguese, Russian and Spanish, each
189
188
  under a bare language tag: a regional or script subtag is dropped (`de-DE` → `de`), and
190
189
  any other language returns `null`.
191
190
 
192
- The same contract covers ship manufacturers, pre-engineered variant names, engineering
193
- group names, experimental-effect descriptions, loadout-slot and restriction labels, and
194
- structured loadout, calculation, SLEF and edit messages. A family whose accepted source
195
- currently supplies only English returns `null` for every non-English locale.
191
+ The same contract covers pre-engineered variant names, experimental-effect names and
192
+ descriptions, loadout-slot and restriction labels, and structured loadout, calculation,
193
+ SLEF and edit messages. A family whose accepted source currently supplies only English
194
+ returns `null` for every non-English locale.
195
+
196
+ **Ship names, manufacturers and engineering groups have no lookup**, because the game
197
+ does not translate them. Hull names and manufacturers are proper nouns — every source
198
+ that publishes a localized ship column publishes the English spelling — so read them
199
+ from the ships catalogue (`getShipBySymbol(symbol)?.name` and `?.manufacturer`). An
200
+ engineering group has no in-game label at all: its menu is headed by the module's own
201
+ outfitting family, so name it with `getOutfittingFamilyName(module.familyId, locale)`.
196
202
 
197
203
  Registry lookups ignore case and surrounding whitespace. The material, commodity and
198
204
  module lookups that resolve one record by symbol or name search their complete registry