Found while fixing objectstack-ai/hotclm#49 (merged as 2807b3b), on @objectstack/* 17.4.0. Filed at the destination per that repo's AGENTS.md — report, never patch. ⛔ Not triaged: no domain:*, no priority, no assignee.
Adjacent to but distinct from #17177: that card is about the loader's summary contradicting the database. This one is about timing — when the boot is actually finished.
Symptom, with the clock
An app script spawns os dev with stdio: 'inherit' and wants to print one line after the boot, where the terminal comes to rest. There is no signal that says when that is. Measured on one run:
07:03:46.862 WARN [Seeder] Inline seed exceeded 8000ms budget … continuing in background
07:03:48 ✓ Server is ready · Press Ctrl+C to stop
07:05:09.768 ERROR [SeedLoader] … 120 lines, from the background continuation
07:05:09.827 WARN [Seeder] Seed loading completed with … dropped record(s) and … error(s)
82 seconds of silence after the banner, then 120 error lines. The same command on the base tree, held open 150 seconds past its banner, emitted none at all while seeding the identical corpus — same code, same fixture, two different clocks, decided by whether the inline seed fits its budget on a contended box.
Why an app cannot work around it
Everything that would distinguish the two cases — the WARN about the budget, the error wall, the completion summary — arrives in the child's inherited stream. A parent that only spawns and waits has no readable signal. The available workarounds are each worse than the problem:
- Pipe the child's stdout to detect quiescence → costs the boot its TTY, and the
ERROR lines arrive dimmed by the very edit meant to explain them.
- Poll a completion endpoint → puts an authenticated dependency into a demo script to work around a timing quirk.
- Print twice → tells the reader the same thing in two places and still guesses.
objectstack-ai/hotclm took none of them: its note now names which clock puts the errors above it and which puts them below, and is the frame either way. That works, but it is a repo writing prose around a missing signal.
What is missing
A readable "the boot has finished, including deferred seeding" signal that a parent process can wait on without owning the child's stdout. ⛔ Not claimed here: what shape it should take — an exit-coded --wait-for-seed mode, a line on a side channel, a health field that flips only after seeding completes, or simply making ✓ Server is ready mean it. That is the platform's call.
⚠️ Worth deciding alongside: whether ✓ Server is ready should print before seeding finishes at all. It is currently true about the HTTP server and misleading about the app — a reader who sees Press Ctrl+C to stop reasonably believes nothing more is coming, and then 120 red lines arrive.
Reproduce
git clone https://github.com/objectstack-ai/hotclm && cd hotclm && pnpm install
rm -rf .objectstack dist
pnpm demo # watch for: WARN [Seeder] … continuing in background
# then hold the terminal open ≥2 minutes past the banner
On a box where the inline seed fits its budget the errors precede the banner and the problem is invisible — which is why it went unnoticed until two runs on different containers disagreed.
Related
hotclm#49 / hotclm PR #51 (the consumer that hit it and the prose workaround it shipped) · hotclm#45 (the dogfood pass that saw the other clock) · #17177 (the loader summary contradicting the database — same subsystem, different defect)
Found while fixing
objectstack-ai/hotclm#49(merged as2807b3b), on@objectstack/*17.4.0. Filed at the destination per that repo'sAGENTS.md— report, never patch. ⛔ Not triaged: nodomain:*, no priority, no assignee.Adjacent to but distinct from #17177: that card is about the loader's summary contradicting the database. This one is about timing — when the boot is actually finished.
Symptom, with the clock
An app script spawns
os devwithstdio: 'inherit'and wants to print one line after the boot, where the terminal comes to rest. There is no signal that says when that is. Measured on one run:82 seconds of silence after the banner, then 120 error lines. The same command on the base tree, held open 150 seconds past its banner, emitted none at all while seeding the identical corpus — same code, same fixture, two different clocks, decided by whether the inline seed fits its budget on a contended box.
Why an app cannot work around it
Everything that would distinguish the two cases — the
WARNabout the budget, the error wall, the completion summary — arrives in the child's inherited stream. A parent that only spawns and waits has no readable signal. The available workarounds are each worse than the problem:ERRORlines arrive dimmed by the very edit meant to explain them.objectstack-ai/hotclmtook none of them: its note now names which clock puts the errors above it and which puts them below, and is the frame either way. That works, but it is a repo writing prose around a missing signal.What is missing
A readable "the boot has finished, including deferred seeding" signal that a parent process can wait on without owning the child's stdout. ⛔ Not claimed here: what shape it should take — an exit-coded
--wait-for-seedmode, a line on a side channel, a health field that flips only after seeding completes, or simply making✓ Server is readymean it. That is the platform's call.✓ Server is readyshould print before seeding finishes at all. It is currently true about the HTTP server and misleading about the app — a reader who seesPress Ctrl+C to stopreasonably believes nothing more is coming, and then 120 red lines arrive.Reproduce
On a box where the inline seed fits its budget the errors precede the banner and the problem is invisible — which is why it went unnoticed until two runs on different containers disagreed.
Related
hotclm#49 / hotclm PR #51 (the consumer that hit it and the prose workaround it shipped) · hotclm#45 (the dogfood pass that saw the other clock) · #17177 (the loader summary contradicting the database — same subsystem, different defect)