Skip to content

docs(skills): type-check more objectstack-ui examples with os:check - #31706

Merged
os-zhuang merged 2 commits into
mainfrom
claude/project-thread-eonc0l
Nov 9, 2026
Merged

os-zhuang merged 2 commits into
mainfrom
claude/project-thread-eonc0l

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steedos · project thread

Refs #31112 (slice 3 of a per-skill split: item 4, objectstack-ui; the card stays open)

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:objectstack-ui 技能包里又有 10 段 TypeScript 示例接入了示例编译检查(33 段中由 15 段变为 25 段),涉及动作、页面、仪表盘和看板/甘特视图的示例;没有发现写错的示例。
  • 为什么改:AI 编写界面元数据时最先照抄这些示例;接入检查后,规范一旦改名或收紧,示例会在 CI 里立刻变红,而不是悄悄教错。
  • 风险与回滚:只改发布技能包的文档文字,不动任何运行时代码;四个文件的 token 上限都未抬高,新增字节靠同文件删减重复说明支付(每处删减的规则都在同文件另有出处)。回滚即 revert 本 PR。
  • 先看:skills/objectstack-ui/rules/dashboards.md(4 段新接入、删减最多)、skills/objectstack-ui/rules/list-views.md(看板与甘特示例改为带类型的 ListView)、skills/objectstack-ui/rules/pages.md(3 段新接入)。
  • 两分钟验证:pnpm --filter @objectstack/spec check:skill-examples,预期最后一行为 332 段示例全部通过类型检查。
  • 需要你做的:作为受管面审批人审阅并批准本 PR(skills/** 属 Tier H)。

What changes

skills/objectstack-ui had 15 of its 33 fenced ts/typescript blocks under check:skill-examples (measured on main 8210894, all *.md outside evals/; references/_index.md and the generator-owned references/react-blocks.md, which holds no ts block, excluded). It now has 25. Every new mark is the os:check marker on the line above the fence; each wrapper is one import line plus a typed const on the existing first line (and, for the two arrays, one opening and one closing line), never more than three lines.

File marked before → after / blocks tokens before → after / ceiling lines before → after
rules/actions.md 4 → 5 / 5 2258 → 2257 / 2259 181 → 184
rules/dashboards.md 4 → 8 / 9 6232 → 6231 / 6232 462 → 473
rules/list-views.md 3 → 5 / 11 3451 → 3446 / 3451 329 → 334
rules/pages.md 1 → 4 / 4 5648 → 5668 / 5669 426 → 432
untouched: SKILL.md, navigation.md, record-page.md 0/1, 2/2, 1/1 headroom 0, 0, 0 unchanged

Skills bundle reading: no SKILL.md changed, so the sum of every published SKILL.md stays 4592 lines.

  • rules/actions.md: the opensInNewTab + newTabUrl action gains its defineAction import and is marked.
  • rules/pages.md: the kind: 'html' page gains its definePage import; the styled pricing card becomes const card: PageComponent = { … }; and the doc navigation item const navigation: NavigationItem[] = [ … ];. The orphan-looking marker above the master/detail block is over a tsx fence and was already counted by the gate, not by this ts tally.
  • rules/dashboards.md: the dataset-bound widget becomes const widget: DashboardWidget; the two filterBindings widgets and the two compareTo widgets become const widgets: DashboardWidget[] = [ … ]; (the second pair gains the comma between its two objects); the options line becomes const options: DashboardWidget['options']. The two bare compareTo: lines stay a fragment and the file says so once.
  • rules/list-views.md: the kanban and gantt examples become const board: ListView and const timeline: ListView, so a top-level groupBy or a missing gantt.startDateField now fails the gate. The bare-key blocks (data, columns, filter, userFilters, sort, grouping) stay fragments and the file says so once.

Why

#31112 item 4 (ruling B of #22059): published examples are guarded by the opt-in type check, and every defect the P0 text-fix card found sat in an unmarked block. This slice brings objectstack-ui's self-contained examples under it.

Example fixes

None. Every candidate block was probed in isolation with its wrapper (TS API, syntactic then semantic pass, with a planted unknown key per file as the control leg) and compiled as written.

Trims that paid the marks (each cut and where its rule survives)

  • rules/actions.md §Action body context: "— the blessed name (same axes and undefined cases as hooks, objectstack-data)" became "(as in hooks, objectstack-data)". The blessed-name rule survives at skills/objectstack-data/references/data-hooks.md:584 ("the single blessed name") and the same read at :619.
  • rules/actions.md new-tab warning: "builds and draws a checkbox in the dialog" became "draws a checkbox"; the rule (never express new-tab via params) is unchanged.
  • rules/pages.md kind:'html': "; use kind:'react' for those" cut; survives in the tier table's react row (hooks, onClick, expressions).
  • rules/pages.md styling block: its comment "every block carries responsiveStyles + tokens" cut; survives in the Rules list above it (stable id on every styled node, values as design tokens).
  • rules/pages.md routing: "; that gives one doc many addresses and breaks cross-references" cut; survives as "so a doc has exactly one URL" in the same paragraph.
  • rules/pages.md live instances: "(one source, never a stale copy)" cut; survives at "Write business concepts" ("has no producer and drifts; the self-describing metadata is the one source").
  • rules/dashboards.md §compareTo: "The renderer derives the comparison automatically; no second filter is required." cut; survives at Requirements ("The shifted query reuses the original filter shape and replaces only the date-bound clauses"). ", so what a widget declares is exactly what runs" cut; the same-shape statement it followed stays.
  • rules/dashboards.md KPI example comments: the metric's "renderer fetches the prior quarter and surfaces a secondary value + delta arrow" survives at Metric widgets ("a delta arrow plus a trend label"); the chart's "(M2). The renderer issues a second query … overlays it as a muted/dashed series" survives at the §compareTo opening and at Cartesian charts (dashed, reduced opacity).
  • rules/dashboards.md: the metric comment "(binds the crm_task_metrics dataset; filter = runtimeFilter)" survives in the block's own dataset: key and at §Dataset-Bound Widgets ("presentation-scope filter flows into the query as the runtime filter"); "for this widget only" in the options comment survives in the dateGranularity table row ("for this widget only"); the pie/donut rationale clause cut, the rule ("compareTo is silently ignored") stays.
  • rules/list-views.md: "Every view lives under list / form / listViews / formViews, as above." survives in §The defineView container's first sentence; the lanes comment "option VALUES to draw, in this order" survives in the note under the block ("lanes chooses the lanes and their order … not one of the field's inline options"); "— past the right edge of a narrow screen —" survives in hand-over item (a) ("scroll right"); "; declare searchableFields to choose the set" survives in the table row "declares searchableFields | that list, verbatim"; ": nothing ever drew it", "(the block above)" and "(CRUD, live updates, filtering, pagination)" carried no rule.

Tests

check:skill-examples, before and after, and the reverse check
  • Before (main 8210894): ✅ 322 prose examples type-check across 3 surface(s).
  • After (head 3bc338e; 0de24c0 adds only a merge of main touching no skills/** or packages/spec path): pnpm --filter @objectstack/spec check:skill-examples exited 0 with ✅ 332 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them (skills + docs surface 288 → 298).
  • Reverse check, after the commit: planted one wrong key per touched file: newTabTarget (rules/actions.md:165), docName on the doc nav item (rules/pages.md:365), the retired widget position (rules/dashboards.md:52) and a top-level kanban groupBy (rules/list-views.md:264). The checker exited 1 with TS2353 at exactly those four lines. Restored with git checkout HEAD -- skills/objectstack-ui; git diff HEAD and git status --porcelain were empty after.
Derived gate sweep (head 3bc338e)

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 44 commands. 43 exited 0. pnpm check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET: needs every package's dist; CI runs it). dispatch-gates --ran exited 0: 44 derived, 43 run, 1 NOT-MEASURED, 0 unrun. Re-run on the merged head 0de24c0: check-skills-token-ratchet, check-changeset-no-major --base origin/main, check:skill-links, check-empty-changeset --base origin/main, all exit 0.

Acceptance notes

  • check:skill-examples is not in the derived gate list for a skills/** diff, so it was run by hand.
  • Unmarked, and why: SKILL.md's subforms block is indented three spaces inside a numbered list item, and the gate's fence pattern only reads a fence at column 0, so a marker there would be an orphan; moving it out of the list would break the list and costs bytes SKILL.md does not have (headroom 0). In rules/list-views.md, filter, sort and grouping would compile with a three-line wrapper (probed green), but each costs about 100 bytes and the file has 5 tokens left after the kanban and gantt marks; data (a [...] placeholder), columns (two statements) and userFilters + appearance are true fragments. In rules/dashboards.md the two bare compareTo: lines are a fragment.
  • No ceiling was raised or lowered; the ratchet printed no lowering instruction.
  • This build ran on the default tier: dispatch-gates --tier mandates Fable for skills/**, and the claim records the no-Fable-build exit; the contract review is the seat's, on the lane's isolated reviewer.

Verification

pnpm --filter @objectstack/spec check:skill-examples (needs @objectstack/spec and @objectstack/client-react built) prints 332 examples green; node scripts/check-skills-token-ratchet.mjs exits 0 with every skills/objectstack-ui file within its ceiling.

Human Minimum

A governed approver reviews and approves (Tier H).

🤖 Generated with Claude Code


Generated by Claude Code

Ten more self-contained blocks in the objectstack-ui rules files carry the
os:check marker: the new-tab action and html page gain their imports, and
the pricing card, doc nav item, four dashboard widgets and the kanban and
gantt views are typed against @objectstack/spec/ui. Each file pays the
marks inside its own token ceiling by trimming restatements whose rule
survives elsewhere in the same file.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsR2jUzyjnwuhUWHpExHXT
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 8, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#3 · zhuangjianguo · session_01QsR2jULfPnqQFGcZUtKDFH

Contract-review-claim: session_01QsR2jULfPnqQFGcZUtKDFH · head 0de24c0 · 2026-11-08T22:11Z

The lane seat's isolated Fable reviewer runs the CONTRACT_REVIEW_TIER review (maintainer 2026-11-08 16:12Z 「有 fable 车道就可以契约复审啊」); the director seat is off duty.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#3 · zhuangjianguo · session_01QsR2jULfPnqQFGcZUtKDFH

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 0de24c02b390ebefe2fe33fc93cfc97c83f5eec9
Local-runs: none
Scope: skills/objectstack-ui/rules/actions.md, skills/objectstack-ui/rules/dashboards.md, skills/objectstack-ui/rules/list-views.md, skills/objectstack-ui/rules/pages.md + none

Inputs read: card #31112 (body + all 10 comments, incl. claim 6727530009 and dev report 6727833568), PR #31706 (body, 5-file list, git diff origin/main...pr/31706 = 3bc338e + a merge of main), the check-runs on 0de24c02. The remainder of the diff (.changeset/31112-ui-skill-examples-checked.md) is the lane seat's ACCEPT at TIER_DEFAULT; it is read here only for ②.

① Derived judgments

  • Accept set of check:skill-examples grows by 10 blocks (objectstack-ui 15 → 25 of 33 ts/typescript fences): actions 4→5/5, dashboards 4→8/9, list-views 3→5/11, pages 1→4/4 (+ the pre-existing tsx master/detail block, which FENCE_OPEN_RE already recognises, so its marker was never an orphan). Counted on the head tree: fences and markers match the dev report exactly. Right.
  • No public surface changes. The diff touches four skill rule files and one changeset; no schema, gate, script, ceiling or generated output moves. The four ratchet ceilings in scripts/check-skills-token-ratchet.mjs (2259 / 6232 / 3451 / 5669) are untouched, and the head files read ceil(bytes/4) = 2257 / 6231 / 3446 / 5668 (main: 2258 / 6232 / 3451 / 5648) — every file at or under its ceiling, none raised. Right.
  • Every wrapper type is the authoring (z.input) half of its schema, except one. DashboardWidget, ListView, PageComponent, Dashboard are declared z.input of their schemas in dashboard.zod.ts:1874, view.zod.ts:8134, page.zod.ts:2287; defineAction / definePage take z.input. So the dashboards and list-views wrappers (widgets with no type, no layout) compile because type has a default and layout is optional on the input half — that matches the rule text ("requires dataset + values"). NavigationItem (app.zod.ts:867) is the OUTPUT union; the input half is NavigationItemInput (app.zod.ts:~905, the one defineApp consumes). See ④ nit.
  • Fragment notes. dashboards.md:241 (the two bare compareTo: lines) and list-views.md:38 (all bare-key blocks) each say once why a block is unmarked, as the card's item 4 asks. Right.
  • Gate verdicts on the head. Every non-skipped check-run that had completed at review time is success (Lint · repo & tooling gates, Lint · docs & code guards, Check Changeset, Governed Surface Queue Guard, PR-body guards, Type Check · source gates / workspace, Build Core, Test UI, Live E2E UI, …). check:skill-examples is NOT in the derived gate list for a skills/** diff (the dev ran it by hand); it IS run in CI by .github/workflows/lint.yml:6322 inside job typecheck-consumers = check-run Type Check · consumer gates, which concluded success on 0de24c02 (landed while this record was being written; it is the gate verdict on the ten new marks, not the dev's hand run). 25 of 26 non-skipped check-runs complete, all success, 0 failures; Test Core (1/8) was still running and touches no file in this diff.

② Semver level

.changeset/31112-ui-skill-examples-checked.md: '@objectstack/skills': patch (package exists at packages/skills/package.json), Clause-②: no, Metadata-protocol: none; the PR body carries the same two lines. The diff publishes prose-only changes to four skill rule files — no exported type, schema, enum or runtime path changes — so patch is the right level, exactly what card #31112 §Acceptance prescribes per slice and what slices 1 (#31507) and 2 (#31618) used. Check Changeset is success on the head.

Clause-②: no — confirmed against the tree: no narrowing of any published spec, no capability removed at a consumer.

③ Boundary flags

Dev flags (report 6727833568 deviations + PR body "Acceptance notes"), each answered:

  1. "check:skill-examples is not in the derived list; run by hand" — answered: CI runs it in Type Check · consumer gates (lint.yml:6322); that check-run's conclusion on 0de24c02 is the gate verdict, not the dev's hand run. Conclusion on the head: success (see ①), agreeing with the schema reads in ④.
  2. "SKILL.md subforms block unmarked: fence indented 3 spaces in a list item; FENCE_OPEN_RE reads column-0 fences only; headroom 0" — verified: check-skill-examples.ts:711 FENCE_OPEN_RE = /^```(ts|tsx|typescript)\s*$/ is anchored at column 0; SKILL.md:80 opens the fence as ```typescript (three spaces, inside list item 2). Un-indenting would break the list and SKILL.md sits at 3814/3814. Rightly unmarked.
  3. "list-views.md filter, sort, grouping unmarked for token headroom (each wrapper ~100 bytes, probed green; 5 tokens left)" — verified arithmetically: head 13783 bytes = 3446 tokens against a 3451 ceiling (5 tokens = 20 bytes); the smallest wrapper (import type { ListView } … + const x: ListView['filter'] = + ;) is well over 20 bytes. Rightly left for a later slice; data ([...] placeholder), columns (two statements) and userFilters+appearance (two keys) are true fragments.
  4. "no ceiling raised or lowered; the ratchet printed no lowering instruction" — verified (diff touches no script; Lint · repo & tooling gates success).
  5. "default tier, no Fable build" — answered: this record is the lane's isolated CONTRACT_REVIEW_TIER review the claim amendment 6724423900 and claim 6727530009 promised; Tier H approval by a governed approver remains whole-PR and is outside this record.

open_questions: none in the report. Serial constraint "PR #31617 (#31487) merged first": verified — actions.md:25–26 on main and on the head carry the helpText locale-map rule unchanged, and action.zod.ts:194,437 (actionParamHelpText, localeMap: true) agrees with it. Nothing escalated.

④ Design judgment

Method: each new mark's block read against the rule text around it and against the schema in the live tree (packages/spec/src/ui/*.zod.ts on main); each trim read against the named surviving home on the head; the four hits files read against the eval prompts in skills/objectstack-ui/evals/*.json.

rules/actions.md — new mark: OpenInvoicePdfAction gains import { defineAction } from '@objectstack/spec/ui'. Schema: opensInNewTab (action.zod.ts:1906), newTabUrl /^\// (1931) with the refine "only valid together with opensInNewTab: true" (2474) — the block declares both, exactly what the prose above it says; a type: 'script' action with target and no body is legal (body optional, 1337). Lesson unchanged. Trims: "the blessed name (same axes and undefined cases as hooks…)" → the blessed-name rule lives at objectstack-data/references/data-hooks.md:584 and :619 (checked); "builds and draws a checkbox in the dialog" → "draws a checkbox" keeps the rule (never express new-tab via params). Eval "Convert action … bulk Add to campaign" unaffected. Holds.

rules/dashboards.md — four new marks. (a) dataset-bound widget → const widget: DashboardWidget — id, type, title, dataset, dimensions, values, layout all declared on DashboardWidgetSchema (strict, 1115). (b) filterBindings pair → DashboardWidget[]: filterBindings: z.record(string, string | false) (1406) — { region: 'sales_region' } and { task_status: false } are the two rows of the table above the block; the widgets omit type/layout, legal on the input half. (c) compareTo pair → DashboardWidget[] with the comma the fragment lacked; compareTo: { kind } is the object form the schema prescribes (370–410). (d) options → DashboardWidget['options']: DashboardWidgetOptionsSchema declares the five keys and is .passthrough() (313–368), so this mark checks the five keys' value types and would NOT catch a sortDirection typo — consistent with the prose ("a typo parses too, and draws that warning" from os validate), so the teaching is not overstated. Trims, each checked on the head: "renderer derives the comparison automatically; no second filter" → Requirements l.261–262; the KPI comments → Metric widgets l.248 and Cartesian charts l.252–256 + the §compareTo opening l.229–230; "(binds the crm_task_metrics dataset; filter = runtimeFilter)" → the block's own dataset: + l.43–44; "for this widget only" → table row l.347; the pie/donut rationale cut, the rule stays l.257. Eval prompts "date-range filter must re-scope six charts" (filterBindings) and "avg days … vs the previous period; slower is worse" (compareTo + polarity, l.248–251) still answered by the text. Holds.

rules/list-views.md — two new marks. Kanban → const board: ListView: KanbanConfigSchema (strict, 2359) has groupByField, lanes, summarizeField, columns (2364–2438); type: 'kanban' is in the view-type enum (3340). A top-level groupBy is now a TS2353 against the strict ListView shape — the exact rule the heading states ("no top-level groupBy"). Gantt → const timeline: ListView: GanttConfigSchema (strict) requires startDateField / endDateField / titleField and declares progressField, dependenciesField, parentField — matching the prose "required in it". Inside a typed const, data: { provider: 'object', … } is contextually narrowed, so no as const is needed (unlike the defineView blocks' hoisted data). Trims: "Every view lives under list/form/listViews/formViews" → l.13–14; the lanes comment → the note l.276–279; "past the right edge of a narrow screen" → hand-over (a) "scroll right" l.299; "declare searchableFields to choose the set" → table row l.182. Eval "add a priority select and a kanban grouped by it … tell them what they will see" asserts listViews, groupByField: 'priority', Uncategorized — all still taught (l.281–305). Holds.

rules/pages.md — three new marks. kind: 'html' page gains definePage import; kind enum ['full','slotted','html','react'] (page.zod.ts:2133), source optional string (2209), type: 'home' — the block is the §html tier's one example and now compiles. Pricing card → const card: PageComponent: PageComponentSchema is strict with id?, type (vocabulary union), properties record, responsiveStyles: ResponsiveStylesSchema (strict, keys large|medium|small|xsmall, responsive.zod.ts:99) — the block's large/small maps and properties.children are what the Rules list above it prescribes (l.245–258); the cut comment duplicated l.247–252. Doc nav item → const navigation: NavigationItem[]: DocNavItemSchema (strict, app.zod.ts:793) has type: 'doc', doc (regex), book?, plus id/label/icon from BaseNavItemSchema — compiles and teaches the doc: target the prose names; eval "write a user guide … link it from the nav" asserts type: 'doc', still taught. Trims: "use kind:'react' for those" → tier table react row l.133; "that gives one doc many addresses…" → "so a doc has exactly one URL" l.351–352; "(one source, never a stale copy)" → l.340–342. Holds, with one nit:

  • nit — pages.md:362–364 types the authoring example with NavigationItem, the OUTPUT half of the union (app.zod.ts:867: "what a parse returns"), while the input half NavigationItemInput (app.zod.ts:~905) is the type defineApp(config) typed as z.input of AppSchema reads and the one the other three new wrappers in this PR parallel (DashboardWidget, ListView, PageComponent are all z.input). For the doc arm the two halves are identical (no .default() on DocNavItemSchema or BaseNavItemSchema), so the block compiles and teaches the doc item correctly; a reader who copies NavigationItem[] as the type of their own navigation array and adds a url or group item would be asked for target / expanded, values the schema exists to supply. No effect on this block's correctness or on the contract. Prose-face fix if taken: NavigationItem → NavigationItemInput (×2, +10 bytes; pages.md has 4 bytes of ceiling left, so it needs a 6-byte trim in the same file) — or leave as an accepted deviation.

Design-break attempts that did not break it: (i) wrappers hiding a wrong lesson — none; every wrapper is one import + a typed const on the existing first line (two arrays add [/];), and each block's keys are the keys the surrounding paragraph names. (ii) a trim removing a rule's only home — each of the 16 cuts was traced to a surviving sentence on the head (named above); the three the dev calls rule-free (": nothing ever drew it", "(the block above)", "(CRUD, live updates, filtering, pagination)") carry no rule. (iii) a mark weaker than the prose implies — only options (passthrough bag), and the prose already says the typo "parses too". (iv) the unmarked set — SKILL.md's indented fence and list-views' headroom claim both verified against the gate regex and the byte count. (v) the eval prompts — no must_contain string depends on cut text.

No must-fix, no should-fix. One nit; nits alone end the round.

Implemented-by: claude/project-thread-eonc0l
Reviewed-by: session_01QsR2jULfPnqQFGcZUtKDFH

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#3 · zhuangjianguo · session_01QsR2jULfPnqQFGcZUtKDFH

维护者速读

  • 改了什么:objectstack-ui 技能里又有 10 段能独立成立的 TypeScript 示例加上 <!-- os:check --> 标记,CI 会把它们当真代码编译,覆盖从 15/33 升到 25/33(actions 5/5、dashboards 8/9、list-views 5/11、pages 4/4)。没有发现写错的示例。
  • 为什么改:AI 照抄技能示例写动作、页面、仪表盘和视图,没人编译的示例会在规范改名后悄悄过期。现在键名一错,CI 直接变红(skills: one home per rule — the same rule written in three skills, "moved verbatim" stubs in data and upgrade SKILL.md, an undocumented user-invocable frontmatter key, and <!-- os:check --> coverage of 1/63 (platform) and 0/42 (query) example blocks #31112 第 4 项,ui 这一片)。
  • 风险与回滚:只改技能文档,不动运行时,没有抬高任何 token 上限。新增字节靠同文件删掉重复说明支付,每处删掉的规则在同文件另有出处,复审逐条核过。回滚即 revert 本 PR。
  • 先看:skills/objectstack-ui/rules/dashboards.md(4 段新接入、删减最多),以及 rules/list-views.md 把看板和甘特示例改成带 ListView 类型的写法。
  • 两分钟验证:pnpm --filter @objectstack/spec check:skill-examples 退出 0,统计应为 332 段示例。
  • 需要你做的:批准本 PR(Approve review)。契约复审 PASS 记录是评论 6727980514,Head-sha 0de24c02b390ebefe2fe33fc93cfc97c83f5eec9;批准后由席位落地。
  • 席位意见:ACCEPT。席位读了 diff:新增的只有标记、类型导入和 const 包装,规则教的写法没变;CI 上跑 check:skill-examples 的 Type Check · consumer gates 在本 head 为 success。

席位核对

Head-sha: 0de24c02b390ebefe2fe33fc93cfc97c83f5eec9

  1. Shape: draft, base main, body Refs #31112 (slice 3 of a per-skill split; the card stays open), changeset '@objectstack/skills': patch. 5 files, +81/−46. Tier H (skills/**).
  2. Premise measured: the slice-2 release note 6727444552 counted ui at 15/33 on main 09df571; its serial PR docs(skills): a param's helpText takes a sentence or an inline locale map in the ui actions rule #31617 (skills: objectstack-ui actions rule still teaches a param's helpText as a sentence only; it takes an inline locale map since objectstack#28266 #31487) had merged. The dev's reverse check went red with TS2353 at all 4 planted lines and came back clean, so the marks are live.
  3. Gates: dev gates 44 derived, 43 exit 0; dual-build-cjs-loads exit 3 (needs a full build; no build input touched). check:skill-examples 322 → 332 exit 0. Check-runs on this head at ACCEPT: 28 success, 15 skipped, 0 failure, 0 running.
  4. Accepted deviations: SKILL.md's subforms block stays unmarked, because its fence is indented inside a list item, the gate reads only column-0 fences, and SKILL.md is at 3814/3814 tokens. list-views filter/sort/grouping compile with a wrapper but stay unmarked for want of headroom (3446/3451). Review nit, accepted as is: pages.md:362–364 types the doc-nav example with NavigationItem (output half) where NavigationItemInput is the authoring half. It is identical on the doc arm, so the block compiles and teaches correctly. The rename costs 10 bytes against 4 bytes of headroom, so it rides the next pages.md edit. Model: opus build under the standing no-Fable-build rule, Fable review (claim 6727530009).
  5. Out of scope / Skills-docs: items 1–3 of skills: one home per rule — the same rule written in three skills, "moved verbatim" stubs in data and upgrade SKILL.md, an undocumented user-invocable frontmatter key, and <!-- os:check --> coverage of 1/63 (platform) and 0/42 (query) example blocks #31112, and item 4 for formula and platform, stay on the card; the automation slice stays too. Metadata-protocol: none, so no Skills-docs: line is owed.
  6. Landing: Tier H. pm:awaiting-merge + reviewers os-zhuang, hotlong; stays draft until an authorized approval or a maintainer merge. K = 2 first-parent merges since merge-base 9bf32864. Refs, not Fixes: the seat releases the card to pm:queue with the remaining counts after the merge.

@objectstack-fleet objectstack-fleet Bot added the pm:awaiting-merge PR only: landing waits on the maintainer's own review and merge (SKILL.md 复核 ②); never on an issue label Nov 8, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review November 9, 2026 00:16
@os-zhuang
os-zhuang added this pull request to the merge queue Nov 9, 2026
@objectstack-fleet objectstack-fleet Bot removed the pm:awaiting-merge PR only: landing waits on the maintainer's own review and merge (SKILL.md 复核 ②); never on an issue label Nov 9, 2026
Merged via the queue into main with commit 5d8e559 Nov 9, 2026
52 checks passed
@os-zhuang
os-zhuang deleted the claude/project-thread-eonc0l branch November 9, 2026 00:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants