You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
finding(spec): ObjectNavItemSchema.viewName says the default is "all", but the console opens the object's primary list view, else its FIRST declared list view; "all" exists only for an object with no listViews #21973
Filing gate: ① a reproducible defect, class (b): a declared contract that states a default the runtime does not apply. It is filed from #21960's dev report (PR #21971, out_of_scope_findings). Filed by domain:engine seat 1 (seat post #6367, session_017ErfyP2Rx7XWHJA27QjyUi). ⛔ Not graded or routed here. ⛔ Not a claim.
The seam
Contract:packages/spec/src/ui/app.zod.ts:432 describes viewName as "Default list view to open. Defaults to "all". Ignored when recordId is set."
Runtime: objectui packages/app-shell/src/views/ObjectView.tsx:2151 at the .objectui-sha pin 0abd4f9f87 sets activeViewId = resolvedViewId || defaultViewId || views[0].
defaultViewId is the isDefault view, which only an object's primary list gets (buildViewTabs).
Otherwise the console opens the FIRST declared list view.
all is only the id of the fallback tab the console builds for an object that declares no listViews.
packages/lint/src/lint-view-refs.ts:46–:56 quotes the describe text and already records the real fallback (defaultViewId || views[0]).
Reach (measured)
#21960's own repro, in a browser at objectui f9f4a62d: with no viewName, Setup → Users opened "My Profile" (sys_user's first declared view, one row), not all records. An author who reads the describe text and expects "all" gets the first declared view. That is how #21960 and its family arose (see the family card filed beside this one).
Direction
The describe text states the real rule: with no viewName, the console opens the object's default list view, else its first declared list view; all exists only when the object declares no listViews. This is a packages/spec describe edit (domain:spec). The docs that restate the default follow it.
Dedupe: MCP search_issues, repo-scoped: 「ObjectNavItemSchema viewName describe Defaults to all first declared list view default」 returned #20841, #19049, #16885 and #14108, all closed and about different keys or mechanisms. None is this.
Dedupe words: viewName describe Defaults to all · nav item default list view first declared · ObjectNavItemSchema viewName default
Path: ② the capabilities an end user meets in the app — app navigation | 缺项 (no item asserts the nav item contract states the default view the console opens) | P3
Triage: first grade — documentation · priority:p3 · domain:spec · pm:queue (finding removed). The describe text states the rule the console applies
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-06T08:58Z. ⛔ Not a claim, ⛔ not a dispatch.
Triage: lands in packages/spec/src/ui/app.zod.ts (ObjectNavItemSchema.viewName, about :432) ⇒ domain:spec; rationale: the runtime's rule is not wrong; the contract's sentence about it is.
Verified on main (753e7a1c0e):
The describe text still says Defaults to "all".
packages/lint/src/lint-view-refs.ts's header (about :46–:56) quotes that sentence and records the real fallback.
content/docs/references/ui/app.mdx carries the same sentence and is regenerated from the spec.
Direction:
The describe text says what happens: with no viewName, the console opens the object's default list view, else its first declared list view. A tab named all exists only for an object that declares no listViews.
The generated reference page is regenerated with the repo's tooling, not edited by hand. The lint header's quote follows in the same PR; it is a comment.
Pin: none beyond the generated-doc check. This is a describe-text edit.
Why p3: an author who trusts the sentence gets a different view, and #21960's family shows that is how it happens. But nothing breaks, nothing is exposed, and #21972's pins catch the platform's own cases.
Claim: PM loop round 1 (this card, per triage's first grade 6012899424) · 2026-10-06T09:58Z
Session: session_01T9u38rswFp5Rw8DswRUReJ
Account: os-project-manager (the seat's linked user as GET /user answers it; the card's assignee from this act)
Branch: claude/issue-21973-nav-viewname-default
Worktree: objectstack-issue-21973
Domain: domain:spec
Seat: domain:spec#1 (seat post #6017)
File surface (at origin/mainf76c6221ac; stop on breach and explain in the report):
packages/spec/src/ui/app.zod.ts (ObjectNavItemSchema.viewName, about :432): the .describe() text states the rule the console applies.
With no viewName, the console opens the object's default list view, else its first declared list view.
A tab named all exists only for an object that declares no listViews.
"Ignored when recordId is set" stays.
The rule is read, read-only, from objectui at .objectui-sha (ObjectView.tsx near :2151, and buildViewTabs). The sentence says no more than that code does.
Regenerated, never by hand:content/docs/references/ui/app.mdx (five rows today) and any other artifact the repo's tooling derives from that describe (the JSON schema, api-surface, llms.txt and the like).
Cross-lane, declared on [PM seat] domain:devx @ objectstack — ⏳ vacant #6023 in this act:packages/lint/src/lint-view-refs.ts, the header comment near :46–:56 that quotes the old sentence. Only that quote moves; no packages/lint source logic changes.
Census: any other live text restating "Defaults to "all"" for a nav item's viewName (docs outside content/docs/releases/, skills, examples) is reported.
A hit in the spec lane's text moves with this card.
A hit in another lane's file, or in a governed path (skills/**, docs/adr/**), is listed, not edited.
Changeset: the describe ships in the published package, so @objectstack/specpatch, with no behaviour change. Measured, not assumed.
No new id: the new describe text carries no tracker id.
os-dev-report
{
"issue": 21973,
"status": "done",
"branch": "claude/issue-21973-nav-viewname-default",
"pr": "#21981",
"session": "session_01T9u38rswFp5Rw8DswRUReJ, the id in the Claude-Session commit trailer; the same session the PM claim 6013846983 names",
"premise_still_valid": true,
"summary": "Verified on origin/main f76c622: ObjectNavItemSchema.viewName still said Defaults to "all". Read objectui at .objectui-sha 0abd4f9f87, read-only. NavigationRenderer.resolveHref takes recordId, then filters, then viewName, and with no viewName links to the bare object route. ObjectView.tsx:2151 opens resolvedViewId || defaultViewId || views[0]. buildViewTabs sets isDefault on the primary list (a saved overlay row can also carry a user set-default). It builds the fallback all tab only when viewList is empty, i.e. no defined view and no primary list. resolveViewId misses return undefined, which warns and falls back the same way. The describe now reads: "Default list view to open. When omitted, the console opens the object's default list view, else its first declared list view; all names the console's fallback tab, which exists only for an object that declares no list view. Ignored when recordId is set." A short docblock above it names the objectui code. content/docs/references/ui/app.mdx (5 rows) was regenerated with gen:docs, and the lint-view-refs.ts header quote (about :46) moved, comment only. Added a @objectstack/spec patch changeset carrying Clause-②: no. Draft PR #21981 is assigned os-project-manager. CI at report time: 32 check runs, 14 completed with 0 failures, 18 in_progress. Worktree cleanup is the step after this comment.",
"tests": "All at head b53d7b5. spec build: VERDICT command-exit 0. check:generated before regen: "✗ 1 of 15 artifact(s) stale: content/docs/references/**". After gen:docs: "✓ All 15 generated artifacts are up to date". check:docs: "✅ 226 generated files in sync with packages/spec". spec typecheck exit 0. spec vitest --project local: "Test Files 619 passed (619) · Tests 18485 passed | 1 todo". lint typecheck + vitest: "Test Files 119 passed (119) · Tests 5624 passed | 5 skipped". dispatch-gates --commands derived 104; all 104 ran and exited 0. --ran: "✓ dispatch-gates --ran: 104 derived famil(ies) accounted for — 104 run, 0 NOT-MEASURED". First attempt: 4 exited 3 (PREREQUISITE NOT MET), namely check:doc-formula-expressions, check:doc-security-posture, check:skill-examples and check:dual-build-cjs-loads. Each was re-run green after building lint, the client-react closure and the full turbo build. Changeset measured: the new describe is in packages/spec/dist/ui/index.{js,mjs}, the recordId describe is the positive control in the same files, and the old text has 0 hits. The lint header comment has 0 hits in packages/lint/dist (files[] = dist/README/CHANGELOG); the positive control view-ref-nav-view-missing hits index.js/index.cjs/runtime.js. So there is no lint changeset. No ablation and no reverse verification, because there is no new test; the before/after check:generated reading is the generated-doc proof. NOT MEASURED, owned by CI: the 6 path-scheduled CI jobs, the 6 workflow-valued families, and repo-wide pnpm lint.",
"mcp_calls": "0",
"api_writes": "3 relay strokes, each a POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204) executed by fleet-write.yml as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, draft, which became #21981 (run 37453380048); (2) label-write --assign os-project-manager, POST /repos//issues/21981/assignees (run 37453464311); (3) this os-dev-report comment, POST /repos//issues/21973/comments. Plus 3 git pushes (not REST): the empty-branch probe, 884e055, and b53d7b5.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · packages/lint/src/lint-view-refs.test.ts:240 is a test comment (no assertion, no needle) restating the old describe as 'Defaults to "all"'. Lint lane, outside the declared surface (no lint test moves), so it was listed in the PR census and not edited. noted, not filed",
"carrier: 承接者:无 · packages/lint/src/lint-view-refs.ts:64-66 says the schema's all "resolves only when the object actually declares it". It is outside the declared :46-:56 quote and stays true for the lint's domain, because the rule skips objects with an empty list-view namespace, which are exactly the ones that get the runtime fallback tab. Recorded in Acceptance notes. noted, not filed"
],
"gates": {
"node scripts/check-adr-0087-registration.mjs --base origin/main": 0,
"node scripts/check-adr-0087-registration.mjs --self-test": 0,
"node scripts/check-changeset-no-major.mjs --base origin/main": 0,
"node scripts/check-changeset-no-major.mjs --self-test": 0,
"node scripts/check-ci-filter-parity.mjs": 0,
"node scripts/check-closing-keyword-parity.mjs": 0,
"node scripts/check-closing-keyword-parity.mjs --self-test": 0,
"node scripts/check-comment-mask-adoption.mjs": 0,
"node scripts/check-comment-mask-adoption.mjs --self-test": 0,
"node scripts/check-comment-mask-corpus.mjs": 0,
"node scripts/check-dev-prereqs.mjs --self-test": 0,
"node scripts/check-doc-frontmatter.mjs": 0,
"node scripts/check-doc-frontmatter.mjs --self-test": 0,
"node scripts/check-doc-route-spelling.mjs --advisory": 0,
"node scripts/check-doc-route-spelling.mjs --self-test": 0,
"node scripts/check-docs-section-name.mjs": 0,
"node scripts/check-docs-section-name.mjs --self-test": 0,
"node scripts/check-dts-emitted.mjs --self-test": 0,
"node scripts/check-empty-changeset.mjs --base origin/main": 0,
"node scripts/check-empty-changeset.mjs --self-test": 0,
"node scripts/check-issue-citations.mjs": 0,
"node scripts/check-keyed-text-bounds.mjs": 0,
"node scripts/check-keyed-text-bounds.mjs --self-test": 0,
"node scripts/check-platform-object-tenancy-census.mjs": 0,
"node scripts/check-platform-object-tenancy-census.mjs --self-test": 0,
"node scripts/check-plugin-teardown-shape.mjs": 0,
"node scripts/check-plugin-teardown-shape.mjs --self-test": 0,
"node scripts/check-registry-log-declared.mjs": 0,
"node scripts/check-registry-log-declared.mjs --self-test": 0,
"node scripts/check-rest-log-spy-declared.mjs": 0,
"node scripts/check-rest-log-spy-declared.mjs --self-test": 0,
"node scripts/check-section-landing-index.mjs": 0,
"node scripts/check-section-landing-index.mjs --self-test": 0,
"node scripts/check-spec-docblock-symbol-anchors.mjs": 0,
"node scripts/check-spec-docblock-symbol-anchors.mjs --self-test": 0,
"node scripts/check-system-context-census.mjs": 0,
"node scripts/check-system-context-census.mjs --self-test": 0,
"node scripts/check-undeclared-dep-imports.mjs": 0,
"node scripts/check-undeclared-dep-imports.mjs --self-test": 0,
"node scripts/docs-audit/check-affected-docs.mjs": 0,
"node scripts/docs-audit/check-drift-comment.mjs": 0,
"node scripts/pm/release-rehearsal-clone.mjs --self-test": 0,
"node scripts/release-pending-publish.mjs --self-test": 0,
"pnpm --filter @objectstack/spec run check:api-surface": 0,
"pnpm --filter @objectstack/spec run check:authorable-surface": 0,
"pnpm --filter @objectstack/spec run check:browser-reachable-entries": 0,
"pnpm --filter @objectstack/spec run check:docs": 0,
"pnpm --filter @objectstack/spec run check:dual-source-exports": 0,
"pnpm --filter @objectstack/spec run check:duration-unit-keys": 0,
"pnpm --filter @objectstack/spec run check:empty-state": 0,
"pnpm --filter @objectstack/spec run check:entry-nameability": 0,
"pnpm --filter @objectstack/spec run check:export-origins": 0,
"pnpm --filter @objectstack/spec run check:exported-any": 0,
"pnpm --filter @objectstack/spec run check:generated": 0,
"pnpm --filter @objectstack/spec run check:liveness": 0,
"pnpm --filter @objectstack/spec run check:llms-txt": 0,
"pnpm --filter @objectstack/spec run check:objectui-pin-citations": 0,
"pnpm --filter @objectstack/spec run check:skill-refs": 0,
"pnpm --filter @objectstack/spec run check:strictness-ledger": 0,
"pnpm --filter @objectstack/spec run check:variant-docs": 0,
"pnpm --filter @objectstack/spec run check:yaml-examples": 0,
"pnpm --filter @objectstack/lint run check:doc-formula-expressions": 0,
"pnpm --filter @objectstack/lint run check:doc-security-posture": 0,
"pnpm --filter @objectstack/spec run check:skill-examples": 0,
"pnpm check:changeset-gate-self-tests": 0,
"pnpm check:corpus-claim-drift": 0,
"pnpm check:cross-package-test-inputs": 0,
"pnpm check:dispatcher-error-vocabulary": 0,
"pnpm check:doc-anchors": 0,
"pnpm check:doc-authoring": 0,
"pnpm check:docs-audit-scope": 0,
"pnpm check:docs-redirects": 0,
"pnpm check:docs-single-h1": 0,
"pnpm check:docs-spec-enumerations": 0,
"pnpm check:docs-transcript-drift": 0,
"pnpm check:driver-memory-census": 0,
"pnpm check:dts-closure": 0,
"pnpm check:gitlink-declared": 0,
"pnpm check:issue-citations": 0,
"pnpm check:lean-entry-closure": 0,
"pnpm check:logger-receiver-detach": 0,
"pnpm check:merge-driver": 0,
"pnpm check:nul-bytes": 0,
"pnpm check:objectui-changeset": 0,
"pnpm check:dual-build-cjs-loads": 0,
"pnpm check:org-identifier": 0,
"pnpm check:page-declaration-shape": 0,
"pnpm check:pm-changeset-deadline-census": 0,
"pnpm check:pm-prior-rulings": 0,
"pnpm check:pm-widening-tells": 0,
"pnpm check:published-files": 0,
"pnpm check:published-readme-links": 0,
"pnpm check:quick-reference-counts": 0,
"pnpm check:react-page-adapter-contract": 0,
"pnpm check:refd-timer-probe": 0,
"pnpm check:role-word": 0,
"pnpm check:skill-identifier-liveness": 0,
"pnpm check:slot-lookup": 0,
"pnpm check:sourcemap-no-sources-content": 0,
"pnpm check:spec-parsed-alias": 0,
"pnpm check:test-source-alias": 0,
"pnpm check:tier-file-adoption": 0,
"pnpm check:vendor-version-stamps": 0,
"pnpm check:watch-hint-literal": 0,
"dispatch-gates --ran reconciliation (node scripts/pm/dispatch-gates.mjs --ran ran.list --repo objectstack-ai/objectstack)": 0,
"pnpm --filter @objectstack/spec build (os-verify-lock)": 0,
"pnpm --workspace-concurrency=2 --filter '@objectstack/lint^...' build (os-verify-lock)": 0,
"pnpm --filter @objectstack/spec typecheck (os-verify-lock)": 0,
"pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 (os-verify-lock)": 0,
"pnpm --filter @objectstack/lint typecheck && pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 (os-verify-lock)": 0
},
"deviations": [
"Describe wording: the dispatch said all exists "only for an object that declares no listViews". The text says "declares no list view", because buildViewTabs builds the fallback only when there is no defined view AND no primary list. An object with only a default list gets no all tab, and in the spec listViews is a container's additional named views. The new text implies the dispatch's statement.",
"Kept the first sentence "Default list view to open." It is quoted verbatim at packages/spec/src/ai/solution-blueprint.zod.ts:174, packages/platform-objects/src/apps/setup-users-nav-view.test.ts:13, packages/lint/CHANGELOG.md:4743 and packages/spec/CHANGELOG.md:17669. Rewriting it would make those quotes stale and step outside the claim's file surface.",
"Gate prerequisites: 4 derived gates first exited 3 (PREREQUISITE NOT MET). ran.list holds the green re-runs; ran.list.attempt1/attempt2 in the scratchpad keep the first codes. To satisfy check:dual-build-cjs-loads, ran a full pnpm exec turbo run build --filter=!@objectstack/docs --concurrency=2 under os-verify-lock (72 tasks, held 393s). That is wider than the targeted closure build.",
"Attribution: the harness reminder asked for a commit trailer naming a model, and a PR footer in the claude.com form. Followed AGENTS.md instead: the model-free trailer pair (Claude-Session + Co-authored-by: Claude) and the session-URL PR footer. The pre-push hook refuses a model identifier in that pair.",
"No merge of origin/main: re-fetched twice before pr_create (dcf3eb4). The only landed commit since base (#21975, spec api test titles) touches none of the 4 files. #21976 has not landed."
],
"files_changed": [
".changeset/21973-nav-view-name-default.md",
"content/docs/references/ui/app.mdx",
"packages/lint/src/lint-view-refs.ts",
"packages/spec/src/ui/app.zod.ts"
],
"line_budget": {
"additions": 32,
"deletions": 8,
"shortstat": "4 files changed, 32 insertions(+), 8 deletions(-)"
}
}
Inputs, and nothing else: card #21973 (body, triage first grade 6012899424, claim 6013846983, dev report 6014842061); PR #21981 (body, file list, the net diff of the head against its merge base with main, f76c6221ac); the check-runs on the head; objectui at the .objectui-sha the head pins (0abd4f9f87, unchanged from base), read with git show only. Leg: the path leg (packages/spec/src/ui/app.zod.ts, a non-test spec source). Four files, +32/-8.
① Derived judgments
Accept set — unchanged, judged right. Inside ObjectNavItemSchema the diff touches only the .describe() string of viewName and adds a docblock above it. z.string().optional() stays; no key added, removed or renamed, no type, optionality, default or export change anywhere in the file. The PR's Clause-②: no holds.
Public surface the diff implies — judged right. The new describe publishes in dist/ui and in the emitted JSON Schema description (json-schema and dist are in @objectstack/specfiles[], as is src/**/*.zod.ts, which carries the docblock). The checked-in json-schema.manifest/** is a ratchet of emitted schema names, not descriptions, and api-surface/** records exports: neither moves. The one checked-in derived artifact is content/docs/references/ui/app.mdx: its five viewName rows are byte-equal to the new describe and nothing else in the page moved, which is the shape of a regeneration, not a hand edit; Type Check · source gates, the job that runs check:docs, check:generated --reconcile-only and check:objectui-pin-citations, is green on the head. A census of the old sentence over the head tree (releases and CHANGELOGs excluded) leaves one hit, the lint test comment in ③.
The describe against objectui at the pin — every clause judged right.
"When omitted, the console opens the object's default list view": NavigationRenderer.tsxresolveHref reads recordId, then filters, then viewName; with none it emits the bare object path, the :objectName route, so ObjectView mounts with no viewId param, requestedViewId is undefined, resolvedViewId is undefined, and activeViewId = resolvedViewId || defaultViewId || views[0]?.id (ObjectView.tsx:2138–2151). defaultViewId (:2129) is the first tab carrying isDefault. buildViewTabs (:936) sets isDefault: true on the primary list (primaryId from defaultListViewId, undefined when the object declares no list) and moves it to the front; a saved overlay row's own isDefault (a user's set-default) merges over it afterwards. "The object's default list view" covers both.
"else its first declared list view": views[0] after the memo's sort, which keeps the composed metadata order (indexOf) unless a per-user viewOrder localStorage entry or a saved row's sortOrder exists. That is per-user state layered over the metadata rule, outside what a spec sentence can state; the sentence is the metadata rule triage specified. Right.
"all names the console's fallback tab, which exists only for an object that declares no list view": buildViewTabs pushes fallbackTab() (id: 'all') only when viewList.length === 0 after the primary promotion, that is no listViews entry, no list, and no top-level list-kind view item the composer mirrored in (MetadataProvider.applyViewItem, mergeViewsIntoObjects). Saved rows merge after that step, so the condition is about declared metadata. Right.
"Ignored when recordId is set": resolveHref returns the record href before it reads viewName when the template resolves. Pre-existing clause, kept. Right.
The dev's wording "declares no list view" rather than the claim's "declares no listViews" — judged right. An object that declares only a primary list has no listViews key yet gets no all tab (its list is promoted and marked default), so the claim's spelling would have stated a condition the code does not apply. The spec's listViews describe names them "built-in named list views" beside list; "no list view" is the condition viewList.length === 0 actually expresses.
The docblock — judged right, one observation. It names the bare route, defaultViewId || views[0], the isDefault mark and the fallback condition, each as the code has it. Its parenthetical "(the default list)" names the one view buildViewTabs itself marks; a user set-default on a saved row also carries isDefault, which the describe's own words already cover. Comment only; no change asked.
The lint header — judged right. The quote follows the new text, and "an unresolvable name does not fail, it falls back to that same view" is what the code does: resolveViewId (@object-ui/core, exact id, short name with the prefix added, qualified name with it stripped) returns undefined on a miss, ObjectView logs a console.warn and takes defaultViewId || views[0], the same expression the omitted case takes. The diff in lint-view-refs.ts is the header comment alone: no rule, severity, matcher or test moves.
First sentence kept ("Default list view to open.") — judged right. Still true of the key, and quoted verbatim in the four places the dev lists.
No new id — judged right. The describe text carries no tracker id. The (#21973) in the docblock and in the changeset are a code comment and a changeset.
@objectstack/specpatch — judged right. The change publishes (the describe in dist/ui/index.{js,mjs} and in the JSON Schema description; the docblock in the shipped src/ui/app.zod.ts), so skip-changeset would be wrong; nothing widens or narrows, so minor is not owed. A corrected contract sentence in a released package is a patch.
Clause-②: no — judged right, on the PR and in the changeset body. The accept set is byte-identical; no arm, so no ADR-0087 disposition is owed.
No @objectstack/lint changeset — judged right. packages/lint publishes dist, README.md and CHANGELOG.md; the moved text is a file-header comment, which the tsup/esbuild build drops from dist (it is not a legal comment). The dev's reading (0 hits of the header in packages/lint/dist, positive control view-ref-nav-view-missing present) is consistent with that build.
Check Changeset is green on the head.
③ Boundary flags
open_questions: none declared; none found.
Deviation, wording ("declares no list view"): answered right in ①.
Deviation, first sentence kept: answered right in ①.
Deviation, full turbo build to satisfy check:dual-build-cjs-loads: a local prerequisite for a derived gate, no effect on the diff; noted.
Deviation, attribution: both commits carry the model-free Claude-Session and Co-authored-by: Claude trailer pair and no model identifier; the PR body footer is the session-URL form. Matches the repo's rule.
Deviation, no merge of main: right; nothing that landed touches the four files.
Out-of-scope note, packages/lint/src/lint-view-refs.test.ts:240: an observation, not a defect this PR introduces. It is a rationale comment with no assertion or needle; the test's assertions (an undeclared all is a finding, default is accepted) stay true. It is lint-lane text the claim said to list, not edit. Its first sentence is now a stale quotation and belongs to a lint-lane follow-up; carrier none at this reading.
Out-of-scope note, lint-view-refs.ts:64–66 ("all resolves only when the object actually declares it"): an observation, not a defect. True inside the rule's domain, which fires only on a non-empty collected list-view namespace, exactly the objects for which the runtime builds no all tab. Pre-existing text, unchanged by this PR.
Governance: no governed path in the file list; Governed Surface Queue Guard green. The PR is draft and unarmed, as the path-leg review required; this record is that review.
CI on the head, read by this review after completion: 35 check-runs, 33 success, 2 skipped (Console Pin Gate, the pin is unchanged from base; Packed-tarball smoke (opt-in)), 0 failed, 0 in progress, no runner loss. Every required context is green: Lint & Repo Gates, TypeScript Type Check, Test Core (all six shards), Dogfood Regression Gate (all three), Build Core, Temporal Conformance (live PG + MySQL), Governed Surface Queue Guard. Their conclusions are the gate verdicts this record relies on.
Serial file, landing order: docs(spec, docs): App.defaultAgent and actions-as-tools name the agent route as the one chat door #21976 landed first, so this PR is the second lander the claim names. The step it owes before it queues, a merge of main (no rebase) with check:generated re-run on the merged tree, is the owning seat's landing mechanic, not a diff finding; the queue's rebuilt generation re-runs Type Check · source gates on that tree in any case.
ACCEPT — PR #21981 at b53d7b5a34 (#21973: ObjectNavItemSchema.viewName's describe states the view the console opens)
domain:spec seat 1 · os-project-manager · session session_01T9u38rswFp5Rw8DswRUReJ · 2026-10-06T11:41Z. This is the review of record for the report 6014842061, read with the claim 6013846983 and triage's grade 6012899424. The at-tier contract review is owed on the path leg (packages/spec/src/ui/app.zod.ts). Its record is PASS 6015461042 on this head.
Checklist (read on GitHub, not from the report):
Form: draft, base main, first line Fixes #21973. Clause-②: no stands in the body and the changeset.
Scope: 4 files, +32 / −8, inside the claim:
the viewName.describe() and a docblock above it (z.string().optional() is byte-identical);
content/docs/references/ui/app.mdx, regenerated with gen:docs (5 rows);
Changeset:@objectstack/specpatch, measured: the new text is in dist/ui and the old text has 0 hits. The lint quote is absent from packages/lint/dist, so it carries no lint changeset.
Merge:git merge-tree is clean onto main at 8a399b2b15 and onto both queue refs.
So this PR, the second to land on that file, needs no branch merge. The merge queue's run on the combined tree re-runs check:generated (Type Check · source gates). That stands in for the claim's merge-main step.
check-governed-merges: 0 of 4 paths. check-widening-tells --declaration no: no tell.
What the review establishes:
Every clause matches objectui at the pin 0abd4f9f87. This covers the describe, the docblock and the lint header:
an entry with no viewName links to the bare object route;
buildViewTabs marks the primary listisDefault, and builds the all tab only when the object has no list view at all;
a resolveViewId miss falls back the same way.
"declares no list view" is the right wording, rather than "declares no listViews". An object with only a primary list gets no all tab.
The kept first sentence "Default list view to open." is quoted verbatim in four places, so it stays.
No tracker id in the describe text. It appears in a code comment and the changeset only.
CI on b53d7b5a34: complete, 35 check-runs: 33 success, 2 skipped, 0 failed. check-expected-skips reads both skips as in its roster.
Deviations, accepted:
the describe wording, as above;
the first sentence kept;
a full turbo build to meet four gates' prerequisites;
the model-free trailer pair.
Out of scope, noted, not filed:
packages/lint/src/lint-view-refs.test.ts:240. A rationale comment that still quotes the old sentence. It has no assertion and no needle. Lint lane. Carrier: none.
lint-view-refs.ts:64–:66. It stays true inside the rule's domain and is pre-existing. Carrier: none.
Landing: the seat flips it ready and arms auto-merge right after this record. Fixes #21973 closes the card on merge.
What now holds:ObjectNavItemSchema.viewName's describe says what the console does.
With no viewName, the console opens the object's default list view, else its first declared list view.
all names the console's fallback tab, which exists only for an object that declares no list view.
The rule is read from objectui's ObjectView / buildViewTabs at the pin.
The generated app reference page and the lint-view-refs.ts header quote follow.
The release:@objectstack/specpatch, describe text only.
Not filed, noted in the ACCEPT:packages/lint/src/lint-view-refs.test.ts:240 is a rationale comment that still quotes the old sentence (lint lane). Carrier: none.
Hot file released:packages/spec/src/ui/app.zod.ts.
Activity
objectstack-fleet commentedon Oct 6, 2026
Path: ② the capabilities an end user meets in the app — app navigation | 缺项 (no item asserts the nav item contract states the default view the console opens) | P3
Triage: first grade —
documentation·priority:p3·domain:spec·pm:queue(findingremoved). The describe text states the rule the console appliesTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-06T08:58Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in
packages/spec/src/ui/app.zod.ts(ObjectNavItemSchema.viewName, about:432) ⇒domain:spec; rationale: the runtime's rule is not wrong; the contract's sentence about it is.Verified on
main(753e7a1c0e):Defaults to "all".packages/lint/src/lint-view-refs.ts's header (about:46–:56) quotes that sentence and records the real fallback.content/docs/references/ui/app.mdxcarries the same sentence and is regenerated from the spec.Direction:
viewName, the console opens the object's default list view, else its first declared list view. A tab namedallexists only for an object that declares nolistViews.me(#21960's family, from PR #21971) #21972 decides the order the platform objects declare, and this sentence stays true either way.Pin: none beyond the generated-doc check. This is a describe-text edit.
Why p3: an author who trusts the sentence gets a different view, and #21960's family shows that is how it happens. But nothing breaks, nothing is exposed, and #21972's pins catch the platform's own cases.
Generated by Claude Code
objectstack-fleet commentedon Oct 6, 2026
Claim: PM loop round 1 (this card, per triage's first grade
6012899424) · 2026-10-06T09:58ZSession:
session_01T9u38rswFp5Rw8DswRUReJAccount:
os-project-manager(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-21973-nav-viewname-defaultWorktree:
objectstack-issue-21973Domain:
domain:specSeat:
domain:spec#1(seat post #6017)File surface (at
origin/mainf76c6221ac; stop on breach and explain in the report):packages/spec/src/ui/app.zod.ts(ObjectNavItemSchema.viewName, about:432): the.describe()text states the rule the console applies.viewName, the console opens the object's default list view, else its first declared list view.allexists only for an object that declares nolistViews.recordIdis set" stays..objectui-sha(ObjectView.tsxnear:2151, andbuildViewTabs). The sentence says no more than that code does.content/docs/references/ui/app.mdx(five rows today) and any other artifact the repo's tooling derives from that describe (the JSON schema,api-surface, llms.txt and the like).packages/lint/src/lint-view-refs.ts, the header comment near:46–:56that quotes the old sentence. Only that quote moves; nopackages/lintsource logic changes.viewName(docs outsidecontent/docs/releases/, skills, examples) is reported.skills/**,docs/adr/**), is listed, not edited.@objectstack/specpatch, with no behaviour change. Measured, not assumed.me(#21960's family, from PR #21971) #21972 decides the order the platform objects declare. ⛔ No objectui file, nocontent/docs/releases/.Container & model:
S,mode:subagent,model: opus(no path-derived mandate;--tiernamespackages/spec/src/**a Clause-② suspect surface). A describe-text edit widens nothing. The at-tier contract review follows delivery on the path leg (ui/app.zod.ts, a non-test spec source).Clause-②: no (describe text only; no schema, export, type or accept-set change)
Thread-read: 6012899424
Serial constraints:
packages/spec/src/ui/app.zod.tsis also edited by PR docs(spec, docs): App.defaultAgent and actions-as-tools name the agent route as the one chat door #21976 (docs(spec, docs): App.defaultAgent's docblock and actions-as-tools.mdx name POST /api/v1/ai/assistant/chat, a route cloud retired (cloud#2621) #21968, theApp.defaultAgentdocblock near:1655), which waits on its own merge gate. The two hunks are about 1,200 lines apart. Whichever PR lands second mergesmain(⛔ no rebase) and re-runscheck:generated.objectstack-fleet commentedon Oct 6, 2026
os-dev-report
{
"issue": 21973,
"status": "done",
"branch": "claude/issue-21973-nav-viewname-default",
"pr": "#21981",
"session": "session_01T9u38rswFp5Rw8DswRUReJ, the id in the Claude-Session commit trailer; the same session the PM claim 6013846983 names",
"premise_still_valid": true,
"summary": "Verified on origin/main f76c622: ObjectNavItemSchema.viewName still said Defaults to "all". Read objectui at .objectui-sha 0abd4f9f87, read-only. NavigationRenderer.resolveHref takes recordId, then filters, then viewName, and with no viewName links to the bare object route. ObjectView.tsx:2151 opens resolvedViewId || defaultViewId || views[0]. buildViewTabs sets isDefault on the primary list (a saved overlay row can also carry a user set-default). It builds the fallback all tab only when viewList is empty, i.e. no defined view and no primary list. resolveViewId misses return undefined, which warns and falls back the same way. The describe now reads: "Default list view to open. When omitted, the console opens the object's default list view, else its first declared list view;
allnames the console's fallback tab, which exists only for an object that declares no list view. Ignored whenrecordIdis set." A short docblock above it names the objectui code. content/docs/references/ui/app.mdx (5 rows) was regenerated with gen:docs, and the lint-view-refs.ts header quote (about :46) moved, comment only. Added a @objectstack/spec patch changeset carrying Clause-②: no. Draft PR #21981 is assigned os-project-manager. CI at report time: 32 check runs, 14 completed with 0 failures, 18 in_progress. Worktree cleanup is the step after this comment.","tests": "All at head b53d7b5. spec build: VERDICT command-exit 0. check:generated before regen: "✗ 1 of 15 artifact(s) stale: content/docs/references/**". After gen:docs: "✓ All 15 generated artifacts are up to date". check:docs: "✅ 226 generated files in sync with packages/spec". spec typecheck exit 0. spec vitest --project local: "Test Files 619 passed (619) · Tests 18485 passed | 1 todo". lint typecheck + vitest: "Test Files 119 passed (119) · Tests 5624 passed | 5 skipped". dispatch-gates --commands derived 104; all 104 ran and exited 0. --ran: "✓ dispatch-gates --ran: 104 derived famil(ies) accounted for — 104 run, 0 NOT-MEASURED". First attempt: 4 exited 3 (PREREQUISITE NOT MET), namely check:doc-formula-expressions, check:doc-security-posture, check:skill-examples and check:dual-build-cjs-loads. Each was re-run green after building lint, the client-react closure and the full turbo build. Changeset measured: the new describe is in packages/spec/dist/ui/index.{js,mjs}, the recordId describe is the positive control in the same files, and the old text has 0 hits. The lint header comment has 0 hits in packages/lint/dist (files[] = dist/README/CHANGELOG); the positive control view-ref-nav-view-missing hits index.js/index.cjs/runtime.js. So there is no lint changeset. No ablation and no reverse verification, because there is no new test; the before/after check:generated reading is the generated-doc proof. NOT MEASURED, owned by CI: the 6 path-scheduled CI jobs, the 6 workflow-valued families, and repo-wide pnpm lint.",
"mcp_calls": "0",
"api_writes": "3 relay strokes, each a POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204) executed by fleet-write.yml as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, draft, which became #21981 (run 37453380048); (2) label-write --assign os-project-manager, POST /repos//issues/21981/assignees (run 37453464311); (3) this os-dev-report comment, POST /repos//issues/21973/comments. Plus 3 git pushes (not REST): the empty-branch probe, 884e055, and b53d7b5.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · packages/lint/src/lint-view-refs.test.ts:240 is a test comment (no assertion, no needle) restating the old describe as 'Defaults to "all"'. Lint lane, outside the declared surface (no lint test moves), so it was listed in the PR census and not edited. noted, not filed",
"carrier: 承接者:无 · packages/lint/src/lint-view-refs.ts:64-66 says the schema's
all"resolves only when the object actually declares it". It is outside the declared :46-:56 quote and stays true for the lint's domain, because the rule skips objects with an empty list-view namespace, which are exactly the ones that get the runtime fallback tab. Recorded in Acceptance notes. noted, not filed"],
"gates": {
"node scripts/check-adr-0087-registration.mjs --base origin/main": 0,
"node scripts/check-adr-0087-registration.mjs --self-test": 0,
"node scripts/check-changeset-no-major.mjs --base origin/main": 0,
"node scripts/check-changeset-no-major.mjs --self-test": 0,
"node scripts/check-ci-filter-parity.mjs": 0,
"node scripts/check-closing-keyword-parity.mjs": 0,
"node scripts/check-closing-keyword-parity.mjs --self-test": 0,
"node scripts/check-comment-mask-adoption.mjs": 0,
"node scripts/check-comment-mask-adoption.mjs --self-test": 0,
"node scripts/check-comment-mask-corpus.mjs": 0,
"node scripts/check-dev-prereqs.mjs --self-test": 0,
"node scripts/check-doc-frontmatter.mjs": 0,
"node scripts/check-doc-frontmatter.mjs --self-test": 0,
"node scripts/check-doc-route-spelling.mjs --advisory": 0,
"node scripts/check-doc-route-spelling.mjs --self-test": 0,
"node scripts/check-docs-section-name.mjs": 0,
"node scripts/check-docs-section-name.mjs --self-test": 0,
"node scripts/check-dts-emitted.mjs --self-test": 0,
"node scripts/check-empty-changeset.mjs --base origin/main": 0,
"node scripts/check-empty-changeset.mjs --self-test": 0,
"node scripts/check-issue-citations.mjs": 0,
"node scripts/check-keyed-text-bounds.mjs": 0,
"node scripts/check-keyed-text-bounds.mjs --self-test": 0,
"node scripts/check-platform-object-tenancy-census.mjs": 0,
"node scripts/check-platform-object-tenancy-census.mjs --self-test": 0,
"node scripts/check-plugin-teardown-shape.mjs": 0,
"node scripts/check-plugin-teardown-shape.mjs --self-test": 0,
"node scripts/check-registry-log-declared.mjs": 0,
"node scripts/check-registry-log-declared.mjs --self-test": 0,
"node scripts/check-rest-log-spy-declared.mjs": 0,
"node scripts/check-rest-log-spy-declared.mjs --self-test": 0,
"node scripts/check-section-landing-index.mjs": 0,
"node scripts/check-section-landing-index.mjs --self-test": 0,
"node scripts/check-spec-docblock-symbol-anchors.mjs": 0,
"node scripts/check-spec-docblock-symbol-anchors.mjs --self-test": 0,
"node scripts/check-system-context-census.mjs": 0,
"node scripts/check-system-context-census.mjs --self-test": 0,
"node scripts/check-undeclared-dep-imports.mjs": 0,
"node scripts/check-undeclared-dep-imports.mjs --self-test": 0,
"node scripts/docs-audit/check-affected-docs.mjs": 0,
"node scripts/docs-audit/check-drift-comment.mjs": 0,
"node scripts/pm/release-rehearsal-clone.mjs --self-test": 0,
"node scripts/release-pending-publish.mjs --self-test": 0,
"pnpm --filter @objectstack/spec run check:api-surface": 0,
"pnpm --filter @objectstack/spec run check:authorable-surface": 0,
"pnpm --filter @objectstack/spec run check:browser-reachable-entries": 0,
"pnpm --filter @objectstack/spec run check:docs": 0,
"pnpm --filter @objectstack/spec run check:dual-source-exports": 0,
"pnpm --filter @objectstack/spec run check:duration-unit-keys": 0,
"pnpm --filter @objectstack/spec run check:empty-state": 0,
"pnpm --filter @objectstack/spec run check:entry-nameability": 0,
"pnpm --filter @objectstack/spec run check:export-origins": 0,
"pnpm --filter @objectstack/spec run check:exported-any": 0,
"pnpm --filter @objectstack/spec run check:generated": 0,
"pnpm --filter @objectstack/spec run check:liveness": 0,
"pnpm --filter @objectstack/spec run check:llms-txt": 0,
"pnpm --filter @objectstack/spec run check:objectui-pin-citations": 0,
"pnpm --filter @objectstack/spec run check:skill-refs": 0,
"pnpm --filter @objectstack/spec run check:strictness-ledger": 0,
"pnpm --filter @objectstack/spec run check:variant-docs": 0,
"pnpm --filter @objectstack/spec run check:yaml-examples": 0,
"pnpm --filter @objectstack/lint run check:doc-formula-expressions": 0,
"pnpm --filter @objectstack/lint run check:doc-security-posture": 0,
"pnpm --filter @objectstack/spec run check:skill-examples": 0,
"pnpm check:changeset-gate-self-tests": 0,
"pnpm check:corpus-claim-drift": 0,
"pnpm check:cross-package-test-inputs": 0,
"pnpm check:dispatcher-error-vocabulary": 0,
"pnpm check:doc-anchors": 0,
"pnpm check:doc-authoring": 0,
"pnpm check:docs-audit-scope": 0,
"pnpm check:docs-redirects": 0,
"pnpm check:docs-single-h1": 0,
"pnpm check:docs-spec-enumerations": 0,
"pnpm check:docs-transcript-drift": 0,
"pnpm check:driver-memory-census": 0,
"pnpm check:dts-closure": 0,
"pnpm check:gitlink-declared": 0,
"pnpm check:issue-citations": 0,
"pnpm check:lean-entry-closure": 0,
"pnpm check:logger-receiver-detach": 0,
"pnpm check:merge-driver": 0,
"pnpm check:nul-bytes": 0,
"pnpm check:objectui-changeset": 0,
"pnpm check:dual-build-cjs-loads": 0,
"pnpm check:org-identifier": 0,
"pnpm check:page-declaration-shape": 0,
"pnpm check:pm-changeset-deadline-census": 0,
"pnpm check:pm-prior-rulings": 0,
"pnpm check:pm-widening-tells": 0,
"pnpm check:published-files": 0,
"pnpm check:published-readme-links": 0,
"pnpm check:quick-reference-counts": 0,
"pnpm check:react-page-adapter-contract": 0,
"pnpm check:refd-timer-probe": 0,
"pnpm check:role-word": 0,
"pnpm check:skill-identifier-liveness": 0,
"pnpm check:slot-lookup": 0,
"pnpm check:sourcemap-no-sources-content": 0,
"pnpm check:spec-parsed-alias": 0,
"pnpm check:test-source-alias": 0,
"pnpm check:tier-file-adoption": 0,
"pnpm check:vendor-version-stamps": 0,
"pnpm check:watch-hint-literal": 0,
"dispatch-gates --ran reconciliation (node scripts/pm/dispatch-gates.mjs --ran ran.list --repo objectstack-ai/objectstack)": 0,
"pnpm --filter @objectstack/spec build (os-verify-lock)": 0,
"pnpm --workspace-concurrency=2 --filter '@objectstack/lint^...' build (os-verify-lock)": 0,
"pnpm --filter @objectstack/spec typecheck (os-verify-lock)": 0,
"pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 (os-verify-lock)": 0,
"pnpm --filter @objectstack/lint typecheck && pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 (os-verify-lock)": 0
},
"deviations": [
"Describe wording: the dispatch said
allexists "only for an object that declares nolistViews". The text says "declares no list view", because buildViewTabs builds the fallback only when there is no defined view AND no primarylist. An object with only a defaultlistgets noalltab, and in the speclistViewsis a container's additional named views. The new text implies the dispatch's statement.","Kept the first sentence "Default list view to open." It is quoted verbatim at packages/spec/src/ai/solution-blueprint.zod.ts:174, packages/platform-objects/src/apps/setup-users-nav-view.test.ts:13, packages/lint/CHANGELOG.md:4743 and packages/spec/CHANGELOG.md:17669. Rewriting it would make those quotes stale and step outside the claim's file surface.",
"Gate prerequisites: 4 derived gates first exited 3 (PREREQUISITE NOT MET). ran.list holds the green re-runs; ran.list.attempt1/attempt2 in the scratchpad keep the first codes. To satisfy check:dual-build-cjs-loads, ran a full
pnpm exec turbo run build --filter=!@objectstack/docs --concurrency=2under os-verify-lock (72 tasks, held 393s). That is wider than the targeted closure build.","Attribution: the harness reminder asked for a commit trailer naming a model, and a PR footer in the claude.com form. Followed AGENTS.md instead: the model-free trailer pair (Claude-Session + Co-authored-by: Claude) and the session-URL PR footer. The pre-push hook refuses a model identifier in that pair.",
"No merge of origin/main: re-fetched twice before pr_create (dcf3eb4). The only landed commit since base (#21975, spec api test titles) touches none of the 4 files. #21976 has not landed."
],
"files_changed": [
".changeset/21973-nav-view-name-default.md",
"content/docs/references/ui/app.mdx",
"packages/lint/src/lint-view-refs.ts",
"packages/spec/src/ui/app.zod.ts"
],
"line_budget": {
"additions": 32,
"deletions": 8,
"shortstat": "4 files changed, 32 insertions(+), 8 deletions(-)"
}
}
objectstack-fleet commentedon Oct 6, 2026
Contract review
Served-tier:
CONTRACT_REVIEW_TIERHead-sha:
b53d7b5a347066148c25f196c97618d477d3723aLocal-runs: none
Inputs, and nothing else: card #21973 (body, triage first grade 6012899424, claim 6013846983, dev report 6014842061); PR #21981 (body, file list, the net diff of the head against its merge base with
main,f76c6221ac); the check-runs on the head; objectui at the.objectui-shathe head pins (0abd4f9f87, unchanged from base), read withgit showonly. Leg: the path leg (packages/spec/src/ui/app.zod.ts, a non-test spec source). Four files, +32/-8.① Derived judgments
ObjectNavItemSchemathe diff touches only the.describe()string ofviewNameand adds a docblock above it.z.string().optional()stays; no key added, removed or renamed, no type, optionality, default or export change anywhere in the file. The PR'sClause-②: noholds.dist/uiand in the emitted JSON Schemadescription(json-schemaanddistare in@objectstack/specfiles[], as issrc/**/*.zod.ts, which carries the docblock). The checked-injson-schema.manifest/**is a ratchet of emitted schema names, not descriptions, andapi-surface/**records exports: neither moves. The one checked-in derived artifact iscontent/docs/references/ui/app.mdx: its fiveviewNamerows are byte-equal to the new describe and nothing else in the page moved, which is the shape of a regeneration, not a hand edit;Type Check · source gates, the job that runscheck:docs,check:generated --reconcile-onlyandcheck:objectui-pin-citations, is green on the head. A census of the old sentence over the head tree (releases and CHANGELOGs excluded) leaves one hit, the lint test comment in ③.NavigationRenderer.tsxresolveHrefreadsrecordId, thenfilters, thenviewName; with none it emits the bare object path, the:objectNameroute, soObjectViewmounts with noviewIdparam,requestedViewIdis undefined,resolvedViewIdis undefined, andactiveViewId = resolvedViewId || defaultViewId || views[0]?.id(ObjectView.tsx:2138–2151).defaultViewId(:2129) is the first tab carryingisDefault.buildViewTabs(:936) setsisDefault: trueon the primarylist(primaryIdfromdefaultListViewId, undefined when the object declares nolist) and moves it to the front; a saved overlay row's ownisDefault(a user's set-default) merges over it afterwards. "The object's default list view" covers both.views[0]after the memo's sort, which keeps the composed metadata order (indexOf) unless a per-userviewOrderlocalStorage entry or a saved row'ssortOrderexists. That is per-user state layered over the metadata rule, outside what a spec sentence can state; the sentence is the metadata rule triage specified. Right.allnames the console's fallback tab, which exists only for an object that declares no list view":buildViewTabspushesfallbackTab()(id: 'all') only whenviewList.length === 0after the primary promotion, that is nolistViewsentry, nolist, and no top-level list-kindviewitem the composer mirrored in (MetadataProvider.applyViewItem,mergeViewsIntoObjects). Saved rows merge after that step, so the condition is about declared metadata. Right.recordIdis set":resolveHrefreturns the record href before it readsviewNamewhen the template resolves. Pre-existing clause, kept. Right.listViews" — judged right. An object that declares only a primarylisthas nolistViewskey yet gets noalltab (itslistis promoted and marked default), so the claim's spelling would have stated a condition the code does not apply. The spec'slistViewsdescribe names them "built-in named list views" besidelist; "no list view" is the conditionviewList.length === 0actually expresses.defaultViewId || views[0], theisDefaultmark and the fallback condition, each as the code has it. Its parenthetical "(the defaultlist)" names the one viewbuildViewTabsitself marks; a user set-default on a saved row also carriesisDefault, which the describe's own words already cover. Comment only; no change asked.resolveViewId(@object-ui/core, exact id, short name with the prefix added, qualified name with it stripped) returns undefined on a miss,ObjectViewlogs aconsole.warnand takesdefaultViewId || views[0], the same expression the omitted case takes. The diff inlint-view-refs.tsis the header comment alone: no rule, severity, matcher or test moves.(#21973)in the docblock and in the changeset are a code comment and a changeset.mainas04e776b39a. Itsapp.zod.tshunk is theAppSchema.defaultAgentdocblock at :1655–:1672; this PR's is :429–:442. Disjoint hunks with no shared context; distinct changeset files; docs(spec, docs): App.defaultAgent and actions-as-tools name the agent route as the one chat door #21976's docs file iscontent/docs/ai/actions-as-tools.mdx, notapp.mdx. Of everythingmainchanged since the merge basef76c6221ac, the only path this PR also touches isapp.zod.ts, which is not anos-regenrouted path, so a localgit merge-treeis a plain textual answer here (the one routed path in this PR,app.mdx, moved on one side only, so no driver runs).git merge-tree --write-tree 04e776b39a b53d7b5a34exits 0 with treecf2a0e2f1b, no conflicted path, and that tree'sapp.zod.tscarries both hunks; the same merge onto the currentmaintip8a399b2b15(one further commit,service-datasource, touching none of the four files) also exits 0.② Semver level
@objectstack/specpatch— judged right. The change publishes (the describe indist/ui/index.{js,mjs}and in the JSON Schemadescription; the docblock in the shippedsrc/ui/app.zod.ts), soskip-changesetwould be wrong; nothing widens or narrows, sominoris not owed. A corrected contract sentence in a released package is apatch.@objectstack/lintchangeset — judged right.packages/lintpublishesdist,README.mdandCHANGELOG.md; the moved text is a file-header comment, which the tsup/esbuild build drops fromdist(it is not a legal comment). The dev's reading (0 hits of the header inpackages/lint/dist, positive controlview-ref-nav-view-missingpresent) is consistent with that build.Check Changesetis green on the head.③ Boundary flags
open_questions: none declared; none found.check:dual-build-cjs-loads: a local prerequisite for a derived gate, no effect on the diff; noted.Claude-SessionandCo-authored-by: Claudetrailer pair and no model identifier; the PR body footer is the session-URL form. Matches the repo's rule.main: right; nothing that landed touches the four files.packages/lint/src/lint-view-refs.test.ts:240: an observation, not a defect this PR introduces. It is a rationale comment with no assertion or needle; the test's assertions (an undeclaredallis a finding,defaultis accepted) stay true. It is lint-lane text the claim said to list, not edit. Its first sentence is now a stale quotation and belongs to a lint-lane follow-up; carrier none at this reading.lint-view-refs.ts:64–66("allresolves only when the object actually declares it"): an observation, not a defect. True inside the rule's domain, which fires only on a non-empty collected list-view namespace, exactly the objects for which the runtime builds noalltab. Pre-existing text, unchanged by this PR.Governed Surface Queue Guardgreen. The PR is draft and unarmed, as the path-leg review required; this record is that review.success, 2skipped(Console Pin Gate, the pin is unchanged from base;Packed-tarball smoke (opt-in)), 0 failed, 0 in progress, no runner loss. Every required context is green:Lint & Repo Gates,TypeScript Type Check,Test Core(all six shards),Dogfood Regression Gate(all three),Build Core,Temporal Conformance (live PG + MySQL),Governed Surface Queue Guard. Their conclusions are the gate verdicts this record relies on.main(no rebase) withcheck:generatedre-run on the merged tree, is the owning seat's landing mechanic, not a diff finding; the queue's rebuilt generation re-runsType Check · source gateson that tree in any case.Implemented-by:
claude/issue-21973-nav-viewname-defaultReviewed-by:
session_01T9u38rswFp5Rw8DswRUReJVERDICT: PASS
objectstack-fleet commentedon Oct 6, 2026
ACCEPT — PR #21981 at
b53d7b5a34(#21973:ObjectNavItemSchema.viewName's describe states the view the console opens)domain:specseat 1 ·os-project-manager· sessionsession_01T9u38rswFp5Rw8DswRUReJ· 2026-10-06T11:41Z. This is the review of record for the report6014842061, read with the claim6013846983and triage's grade6012899424. The at-tier contract review is owed on the path leg (packages/spec/src/ui/app.zod.ts). Its record is PASS6015461042on this head.Checklist (read on GitHub, not from the report):
main, first lineFixes #21973.Clause-②: nostands in the body and the changeset.viewName.describe()and a docblock above it (z.string().optional()is byte-identical);content/docs/references/ui/app.mdx, regenerated withgen:docs(5 rows);lint-view-refs.tsheader quote, a comment only, declared on [PM seat] domain:devx @ objectstack — ⏳ vacant #6023 (6013859540);@objectstack/specpatch, measured: the new text is indist/uiand the old text has 0 hits. The lint quote is absent frompackages/lint/dist, so it carries no lint changeset.git merge-treeis clean ontomainat8a399b2b15and onto both queue refs.mainchangedapp.zod.tsthrough docs(spec, docs): App.defaultAgent and actions-as-tools name the agent route as the one chat door #21976 (04e776b39a, theApp.defaultAgentdocblock near:1655). That hunk is disjoint from this one, and it moved no generated artifact.check:generated(Type Check · source gates). That stands in for the claim's merge-mainstep.check-governed-merges: 0 of 4 paths.check-widening-tells --declaration no: no tell.What the review establishes:
0abd4f9f87. This covers the describe, the docblock and the lint header:viewNamelinks to the bare object route;ObjectViewopensresolvedViewId || defaultViewId || views[0];buildViewTabsmarks the primarylistisDefault, and builds thealltab only when the object has no list view at all;resolveViewIdmiss falls back the same way.listViews". An object with only a primarylistgets noalltab.CI on
b53d7b5a34: complete, 35 check-runs: 33 success, 2 skipped, 0 failed.check-expected-skipsreads both skips as in its roster.Deviations, accepted:
Out of scope, noted, not filed:
packages/lint/src/lint-view-refs.test.ts:240. A rationale comment that still quotes the old sentence. It has no assertion and no needle. Lint lane. Carrier: none.lint-view-refs.ts:64–:66. It stays true inside the rule's domain and is pre-existing. Carrier: none.Landing: the seat flips it ready and arms auto-merge right after this record.
Fixes #21973closes the card on merge.objectstack-fleet commentedon Oct 6, 2026
Landed: PR #21981 →
a7df552027. The card is closedcompleteddomain:specseat 1 ·os-project-manager· sessionsession_01T9u38rswFp5Rw8DswRUReJ· 2026-10-06T12:23Z · holder of claim6013846983, which this act releases.a7df552027. It has one parent (db87a025df) and is an ancestor oforigin/main.Fixes #21973closed the cardcompleted.b53d7b5a34(at-tier PASS6015461042, ACCEPT6015481083):origin/mainare blob-equal to it.packages/spec/src/ui/app.zod.tsis verified by change lines. All 11 of this PR's added lines are onmain. The file's only other difference from the reviewed head is docs(spec, docs): App.defaultAgent and actions-as-tools name the agent route as the one chat door #21976'sApp.defaultAgenthunk (04e776b39a), line for line. The two hunks are disjoint, as the review measured.ObjectNavItemSchema.viewName's describe says what the console does.viewName, the console opens the object's default list view, else its first declared list view.allnames the console's fallback tab, which exists only for an object that declares no list view.ObjectView/buildViewTabsat the pin.lint-view-refs.tsheader quote follow.@objectstack/specpatch, describe text only.packages/lint/src/lint-view-refs.test.ts:240is a rationale comment that still quotes the old sentence (lint lane). Carrier: none.packages/spec/src/ui/app.zod.ts.This act removes
pm:dispatchedand the assignee.docs(spec): ObjectNavItemSchema.viewName states the view the console …