Uh oh!
There was an error while loading. Please reload this page.
docs(create-objectstack): say that the blank starter ships no app - #10507
Merged
Conversation
Scaffolded with the real CLI against published 17.1.0 packages and booted with `objectstack dev --ui`: `GET /api/v1/meta/app` returns two items, both platform apps (setup, account), while `GET /api/v1/data/my_app_note` serves the scaffolded object for the whole session. The object is live and simply has no route into Console navigation. That is deliberate. `blank` is described in the registry as "Minimal starter — one object, REST API, ready to extend"; all three `os init` templates ship `src/objects/` only, including the one described as "Full application with objects"; and no `*.app.ts` has ever existed under `src/templates/**` in this repo's history. Apps are what the agent authors in step 2 of the root README's loop, not what the scaffolder pre-writes into every project. What was missing is the disclosure: `pnpm dev` prints the Console URL on every boot, and nothing the newcomer could reach explained why their object is not there. Adds a "The Console" section to the generated README naming the path, the consequence and `src/apps/*.app.ts` as the remedy, plus a bidirectional test — the template's own tree decides which README claim is required, so adding an app later cannot leave a stale "ships no app" green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019bmVFqoQPq63zhKrxdYG1r
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 1 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
os-elon
marked this pull request as ready for review
August 21, 2026 02:01
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 21, 2026
os-elon pushed a commit
that referenced
this pull request
Aug 21, 2026
Backs the three `src/templates/blank/` files out of this PR. They are the declared surface of #10321, which was promoted into sweep anchor #10353 — a queued card with its own PR contract ("zero changes outside the six items", one closing line per member). Sweeping them here would have left that member half-delivered by a PR that never named it, and `blank/README.md` is also touched by the open PR #10507. The canonical host is settled now, so #10321's open question ("dev states which and why") has an answer; that is recorded on the anchor rather than acted on here. The gate does not read these files — they are outside the published-doc population — so nothing goes red by leaving them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GawRwpD44VwBDVy3hs77AX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #10317. Verified at
1776d515c.That card is two defects wearing one title, with opposite fixes — (a) the template is
right and the README lies, or (b) the README is right and the template is incomplete.
This PR implements (a), and only after measuring. It deliberately does not implement (b);
the evidence below is why, and the remaining product call is left to the maintainer.
What actually renders — measured, not predicted
Scaffolded with the real CLI, installed against the published 17.1.0 packages, booted with
objectstack dev --ui, signed in as the seeded dev admin:The symptom the card describes is real: the scaffolder's own object is live over REST for the
whole session and sits in no app's navigation. (The card said "Your apps 1"; at head it is 2 —
accounthas since joinedsetup. The count is stale, the substance is not: zero of themcome from the scaffolded project.)
Why (a) — the template is deliberately empty
Not a taste call. Four independent readings agree:
template-registry.tsdescribesblankas"Minimal starter — one object, REST API, ready to extend" — the promise names REST, not
the Console.
initoffers alongside it.os inithas three templates —app,plugin,empty. All three writesrc/objects/only. The one literally described as"Full application with objects" ships no
*.app.tseither.so
blankis the sole template. Anything added here ships into every project everscaffolded, forever.
*.app.tshas ever existed underpackages/create-objectstack/src/templates/**.(b) would be adding something new, not restoring something lost.
And
README.md:69does not say what the card reads it as saying. It is step 3 of athree-step loop whose step 2 has the agent author the ticket object, the Resolve action,
an "Open tickets" list view and a Support nav group. "The Console renders the real app" is a
claim about what you build in step 2 — not about the scaffolder's output. The generated
template README never promised a Console either: it says "a clean slate for building" and
already lists "Add a view or app" under Next steps.
So the card's headline premise — the README promises the opposite — does not hold, and (b)
would be unrequested scope in every blank project forever.
What was actually broken, and what this changes
The real defect is the half both readings agree on, and it is the one the card names in its own
"Adjacent gap" section: nothing the newcomer can reach says an app is the missing piece —
while
pnpm devprints➜ Console: http://localhost:3000/_console/on every boot. The productsends them to a screen and never explains it.
This PR adds one section to the generated
README.mdnaming the Console path, the consequence,and
src/apps/*.app.tsas the remedy. Documentation only — no change to what the scaffolderwrites into
src/.Reverse verification
Runtime, from real scaffold-and-boot runs — proving the instruction this PR ships is true.
One
*.app.tsadded to the scaffolded project (not to the template), rebooted:GET /api/v1/meta/app2—setup,account3—my_app_main,setup,accountThe project app carries
nav_notes → objectName: my_app_note. The emptysrc/apps/is theentire cause and an app is the entire remedy — exactly what the new README section now says.
The test. Reverting only the README to
origin/mainand re-running the new file:The three tree/vacuity assertions stayed green — the failure is the disclosure, which is the
predicted direction. The README was then restored from the commit and confirmed byte-identical.
The assertion is bidirectional on purpose: the template's tree decides which README claim is
required, so if someone later adds an app to the template, the stale "ships no app" sentence
fails rather than sitting green on a claim that has become false.
Gates
Re-derived with
node scripts/pm/dispatch-gates.mjs(no path arguments) after the final commit,on a clean tree —
committed 3, working tree 0, untracked 0. The dispatch brief named no gatefamily; all of these are newly derived. Each line below is the gate's own verdict.
check:changeset-gate-self-tests✓ check-empty-changeset --self-test: 118 assertions over real temp git reposcheck:objectui-changeset✓ objectui-range --self-test: all checks passedcheck:slot-lookup✓ slot-lookup ratchet holds: 107 unswept site(s) in 25 file(s), none newcheck:template-version-sync✓ sync-template-versions --self-test: 40 assertions over temp fixturescheck-adr-0087-registration.mjs✓ this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen).check-changeset-no-major.mjs✓ This diff introduces no 'major' bump.check-empty-changeset.mjs✓ No empty-frontmatter changeset introduced by this diff (1 declaring changeset(s) added).docs-audit/check-affected-docs.mjs✓ affected-docs self-test: 262 cases pass.Convention-triggered by adding a test file:
check:query-options-erasure✓ query-options-erasure ratchet holds: 67 unswept non-test site(s) in 17 file(s), none newcheck:engine-double-contractcheck-engine-double-contract: OK — 340 pinned, 133 in the DEBT ledger, 2 exempt.check:where-matcher✓ where-matcher conformance holds: 266 matcher(s) discovered … 0 silently-wrong … none new.check:type-check-coveragecheck-type-check-coverage: OK — 64/77 workspace packages type-checked (plus the root), 13 in the DEBT ledger, 1 exempt.Plus
check:nul-bytes→check-nul-bytes: OK (scanned 6145 text file(s) … no raw ASCII control bytes).and
pnpm --filter create-objectstack typecheck && … test→Test Files 8 passed (8) · Tests 88 passed (88).One family declared NOT MEASURED locally:
check:type-check-debt. Its--re-measurepathrefuses on this worktree — "55 workspace dependenc(ies) of the ledgered packages have no built
type entry point on disk" — and that refusal means not-measured, never not-applicable. It needs
a full 77-package
turbo run build, and the shared verify lock had two agents queued behind me,so holding it for that was disproportionate to a three-file documentation change. What bounds the
risk:
create-objectstackcarries no ledger entry in eitherDEBTorTEST_DEBT, and--re-measureonly re-runs tsc for ledger entries, so a new test file here cannot move a ledgernumber. The half my change could move — the structural one, a test file no tsc program reaches —
ran green above, and the file is provably inside the package's program (
tsconfig.jsonisinclude: ["src"], excluding onlysrc/templates, and the package typecheck passes with the filepresent). CI runs the family regardless.
Fences
objectstack initscaffolds a project whosepnpm installexits 1 on pnpm 11 — its rendered pnpm-workspace.yaml omitsallowBuilds#10405 owns the renderedpnpm-workspace.yamland [finding] The scaffolder's "Created files" list names 12 files and omits AGENTS.md, both ~968 KB skill trees and the lockfiles — then tells you to review the skills it did not name #10323 owns the "Created files" listing insrc/index.ts. Thisdiff touches neither.
this same file,
blank/README.md: [finding] One scaffold run writes three different documentation hostnames — objectstack.ai, objectstack.com, docs.objectstack.ai #10321 (doc-hostname convergence) and [finding] npm vs pnpm vsnpm run: a newcomer gets three different answers to "what do I run next", and the generated README omitsvalidateentirely #10322 (onepackage manager everywhere; lead with
dev+validate). Both are unassigned with no branch andno worktree, so nothing is in flight on the file and there was nothing to serialize against — but
whichever lands second will need to merge. Worth knowing: sweep: first-touch text corrections across the newcomer surface — root README + create-objectstack output (6 members from the #10264 audit) #10353's exclusion list drops [finding] The blank template ships no app, so the Console renders nothing the scaffolder wrote — the README promises the opposite #10317 as
a "behaviour change to template content", and the measurement above falsifies that premise —
the surviving half of [finding] The blank template ships no app, so the Console renders nothing the scaffolder wrote — the README promises the opposite #10317 is text, which is exactly sweep: first-touch text corrections across the newcomer surface — root README + create-objectstack output (6 members from the #10264 audit) #10353's defect class. My new section uses
pnpm, matching the file today; if [finding] npm vs pnpm vsnpm run: a newcomer gets three different answers to "what do I run next", and the generated README omitsvalidateentirely #10322 converges onnpm, this section moves with it.content/docs/releases/**.retry-wrapped.
Deliberately left open
This PR is scoped with
Part ofdeliberately, so that #10317 stays open on merge. Two thingsit raises are not settled here:
blank, on thefour readings above. That is a recommendation, not a ruling, and it is the maintainer's to make.
os validatesilence the card flags — filed separately as [finding]os validatedrops the wholeUI:row at zero apps, so a project with no navigable UI reads identically to one that was never asked #10504, unassigned. Measuredthere: at zero apps the
UI:row is not printed as0, it is absent, so "no navigable UI"and "this summary does not report on UI" read identically. That lives in
packages/cli, outsidethis card's file fence. Note the measurement also argues against the card's suggested shape: a
warning would fire on every clean scaffold, since zero apps is the intended blank state — a
printed
UI: 0 Appsis the cheaper reading.Generated by Claude Code
Generated by Claude Code