Skip to content

fix(cli): serve's ready banner no longer names a config that was not read - #9347

Merged
os-zhuang merged 3 commits into
mainfrom
claude/issue-8978-serve-banner-artifact-row
Aug 17, 2026
Merged

fix(cli): serve's ready banner no longer names a config that was not read#9347
os-zhuang merged 3 commits into
mainfrom
claude/issue-8978-serve-banner-artifact-row

Conversation

@os-zhuang

@os-zhuangos-zhuang commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Fixes#8978

The defect

os serve's ready banner's Config: row printed relativeConfig
unconditionally. relativeConfig is derived from args.config at the top
of run(), before the artifact-fallback branch is decided, so on every
artifact-fallback boot it named a file that was either never read or does
not exist on disk:

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.ts gains an exported pure decision
function, resolveBannerConfigRow, next to the existing
describeRegisteredDriver banner helper:

  • pinnedArtifact set (OS_ARTIFACT_URL) → report it. The resolver's
    display string is already resolved and already redacted for a
    pre-signed URL, so it is safe to print as-is.
  • useArtifactFallback set with no pinnedArtifact (OS_ARTIFACT_PATH,
    the cwd's dist/objectstack.json convention, or an empty/quick-start
    boot) → omit the row. No config was read, and there is no
    safely-redacted display in hand here (OS_ARTIFACT_PATH may itself be a
    credentialed URL) — an absent row beats a nonexistent-file claim or a
    leaked secret.
  • Neither set (the ordinary config-boot path) → report relativeConfig
    exactly as before.

packages/cli/src/utils/format.ts's printServerReady renders whichever
of configFile / artifactSource the caller actually has — a new
Artifact: row (value, then a literal " (OS_ARTIFACT_URL)" suffix) in the
Config: 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_PATH
verbatim risks the same credential-leak class OS_ARTIFACT_URL's resolver
already 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.ts is a
three-way mutually-exclusive hot-file slot this batch, #8985 is held back
until this lands).

The two other relativeConfig readers in serve.ts (:1076's "Loading …"
diagnostic, :1663's orphaned-export warning) are untouched — this PR does
not touch the relativeConfig variable itself, only how the banner call
site 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:

Reverse-verified: committed the fix, reverted only
packages/cli/src/commands/serve.ts and packages/cli/src/utils/format.ts
to origin/main (tests untouched), ran the two new test files — 7 of 8
cases failed (resolveBannerConfigRow is not a function; the printServerReady
"omits both rows" case asserted Config: undefined was printed instead of
nothing). Restored the fix from the commit; all 8 pass.

Gates run locally

  • pnpm check:cross-package-test-inputs — OK
  • node scripts/check-cross-package-test-inputs.mjs — OK
  • node 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 artifactSource symbol — the pre-existing MetadataPlugin
    config option, not this PR's new ServerReadyOptions.artifactSource
    field — no doc drift)
  • Convention-triggered (new test files): 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 OK
  • pnpm --filter '@objectstack/cli' typecheck — clean
  • pnpm --filter '@objectstack/cli' test — 126 files / 1375 tests pass

Merged current origin/main in (no churn on the two target files;
packages/spec moved on the other side — rebuilt it, check:generated
still all up to date, then rebuilt @objectstack/cli's dependency closure
and 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: Claude only.

Generated by Claude Code

)
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>
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/cli, touching 5 documentable anchor(s).

2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/deployment/environment-variables.mdx(via artifactSource (symbol))
  • content/docs/protocol/kernel/metadata-service.mdx(via artifactSource (symbol))

1 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/implementation-status.mdx(via artifactSource (symbol))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see

Coarse fallback — 22 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json origin/mainpackageMentionDocs.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Aug 17, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 17, 2026 15:39
@os-zhuang
os-zhuang added this pull request to the merge queueAug 17, 2026
@github-merge-queue
github-merge-queueBot removed this pull request from the merge queue due to failed status checks Aug 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 32043024511 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

失败的 job(日志抽取,best effort):

  • Test Core — 失败步骤: Set up job(日志不可读,点进 job 看)

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 2 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 在其他 PR 的同类评论里搜同名测试;出现过 ⇒ flaky 实锤,开 issue 修/隔离那条测试。修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

@claude

claudeBot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Queue-eviction triage — infrastructure, not a regression. Re-queue is warranted, and is being sequenced rather than fired immediately.

PM seat, session session_012WKSnqAaoqtW3QX7SSf1Vk. Recording the signature before acting, per the re-queue discipline.

Signature

Queue build 32043024511: 13 of 14 jobs succeeded. The single failure is Test Core, and its failing step is Set up job — before any test body ran:

Download action repository 'actions/download-artifact@v8' (SHA:3e5f45b2…)
##[warning]Failed to download action … 429 (Too Many Requests) ×3
##[error]Failed to download archive … after 3 attempts.

Which triage branch this is

Running the workflow's own checklist, none of its three branches fit, and that is informative rather than ambiguous:

  1. Failing test in a package this PR changed? No test executed at all.
  2. Unrelated failing test? Same — the job never reached one.
  3. Semantic conflict with a batch sibling? No; the runner failed to assemble the job.

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

codeload.github.com has been 429-ing action downloads repo-wide for roughly the last half hour. The same signature hit six distinct jobs across four PRs in that window — lycheeverse/lychee-action, CodelyTV/pr-size-labeler, actions/labeler, and actions/download-artifact twice — each dying in Prepare all required actions. Unrelated branches (dependabot, #9318) show it too, and GitHub's own API returned 502/503 during the same period. On #9341 the identical failures cleared on a spaced re-run once the window passed.

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 97db3f31e, and the eviction carries no information about the diff.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[finding] serve's ready banner prints Config: objectstack.config.ts on an OS_ARTIFACT_URL boot, where no config was loaded

2 participants

@os-zhuang@claude