Repository navigation
Commit 658d84f
docs(skills): mark the always-on tokens in the platform skill's requires: table (#31181)
<!-- claude-projects-attribution: {"github_login":"huangyiirene"} -->
_Requested by **Irene** · [project
thread](https://claude.ai/code/project/chan_01TJXtQ1tVD26ecLDZxFS67x?thread=cmsg_01TJXtQ1tVD26ecLDZxFS67xVLaZCHfVovNCieVsJ1xWP3)_
Fixes #31130
Clause-②: no
Metadata-protocol: none
`dispatch-gates --tier` reads a MANDATORY model tier for `skills/**`
(clause ① of the model-tiering ruling); it is waived by the standing
order of the maintainer in this project (2026-11-03), and this card ran
on the project's default model. The dispatching seat runs the contract
review.
## 维护者速读
- 改了什么:`objectstack-platform` 的 `### requires:` 表用 ° 标出全部常驻
token(`PLATFORM_ALWAYS_ON_CAPABILITIES`),导语改为「标 °
的每次启动都挂载,列不列都一样;`--preset minimal` 恰好去掉这些」;`auth`→`email` 规则注明 minimal
下也成立,`triggers`+`job` 配对限定到 `--preset
minimal`;`queues`/`assignmentRules` 一段删去「(`sharing` in `requires`)」;eval
第 3、9 例不再要求在 `requires` 里写 `job`/`messaging`/`sharing`,新增第 20
例(常驻服务要不要列进 `requires:`)。
- 为什么改:导语原文「其余服务插件都是 opt-in」与代码相反:`resolveServedCapabilities` 在非 minimal
预设下把常驻清单追加到每个应用的 `requires`(#31130)。作者会误以为未列出的服务不存在。
- 风险与回滚:只改技能文字与 eval;SKILL.md 6007 → 6004 / 6011(净减 3 token),无上限上调;发
`@objectstack/skills` patch;回滚即 revert。
- 先看:`skills/objectstack-platform/SKILL.md` § `### requires:` 的导语和表,以及
L55 的 `sharing` 一句(下方 diff)。
- 两分钟验证:`node scripts/check-skills-token-ratchet.mjs`,预期退出
0,`objectstack-platform/SKILL.md 6004 / 6011`。
- 需要你做的:`skills/**` 属 Tier H(人合),需要 `os-zhuang` 或 `hotlong` 的一次
approval,之后席位落地。
## Code sites read (on `main` `8ef4d309`, re-checked after merging
`21c1f748`)
- `packages/spec/src/kernel/platform-capabilities.ts`
`PLATFORM_ALWAYS_ON_CAPABILITIES`: `queue`, `job`, `cache`, `settings`,
`email`, `storage`, `sms`, `sharing`, `messaging`, `analytics`,
`package-registry`. These, and only these, carry ° in the table.
- `packages/core/src/capability-composition.ts`
`resolveServedCapabilities`, in order: the declared tokens
(deduplicated); `email` when `auth` is declared; `hostDefaults`; the
slate unless `preset === 'minimal'`; then `job` and `queue` moved to the
front when `email` / `approvals` / `auth` is present. So `--preset
minimal` drops the slate and nothing else.
- `packages/cli/src/commands/serve.ts` L3006–3009: `hostDefaults` =
`mcp` unless `OS_MCP_SERVER_ENABLED` is `0`/`false`/`off`/`no`
(`packages/types/src/env.ts` `isMcpServerEnabled`), plus `pinyin-search`
when `stampSearchPinyinEnabled(config.i18n)` (the env var, else any
`zh-*` locale). They are appended under every preset, `minimal`
included. Not taught here (see Other sites).
- `packages/core/src/capability-providers.ts`: every slate token has a
provider row (`package-registry` → `@objectstack/service-package`,
L174), and `packages/cli/package.json` depends on all eleven provider
packages, so a stock `os serve` mounts each one.
Every existing table row was checked against
`PLATFORM_CAPABILITY_TOKENS` and core's `CAPABILITY_PROVIDERS`: every
service token has a row and every row names its registry package. No
phantom row, no missing row.
## What changes
```diff
@@ -52,8 +52,8 @@ objectstack-data): named sets of people a new record of an `ownership: 'user'`
object sits in until a member claims it. `assignmentRules` (`defineAssignmentRule`,
`@objectstack/spec/automation`; objectstack-automation) routes each inserted
ownerless row into a queue — parked, `round_robin` or `least_loaded` — or to one
-user. Both need the ownership-queue service `@objectstack/plugin-sharing` registers
-(`sharing` in `requires`): a stack declaring either without it is refused at boot.
+user. Both need the ownership-queue service `@objectstack/plugin-sharing` registers:
+a stack declaring either without it is refused at boot.
Undeclared keys are handled per surface, in two postures:
@@ -294,18 +294,19 @@ production fails loudly): [Ports & networking](./references/operations.md#ports-
### `requires:` — which service plugins boot
-Step 4's list is the fixed core. Every other service plugin is opt-in, and
-`requires: [...]` on the stack root is what turns it on. The CLI expands each
+Step 4's list is the fixed core. Tokens marked ° are always-on: every boot
+mounts them, listed or not, and `--preset minimal` drops exactly those. Every
+other service plugin is opt-in: `requires: [...]` on the stack root turns it on. The CLI expands each
token through the `CAPABILITY_PROVIDERS` registry in
`@objectstack/core`:
| Token | Provider package |
|:--|:--|
| `automation` | `@objectstack/service-automation` — flows, and any declarative `connectors:` entry |
-| `analytics` `cache` `storage` `queue` `job` `messaging` `realtime` `settings` `sms` `push` | `@objectstack/service-` + the token ([the `push` block](./references/operations.md#mobile-push)) |
+| `analytics`° `cache`° `storage`° `queue`° `job`° `messaging`° `realtime` `settings`° `sms`° `push` | `@objectstack/service-` + the token ([the `push` block](./references/operations.md#mobile-push)) |
| `mailbox` | `@objectstack/service-mailbox` — inbound mail |
-| `marketplace` `package-registry` | `@objectstack/service-package` |
-| `audit` `email` `sharing` `approvals` `webhooks` | `@objectstack/plugin-` + the token |
+| `marketplace` `package-registry`° | `@objectstack/service-package` |
+| `audit` `email`° `sharing`° `approvals` `webhooks` | `@objectstack/plugin-` + the token |
| `pinyin-search` | `@objectstack/plugin-pinyin-search` |
| `mcp` | `@objectstack/mcp` |
| `triggers` | `@objectstack/trigger-record-change`, plus `trigger-schedule` and `trigger-api` |
@@ -315,8 +316,7 @@ through it:
- **Tier-gated** — `ai`, `ai-studio`, `i18n`, `ui`, `auth` have no provider
entry; dedicated blocks in `serve.ts` `run()` open their tier instead
- (`ai`/`ai-studio` through the intent-driven AI block, the other three through
- their tier blocks).
+ (`ai`/`ai-studio` through the intent-driven AI block).
- **Enterprise / cloud** — `hierarchy-security` has no open-edition provider and
ships in `@objectstack/security-enterprise`, loaded through `plugins[]`;
`ai-seat` and `governance` are resolved only by cloud's objectos-runtime.
@@ -332,14 +332,14 @@ Five rules that change what you write:
- **Declaring is a demand.** A capability YOU declared whose provider package is
absent is a hard boot error; one the platform auto-injects for you stays
best-effort (warn and continue).
-- **`auth` implies `email`.** Auth callbacks need the mail service, so the CLI
- appends `email` whenever `auth` is required.
+- **`auth` implies `email`**, even under `--preset minimal`: auth callbacks
+ need the mail service.
- **Keep `automation` whenever `plugins:` lists a connector** — connector
- executors register their provider factories with it, and without it they have
- nowhere to register and boot fails.
-- **Pair `triggers` with `job`.** `triggers` alone arms record-change triggers;
- schedule and time-relative triggers run on the job service, so autolaunched
- scheduled flows stay silent without `job`.
+ executors register their provider factories with it, and without it boot
+ fails.
+- **Under `--preset minimal`, pair `triggers` with `job`:** `triggers` alone
+ arms record-change triggers; schedule and time-relative ones run on the job
+ service, so scheduled flows stay silent.
### `onEnable` — where an app binds runtime code
```
## Token readings and the deletions that pay them
`node scripts/check-skills-token-ratchet.mjs` (`ceil((bytes − 20) /
4)`): `skills/objectstack-platform/SKILL.md` **6007 / 6011 on `main`**
(24045 bytes) → **6004 / 6011 at this head** (24035 bytes): a net change
of −3 tokens. No ceiling raised;
`scripts/check-skills-token-ratchet.mjs` is untouched; standing ruling
6513306068 is not used.
The growth (lead sentence + eleven ° markers) is paid by the deletions
below, all in the same file. Facts each cut text held, and where each
survives:
| Cut | Facts it held | Surviving home |
|:--|:--|:--|
| Tier-gated bullet: ", the other three through their tier blocks" |
`i18n` / `ui` / `auth` open a tier | Same bullet: "dedicated blocks in
`serve.ts` `run()` open their tier instead", which names all five tokens
|
| `auth` bullet: "so the CLI appends `email` whenever `auth` is
required" | the CLI appends `email` when `auth` is declared | The
bullet's own head "`auth` implies `email`", which now also says it holds
under `--preset minimal` |
| `automation` bullet: "they have nowhere to register and" | connector
executors register with the automation service | Same sentence:
"connector executors register their provider factories with it" |
| `triggers` bullet: "autolaunched", "without `job`" | scheduled flows
are autolaunched; they need `job` | The bullet's head now names the
pairing ("pair `triggers` with `job`"); "scheduled flows" stays |
| Lead: "and … is what" | none (wording) | n/a |
| § Full Configuration Reference L55–56: " (`sharing` in `requires`)"
(contract review M1) | the ownership-queue service comes from the
`sharing` token | The `### requires:` table (`sharing`° →
`@objectstack/plugin-sharing`, always-on) and its lead (`--preset
minimal` drops it). The remaining sentence ("Both need the
ownership-queue service `@objectstack/plugin-sharing` registers: a stack
declaring either without it is refused at boot") is true under every
preset. |
No deleted text is pinned: `grep` of `scripts/**` and `packages/**` for
each cut phrase finds only files that never read this skill ("nowhere to
register" is matched in `create-objectstack`'s starter-comment test,
which reads the scaffold's own comments, and the test's regex also
accepts "boot fails", which stays).
## Eval cases
(`skills/objectstack-platform/evals/config-plugins-ops.json`)
- **Case 3 corrected** (seat ruling Q1). It expected `requires:
['automation', 'triggers', 'job', 'messaging']` and said notify is
skipped without `messaging`. Both are always-on on a default boot. It
now expects `requires: ['automation', 'triggers']`, says `job` and
`messaging` are always-on, and gives the `--preset minimal` caveat.
`must_contain` drops `job` / `messaging` for `--preset minimal`. No new
`must_not_contain` entry: a careful answer writes the minimal-preset
line as `requires: ['automation', 'triggers', 'job', 'messaging']`
(contract review S1).
- **Case 9 corrected** (contract review M1; claim widened in
6709825690). It expected "plus `'sharing'` in `requires` … else the boot
is refused". The refusal (`describeMissingOwnershipQueueService`,
`packages/objectql/src/assignment-rules.ts`) tests only that the
`ownership-queue` service is registered, and `sharing` is always-on. It
now says no `requires` change is needed on a default boot and gives the
`--preset minimal` caveat; `must_contain` takes `sharing` instead of
`'sharing'` and adds `--preset minimal`, as cases 3 and 20 have, so the
old unconditional answer no longer passes (delta review should-fix);
`'sharing'` is not banned, since the minimal-preset line spells it.
- **Case 20 added**: "Do I have to list `storage` and `settings` in
`requires:`?" Expected: no, both are always-on, listing is harmless,
only `--preset minimal` drops them. `must_contain` is `--preset minimal`
only; neither case 3 nor case 20 requires the hyphenated "always-on"
(contract review N2). Eval fixtures are measured, not ratcheted.
## Interplay
#31115 item 2 (open, unclaimed) would register this table as a
liveness-exhaustive section against `PLATFORM_CAPABILITY_TOKENS` ∩
`CAPABILITY_PROVIDERS`. The ° marker sits outside the backticks, so the
token spans it would parse are unchanged; whichever of the two lands
second re-reads the first.
## Other sites found (reported, not fixed)
Filed as #31184 by the seat: it covers items 1–3 below (the automation
rows, the host defaults and the jsdoc).
1. `skills/objectstack-automation/SKILL.md` § Prerequisite table: the
`job`, `queue` and `messaging` rows give an "Absent ⇒" outcome, but all
three are always-on, so those outcomes happen only under `--preset
minimal`. Even there, `email`, `approvals` or `auth` pulls `job` and
`queue` back in (`NEEDS_JOB_AND_QUEUE`,
`packages/core/src/capability-composition.ts`). Same teaching in
`references/examples-flows.md` L132 and
`references/integration-recipes.md` L62 (`'job'` added to `requires`).
2. The lead's "Every other service plugin is opt-in" is still false for
`mcp` and `pinyin-search`: `os serve` adds `mcp` (unless
`OS_MCP_SERVER_ENABLED` is off) and `pinyin-search` (for a `zh-*`
locale) as host defaults under every preset, `minimal` included. Left
out: the clause naming both costs more than the 7 tokens the `sharing`
deletion freed.
3. `packages/spec/src/kernel/platform-capabilities.ts`, the jsdoc on
`'package-registry'` in `PLATFORM_ALWAYS_ON_CAPABILITIES` ("1 parent 150f740 commit 658d84f
3 files changed
Lines changed: 46 additions & 22 deletions
File tree
- .changeset
- skills/objectstack-platform
- evals
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
55 | | - | |
56 | | - | |
| 55 | + | |
| 56 | + | |
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| |||
294 | 294 | | |
295 | 295 | | |
296 | 296 | | |
297 | | - | |
298 | | - | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
299 | 300 | | |
300 | 301 | | |
301 | 302 | | |
302 | 303 | | |
303 | 304 | | |
304 | 305 | | |
305 | | - | |
| 306 | + | |
306 | 307 | | |
307 | | - | |
308 | | - | |
| 308 | + | |
| 309 | + | |
309 | 310 | | |
310 | 311 | | |
311 | 312 | | |
| |||
315 | 316 | | |
316 | 317 | | |
317 | 318 | | |
318 | | - | |
319 | | - | |
| 319 | + | |
320 | 320 | | |
321 | 321 | | |
322 | 322 | | |
| |||
332 | 332 | | |
333 | 333 | | |
334 | 334 | | |
335 | | - | |
336 | | - | |
| 335 | + | |
| 336 | + | |
337 | 337 | | |
338 | | - | |
339 | | - | |
340 | | - | |
341 | | - | |
342 | | - | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
343 | 343 | | |
344 | 344 | | |
345 | 345 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
45 | | - | |
| 45 | + | |
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
50 | | - | |
51 | | - | |
52 | | - | |
| 50 | + | |
| 51 | + | |
53 | 52 | | |
54 | 53 | | |
55 | 54 | | |
| |||
148 | 147 | | |
149 | 148 | | |
150 | 149 | | |
151 | | - | |
| 150 | + | |
152 | 151 | | |
153 | 152 | | |
154 | 153 | | |
155 | 154 | | |
156 | 155 | | |
157 | 156 | | |
158 | | - | |
| 157 | + | |
| 158 | + | |
159 | 159 | | |
160 | 160 | | |
161 | 161 | | |
| |||
333 | 333 | | |
334 | 334 | | |
335 | 335 | | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
336 | 350 | | |
337 | 351 | | |
338 | 352 | | |
0 commit comments