So here's the resolution.
I believe the problem was indeed the fact that I didn't roll back the database. This makes sense because in version 2.3.6.7, two columns were added and initialized to 0: mp_Pages PublishMode and mp_Modules PublishMode.
When I upgraded, they surely got initialized properly, but then I downgraded without backing out the schema changes, so further rows got added to the db which weren't aware of the new columns, leaving them null. This ended up being a problem when the code was upgraded again and didn't allow for null values in the new columns.
The solution was to run the update statements for those two columns, setting all values to 0. They were:
UPDATE mp_Pages
SET PublishMode = 0
GO
and:
UPDATE mp_Modules
SET PublishMode = 0
GO
On another note, the reason it took me so long to get back about this is because I was dealing with the significant changes in the html between 2.3.6.5 and 2.3.7.5. Some of it has to do with Artisteer, but there was actually another very significant change that happened to affect my CSS selectors in particular.
I have some custom ways of placing content modules side-by-side in my layout by using floats and display: table-cells. When I first looked at doing it, it seemed like the custom CSS class setting for the content module might do the trick. I was sad to find out, however, that the div with the custom CSS was nested inside a couple other divs within each content module. Since the custom CSS div levels for two content modules weren't at a sibling level, you couldn't use float or table-cell to connect them side-by-side.
So instead, I found that there were module id's at the proper level (#module100, etc) that I could use to control the layout the way I wanted. While this resulted in painfully custom CSS tied to each and every module, there were few enough places which needed it that I could get away with doing so. How I wished that I could have just used the custom CSS class setting in the first place.
The good news is that with 2.3.7.5, the enveloping divs around the custom CSS class div are gone, putting the proper div at sibling level with every other content module. Great!
Unfortunately, all of the module id's are gone! So all of my carefully crafted CSS falls flat on its face. Ouch. So I went through the exercise of figuring out the cause and migrating to custom CSS classes which apply floats and table-cells in the content module settings, and it works like a charm. I'll write a post about how I do it at some point.
However, now I'm concerned that the current html structure may become impermanent as well, in case some of those nasty enclosing divs show up in a future release.
To be more precise, here is an example:
I add HTML content module A. I add a custom CSS class "table-cell" to the module settings, which renders a div with the content inside and marked with the table-cell class.
In my CSS, I define .table-cell to be "display: table-cell".
I then add HTML content module B, appearing right after A. I add the same custom CSS class to the module settings. Now, another div with the content for module B renders with the table-cell class.
Because both content modules are divs with the table-cell class and appear next to each other (siblings) in the tree, all modern browsers with turn them into a row in an "anonymous table", i.e., a table that is created by the browser to imitate the layout of the full set of table, td and tr tags that you'd have to create in HTML otherwise. It's just as if I'd put the content modules within two cells of a table so they could be displayed next to one another, except it requires no markup, just CSS.
Now, if the divs that get the custom CSS class were to move lower in the tree and no longer be siblings, my layout would be blown because table-cells only join when they are right next to each other.
What are the chances of that structure being changed again? Was the custom CSS class setting moved to the outer div of the content module by design and will it stay there in future versions?