Uh oh!
There was an error while loading. Please reload this page.
fix(cli): serve's ready banner no longer names a config that was not read - #9347
Conversation
) serve's Config: row printed relativeConfig unconditionally, computed before the artifact-fallback branch was decided. On an OS_ARTIFACT_URL boot the objectstack.config.ts in cwd is deliberately never executed; on the plain artifact-fallback path (no config authored, booting from dist/objectstack.json) the row named a config file that does not exist on disk at all. Both are the same defect: the row is what an operator reads to answer "what is this container actually running". resolveBannerConfigRow (serve.ts) now decides what the row should say: report the resolved artifact's already-redacted display when OS_ARTIFACT_URL pinned one, omit the row entirely on the other artifact-fallback paths (no safely-redacted value is in hand there), and report the config exactly as before on the ordinary boot path. printServerReady (format.ts) renders whichever of configFile / artifactSource the caller actually has. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…ve-banner-artifact-row
📓 Docs Drift CheckThis PR changes 1 package(s): 2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not seeCoarse fallback — 22 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop):
|
Uh oh!
There was an error while loading. Please reload this page.
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 32043024511 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 失败的 job(日志抽取,best effort):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Queue-eviction triage — infrastructure, not a regression. Re-queue is warranted, and is being sequenced rather than fired immediately.PM seat, session SignatureQueue build 32043024511: 13 of 14 jobs succeeded. The single failure is Which triage branch this isRunning the workflow's own checklist, none of its three branches fit, and that is informative rather than ambiguous:
This is the fourth shape: a setup-phase infrastructure failure, which is the one case where re-running is the fix rather than an excuse, because nothing about this PR's content was ever exercised. Why this is confidently environmental
Action⛔ Not re-queuing this instant.#9341 is in the queue with its build in progress, and the triage workflow is right that a blind re-queue rebuilds every PR behind it. Firing a second entry into an active 429 window risks paying that cost for nothing. ⇒ Re-queue once #9341's queue build resolves, giving the window more time to clear. If the same setup-phase signature recurs after that, it stops being a re-queue case and gets escalated as a repo-wide CI availability problem rather than retried a third time. ⛔ No change is being pushed to this PR: all five required checks are green on Generated by Claude Code |
Fixes#8978
The defect
os serve's ready banner'sConfig:row printedrelativeConfigunconditionally.
relativeConfigis derived fromargs.configat the topof
run(), before the artifact-fallback branch is decided, so on everyartifact-fallback boot it named a file that was either never read or does
not exist on disk:
OS_ARTIFACT_URLboot (Artifact-pinned boot: OS_ARTIFACT_URL (+ OS_ARTIFACT_SHA256) — boot a stack from a published artifact by reference #8368) — theobjectstack.config.tsin cwd isdeliberately never executed; the boot diagnostics say so a few lines above
the banner, but the banner still named it.
OS_ARTIFACT_PATHor the cwd'sdist/objectstack.jsonconvention) — therow named a config file that does not exist at all.
The banner is the surface an operator reads to answer "what is this
container actually running", and naming what did NOT boot points them at
the wrong app (cloud#1292).
The fix
packages/cli/src/commands/serve.tsgains an exported pure decisionfunction,
resolveBannerConfigRow, next to the existingdescribeRegisteredDriverbanner helper:pinnedArtifactset (OS_ARTIFACT_URL) → report it. The resolver'sdisplaystring is already resolved and already redacted for apre-signed URL, so it is safe to print as-is.
useArtifactFallbackset with nopinnedArtifact(OS_ARTIFACT_PATH,the cwd's
dist/objectstack.jsonconvention, or an empty/quick-startboot) → omit the row. No config was read, and there is no
safely-redacted display in hand here (
OS_ARTIFACT_PATHmay itself be acredentialed URL) — an absent row beats a nonexistent-file claim or a
leaked secret.
relativeConfigexactly as before.
packages/cli/src/utils/format.ts'sprintServerReadyrenders whicheverof
configFile/artifactSourcethe caller actually has — a newArtifact:row (value, then a literal " (OS_ARTIFACT_URL)" suffix) in theConfig:row's slot, or no row at all.Chose "report the artifact, or omit" over "always report something" for the
plain artifact-fallback path specifically because printing
OS_ARTIFACT_PATHverbatim risks the same credential-leak class
OS_ARTIFACT_URL's resolveralready guards against, and nothing upstream of the banner call site
currently produces a redacted display for that path — computing one safely
was judged out of scope for this card (tight diff;
serve.tsis athree-way mutually-exclusive hot-file slot this batch, #8985 is held back
until this lands).
The two other
relativeConfigreaders inserve.ts(:1076's "Loading …"diagnostic,
:1663's orphaned-export warning) are untouched — this PR doesnot touch the
relativeConfigvariable itself, only how the banner callsite derives what to pass to
printServerReady.Tests
Both new test files pin the banner assertion the card requires, at the two
layers the fix touches:
packages/cli/src/commands/serve-banner-config-row.test.ts— pinsresolveBannerConfigRowagainst every boot shape (ordinary config boot,OS_ARTIFACT_URL, plain artifact-fallback, empty/quick-start boot).packages/cli/src/utils/format.config-artifact-row.test.ts— pinsprintServerReady's own rendering of the row (capturesconsole.error,ANSI-stripped, same pattern as the CLI 启动 banner 的
Tenancy:读布尔 multiTenant,与 ADR-0105 D1 的权威 knobOS_TENANCY_POSTURE对不上——isolated 会显示成 single-tenant #4801Tenancy:row test), so a futureedit to either function cannot silently reintroduce the
always-print-
configFilebug.Reverse-verified: committed the fix, reverted only
packages/cli/src/commands/serve.tsandpackages/cli/src/utils/format.tsto
origin/main(tests untouched), ran the two new test files — 7 of 8cases failed (
resolveBannerConfigRow is not a function; theprintServerReady"omits both rows" case asserted
Config: undefinedwas printed instead ofnothing). Restored the fix from the commit; all 8 pass.
Gates run locally
pnpm check:cross-package-test-inputs— OKnode scripts/check-cross-package-test-inputs.mjs— OKnode scripts/docs-audit/check-affected-docs.mjs— OK (self-test only,advisory job; the real mapper flags 2 non-release docs via a same-named
but unrelated
artifactSourcesymbol — the pre-existingMetadataPluginconfig option, not this PR's new
ServerReadyOptions.artifactSourcefield — no doc drift)
pnpm check:query-options-erasure,pnpm check:type-check-coverage,pnpm check:type-check-debt(
--re-measure, full workspace closure built first),pnpm check:engine-double-contract,pnpm check:where-matcher— all OKpnpm --filter '@objectstack/cli' typecheck— cleanpnpm --filter '@objectstack/cli' test— 126 files / 1375 tests passMerged current
origin/mainin (no churn on the two target files;packages/specmoved on the other side — rebuilt it,check:generatedstill all up to date, then rebuilt
@objectstack/cli's dependency closureand re-ran the full cli suite and the debt re-measure gate on the merged
tree).
Changeset
.changeset/serve-banner-artifact-row.md— patch on@objectstack/cli.Zone 1 rule 5 followed: no model identifier anywhere in this diff, commit
messages, or this PR —
Co-Authored-By: Claudeonly.Generated by Claude Code