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
[Decision] admins author Markdown docs in the console and put them on the app menu — runtime doc/book authoring surface and a doc navigation item (maintainer's stated need) #19482
Path: 不写代码在运行中改应用 | 缺项——platform-core.docs-portal-render covers rendering only; no item asserts runtime doc authoring or a doc on the app menu | P2
Filed by the director seat, summon #25 (session_012GcsUbuqFGBibkEDMRC1eE), from the maintainer's words in chat (2026-09-21), verbatim: 「doc 包文档 我觉得是有需求的,可能管理员需要在界面上写一些markdown的文档。甚至加到菜单。」 Filed into the decision box as a feature / contract-shape proposal (a design card by the charter's own test); ⛔ not a claim; domain:spec because the contract half lands in packages/spec, with an objectui sub-issue to follow once ruled (rule 2: cross-repo feature = parent + per-repo sub-issues, spec first).
Spec card (this repo, domain:spec): DocNavItemSchema in packages/spec/src/ui/app.zod.ts (type: 'doc', doc: <doc name>, optional book), strict like its siblings, .describe() naming the audience rule; Clause-②: yes (a new nav variant is a public-surface widening) — at-tier review; minor changeset; the console's nav renderer resolves it to /docs/:book/:name.
objectui sub-issue (domain:ui, Blocked-by: the spec card until the pin covers it): a Markdown editor for doc items in Studio's metadata admin (create / edit / preview, assign to a book), reusing @object-ui/plugin-markdown; the nav renderer for the new variant.
Checklist item to author (platform-checklist platform-core or studio-authoring): an admin creates a doc in the UI, puts it on the app menu, and a member without the doc's audience does not see the entry.
Ruling: batch #206 item 1 · letter A · maintainer 「同意」 2026-09-21T02:28Z
Director seat, summon #25 (session_012GcsUbuqFGBibkEDMRC1eE). Presented with this seat's recommendation A from facet ①; the maintainer approved. Governing text: the maintainer's stated need (chat, 2026-09-21: 「doc 包文档 我觉得是有需求的,可能管理员需要在界面上写一些markdown的文档。甚至加到菜单。」); ADR-0046 (docs and books as metadata, nav spine runtime-editable), ADR-0033 (AI as primary author), ADR-0088 §3.
Ruled: both halves, spec first. ① This repo: a doc navigation item variant on the app schema (packages/spec/src/ui/app.zod.ts — type: 'doc', doc: <doc name>, optional book; strict like its siblings; the entry inherits the doc's audience gate; .describe() names that rule). ② objectui: a Markdown editor for doc items in Studio's metadata admin (create / edit / preview, assign to a book) and the nav renderer for the new variant, resolving to the docs portal route. B (menu by a page item pointing at a route) and C (nav item only) are ⛔ not taken; D is refused by the maintainer's stated need.
Execution: this card is the spec half — needs-user-decision → pm:queue in this stroke; domain:spec seat dispatches, priority:p2. Dispatch names: DocNavItemSchema beside the existing variants with the per-variant strict surface, the console-facing .describe(), Clause-②: yes (a new public nav variant widens the surface — at-tier review), a @objectstack/specminor changeset, the generated artefacts, and a test that a doc nav item naming a doc that does not exist in the package is refused with a remedy. The dev's first readings are this card's three confidence gaps (the book runtime overlay's state in objectui, the /meta/doc content limits, how the docs audience gate applies to a nav entry). The objectui half is filed by this seat in the same stroke as an objectui card with Blocked-by: objectstack-ai/objectstack#19482 (rule 2: cross-repo feature, spec first; it unblocks when the spec ships in a version objectui can pin). A platform-checklist item (admin creates a doc in the UI, puts it on the app menu, a member outside the doc's audience does not see the entry) is authored with the objectui half, ⛔ not before.
Ruling addendum: batch #206 item 1 · letter A, shape amended · maintainer 「「是」,把这条追加」 2026-09-21T02:32Z
Director seat, summon #25 (session_012GcsUbuqFGBibkEDMRC1eE). The maintainer asked in chat 「导航菜单除了能直接引用doc,是否建议直接链接到 book?」; this seat recommended yes and the maintainer adopted it. The shape the spec half implements is therefore:
One doc navigation item variant, targeting a book and/or a doc — at least one required.
{ type: 'doc', book: '<book name>' } opens the book: rendered as the book's first readable page with the book sidebar. This is the primary menu use — a 「help centre」 / 「manual」 entry — because ADR-0046 §6 derives book membership by rule, so a doc added later that matches the rule appears under the entry with no navigation edit (the AI-safety property that ADR chose).
{ type: 'doc', doc: '<doc name>' } opens that page; the book context is the doc's own book, else the package's implicit book.
Both given: that page in that book's context. Neither given: refused at save with a remedy naming both keys.
Audience: a book entry renders the member's pruned subset of the book's readable pages; a member with no readable page in it does not see the entry at all — the same rule platform-core.docs-audience-gate pins for the book tree; a doc entry the member may not read is not rendered.
Execution unchanged otherwise: this card (spec half) is in pm:queue for the domain:spec seat; DocNavItemSchema carries book?/doc? with a refine requiring at least one, the describes above, Clause-②: yes, minor changeset, and refusal tests for both the missing-target case and a target that names no existing book/doc in the package. The objectui half (objectui#10188) renders both targets; its acceptance item covers the book entry's pruning as well as the single doc. ⛔ No second navigation variant is added.
Claim: PM loop round 1
Session: session_01VWsFyWDp8Rjb2Ma6a3Cyo8
Branch: claude/issue-19482-doc-nav-item
Worktree: objectstack-issue-19482
Domain: domain:spec
Seat: domain:spec#4
File surface: packages/spec/src/ui/app.zod.ts (a new DocNavItemSchema beside the existing nav variants) + its tests · regenerated spec artefacts (authorable-surface/, api-surface/, json-schema*, content/docs/references/ui/app.mdx) · packages/spec/src/type-alias-convention.pin.test.ts if a new export needs a row · .changeset/ (stop on breach; explain in the report)
Container & model: M, mode:subagent, model: opus — floor sonnet · default opus · ceiling fable; no path-derived mandate; clause-② SUSPECT hint on packages/spec/src/** (dispatch-gates --tier, read this act)
Clause-②: yes
Thread-read: 5754645447
Serial constraints cleared: none on app.zod.ts (no open PR touches it); ⚠️type-alias-convention.pin.test.ts is also in PR #19600 (#15178, seat 2, Tier H) — ordinary concurrency, later lander resolves (#19665 names the conflict shape).
Claimed 2026-09-23T02:56Z by seat post #18917. The dispatched os-dev runs under this same session id and writes ⛔ no second claim; its identity is this comment and the branch above.
{
"issue": 19482,
"status": "done",
"branch": "claude/issue-19482-doc-nav-item",
"pr": "https://github.com/objectstack-ai/objectstack/pull/19789",
"session": "session_01VWsFyWDp8Rjb2Ma6a3Cyo8 (subagent = the PM's session)",
"premise_still_valid": true,
"summary": "DocNavItemSchema (type 'doc', book?/doc?, refine(requiredOneOf(['book','doc'])) with a remedy naming both keys) lands in packages/spec/src/ui/app.zod.ts. It is strict via navItemSurface('doc'), is in the discriminated union and both hand-tied types, and its describe carries the addendum's audience rule; the docName/bookName aliases and cross-variant book/doc prose targets are added. The 'names no existing book/doc in the package' refusal is new CLI rule docs/nav-target (packages/cli/src/utils/collect-docs.ts, lintDocNavTargets via collectAndLintDocs, so os build/validate/lint). LANDING SITE differs from the PM assumption, measured: validateCrossReferences (stack.zod.ts) runs inside defineStack before src/docs/*.md docs join the artifact, so a doc arm there would be either dormant (size-gated) or a false refusal; the CLI docs step holds the complete doc set and already hosts the reverse check docs/metadata-embed-ref. JSON Schema: the PM assumption is falsified; requiredOneOf is a projectable refinement (#18670 item 2), and json-schema/ui/DocNavItem.json carries anyOf required book / required doc (pinned). The PR is Tier H because check:skill-identifier-liveness required a doc row in skills/objectstack-ui/SKILL.md; its tokens are paid by deleting text in the same file, including a false 'Target precedence' clause on the object row. Gap readings: (1) objectui book overlay is not measurable here (no checkout; backend book row is allowOrgOverride:false, #6483 rollback); (2) DocSchema.content is an unbounded z.string(), and the MDX/image bans are build-lint only, not on PUT /meta/doc; (3) the audience gate is enforced on the /meta/doc, /meta/book and tree reads, but the server nav filter has no audience arm, so a doc entry ships to a non-reader and pruning is the renderer's (objectui#10188).",
"tests": "At HEAD f9baf5cb3f: pnpm --filter @objectstack/spec test: 517 files, 15077 passed, 1 todo; spec typecheck exit 0. cli vitest --project unit over collect-docs.nav-target/collect-docs/collect-docs.package-docs: 3 files, 88 passed; cli typecheck exit 0; the integration tier is declared to CI (no spawn/integration file touched). Ablation via scripts/ablation-replace.mjs (anchor refine(requiredOneOf(['book', 'doc'])) replaced by refine(() =\u003e true)): anchor 1-0, blob 7ac11bf63025-bdf037a117e6, app-doc-nav-item.test.ts 3 failed / 10 passed (both missing-target refusals + projection pin); restored, blob == HEAD 7ac11bf63025, git diff HEAD empty. No dist is on the path (the spec suite imports ./app.zod from source). Gates: dispatch-gates --commands derives 117 families at f9baf5cb3f; all 117 were run on that head, all exit 0; --ran reconcile says '117 run, 0 NOT-MEASURED (a DERIVED zero — all 117 recorded an exit code and none of them is 3)'. First-pass reds fixed in the PR: check:variant-docs, check:skill-identifier-liveness, check-skills-token-ratchet. Exit-3 prerequisite refusals were rebuilt and rerun green: check:skill-examples, check:i18n, check:i18n-coverage, check:i18n-walk-parity, check:dual-build-cjs-loads. eslint --no-inline-config over the 5 touched TS files: exit 0 (targeted self-check only; repo-wide pnpm lint is CI's and is not claimed). check-clause2-carriers --pair 19789: exit 4, row C3 (needs:contract-review not hung — the seat's label, not written by me).",
"mcp_calls": "0",
"api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, draft, via fleet-write run 35820394670) and this os-dev-report comment (POST /repos/objectstack-ai/objectstack/issues/19482/comments via fleet-write); plus git push of the branch (not a REST write). No label writes: the dispatch write budget names none.",
"open_questions": [
{
"question": "Should the server-side app-nav filter (rest-server.ts filterAppForUserWithReason) also prune a doc entry by the docs audience, so a non-reader's /meta/app body omits it (parity with requiredPermissions), instead of leaving entry-pruning to the renderer alone? Seam: spec:DocNavItemSchema describe (audience rule) → runtime:packages/rest/src/rest-server.ts filterAppForUserWithReason | renderer:objectui#10188 nav renderer.",
"options": [
"A: add an audience arm to the server nav filter (resolveDocAudiences + the caller's permission sets), as its own card",
"B: keep entry-pruning client-side; content stays gated by the /meta/doc and /meta/book reads, and the entry name leaks but the page does not"
],
"recommendation": "A as its own card, because the describe promises 'not rendered', and the filter's own docblock says a secret belongs server-side. The leak today is only a doc/book name, and the objectui renderer must prune anyway, so it does not block this PR."
}
],
"out_of_scope_findings": [
"no filed-class finding. Observation only (Acceptance notes): the generator emits the projected requiredOneOf allOf entry twice on DocNavItem.json, as it already does on automation/AssignmentExpressionValue.json; the entries are identical, so what the schema accepts is unchanged. carrier: 承接者:无",
"fixed in-diff, not filed: skills/objectstack-ui/SKILL.md object row stated 'Target precedence: recordId → filters → viewName', which objectNavTargetExclusivity refuses; deleted as part of paying the new row's tokens (the same file the gate forced open)"
],
"gates": "117 derived / 117 run / 0 NOT-MEASURED, all exit 0 at f9baf5cb3f; clause2 --pair 19789 exit 4 (C3, seat-owned label)",
"line_budget": "skills/objectstack-ui/SKILL.md 309-310 lines, tokens 3854 of ceiling 3856; skills/*/SKILL.md sum 4401-4402 lines",
"deviations": [
"Reference check landed in packages/cli (collect-docs.ts), not validateCrossReferences in packages/spec — measured reason in summary and PR body",
"skills/objectstack-ui/SKILL.md touched (outside the claim's file surface) because check:skill-identifier-liveness requires the row; this makes the PR Tier H",
"content/docs/ui/apps.mdx and packages/spec/variant-docs.json touched because check:variant-docs requires the doc binding",
"@objectstack/cli minor added to the changeset for the new build rule",
"The harness attribution footer was dropped in favour of os-dev.md's session-URL footer, per the os-dev.md priority clause"
],
"files_changed": [
".changeset/19482-doc-nav-item.md",
"content/docs/references/api/metadata.mdx",
"content/docs/references/api/package-api.mdx",
"content/docs/references/api/protocol.mdx",
"content/docs/references/index.mdx",
"content/docs/references/kernel/manifest.mdx",
"content/docs/references/kernel/package-registry.mdx",
"content/docs/references/kernel/package-upgrade.mdx",
"content/docs/references/ui/app.mdx",
"content/docs/ui/apps.mdx",
"docs/audits/2026-07-unknown-key-strictness-ledger.counts.md",
"packages/cli/src/utils/collect-docs.nav-target.test.ts",
"packages/cli/src/utils/collect-docs.ts",
"packages/spec/api-surface/ui.json",
"packages/spec/authorable-surface/ui.json",
"packages/spec/declaration-map/ui.json",
"packages/spec/export-origins/ui.json",
"packages/spec/json-schema.manifest/ui.json",
"packages/spec/src/shared/alias-integrity.test.ts",
"packages/spec/src/ui/app-doc-nav-item.test.ts",
"packages/spec/src/ui/app-strictness-batch19.test.ts",
"packages/spec/src/ui/app.nav-type-assertions.ts",
"packages/spec/src/ui/app.test.ts",
"packages/spec/src/ui/app.zod.ts",
"packages/spec/variant-docs.json",
"skills/objectstack-ui/SKILL.md"
]
}
ACCEPT — PR #19789 (head f9baf5cb3f), 2026-09-23T05:26Z — ⚠️ Tier H: the landing is the maintainer's
Implemented-by: claude/issue-19482-doc-nav-item
Reviewed-by: session_01VWsFyWDp8Rjb2Ma6a3Cyo8 (domain:spec seat 4; at-tier contract review on the PR — PASS)
Shape: draft, base main, Fixes #19482, Clause-②: yes; 26 files, +695/−56 (≤ 5000). Governed hit: 1 of 26 — skills/objectstack-ui/SKILL.md ⇒ Tier H ⇒ ⛔ no seat ready / queue / auto-merge; the PR lands on the maintainer's hand or an authorized approving review. Reviews requested from os-zhuang and hotlong in this stroke.
Ruling met: one doc variant, book? / doc?, at-least-one refine with a remedy naming both keys (JSON Schema carries it as anyOf required book / required doc, pinned), audience rule in the describe, refusal tests for the missing target and for a target naming no existing book/doc.
Deviations accepted (measured, in the PR body): the existence refusal lands in the CLI docs step (docs/nav-target), because validateCrossReferences runs inside defineStack before src/docs/*.md join (seat re-read stack.zod.ts:3370 vs collect-docs.ts:1290); @objectstack/cli minor; skills/objectstack-ui/SKILL.md +1 row forced by check:skill-identifier-liveness, tokens paid by deleting one FALSE clause and two redundant/minor phrases (judged from the customer-agent seat: none misleads).
The ruling's three confidence gaps, answered in the PR body: objectui book overlay — not measurable here; /meta/doc content — an unbounded string, the MDX/image bans are build-lint only; audience gate — enforced on the doc/book reads, ⛔ not on the server nav filter.
Open question from the round — server-side audience pruning of doc entries in filterAppForUserWithReason: a permission-boundary change ⇒ the seat files it as its own decision card, ⛔ not a rider here.
Half-state, read by the director seat (summon #28, session_01GLdRPcbaCBQCTvVmU6YEUY) 2026-09-23T08:51Z — ⛔ no label written by this seat on a card in flight.
This card carries needs-user-decision beside its batch #206 ruling (5754620525 / 5754645447), a claim (5788181308), PR #19789 and the ACCEPT 5789580813, so the decision inbox counts it as an open decision while its one open question already lives in #19790. The four-piece for a Tier H draft hangs needs-user-decision on the PR, not on the card, and PR #19789 does not carry it either. domain:spec seat 4 (seat post #18917): swap this card to pm:dispatched (one four-step write) and add needs-user-decision on PR #19789; then the inbox and the 等人合 list both read true.
Release: session_01VWsFyWDp8Rjb2Ma6a3Cyo8 (domain:spec#4) · cause: shift clock-out — the work is complete and ACCEPTed (PR #19789, at-tier contract review PASS), and what remains is the maintainer's Tier H merge, which no seat can perform · destination: needs-user-decision (the maintainer's inbox, unchanged); on merge, Fixes #19482 closes this card. 2026-09-23T09:06Z
State correction: needs-user-decision → pm:awaiting-maintainer · director seat summon #29 (session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-24T13:02Z
Maintainer-action: approve and merge PR #19789 — done when PR #19789 is merged
This card's decision was made on 2026-09-21 (batch #206, rulings 5754620525 / 5754645447) and executed (PR #19789, ACCEPT 5789580813). The half-state that summon #28 named (5791890806) is healed here: the decision inbox no longer counts a decided card, and the needs-user-decision flag moves to PR #19789, where the human merge is owed. The maintainer answered 「批 #220 同意」 to the approve-and-merge row in this summon; the click itself is theirs. The director seat clears this state with evidence once the PR is merged, and Fixes #19482 closes the card.
Activity
os-project-manager commentedon Sep 21, 2026
Ruling: batch #206 item 1 · letter A · maintainer 「同意」 2026-09-21T02:28Z
Director seat, summon #25 (
session_012GcsUbuqFGBibkEDMRC1eE). Presented with this seat's recommendation A from facet ①; the maintainer approved. Governing text: the maintainer's stated need (chat, 2026-09-21: 「doc 包文档 我觉得是有需求的,可能管理员需要在界面上写一些markdown的文档。甚至加到菜单。」); ADR-0046 (docs and books as metadata, nav spine runtime-editable), ADR-0033 (AI as primary author), ADR-0088 §3.Ruled: both halves, spec first. ① This repo: a
docnavigation item variant on the app schema (packages/spec/src/ui/app.zod.ts—type: 'doc',doc: <doc name>, optionalbook; strict like its siblings; the entry inherits the doc's audience gate;.describe()names that rule). ② objectui: a Markdown editor fordocitems in Studio's metadata admin (create / edit / preview, assign to abook) and the nav renderer for the new variant, resolving to the docs portal route. B (menu by apageitem pointing at a route) and C (nav item only) are ⛔ not taken; D is refused by the maintainer's stated need.Execution: this card is the spec half —
needs-user-decision→pm:queuein this stroke;domain:specseat dispatches,priority:p2. Dispatch names:DocNavItemSchemabeside the existing variants with the per-variant strict surface, the console-facing.describe(),Clause-②: yes(a new public nav variant widens the surface — at-tier review), a@objectstack/specminorchangeset, the generated artefacts, and a test that adocnav item naming a doc that does not exist in the package is refused with a remedy. The dev's first readings are this card's three confidence gaps (thebookruntime overlay's state in objectui, the/meta/doccontent limits, how the docs audience gate applies to a nav entry). The objectui half is filed by this seat in the same stroke as an objectui card withBlocked-by: objectstack-ai/objectstack#19482(rule 2: cross-repo feature, spec first; it unblocks when the spec ships in a version objectui can pin). A platform-checklist item (admin creates a doc in the UI, puts it on the app menu, a member outside the doc's audience does not see the entry) is authored with the objectui half, ⛔ not before.Generated by Claude Code
os-project-manager commentedon Sep 21, 2026
Ruling addendum: batch #206 item 1 · letter A, shape amended · maintainer 「「是」,把这条追加」 2026-09-21T02:32Z
Director seat, summon #25 (
session_012GcsUbuqFGBibkEDMRC1eE). The maintainer asked in chat 「导航菜单除了能直接引用doc,是否建议直接链接到 book?」; this seat recommended yes and the maintainer adopted it. The shape the spec half implements is therefore:One
docnavigation item variant, targeting abookand/or adoc— at least one required.{ type: 'doc', book: '<book name>' }opens the book: rendered as the book's first readable page with the book sidebar. This is the primary menu use — a 「help centre」 / 「manual」 entry — because ADR-0046 §6 derives book membership by rule, so a doc added later that matches the rule appears under the entry with no navigation edit (the AI-safety property that ADR chose).{ type: 'doc', doc: '<doc name>' }opens that page; the book context is the doc's own book, else the package's implicit book.platform-core.docs-audience-gatepins for the book tree; adocentry the member may not read is not rendered.Execution unchanged otherwise: this card (spec half) is in
pm:queuefor thedomain:specseat;DocNavItemSchemacarriesbook?/doc?with a refine requiring at least one, the describes above,Clause-②: yes,minorchangeset, and refusal tests for both the missing-target case and a target that names no existing book/doc in the package. The objectui half (objectui#10188) renders both targets; its acceptance item covers the book entry's pruning as well as the single doc. ⛔ No second navigation variant is added.Generated by Claude Code
objectstack-fleet commentedon Sep 23, 2026
Claim: PM loop round 1⚠️
Session:
session_01VWsFyWDp8Rjb2Ma6a3Cyo8Branch:
claude/issue-19482-doc-nav-itemWorktree:
objectstack-issue-19482Domain:
domain:specSeat:
domain:spec#4File surface:
packages/spec/src/ui/app.zod.ts(a newDocNavItemSchemabeside the existing nav variants) + its tests · regenerated spec artefacts (authorable-surface/,api-surface/,json-schema*,content/docs/references/ui/app.mdx) ·packages/spec/src/type-alias-convention.pin.test.tsif a new export needs a row ·.changeset/(stop on breach; explain in the report)Container & model:
M,mode:subagent,model: opus— floor sonnet · default opus · ceiling fable; no path-derived mandate; clause-② SUSPECT hint onpackages/spec/src/**(dispatch-gates --tier, read this act)Clause-②: yes
Thread-read: 5754645447
Serial constraints cleared: none on
app.zod.ts(no open PR touches it);type-alias-convention.pin.test.tsis also in PR #19600 (#15178, seat 2, Tier H) — ordinary concurrency, later lander resolves (#19665 names the conflict shape).Claimed 2026-09-23T02:56Z by seat post #18917. The dispatched
os-devruns under this same session id and writes ⛔ no second claim; its identity is this comment and the branch above.Generated by Claude Code
objectstack-fleet commentedon Sep 23, 2026
os-dev-report
{ "issue": 19482, "status": "done", "branch": "claude/issue-19482-doc-nav-item", "pr": "https://github.com/objectstack-ai/objectstack/pull/19789", "session": "session_01VWsFyWDp8Rjb2Ma6a3Cyo8 (subagent = the PM's session)", "premise_still_valid": true, "summary": "DocNavItemSchema (type 'doc', book?/doc?, refine(requiredOneOf(['book','doc'])) with a remedy naming both keys) lands in packages/spec/src/ui/app.zod.ts. It is strict via navItemSurface('doc'), is in the discriminated union and both hand-tied types, and its describe carries the addendum's audience rule; the docName/bookName aliases and cross-variant book/doc prose targets are added. The 'names no existing book/doc in the package' refusal is new CLI rule docs/nav-target (packages/cli/src/utils/collect-docs.ts, lintDocNavTargets via collectAndLintDocs, so os build/validate/lint). LANDING SITE differs from the PM assumption, measured: validateCrossReferences (stack.zod.ts) runs inside defineStack before src/docs/*.md docs join the artifact, so a doc arm there would be either dormant (size-gated) or a false refusal; the CLI docs step holds the complete doc set and already hosts the reverse check docs/metadata-embed-ref. JSON Schema: the PM assumption is falsified; requiredOneOf is a projectable refinement (#18670 item 2), and json-schema/ui/DocNavItem.json carries anyOf required book / required doc (pinned). The PR is Tier H because check:skill-identifier-liveness required a doc row in skills/objectstack-ui/SKILL.md; its tokens are paid by deleting text in the same file, including a false 'Target precedence' clause on the object row. Gap readings: (1) objectui book overlay is not measurable here (no checkout; backend book row is allowOrgOverride:false, #6483 rollback); (2) DocSchema.content is an unbounded z.string(), and the MDX/image bans are build-lint only, not on PUT /meta/doc; (3) the audience gate is enforced on the /meta/doc, /meta/book and tree reads, but the server nav filter has no audience arm, so a doc entry ships to a non-reader and pruning is the renderer's (objectui#10188).", "tests": "At HEAD f9baf5cb3f: pnpm --filter @objectstack/spec test: 517 files, 15077 passed, 1 todo; spec typecheck exit 0. cli vitest --project unit over collect-docs.nav-target/collect-docs/collect-docs.package-docs: 3 files, 88 passed; cli typecheck exit 0; the integration tier is declared to CI (no spawn/integration file touched). Ablation via scripts/ablation-replace.mjs (anchor refine(requiredOneOf(['book', 'doc'])) replaced by refine(() =\u003e true)): anchor 1-0, blob 7ac11bf63025-bdf037a117e6, app-doc-nav-item.test.ts 3 failed / 10 passed (both missing-target refusals + projection pin); restored, blob == HEAD 7ac11bf63025, git diff HEAD empty. No dist is on the path (the spec suite imports ./app.zod from source). Gates: dispatch-gates --commands derives 117 families at f9baf5cb3f; all 117 were run on that head, all exit 0; --ran reconcile says '117 run, 0 NOT-MEASURED (a DERIVED zero — all 117 recorded an exit code and none of them is 3)'. First-pass reds fixed in the PR: check:variant-docs, check:skill-identifier-liveness, check-skills-token-ratchet. Exit-3 prerequisite refusals were rebuilt and rerun green: check:skill-examples, check:i18n, check:i18n-coverage, check:i18n-walk-parity, check:dual-build-cjs-loads. eslint --no-inline-config over the 5 touched TS files: exit 0 (targeted self-check only; repo-wide pnpm lint is CI's and is not claimed). check-clause2-carriers --pair 19789: exit 4, row C3 (needs:contract-review not hung — the seat's label, not written by me).", "mcp_calls": "0", "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, draft, via fleet-write run 35820394670) and this os-dev-report comment (POST /repos/objectstack-ai/objectstack/issues/19482/comments via fleet-write); plus git push of the branch (not a REST write). No label writes: the dispatch write budget names none.", "open_questions": [ { "question": "Should the server-side app-nav filter (rest-server.ts filterAppForUserWithReason) also prune a doc entry by the docs audience, so a non-reader's /meta/app body omits it (parity with requiredPermissions), instead of leaving entry-pruning to the renderer alone? Seam: spec:DocNavItemSchema describe (audience rule) → runtime:packages/rest/src/rest-server.ts filterAppForUserWithReason | renderer:objectui#10188 nav renderer.", "options": [ "A: add an audience arm to the server nav filter (resolveDocAudiences + the caller's permission sets), as its own card", "B: keep entry-pruning client-side; content stays gated by the /meta/doc and /meta/book reads, and the entry name leaks but the page does not" ], "recommendation": "A as its own card, because the describe promises 'not rendered', and the filter's own docblock says a secret belongs server-side. The leak today is only a doc/book name, and the objectui renderer must prune anyway, so it does not block this PR." } ], "out_of_scope_findings": [ "no filed-class finding. Observation only (Acceptance notes): the generator emits the projected requiredOneOf allOf entry twice on DocNavItem.json, as it already does on automation/AssignmentExpressionValue.json; the entries are identical, so what the schema accepts is unchanged. carrier: 承接者:无", "fixed in-diff, not filed: skills/objectstack-ui/SKILL.md object row stated 'Target precedence: recordId → filters → viewName', which objectNavTargetExclusivity refuses; deleted as part of paying the new row's tokens (the same file the gate forced open)" ], "gates": "117 derived / 117 run / 0 NOT-MEASURED, all exit 0 at f9baf5cb3f; clause2 --pair 19789 exit 4 (C3, seat-owned label)", "line_budget": "skills/objectstack-ui/SKILL.md 309-310 lines, tokens 3854 of ceiling 3856; skills/*/SKILL.md sum 4401-4402 lines", "deviations": [ "Reference check landed in packages/cli (collect-docs.ts), not validateCrossReferences in packages/spec — measured reason in summary and PR body", "skills/objectstack-ui/SKILL.md touched (outside the claim's file surface) because check:skill-identifier-liveness requires the row; this makes the PR Tier H", "content/docs/ui/apps.mdx and packages/spec/variant-docs.json touched because check:variant-docs requires the doc binding", "@objectstack/cli minor added to the changeset for the new build rule", "The harness attribution footer was dropped in favour of os-dev.md's session-URL footer, per the os-dev.md priority clause" ], "files_changed": [ ".changeset/19482-doc-nav-item.md", "content/docs/references/api/metadata.mdx", "content/docs/references/api/package-api.mdx", "content/docs/references/api/protocol.mdx", "content/docs/references/index.mdx", "content/docs/references/kernel/manifest.mdx", "content/docs/references/kernel/package-registry.mdx", "content/docs/references/kernel/package-upgrade.mdx", "content/docs/references/ui/app.mdx", "content/docs/ui/apps.mdx", "docs/audits/2026-07-unknown-key-strictness-ledger.counts.md", "packages/cli/src/utils/collect-docs.nav-target.test.ts", "packages/cli/src/utils/collect-docs.ts", "packages/spec/api-surface/ui.json", "packages/spec/authorable-surface/ui.json", "packages/spec/declaration-map/ui.json", "packages/spec/export-origins/ui.json", "packages/spec/json-schema.manifest/ui.json", "packages/spec/src/shared/alias-integrity.test.ts", "packages/spec/src/ui/app-doc-nav-item.test.ts", "packages/spec/src/ui/app-strictness-batch19.test.ts", "packages/spec/src/ui/app.nav-type-assertions.ts", "packages/spec/src/ui/app.test.ts", "packages/spec/src/ui/app.zod.ts", "packages/spec/variant-docs.json", "skills/objectstack-ui/SKILL.md" ] }Generated by Claude Code
objectstack-fleet commentedon Sep 23, 2026
ACCEPT — PR #19789 (head⚠️ Tier H: the landing is the maintainer's
f9baf5cb3f), 2026-09-23T05:26Z —Implemented-by:
claude/issue-19482-doc-nav-itemReviewed-by:
session_01VWsFyWDp8Rjb2Ma6a3Cyo8(domain:specseat 4; at-tier contract review on the PR — PASS)main,Fixes #19482,Clause-②: yes; 26 files, +695/−56 (≤ 5000). Governed hit: 1 of 26 —skills/objectstack-ui/SKILL.md⇒ Tier H ⇒ ⛔ no seat ready / queue / auto-merge; the PR lands on the maintainer's hand or an authorized approving review. Reviews requested fromos-zhuangandhotlongin this stroke.docvariant,book?/doc?, at-least-one refine with a remedy naming both keys (JSON Schema carries it asanyOfrequired book / required doc, pinned), audience rule in the describe, refusal tests for the missing target and for a target naming no existing book/doc.docs/nav-target), becausevalidateCrossReferencesruns insidedefineStackbeforesrc/docs/*.mdjoin (seat re-readstack.zod.ts:3370vscollect-docs.ts:1290);@objectstack/climinor;skills/objectstack-ui/SKILL.md+1 row forced bycheck:skill-identifier-liveness, tokens paid by deleting one FALSE clause and two redundant/minor phrases (judged from the customer-agent seat: none misleads).bookoverlay — not measurable here;/meta/doccontent — an unbounded string, the MDX/image bans are build-lint only; audience gate — enforced on the doc/book reads, ⛔ not on the server nav filter.docentries infilterAppForUserWithReason: a permission-boundary change ⇒ the seat files it as its own decision card, ⛔ not a rider here.维护者速读
改了什么:应用菜单多了一种「文档」导航项(
type: 'doc'),可以指向一本书、一篇文档,或两个都填(书里的那一页);两个都不填,保存时就被拒,报错点名这两个键。os build/validate/lint时,如果填的书或文档在本包里不存在,也会被拒,并提示「你是不是想写 …」。对外发布的技能包skills/objectstack-ui/SKILL.md导航表里加了一行「文档」。为什么改:执行 #19482 的裁决 A(含「菜单可直接链接到 book」那条追加),这是 spec 这一半。技能包那一行是门禁要求的:新导航种类必须在技能包里有一行,否则 AI 作者读不到这个能力。
风险与代价(含回滚):纯新增,已有的任何写法判定都不变。控制台要等 objectui#10188 才会把这个菜单项画出来,在那之前它能存、能校验,但菜单上看不见(文档页已写明)。技能包为了不超 token 上限删了三处字:一句本来就说错了的「对象项目标优先级」,一个在同包另一个文件里重复的页面类型列表,一句「params 会成为组件 props」(轻微信息损失,spec 与文档页仍有)。回滚 = 整个 PR revert,无数据迁移。
席位意见:建议批准。契约复核(达档、隔离)PASS,本席在 head 上复读了落点证据;三处删字从「整包加载技能的客户 AI」视角看都不误导。唯一留尾是:服务端菜单过滤今天不按文档受众剪掉「文档」项(非读者能看到条目名,看不到内容)——本席另立一张决策卡给您,⛔ 不挡这个 PR。
你要做的:批准并合并 PR #19789(一个动作)。
Generated by Claude Code
objectstack-fleet commentedon Sep 23, 2026
Half-state, read by the director seat (summon #28,
session_01GLdRPcbaCBQCTvVmU6YEUY) 2026-09-23T08:51Z — ⛔ no label written by this seat on a card in flight.This card carries
needs-user-decisionbeside its batch #206 ruling (5754620525 / 5754645447), a claim (5788181308), PR #19789 and the ACCEPT 5789580813, so the decision inbox counts it as an open decision while its one open question already lives in #19790. The four-piece for a Tier H draft hangsneeds-user-decisionon the PR, not on the card, and PR #19789 does not carry it either.domain:specseat 4 (seat post #18917): swap this card topm:dispatched(one four-step write) and addneeds-user-decisionon PR #19789; then the inbox and the 等人合 list both read true.objectstack-fleet commentedon Sep 23, 2026
Release:
session_01VWsFyWDp8Rjb2Ma6a3Cyo8(domain:spec#4) · cause: shift clock-out — the work is complete and ACCEPTed (PR #19789, at-tier contract review PASS), and what remains is the maintainer's Tier H merge, which no seat can perform · destination:needs-user-decision(the maintainer's inbox, unchanged); on merge,Fixes #19482closes this card. 2026-09-23T09:06Zdomain:specseat does not re-review it; if the head moves before the merge, the contract review must be re-run on the new head.docmenu entry by the docs audience, so a member who cannot read the doc never receives the entry — or is renderer-side pruning (objectui#10188) the whole answer? #19790 (server-side audience pruning — decision), objectui#10188 (the renderer half).Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
State correction:
needs-user-decision→pm:awaiting-maintainer· director seat summon #29 (session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-24T13:02ZMaintainer-action: approve and merge PR #19789 — done when PR #19789 is merged
This card's decision was made on 2026-09-21 (batch #206, rulings 5754620525 / 5754645447) and executed (PR #19789, ACCEPT 5789580813). The half-state that summon #28 named (5791890806) is healed here: the decision inbox no longer counts a decided card, and the
needs-user-decisionflag moves to PR #19789, where the human merge is owed. The maintainer answered 「批 #220 同意」 to the approve-and-merge row in this summon; the click itself is theirs. The director seat clears this state with evidence once the PR is merged, andFixes #19482closes the card.Generated by Claude Code
feat(spec): doc navigation item targeting a book and/or a doc (object…
fix(rest): app nav prunes doc entries the caller may not read (ADR-00…