Repository navigation
docs(skills): navigation.md states the derived record surface per flow — viewing routes to a page, create/edit opens a modal bounded on desktop and full-screen on mobile, a light record uses a drawer - #23795
Conversation
…ecord surface per flow The Surface bullet in skills/objectstack-ui/rules/navigation.md said a field-heavy object opens create/edit/detail as a full page and that mobile always pages. deriveRecordFlowSurface routes only the view flow to a page; the create, edit and child task flows open a modal, bounded on desktop and full-screen on mobile; a light record on desktop opens every flow in a drawer. The bullet now states that mapping, drops the "(or object)" placement (navigation is not an object key) and pays its tokens inside the file: net 0 lines, 2273 tokens against ceiling 2273. An @objectstack/skills patch changeset accompanies it. Claude-Session: https://claude.ai/code/session_01VqGhCg9wdsBXPz54uAEWg7 Co-authored-by: Claude <noreply@anthropic.com>
维护者速读改了什么
为什么改
风险与代价(含回滚)
席位意见
你要做的
席位核对Seat Implemented-by:
Generated by Claude Code |
Contract reviewServed-tier: Read 2026-10-16T03:15Z by the isolated at-tier reviewer under seat session ① Derived judgmentsAccept-set changes the diff implies — one, plus its changeset. The diff rewrites the Surface bullet (navigation.md L131–135, 4 lines replaced, L135 kept) and adds one changeset. No code, no schema, no gate, no generated artifact. Each sentence of the new bullet, judged against the derivation on
The renderer, read as the second half of "derive". objectui's Two residual divergences, renderer against derivation, both pre-existing — the old text made the same two claims — and neither introduced nor widened by this diff:
Judgment: the skill states the derivation, which is the contract (ADR-0085 §5 "one shared derivation, every surface"; Prime Directive #12: spec → implementation → docs). Rewording the paragraph to the console's lag would advertise an implementation gap as platform behaviour and contradict the spec's own docblock. The cure sits in objectui; both are escalated in ③ for filing. They are not defects of this diff. Override reach (reader's seat). Token payment — lossless, verified at the head. 「Don't set it.」 is carried by L125–126 (「You do not author the surface…」) and L160–162 (「Reach for Whole-package value density. Five lines, net 0 tokens, that tell an authoring AI (a) not to author the surface, (b) the derived mapping per flow and viewport, (c) the one declared knob and the sanctioned page path. Nothing else under Main drift since the merge base. Check-runs on ② Semver level
③ Boundary flagsDev report 6206965250:
Reviewer's own flags, none in the dev report:
Implemented-by: VERDICT: PASS The diff replaces a published sentence that was false of the derivation with one that is true of it clause by clause, pays its tokens by lossless deletion inside the file, names only declared keys, carries the owed Generated by Claude Code |
Fixes #23753
Clause-②: no
What
skills/objectstack-ui/rules/navigation.mdL131–135 — the 「Surface (page vs drawer)」 bullet under Record Presentation — said a field-heavy object "opens create/edit/detail as a full page" and that "Mobile always pages". The platform derives otherwise.deriveRecordFlowSurfaceinpackages/spec/src/data/record-surface.ts, read at the branch point0b1179f33:deriveRecordSurfaceanswers'page'on a mobile viewport or at/aboveRECORD_SURFACE_PAGE_THRESHOLD(12) authorable fields, else'drawer'(L88–93); theviewflow routes when that says'page'and overlays a drawer otherwise (L160–162); the task flows (create/edit/child-*) never route — a derived'page'becomes a modal,size: 'full'on mobile andsize: 'auto'(the renderer's bounded lg/xl) on desktop, and a light record stays a drawer (L163–169; objectui#12521 letter B, landed as PR #23747). So the sentence was wrong for create/edit on every viewport, and "mobile always pages" held only forview.The bullet now reads (5 lines, as before):
Each clause against the derivation: "field-heavy record, or any on mobile" is
deriveRecordSurfaceanswering'page'(L89, L91); "viewed on a page" is theviewbranch's'route'(L161); "created/edited in a modal (bounded on desktop, full-screen on mobile)" is the task-flow branch (L166–168:surface: 'modal',size: opts.viewport === 'mobile' ? 'full' : 'auto'); "otherwise a drawer" is the light record on desktop, which every flow overlays as a drawer (L92, L169).Keys named, each checked where the sentence puts it:
navigation.modeisNavigationConfigSchema.mode(packages/spec/src/ui/view.zod.tsL2355; the enum at L2308–2316 carriespage/drawer/modalamong its seven values, unchanged hint), mounted on the list view at L2859 (ListViewSchema.navigation); a recordPageis unchanged from the old text. The old "(or object)" is dropped: the object schema declares nonavigationkey (packages/spec/src/data/object.zod.ts— its edit-intent key iseditMode, a different key; see Acceptance notes).navigation.size,FormView.typeandmodalSize, which the derivation's docblock (L150–152) also lists as overrides, are declared (L2376, L4313–4320, L4399) but not added here:sizeis already taught two bullets down under Overlay width, and the token budget below buys no new key.Token payment at zero headroom, inside the file, by content deletion only (no re-wrap): the title parenthetical "(page vs drawer)" — the bullet now names three surfaces, so the two-way title was false as well as costly; "Don't set it." — the section's intro at L125–126 ("You do not author the surface…") and its closing rule of thumb at L160–162 both state it; the false "(or object)"; and "for a specific object" — the list view is the per-object placement. The bullet goes 364 → 363 bytes, the file 9091 → 9090.
Text only; no behaviour changes. One other file:
.changeset/23753-navigation-record-surface.md(@objectstack/skillspatch). The edited file ships:packages/skills/package.jsonfiles[]isdist, andsync-catalogcopiesskills/**intodist/skills/**byte for byte. Measured afterpnpm --filter @objectstack/skills buildunder the shared verify lock (65 files across 10 skills copied, read back byte-identical): the new lead sentence is indist/skills/objectstack-ui/rules/navigation.md(1 hit), the old title "Surface (page vs drawer)" is not (0 hits), the file's heading is (positive control, 1 hit), andcmpagainst the source answers identical.Readings (
skills/**)0b1179f33)9fc1d4717)navigation.mdlinesskills/objectstack-ui/**lines (the skill, every file)skills/*/SKILL.mdlines (the catalog)check-skills-token-ratchet,navigation.mdVerdict lines verbatim — before:
✓ check-skills-token-ratchet: skills/objectstack-ui/rules/navigation.md is 2273 tokens (ceiling 2273; headroom 0).— after:✓ check-skills-token-ratchet: skills/objectstack-ui/rules/navigation.md is 2273 tokens (ceiling 2273; headroom 0).No ceiling moves (theCEILINGSrow is untouched). The new bullet's longest line is 80 characters (the old one's was 84; the file's longest line is 181, inside a code block); no other line in the file was touched.Verification
Derived at
9fc1d4717bynode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no paths; change set from the merge base0b1179f33: 2 files, +13/−4): 41 commands — the dispatch's 29 plus 12 the changeset adds. Each ran in the foreground after the final commit, its exit code captured before any pipe into acmd :: exit Nrecord, then--ranreconciled the record:✓ dispatch-gates --ran: 41 derived famil(ies) accounted for — 39 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3).check-skills-token-ratchet(and its--self-test),check:skill-compatibility,check:skill-frame-sync,check:skill-identifier-liveness,check:pm-skill-id-lint,check:doc-authoring,check:nul-bytes,check:role-word,check-adr-0087-registration --base origin/main,check-changeset-no-major --base origin/main,check-empty-changeset --base origin/main,check:changeset-gate-self-tests,check:published-files,check:pm-changeset-deadline-census,check:objectui-changeset,check:pm-governed-merges,check:dts-closure,check:sourcemap-no-sources-content.check:doc-formula-expressionsfirst refused (exit 3,PREREQUISITE NOT MET — the workspace package @objectstack/formula is not built), then passed (exit 0) afterpnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lintunder the shared verify lock — the fix its refusal named.pnpm check:dual-build-cjs-loadsandpnpm check:lean-entry-closureexit 3 (PREREQUISITE NOT MET: they load every package's builtdist/, which only a whole-workspace build supplies; not built here for a markdown edit). CI'sLint & Repo Gatesbuilds and runs them; its check-run is the reading.grep -naPover both changed files finds none;pnpm check:nul-bytesexit 0.packages/*source, no generated artifact, nopackages/specbuild (so the local-onlycheck:dev-prereqs/check:skill-frame-freshnessare not owed).CI runs the full farm; the
os-dev-reportcomment on #23753 cites this PR's check-runs by name and conclusion.Acceptance notes
editMode('modal' | 'page',object.zod.tsL2805; its TSDoc says objectui'srecordFormNavigation.tsbranches on it) — a per-object edit-surface intent that the derivation's docblock does not list among its sanctioned overrides and that this skill does not name; whether the skill should teach it is a wording question for the skill's owner, outside this card's one paragraph and its zero-headroom budget. Dedupe words: editMode object edit intent; navigation.md override keys; record-surface sanctioned overrides. (2) The bullet'snavigation.modehint lists 3 of the 7 declared modes (split/popover/new_window/noneomitted) — pre-existing, unchanged. (3)content/docs/releases/v12.mdxL71 says "mobile always pages" — a release page is release-owned history and is never edited in a code PR; it described v12 as shipped.skills/states the old mapping:git grep -n -i -E "full page|always pages|page vs drawer|field-heavy"overskills/at9fc1d4717hits this bullet only.skills/**), Tier H: this PR stays a draft until an authorized approval. No label written: the changeset is present, soskip-changesetdoes not apply, and the dispatch names no other label.skills/objectstack-ui/rules/pages.md+ its changeset) and the release PR chore: version packages (next) #23481 (skills/*/SKILL.md): no shared file.维护者速读(草稿)
改了什么 —
skills/objectstack-ui/rules/navigation.md「Record Presentation」节的 Surface 要点(第 131–135 行,共 5 行)。原文说「字段多的对象,新建/编辑/详情都以整页打开;字段少的用抽屉;移动端一律整页」;现在改为「按字段数与视口推导:字段多的记录(或移动端的任何记录),查看走整页,新建/编辑走弹窗——桌面端有界、移动端全屏;其余用抽屉」。覆盖子句只保留 spec 真实声明的位置(navigation.mode在列表视图上),删掉了「或对象上」这个并不存在的键位。文件行数不变(162 → 162),token 读数不变(2273/2273,余量 0,上限不动);另加一个@objectstack/skills的 patch changeset。为什么改 — 这份技能包随
npx skills add发到客户项目,读者是写元数据的 AI。平台的实际推导(deriveRecordFlowSurface)只有「查看」会走整页;新建/编辑一律是弹窗,PR #23747 落地后桌面端弹窗有界、移动端全屏。原句让 AI 以为新建/编辑会整页跳转,与运行时不符,属于「已发布句子失真」。风险与代价(含回滚) — 纯文本改动,不改任何代码与行为。token 棘轮在零余量下靶内付清(删掉标题括注、与前后文重复的「Don't set it.」、错误的「(or object)」、「for a specific object」),上限不动。回滚:revert 本 PR 即可,无数据与迁移影响。
席位意见 — (留空)
你要做的 — Tier H 面(
skills/**):审阅上面那 5 行英文是否准确(尤其「bounded on desktop, full-screen on mobile」与 #23747 的裁决一致);同意则给 APPROVED review,由席位落地。不需要其他动作。Generated by Claude Code