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

Closed

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. added
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    domain:skillsDomain lane — seat card indexed by label:pm:seat
    on Oct 10, 2026
  2. 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

  3. removed
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    on Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:skillsDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions