Skip to content

[finding] an undeclared number field prints two different decimal widths on two faces of the same column — and ⛔ number ⇒ 0 cannot be the fix, because a declared 0 also turns grouping OFF #19628

Closed

Description

@os-steve

Ruled: 5791809146 · letter A′ · 2026-09-23T08:49Z

Filed at 2026-09-22T02:11Z by the domain:spec seat 4 (session_01AmH9bKvGoLjiY86Q4Z3og2, seat post #18917), from the
out_of_scope_findings of the #19579 round, marked class (a) by the dev. ⛔ Filed unassigned, ⛔ no
priority:*, ⛔ no type — routing and grading are triage's. ⛔ Not a claim. ⛔ Not a ruling.

⭐ This card exists because a ruling said it must. Ruling batch #194 item 1 letter A′ scoped number and
currency to ride #19579's PR only if a consumer census showed one consistent absent-value per type, and
「where consumers disagree, that type gets its own card with the readings」. The number census came back
inconsistent. ⇒ this is that card, with those readings.

The defect

An undeclared number field — no scale on the declaration — prints a different number of decimal
places
in its own cell than in the summary footer under that same column. One field, one value, two widths,
from a single empty declaration.

⏱️ Readings — the sibling repo objectstack-ai/objectui

⚠️ Provenance split, stated rather than blurred. The dev took its readings at objectui origin/main
0cf2d6644bdb96a9a6784ef801ee6a60a5306bd8 and re-read them identically at the pinned .objectui-sha
87af769e9a3ee28ace099fdd653d3ebd79fe82e2. This seat re-verified two of the three legs first-hand at the
checkout it has, 3e4f6324, and attributes the third. Line numbers move between shas; the facts are what to
carry.

leg reading who took it
the summary footer resolves absence to 0 packages/plugin-grid/src/useColumnSummary.ts:343 — const decimals = column?.scale ?? 0;, under a comment saying 「Decimal places come from scale, not precision」 ⭐ this seat, at 3e4f6324
a declared 0 also turns grouping off packages/core/src/utils/number-display.ts:150 declares shouldGroupDisplayNumber(scale?, currency?) and :197 consumes it as if (!shouldGroupDisplayNumber(...)) intlOptions.useGrouping = false ⭐ this seat, at 3e4f6324
the cell resolves absence to no fixed width (minimumFractionDigits 0 / maximumFractionDigits 20) packages/fields/src/index.tsx — the dev cites :772-773 at its own shas; at 3e4f6324 this file's maximumFractionDigits hits sit at :500, :518, :530, :555, so the line is sha-dependent ⛔ the dev's, ⛔ not re-taken here
⭐ dark control, same instrument, same corpus zzzNotAFunction → exit 1, 0 hits this seat

Two further sites the dev names as resolving absence to 0, ⛔ not re-taken by this seat:
packages/plugin-grid/src/useColumnSummary.ts:401 and
packages/plugin-dashboard/src/ObjectMetricWidget.tsx:229.

⭐⭐ Why number ⇒ 0 is NOT the fix — this is the whole reason the card exists

percent ⇒ 0 worked because a percent's declared scale is its decimal width and nothing else. For number
the same value carries a second meaning:

shouldGroupDisplayNumber(scale) => scale !== 0 — with the in-line reading 「Only an explicitly declared
scale of 0 is an ordinal. undefined !== 0」

⇒ a declared 0 marks the field as an ordinal (a year, a fiscal period, an identifier) and renders it
ungrouped, while an absent scale keeps its separators. So declaring number ⇒ 0 would print 2026
where the platform shows 2,026, for every undeclared number field in every app.

⚠️ That is a user-visible regression across the whole install base, not a formatting nit. It is also why
the ruling refused plain letter A.

What the decision actually is

Not 「what is number's default scale」 but: can one declaration serve both the display width and the
ordinal marker, or does the ordinal marker need its own key?
⛔ This card states no preference and ⛔ names
no option as preferred — the readings are here so whoever rules does not re-derive them.

Seam

spec:FieldSchema.scale → renderer:NumberCellRenderer | renderer:useColumnSummary |
renderer:ObjectMetricWidget | core:shouldGroupDisplayNumber

Why it lands in THIS repo

The ruling puts the declaration in packages/spec; the consumer half follows in objectui
(objectstack-ai/objectui#9843 holds that half). 〈多仓协调〉rule 1: 「issue 住在修复落地的仓」.

⛔ Independent card, ⛔ NOT a sub-issue of #19579 and ⛔ not blocked by it — #19579 is complete without it,
and its PR states in terms that number and currency do not ride.

Dedupe

absent scale number default · number-display grouping scale 0 · NumberCellRenderer maximumFractionDigits 20 ·
useColumnSummary decimals · shouldGroupDisplayNumber ordinal · declared zero turns grouping off

Activity

  1. objectstack-fleet commented on Sep 22, 2026

    @objectstack-fleet
    Contributor

    Triage: moved to the decision box by the triage seat (session_01Tw7jnJinGHvoGSi8aFkhPJ), 2026-09-22T18:44Z. ⛔ Not dispatchable until ruled.

    Path: records · 每种字段都渲染得出、收得下、存得住 | records-forms.field-type-matrix(② 步骤够不到该路径) | P② | 待裁
    Governing text: 维护者裁决 batch #194 item 1 letter A′(「where consumers disagree, that type gets its own card with the readings」);ADR-0049
    Prior rulings on this card: batch #194 item 1 A′ ordered this card to exist; ⛔ no ruling on the key's meaning

    维护者速读

    一个没有指定小数位的数字列,在表格里和在底部汇总行里,小数位数不一样 —— 同一个数,两种印法。

    本来最简单的修法是「没写就当 0 位」,但不行:0 这个值在系统里已经被借去表示另一件事(「这是序号,别加千分位」)。所以一改就会给全库所有没写小数位的数字字段悄悄关掉千分位。

    两条路:让一个设置继续兼两个意思(改动小,坑留着),或者给「序号」一个自己的设置项(语义干净,但动到对外的配置面,要迁移)。

    席位建议后者:这个坑今天就在印错数字,而且只要不拆开,下一个碰它的人会再写一张一模一样的卡。

    要您定的一件事:A(一个设置兼两职)还是 B(序号另立一个键)?

    The reading this rests on

    一个没有声明 scale 的 number 字段,在同一列的两个面上印出不同的小数位:单元格按「最多 20 位」渲染,列底部的汇总按 0 位渲染(column?.scale ?? 0)。两个消费者对「没写」这件事给了相反的默认。

    ⚠️ 显而易见的修法(把缺省当 0)走不通,而这正是要您裁的原因:scale: 0 这个值同时被当成另一个意思用 —— 「这是序数,不要加千分位」(shouldGroupDisplayNumber(scale) => scale !== 0)。把缺省折成 0,等于给全库每一个没声明 scale 的数字字段都悄悄关掉千分位。

    两个消费面都在前端仓;声明的那一半在这里。

    Options

    A —— 一个 scale 兼两职。 定义「没写」等于什么,并接受序数标记继续借用 0。改动小,但两个意思永远绑在一个数上。
    B —— 序数标记拿自己的键。 scale 只管显示宽度,序数另立一个显式的键。语义干净,但扩大公开面(条款② yes),且要迁移现有借用 0 的数据。

    四棱

    • 实际业务需求:这是今天就撞得到的 —— 任意一个没声明 scale 的数字列,单元格和汇总行印得不一样。有实测拉动,⛔ 不是投机面。
    • 项目长远合理性:一个键扛两个意思,是这张卡卡住的唯一原因。B 一次付清;A 把这个耦合留给下一个碰它的人,而下一个人会再写一张同样的卡。
    • 防 AI 写错:B 更难写错 —— AI 写 scale: 0 时意思是唯一的。A 之下,AI 无法从键名知道自己顺手关掉了千分位。
    • 创业阶段不扩散:A 不动公开面,B 动。⚠️ 这一轴单独指向 A,与上面三轴相反 —— 如实呈上,不替您折中。

    席位推荐:B,依「分歧推荐序」:本卡有实测拉动(今天就印错),按 「有实测拉动 ⇒ 荐长远形态一次付清」。⚠️ 但 B 扩大公开契约面,属人工地板,⛔ 席位不代裁。若您取 A,请一并指定「没写」等于什么,否则这张卡会以另一种形状回来。


    Generated by Claude Code

  2. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    Ruling: batch #215 item 2 · letter A′ · maintainer 「215 同意」 2026-09-23T08:45Z

    Director seat, summon #28 (session_01GLdRPcbaCBQCTvVmU6YEUY). Presented in this seat's chat with recommendation A′; the maintainer approved the batch as presented. A (a declared default width for number) was refused by batch #194 A′ by name (「number ⇒ 0 would print 2026 where the platform shows 2,026」); B (an ordinal marker of its own) already exists on main — FieldSchema.useGrouping (packages/spec/src/data/field.zod.ts:1272, #7768), whose describe names the absent case 「renderer decides (interim heuristic today, locale default eventually)」 — so the card's A/B question was already answered by the protocol, and what remained was the absent width and the computed faces.

    Governing text: batch #194 item 1 A′ (「the absent value is PROTOCOL … ⛔ no ?? N in any consumer」, packages/spec/src/data/field-scale.ts, whose docblock already states 「a type with no row has NO declared width for an absent scale, which is a real answer … ⛔ not a hole for a caller to fill」); the FieldSchema.useGrouping describe; ADR-0049. Prior rulings read: number,undeclared,field,prints,different,decimal,widths,faces,column,declared,turns,grouping → 186 hits; ADR-0032 Decision §1, ADR-0085 Decision §5, ADR-0085 Decision §6, ADR-0120 D3, ADR-0120 D5, ADR-0005 Decision §5, ADR-0032 Decision §3; thread: none; repo: objectstack-ai/objectstack — none rules on this key's absent value.

    Ruled shape — A′

    1. field-scale.ts gets no number row: an absent scale on a number field means NO fixed width — the value's natural precision — and that is the platform's declared answer, ⛔ not an open question. The docblock's 「nobody has ruled yet」 wording for number is replaced by a citation of this ruling; a pin asserts resolveFieldScale({ type: 'number' }) is undefined and stays so.
    2. Every consumer reads the width through resolveFieldScale and deletes its private ?? 0 — the summary footer (packages/plugin-grid/src/useColumnSummary.ts:343 / :401) and the metric widget (packages/plugin-dashboard/src/ObjectMetricWidget.tsx:229): finding(fields): 一个既不声明 precision 也不声明 scale 的 percent 字段在 main 上被渲染成两个宽度 —— 四个站点已按 objectui#9295 收敛到 scale ?? 0,编辑控件仍停在 precision ?? 2 objectui#9843's scope, which unblocks now that [rebuild of #19368] spec: declare what an ABSENT scale means per numeric field type — percent ⇒ 0 — the @objectstack/spec half of objectstack-ai/objectui#9843 (ruled A′) #19579 is closed.
    3. Computed results over a no-fixed-width column (summary footer, metric widget): round to the widest decimal count among the values that entered the computation — derived from the data, ⛔ never a constant.
    4. Grouping stays on its own key: useGrouping decides; the interim heuristic for its absent case (scale === 0 ⇒ ungrouped, objectui number-display.ts) reads the DECLARED scale only, never a resolved width — so nothing in this ruling moves a thousands separator.

    Execution

    needs-user-decision → pm:queue in this stroke; domain:spec · priority:p3 · Clause-②: no (the spec half is a docblock ruling + a pin; no key changes). A pointer is left on objectstack-ai/objectui#9843 with item 3's rule.

  3. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 1
    Session: session_01CiCTczDo7tGhafXjf61dUJ
    Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-19628-number-absent-scale-ruled
    Worktree: objectstack-issue-19628
    Domain: domain:spec
    Seat: domain:spec#4 (seat post #18917)
    File surface: the spec half of ruling 5791809146 (batch #215 item 2, letter A′), item 1 only. That is packages/spec/src/data/field-scale.ts, docblock only: the number passage (about :59–:67) and the sentence at :84 that still says number 「still awaits its own ruling」. Plus packages/spec/src/data/field-scale.test.ts, where the existing resolveFieldScale({ type: 'number' }) → undefined pin (:53) gets its ruling citation; and a patch changeset for @objectstack/spec, since the docblock ships. ⛔ No code token of field-scale.ts moves: no number row. ⛔ Not objectui: items 2–3 are objectui#9843's. (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: default judgment tier (no path-derived mandate for packages/spec/src/data/). The diff touches a non-test file under packages/spec/src/**, so the at-tier review is owed on the path limb before enqueue.
    Clause-②: no
    Thread-read: 5791809146
    Serial constraints cleared: read at 2026-09-27T13:42Z. Open-PR census: 12 open PRs besides the release PR; none touches field-scale.ts or its test. In-flight claims, 29 pm:dispatched cards read: none names field-scale. The file's last change is 5b9402d89 (#19909, the currency scale retirement), which is landed.

    Ruling carried: 5791809146 (batch #215 item 2, letter A′, maintainer 「215 同意」). Item 1, verbatim: 「field-scale.ts gets no number row: an absent scale on a number field means NO fixed width — the value's natural precision — and that is the platform's declared answer, ⛔ not an open question. The docblock's 「nobody has ruled yet」 wording for number is replaced by a citation of this ruling; a pin asserts resolveFieldScale({ type: 'number' }) is undefined and stays so.」

  4. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 19628,
    "status": "done",
    "branch": "claude/issue-19628-number-absent-scale-ruled",
    "pr": "#20248",
    "session": "session_01CiCTczDo7tGhafXjf61dUJ — subagent, so the dispatching parent's id (the container env carries the cse_ spelling of the same id)",
    "premise_still_valid": true,
    "summary": "Spec half of ruling 5791809146 (batch 215 item 2, letter A′), item 1 only. field-scale.ts: the number docblock bullet now states the ruled answer (an absent scale on number = NO fixed width, the value's natural precision, the platform's declared answer, not an open question), cites the ruling by its record, attributes items 2-3 to objectui#9843, and names FieldSchema.useGrouping as the key that decides grouping, with the interim heuristic reading the DECLARED scale only (item 4). The closing sentence no longer says number 「still awaits its own ruling」. The currency bullet is byte-identical and there is no number row: the comments-stripped token stream is identical base vs head. field-scale.test.ts: the existing resolveFieldScale({ type: 'number' }) → undefined pin got its own case titled and commented with the ruling; the currency assertion keeps its own case; no assertion changed. Mechanism assumptions 1-3 all held at c02fa12. One PM premise failed: the edited docblock does NOT ship, so there is no changeset and the PR carries skip-changeset (see deviations). Items 2-4 are objectui#9843's and untouched.",
    "tests": "All at HEAD bf7b0ff (base c02fa12). (1) Token identity: TypeScript scanner, comments skipped, base vs head field-scale.ts gives 123 = 123 tokens, identical=true, sha256 prefix 65aed4895c596175 on both; control copy with percent: 0 changed to percent: 1 gives identical=false, exit 1; raw bytes differ (cmp exit 1). (2) pnpm --filter '@objectstack/spec^...' build: No projects matched (empty closure, exit 0). pnpm --filter @objectstack/spec build: exit 0 (lock VERDICT batch-last-exit 0; closure step separately exit 0). (3) pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/data/field-scale.test.ts: Test Files 1 passed, Tests 13 passed, exit 0. (4) Full spec suite vitest run --project local --maxWorkers=2: Test Files 546 passed (546), Tests 16071 passed | 2 todo (16073), exit 0 (lock VERDICT command-exit 0). (5) pnpm --filter @objectstack/spec typecheck: exit 0 (tsc --noEmit + check:scripts-typecheck + check:test-typecheck OK, 53 files / 255 errors / 142 pinned signatures held); tsc -p tsconfig.test.json --listFilesOnly lists field-scale.test.ts (1 hit of 519 test files), main tsconfig.json 0 (it excludes tests). (6) Gates: see gates, 77 derived, reconciled with --ran as 74 run, 3 NOT MEASURED, 0 unrun. (7) eslint --no-inline-config --format json over the 2 touched files: 2 files linted, 0 errors, 0 warnings, exit 0; resolved config for the path has parserOptions.project and projectService undefined (no type-aware linting), so the diff cannot move any untouched file's verdict; repo-wide pnpm lint left to CI. (8) Control-byte self-scan of both files: 0 hits (grep exit 1). (9) Shipping measurement after the spec build: 0 hits for the docblock heading, the old sentence, the new text and the ruling id across every files[] path; the unchanged resolveFieldScale TSDoc (positive control) hits dist/data/index.d.ts and .d.mts. No ablation was owed: the diff moves no code token and adds no guard.",
    "mcp_calls": "0 — no MCP GitHub tool was called (the objectui read went through the public raw host)",
    "api_writes": "3 relay dispatches from this process, each POST /repos/objectstack-ai/objectstack/dispatches through the scripts/pm tools; the relay executed 4 writes as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, draft #20248 (relay run 36326450026, success); (2)+(3) label-write, POST /repos//issues/20248/labels [skip-changeset] and POST /repos//issues/20248/assignees [os-sales] (relay run 36326494626, success, read back MATCHES); (4) this os-dev-report, POST /repos//issues/19628/comments via post-stamped. Plus 3 git pushes (empty-branch probe, cf7108c, bf7b0ff), not REST. No other writes.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: 承接者:无 · noted, not filed — FieldSchema.useGrouping TSDoc in packages/spec/src/data/field.zod.ts (the interim-heuristic paragraph about :1255-1262) gives the objectui heuristic as bounds-based (scale: 0 + no upper bound keeps grouping). objectui at the pinned .objectui-sha f8a9d0fb, packages/core/src/utils/number-display.ts:166-171, is return scale !== 0 with no bound (dark control zzzNotAFunction 0 hits). This is comment drift, not a defect, contract breach or (c) trap: the describe an author sees says only "renderer decides". It is outside this claim's file surface and recorded in PR #20248's Acceptance notes."
    ],
    "gates": {
    "head": "bf7b0ff03",
    "reconcile": "dispatch-gates --ran: 77 derived, 74 run, 3 NOT-MEASURED (DERIVED from recorded exit 3), 0 UNRUN; the 5 roster families below are extra (their roster sits in a directory this diff touches)",
    "note": "check:doc-formula-expressions first exited 3 (formula/sdui-parser/lint closure unbuilt); after turbo build of that closure (exit 0) it exits 0, and the line below records the rerun. The 3 exit-3 families each need a full workspace build (86 packages without dist) and are NOT MEASURED; CI runs them.",
    "commands": [
    "node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
    "node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
    "node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
    "node scripts/check-changeset-no-major.mjs --self-test :: exit 0",
    "node scripts/check-ci-filter-parity.mjs :: exit 0",
    "node scripts/check-closing-keyword-parity.mjs :: exit 0",
    "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
    "node scripts/check-comment-mask-adoption.mjs :: exit 0",
    "node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
    "node scripts/check-comment-mask-corpus.mjs :: exit 0",
    "node scripts/check-dev-prereqs.mjs --self-test :: exit 0",
    "node scripts/check-keyed-text-bounds.mjs :: exit 0",
    "node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0",
    "node scripts/check-platform-object-tenancy-census.mjs :: exit 0",
    "node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0",
    "node scripts/check-plugin-teardown-shape.mjs :: exit 0",
    "node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
    "node scripts/check-registry-log-declared.mjs :: exit 0",
    "node scripts/check-registry-log-declared.mjs --self-test :: exit 0",
    "node scripts/check-rest-log-spy-declared.mjs :: exit 0",
    "node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0",
    "node scripts/check-spec-docblock-symbol-anchors.mjs :: exit 0",
    "node scripts/check-spec-docblock-symbol-anchors.mjs --self-test :: exit 0",
    "node scripts/check-system-context-census.mjs :: exit 0",
    "node scripts/check-system-context-census.mjs --self-test :: exit 0",
    "node scripts/check-undeclared-dep-imports.mjs :: exit 0",
    "node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0",
    "node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
    "node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
    "pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0",
    "pnpm --filter @objectstack/spec run check:api-surface :: exit 0",
    "pnpm --filter @objectstack/spec run check:authorable-surface :: exit 0",
    "pnpm --filter @objectstack/spec run check:browser-reachable-entries :: exit 0",
    "pnpm --filter @objectstack/spec run check:docs :: exit 0",
    "pnpm --filter @objectstack/spec run check:dual-source-exports :: exit 0",
    "pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
    "pnpm --filter @objectstack/spec run check:empty-state :: exit 0",
    "pnpm --filter @objectstack/spec run check:entry-nameability :: exit 0",
    "pnpm --filter @objectstack/spec run check:export-origins :: exit 0",
    "pnpm --filter @objectstack/spec run check:exported-any :: exit 0",
    "pnpm --filter @objectstack/spec run check:liveness :: exit 0",
    "pnpm --filter @objectstack/spec run check:llms-txt :: exit 0",
    "pnpm --filter @objectstack/spec run check:objectui-pin-citations :: exit 0",
    "pnpm --filter @objectstack/spec run check:skill-refs :: exit 0",
    "pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0",
    "pnpm --filter @objectstack/spec run check:variant-docs :: exit 0",
    "pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0",
    "pnpm check:changeset-gate-self-tests :: exit 0",
    "pnpm check:cross-package-test-inputs :: exit 0",
    "pnpm check:dispatcher-error-vocabulary :: exit 0",
    "pnpm check:doc-authoring :: exit 0",
    "pnpm check:driver-memory-census :: exit 0",
    "pnpm check:dts-closure :: exit 0",
    "pnpm check:dual-build-cjs-loads :: exit 3",
    "pnpm check:engine-double-contract :: exit 0",
    "pnpm check:gitlink-declared :: exit 0",
    "pnpm check:issue-citations :: exit 0",
    "pnpm check:lean-entry-closure :: exit 3",
    "pnpm check:logger-receiver-detach :: exit 0",
    "pnpm check:merge-driver :: exit 0",
    "pnpm check:nul-bytes :: exit 0",
    "pnpm check:objectql-double-limit :: exit 0",
    "pnpm check:org-identifier :: exit 0",
    "pnpm check:page-declaration-shape :: exit 0",
    "pnpm check:pm-prior-rulings :: exit 0",
    "pnpm check:published-files :: exit 0",
    "pnpm check:query-options-erasure :: exit 0",
    "pnpm check:refd-timer-probe :: exit 0",
    "pnpm check:slot-lookup :: exit 0",
    "pnpm check:sourcemap-no-sources-content :: exit 0",
    "pnpm check:spec-parsed-alias :: exit 0",
    "pnpm check:test-source-alias :: exit 0",
    "pnpm check:tier-file-adoption :: exit 0",
    "pnpm check:type-check-coverage :: exit 0",
    "pnpm check:type-check-debt :: exit 3",
    "pnpm check:watch-hint-literal :: exit 0",
    "pnpm check:where-matcher :: exit 0",
    "pnpm --filter @objectstack/spec run check:meta-url-spelling :: exit 0",
    "pnpm --filter @objectstack/spec run check:spec-changes :: exit 0",
    "pnpm check:authz-resolver :: exit 0",
    "pnpm check:error-code-casing :: exit 0",
    "pnpm check:filter-alias-parity :: exit 0"
    ]
    },
    "line_budget": {
    "changed_lines": 53,
    "additions": 36,
    "deletions": 17,
    "human_merge_threshold": 5000,
    "packages/spec/src/data/field-scale.ts": "155 → 167 lines (+23/-11)",
    "packages/spec/src/data/field-scale.test.ts": "142 → 149 lines (+13/-6)",
    "skills": "no skills/** path touched"
    },
    "deviations": [
    "Changeset: the dispatch ordered a patch changeset for @objectstack/spec "(the docblock ships)". Measured after the spec build, it does not ship: field-scale.ts is outside src/**/*.zod.ts, and the module docblock text reaches none of the files[] paths while the positive control does. Under the agent definition's criterion (symbol zero hits, positive control hits = not published; that file governs when it conflicts with a dispatch), there is no changeset and the PR takes skip-changeset. The changeset was added in ce8d3d3 and removed in bf7b0ff; the PR diff carries none. If the PM wants a patch anyway, re-adding it is one file and removing the label is one write.",
    "label-write carried skip-changeset alongside the named PR assignee in the ONE budgeted call; skip-changeset is the one label the agent definition's labelling scope adds by that criterion.",
    "The combined number+currency test case was split in two so that the number pin's title carries the ruling. The currency assertion and its comment facts are unchanged, and no assertion was added, removed or altered.",
    "Attribution follows AGENTS.md over the harness reminder: commits end with the model-free Claude-Session / Co-authored-by pair, and the PR body ends with the session-URL footer form."
    ],
    "files_changed": [
    "packages/spec/src/data/field-scale.ts",
    "packages/spec/src/data/field-scale.test.ts"
    ]
    }

  5. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    Contributor

    ACCEPT — PR #20248 (2026-09-27T15:12Z)

    domain:spec seat 4 (session_01CiCTczDo7tGhafXjf61dUJ). This is the review of record for the round claimed in 5856375966; the dev report is 5856798203.

    Checklist, read on GitHub:

    • PR form: base main, first line Fixes #19628, no other closing keyword. The bare line Clause-②: no matches the diff. Assignee os-sales. Labelled skip-changeset.
    • Scope: 2 files (+36 / −17). packages/spec/src/data/field-scale.ts changes its docblock only. field-scale.test.ts splits one case in two, so the number pin carries the ruling in its title; no assertion changes.
    • At-tier contract review: PASS, record 5857071016 on the PR, at head bf7b0ff033.
      • No code token moves: 123 = 123 tokens, and the stream hash is identical, with a code-token control and a comment-only control.
      • The 25 assertions are byte-identical in sequence.
      • The docblock states ruling 5791809146 item 1 as the platform's declared answer. It cites the ruling record, attributes items 2–3 to objectui#9843, and matches item 4 on grouping. The stale 「still awaits its own ruling」 sentence is gone, and the currency bullet is byte-identical.
    • skip-changeset is right. This seat's dispatch assumed the docblock ships; the dev measured that it does not, and the review confirmed it:
      • field-scale.ts is outside src/**/*.zod.ts;
      • a declaration emit carries none of the module docblock;
      • esbuild drops it;
      • source maps carry no sources content.
        The correction is accepted.
    • CI at bf7b0ff033: 31 success, 8 skipped, 0 failed. All seven required contexts are success.
    • Merge: mergeable_state: clean. A no-driver merge-tree onto today's main (a91d12af2) exits 0.
    • Governed surface: 0 paths; 53 changed lines.

    Out-of-scope finding (1), disposed: the FieldSchema.useGrouping TSDoc in field.zod.ts (about :1262–:1265) describes objectui's interim heuristic as bounds-based, while the pinned objectui reads scale !== 0. The author-facing .describe() is accurate → Acceptance notes. It is comment drift in a file other claims hold regions of, for whoever next touches that block.

    Downstream: items 2–4 of the ruling are objectui#9843's, where the ruling left its pointer.

    Next: ready → auto-merge through the relay → merge queue. This card closes on the merge through Fixes.

  6. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    Contributor

    Landed — PR #20248 → 14ae40b0e1 (2026-09-27T15:36Z)

    domain:spec seat 4 (session_01CiCTczDo7tGhafXjf61dUJ). PR #20248 merged through the merge queue on 2026-09-27T15:35:53Z, and this card closed completed through its Fixes line. The readings that confirm the landing:

    • 14ae40b0e1 has one parent (08c8484a19), is an ancestor of origin/main, and the queue branch for the PR is gone.
    • Its git patch-id --stable equals the reviewed diff's (0fd0a25c4163 on both; record 5857071016 at bf7b0ff033).
    • By content: field-scale.ts's stale 「number still awaits its own ruling」 reads 0 at the merge and 1 on the parent, and the ruling record 5791809146 is cited at the merge.

    pm:dispatched and the assignee come off in the same act.

    Downstream: the ruling's items 2–4 are objectui#9843's. The FieldSchema.useGrouping TSDoc drift in field.zod.ts stays noted for whoever next touches that block.

  7. added a commit that references this issue on Sep 28, 2026
    14ae40b
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

    area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:specpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions