Skip to content

docs(quickstart): name what each path loads out of the box at CLI 17.5.0 - #289

Merged
hotlong merged 1 commit into
mainfrom
claude/pm-dispatch-objectos-ju9td1
Oct 1, 2026
Merged

hotlong merged 1 commit into
mainfrom
claude/pm-dispatch-objectos-ju9td1

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #141

This PR brings the "What's loaded out of the box" section of content/docs/quickstart.mdx (:280–:296) up to what each path loads at @objectstack/cli 17.5.0. It is the follow-up the seat took on from PR #288's contract review (③), on the same 17.5.0 trigger. The diff is one file, +8/−3.

What each path loads at 17.5.0, measured this round

I ran one fresh boot per path from an isolated npm --prefix tree. The CLI tree and the scaffold each read back 53 of 53 @objectstack packages at 17.5.0.

Boot Mode Plugins:
Path A: os start in an empty directory, which prints No objectstack.config.ts or artifact found — booting empty kernel... production 31 loaded, 31 names
Path B: pnpm dev on a fresh os init my-app -t app --install scaffold development 36 loaded, 36 names
  • Both paths (30): HonoServer, Marketplace, PlatformObjects, Auth, @objectstack/setup, @objectstack/account, Security, Audit, com.objectstack.runtime.default-datasource, com.objectstack.metadata, ObjectQL, RestAPI, Dispatcher, MCPServerPlugin, QueueServicePlugin, JobServicePlugin, CacheServicePlugin, SettingsServicePlugin, EmailServicePlugin, StorageServicePlugin, SmsServicePlugin, SharingServicePlugin, MessagingServicePlugin, AnalyticsServicePlugin, PackageServicePlugin, ExternalDatasourceServicePlugin, ExternalValidationPlugin, DatasourceAdminServicePlugin, DatasourceAdminRoutes, ConsoleUI.
  • Path A only (1): empty, the empty-kernel app.
  • Path B only (6): my-app, the scaffolded app itself, plus AutomationServicePlugin, RecordChangeTriggerPlugin, ScheduleTriggerPlugin, TimeRelativeTriggerPlugin and ApiTriggerPlugin.

Every name the list already carried still maps to a plugin that both paths load:

  • HTTP server is HonoServer.
  • The default, external-datasource and datasource-admin entries cover four plugins: the default datasource, ExternalDatasourceServicePlugin, DatasourceAdminServicePlugin and DatasourceAdminRoutes.
  • The Setup and Account apps are @objectstack/setup and @objectstack/account.
  • The other entries map one to one.

So nothing is removed. PackageServicePlugin was the one shared plugin the list did not cover, and it is added as "Package management".

The app slot (empty on Path A, my-app on Path B) holds the loaded app, not a platform plugin, so it stays out of the list. The page already describes both: the empty kernel on Path A and your own app on Path B.

Why Path B loads five more: the scaffold's declaration, not dev mode

The scaffold's objectstack.config.ts declares requires: ['automation', 'triggers']. Two more boots separate that declaration from the mode:

Boot Mode requires line Plugins: The five
pnpm dev on a copy of the scaffold with that one line deleted development absent 31 0 of 5
os start on the unmodified scaffold production present 36 5 of 5

Apart from the five, each list matches the Path B dev boot exactly (symmetric difference 0). The CLI 17.5.0 source agrees: in dist/commands/serve.js, CAPABILITY_PROVIDERS maps automation to AutomationServicePlugin, and maps triggers to the record-change, schedule, time-relative and API trigger plugins.

So "they activate when something declares it needs them" holds for these five. The new sentence credits them to Path B and names the declaration.

The closing sentence: one clause added

For the both-paths list, the sentence was not borne out. Path A boots with no config and no artifact, so nothing declares anything, and it still loads all 30. The scaffold with its requires line deleted also loads all 30.

The CLI source shows why. serve.js appends the spec's PLATFORM_ALWAYS_ON_CAPABILITIES to requires on every boot whose preset is not minimal. At 17.5.0 that list ends in package-registry, which is the token behind PackageServicePlugin.

So the sentence now says the list above loads even when nothing declares it, and it keeps "activate when something declares it needs them" for the rest. If the seat would rather leave that half of the sentence as it was, reverting it is a one-line change.

Reader-facing names and their sources

Each name comes from the published 17.5.0 package's own description.

Plugin On the page Source
PackageServicePlugin Package management @objectstack/service-package package.json description: "Package management service for ObjectStack — publish, install, and manage packages". The class JSDoc in dist/index.d.ts says "Package Management Service Plugin".
AutomationServicePlugin the automation service @objectstack/service-automation package.json description: "Automation Service for ObjectStack — implements IAutomationService with plugin-based DAG flow execution engine"
RecordChangeTriggerPlugin record-change flow trigger @objectstack/trigger-record-change package.json description: "Record-change flow trigger for ObjectStack — auto-launches flows on object insert/update/delete …"
ScheduleTriggerPlugin schedule flow trigger @objectstack/trigger-schedule package.json description: "Schedule flow trigger for ObjectStack — auto-launches flows on a cron/interval/once schedule …"
TimeRelativeTriggerPlugin time-relative flow trigger @objectstack/trigger-schedule class JSDoc in dist/index.d.ts: "Arms declarative time-relative flows". The package's description names only the schedule trigger.
ApiTriggerPlugin inbound HTTP/webhook flow trigger @objectstack/trigger-api package.json description: "Inbound HTTP/webhook flow trigger for ObjectStack — per-flow HMAC-verified endpoints with queue-backed ingestion"

"Marketplace" in the list is a separate plugin and is unchanged. The CLI tracks it when it mounts the cloud marketplace surfaces from @objectstack/cloud-connection (serve.js, trackPlugin('Marketplace')).

Scope

The edit stays inside the "What's loaded out of the box" section. These are untouched:

  • the sample blocks
  • the pins
  • the declaration sentences
  • the port paragraph
  • reference/cli.mdx
  • the locale siblings

There is no new section and no table on the page.

Gates on 1430ec1

Gate Exit Verdict
verify lock: pnpm turbo run build --force --concurrency=2 0 Tasks: 1 successful, 1 total, Cached: 0 cached, 1 total
verify lock: pnpm turbo run test --force --concurrency=2 0 Tasks: 1 successful, 1 total, ✓ 7 self-test(s) passed
check-locale-surface.mjs 0 ✓ every advertised URL has a source file and every source file is advertised; …
check-translations.mjs 0 ✓ translations gate passed
check-translation-ownership.mjs, run with the workflow's --actor and --files 0 This PR touches 0 translation artifact(s) and 1 other file(s).
check-translation-output.mjs --self-test 0 ✓ self-test: 29 rule case(s), 9 split case(s) and 5 derived-locale case(s) …
check-translation-output.mjs --files, run with the workflow's argv 0 ✓ translation output gate passed (145 pre-existing finding(s) reported)
gen-zh-hant.mjs --check (extra) 0 ✓ zh-Hant: 73 generated file(s) match the zh-Hans sources byte for byte.

The built page en/docs/quickstart.html contains each of these strings twice: Package management, Path B also loads the automation service, inbound HTTP/webhook flow triggers and loads even when nothing. Plugins: 31 loaded and Plugins: 36 loaded still appear twice each.

Acceptance notes

  • Not re-measured this round. The 17.4.0 figures (30 per path) and the claim that PackageServicePlugin is new at 17.5.0 come from the previous round's report. This PR does not depend on either.
  • Measurement depth. There is one boot per path, plus the two activation boots. The previous round's counts (Path A 31 in 3 of 3, Path B 36 in 11 of 11) agree, but they were taken by another run.

Method notes

  • The CLI ran from an isolated npm --prefix tree. The Path B scaffold came from that tree's os init my-app -t app --install, not from npx.
  • Each boot ran under a pty with a fresh HOME and was stopped with Ctrl+C through the tty. Leftover processes were killed by PID, looked up through /proc.
  • After the last boot, no CLI process was alive, and ports 3000–3002 refused connections.
  • Installs, the scaffold and the turbo runs went through the shared verify lock. The boots ran outside it.

Generated by Claude Code

Both paths now load the package management service (PackageServicePlugin),
so it joins the both-paths list. Path B's scaffold declares
requires: ['automation', 'triggers'] in objectstack.config.ts, which adds
the automation service and four flow triggers; that is attributed to
Path B rather than listed under "either path". Measured on fresh 17.5.0
boots: os start in an empty directory loads 31 plugins, pnpm dev on the
scaffold 36, the same scaffold with the requires line removed 31, and
os start on the unmodified scaffold 36.

The closing sentence now says the list above loads even when nothing
declares it, which is what the empty-directory boot shows, and keeps
"activate when something declares it needs them" for the declared rest.

Claude-Session: https://claude.ai/code/session_01FeA1nwBz1ohH65dvffUGKr
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 1430ec1203b6cf1a6e6519673120143b417913d3
Local-runs: none

Inputs read, and nothing else: card #141 (body and all 27 comments, the newest os-dev-report being 5926848077), PR #289 (body, file list, and the diff against main, whose current head is the PR's base commit, #288's squash merge, so the PR diff is the net diff), and the four check-runs on the head. The dev report is treated as the dev's account, not as evidence; the check-run conclusions are the gate verdicts.

The diff. One file, content/docs/quickstart.mdx, +8/−3, one hunk (@@ -285,10 +285,15 @@) inside "What's loaded out of the box". Three edits: "Package management" is inserted into the both-paths list; a sentence is added crediting five plugins to Path B and to the scaffold's requires: ['automation', 'triggers'] line; the closing sentence is split so the list is said to load without a declaration and "the rest" to activate on one.

Check-runs on the head. build 110265260066 success · Node floor 110265259759 success · Ownership & freshness 110265259153 success · Deploy docs 110265843696 skipped, which is the gated shape on a PR event; the merge is what publishes.

① Derived judgments

  1. "Package management" joins the both-paths list — right. The report's two name lists carry PackageServicePlugin in both (Path A 31 names, Path B 36 names, 30 shared). I mapped the edited list onto the reported shared set mechanically: the 29 pre-existing entries plus the new one cover exactly the 30 shared names, none uncovered and none extra. The page now reconciles with its own sample blocks: 30 shared plus empty is the Plugins: 31 loaded at line 56, and 30 shared plus my-app plus five is the Plugins: 36 loaded at line 198. The previous round's report (5926180364) already names PackageServicePlugin as added to both lists at 17.5.0 (A 3 of 3, B 11 of 11), so shared membership rests on four Path A and twelve Path B boots across two reports. The reader-facing name is the package's own description. Marketplace stays as a separate entry, and the body says why.

  2. The Path B sentence and its "because" — right. The five named plugins are exactly the Path B-only set less the app slot. The causal attribution is the judgment the two extra boots exist for, and they separate declaration from mode in both directions: the scaffold with its requires line deleted under pnpm dev loads 31 with 0 of the five; the unmodified scaffold under os start (production) loads 36 with 5 of 5, symmetric difference 0 otherwise. The CLI 17.5.0 CAPABILITY_PROVIDERS map agrees (automation to the automation plugin, triggers to the four trigger plugins). That is the evidence shape a causal sentence needs; "dev mode" would have been the wrong attribution and the diff does not make it. The four trigger names come from package descriptions, and the time-relative one from the class JSDoc of trigger-schedule, which the body discloses.

  3. The closing sentence, split in two — right, within the section's scope. "The list above loads even when nothing declares it": Path A boots with no config and no artifact and loads all 30; the requires-stripped scaffold loads all 30; the dev's reading of serve.js is that PLATFORM_ALWAYS_ON_CAPABILITIES is appended on every preset except minimal. "The rest activate when something declares it needs them" is the original claim narrowed to the declared set, which is what the activation boots measured. Read against the list it follows, the old sentence asserted something a Path A boot contradicts, so restoring it would leave a measured-false sentence under a measured-true list. The one boundary (the minimal preset) is outside what this page describes and is recorded in ③, not as a defect.

  4. Nothing removed — right. Every one of the 29 prior entries still maps to a plugin both paths load (the mapping in item 1).

  5. App slot kept out of the list — right. empty (Path A) and my-app (Path B) are the loaded app, not a platform plugin, and the page already describes both (the empty kernel; your own app). Listing them as plugins would mislead.

  6. Public surface. One English page, /docs/quickstart, one section. The hunk is the only one: both sample blocks, both 17.5.0 pins (lines 63 and 204 at the head), both declaration sentences and the port paragraph are untouched. No new page, URL or sidebar entry, so no locale-surface, sitemap or hreflang effect. Locale siblings are untouched and go stale by design; Ownership & freshness is success, so the freshness gate reports and does not block. The blockquote reflow is Markdown only (the line-start blockquote marker on the two reflowed lines); the diff carries no angle-bracket fragment and no numeric character reference. build success on the head covers the render.

② Semver level

  • This repository publishes no package. The head's check-run roster (build, Node floor, Ownership & freshness, Deploy docs) carries no changeset gate, and the PR carries no changeset and no skip-changeset label, which is the correct shape here: nothing versioned moves. What the merge publishes is production docs prose on one page, not a semver event. Level: none.
  • The PM claim (5925774509) declares Clause-② as no with no direction arm — right. The diff widens no accept set and narrows none: it adds one entry to a descriptive list, adds a sentence, and corrects a sentence, all on one docs page; it changes nothing any CLI or runtime accepts. Either arm would have been wrong.

③ Boundary flags

Dev flags (deviations in 5926848077), each answered:

  1. Two pushes (empty route probe, then plain): the PR has one commit and the diff is the one hunk. Accepted.
  2. Worktree upstream unset so a bare push could not target main: hygiene in the right direction. Accepted.
  3. The added closing clause: the open question below, answered A. Accepted.
  4. CLI from an isolated npm --prefix tree and the scaffold from that tree's os init my-app -t app --install rather than npx: same template, versions read back (53 of 53 at 17.5.0), the method accepted at 17.3.0, 17.4.0 and on docs(quickstart): re-transcribe both boot samples against CLI 17.5.0 #288. Accepted.
  5. pty boots with a fresh HOME, Ctrl+C through the tty, PID cleanup via /proc, boots outside the verify lock: same as prior rounds; 0 processes alive and ports 3000-3002 refusing afterwards. Accepted.
  6. Waited for CI before reporting: no effect on the diff. Accepted.
  7. Extra gates (gen-zh-hant --check, control-byte scan): exit 0 per the account; the CI check-runs are the verdicts here regardless. Accepted.
  8. Model-free commit trailer with no card reference: the commit message is not a public surface and a squash merge rewrites it. What matters is the PR body: first line Part of #141, zero closing-keyword hits, so the card stays open as it must. Accepted.
  9. Report omits the summary and tests prose fields: the gates array carries the evidence, and a report is an account in any case. Accepted.

PR body acceptance notes:

  • "Not re-measured this round" (the 17.4.0 figures and "new at 17.5.0"): neither claim is on the page; the diff asserts no version delta. Nothing to re-measure for this diff.
  • "Measurement depth" (one boot per path plus two activation boots): for a list-membership edit rather than a transcript, adequate, given the previous round's 3 of 3 and 11 of 11 name lists carry the same plugin. The next trigger's standard of three-plus boots re-covers it.

Open question — keep the clause (A) or restore the original sentence (B): A. B would restore a sentence this round measured false for the base list, under a list the same PR just corrected; a public page should not carry a claim its own measurement contradicts. A is the minimal wording that states what was measured, and the dispatch rule that the section must be true for both paths selects it. The revert is one line, and it would be a one-line regression.

Escalated to the seat (not defects of this diff):

  • E1. The section is now version-bound prose with no pin of its own: the 30-name shared list and the requires: ['automation', 'triggers'] attribution both depend on CLI 17.5.0 and on the -t app scaffold template. The card's re-arm should name "What's loaded out of the box" among the watched items with two checks: the shared set of the two plugin-name continuations against the list, and the scaffold's requires line against the sentence (the template can change without the banner changing). The ACCEPT on docs(quickstart): re-transcribe both boot samples against CLI 17.5.0 #288 said the seat would take this; the re-arm record is where it has to be written down.
  • E2. The minimal preset: "loads even when nothing declares it" holds on every preset except minimal, per the dev's reading of serve.js. No change is needed here because the page documents no preset; if a page ever does, the sentence needs a qualifier. Note only.
  • E3. Deploy docs is skipped on the PR event by design, so the merge publishes production directly. The locale siblings of this section render the pre-PR text until the translation pass, by design and reported, not blocking.

Implemented-by: claude/pm-dispatch-objectos-ju9td1
Reviewed-by: session_01FeA1nwBz1ohH65dvffUGKr

VERDICT: PASS


Generated by Claude Code

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.

2 participants