Skip to content

Commit 6704717

Browse files
objectstack-fleet[bot]os-steveclaude
authored
docs(skills): dashboards.md conditions the measure-currency chain on currencyMode 'fixed' and cites the spec describe (#20256)
Fixes #20196 Clause-②: no ## What One comment block in `skills/objectstack-ui/rules/dashboards.md` (the `os:check` dataset snippet under "Server-side date bucketing", `:304`–`:308` on the base) taught the monetary measure's currency chain as reading the aggregated field's `currencyConfig.defaultCurrency` unconditionally and cited ADR-0053 for it. The block now reads: > It resolves measure `currency` → the aggregated field's `currencyConfig.defaultCurrency` (only under `currencyMode: 'fixed'`) → the tenant `localization.currency` (`CurrencyConfigSchema`'s `currencyMode` describe). Omit it for non-money measures (count, avg-of-hours). So the middle step is conditioned on `currencyMode: 'fixed'`, a `dynamic` field falls straight to the tenant `localization.currency`, and the citation is the spec describe (navigable from `references/_index.md`, which lists `CurrencyConfigSchema` in `field.zod.ts`) instead of the date/datetime ADR. The first two lines of the block (the `currency` key, its ISO 4217 shape and the example measure) are unchanged. ## Why - The contract, verbatim from `packages/spec/src/data/field.zod.ts` at the base (`:449`; `:447` on `08c8484a`): 「Currency mode. `fixed`: the field has one currency, `defaultCurrency`. `dynamic` (the default): the field has no currency of its own — amounts display in the tenant default currency (the `localization.currency` setting; a plain number when none is set) and `defaultCurrency` is not read. Neither mode is a per-record choice: the value is a bare number either way.」 - The runtime implements exactly that chain: `packages/services/service-analytics/src/analytics-service.ts:1863`–`:1875` (explicit measure `currency` → `sourceFieldMeta().defaultCurrency` → `ctx.currency`) with `plugin.ts:1153`–`:1161` relaying `defaultCurrency` only when `currencyConfig.currencyMode === 'fixed'`; the response contract says the same at `packages/spec/src/contracts/analytics-service.ts:79`–`:89`. The skill text now matches both. - ADR-0053 is the date / datetime semantics record and never names currency. The card is the split-out site 2 of the currency-mode family card; #20126 remains open and carries the family's enumerating pin, which this PR does not add (spec-lane surface). ## Line budget (the skill token ratchet had headroom 0 on this file) `skills/**` is priced in tokens by `node scripts/check-skills-token-ratchet.mjs` (`ceil(utf8 bytes / 4)`), and the dispatch asked for net ≤ 0 lines and ≤ 0 tokens on the file and on the package. | file | before | after | ceiling | |---|---|---|---| | `skills/objectstack-ui/rules/dashboards.md` | 468 lines / 6252 tokens (25006 bytes) | 468 lines / 6245 tokens (24978 bytes) | 6252 tokens (`check-skills-token-ratchet`) — headroom 0 → 7 | | `skills/objectstack-ui/**` hand-authored (9 files: `SKILL.md`, `evals/README.md`, 2 evals JSON, 5 `rules/*.md`) | 2064 lines / 26213 tokens | 2064 lines / 26206 tokens | per-file ceilings; the two `references/*.md` files are generator-owned and not ratcheted | - The rewritten block grows from 5 lines / 376 bytes to 6 lines / 448 bytes (+72 bytes, +1 line). The dispatch's expectation that dropping 「(ADR-0053)」 alone pays for the condition did not hold: the tightest 5-line rewrite measured still exceeded the ceiling by 17 bytes, and the wording above by 70. - The addition is paid by **deleting content** in the same file, not by re-wrapping: the report snippet's comment line `// drilldown defaults true — click a cell to open the underlying records; set false to disable.` (`:408` on the base, 100 bytes). The same file states that fact twice in prose — `:378`–`:379` (「A `summary` / `matrix` report (`drilldown` defaults `true`) opens the identical in-place drawer on row/cell click」) and `:421`–`:422` (「`drilldown` (default `true`) makes cells click-through to the underlying records」) — so nothing an author needs is lost. - Line wrap of the rewritten block stays at the file's ≤ 85-column comment width; no other line is reflowed. The ceiling is not raised. ## Verification (all at head `1e5ff84a`, the only commit) - Gate list from `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` with no paths: the change set was derived from merge base `14ae40b0` (1 path, +3 / −3, committed 1, working tree 0, untracked 0). It derived 23 commands (15 matched by path, 8 whole-tree). - Result: **23 commands, every one exit 0.** Reconciliation `dispatch-gates --ran`: `23 derived famil(ies) accounted for — 23 run, 0 NOT-MEASURED (a DERIVED zero — all 23 recorded an exit code and none of them is 3)`. - The first run of `pnpm --filter @objectstack/lint run check:doc-formula-expressions` exited 3 with `PREREQUISITE NOT MET` (`@objectstack/formula` and `@objectstack/lint` not built); nothing was measured in that run. Both were built under the verify lock (`turbo run build --filter=@objectstack/spec --filter=@objectstack/formula --filter=@objectstack/lint`, `VERDICT command-exit 0`) and the rerun exited 0: `22 record-scoped formula example(s) across 456 files / 1383 TS blocks judged clean by @objectstack/formula`. - Verdict lines for the gates this change touches: - `node scripts/check-skills-token-ratchet.mjs`, exit 0: `skills/objectstack-ui/rules/dashboards.md is 6245 tokens (ceiling 6252; headroom 7)`; `54 authored bundle file(s) within their ceilings`. `--self-test`, exit 0: `65 cases pass`. - `pnpm check:nul-bytes`, exit 0: `OK (scanned 9707 text file(s) … no raw ASCII control bytes)`. - `pnpm check:doc-authoring`, exit 0: `16350 customer-facing string(s) across 1093 spec sources clean`. - `pnpm check:skill-identifier-liveness`, exit 0: `Leg 1: 457 citation(s) over 53 published file(s) checked against 108541 implementation word tokens`. - `pnpm check:skill-frame-sync`, `pnpm check:skill-compatibility`, `pnpm check:role-word`, `pnpm check:corpus-claim-drift`, `node scripts/check-doc-route-spelling.mjs --advisory`, `node scripts/check-comment-mask-corpus.mjs` (`7260 files, 0 disagree`): exit 0. - Beyond the derived set, because the edited block sits inside an `os:check`-marked snippet: `pnpm --filter @objectstack/spec check:skill-examples`. Its first run exited 3 (`packages/client-react/dist holds no .d.ts declarations`; nothing measured); after `turbo run build --filter=@objectstack/client --filter=@objectstack/client-react` under the verify lock (`VERDICT command-exit 0`, 34 tasks) the rerun exited 0: `259 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them` (225 blocks on the skills + docs surface). - Not in the derived total, and so not measured locally: the artifact-roster families, the wide-population families and the CI jobs these paths schedule. CI runs them. - `origin/main` moved two commits past the base while this ran (`e4621867`); neither touches `skills/objectstack-ui/**`, so no merge was made. ## Changeset - None, and `skip-changeset` applies: the path is the published skills catalog (`npx skills add`), not a workspace package. - Measured: the root `package.json` is `private: true` with no `files`; no workspace `package.json` has a `files[]` entry that reaches the repo-root `skills/` tree (grep over every `packages/**/package.json` for `skills` or a `..` segment: 0). Positive control: `CurrencyConfigSchema`, a symbol the new text names, is present in 30 files under `packages/spec/dist` (spec's `files[]` starts with `dist`); the rewritten sentence itself appears in none of spec's published paths (`dist`, `json-schema`, `prompts`, `llms.txt`, `liveness`, `api-surface`). ## Acceptance notes - **Sweep of `skills/**` for the same unconditioned chain, or `ADR-0053` within five lines of `currenc`** (read at the base `14ae40b0`, before the edit): - `git grep -n "ADR-0053" -- skills`: 2 hits — `skills/objectstack-query/rules/filters.md:251` (the calendar-day rule; no `currenc` within five lines) and the site `dashboards.md:308`. A mechanical five-line window check pairs `ADR-0053` with `currenc` only at the site (`:308` against `:304`–`:307`). - `git grep -n "defaultCurrency" -- skills`: 6 lines — five in `skills/objectstack-data/rules/field-types.md` (`:55`, `:183`, `:184`, `:191`, `:192`), whose resolution paragraph `:189`–`:193` states the `'fixed'` / `'dynamic'` condition across a wrapped sentence and is not a hit, plus the site `dashboards.md:307`. `localization.currency`: `field-types.md:192` and the site only. - Every other `currenc` line in `skills/**` (case-insensitive, 12 files) is a field-type table row, an example field (`Field.currency(...)`, `type: 'currency'`, `format: 'currency'`), a generated `_index.md` export list, or the word "concurrency" — none is a resolution chain. - **Hit count outside the site: 0** for both criteria, matching the dispatch's pre-read. After the edit, `ADR-0053` in `skills/**` is `filters.md:251` alone. - **The dispatch's token-budget assumption was falsified** (numbers in "Line budget" above). The payment line was chosen as the one comment in the file that restates a fact the file's prose already carries twice. - **Observation, no card:** the runtime's own comments at `analytics-service.ts:680`–`:694` and `plugin.ts:1129`–`:1145` and the `packages/spec/liveness/dataset.json:115` note already describe the conditioned chain (the liveness note was re-worded on 2026-09-27 under the family card), so the skill text was the last teaching site with the unconditioned form. Carrier: none. - **Observation, no card:** `references/_index.md` for the UI skill lists `CurrencyConfigSchema` under `field.zod.ts` with no describe text; a reader following the new citation lands on the schema and reads the describe there. That is the intended navigation, not a gap. ## 维护者速读(草稿) **改了什么**:只改 `skills/objectstack-ui/rules/dashboards.md` 里一段注释。原文教「货币度量的币种:先看度量自己的 `currency`,再看字段的 `defaultCurrency`,再看租户默认」,并引用 ADR-0053。现在改成「字段的 `defaultCurrency` 只在 `currencyMode: 'fixed'` 时才算数,否则直接落到租户的 `localization.currency`」,引用改为 spec 里 `currencyMode` 的 describe 原文。 **为什么改**:spec 与运行时都已经是「只有 fixed 模式才读 `defaultCurrency`」,这段技能文字是最后一处还在教旧链的地方;AI 照着旧文字写仪表盘,会以为 dynamic 字段也会用 `defaultCurrency`,与实际显示不符。ADR-0053 讲的是日期语义,和币种无关,引错了。 **风险与代价(含回滚)**:纯文字修正,不动代码、不动 schema、不发包,无需 changeset。该文件的 token 上限本来是零余量,新增的字用删掉同文件里一行重复注释(报表片段里「drilldown 默认为 true」,正文已说过两遍)来抵,行数不变、token 少 7,上限没动。回滚就是 revert 这一个提交。同族的枚举型 pin 按卡片约定不在本 PR 加,留给 #20126(仍开着)。 **席位意见**: **你要做的**:审阅这段注释改动,同意就在本 PR 上批准(Approve)。 --- _Generated by [Claude Code](https://claude.ai/code/session_01MjvgiFAmjHqsxy1XLiVYfH)_ Co-authored-by: os-steve <steve@objectstack.ai> Co-authored-by: Claude <noreply@anthropic.com>
1 parent daedf1f commit 6704717

1 file changed

Lines changed: 3 additions & 3 deletions

File tree

‎skills/objectstack-ui/rules/dashboards.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,9 @@ defineDataset({
304304
// A monetary measure may declare `currency` (ISO 4217) for a locale-correct
305305
// symbol: `{ name: 'revenue', aggregate: 'sum', field: 'amount', currency: 'USD' }`.
306306
// It resolves measure `currency` → the aggregated field's
307-
// `currencyConfig.defaultCurrency` → the tenant `localization.currency` default
308-
// (ADR-0053). Omit it for non-money measures (count, avg-of-hours).
307+
// `currencyConfig.defaultCurrency` (only under `currencyMode: 'fixed'`) → the
308+
// tenant `localization.currency` (`CurrencyConfigSchema`'s `currencyMode`
309+
// describe). Omit it for non-money measures (count, avg-of-hours).
309310

310311
// The widget just selects the dimension by name:
311312
const signedByMonth: DashboardWidget = { id: 'signed_by_month', type: 'line',
@@ -405,7 +406,6 @@ export const PipelineCoverageReport = defineReport({
405406
// already chronological by default — declare `order` only to change that, or
406407
// to sort by a measure / a non-date dimension.
407408
order: [{ by: 'amount_sum', direction: 'desc' }],
408-
// drilldown defaults true — click a cell to open the underlying records; set false to disable.
409409
chart: { type: 'bar', xAxis: 'forecast_category', yAxis: 'amount_sum' },
410410
});
411411
```

0 commit comments

Comments
 (0)