Skip to content

docs(cli): stop naming the out-of-repo apps/objectos as serve.ts's in-repo host-config example - #14812

Merged
os-trump merged 1 commit into
mainfrom
claude/issue-14634-serve-host-config-example
Sep 3, 2026
Merged

docs(cli): stop naming the out-of-repo apps/objectos as serve.ts's in-repo host-config example#14812
os-trump merged 1 commit into
mainfrom
claude/issue-14634-serve-host-config-example

Conversation

@os-trump

@os-trump os-trump commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Fixes #14634

packages/cli/src/commands/serve.ts named apps/objectos at three sites as though it were a path in this repo. It is not. The app is real — it lives in the sibling objectstack-ai/cloud repo, split out of this one — so the precise claim is "not in this repo", never "does not exist".

Readings, with the positive control

The card's claim is a negative, so it is paired with a control that shows the query works and the directory is not simply unreadable:

$ git ls-tree origin/main -- apps/
040000 tree f281e0156f1e4569560b79b9899d3ea56cfb7f1d	apps/docs      # control: apps/ is populated
                                                                       and it holds exactly one entry
$ git grep -c "apps/objectos" -- packages/cli/src/commands/serve.ts     # before
3
$ git grep -c "apps/objectos" -- packages/cli/src/commands/serve.ts     # after
1                                                                       # the one deliberately kept,
                                                                          now marked out-of-repo

Where the app actually went, from this repo's own records — CHANGELOG.md:

apps/objectos — deleted from this repo. The tenant runtime (serving *.objectos.app) now lives in objectstack-ai/cloud/apps/objectos.

and ROADMAP.md:41: "apps/cloud, apps/objectos, apps/studio, and service-tenant no longer exist in this repo."

Why the three sites did not take one fix

The dispatch asked which disposition is true of the host-config feature — name something openable, or mark it out-of-repo. The answer is both, because the three sites are making different claims. Treating them as one defect repeated is what would have produced a wrong one-line sweep.

:1921 — a provenance note. Marked out-of-repo.
It says where the artifact-first fallback came from. The referent genuinely is the out-of-repo app, so renaming it would destroy true information; the defect was only that nothing told the reader to stop looking in apps/. It now names the app and says where it lives:

that app is apps/objectos in the separate objectstack-ai/cloud repo, NOT a path in this one

:2791 and :2965 — worked examples of live branches. Shape stated, no app named.
Both branches key on a shape, never on an app: plugins[] already holding an AppPlugin instance, and a config composing several new AppPlugin(...) entries. The app name was never what the code read, so it is gone and the shape is spelled out. This is what makes the comment un-falsifiable rather than merely re-pointed.

examples/app-showcase is named once, at the one claim that is true of it.
It is added to the "even host/aggregator configs need this wrap" sentence — a host config whose plugins[] holds instantiated plugins while the stack still carries top-level metadata. Checked before writing it, because naming a wrong example here would be the same defect again:

  • plugins[] at examples/app-showcase/objectstack.config.ts:134 holds ConnectorOpenApiPlugin, ConnectorMcpPlugin, ConnectorRestPlugin, ConnectorSlackPlugin;
  • top-level manifest:79, objects:189, apps:202, flows:213, apis:259 — so it really does carry both halves;
  • serve-host-config-security-registrar.pin.test.ts records an os dev boot of it, which is what the added parenthetical claims and no more.

⛔ It is deliberately not named at :2791's skip branch or at :2965. Its plugins[] holds no AppPlugin instance, and it declares top-level translations:181 — so at those two sites it would have been a fresh false example.

File face

One file, comments only: packages/cli/src/commands/serve.ts (+17 −9).

No behaviour, no exported surface, no authored metadata, no control-flow. hasAppPluginAlready, pluginBundleHasTranslations and the artifact-fallback block are byte-identical.

Changeset: none — skip-changeset instead, and the measurement behind that

The dispatch asked me to conclude and say why. Its parenthetical was that a comment in packages/cli/src/** ships inside a released package; measured, it does not:

$ node -e 'console.log(require("./packages/cli/package.json").files)'
[ 'dist', 'README.md', 'CHANGELOG.md' ]

src/ is not published. This diff changes no dist behaviour and releases nothing, which is the closed-list comments-only case, and lint.yml states the same test in its own words — "such a PR releases nothing, so by the workflow's own prescription it takes the label". dispatch-gates.mjs prints the same fork: "write one unless this card publishes nothing from any released package (then the skip-changeset label instead)".

Gates — 24 families derived, 21 measured green, 3 NOT MEASURED

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack derived the family list from the real change set (23 by path + 1 by change kind = 24), rather than from a recalled list. All readings below were taken at head 876ce8ee52, which is the final commit — the tree has not moved since.

Exit codes captured before any pipe (cmd > log 2>&1; EXIT=$?), and each verdict quoted from the gate's own output rather than from $?:

check:nul-bytes                OK (8064 text files; no raw ASCII control bytes) + 75 self-test assertions
check-comment-mask-adoption    OK — 14 private comment-stripper(s), all recorded and still reached
check:doc-authoring            393 files clean; 46 published skill files clean; 14546 customer-facing strings clean
check:dispatcher-error-vocabulary   0 unregistered wire code(s)
check:published-files          69 publishable package(s); census control floor 50
check:route-envelope           4 module(s) audited; both ratchets unmoved
check:logger-receiver-detach   2398 non-test TS files, 0 detaches; control corpus fired on all five shapes
check:keyed-text-bounds        112 files / 148 keyed text columns, 148 bounded
check:plugin-teardown-shape    64 Plugin implementations; baseline fully burned down
check:system-context-census    109 elevation read sites, all anchored
check:undeclared-dep-imports   79 packages / 2147 src files; 2 ledger rows intact
check:cross-package-test-inputs  117 self-test cases passed; 25 packages declared
check-ci-filter-parity         130 declared cross-package globs covered
check:test-source-alias        72 packages scanned
check:slot-lookup              106 unswept sites, none new
check:page-declaration-shape   34 page entries, all discoverable
check-affected-docs            exit 0
check-drift-comment            56 cases pass across 5 fixture diffs
check-shard-attestation        2 aggregate gates count 3 declared legs
check:type-source-resolution   114 tsc programs across 78 packages; self-test OK
pnpm lint (WHOLE repo)         exit 0 — `eslint . --no-inline-config`, no narrowing, no findings

Package-level, under the shared verify lock:

pnpm --filter @objectstack/cli exec vitest run --maxWorkers=2 THE_19_FILES_THAT_READ_SERVE_TS_SOURCE
  Test Files  19 passed (19)
       Tests  190 passed (190)
pnpm --filter @objectstack/cli typecheck        exit 0, no diagnostics

Those 19 files are the exact blast radius of a comments-only edit: they are every file under packages/cli/src/commands/ that reads serve.ts as text (git grep -l "serve\.ts'"), including serve-host-config-security-registrar.pin.test.ts, whose source pins sit within a few lines of two of the three edits. None asserts on comment text — checked before editing — and all 19 stay green.

3 of the 24 are NOT MEASURED, not red, each refusing by its own documented prerequisite branch and each saying so in its own words:

  • check:test-completeness — exit 3: "this gate grades a saved turbo run test log, and no log was named … the local reading for this gate is NOT MEASURED. ⛔ It is not a red."
  • check:i18n and check:i18n-coverage — exit 1 on the prerequisite branch: "PREREQUISITE NOT MET — the workspace CLI is not built … Nothing was checked".
  • check:dual-build-cjs-loads — exit 3: "PREREQUISITE NOT MET — this gate reads built output, and some package has no dist/ … ⛔ This is NOT a pass: nothing was measured." (13 packages listed.)

Clearing those needs a full workspace build on a box four other agents are queued on. Declared narrowing: a diff of three source comments cannot move a translation bundle, an os lint label count, or a CJS/ESM resolution — no string is authored, extracted or exported by it — and CI runs the farm exactly once regardless. They are recorded as not measured rather than as passed.

No test pins the edited comment text — checked before editing (git grep over packages/cli/src/**/*.test.ts, packages/cli/test/, scripts/); the serve*.pin.test.ts family asserts on code strings only.

What I did NOT do, and why

  • Did not sweep the token objectos. ~50 occurrences in packages/cli/src are correct and load-bearing: objectos.ai / cloud.objectos.ai (the product domain, DEFAULT_CLOUD_URL, the root-domain guard, admin@objectos.ai), and objectos-ee / objectos-runtime / objectos-environment / objectos-stack, several matched as literal plugin ids. The false references are the path apps/objectos only, and the difference is invisible from the token.
  • Did not add an apps/objectos to make the old comments true.
  • Did not touch CHANGELOG.md, the per-package changelogs, docs/adr/0004-*, docs/adr/0006-*, or ROADMAP.md. Those name the same path as history and are accurate as written; ROADMAP.md:41 and content/docs/getting-started/examples.mdx:40 already state the app is gone.
  • Did not fix seven same-class sites outside this card's ruled scope — three apps/objectos references in packages/adapters/hono, packages/plugins/plugin-hono-server and packages/cloud-connection, and four apps/cloud references inside serve.ts itself. Filed as [finding] Seven more source comments name deleted in-repo app paths (apps/objectos, apps/cloud) as live — same class as #14634, outside its ruled scope #14806 (searched first; no open card covered it). The apps/cloud one at serve.ts:133 is the reason they are not a rider here: "keep the two in sync if you tweak names" is a live cross-repo obligation, and whether it still stands cannot be read from this repo — a decision, not a mechanical rename.

🤖 Generated with Claude Code

https://claude.ai/code/session_016yfqQh2dBgPAymYd7xipza


Generated by Claude Code

…in-repo host-config example

`packages/cli/src/commands/serve.ts` named `apps/objectos` at three sites as if
it were a path in this repo. It is not: `apps/` holds exactly one entry,
`apps/docs`. The app is real but lives in the sibling `objectstack-ai/cloud`
repo, split out of this one (CHANGELOG.md, "deleted from this repo ... now
lives in `objectstack-ai/cloud/apps/objectos`"; ROADMAP.md says the same).

The three sites are not one defect repeated, so they do not take one fix:

- `:1921` is a provenance note about where the artifact-first fallback came
  from. The referent is genuinely out of this repo, so it is marked as such
  rather than renamed — a reader who wants it can still find it.
- `:2791` and `:2965` were worked examples of live branches. Both branches key
  on a SHAPE (`plugins[]` already holding an `AppPlugin` instance; a config
  composing several `new AppPlugin(...)` entries), never on an app name, so the
  shape is stated and no app is named. `examples/app-showcase` is named once,
  at the one claim that is true of it and checkable: a host config whose
  `plugins[]` holds instantiated plugins while the stack still carries
  top-level metadata.

Comments only; no behaviour, no exported surface, no authored metadata changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016yfqQh2dBgPAymYd7xipza
@github-actions github-actions Bot added the size/s label Sep 3, 2026
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

17 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: node scripts/docs-audit/affected-docs.mjs --json 5a5336b399db2ef18dd4700f97d579a328197dda.

4 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.

What this run could not see
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • 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.

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 5a5336b399db2ef18dd4700f97d579a328197ddapackageMentionDocs.

Which tree this was computed on

This run read content/docs from 5aaf82037be18e900bc5f6494b7499ff190d9e33 — the merge of head 876ce8ee525be2c5f371c0d8fb16b85d42f84dd1 into base 5a5336b399db2ef18dd4700f97d579a328197dda, 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 5aaf82037be18e900bc5f6494b7499ff190d9e33 && git checkout 5aaf82037be18e900bc5f6494b7499ff190d9e33
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 5a5336b399db2ef18dd4700f97d579a328197dda 876ce8ee525be2c5f371c0d8fb16b85d42f84dd1 && git checkout -B drift-repro 5a5336b399db2ef18dd4700f97d579a328197dda && git merge --no-ff 876ce8ee525be2c5f371c0d8fb16b85d42f84dd1

node scripts/docs-audit/affected-docs.mjs --json 5a5336b399db2ef18dd4700f97d579a328197dda

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

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

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

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

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

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

    @objectstack/cli:test:  FAIL   integration  test/run-dev-unbuilt-workspace.e2e.test.ts > the mirror direction: a reader that is never coming back > gives up and exits instead of waiting forever
      ↳ 失败原因: @objectstack/cli:test: AssertionError: the harness SIGKILLed the child — it was still alive at the ceiling. cap 180000 ms (RUN_TIMEOUT_MS, constant and load-independent by design); this child ran 1801
    

↳ 失败原因 是判读的关键:超时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 队列共有 71 个失败构建(不含本次)。

分诊清单:

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

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

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

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

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

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

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

    @objectstack/cli:test:  FAIL   integration  test/run-dev-unbuilt-workspace.e2e.test.ts > the mirror direction: a reader that is never coming back > gives up and exits instead of waiting forever
      ↳ 失败原因: @objectstack/cli:test: AssertionError: the harness SIGKILLed the child — it was still alive at the ceiling. cap 180000 ms (RUN_TIMEOUT_MS, constant and load-independent by design); this child ran 1800
    

↳ 失败原因 是判读的关键:超时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 已在队列失败 1 次(不含本次)。 内容未变而反复失败 ⇒ 高度怀疑 flaky 测试或与同组 PR 的语义冲突,重排不解决。
  • 过去 24h 队列共有 72 个失败构建(不含本次)。

分诊清单:

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

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

Merged via the queue into main with commit 2263ca4 Sep 3, 2026
42 checks passed
@os-trump
os-trump deleted the claude/issue-14634-serve-host-config-example branch September 3, 2026 05:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants