Repository navigation
[Decision] bind the published skills catalog to the ObjectStack version it teaches: ship skills/** as a versioned package beside @objectstack/spec (A), pin a git ref per release (B), warn on mismatch (C), or keep serving main #22649
Description
Ruled: 6096124407 · letter A · 2026-10-10T09:28Z
Filing gate ②: a decision only the maintainer can make. Raised by the maintainer in the skills seat's session on 2026-10-10, verbatim: 「这个应该立一个决策卡,然后按总监决裁格式和我讨论:skills 感觉应该是要绑定objectstack版本才对,目前只有整个仓库一个版本,和我讨论后续应该如何改进」. Filed by domain:skills seat 1 (seat post #7623, session_01RdnZdPZH9ByduzPRWuH9tN). Reader: the maintainer rules with a letter; the skills seat then files the execution cards (the cli and devx halves go to their lanes with Blocked-by:). ⛔ Not a claim.
一句话问题
今天装 ObjectStack 的人拿到的 AI 技能文本来自仓库 main,不是来自他装的那个版本:一个刚装了 17.7.0 的新项目,其技能已经在教只有 v18 才接受的写法。
Background (measured on origin/main 86da194919, 2026-10-10)
- The published catalog is
skills/**(10 skills). It ships verbatim bynpx skills add objectstack-ai/objectstack/skills --skill '*' --agent claude-code -y(five docs pages andpackages/create-objectstack/src/skills-install.ts), which the skills CLI resolves from the GitHub repository's default branch at the moment the command runs.npm create objectstackruns that command after installing the latest published packages. - The only version binding is self-declared prose: every
SKILL.mdcarriescompatibility: Requires @objectstack/spec 17.x (Zod v4 schemas)and a hand-bumpedmetadata.version("4.4","1.3", …).scripts/check-skill-compatibility-version.mjsreconciles the17.xagainst the WORKSPACE's spec version, so the line followsmain, not the consumer. Each skill'sreferences/_index.mdpoints into the consumer'snode_modules/@objectstack/spec/src/**(the published spec ships its.zod.tssources), so the schema pointers are version-aligned by construction; theSKILL.mdprose is not. - The gap is live now:
skills/objectstack-automation/SKILL.md:108–:109onmainteachestitle: 'Done: {{ record.title }}'(the v18 text-slot delimiter, PR docs(skills): objectstack-automation teaches the {{ }} delimiter in flow text slots #22475 undertarget:v18), whilenpm view @objectstack/spec versionanswers17.7.0. Everytarget:v18landing that touchesskills/**widens it until 18.0.0 is published; after that the reverse holds for every 17.x project that re-runs the install command. - The repository publishes one fixed version line (
.changeset/config.jsonfixedgroup:@objectstack/spec,@objectstack/cli, … all 17.7.0) and a git tag per package per version (refs/tags/@objectstack/spec@17.7.0exists; 15,909 tags). - The skills CLI (
skills@latest, help read 2026-10-10) hasadd PACKAGE(a GitHub owner/repo/path or URL; no ref flag in its help),experimental_sync("Sync skills from node_modules into agent directories") andexperimental_install(restore fromskills-lock.json).
Governing text
None rules on it. Nearest texts, quoted: AGENTS.md § Skills — "skills/ — the published catalog (it ships to customer projects)"; packages/spec/scripts/build-skill-references.ts header — "Skills do NOT bundle copies of the schemas — when a skill is installed into a metadata-driven project (e.g. via skills.sh), @objectstack/spec is always present as a dependency. Pointing at the published source files keeps a single source of truth and stays version-aligned automatically"; scripts/check-skill-compatibility-version.mjs header — "compatibility is a skill's only self-declared applicability range, and it ships to third parties verbatim". Prime Directive #14 keeps skills/** Tier H under every option. grep: git grep -n 'published.*catalog\|version-aligned\|self-declared applicability' origin/main -- AGENTS.md packages/spec/scripts/build-skill-references.ts scripts/check-skill-compatibility-version.mjs → the three lines above. No ADR names the catalog's distribution: ADR-0003 is runtime metadata-package versioning and ADR-0063 is runtime AI skills, neither the authoring catalog.
Protocol declaration
No packages/spec schema changes under any option. Option A changes what a published package ships (a new package in the fixed group); it changes no contract.
Premises, each with its re-check
main's skills teach v18 spellings while the latest published spec is 17.x —git grep -n 'Done: {{ record.title }}' origin/main -- skills/objectstack-automation/SKILL.md(1 hit; controlgit grep -c 'defineFlow' origin/main -- skills/objectstack-automation/SKILL.md≥ 1) andnpm view @objectstack/spec version.- The install path reads
main—git grep -n 'npx skills add objectstack-ai/objectstack/skills' origin/main -- content/docs packages/create-objectstack/src(≥ 5 hits; controlgit grep -c 'skills' origin/main -- skills/README.md≥ 1). - The only binding is the hand line —
grep -n '^compatibility:' skills/*/SKILL.md(10 lines, all17.x);node scripts/check-skill-compatibility-version.mjsreconciles against the workspace. - The skills CLI can sync from
node_modules—npx -y skills@latest add --help | grep -c experimental_sync(1). - A tag exists per published version —
git ls-remote --tags origin '@objectstack/spec@17.7.0'(1 line).
选项 × 真实代价 × 开发工作量
| 选项 | 做什么 | 客户可感知的后果 | 开发工作量(车道 · PR 数 · 实测先例) |
|---|---|---|---|
| A 技能随版本发运 | 新增发布包 @objectstack/skills(进 changeset fixed 组,版本号恒等于 spec;构建时把根目录 skills/** 复制进包,files 只含它);npm create objectstack 与现有项目从已装的包同步技能(npx skills experimental_sync,或 scaffolder 自行复制);GitHub 路径只作文档里写明的 next 渠道;compatibility: 行与每技能 metadata.version 改为由包版本派生 |
装 17.7.0 的项目拿到 17.7.0 的技能;升级到 18 时技能随 pnpm up 一起换;永远读不到自己版本不接受的写法 |
skills 车道 2 PR:包骨架(S)+ 兼容行派生,触及 10 个 SKILL.md 的 frontmatter(Tier H,S;先例 PR #22475 一文件 +17/−18)· cli 车道 1 PR:scaffolder 改从包同步(M;先例 skills-install.ts 及其 e2e)· devx 车道 1 PR:5 页文档改命令(S;先例 PR #22556,按 major 分页,15 文件 +860/−1696)。共 4 PR、3 车道 |
| B 每个发布版一个 git ref | 发布时让安装命令指向该版本的 tag(…/tree/@objectstack/spec@17.7.0/skills 形);17.x 的技能修复走 release/17.x 分支 |
装对 ref 就对;装错或忘改 ref 就回到今天;17.x 技能修复要有人维护分支 | devx 1 PR(文档与 scaffolder 的 ref 拼法,S)+ 常设分支维护流程(本仓无先例:单主干、固定版本线、无 backport);skills CLI 的 add 今天的帮助里没有 ref 参数,URL 形 NOT MEASURED |
| C 维持现状,装时核对 | scaffolder/安装步骤读已装 spec 的 major 与技能的 compatibility: 行,不一致响亮拒绝或警告 |
用户被告知不匹配,但仍拿不到匹配版本的技能(main 只有一份) | cli 1 PR(S);不解决 18.0 发布后 17.x 用户的来源问题 |
D = A + 保留 GitHub 路径为显式 next |
同 A,文档多一句「要试 main 上的下一版技能,用 GitHub 路径」 | 同 A,外加内测者可取最新 | A + 0 |
业务含义直译
- A:技能像 SDK 一样「装哪个版本用哪个版本」,与
@objectstack/spec发运.zod.ts源码的做法同构——指针今天已按版本对齐,只差正文。 - B:像给每个版本印一本手册,读者得自己找对那一本,而且旧手册要有人改。
- C:只在封面贴一张「本手册可能不适用于你的版本」。
- D:A 的做法,再加一个「预览版」入口。
四轴(从业务立场)
- 实际业务需求:今天就撞上,实测:main 自 PR docs(skills): objectstack-automation teaches the {{ }} delimiter in flow text slots #22475 起教
{{ }},npm 最新 spec 是 17.7.0,npm create objectstack装 17.7.0 却从 main 取技能;v18 主干期间每一个碰skills/**的target:v18落地都在扩大缺口,18.0 发布后方向反过来落在每个 17.x 项目上。不是投机面。 - 项目长远合理性:A 让技能文本成为契约版本的一部分(contract-first:契约与教它的文本同版同装),与 spec 已发运源码的既有设计一致;B 引入本仓没有的分支维护;C 是绕行。
- 防 AI 犯错:A 让「技能教的写法 ≠ 已装运行时接受的写法」在结构上不可能(同一版本号、同一次安装);出错形态是构建期发布包缺文件,CI 可见。C 只能在安装时响亮告知,仍无匹配文本可装;B 的错误形态是人选错 ref,静默。
- 创业阶段不扩散:A 多一个发布包,但删掉两条手工维护面(
compatibility:行、每技能metadata.version)与一整类漂移,零件净减;B 新增常设流程,拒;C 恰是一条新门禁,默认否。
os-decision-facets
① 项目长远合理性:A 缩小特例——技能文本与它教的契约同版发运,与 spec 发运源码的既有形态同构;B/C 保留「main 是唯一技能版本」的特例并新增维护面。
② 实际业务拉动:今天已撞上(main 教 v18 的 {{ }},npm 最新 spec 17.7.0,scaffolder 从 main 取技能);零拉动不成立。
③ 防 AI 犯错:A 结构性不可能错配;C 响亮告知但无匹配物可装;B 靠人选 ref、错了静默。
④ 创业阶段不扩散:A 加一包、删两行手工面与一类漂移,净减;B 加常设分支流程;C 加一条门禁。
Prior rulings read: skills,compatibility,catalog,version → 39 hits; ADR-0003 Decision §3/§4 (runtime metadata-package versioning, not the authoring catalog), ADR-0023 §4, ADR-0024 §4, ADR-0030 §9 (unrelated by subject); thread: none (new card).
推荐 A(以 D 的一句文档为附带)。自检:只看①选 A;②③④ 是否翻转:否。
置信缺口:npx skills experimental_sync 对本包布局的实际行为未实测(若不可用,scaffolder 自行从 node_modules/@objectstack/skills/skills/* 复制,一个小函数,方案不依赖它);17.7.0 运行时对 {{ }} 文本槽的接受/拒绝未在本卡实测(缺口的方向不因此改变)。
推荐 + 回退
推荐 A,一次付清(创业阶段不渐进:不保留双渠道宽限,GitHub 路径只作文档里写明的 next)。回退 C(若维护者暂不想新增发布包)。置信缺口见四棱块末行。
裁后执行段
A ⇒ skills 席立 4 张执行卡:① packages/skills(@objectstack/skills,进 fixed 组,构建时把根目录 skills/** 复制进包,files 只含它;skills/** 本身不动);② check-skill-compatibility-version.mjs 改为由包版本派生并删去手工行(门禁内部参数修复,非新增;10 个 frontmatter 的 Tier H 触碰);③ cli 车道:create-objectstack 的 skills-install.ts 改从已装包同步,模板 devDependencies 加 @objectstack/skills,e2e 随之;④ devx 车道:五页文档改命令并写明 next 渠道。②③④ Blocked-by: ①;① 落地前 npx skills add 命令不变。B ⇒ 先实测 URL-ref 形,再立文档卡与分支流程卡。C ⇒ cli 一张卡。
维护者速读
- 改了什么:把对外发布的 AI 技能目录从「永远读仓库 main」改成「随你装的 ObjectStack 版本一起装」。
- 为什么改:今天装 17.7.0 的项目拿到的技能已经在教 v18 才接受的写法;18.0 发布后反过来落在所有 17.x 项目上。
- 风险与代价(含回滚):多一个发布包与一次 scaffolder 改动(4 PR、3 车道);回滚 = 文档命令改回 GitHub 路径,包留着无害。
- 席位意见:A。
- 你要做的:回一个字母(A/B/C/D),附加条件随执行落地。
Related
#5245 (closed: the compatibility line drifted a whole major), #5331 (closed: the reconciling gate), PR #22475 (the live v18 teaching on main), #22085 (the v18 version-pr lane), #22585 (pm:blocked: the automation skill's $User spelling moves with v18 pass 2/3 — one more line the catalog teaches per version). Dedupe: REST listing labels=domain:skills&state=all&since=2026-08-01 (12 pages, 1,150 cards) grepped for version|compat|bind|npx skills|skills add|catalog|release → 0 cards on the catalog's version binding; the gate header names #5245 / #5331 as the only prior work on the compatibility: line.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 10, 2026
Ruling: skills-seat presentation R1 item 1 · letter A · maintainer 「22649 同意 A」 2026-10-10T09:27Z
Skills seat 1 (seat post #7623),
session_01RdnZdPZH9ByduzPRWuH9tN. Provenance, three items: the maintainer; verbatim 「22649 同意 A」; said in this seat's session chat, read at the stamp above, after the card was presented there in the director format (the R1 report: the six items in prose, the four facets, the recommendation A with D's one documentation sentence as its rider). Freshness gate: the body (9,227 bytes, unedited since filing) and the comment list (none) were re-read before this record.Blocked-by:none. Thread-read: none.The ruling
@objectstack/spec. A new published package@objectstack/skillsjoins the changesetfixedgroup, so its version is always the spec's; its build copies the repository'sskills/**in andfileslists only that;npm create objectstackand existing projects install the catalog from the installed package (the skills CLI's sync fromnode_modules, or the scaffolder's own copy if that sync does not fit the layout); the GitHub path stays only as the documentednextchannel; thecompatibility:line and each skill'smetadata.versionderive from the package version instead of being kept by hand.Workload of the chosen option, as the rule requires
Three lanes, four PRs by the card's precedent-based estimate: skills lane — the package skeleton (S) and the compatibility-line derivation touching the ten
SKILL.mdfrontmatters (Tier H, S; precedent PR #22475, one file +17/−18); cli lane — the scaffolder installing from the package (M; precedentpackages/create-objectstack/src/skills-install.tsand its e2e); devx lane — five docs pages (S; precedent PR #22556, +860/−1696). Not measured stage by stage. The two skills-lane PRs are filed as ONE card below (the per-fire filing quota is three cards; the derivation rides the same card as a second commit or PR).State and execution
completedin this act;needs-user-decisionleaves with the close;priority:p2anddomain:skillsstay. The body gains itsRuled:line in the same act.Ruling-ref:pointing here: ①@objectstack/skillspackage + the derived compatibility line (skills lane,pm:queue); ③create-objectstackinstalls the catalog from the installed package (cli lane,pm:blocked,Blocked-by:①); ④ the five docs pages and thenextchannel sentence (devx lane,pm:blocked,Blocked-by:①). Until ① lands the install command is unchanged. The cross-lane cards are filed on this ruling, under the maintainer's direct-dispatch channel; triage may re-grade them on first touch.Generated by Claude Code