There are definitely parts for that in the DLL.
Consts.py
Stability.py
DynamicCivs.py
RiseAndFall.py
RFCUtils.py
Victory.py
EntryPoints\CvRandomEventInterface.py
It's in the DLL, based on the position in the XML files.

if (!bStateReligion && !bOrStateReligion && getCivics((CivicOptionTypes)4) != CIVIC_SECULARISM)
{
return false;
}
Code from CvPlayer::canConstruct():
Code:if (!bStateReligion && !bOrStateReligion && getCivics((CivicOptionTypes)4) != CIVIC_SECULARISM) { return false; }

CIVIC_SECULARISM is the DLL constant which matches the ordering of civics in the XML (in DoC). You did not reorder civics or add some in between in the XML right? This applies regardless of how civics are ordered in their category.

Then I'm out of ideas. You could look into CvEnums.h with Visual Studio and confirm that the value of CIVIC_SECULARISM (mouse over tooltip) equals the output of GC.getInfoTypeForString("CIVIC_SECULARISM") in the ingame Python console.

You do.
A lot of things, generally you can follow the old version of the new civ guide for DoC, most of it should apply to SoI as well.