Skip to content

Commit 35b178b

Browse files
docs(skills): the data skill's percent row states the storage scale — a fraction unless the field declares max above 1 (#28513)
<!-- claude-projects-attribution: {"github_login":"os-tesla"} --> _Requested by **Tesla** · [project thread](https://claude.ai/code/project/chan_01AXsQkLFKRdQCqQ3RTr6Jao?thread=cmsg_01AXsQkLFKRdQCqQ3RTr6Jao1GXHCbqC69qQauk9Qizcus)_ Fixes #28489 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:objectstack-data 技能字段类型表的 `percent` 行,把「Percentage values (0-100)」改成平台真正的存储规则:不声明 `max` 大于 1 时存 0-1 的小数,声明了(如 `max: 100`)才存整数百分点;种子、默认值、API 写入都按这个存储刻度。 - 为什么改:发布出去的技能说错了一句,AI 作者照着在没有 `max` 的 percent 字段上种 `25`,界面读出来是 `2500%`(#28487 契约复审发现,triage 定 p2)。 - 风险与回滚:纯文档;技能文件 token 上限余量为 1,新增以删除 `Vector (AI Embeddings)` 示例支付(它唯一的事实「`dimensions` 是平级键」Enhanced Types 表行已写明);回滚即 revert。 - 先看:`skills/objectstack-data/rules/field-types.md` 第 54 行(`percent` 行)与被删的 Vector 示例块,`.changeset/28489-percent-storage-scale-skill.md`。 - 两分钟验证:`node scripts/check-skills-token-ratchet.mjs`,预期退出 0,`field-types.md` 读数 3207/3207。 - 需要你做的:受管面(`skills/**`,Tier H)——席位完成契约复审后,由授权账号 Approve,再由席位落地。 ## What changes One cell of the `percent` row in `skills/objectstack-data/rules/field-types.md` (Numbers table). It read `Percentage values (0-100)`; it now reads: *Percentage; stored as a fraction (0-1) unless the field declares `max` above 1 (`max: 100`), then whole points; seeds, defaults, API values use that scale.* The Config cell (`min`, `max`, `precision`, `percentDisplay`) is unchanged. The rule is `percentScaleOf` in `packages/spec/src/data/percent-scale.ts` on `main` `1f1a369b`: "A percent field stores a FRACTION unless it declares `max` above 1" — the rule the percent edit widget writes by (typed input divided by 100 unless `max` is above 1), so `min: 0, max: 100` is a storage statement, not only validation; the read side (`percentDisplayValue`, `ui/packages/fields/src/index.tsx` `PercentCellRenderer` via `percentCellScale`) multiplies a fraction by 100. The cell says "seeds, defaults, API values use that scale" because every write path stores the number as sent: a seeded `25` on a field without `max` reads back `2500%`, and `0.25` is what "25%" needs. **Changeset** `.changeset/28489-percent-storage-scale-skill.md`: `@objectstack/skills` patch, both declaration lines. ### Token ceiling — paid by deletion, never by re-wrap `field-types.md` had 1 token of headroom under its 3207 ceiling after PR #28487. The new cell is +128 bytes over the old one. Deleted to pay for it: the `### Vector (AI Embeddings)` example under Common Field Configurations (125 bytes) — its one fact, that `dimensions` is the flat field-level key, is already the Enhanced Types row (`` `dimensions` (flat sibling, e.g. `1536`) ``), and the invented-key blockquote at the top of the file already names `vectorConfig` as refused. No line was re-wrapped. **Readings** (bytes · ceil(bytes/4) tokens · lines), base `1f1a369b` → head `12f6cdc6`: | Surface | Before | After | |:---|:---|:---| | `skills/objectstack-data/rules/field-types.md` | 12824 B · 3206 tok · 273 lines | 12828 B · 3207 tok · 264 lines (ceiling 3207, headroom 0) | Every other file under `skills/` is unchanged. ## Tests Documentation only. `skills/objectstack-data/evals/*.json`, `SKILL.md` and the other rules files were grepped for `percent`, `0-100` and `0–100`: no eval or other skill text states a 0–100 scale, so no eval changes (the order's condition did not fire). ## Acceptance notes - **Scope held to the one cell.** The `scale` consequence (`FieldSchema.scale` counts the decimal places of the displayed percentage-point value, so a fraction-stored field carries `scale + 2` stored places) is stated once on the `scale` describe and not restated in the skill; the cell gives the author the storage answer the `scale` rule hangs on. - **The `progress` type is not a `percent`.** Its row (`Progress bar`, `min`, `max`) is untouched; `percentScaleOf` answers `undefined` for it and the renderer reads it as whole points, which is not this card's subject. - **Not touched:** `skills/*/references/_index.md` (open PR #28467), the docs site page (`content/docs/data-modeling/fields.mdx` Number Types already carries no 0–100 claim for `percent`), `skills/objectstack-ui`. - **Dedupe words** for the seat: percent fraction skill, percentScaleOf skill, field-types token ceiling. ## Verification All readings at head `12f6cdc6` (= `origin/main` `1f1a369b` + one commit). - **Derived gates** — `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` → 43 families; every line run with stdin closed after `turbo run build --filter='@objectstack/client-react...'` under the verify lock, exit codes landed on disk first; `dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILE` → `✓ dispatch-gates --ran: 43 derived famil(ies) accounted for — 42 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)`. 42 families exit 0, among them `check-skills-token-ratchet` (+ `--self-test`), `check:skill-identifier-liveness`, `check:corpus-claim-drift`, `check:doc-authoring`, `check:role-word`, `check:pm-skill-id-lint`, `check:pm-governed-merges`, `@objectstack/spec check:skill-examples`, `check:closing-keyword-parity`, `check:empty-changeset`, `check:changeset-no-major`. - NOT MEASURED: `pnpm check:dual-build-cjs-loads`, exit 3 (PREREQUISITE NOT MET — it needs every package's `dist`, a full `pnpm build`); the diff touches no package entry. CI runs it. - **Tier** — `skills/**`: `claude-fable-5-1` MANDATORY, no one-line exit; this thread runs on that tier. - **Changed lines** — 1 file under `skills/` plus the changeset, far under the 3000 human-merge threshold. Dogfood: not run — the title carries no `!` and `Clause-②` carries no `(narrowing)` arm. ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (No schema touched.) - [x] 2. Every name I added uses the casing for its kind. - [x] 3. No formatter ran; `pnpm lint` passes (CI-owned repo scan; no `.ts` touched). - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. - [x] 6. `packages/spec` touched: its generated artifacts are regenerated and committed. (Not touched.) - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English. - [x] The *Before Submitting* list in CONTRIBUTING.md is done. --- _Generated by [Claude Code](https://claude.ai/code/session_01L9qibvc9vjAiGhyhnLTp34)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent eeec88d commit 35b178b

2 files changed

Lines changed: 11 additions & 10 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/skills': patch
3+
---
4+
5+
docs(skills): the objectstack-data field-types rule states a percent field's storage scale
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
The `percent` row of the field-type table no longer says "Percentage values (0-100)". It states the storage rule the platform applies: a `percent` field stores a fraction (0-1) unless it declares `max` above 1 (for example `max: 100`), in which case it stores whole percentage points; seeds, defaults and API values use that stored scale. An author who followed the old text seeded `25` on a field without `max` and read back `2500%`. Paid inside the file's token ceiling by deleting the `Vector (AI Embeddings)` example, whose one fact (`dimensions` is the flat key) the Enhanced Types row already states.

‎skills/objectstack-data/rules/field-types.md‎

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fields: {
5151
|:-----|:------------|:-------|
5252
| `number` | Generic numeric value | `min`, `max`, `precision`, `scale` |
5353
| `currency` | Monetary amounts | `currencyConfig` (currencyMode, defaultCurrency, currencyField, homeAmount) |
54-
| `percent` | Percentage values (0-100) | `min`, `max`, `precision`, `percentDisplay` — the read-only face: unset or `'bar'` draws a progress bar, `'plain'` the number alone, for a rate or a probability |
54+
| `percent` | Percentage; stored as a fraction (0-1) unless the field declares `max` above 1 (`max: 100`), then whole points; seeds, defaults, API values use that scale | `min`, `max`, `precision`, `percentDisplay` — the read-only face: unset or `'bar'` draws a progress bar, `'plain'` the number alone, for a rate or a probability |
5555

5656
## Date & Time
5757

@@ -243,15 +243,6 @@ The `format` is literal text interleaved with `{...}` tokens:
243243
3. **Pad width is a MINIMUM, not a cap.** `{000}` → `001`…`999`, then `1000` (it grows, never wraps). Size it for readability, not as a ceiling.
244244
4. **Only known tokens are interpolated.** Date tokens are **case-sensitive** — `{yyyy}` parses as a `{field}` reference and renders **empty** (rule 1 applies). Only a spelling no field could have — `{ YYYY }`, `{YYYY-MM}` — is emitted **literally**.
245245
246-
### Vector (AI Embeddings)
247-
248-
```typescript
249-
{
250-
type: 'vector',
251-
dimensions: 1536, // flat sibling — OpenAI ada-002
252-
}
253-
```
254-
255246
## Incorrect vs Correct
256247
257248
### ❌ Incorrect — Autonumber interpolating an optional / adjacent field

0 commit comments

Comments
 (0)