Skip to content

docs(quickstart): transcribe both boot samples from @objectstack/cli 17.1.0, delete the expired Path B warning - #143

Merged
os-warren merged 2 commits into
mainfrom
claude/issue-94-quickstart-transcribe-17-1-0
Aug 20, 2026
Merged

docs(quickstart): transcribe both boot samples from @objectstack/cli 17.1.0, delete the expired Path B warning#143
os-warren merged 2 commits into
mainfrom
claude/issue-94-quickstart-transcribe-17-1-0

Conversation

@os-warren

Copy link
Copy Markdown
Collaborator

Fixes #94

Completes objectos#141 items 1-4 — the four things that page owed the moment a
CLI carrying objectstack#9736 and objectstack#9347 published. @objectstack/cli
17.1.0 published 2026-08-20T11:21:17Z; every sample line below comes from a
boot of that version that I ran in this container.

What changed

# objectos#141 item Done
1 Re-transcribe Path A Config: objectstack.config.ts row gone, as predicted. Nothing else moved.
2 Measure + transcribe Path B First real measurement of this block. pnpm dev compiles and serves.
3 Delete the Path B Warning: blockquote Deleted outright — not edited, not softened, not repointed.
4 Update the Path A version pin 17.0.0 → 17.1.0.

Plus one correction I did not go looking for, described under Measurement vs
expectation
below: the sentence under Path B's block asserted a port that
neither boot produced.

Verification of the two upstream fixes, in the published tarball

Not merge dates — the shipped files:

$ grep -n "sharingModel: 'private'" node_modules/@objectstack/cli/dist/commands/init.js
180:  sharingModel: 'private',
245:  sharingModel: 'private',
$ grep -n "SCAFFOLD_RULE_COMMAND" node_modules/@objectstack/cli/dist/utils/scaffold-validate.js
42:export const SCAFFOLD_RULE_COMMAND = 'build';
$ grep -n "8978" node_modules/@objectstack/cli/dist/commands/serve.js
3125:            // #8978 — the Config:/Artifact: row must name what actually booted,
$ node -p "require('@objectstack/cli/package.json').version"
17.1.0

Raw capture — Path A, os start, clean home (no ~/.objectstack existed)

Verbatim, nothing removed:


◆ ObjectStack
────────────────────────────────────────
🏠 Home: /root/.objectstack
📦 Artifact: none (empty kernel — install apps via the Console marketplace)
🗄️ Database: file:/root/.objectstack/data/objectstack.db
🎯 Environment: env_local
🖥️ Console: http://localhost:3000/_console/
  → Starting server...

  No objectstack.config.ts or artifact found — booting empty kernel...
  ⚠ StorageServicePlugin using local driver (.objectstack/data/uploads) — switch to S3/GCS/Azure for production (set OS_STORAGE_* or configure storage in Setup → Settings).
[LocalCryptoProvider] No OS_SECRET_KEY set — minted a new AES-256-GCM key and persisted it to /root/.objectstack/dev-crypto-key (mode 0600). Restarts on this host reuse it automatically. For containers, CI, or multi-node, set OS_SECRET_KEY so every node shares one key.
[LocalCryptoProvider] No OS_SECRET_KEY set — using the persisted key at /root/.objectstack/dev-crypto-key. For containers / multi-node, prefer setting OS_SECRET_KEY so every node shares one key.

  ✓ Server is ready

  ➜  API:       http://localhost:3000/
  ➜  Console:   http://localhost:3000/_console/
  ➜  MCP:       http://localhost:3000/api/v1/mcp
      connect an AI client (Claude Code, Cursor, …) · skill: http://localhost:3000/api/v1/mcp/skill

  Mode:    production
  Driver:  SqlDriver(better-sqlite3)  → /root/.objectstack/data/objectstack.db
  Tenancy: single
  Plugins: 30 loaded
           HonoServer, Marketplace, PlatformObjects, Auth, @objectstack/setup, @objectstack/account, Security, Audit, com.objectstack.runtime.default-datasource, com.objectstack.metadata, ObjectQL, empty, RestAPI, Dispatcher, MCPServerPlugin, QueueServicePlugin, JobServicePlugin, CacheServicePlugin, SettingsServicePlugin, EmailServicePlugin, StorageServicePlugin, SmsServicePlugin, SharingServicePlugin, MessagingServicePlugin, AnalyticsServicePlugin, ExternalDatasourceServicePlugin, ExternalValidationPlugin, DatasourceAdminServicePlugin, DatasourceAdminRoutes, ConsoleUI

  ⚠ Boot diagnostics — 1 warning logged during startup:
    2026-08-20T14:10:17.195Z WARN [AppPlugin] [protocol] package 'com.objectstack.empty' declares no engines.protocol range; loading under protocol 17.0.0 without a compatibility check (ADR-0087).
    run with --log-level debug to watch the boot stream live

  Press Ctrl+C to stop

[HonoServerPlugin] Server stopped

The block on the page omits, exactly as the 17.0.0 transcription in #140 did:
the empty-kernel/storage/crypto advisories, the plugin-name list, and the boot
diagnostics trailer (now named in the page's own omission sentence). Home paths
are shown as ~/…; the CLI printed /root/…. Omission and one declared path
substitution — no alteration.

Absence discipline for the Config: row

An empty grep is not evidence until a neighbouring positive grep proves the
probe works. Same capture, same probe style:

$ grep -c 'Config:'  pathA-boot.log   ->  0     (exit 1, zero hits)
$ grep -c 'Mode:'    pathA-boot.log   ->  1     control
$ grep -c 'Driver:'  pathA-boot.log   ->  1     control
$ grep -c 'Tenancy:' pathA-boot.log   ->  1     control
$ grep -c 'Plugins:' pathA-boot.log   ->  1     control
$ grep -c 'MCP:'     pathA-boot.log   ->  1     control
$ grep -c 'Account:' pathA-boot.log   ->  0     (still absent, as #140 found)

Three further checks that the zero is real and not a broken probe:

  1. A second, independent os start bootConfig: 0 hits again, Mode:
    and Plugins: 1 each, and the two banners are byte-identical:
    diff <(grep -A9 'Server is ready' boot1) <(grep -A9 'Server is ready' boot2)
    is empty.
  2. The same probe goes positive on Path B — 3 hits there, one of them the
    banner row itself. The row was not deleted from the CLI; it is suppressed
    when nothing was found, which is what objectstack#8978 asked for.
  3. The string is still in the Path A capture, in the diagnostic that replaces
    the row
    : No objectstack.config.ts or artifact found — booting empty kernel.... So the grep can see that text when it is printed.

Raw capture — Path B, the page's own sequence, verbatim

npx @objectstack/cli init my-app -t app --install exited 0:

  → Validating scaffold...
  ✓ Scaffold validated (namespace: my_app; 41 author-time rules passed)
  ✓ Project initialized!

41 rules pass. On 17.0.0 this was 40 rules with one failure
(security-owd-unset) and no dev server. The scaffold now ships
src/objects/my_app_item.ts:32: sharingModel: 'private',.

Then pnpm dev, verbatim, nothing removed:


> my-app@0.1.0 dev /tmp/claude-0/-home-user/7ba0d6d5-fbff-5c79-b73e-b6102626a092/scratchpad/issue-94/pathB/my-app
> objectstack dev


◆ Development Mode
────────────────────────────────────────
📂 Config: /tmp/claude-0/-home-user/7ba0d6d5-fbff-5c79-b73e-b6102626a092/scratchpad/issue-94/pathB/my-app/objectstack.config.ts
  → Compiling objectstack.config.ts → dist/objectstack.json...

◆ Compile
────────────────────────────────────────
  → Loading configuration...
  Config: objectstack.config.ts
  Load time: 86ms
  → Normalizing stack definition...
  → Lowering inline handlers...
  → Validating protocol compliance...
  → Running author-time rules (41)...
  → Checking capability providers (#3366)...
  → Collecting package docs (ADR-0046)...
  → Writing artifact...

  ✓ Build complete (117ms)

  Data: 1 Objects  3 Fields

  Artifact: /tmp/claude-0/-home-user/7ba0d6d5-fbff-5c79-b73e-b6102626a092/scratchpad/issue-94/pathB/my-app/dist/objectstack.json (1.9 KB)

  → Starting dev server (local mode)...
🎯 Environment ID: env_local
📦 Artifact: dist/objectstack.json
🗄️ Database: file:/tmp/claude-0/-home-user/7ba0d6d5-fbff-5c79-b73e-b6102626a092/scratchpad/issue-94/pathB/my-app/.objectstack/data/objectstack.db
  👁  watching objectstack.config.ts, src — rebuild + restart on change

  Loading objectstack.config.ts...
  ↪ secret fields: LocalCryptoProvider wired (dev) — set OS_SECRET_KEY and swap for KMS/Vault in production

  ✓ Server is ready

  ➜  API:       http://localhost:3000/
  ➜  Console:   http://localhost:3000/_console/
  ➜  MCP:       http://localhost:3000/api/v1/mcp
      connect an AI client (Claude Code, Cursor, …) · skill: http://localhost:3000/api/v1/mcp/skill

  🔑  Dev admin: admin@objectos.ai / admin123
      seeded on empty DB · dev only — do not use in production

  Config:  objectstack.config.ts
  Mode:    development
  Driver:  SqlDriver(better-sqlite3)  → /tmp/claude-0/-home-user/7ba0d6d5-fbff-5c79-b73e-b6102626a092/scratchpad/issue-94/pathB/my-app/.objectstack/data/objectstack.db
  Tenancy: single
  Plugins: 30 loaded
           HonoServer, Marketplace, PlatformObjects, Auth, @objectstack/setup, @objectstack/account, Security, Audit, com.objectstack.runtime.default-datasource, com.objectstack.metadata, ObjectQL, my_app, RestAPI, Dispatcher, MCPServerPlugin, QueueServicePlugin, JobServicePlugin, CacheServicePlugin, SettingsServicePlugin, EmailServicePlugin, StorageServicePlugin, SmsServicePlugin, SharingServicePlugin, MessagingServicePlugin, AnalyticsServicePlugin, ExternalDatasourceServicePlugin, ExternalValidationPlugin, DatasourceAdminServicePlugin, DatasourceAdminRoutes, ConsoleUI

  Press Ctrl+C to stop


  🤖 MCP server — connect a coding agent:
     Endpoint  http://localhost:3000/api/v1/mcp
     Skill     http://localhost:3000/api/v1/mcp/skill
     Connect   claude mcp add --transport http my-app http://localhost:3000/api/v1/mcp
     Disable   OS_MCP_SERVER_ENABLED=false

Compile failed and security-owd-unset: 0 hits in that capture.
Config: objectstack.config.ts: 1 hit — Path B has a config, so the row
appears. MCP: is on the page for Path B because Path B printed it, not
because Path A did.

The page's block omits the per-step compile progress lines, the
Loading objectstack.config.ts / secret-fields advisories and the plugin-name
list, and shows the project path as my-app/… — both declared in the sentence
under the block.

Measurement vs expectation — one contradiction, please read this one

The page said, directly under Path B's block:

Note the dev server uses port 3002 to avoid colliding with a
running os start on 3000.

Neither reading of that survives measurement:

  • Path B alone (3000 free): the dev server binds 3000 — the same port
    os start uses. See the capture above.
  • Path B with os start already on 3000 (I re-booted Path A, confirmed
    200 on http://localhost:3000/_console/, then ran pnpm dev again): it
    binds 3001 and says so.
  ✓ Server is ready

  ➜  API:       http://localhost:3001/
  ➜  Console:   http://localhost:3001/_console/
  ➜  MCP:       http://localhost:3001/api/v1/mcp
...
  Press Ctrl+C to stop

  ↪ server bound to port 3001 (requested 3000)

grep -o 'localhost:[0-9]*' | sort -u over that whole run returns exactly one
value: localhost:3001. 3002 appears in neither boot.

This is outside objectos#141's four items, and I would have left it as a filed
finding — except that the ports are the block I was told to transcribe. A
faithful Path B block showing localhost:3000 sitting above a sentence saying
the dev server uses 3002 is a contradiction this PR would have created. So the
sentence is rewritten from the two measurements above and nothing else. If you
would rather it were deleted outright, or split off into its own card, say so
and I will do that instead — it is one paragraph.

Everything else the boots could have contradicted

  • Plugins: 30 loaded — still 30, on both paths. The count in the sample
    blocks stands; the out-of-the-box blockquote still carries no count (docs(quickstart): transcribe the os start banner from a real boot, retire /_account/ from the page #140).
  • The plugin-name list contains ConsoleUI exactly once on both paths, so the
    blockquote's naming is still right.
  • Path B's list is Path A's with empty replaced by my_app — the scaffold's
    own package, which is the only difference between the two boots' plugin sets.
  • http://localhost:4002 in Or start from a template is the templates repo,
    not this CLI. Not measured, not touched.
  • Probes on the Path A boot, for the What's running table: / 302,
    /_console/ 200, /_console/register 200, /_console/apps/setup 200,
    /api/v1/health 200, /api/v1/ready 200 — and the control that makes those
    200s worth little on their own, /_console/zzz-nonexistent-control 200
    (SPA fallback). /_account/register is still 404, as docs(quickstart): transcribe the os start banner from a real boot, retire /_account/ from the page #140 established.

Gates

Local, on this exact commit (git rev-parse --short HEAD = 2b4cb10):

turbo run type-check build --filter=@objectos/docs   Tasks: 2 successful, 2 total
                                                     Cached: 0 cached, 2 total
check-translation-ownership.mjs --actor ... --files   exit 0 — 0 translation artifacts, 1 other file
check-translations.mjs                                exit 0 — "translations gate passed"
check-translation-output.mjs --self-test              exit 0 — 29 rule cases, every rule shown able to fail
check-translation-output.mjs --files changed.txt      exit 0 — "passed (138 pre-existing finding(s) reported)"
check-node-floor.mjs                                  exit 0

Exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?), never from a
tail.

Turbo hash moved, and moved back — the check this repo asks for on a
content-only change, so a green here cannot be a replayed cache entry:

type-check hash, my content        e0f4236856c45574
type-check hash, origin/main file  9dc3fcdcddbe29c9   (the value #140's review recorded)
type-check hash, restored          e0f4236856c45574

English source only; the locale siblings are stale and the freshness gate says
so, which is the design (AGENTS.md § Translation workflow), not an oversight.

Teardown

Every server I started is dead — killed by recorded PID, never by name, and
each PID checked against /proc/PID/cwd before the signal. Ports 3000, 3001
and 3002 all answer nothing.

Generated by Claude Code


Generated by Claude Code

…17.1.0

Path A re-transcribed from a real `os start` on a clean home: the
`Config:  objectstack.config.ts` row is gone, which is objectstack#9347
(#8978) landing — the banner now names only what actually booted, and an
empty kernel has no config to name. Verified by absence probe with a
positive control in the same capture (`Mode:`/`Driver:`/`Tenancy:`/
`Plugins:` all present, `Config:` zero hits across two independent boots).

Path B measured for the first time. `os init -t app` now scaffolds
`sharingModel: 'private'` (objectstack#9736), so `pnpm dev` compiles —
41 author-time rules pass where 17.0.0 failed one on `security-owd-unset`.
Its banner is its own measurement, not Path A's: it prints `MCP:`, and it
DOES print `Config:  objectstack.config.ts`, because here a config exists.

The Path B `Warning:` blockquote is deleted, not updated — it described a
sequence that is no longer broken (objectos#141 item 3).

The port note under Path B was falsified by both boots and is rewritten
from measurement: dev asks for 3000, the same port `os start` uses, and
falls back to the next free port when it is taken (measured: 3001, with
`↪ server bound to port 3001 (requested 3000)`). It never chose 3002.

Part of #94
PM review of the transcription: Path A's sentence names its omissions and
Path B's under-declared, which is the undeclared-deviation shape the pin
exists to prevent. Checked against the capture rather than reasoned about
— diffing the raw `pnpm dev` log against the block leaves exactly five
kinds of line, and the sentence now names all five: pnpm's script header,
per-step compile progress, the two startup advisories (`Loading
objectstack.config.ts...`, `↪ secret fields: LocalCryptoProvider wired
(dev) …`), the plugin-name list, and the `🤖 MCP server` connection
trailer printed after `Press Ctrl+C to stop`.

Prose only. No sample line, no measurement and no other sentence moved.

Part of #94

Copy link
Copy Markdown
Collaborator Author

Head sha changed: 2b4cb10d9fc8cf. One prose commit, the requested change and nothing else. Still draft, still one file.

What the sentence names now. I did not reason about what the block omits — I diffed the raw capture against the block and let the leftovers dictate the list:

$ # every line in pathB-dev.log that the page block does not show
> my-app@0.1.0 dev …/my-app          <- pnpm's script header
> objectstack dev                     <- (same)
  → Loading configuration...          <- per-step compile progress
  Config: objectstack.config.ts       <- (same; the compile echo, not the banner row)
  Load time: 86ms                     <- (same)
  → Normalizing stack definition...   <- (same)
  → Lowering inline handlers...       <- (same)
  → Validating protocol compliance... <- (same)
  → Running author-time rules (41)... <- (same)
  → Checking capability providers …   <- (same)
  → Collecting package docs (ADR-0046)…  <- (same)
  → Writing artifact...               <- (same)
  Loading objectstack.config.ts...    <- startup advisory 1
  ↪ secret fields: LocalCryptoProvider wired (dev) — set OS_SECRET_KEY …   <- startup advisory 2
           HonoServer, Marketplace, PlatformObjects, …                     <- plugin-name list
  🤖 MCP server — connect a coding agent:   <- MCP connection trailer
     Endpoint  http://localhost:3000/api/v1/mcp      <- (same)
     Skill     http://localhost:3000/api/v1/mcp/skill <- (same)
     Connect   claude mcp add --transport http my-app …  <- (same)
     Disable   OS_MCP_SERVER_ENABLED=false           <- (same)

Five kinds, and the sentence now names five:

yours expanded. Your own run also prints pnpm's script header above the block,
per-step compile progress, startup advisories (configuration load, dev
secret-field crypto), the full list of loaded plugin names, and an MCP
connection trailer below the banner.

One addition beyond the two you named, flagged rather than slipped in: pnpm's own two-line script header. It is not the CLI's output, so it sat outside your list — but it is the first thing on a reader's screen and the block does not show it, so leaving it undeclared would have been the same defect one line higher up. Say the word if you want it dropped.

Gates re-run on d9fc8cf, all local, exit codes captured before any pipe:

turbo run type-check build --filter=@objectos/docs   Tasks: 2 successful, 2 total / Cached: 0 cached, 2 total
check-translation-ownership.mjs  exit 0     check-translations.mjs           exit 0  "translations gate passed"
check-translation-output.mjs --self-test  exit 0    --files changed.txt      exit 0  "138 pre-existing"
check-node-floor.mjs             exit 0

type-check hash moved with the prose edit — e0f4236856c45574 (2b4cb10) → e70ea17b6057cc57 (d9fc8cf), so this green is a real run on the new tree, not the previous head's cache entry.

Closing-keyword scan over both commits in the range: no close/fix/resolve variant adjacent to any issue number. The only closing reference is Fixes #94, in the PR body, where you want it.

No re-boot, no re-measurement, no sample line touched — the diff is 4 insertions, 2 deletions, all prose. Worktree removed without --force; ports 3000/3001/3002 answer nothing.

Generated by Claude Code


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

ACCEPT — landing

PM review, repo:objectos seat (objectstack#9831), session session_01DXBoKN4MauvPdbMemPMqpr. Reviewed at head d9fc8cf, two commits, one file, +44/−19.

Verified independently of the report

  • CI on the head commit, not a local claim: build (required), Ownership & freshness, Node floor — all success on d9fc8cf. mergeable_state: clean.
  • Closing-keyword scan over the commit range. git log --format='%s%n%b' origin/main..d9fc8cf matched no close|fix|resolve variant adjacent to an issue number. The only closing reference is Fixes #94 in the PR body, which is correct: keywords are parsed from both the body and the commit messages, so a stray one in a commit would have over-closed.
  • Round-two diff read in full. Prose only, 4 insertions / 2 deletions, confined to Path B's declaration sentence. No sample line, measurement, or other sentence moved.

On the review finding

The request was that Path B's declaration name what its block omits, as Path A's does. You did not implement the two items I named — you diffed the raw capture against the published block and found five, then named five. That is the right way to answer a question about absence, and it caught one I had missed: pnpm's script header, which is not CLI output at all but is the first thing on a reader's screen. Flagging it as an addition rather than folding it in silently was also right.

The sentence now reads as a genuine provenance declaration rather than a gesture at one, and it mirrors Path A's form.

On the out-of-scope correction

The port sentence rewrite stands, as directed. Restating the reasoning for the record, because it is the kind of judgement that should be reusable rather than re-argued: the four dispatched items did not include it, but the ports are inside the block item 2 required transcribing. Leaving the old sentence would have shipped a contradiction this PR created — a faithful block printing localhost:3000 directly above prose asserting 3002. Correcting a claim your own measurement falsifies inside the surface you were sent to measure is in scope; going looking for others is not. You did the former and said so explicitly.

Correction to this PR's own record

The Gates section of the body is pinned to 2b4cb10 and was not refreshed after round two, so as written it reports a run against a commit that is no longer the head. The gates were re-run on d9fc8cf — type-check hash moved e0f4236856c45574e70ea17b6057cc57, confirming a real run on the new tree rather than the reviewed head's cache entry — and GitHub's own check runs on d9fc8cf are green, which is the stronger evidence anyway. Recorded here rather than sent back for another round: the body is history once this merges, and this comment is part of the same record.

Carried upward, not blocking

The Path B block now publishes the seeded dev credential (admin@objectos.ai / admin123) on a public docs page. It is a faithful transcript, the CLI prints it on every dev boot, and its own dev only — do not use in production caveat is transcribed with it — so it stays. Raised with the maintainer as an observation about the change in exposure (local terminal output → published documentation), not as a defect in this PR.

Disposition

Fixes #94 closes the card on merge. objectos#141 is not closed by this PR — its trigger has now been consumed, so it will be re-evaluated separately rather than auto-closed. objectos#142 remains blocked on objectstack#10232 and is untouched by this.

Flipping ready and merging through the queue.


Generated by Claude Code

@os-warren
os-warren marked this pull request as ready for review August 20, 2026 14:37
@os-warren
os-warren merged commit 514527b into main Aug 20, 2026
3 checks passed
os-zhuang pushed a commit that referenced this pull request Aug 29, 2026
`reference/cli.mdx:70` claimed `os dev` defaults to port 3002. PR #143
measured the real behavior (against @objectstack/cli 17.1.0) and landed
it in quickstart.mdx: os dev asks for 3000, the same port os start uses,
and binds the next free port on collision. Re-verified here against
17.2.0's shipped source (packages/cli/src/commands/dev.ts,
`requestedPort = port ?? '3000'`) — the default and the collision/rebind
behavior are unchanged.

Corrects line 70's comment and adds a short note under the block
carrying the collision behavior, since that is the part that surprises
a reader running `os dev` alongside `os start`. Also updates the -p
example on line 71 from 4002 to 4000, since 4002 read as "3002 plus a
bit."

Fixes #229
os-zhuang added a commit that referenced this pull request Aug 29, 2026
`reference/cli.mdx:70` claimed `os dev` defaults to port 3002. PR #143
measured the real behavior (against @objectstack/cli 17.1.0) and landed
it in quickstart.mdx: os dev asks for 3000, the same port os start uses,
and binds the next free port on collision. Re-verified here against
17.2.0's shipped source (packages/cli/src/commands/dev.ts,
`requestedPort = port ?? '3000'`) — the default and the collision/rebind
behavior are unchanged.

Corrects line 70's comment and adds a short note under the block
carrying the collision behavior, since that is the part that surprises
a reader running `os dev` alongside `os start`. Also updates the -p
example on line 71 from 4002 to 4000, since 4002 read as "3002 plus a
bit."

Fixes #229

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

quickstart.mdx sample os start output does not match what CLI 17.0.0 prints, and the plugin count is wrong

1 participant