@girish apologies, I jumped the gun on that last post. You were right.
I had a look at the box source code (src/scheduler.js, src/docker.js) and the manifest command IS respected by the scheduler. The php artisan schedule:run on my instance came from a custom crontab entry carried over when we migrated from a standalone install to Cloudron over 2 years ago. That entry must have slipped through unnoticed, but it explains everything.
After removing it, the scheduler container (now suffixed -housekeeping instead of -crontab.0) correctly runs cron.sh:
$ docker inspect --format '{{.Config.Cmd}}' 1af144bb-fbf4-434d-8edd-bb4b95c00ef5-housekeeping
Cmd: [/bin/sh -c /app/pkg/cron.sh]
Things are working correctly with cron.sh + gosu now
I should have caught this sooner. In my defense (barely), the Cron tab of the app doesn't mention that commands run as root. I eventually found it in the documentation at the bottom of the Cron page. A small note in the Cron tab itself would probably help others avoid the same mistake.
Cheers,
JD