Skip to content

docs(skills): the upgrade skill's v17-canonical Lead declares its select options - #21402

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-21392-upgrade-skill-select-options
Oct 2, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-21392-upgrade-skill-select-options

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #21392
Clause-②: no

What changed

skills/objectstack-upgrade/references/examples-upgrade.md, § The v17-canonical shapes, compiled — two edits, nothing else in the file:

  1. The status field in the block carrying the os:check marker gains a two-entry options list (New / Qualified, CRM-lead vocabulary), in the shape skills/objectstack-data/references/examples-objects.md:73 already teaches. Every other line of the block is unchanged.
  2. The section's lead sentence is narrowed to what check:skill-examples actually does — a type check. The clause claiming the block "cannot rot into teaching a shape that no longer compiles" is removed: PR feat(spec)!: FieldSchema refuses a select / radio with neither options nor picklist #21390 is the counter-example (the block type-checked green and parsed red at the same time), and the deletion is what pays for the options list under the file's token ceiling.

The section title is untouched (SKILL.md:461 references it by text). No parse limb is added to check:skill-examples — triage 5950866103: not this card, new gates default to no.

Why

PR #21390 (ruling A on #20827, record 5910124148) is on main at c52c49d9: FieldSchema refuses at parse a select / radio with neither a non-empty options list nor a picklist reference. The published block was teaching exactly that shape to every AI author who reads the skill, while the gate watching the block (tsc --noEmit) stayed green — options is optional in the type, and the refusal is a Zod refine. ObjectSchema.create() runs that same parse, so the block as published would also throw at module evaluation.

Measured

Tree: 05733de0 (this PR's head, the branch's only commit). Base: ecb6ca02.

Parse probe (one-shot script in the scratchpad, not committed, no gate added) — the Lead literal extracted from the block and handed to ObjectSchema.safeParse from packages/spec/dist built at this head:

  • before (the block at ecb6ca02): success=false, one issue, code=custom path=fields.status.options, message begins "A select field needs its choices: declare a non-empty options list …"
  • after (this head): success=true

Token ratchet (node scripts/check-skills-token-ratchet.mjs, unit = ceil(utf8 bytes / 4)):

bytes tokens ceiling headroom lines
before 4751 1188 1197 9 119
after 4780 1195 1197 2 119

Net +29 bytes / +7 tokens / 0 lines: the options list costs +94 bytes, the lead-sentence narrowing pays −65. The ceiling is not moved, and no re-wrap is used as currency.

Gates — the 24 families node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derives at 05733de0 (set-equal to the dispatch's list), each exit captured before any pipe, then --ran reconciled: 0 unrun, every family exit 0. Two refused on first run with a printed prerequisite (exit 3 — not a verdict): check:skill-examples until packages/client-react/dist existed, check:doc-formula-expressions until @objectstack/formula and @objectstack/lint were built. After turbo run build --filter=@objectstack/client-react --filter=@objectstack/lint (34 tasks, under the shared verify lock) both ran green: check:skill-examples — "259 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them"; check:doc-formula-expressions — 22 record-scoped examples and 14 field-level *When predicates judged clean.

Not run locally, declared to CI: repo-wide pnpm lint; package test suites (the diff touches no package, and skills/** is in no package's files[], hence skip-changeset).

Risk and rollback

A two-line example-and-prose change in a published skill reference; no runtime, package or gate code moves. Rollback is a revert of 05733de0. Governed surface (skills/**, Tier H): this PR stays draft until an authorized APPROVED review; no seat readies, queues or arms it.

Acceptance notes

  • The lead sentence overclaimed what the gate checks; the mechanism-level remedy (a parse limb on check:skill-examples) is a new gate and explicitly not this card. Noted, not filed; carrier: none.
  • check:skill-examples and check:doc-formula-expressions each exit 3 with a printed remedy on an unbuilt tree — a prerequisite refusal by design, not a finding.
  • ObjectSchema.create() runs the full parse at module evaluation, so the block before this PR would have thrown when executed, not only under os validate. Observation only; the gate that reads the block never executes it.

维护者速读(草稿)

改了什么:升级技能(skills/objectstack-upgrade)参考文件里「v17 规范形状」示例中的 status 单选字段补上两项 options(New / Qualified);该节引导句从「经类型检查所以不会腐烂」收窄为「经类型检查」。文件其余部分、节标题、门禁脚本均未动。

为什么改:PR #21390 已合入,spec 现在在 parse 时拒收没有选项的 select 字段;这段示例正是在教 AI 写一个会被拒收的形状,而守着它的门禁只做类型检查,看不见这一点。写给 AI 的技能说错一句等于产品缺陷(NORTH-STAR 优先规则 4)。

风险与代价(含回滚):纯文档示例,两处改动,不影响任何运行时与发布包;token 账本余量从 9 降到 2,未抬上限。回滚即 revert 本 PR 的单个 commit。

席位意见:(留空)

你要做的:审阅通过即在本 PR 上 APPROVE,席位随后落地;本 PR 应与 #21390 同随下一个 Version Packages 发布。


Generated by Claude Code

…ect options

`FieldSchema` now refuses a `select` / `radio` with neither a non-empty
`options` list nor a `picklist` reference, so the "v17-canonical shapes,
compiled" block in the objectstack-upgrade skill was teaching a shape the
spec rejects at parse while `check:skill-examples` (a type check) stayed
green. The `status` field gains a two-entry `options` list; the section's
lead sentence is narrowed to what the gate actually checks, which pays for
the addition under the file's token ceiling (1188 -> 1195 of 1197).

Claude-Session: https://claude.ai/code/session_01FNKm1SmPpuJASnbjxWGtsJ
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读(终稿)

席位(skills 席 1,session_01FNKm1SmPpuJASnbjxWGtsJ)对照自读的 diff、main 上的 spec 源码与席位自跑的 token 棘轮校正 dev 草稿后定稿,2026-10-02T12:00Z。

改了什么。 对外发布的 skills/objectstack-upgrade/references/examples-upgrade.md「The v17-canonical shapes, compiled」一节:① 示例块里 status 这个 select 字段补上 options: [{ label: 'New', value: 'new' }, { label: 'Qualified', value: 'qualified' }];② 引导句去掉「so it cannot rot into teaching a shape that no longer compiles」—— 这句话声称门禁能防住的事它其实防不住(门禁只做类型检查,不 parse),删掉它也正好付清 token 预算(1188 → 1195 / 1197,余量 2)。+3 / −3,行数 119 不变,节标题、其它示例、SKILL.md 一字未动。

为什么改。 PR #21390(#20827 裁决 A)今天 10:55 合入后,FieldSchema 在 parse 时拒收没有 options 也没有 picklist 的 select。这个发布给 AI 作者的示例块恰好写了这样一个 select:类型检查过、check:skill-examples 绿,但 dev 用构建好的 spec 跑 ObjectSchema.safeParse 实测:改前 success: false(issue 在 fields.status.options),改后 success: true。照它写元数据的 AI 现在会被 spec 拒收。分诊的升级规则(PR #21390 合入即升 p1)已触发。

风险与代价(含回滚)。 纯文档,一个示例块加两项选项、一句引导句收窄;24 条派生门禁全绿,check:skill-examples 改后绿。⚠️ 一处非 diff 的红:dev 给 PR 打 skip-changeset 与 assignee 的那一笔在其沙箱里被权限分类器拒绝(未发出任何请求,本班第二次,上次是 PR #21283);席位依规不代写被拒的那一笔,所以 Check Changeset 目前为红,标签补上即绿。回滚 = revert 本 PR。

席位意见。 建议批准,且建议尽快 —— 发布目录现在在教一个 spec 拒收的形状。席内达档契约复核 PASS(见本 PR 评论)。给 check:skill-examples 加 parse 分支能从机制上防住这一类,但那是新增门禁,需要你点名,本 PR 不碰。

你要做的(一个动作)。 在本 PR 上留一条 APPROVED review(os-zhuang / hotlong 任一),并顺手给 PR 加 skip-changeset 标签 —— 或在 review 文字里写一句「skip-changeset ok」,席位即凭此补标。之后由席位清标、翻 ready、挂 auto-merge 入队(或由你亲手入队);不需要你合并。

@os-zhuang
os-zhuang marked this pull request as ready for review October 2, 2026 12:02
@os-zhuang
os-zhuang enabled auto-merge October 2, 2026 12:02
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 05733de06a7204c65110ea1e2c2e5b88addaa0e2
Local-runs: probe — node scripts/check-skills-token-ratchet.mjs run once from a detached worktree at the head to confirm the dev's ratchet reading (read-only; examples-upgrade.md 1195 / 1197, exit 0, cited in ① 5)

Face: governed skill text (skills/objectstack-upgrade/references/examples-upgrade.md; skills/**, the published catalog), reviewed in-seat by the dispatching seat at the constant's tier. Inputs: #21392 (body and every comment: triage 5950866103, the claim 5951391758, the report 5951825967), this PR's body, its file list (1 file, +3 / −3) and patch against main at ecb6ca02, packages/spec/src/data/field.zod.ts on main, and the check-runs on this head as read at this record.

① Derived judgments

  1. Scope: the 「## The v17-canonical shapes, compiled」 section only — the status field inside the <!-- os:check --> block gains options: [{ label: 'New', value: 'new' }, { label: 'Qualified', value: 'qualified' }], and the lead sentence drops 「, so it cannot rot into teaching a shape that no longer compiles」; the section title, every other line of the block and the file, and SKILL.md (whose :461 cites the title) are byte-identical; 119 → 119 lines. RIGHT.
  2. The defect: since PR feat(spec)!: FieldSchema refuses a select / radio with neither options nor picklist #21390 (A select / radio field with neither options nor picklist: refuse it at the FieldSchema door (an accept-set narrowing), or keep it at the ADR-0078 completeness gate? (split from #19518) #20827 ruling A, merged c52c49d9) FieldSchema refuses at parse a select / radio with neither non-empty options nor picklist (field.zod.ts:2184, 「A select field needs its choices: declare a non-empty options list …」). The published block authored exactly that shape while check:skill-examples (a type check — options is optional in the type) stayed green. The dev's one-shot ObjectSchema.safeParse probe against the spec dist built at the head: BEFORE success: false, one custom issue at fields.status.options; AFTER success: true. RIGHT.
  3. The options form follows the catalog's existing shape (skills/objectstack-data/references/examples-objects.md:73: label / value pairs); the values fit the block's CRM-lead context; written as one continuation line because the wrapped form costs 1198 tokens and does not fit. RIGHT.
  4. The lead sentence now claims only what the gate measures (「This block is type-checked against the published spec:」) — the over-claim triage named is gone, and this is the edit triage allowed to pay for the addition; no parse limb was added to the gate (⛔ not this card). RIGHT.
  5. Token ratchet: 1188 → 1195 of 1197 (headroom 9 → 2), seat-run confirms; +94 bytes for the list, −65 for the narrowing, net +29 bytes / +7 tokens / 0 lines; no ceiling moved, no re-wrap, no other sentence deleted. RIGHT.
  6. Gates: 24 / 24 exit 0 at the head, --ran 24 / 24, 0 NOT-MEASURED; check:skill-examples (not in the derived 24; run as the dispatch named it) exit 0 AFTER under the verify lock — 259 prose examples type-check. The BEFORE leg of that gate was not run locally (NOT MEASURED; the type-level fact is uncontested and CI on main is green). RIGHT.
  7. Dev readings, noted not filed: the mechanism-level remedy (a parse limb on check:skill-examples) is a new gate and explicitly not this card; ObjectSchema.create() runs the full parse at module evaluation, so the pre-fix block would have thrown when executed — the gate never executes it. RIGHT.

② Semver level

Docs-only in a governed surface no package ships (skills/** in no files[]); skip-changeset is the correct reading; Clause-②: no. Consistent.

③ Boundary flags

  • skip-changeset and the PR assignee are NOT on this PR. The dev's one label-write stroke was refused inside its sandbox by the auto-mode permission classifier before any request left the container (nothing written, not re-routed). As on PR docs(skills): the dashboards rule stops teaching a per-series override on the compareTo comparison series #21283, the seat does not perform a write on a dev's behalf after that dev's own attempt was refused; it records the gap here and puts it in front of the maintainer. Consequence: Check Changeset reads failure on this head for a reason that is not the diff. The seat's own four-piece (label needs-user-decision, the final 维护者速读, the review request, the assignee) goes on as the seat's standing duty.
  • Triage's raise rule (「if PR feat(spec)!: FieldSchema refuses a select / radio with neither options nor picklist #21390 merges while this card is open, it goes to p1」) is met: PR feat(spec)!: FieldSchema refuses a select / radio with neither options nor picklist #21390 merged at 10:55Z, 41 minutes after the card was filed. The relabel is triage's; the seat dispatched at once regardless. Until this PR lands, the published catalog teaches a shape the spec refuses.
  • Check-runs on 05733de0 at this record: 17 success, 7 skipped, 4 in_progress (Lint & Repo Gates, Test Core 1/6, 2/6, Type Check · workspace), 1 failure (Check Changeset, the label above). Tier H landing: an authorized APPROVED review, then every check green on the landing head; no other open PR touches skills/objectstack-upgrade/**.
  • open_questions: none.

Implemented-by: claude/issue-21392-upgrade-skill-select-options
Reviewed-by: session_01FNKm1SmPpuJASnbjxWGtsJ

VERDICT: PASS (text); landing blocked on the approval and the skip-changeset label, neither of which is the diff's.

@os-zhuang
os-zhuang added this pull request to the merge queue Oct 2, 2026
Merged via the queue into main with commit a513940 Oct 2, 2026
35 of 37 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-21392-upgrade-skill-select-options branch October 2, 2026 12:42
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/xs

Projects

None yet

3 participants