diff --git a/CaloConditions/inc/CalCombinedEnergyCalibStatus.hh b/CaloConditions/inc/CalCombinedEnergyCalibStatus.hh
new file mode 100644
index 0000000000..445a6610b4
--- /dev/null
+++ b/CaloConditions/inc/CalCombinedEnergyCalibStatus.hh
@@ -0,0 +1,45 @@
+#ifndef CaloConditions_CalCombinedEnergyCalibStatus_hh
+#define CaloConditions_CalCombinedEnergyCalibStatus_hh
+
+//
+// Status codes for combined calorimeter energy calibrations.
+//
+// 0   - updated: cosmic + source, consistent
+// 1   - fallback: methods inconsistent, kept old value
+// 2   - fallback: all methods statistically invalid
+// 101 - updated using cosmic only
+// 102 - updated using source only
+//
+
+namespace mu2e {
+
+namespace CalCombinedEnergyCalibStatus {
+
+constexpr int Updated = 0;
+constexpr int FallbackInconsistentMethods = 1;
+constexpr int FallbackAllMethodsInvalid = 2;
+constexpr int UpdatedUsingCosmicOnly = 101;
+constexpr int UpdatedUsingSourceOnly = 102;
+
+inline const char* description(int statusCode) {
+  switch (statusCode) {
+    case Updated:
+      return "updated: cosmic + source, consistent";
+    case FallbackInconsistentMethods:
+      return "fallback: methods inconsistent, kept old value";
+    case FallbackAllMethodsInvalid:
+      return "fallback: all methods statistically invalid";
+    case UpdatedUsingCosmicOnly:
+      return "updated using cosmic only";
+    case UpdatedUsingSourceOnly:
+      return "updated using source only";
+    default:
+      return "unknown status";
+  }
+}
+
+}  // namespace CalCombinedEnergyCalibStatus
+
+}  // namespace mu2e
+
+#endif
diff --git a/DbTables/inc/CalCombinedEnergyCalib.hh b/DbTables/inc/CalCombinedEnergyCalib.hh
new file mode 100644
index 0000000000..794ceba211
--- /dev/null
+++ b/DbTables/inc/CalCombinedEnergyCalib.hh
@@ -0,0 +1,104 @@
+#ifndef DbTables_CalCombinedEnergyCalib_hh
+#define DbTables_CalCombinedEnergyCalib_hh
+
+/*
+  Per-SiPM combined calibration metadata table.
+  Stores the combined ADC/MeV constants, uncertainties, and status flags
+  from the cosmic + source calibration combination algorithm.
+
+  Status-code values and descriptions are defined in:
+    Offline/CaloConditions/inc/CalCombinedEnergyCalibStatus.hh
+
+  Author: W. Zhou 2025
+*/
+
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <vector>
+#include "cetlib_except/exception.h"
+#include "Offline/CaloConditions/inc/CalCombinedEnergyCalibStatus.hh"
+#include "Offline/DbTables/inc/DbTable.hh"
+#include "Offline/DataProducts/inc/CaloSiPMId.hh"
+#include "Offline/DataProducts/inc/CaloConst.hh"
+
+namespace mu2e {
+
+class CalCombinedEnergyCalib : public DbTable {
+ public:
+  typedef std::shared_ptr<CalCombinedEnergyCalib> ptr_t;
+  typedef std::shared_ptr<const CalCombinedEnergyCalib> cptr_t;
+
+  class Row {
+   public:
+    Row(CaloSiPMId roid, float ADC2MeV, float ADC2MeV_err,
+        int status_code, const std::string& status_message)
+        : _roid(roid),
+          _ADC2MeV(ADC2MeV),
+          _ADC2MeV_err(ADC2MeV_err),
+          _status_code(status_code),
+          _status_message(status_message) {}
+
+    CaloSiPMId roid() const { return _roid; }
+    float ADC2MeV() const { return _ADC2MeV; }
+    float ADC2MeV_err() const { return _ADC2MeV_err; }
+    int status_code() const { return _status_code; }
+    std::string status_message() const { return _status_message; }
+
+   private:
+    CaloSiPMId _roid;
+    float _ADC2MeV;
+    float _ADC2MeV_err;
+    int _status_code;
+    std::string _status_message;
+  };
+
+  constexpr static const char* cxname = "CalCombinedEnergyCalib";
+
+  CalCombinedEnergyCalib()
+      : DbTable(cxname, "cal.combinedenergycalib",
+                "roid,adc2mev,adc2mev_err,status_code,status_message") {}
+
+  const Row& row(CaloSiPMId roid) const { return _rows.at(roid.id()); }
+  std::vector<Row> const& rows() const { return _rows; }
+  std::size_t nrow() const override { return _rows.size(); }
+  size_t size() const override { return baseSize() + nrow() * sizeof(Row); }
+  virtual std::size_t nrowFix() const override { return CaloConst::_nChannelDB; }
+  const std::string orderBy() const { return std::string("roid"); }
+
+  void addRow(const std::vector<std::string>& columns) override {
+    std::uint16_t index = std::stoul(columns[0]);
+    // enforce order, so channels can be looked up by index
+    if (index >= CaloConst::_nChannelDB || index != _rows.size()) {
+      throw cet::exception("CALCOMBINEDENERGYCALIB_BAD_INDEX")
+          << "CalCombinedEnergyCalib::addRow found index out of order: "
+          << index
+          << " != " << _rows.size() << "\n";
+    }
+    _rows.emplace_back(CaloSiPMId(index), std::stof(columns[1]),
+                       std::stof(columns[2]), std::stoi(columns[3]),
+                       columns[4]);
+  }
+
+  void rowToCsv(std::ostringstream& sstream, std::size_t irow) const override {
+    Row const& r = _rows.at(irow);
+    sstream << r.roid() << ",";
+    sstream << std::fixed << std::setprecision(5);
+    sstream << r.ADC2MeV() << ",";
+    sstream << r.ADC2MeV_err() << ",";
+    sstream << r.status_code() << ",";
+    sstream << "\"" << r.status_message() << "\"";
+  }
+
+  virtual void clear() override {
+    baseClear();
+    _rows.clear();
+  }
+
+ private:
+  std::vector<Row> _rows;
+};
+
+}  // namespace mu2e
+
+#endif
diff --git a/DbTables/inc/CalCosmicEnergyCalibInfo.hh b/DbTables/inc/CalCosmicEnergyCalibInfo.hh
index 2df1741a6b..d97bea0d85 100644
--- a/DbTables/inc/CalCosmicEnergyCalibInfo.hh
+++ b/DbTables/inc/CalCosmicEnergyCalibInfo.hh
@@ -13,7 +13,9 @@ class CalCosmicEnergyCalibInfo : public DbTable {
  public:
   class Row {
    public:
-    Row(int cID, int FirstCalibRun, int LastCalibRun, std::string EnergyMethod, std::string FitMethod, std::string Comment) :
+    Row(int cID, int FirstCalibRun, int LastCalibRun,
+        const std::string& EnergyMethod, const std::string& FitMethod,
+        const std::string& Comment) :
         _cID(cID),
         _FirstCalibRun(FirstCalibRun),
         _LastCalibRun(LastCalibRun),
diff --git a/DbTables/inc/CalEnergyCalibInfo.hh b/DbTables/inc/CalEnergyCalibInfo.hh
new file mode 100644
index 0000000000..f89873c625
--- /dev/null
+++ b/DbTables/inc/CalEnergyCalibInfo.hh
@@ -0,0 +1,75 @@
+#ifndef DbTables_CalEnergyCalibInfo_hh
+#define DbTables_CalEnergyCalibInfo_hh
+
+//
+// Ad-hoc table linking a CalEnergyCalib CID to the matching
+// CalCombinedEnergyCalib CID produced by the same combination pass.
+//
+
+#include "Offline/DbTables/inc/DbTable.hh"
+#include "cetlib_except/exception.h"
+#include <sstream>
+#include <string>
+
+namespace mu2e {
+
+class CalEnergyCalibInfo : public DbTable {
+ public:
+  class Row {
+   public:
+    Row(int energyCalibCid, int combinedEnergyCalibCid,
+        const std::string& comment) :
+        _energyCalibCid(energyCalibCid),
+        _combinedEnergyCalibCid(combinedEnergyCalibCid),
+        _comment(comment) {}
+
+    int energyCalibCid() const { return _energyCalibCid; }
+    int combinedEnergyCalibCid() const { return _combinedEnergyCalibCid; }
+    std::string comment() const { return _comment; }
+
+   private:
+    int _energyCalibCid;
+    int _combinedEnergyCalibCid;
+    std::string _comment;
+  };
+
+  constexpr static const char* cxname = "CalEnergyCalibInfo";
+
+  CalEnergyCalibInfo() :
+      DbTable(cxname, "cal.energycalibinfo",
+              "energycalibcid,combinedenergycalibcid,comment") {}
+
+  const Row& rowAt(const std::size_t index) const { return _rows.at(index); }
+  std::vector<Row> const& rows() const { return _rows; }
+  std::size_t nrow() const override { return _rows.size(); }
+  size_t size() const override { return baseSize() + nrow() * sizeof(Row); }
+  tableType type() const override { return Adhoc; }
+
+  void addRow(const std::vector<std::string>& columns) override {
+    if (columns.size() < 3) {
+      throw cet::exception("CALENERGYCALIBINFO_BAD_COLUMNS")
+          << "CalEnergyCalibInfo::addRow expected at least 3 columns, got "
+          << columns.size() << "\n";
+    }
+    _rows.emplace_back(std::stoi(columns[0]), std::stoi(columns[1]),
+                       columns[2]);
+  }
+
+  void rowToCsv(std::ostringstream& sstream, std::size_t irow) const override {
+    Row const& r = _rows.at(irow);
+    sstream << r.energyCalibCid() << ",";
+    sstream << r.combinedEnergyCalibCid() << ",";
+    sstream << "\"" << r.comment() << "\"";
+  }
+
+  virtual void clear() override {
+    baseClear();
+    _rows.clear();
+  }
+
+ private:
+  std::vector<Row> _rows;
+};
+
+}  // namespace mu2e
+#endif
diff --git a/DbTables/inc/CalSourceEnergyCalib.hh b/DbTables/inc/CalSourceEnergyCalib.hh
index 89211d298f..92e940a545 100644
--- a/DbTables/inc/CalSourceEnergyCalib.hh
+++ b/DbTables/inc/CalSourceEnergyCalib.hh
@@ -16,7 +16,7 @@ namespace mu2e {
 
     class Row {
     public:
-      Row(CaloSiPMId roid, float fullEPeak,float fullErrEPeak,float fullWidth,float fullErrWidth,float firstescEPeak,float firstescErrEPeak,float firstescWidth,float firstescErrWidth,float secescEPeak,float secescErrEPeak,float secescWidth,float secescErrWidth, float frFull, float frFirst, float frSecond, float chisq): _roid(roid), _fullEPeak(fullEPeak), _fullErrEPeak(fullErrEPeak), _fullWidth(fullWidth), _fullErrWidth(fullErrWidth),_firstescEPeak(firstescEPeak), _firstescErrEPeak(firstescErrEPeak), _firstescWidth(firstescWidth), _firstescErrWidth(firstescErrWidth),_secescEPeak(secescEPeak), _secescErrEPeak(secescErrEPeak), _secescWidth(secescWidth), _secescErrWidth(secescErrWidth), _frFull(frFull), _frFirst(frFirst), _frSecond(frSecond), _chisq(chisq){}
+      Row(CaloSiPMId roid, float fullEPeak,float fullErrEPeak,float fullWidth,float fullErrWidth,float firstescEPeak,float firstescErrEPeak,float firstescWidth,float firstescErrWidth,float secescEPeak,float secescErrEPeak,float secescWidth,float secescErrWidth, float frFull, float frFirst, float frSecond, float chisq, int ndf): _roid(roid), _fullEPeak(fullEPeak), _fullErrEPeak(fullErrEPeak), _fullWidth(fullWidth), _fullErrWidth(fullErrWidth),_firstescEPeak(firstescEPeak), _firstescErrEPeak(firstescErrEPeak), _firstescWidth(firstescWidth), _firstescErrWidth(firstescErrWidth),_secescEPeak(secescEPeak), _secescErrEPeak(secescErrEPeak), _secescWidth(secescWidth), _secescErrWidth(secescErrWidth), _frFull(frFull), _frFirst(frFirst), _frSecond(frSecond), _chisq(chisq), _ndf(ndf){}
 
       CaloSiPMId  roid() const { return _roid;}
       float fullEPeak() const { return _fullEPeak; }
@@ -39,6 +39,7 @@ namespace mu2e {
       float frSecond() const { return _frSecond; }
 
       float chisq() const { return _chisq; }
+      int ndf() const { return _ndf; }
 
     private:
       CaloSiPMId  _roid;
@@ -58,11 +59,12 @@ namespace mu2e {
       float _frFirst;
       float _frSecond;
       float _chisq;
+      int _ndf;
     };
 
     constexpr static const char* cxname = "CalSourceEnergyCalib";
 
-    CalSourceEnergyCalib():DbTable(cxname,"cal.sourceenergycalib","roid,fullepeak,fullerrepeak,fullwidth,fullerrwidth,firstescepeak,firstescerrepeak,firstescwidth,firstescerrwidth,secescepeak,secescerrepeak,secescwidth,secescerrwidth, frfull,frfirst,frsecond,chisq"){}
+    CalSourceEnergyCalib():DbTable(cxname,"cal.sourceenergycalib","roid,fullepeak,fullerrepeak,fullwidth,fullerrwidth,firstescepeak,firstescerrepeak,firstescwidth,firstescerrwidth,secescepeak,secescerrepeak,secescwidth,secescerrwidth,frfull,frfirst,frsecond,chisq,ndf"){}
 
     const Row& row(CaloSiPMId  roid) const {
                 return _rows.at(roid.id()); }
@@ -82,7 +84,7 @@ namespace mu2e {
        _rows.emplace_back(CaloSiPMId(index),std::stof(columns[1]),std::stof(columns[2]),std::stof(columns[3]),
        std::stof(columns[4]),std::stof(columns[5]),std::stof(columns[6]),std::stof(columns[7]),
        std::stof(columns[8]),std::stof(columns[9]),std::stof(columns[10]),std::stof(columns[11]),
-       std::stof(columns[12]),std::stof(columns[13]),std::stof(columns[14]),std::stof(columns[15]),std::stof(columns[16]));
+       std::stof(columns[12]),std::stof(columns[13]),std::stof(columns[14]),std::stof(columns[15]),std::stof(columns[16]),std::stoi(columns[17]));
 
     }
 
@@ -102,7 +104,11 @@ namespace mu2e {
       sstream << r.secescErrEPeak()<<",";
       sstream << r.secescWidth()<<",";
       sstream << r.secescErrWidth()<<",";
-      sstream << r.chisq();
+      sstream << r.frFull()<<",";
+      sstream << r.frFirst()<<",";
+      sstream << r.frSecond()<<",";
+      sstream << r.chisq()<<",";
+      sstream << r.ndf();
     }
 
     virtual void clear() override { baseClear(); _rows.clear();}
diff --git a/DbTables/src/DbTableFactory.cc b/DbTables/src/DbTableFactory.cc
index f49459c491..2e6bd545fe 100644
--- a/DbTables/src/DbTableFactory.cc
+++ b/DbTables/src/DbTableFactory.cc
@@ -14,6 +14,8 @@
 #include "Offline/DbTables/inc/CalSourceEnergyCalib.hh"
 #include "Offline/DbTables/inc/CalCosmicEnergyCalib.hh"
 #include "Offline/DbTables/inc/CalCosmicEnergyCalibInfo.hh"
+#include "Offline/DbTables/inc/CalCombinedEnergyCalib.hh"
+#include "Offline/DbTables/inc/CalEnergyCalibInfo.hh"
 #include "Offline/DbTables/inc/CalLaserEnergyCalib.hh"
 #include "Offline/DbTables/inc/CalLaserTimeCalib.hh"
 #include "Offline/DbTables/inc/CalLaserRuns.hh"
@@ -114,6 +116,10 @@ mu2e::DbTable::ptr_t mu2e::DbTableFactory::newTable(std::string const& name) {
     return std::shared_ptr<mu2e::DbTable>(new mu2e::CalLaserRuns());
   } else if (name=="CalEnergyCalib") {
     return std::shared_ptr<mu2e::DbTable>(new mu2e::CalEnergyCalib());
+  } else if (name=="CalCombinedEnergyCalib") {
+    return std::shared_ptr<mu2e::DbTable>(new mu2e::CalCombinedEnergyCalib());
+  } else if (name=="CalEnergyCalibInfo") {
+    return std::shared_ptr<mu2e::DbTable>(new mu2e::CalEnergyCalibInfo());
   } else if (name=="CalTimeCalib") {
     return std::shared_ptr<mu2e::DbTable>(new mu2e::CalTimeCalib());
   } else if (name=="CalCosmicT0Align") {
