Skip to content

Commit 165587e

Browse files
feat(skills): publish the skills catalog as @objectstack/skills in the fixed group (#22691)
Part of #22658 Clause-②: no Ruling A on #22649 (record 6096124407, maintainer 「22649 同意 A」): the published skills catalog ships as a versioned package in the changeset `fixed` group. This is PR 1 of the two the card allows — the package. PR 2 (`claude/issue-22658-compat-line-derived`, Tier H) derives the frontmatter lines; the cli and devx halves (#22659, #22668) remain open and consume what this PR publishes. ## What this adds - `packages/skills/` — a new publishable package `@objectstack/skills` (version 17.7.0, the fixed group's; `publishConfig.access: public`; `files: dist, README.md, CHANGELOG.md`; `exports` names only `./package.json`, the `@objectstack/console` shape for a package with no JS entry). No second copy of a skill is committed and nothing is symlinked: `dist/` is gitignored and produced by the build. - `packages/skills/scripts/sync-catalog.mjs` — the build: wipe `dist/`, copy the repository root's `skills/**` into `dist/skills/**`, read the copy back and refuse to finish unless the two trees are equal file for file and byte for byte; `--check` runs that same comparison and is the package's `prepack`, so `pnpm pack` / `pnpm publish` refuse a stale or absent tree; `--self-test` (nine batteries over temp fixtures: byte equality, idempotence, a deleted source file not surviving a rebuild, byte change / extra file / missing file / absent tree each red, an empty catalog refused, a symlink refused rather than followed) runs as the first leg of the package's `build`, the `--self-test && run` idiom every `check:*` alias uses, so it is never dormant and needs no new gate. - `.changeset/config.json` — `@objectstack/skills` joins the `fixed` group (70 members); `.changeset/22658-skills-package.md` — `minor` for the new package, plus a `patch` line for `@objectstack/spec` because `packages/spec/llms.txt` (a published file) counts the scoped packages and `check:llms-txt` moved it 68 → 69. - `pnpm-lock.yaml` — the new importer (`packages/skills: {}`), as `pnpm install` writes it; `pnpm-workspace.yaml` is untouched (`packages/*` already covers it). ## Why `dist/skills/`, measured `skills@1.7.2`'s `experimental_sync` discovers a dependency's skills at exactly two places, read from its `discoverPackageSkills`: `PKG/skills/NAME/SKILL.md` and `PKG/dist/skills/NAME/SKILL.md`. Of the two, `dist/` is the one this repository already treats as a build output everywhere: canonical in `files` for `check:published-files` (no EXTRA_ENTRIES row), gitignored repo-wide, turbo's default `outputs`, and skipped by the directory walk of `check:published-readme-exports` / `check:published-readme-links` — a copy at `PKG/skills/` would have put all 53 catalog markdown files into those two gates' published-markdown population whenever a build had run, so their verdict would have depended on local build state. The sibling cards wrote `node_modules/@objectstack/skills/skills/*` before this measurement; the path they consume is `node_modules/@objectstack/skills/dist/skills/NAME/`. ## Tarball and consumer measurement (the card's Done-when) `pnpm pack` from `packages/skills` on the built tree: `prepack` ran `--check` (65 files byte-identical), tarball `objectstack-skills-17.7.0.tgz`, 68 entries — 65 under `package/dist/skills/` (10 `SKILL.md`, 21 references, 18 rules, 15 evals, the catalog README) plus `package.json`, `README.md`, `LICENSE`. Installed in a throwaway project outside the repository (`npm install --save-dev FILE.tgz`), then `npx -y skills@latest experimental_sync --yes --agent claude-code`: - `Found 10 skills in node_modules`, each listed as `NAME from @objectstack/skills`; - wrote `.agents/skills/NAME` as a symlink to `../../node_modules/@objectstack/skills/dist/skills/NAME` and `.claude/skills/NAME` as a symlink to `../../.agents/skills/NAME`; 64 files reachable through `.claude/skills` (65 minus the catalog README, which is not a skill); `diff -r` of `.agents/skills/objectstack-data` against the package copy: identical; - `skills-lock.json` records each skill with `source: @objectstack/skills`, `sourceType: node_modules`, `skillPath: dist/skills/NAME/SKILL.md`, `version: 17.7.0`. So the sync fits the layout; `--copy` copies instead of linking. The cli card can use the sync as is. ## Every gate that must learn a no-JS package, through its declared path - `check:type-check-coverage` — an EXEMPT ledger row beside `@objectstack/console` (no TypeScript sources, no tsconfig). - `check:dts-closure`, `check:dual-build-cjs-loads`, `check:sourcemap-no-sources-content`, `check:lean-entry-closure` — nothing declared: the populations are derived (a built package whose manifest declares no declaration path owes none; no `require` entry, no `.map`, no lean entry). Measured on the fully built tree: `check-dts-closure: 1 built package(s) declare no declaration entry point and owe none` on the package alone, and all four green over the 73-task build. - `check:published-files` — `dist` + README + CHANGELOG are canonical; `exports` present (70 publishable packages, census floor 50). - `check-published-list-mirrors` does not fit (it mirrors a constant into AGENTS.md), so byte equality is proven by the copy step's self-test, as the card allows. - `turbo.json` — `@objectstack/skills#build` declares `$TURBO_ROOT$/skills/**` as an input (otherwise an edit under `skills/**` is a cache hit replaying a stale copy, remote cache included). Probe on this tree: one byte appended to `skills/objectstack-data/SKILL.md` → `cache miss, executing aca937c23b400d14`; restored to HEAD (blob equal, `git diff HEAD` empty) → `cache hit, replaying logs 47fea834c3a0ce5a`. - `.github/workflows/ci.yml` — the `core:` filter gains `skills/**`, because `check-ci-filter-parity` requires every `$TURBO_ROOT$` build input to be covered there (`OK: all 21 build input(s) … covered by core`). Its self-test pins the live `crosspkg` rollback count over the LIVE table on purpose; with `core` now covering the skills root the rollback uncovers 19 instead of 22, and the pin moved with the tree (the two by-name assertions now assert coverage through `core`), recorded in its comment. - `check:lockstep-package-count --fix` — the three prose restatements of the group's size (two in `content/docs/protocol/backward-compatibility.mdx`, one in `scripts/publish-smoke-pack.mjs`'s header) 69 → 70; `check:llms-txt` — `packages/spec/llms.txt` 68 → 69 (the gate's own remedy: the number and the prose). `pnpm changeset status`: `@objectstack/skills` is listed among the 70 fixed-group packages to be bumped, at the group's pending level (`major`, from the v18 stock already on `main`). ## Gates run (exit codes captured before any pipe) Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` on the changed set and reconciled with `--ran`: 140 derived, 140 run, 0 UNRUN. All exit 0 except two prerequisite refusals (exit 3, NOT MEASURED, neither reads this diff's surface): `check-plugin-teardown-shape --self-test` (needs an unshallow clone) and, before the build, `check:docs-transcript-drift` (needs `@objectstack/lint` built — green after the build). Highlights: `check:published-files`, `check:type-check-coverage`, `check:type-check-debt`, `check:ci-filter-parity` (+ self-test, 131 assertions), `check:changeset-fixed` (70 public packages in sync), `check:lockstep-package-count`, `check:llms-txt`, `check:published-readme-links` (102 published markdown files), `check:published-readme-exports`, `check:dts-closure`, `check:dual-build-cjs-loads`, `check:sourcemap-no-sources-content`, `check:lean-entry-closure`, `check:skill-compatibility`, `check:skill-identifier-liveness`, `check:doc-authoring`, `check:nul-bytes`, `check:pm-governed-prose`, `check:merge-driver`, the three changeset gates against `origin/main`, spec `check:docs` / `check:skill-examples` (262 prose examples type-check), `check:pm-dispatch-gates` (fast tier: 1825 cases pass; 6 slow sections deferred to CI). Full workspace build under the verify lock: 73 tasks successful, `VERDICT command-exit 0`, held 350s. Lint, narrowed and measured at `3372d78b1`: eslint over the four JavaScript files this PR touches (`packages/skills/scripts/sync-catalog.mjs`, `scripts/check-ci-filter-parity.mjs`, `scripts/check-type-check-coverage.mjs`, `scripts/publish-smoke-pack.mjs`) — `--format json`: 4 files, 0 errors, 0 warnings. Population: `eslint.config.mjs` judges `.`; invariance: the config enables no type-aware linting (its own note: no `parserOptions.project`, no typed rules), so this diff cannot move the verdict of any untouched file; the repo-wide run is CI's. ## Acceptance notes - The README's sentence that `npm create objectstack` and the docs read the catalog from this package describes the ruling's end state; #22659 and #22668 are the halves that make it true and are not addressed here. - `metadata.version` and the `compatibility:` majors are untouched here; PR 2 derives them. - `scripts/publish-smoke-pack.mjs`'s header digit moved, which schedules the advisory `OS Create Smoke` workflow on this PR. - A new published package skeleton has no recent precedent in this repository (the card says so); `@objectstack/console` is the nearest shape and was copied for the manifest. ## 维护者速读(草稿) - 改了什么:新增发布包 `@objectstack/skills`,构建时把仓库根目录的 `skills/**` 原样复制进 `dist/skills/`,进 changeset `fixed` 组,版本号恒等于 `@objectstack/spec`。`skills/**` 本身不动、不搬、不做符号链接。 - 为什么改:今天装 17.7.0 的项目从仓库 `main` 取技能,拿到的是在教 v18 写法的文本;发成包以后,装哪个版本就拿哪个版本的技能(已用打包 + `npx skills experimental_sync` 实测:10 个技能全部从 `node_modules` 装入)。 - 风险与代价(含回滚):多一个发布包;`fixed` 组从 69 变 70,三处文案计数与 `llms.txt` 的计数随之改动。回滚 = 从 `fixed` 组移除并删掉目录,其余文件不受影响。 - 席位意见:(留空) - 你要做的:这张 PR 不是受管面,走队列即可;你要批的是第二张(十个 SKILL.md 的两行派生)。 --- _Generated by [Claude Code](https://claude.ai/code/session_01RdnZdPZH9ByduzPRWuH9tN)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent e84aeb3 commit 165587e

14 files changed

Lines changed: 512 additions & 16 deletions

File tree

‎.changeset/22658-skills-package.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@objectstack/skills": minor
3+
"@objectstack/spec": patch
4+
---
5+
6+
New published package `@objectstack/skills`: the ObjectStack skills catalog (`skills/**` of the repository), shipped in the changeset `fixed` group so it always carries the version of the `@objectstack/*` packages it teaches. Its build copies the catalog into `dist/skills/<skill>/…` byte for byte (the layout the skills CLI's `experimental_sync` reads from `node_modules`), and `files` lists only that tree. The repository's `skills/**` stays the one source of truth and the documented `next` channel; nothing a consumer writes changes.
7+
8+
`@objectstack/spec`: `llms.txt`'s package-ecosystem count reads 69 with `@objectstack/skills` joining the scope.

‎.changeset/config.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"fixed": [
1111
[
1212
"@objectstack/spec",
13+
"@objectstack/skills",
1314
"@objectstack/cli",
1415
"@objectstack/console",
1516
"@objectstack/cloud-connection",

‎.github/workflows/ci.yml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@ jobs:
205205
# touching a `scripts/pm/` tool or a `scripts/check-*` gate.
206206
- 'turbo.json'
207207
- 'tsup.config.ts'
208+
# `@objectstack/skills#build` copies the repository root's
209+
# `skills/**` into its publish tree, so that catalog is a build
210+
# input of a task `pnpm build` runs (turbo.json declares it as
211+
# `$TURBO_ROOT$/skills/**`; check-ci-filter-parity holds it here).
212+
- 'skills/**'
208213
- 'scripts/build-input-hash.mjs'
209214
- 'scripts/check-dev-prereqs.mjs'
210215
- 'scripts/check-dts-emitted.mjs'

‎content/docs/protocol/backward-compatibility.mdx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ Read the **Breaking?** column, not the version number: during the launch window
112112
1. **RFC (Request for Comments)** — Breaking changes are proposed as GitHub issues with the `protocol:breaking` label.
113113
2. **Deprecation** — The old behavior is deprecated in a MINOR release (see timeline above).
114114
3. **Migration Guide** — A detailed migration guide is published before the removal lands, in the release notes for the version that carries it.
115-
4. **Release** — During the launch window the breaking change ships in the next **MINOR** version, carrying a changeset entry marked `**BREAKING**`. `scripts/check-changeset-no-major.mjs` fails any pull request that declares a `major` bump, because under lockstep one `major` would promote all 69 published packages.
115+
4. **Release** — During the launch window the breaking change ships in the next **MINOR** version, carrying a changeset entry marked `**BREAKING**`. `scripts/check-changeset-no-major.mjs` fails any pull request that declares a `major` bump, because under lockstep one `major` would promote all 70 published packages.
116116

117117
---
118118

@@ -190,7 +190,7 @@ The `@objectstack/spec` package provides additional stability guarantees:
190190

191191
### Which surfaces this covers
192192

193-
**All of them.** This is not scoped to an experimental corner or a pre-release channel: all **69** packages published from this repository belong to a single Changesets `fixed` group, so they share one version number and one policy. No published surface is exempt.
193+
**All of them.** This is not scoped to an experimental corner or a pre-release channel: all **70** packages published from this repository belong to a single Changesets `fixed` group, so they share one version number and one policy. No published surface is exempt.
194194

195195
The convention is enforced rather than informal — `scripts/check-changeset-no-major.mjs` fails any pull request that introduces a `major` bump, because under lockstep a single `major` on one package would promote the entire stack.
196196

‎packages/skills/.gitignore‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# The publish tree: `skills/**` of the repository root, copied in by
2+
# `scripts/sync-catalog.mjs` (the package's `build`). Never committed — the
3+
# repository root's `skills/**` is the one source of truth.
4+
dist/

‎packages/skills/README.md‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# @objectstack/skills
2+
3+
**The ObjectStack skills catalog, shipped at the version of the packages it teaches.**
4+
5+
This package contains nothing but `dist/skills/`: a byte-for-byte copy of the
6+
[`skills/`](https://github.com/objectstack-ai/objectstack/tree/main/skills) tree
7+
of the `objectstack-ai/objectstack` repository — one directory per skill, each
8+
with its `SKILL.md`, `references/`, `rules/` and `evals/` — taken at the commit
9+
that released this version.
10+
11+
It is published from the Changesets `fixed` group, so its version is always the
12+
version of `@objectstack/spec`, `@objectstack/cli` and every other
13+
`@objectstack/*` package released with it. A project that depends on
14+
`@objectstack/skills@17.7.0` reads the skills written for `@objectstack/spec`
15+
17.7.0 — never the ones already teaching the next major, and never a catalog
16+
that has moved on since the project was created.
17+
18+
## Installing the skills into an agent's directory
19+
20+
The catalog is read from `node_modules`, so it follows the version the project
21+
depends on. With this package in `devDependencies`, the
22+
[skills CLI](https://www.npmjs.com/package/skills) syncs it into the detected
23+
agent's own skills directory (`.claude/skills/` for Claude Code, and so on):
24+
25+
```sh
26+
npm install --save-dev @objectstack/skills
27+
npx skills experimental_sync
28+
```
29+
30+
`experimental_sync` discovers the skills at `dist/skills/<skill>/SKILL.md` of
31+
every dependency and links or copies them for the agent runtimes it detects
32+
(`--agent <name>` names one; `--copy` copies instead of linking). Re-running it
33+
after `pnpm up @objectstack/skills` — which moves with the rest of the
34+
`@objectstack/*` set — refreshes the installed catalog.
35+
36+
## The `next` channel
37+
38+
The repository's `skills/` tree on `main` is the catalog of the **next**
39+
release. `npx skills add objectstack-ai/objectstack/skills --skill '*' --agent claude-code -y`
40+
reads it directly from GitHub — for trying the skills of the version that is
41+
not published yet, not for a released project.
42+
43+
## How the tree is produced
44+
45+
`scripts/sync-catalog.mjs`, this package's `build`, wipes `dist/` and copies the
46+
repository's `skills/**` into `dist/skills/**`, reads the copy back and
47+
refuses to finish unless the two trees are equal, file for file and byte for
48+
byte. Its `prepublishOnly` runs the same comparison, so a stale or absent copy is
49+
never published. The copy is gitignored; the repository's `skills/**` is the one source
50+
of truth, reviewed and gated there.
51+
52+
## Related
53+
54+
- [Skills reference](https://objectstack.ai/docs/ai/skills-reference) — every skill in the catalog, with what it covers.
55+
- [`@objectstack/spec`](https://www.npmjs.com/package/@objectstack/spec) — the schemas the skills point at (`node_modules/@objectstack/spec/src/**/*.zod.ts`), shipped at the same version.

‎packages/skills/package.json‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "@objectstack/skills",
3+
"version": "17.7.0",
4+
"description": "The published ObjectStack skills catalog \u2014 the repository's skills/** tree, shipped at the version of the @objectstack/* packages it teaches.",
5+
"license": "Apache-2.0",
6+
"homepage": "https://github.com/objectstack-ai/objectstack/tree/main/packages/skills",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/objectstack-ai/objectstack.git",
10+
"directory": "packages/skills"
11+
},
12+
"bugs": {
13+
"url": "https://github.com/objectstack-ai/objectstack/issues"
14+
},
15+
"publishConfig": {
16+
"access": "public"
17+
},
18+
"files": [
19+
"dist",
20+
"README.md",
21+
"CHANGELOG.md"
22+
],
23+
"exports": {
24+
"./package.json": "./package.json"
25+
},
26+
"scripts": {
27+
"build": "node scripts/sync-catalog.mjs --self-test && node scripts/sync-catalog.mjs",
28+
"prepublishOnly": "node scripts/sync-catalog.mjs --check"
29+
},
30+
"keywords": [
31+
"objectstack",
32+
"skills",
33+
"agent-skills",
34+
"claude-code",
35+
"ai"
36+
]
37+
}

0 commit comments

Comments
 (0)