Skip to content

[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

@objectstack-fleet

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 by npx skills add objectstack-ai/objectstack/skills --skill '*' --agent claude-code -y (five docs pages and packages/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 objectstack runs that command after installing the latest published packages.
  • The only version binding is self-declared prose: every SKILL.md carries compatibility: Requires @objectstack/spec 17.x (Zod v4 schemas) and a hand-bumped metadata.version ("4.4", "1.3", …). scripts/check-skill-compatibility-version.mjs reconciles the 17.x against the WORKSPACE's spec version, so the line follows main, not the consumer. Each skill's references/_index.md points into the consumer's node_modules/@objectstack/spec/src/** (the published spec ships its .zod.ts sources), so the schema pointers are version-aligned by construction; the SKILL.md prose is not.
  • The gap is live now: skills/objectstack-automation/SKILL.md:108–:109 on main teaches title: 'Done: {{ record.title }}' (the v18 text-slot delimiter, PR docs(skills): objectstack-automation teaches the {{ }} delimiter in flow text slots #22475 under target:v18), while npm view @objectstack/spec version answers 17.7.0. Every target:v18 landing that touches skills/** 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.json fixed group: @objectstack/spec, @objectstack/cli, … all 17.7.0) and a git tag per package per version (refs/tags/@objectstack/spec@17.7.0 exists; 15,909 tags).
  • The skills CLI (skills@latest, help read 2026-10-10) has add PACKAGE (a GitHub owner/repo/path or URL; no ref flag in its help), experimental_sync ("Sync skills from node_modules into agent directories") and experimental_install (restore from skills-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

  1. 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; control git grep -c 'defineFlow' origin/main -- skills/objectstack-automation/SKILL.md ≥ 1) and npm view @objectstack/spec version.
  2. 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; control git grep -c 'skills' origin/main -- skills/README.md ≥ 1).
  3. The only binding is the hand line — grep -n '^compatibility:' skills/*/SKILL.md (10 lines, all 17.x); node scripts/check-skill-compatibility-version.mjs reconciles against the workspace.
  4. The skills CLI can sync from node_modules — npx -y skills@latest add --help | grep -c experimental_sync (1).
  5. 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

  1. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    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

    • A — the published skills catalog ships as a versioned package beside @objectstack/spec. A new published package @objectstack/skills joins the changeset fixed group, so its version is always the spec's; its build copies the repository's skills/** in and files lists only that; npm create objectstack and existing projects install the catalog from the installed package (the skills CLI's sync from node_modules, or the scaffolder's own copy if that sync does not fit the layout); the GitHub path stays only as the documented next channel; the compatibility: line and each skill's metadata.version derive from the package version instead of being kept by hand.
    • ⛔ Not taken: B (a git ref per release, with a standing release-branch maintenance process the repository does not have), C (a mismatch warning at install, which tells the user and gives them nothing matching to install), D as a separate option (its one sentence rides A).

    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.md frontmatters (Tier H, S; precedent PR #22475, one file +17/−18); cli lane — the scaffolder installing from the package (M; precedent packages/create-objectstack/src/skills-install.ts and 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

    • This card closes completed in this act; needs-user-decision leaves with the close; priority:p2 and domain:skills stay. The body gains its Ruled: line in the same act.
    • Execution cards, filed in this act with Ruling-ref: pointing here: ① @objectstack/skills package + the derived compatibility line (skills lane, pm:queue); ③ create-objectstack installs the catalog from the installed package (cli lane, pm:blocked, Blocked-by: ①); ④ the five docs pages and the next channel 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions