Skip to content

feat(cli): os deploy and the os dev d key deploy to a self-hosted runtime remembered by os environments use-runtime - #31137

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-30888-deploy-self-hosted
Nov 7, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-30888-deploy-self-hosted

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by 田騏 · project thread

Fixes #30888

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:新增 os environments use-runtime 地址 --token 密钥,记住一个私有部署的运行时(Docker 社区版或企业版)并设为部署目标;之后 os deploy 和 os dev 里按 d 不带任何参数就部署到它:先构建,再请运行时做一次预演(打印升级计划,含 renamedFrom 声明的改名),然后把构建产物直接装进去,按运行时的 hotLoaded 回答报告是否已生效。os package install 不写 -u/-t 时也用它。
  • 为什么改:私有部署现在每次都要手敲地址和令牌,默认地址 3000 还和官方镜像的 8080 对不上;维护者要求私有部署的发布流程和云端一样顺手(epic cloud#3652)。记住的目标让默认端口问题不再需要改默认值。
  • 风险与回滚:只动 CLI。地址和密钥存在 ~/.objectstack/cloud.json(0600)里独立的一段,云端登录/登出都保留它,密钥只发给它自己的地址。Q3 的「默认拒绝」由 install-local 自己判(Package upgrade plan: one framework comparison of installed vs new version (fields, types, renames, seeds) as a dry run; declared renamedFrom is planned, an undeclared rename or type change is refused unless confirmed (epic cloud#3652 Q3) #30884 第二个 PR 尚未合入),本 PR 只负责把它的拒绝原样打印并以非零退出。回滚 = revert 本 PR。
  • 先看:packages/cli/src/utils/cloud-config.ts(两半存储,登录/登出不丢目标)、packages/cli/src/commands/deploy.ts 的 deployToRuntime、packages/cli/src/utils/runtime-target.ts 的 runtimeInstallTarget(密钥只发给同一地址)。
  • 两分钟验证:pnpm --filter @objectstack/cli exec vitest run --project unit test/deploy.test.ts test/environments-use-runtime.test.ts,预期全部通过,其中「a self-hosted runtime as the active target」一组 8 条。
  • 需要你做的:无,席位落地。

What changes

os environments use-runtime URL --token KEY (new) records a self-hosted runtime and an API key it issued, and makes it the deploy target. The name is a verb beside os environments switch, and "runtime" is the word os package install already uses for this server (OS_RUNTIME_URL / OS_RUNTIME_TOKEN). Before writing, the key is tried with one authenticated GET /api/v1/marketplace/install-local. A rejected key (401/403), a runtime that does not serve the door (404), or one that cannot be reached is refused and nothing is recorded; --no-verify records anyway. --forget drops the record. os environments switch ID, when it records into cloud.json, makes the cloud the target again and keeps the runtime remembered. Whichever ran last wins.

Storage (card item 1: "the same protected file the cloud token uses"). ~/.objectstack/cloud.json (0600) gains a deploy-target half, runtimeTarget: { url, token, recordedAt } and deployTarget: 'cloud' | 'runtime'. It is never read by the cloud credential path. writeCloudConfig carries it across every cloud write, so os cloud login keeps it. deleteCloudConfig keeps it, so os cloud logout clears only the session. A file that holds only the runtime half reads as "not logged in" to the cloud. Only writeDeployTargetRecord changes the half. login.ts and logout.ts are untouched.

os deploy — when a runtime is the active target and --env is not given (card items 2–4):

  1. It builds with compileForDeploy, as the cloud path does.
  2. It asks install-local for a dry run (dryRun: true, from Package upgrade plan: one framework comparison of installed vs new version (fields, types, renames, seeds) as a dry run; declared renamedFrom is planned, an undeclared rename or type change is refused unless confirmed (epic cloud#3652 Q3) #30884 PR 1) and prints the upgrade plan with the same renderer as os package install --dry-run. Declared renamedFrom renames are listed.
  3. It installs the artifact inline. There is no catalog publish and no -dev version. --confirm-access-upgrade FINDING_SET passes through to the install. The flag is refused when the target is the cloud.
  4. It reads the answer. install-local registers the package before it answers, so hotLoaded means live, with exit 0. A package the kernel could not load gives exit 1.

Steps 2–3 run os package install in-process, as the cloud path runs os package publish. Every refusal is printed once, in one place, and the retry lines name os deploy. If the dry run is refused, nothing more is sent. If the runtime answers 404 (a runtime booted from a composed artifact, or one without the door), the deploy names the cause and exits 1. If the runtime predates the dry run, the deploy says so and exits 1.

The d key names the remembered runtime in its offer line and runs the same os deploy with no cloud login prompt.

os package install without -u / $OS_RUNTIME_URL uses the remembered runtime. Without -t / --email it uses that runtime's key, but only when the URL is the runtime's own (isSameControlPlane). The url flag loses its oclif default so that an absent flag can be told from a typed one. With nothing remembered, the URL is still http://localhost:3000. The 404 sentence now names the composed-artifact case.

Item 5 (default port). The remembered target makes it moot, so the default stays http://localhost:3000.

Tests

  • test/deploy.test.ts, new top-level describe "a self-hosted runtime as the active target" (8). Covers: no-flag deploy (dry run, then inline install, plan printed, key sent, no -dev suffix, no cloud call); a dry-run refusal stops before the install; 404 named; runtime predating the dry run; access-upgrade refusal with retry os deploy --confirm-access-upgrade …, and the token passed through on rerun; hotLoaded: false gives exit 1; a failed build installs nothing; the flag refused on the cloud target.
  • test/environments-use-runtime.test.ts (new, 10). Covers: record after probe (0600, cloud session kept, cloud reads never see the key, still "not logged in" without a cloud login); 401 and 404 refused with nothing recorded; --no-verify; URL validation; --forget. For cloud.json: login keeps the runtime target, logout keeps it (and deletes the file when nothing else is left), and switch activates the cloud.
  • test/package-install-url-token-flags.test.ts, new describe (5). Covers: fallback to the remembered runtime and its key; -u to the same runtime keeps the key; -u to another server never gets the key; explicit -t wins; --email never mixes the two; nothing remembered falls back to localhost:3000.
  • test/dev-deploy-key.test.ts, new describe (2). Covers: the runtime offer line, and d deploying with no login; the wiring in startDevDeployKey.
  • Ablation (one-shot): isSameControlPlane(stored.url, url) was replaced with true in runtime-target.ts. The test "-u naming another server never receives the remembered key" went red (1 failed / 13 passed), and the file was restored to its HEAD blob 900b6fe7.

Acceptance notes

Verification

Local gates on head b57c03a (merge base 5f00374; origin/main merged once, already up to date)
pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2 :: exit 0   (397 files / 5603 tests passed)
pnpm --filter @objectstack/cli typecheck :: exit 0   (tsc + check:test-typecheck, NODE_OPTIONS=--max-old-space-size=8192)
eslint packages/cli --no-inline-config :: exit 0
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack :: exit 0   (62 families)
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-adoption.mjs :: exit 0
node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-dts-emitted.mjs --self-test :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-issue-citations.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0
node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0
node scripts/ci/snapshot-next.mjs --self-test :: exit 0
node scripts/docs-audit/check-affected-docs.mjs :: exit 0
node scripts/docs-audit/check-drift-comment.mjs :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:cli-test-child-env :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:dts-closure :: exit 0
pnpm check:dual-build-cjs-loads :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:i18n :: exit 0
pnpm check:i18n-coverage :: exit 0
pnpm check:i18n-walk-parity :: exit 0
pnpm check:issue-citations :: exit 0
pnpm check:keyed-text-bounds :: exit 0
pnpm check:lean-entry-closure :: exit 0
pnpm check:logger-receiver-detach :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:objectql-double-limit :: exit 0
pnpm check:org-identifier :: exit 0
pnpm check:page-declaration-shape :: exit 0
pnpm check:platform-object-tenancy-census :: exit 0
pnpm check:published-files :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:slot-lookup :: exit 0
pnpm check:sourcemap-no-sources-content :: exit 0
pnpm check:system-context-census :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:vouch-for-reference-callers :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran.list :: exit 0   (62 derived, 62 run, 0 NOT-MEASURED)

First passes that exited 3 for a missing prerequisite were rebuilt and rerun (the exit-0 lines above): check-plugin-teardown-shape --self-test (shallow clone, so the pinned control commit was fetched), check:dual-build-cjs-loads, check:i18n, check:i18n-coverage, check:i18n-walk-parity (built output missing, so those packages were built), and check:type-check-debt (lock queue timeout, rerun with a slot). The CLI integration tier is left to CI: the diff touches no spawn entry and no integration-tier file.

Manual check on the Community image

NOT RUN: docker is not available in this container. Steps: docker run -p 8080:8080 ghcr.io/objectstack-ai/objectstack (os start); create an API key in Setup → API Keys; in a fresh scaffold run os environments use-runtime http://localhost:8080 --token KEY, then os dev, press d, edit an object label, press d again, and confirm that GET http://localhost:8080/api/v1/meta/object/NAME serves the second label.

🤖 Generated with Claude Code

@github-actions github-actions Bot added size/xl documentation Improvements or additions to documentation tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 7, 2026
@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

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

  • content/docs/automation/connectors.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts), /api/v1/marketplace/install-local (route, a path literal in PackageInstall; a path literal in a comment on a changed line; a path literal in probeRuntime))
  • content/docs/automation/jobs.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))
  • content/docs/data-modeling/external-datasources.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts), /api/v1/marketplace/install-local (route, a path literal in PackageInstall; a path literal in a comment on a changed line; a path literal in probeRuntime))
  • content/docs/data-modeling/seed-data.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))
  • content/docs/deployment/app-dependencies.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts), /api/v1/marketplace/install-local (route, a path literal in PackageInstall; a path literal in a comment on a changed line; a path literal in probeRuntime))
  • content/docs/deployment/cli.mdx (via OS_RUNTIME_TOKEN (literal, a string literal in flags), os deploy (command, read off packages/cli/src/commands/deploy.ts), os environments switch (command, read off packages/cli/src/commands/environments/switch.ts), os package install (command, read off packages/cli/src/commands/package/install.ts))
  • content/docs/deployment/cloud-connection.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))
  • content/docs/deployment/install-modes.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts), /api/v1/marketplace/install-local (route, a path literal in PackageInstall; a path literal in a comment on a changed line; a path literal in probeRuntime))
  • content/docs/deployment/marketplace-handbook.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts), /api/v1/marketplace/install-local (route, a path literal in PackageInstall; a path literal in a comment on a changed line; a path literal in probeRuntime))
  • content/docs/deployment/publish-and-preview.mdx (via os environments switch (command, read off packages/cli/src/commands/environments/switch.ts), os package install (command, read off packages/cli/src/commands/package/install.ts), /api/v1/marketplace/install-local (route, a path literal in PackageInstall; a path literal in a comment on a changed line; a path literal in probeRuntime))
  • content/docs/protocol/kernel/index.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))
  • content/docs/protocol/kernel/lifecycle.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))
  • content/docs/protocol/kernel/metadata-service.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))
  • content/docs/protocol/kernel/plugin-spec.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))

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

  • content/docs/releases/v17/17-0.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))
  • content/docs/releases/v17/17-6.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))
  • content/docs/releases/v17/17-7.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))
  • content/docs/releases/v18/18-1.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))
  • content/docs/releases/v18/18-2.mdx (via /api/v1/marketplace/install-local (route, a path literal in PackageInstall; a path literal in a comment on a changed line; a path literal in probeRuntime))
  • content/docs/releases/v18/18-3.mdx (via os package install (command, read off packages/cli/src/commands/package/install.ts))

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
  • 8 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 63 of 226 client-bound route-ledger rows — the other 163 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 163: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 59 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 104 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 35 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 cadd6aa280075295619c6a8ab4da75daab8aab94 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from cad134230d33bfe5e2ec29c25df19d1404a062f1 — the merge of head b57c03aa03ab30e9502660953d02fc93accf3d4c into base cadd6aa280075295619c6a8ab4da75daab8aab94, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin cad134230d33bfe5e2ec29c25df19d1404a062f1 && git checkout cad134230d33bfe5e2ec29c25df19d1404a062f1
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin cadd6aa280075295619c6a8ab4da75daab8aab94 b57c03aa03ab30e9502660953d02fc93accf3d4c && git checkout -B drift-repro cadd6aa280075295619c6a8ab4da75daab8aab94 && git merge --no-ff b57c03aa03ab30e9502660953d02fc93accf3d4c

node scripts/docs-audit/affected-docs.mjs --json cadd6aa280075295619c6a8ab4da75daab8aab94

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

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 cadd6aa280075295619c6a8ab4da75daab8aab94 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#4 · marchtian · session_017ihL2dLQEXWGsE2SZ3Qn5F

席位核对 — ACCEPT · domain:server#4 · Head-sha: b57c03aa03ab30e9502660953d02fc93accf3d4c

  • Shape: draft → main, first line attribution, Fixes #30888 once (card fully delivered except the items below), Clause-②: no, Metadata-protocol: none line-initial in body and changeset. 12 files, +1103/−45, all under packages/cli/** + one .changeset (@objectstack/cli patch); no governed path, under the 3000-line threshold.
  • Diff read by the seat: utils/cloud-config.ts (two-half store: writeCloudConfig carries the deploy-target half across, deleteCloudConfig keeps it, a target-only file reads as not logged in), utils/runtime-target.ts (runtimeInstallTarget: the stored key is sent only when isSameControlPlane(stored.url, url); --email turns the stored key off), commands/deploy.ts deployToRuntime (build → PackageInstall --dry-run in-process → install → hotLoaded; non-installed/non-hot answers exit 1; --confirm-access-upgrade refused on the cloud target), environments/switch.ts (flips back to cloud only when recorded into cloud.json). No second copy of target resolution or refusal handling.
  • Gates (check-runs on the head): 48 runs — 35 success, 13 skipped, 0 failed; Lint & Repo Gates success, TypeScript Type Check success. Dev's local dispatch-gates 62/62 exit 0 (report 6707948212).
  • Accepted deviations: manual Community-image check not run (no docker in the dev container; steps recorded in the report); EE composed-mode refusal not measured (cloud repo unreadable, 404 answer named generically); Q3 --confirm-upgrade forward waits on Package upgrade plan: one framework comparison of installed vs new version (fields, types, renames, seeds) as a dry run; declared renamedFrom is planned, an undeclared rename or type change is refused unless confirmed (epic cloud#3652 Q3) #30884 PR 2 (unclaimed) — the deploy stops on any refusal the runtime answers, pinned generically.
  • Out of scope: docs + skills/objectstack-platform follow-up → filed docs + skill: teach os environments use-runtime and the self-hosted os deploy target (follow-up owed by #30888 / PR #31137) #31143. Item 2's cloud-bound-runtime catalog path → Acceptance notes (no pull; the remembered target is self-hosted only). os environments create --activate leaves the deploy target unchanged → Acceptance notes (only switch flips it, by design here).
  • Landing: Tier: none (non-governed). Seat lands: pr_ready + automerge_enable through the relay.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 7, 2026 14:30
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 7, 2026 14:30
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 7, 2026
@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

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

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

分类:failure —— 按下面的日志分诊。

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

  • Test Core (1/8) — 失败步骤: Run this shard's tests

    @objectstack/cli:test:  FAIL   unit  test/platform-page-i18n-parity.test.ts > shipped platform record pages -- i18n ownership (#14817) > holds every inline locale map on those pages complete in every 
      ↳ 失败原因: @objectstack/cli:test: AssertionError: expected [ { …(2) } ] to deeply equal []
    

↳ 失败原因 是判读的关键:超时(Test timed out in … / Hook timed out in …)多半是负载/时序,不是本 PR 的回归;
断言(AssertionError: …)才指向真实的行为改变。两者的 FAIL 行长得一模一样,只有这一行能区分。

⚠️ 断言这一侧有一类例外,判据是断言在测什么,不是它是不是 AssertionError。 断言的对象是产品行为(一个值、一个形状、一次拒收)⇒ 照上面读:真实的行为改变,去查,⛔ 不要重排掉;
断言的对象是这次实验自身的有效性前提(跑完的耗时、负载下的先后、任何只在时间预算内才成立的条件)⇒ 它跟超时是同一类,同样对负载敏感,重排一次是合法的判别手段。
识别是机械的:断言的消息或它比较的值本身点名了一段时长、一个时间戳、一个耗时计数。实测过的一对 —— AssertionError: SecurityPlugin.init() ran: expected false to be true 测的是产品行为(真回归);
AssertionError: this run took over a second, so second-precision stamps could have differed too: expected 1006 to be less than 1000 测的是实验前提:它守护的那条不变式当时是绿的,同一个 head 原样重排一次即成功。
穿着 AssertionError 外衣的时间测量,仍然是时间测量。(⛔ 这只改「怎么读一次红」,不改「哪些测试可以重排」——后者由别处管。)

跨 PR 相同签名(24h,按失败测试文件聚合):

历史信号:

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

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 看上面的「跨 PR 相同签名」;已有汇总 issue ⇒ flaky/环境问题实锤,去那张 issue 上谈,修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#4 · marchtian · session_017ihL2dLQEXWGsE2SZ3Qn5F

Queue ejection read · build 42381953842 · Test Core (1/8) · test/platform-page-i18n-parity.test.ts (AssertionError, inline locale map incomplete). Per the triage anchor #31153 this PR is the inherited row of stack S1 whose root is #31120 (Arabic platform-object translations, packages/platform-objects/**), ejected from the queue before this one. This diff touches only packages/cli/src/commands/{deploy,environments,package}, utils/{cloud-config,runtime-target,dev-deploy-key} and their tests — nothing under platform pages or translations. #31120 is no longer in the queue, so the seat re-arms auto-merge once on the same head b57c03aa03ab30e9502660953d02fc93accf3d4c. A second ejection on this signature without #31120 ahead of it stops the re-queue and goes to diagnosis.

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

Labels

documentation Improvements or additions to documentation size/xl tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

2 participants