A preview of a pull dies at boot when the production data copied into it is newer than the pull's build, and that — not the change — is what makes a good pull red.
Pull #29's preview never answered: the log reads data: copied from production, then ForgeError: database is at schema 22, this build only knows 21 - refusing to run, then start: exited with code 1 before answering. The pull is red for a migration that landed on main after it branched, and the studio calls it stopped. ensureEnvData (src/apps/data.ts) seeds every fresh preview from production's data directory, so any app whose state has migrated ahead of a pull's build cannot come up — the forge does this to itself on every pull that predates a migration. The direction asks that a change be visible in its preview within seconds of each push; this is the case where it is never visible at all.
The deploy already fails well. What it does not do is try the one obvious thing: the same commit, on empty data.
Done looks like
[ ] A preview whose process exits before answering, when its data directory was seeded from production, is brought up once more on a fresh empty data directory for that environment; a preview that was already seeded empty is not retried.
[ ] The run log says it plainly — the copied data was not usable by this build, the preview is starting on empty data — with the first failure's last output kept above it.
[ ] At most one retry, inside the same deploy run. A second failure fails the run as today, and the summary names the first failure's reason too.
[ ] servingAt on a preview that came up on the retry is the retry's swap-in, and the previous deployment keeps serving until then: the serve-before-tests path is otherwise untouched.
[ ] The discarded copy is removed rather than left beside the new directory, and nothing outside that environment's data directory is written.
[ ] Production is never retried this way: a production deploy that cannot read its own data fails loudly and the previous deployment keeps serving.
[ ] Tests in test/apps.test.ts: a fake app that exits non-zero when a marker file is present in its data dir (the copy carries the marker, a fresh dir does not) comes up on the retry and its run ends ok; an app that always exits retries exactly once and ends failed; the same app in production never retries.
[ ] docs/APPS.md gains the sentence beside the existing preview-data paragraph.
Files I expect to change
src/apps/data.ts (the seed outcome has to say how it was seeded), src/apps/runtime.ts (bringUp/execute), test/apps.test.ts, docs/APPS.md.
Risks
A retry loop: bound it to one attempt per deploy run in code, not by convention.
Discarding something wanted: only a copied preview directory may be dropped, and only when the process never answered.
Hiding a real crash: a genuinely broken app now takes twice as long to fail, so the log must make both attempts obvious.
Suggested: Mason — this is the apps runtime's own correctness, on a path that has no test today.
A preview of a pull dies at boot when the production data copied into it is newer than the pull's build, and that — not the change — is what makes a good pull red.
Pull #29's preview never answered: the log reads
data: copied from production, thenForgeError: database is at schema 22, this build only knows 21 - refusing to run, thenstart: exited with code 1 before answering. The pull is red for a migration that landed on main after it branched, and the studio calls it stopped.ensureEnvData(src/apps/data.ts) seeds every fresh preview from production's data directory, so any app whose state has migrated ahead of a pull's build cannot come up — the forge does this to itself on every pull that predates a migration. The direction asks that a change be visible in its preview within seconds of each push; this is the case where it is never visible at all.The deploy already fails well. What it does not do is try the one obvious thing: the same commit, on empty data.
Done looks like
servingAton a preview that came up on the retry is the retry's swap-in, and the previous deployment keeps serving until then: the serve-before-tests path is otherwise untouched.test/apps.test.ts: a fake app that exits non-zero when a marker file is present in its data dir (the copy carries the marker, a fresh dir does not) comes up on the retry and its run endsok; an app that always exits retries exactly once and endsfailed; the same app in production never retries.docs/APPS.mdgains the sentence beside the existing preview-data paragraph.Files I expect to change
src/apps/data.ts(the seed outcome has to say how it was seeded),src/apps/runtime.ts(bringUp/execute),test/apps.test.ts,docs/APPS.md.Risks
Suggested: Mason — this is the apps runtime's own correctness, on a path that has no test today.