Repository navigation
docs, cli: the on-ramp a first-time reader walks reads true (CONTRIBUTING, README curl, one pnpm floor, five examples, os dev / os init strings, tutorial transcript) - #22280
Conversation
…md; one pnpm floor; the examples page counts five CONTRIBUTING.md still described the retired protocol-only repository: clone and upstream URLs, issue and discussion links, an internal/planning directory that does not exist, docs trees that do not exist, a bilingual .cn.mdx convention with zero files, and a pnpm >= 8 floor. It now names this repository, sends contributors to AGENTS.md for the rules instead of restating them, and carries the changeset step of the flow that gates a PR. The getting-started prerequisites and the examples Quick Run now say pnpm 10, the floor the workspace enforces, matching README.md and CONTRIBUTING.md. The examples page opens with the five examples examples/ holds. Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q Co-authored-by: Claude <noreply@anthropic.com>
… package manager it resolved `os dev --port`'s help read "overrides $PORT" while the command reads OS_PORT first and PORT only as the legacy alias. It now names both, in that order. `os init` resolved its package manager only inside the install branch, so a --no-install run kept the literal 'npm' initialiser and printed `npm install` / `npx objectstack` even under --package-manager pnpm or a pnpm invocation. The package manager is now resolved before that branch, by the same rule (flag, then the invoking package manager, then npm). Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q Co-authored-by: Claude <noreply@anthropic.com>
…idate is clean README.md's first data call answered 401 UNAUTHENTICATED against a scaffolded project: data endpoints run under the same permissions as the UI. It now signs in as the dev admin `os dev` seeds and sends the session cookie, the same two calls the scaffolded README and Your First Project show. build-with-claude-code.mdx promises every example passes `os validate` verbatim and prints a clean transcript, but its `description` field sat on no view, so every run printed a field-no-consumers warning. The view file now declares the create and edit form that places it, the prompt asks for that form, one paragraph says why, and the transcript carries the two summary lines the command prints today. Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q Co-authored-by: Claude <noreply@anthropic.com>
…t test a 60s budget check-docs-section-name requires a teaching example's form section to carry a `name` (its i18n anchor). The init Next-steps test now takes the 60s budget the in-process doctor tests use: the first oclif load in a busy worker ran past vitest's 5s default. Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 19 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 9 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 28 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin a9611a24ca1de2e66c60eeeef30b5bb10e490e9d && git checkout a9611a24ca1de2e66c60eeeef30b5bb10e490e9d
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin c8bb3c8d9cdae41c51b72f1cb3cb5028988e1fe4 fae81259be665e11fa23e333bbec8bbed2c42943 && git checkout -B drift-repro c8bb3c8d9cdae41c51b72f1cb3cb5028988e1fe4 && git merge --no-ff fae81259be665e11fa23e333bbec8bbed2c42943
node scripts/docs-audit/affected-docs.mjs --json c8bb3c8d9cdae41c51b72f1cb3cb5028988e1fe4
|
…odo pnpm floors; a non-exhaustive consumer list `os start --port`'s help read "overrides $PORT" while the command reads OS_PORT first, the same drift as `os dev`. It now names OS_PORT with PORT as the legacy alias, and keeps "default 3000". The changeset names it. your-first-project.mdx said pnpm 8+ for a scaffolded project whose package.json declares the pnpm floor 10.15; it now says 10.15+. examples/app-todo/README.md said pnpm 8+ for the monorepo; it now says pnpm 10, as the other on-ramp pages do. The tutorial's field-no-consumers sentence named five consumers as if the list were complete; it now says they are among the ones the rule counts. Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q Co-authored-by: Claude <noreply@anthropic.com>
Fixes #22156
Clause-②: no
This PR fixes the seven on-ramp items #22156 lists, one by one, each measured on this branch. Five are docs-only. Two are CLI strings, and patch round 1 adds
os start's help text to them. Those carry the one patch changeset for@objectstack/cli.Clause-②: no: the CLI change is help text and printed text, with no change to the accept set or the public surface.Item by item
specrepositoryobjectstack-ai/objectstackin the clone, upstream, issue and discussion URLs, and theinternal/planninglinks are gone. It lists real docs trees and says which are generated (references/) or release-owned (releases/), where it used to send authors to hand-write MDX inreferences/. The bilingual.cn.mdxsection is gone (0 such files), and so is the deadQUICK_START_IMPLEMENTATION.mdlink. The pnpm floor is now 10, and the title covers the whole stack. It points to AGENTS.md for the rules instead of restating them: the restated naming, Zod-first and single-source copies are removed. The flow now includes the changeset step and the worktree-per-task note. Theneeds:pack-smokecriterion is kept word for word, becausepack-smoke-optin.ymlsays authors meet it in this file.CONTRIBUTING.mdcurlanswered 401os devseeds and sends the cookie. These are the two calls the scaffolded README andyour-first-project.mdxshow, and the sentence before them says a data call needs a session.README.mdcorepack enableinstalling the pinned version. That is the floor the workspace enforces (measured below). Patch round 1 adds two more lines of the same drift.examples/app-todo/README.mdsaidpnpm 8+for the monorepo and now sayspnpm 10 (corepack enable).your-first-project.mdx's prerequisites row saidnpm 9+ / pnpm 8+ / yarn / bunfor a scaffolded project and now saysnpm 9+ / pnpm 10.15+ / yarn / bun, the floor both scaffolders write (engines.pnpmincreate-objectstack/src/templates/blank/package.jsonandSCAFFOLD_PNPM_RANGEininit.ts). The npm, yarn and bun parts were not measured and are unchanged, and so is theengines.protocolline #22215 edits.content/docs/getting-started/index.mdx,examples.mdx,your-first-project.mdx,CONTRIBUTING.md,examples/app-todo/README.md(README.mdalready said pnpm 10)pnpm dev:*script), thenapp-multi-package(linked to its section lower on the page) andembed-objectql.content/docs/getting-started/examples.mdxos dev --helpnamed only$PORTServer port (overrides $OS_PORT; $PORT is the legacy alias). That is the orderreadEnvWithDeprecation('OS_PORT', 'PORT')reads them in. Patch round 1 fixesos start --helpthe same way:Port to listen on (overrides $PORT, default 3000)becomesPort to listen on, default 3000 (overrides $OS_PORT; $PORT is the legacy alias).os startreads the same pair atstart.ts:327, and "default 3000" is kept because it measured true. No test, snapshot or generated docs page pins either old string, anddeployment/cli.mdxis hand-written and already saysOS_PORT/PORT.packages/cli/src/commands/dev.ts,packages/cli/src/commands/start.tsticket.view.tsdeclares the create and editformthat placesdescription, and the prompt asks for that form. One paragraph explains that a field nothing names drawsfield-no-consumers. In patch round 1 its consumer list became visibly non-exhaustive ("a view, a form, a flow, a formula or an action, among the others the rule counts"), because the rule also credits page blocks, dataset members, validations, view filters and hooks. The transcript also carries theLogic:andSecurity:lines the command prints today.content/docs/getting-started/build-with-claude-code.mdxos init --no-installprintednpm install--no-installrun kept the literal'npm'initialiser, whatever was asked.packages/cli/src/commands/init.ts, newinit-next-steps-package-manager.test.tsRoute choices
Item 6: a clean example, not a printed warning
I chose the PM's suggested route, measured against both alternatives on the four axes:
validate-field-consumers.tsdocblock). Declaring the form makes the placement explicit. A grid column for long text, the one-line alternative, would teach the wrong UI, and the prompt asked for(subject, status, priority)columns.os validateverbatim. A clean example keeps that promise whatever the rule later credits. A transcript that prints the ~900-character warning would drift again the day the rule changes.formblock (11 lines) and one paragraph. No new gate.Narrative check: the Console step ("Create a ticket. Confirm the fields…") reads the same, and the counts stay
2 Objects 6 Fieldsand1 Apps 1 Views 1 Actions.Item 7: what changes and what does not
Measured (below): under
--no-installall three invocations printednpm install, including--package-manager pnpm, because the variable was assigned only insideif (flags.install). That contradicts the flag's own help and the contractcreate-objectstackpins inscaffold-next-steps-pm.test.ts(never a hardcoded npm). After the fix,--package-manager pnpmand a pnpm-invoked run printpnpm installandpnpm exec objectstack ….A plain
npx os init … --no-install, the card's literal command, still printsnpm install, and that is correct. The scaffold deliberately supports npm, yarn and bun: it declaresengines.pnpm, never apackageManagerstamp, andinit.test.tspins this ("does NOT pin a packageManager — the scaffold also supports npm, yarn and bun").pnpm-workspace.yamlis inert for npm. So the card's alternative, dropping the pnpm files when recommending npm, would change which files the scaffold writes. That is outside this card, and the design says it is not needed. Rollback: revert theinit.tshunk. The variable goes back to being assigned in the install branch, and nothing else reads it.Measurements (this branch; the CLI built from the worktree)
Item 2. I booted a tutorial-shaped scaffold with
os dev --freshon a random port.GET /api/v1/data/support_desk_ticketwith no session gave401 {"error":"UNAUTHENTICATED",…}.POST /api/v1/auth/sign-in/emailas the dev admin gave 200. The same GET with the cookie gave200 {"object":"support_desk_ticket","records":[],…}./api/v1/healthand/api/v1/discoveryanswer without a session, but neither shows that the object's API exists, so the README signs in instead. The server was stopped by its recorded PID.Item 3. Root
enginesdeclares only a Node floor (22.0.0).packageManagerispnpm@10.31.0. The global pnpm here is 10.28.0 outside the repo and runs as 10.31.0 inside it, so pnpm 10 switches to the pin. In a throwaway worktree at the base commit,pnpm@8.15.9 install --frozen-lockfile --lockfile-onlyfailed withERR_PNPM_LOCKFILE_BREAKING_CHANGE, andpnpm@9.15.9failed withERR_PNPM_LOCKFILE_CONFIG_MISMATCH … "overrides" configuration doesn't match. The floor is therefore pnpm 10.Item 5.
os dev --helpbefore (base source):Server port (overrides $PORT). After:Server port (overrides $OS_PORT; $PORT is the legacy alias).os start --helpbefore, on the CLI built at8fe75a222:Port to listen on (overrides $PORT, default 3000). After, on the CLI built atfae81259b:Port to listen on, default 3000 (overrides $OS_PORT; $PORT is the legacy alias). The behaviour the new text states was measured on that build. Eachos startran in an empty directory, inside a private network namespace (unshare -n) so the shared box's port 3000 stayed untouched. With no port variable, the banner readAPI: http://localhost:3000/. WithOS_PORT=41077it read:41077. WithOS_PORT=41077 --port 41078it read:41078.Item 3, patch round 1. On an
os initscaffold,pnpm@9.15.9 installfails withERR_PNPM_UNSUPPORTED_ENGINE … Expected version10.15 or later,Got: 9.15.9. The monorepo's pnpm 8 refusal is the item 3 reading above.Item 6. I scaffolded the
blankstarter fromcreate-objectstacksource (--skip-install --skip-skills), wrote the page's four files verbatim and wired their barrels, then ranos validate. With the page's original view:✓ Validation passed, then thefield-no-consumerswarning forsupport_desk_ticket.description(verdictinert). With the edited page, re-run atfae81259b:Running author-time rules (50)…,✓ Validation passed, no warning, and the six summary lines the transcript now shows.tsc --noEmiton the scaffold passes, and--listFilesconfirms it compiledticket.view.ts.Item 7.
os init APP --no-installbefore and after the fix:npm installnpm install(control)--package-manager pnpmnpm installpnpm installnpm installpnpm installTests and gates, at
fae81259b(this branch after patch round 1 and mergingmainatc8bb3c8d9)packages/cli/src/commands/init-next-steps-package-manager.test.ts(unit tier, in-processInit.run, nothing spawned): 3 cases.scripts/ablation-replace.mjsput the old semantics back (flags.install ? (flag ?? detect) : 'npm'): anchor 1→0, blobc4c2caca→9b93b146. Result: 2 failed (the flag case and the pnpm-agent case), and the npm control passed. Restore: blob equals HEAD, andgit diff HEADis empty.pnpm --filter @objectstack/cli typecheck: exit 0 atfae81259b(tsc --noEmitcompilessrc/**, the new test included, andcheck:test-typechecksays OK).pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2: 265 files, 3918 tests passed, atfae81259band before that at8fe75a222. The integration tier is left to CI: the diff touches no spawn entry and no integration-tier file.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon the 12-path diff gave 95 commands; the round-1 files addedcheck:examples-live-imports. All 95 exited 0 atfae81259b.--ranreconciliation: 95 derived, 95 run, 0 NOT-MEASURED (a derived zero: every command has a recorded exit code). The earlier round gave 94 of 94 at8fe75a222. On the first pass,check-docs-section-namecaught the new form section's missingname, which is fixed.Acceptance notes
create-objectstacknames pnpm wheneverpnpm --versionsucceeds.os initreadsnpm_config_user_agent. So undernpxwith pnpm installed, one says pnpm and the other says npm. Both instructions install, so this is an observation, not a defect. Carrier: none.field-no-consumersheadline. Its text says "nothing in this stack reads or displays it" for a field the default form does draw. The rule's docblock excludes that unkeyed fallback layout on purpose: crediting it would credit every visible field. I read it as working to its contract and did not editpackages/lint. Carrier: none.formview: no objectui build in this container. That the form view is what the create and edit surfaces render is a reading ofexamples/app-crm/src/views/lead.view.ts, not a measurement here.packages/cli/test/start-port-banner-agreement.e2e.test.ts:204quotes the oldos starthelp text ("overrides $PORT") in a comment. It asserts nothing, and the file is outside the surface, so it is left as is.Generated by Claude Code