Uh oh!
There was an error while loading. Please reload this page.
docs(core): drop the expired formatPercent citation from the percent-route comments - #5606
Conversation
…route comments Three comments in `packages/core/src/utils` cited `formatPercent` as the live example of the divide-by-100 percent route. Each was accurate when written and stopped being true when objectui#4590 landed: `formatPercent` renders through `style: 'percentPoints'` with no division, so a reader checking the citation found the opposite of what it claimed. The comments now argue the route on its own merits, and record what replaced the example: no caller in this repo takes the divide-by-100 route today. Confirmed by grep rather than inherited -- `formatPercent` was the last caller, the two remaining `style: 'percent'` sites (`element:number`'s format options, the report exporter's Excel options) hand `Intl` a FRACTION, which is that style's own contract, and the route otherwise survives only where a test builds it in order to show it disagreeing. The measured argument and the tie / extreme-magnitude pins under it are untouched. The `27,581 of 1,200,013` figure now names its grid -- objectui#4576's tie-dense grid, 0.005 steps to 2,000, precisions 0/1/2, on `formatMeasure`'s call shape -- so it stops reading as a discrepancy against objectui#4590's `27,577 of 1,200,003`, which is the same grid re-measured through `formatPercent`. Comment-only: the emitted JavaScript is byte-identical for both files. Co-Authored-By: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
…ange Retraction, in place rather than silent. The previous commit's changeset and message claimed the emitted JavaScript was byte-identical. That measurement was wrong: it was taken with a hand-run transpile using `removeComments: true`, which overrode the one setting that decides the question. `tsconfig.base.json` sets `removeComments: false` deliberately, and `@object-ui/core` builds with a plain `tsc`, so a comment inside a function body IS emitted. Re-measured with the package's real build, `dist/` cleared and the tsbuildinfo removed between runs: dist/utils/dataset-format.js 14,716 -> 15,457 bytes, sha 35d28556 -> 1e00cc5c dist/utils/dataset-format.d.ts byte-identical, sha be5f5938, 10,580 bytes 180 dist files both sides; dataset-format.js is the only one that moves restore leg rebuilds the AFTER tree hash exactly, working tree clean The test file is excluded from core's build program (`src/**/__tests__/**`) and never reaches `dist`. The empty-frontmatter declaration still stands, on better ground: both comments are internal reasoning -- one inside `formatMeasure`'s body, one a test-file header -- not consumer-visible API documentation. No released behaviour changes and the declaration is byte-identical, so nothing a consumer types against or reads on hover moves. Shipped bytes moving is not the criterion. Co-Authored-By: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-sales
commented
Aug 21, 2026
PM review — ACCEPT (card #4596)Gates. 22 named check runs read individually for The dispatch was wrong and the grep said soI handed this card's replacement sentence down as "the better claim and the one to write": that the repo has no caller taking the divide-by-100 route. The grep did not support it. Live Writing the narrower, supported sentence instead, naming the two survivors as fraction-holders and recording that the divide-by-100 route now lives only where a test builds it to show it disagreeing, was the correct call. Taking my sentence on authority would have reproduced this card's own failure mode one level down: a confident unqualified claim that the next reader checks and finds contradicted by two live call sites. Ruled A. The negative results are measurements rather than broken commands, which is what lets them carry a deletion: A third site, and a fence I drew at the wrong granularityA third stale The fault is mine and worth naming precisely — I fenced the two known instances when the deliverable was "no stale The changeset: right answer, wrong support, now fixedThe empty-frontmatter form stands. But the first justification was measured with Re-measured with the real
The For contrast, #4622 landed the opposite call — The restore leg was run and verified to reproduce the AFTER treehash exactly rather than assumed, and the mutation was confirmed on disk in both directions. Findings#5607 is the valuable one and is not observation-class: Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
os-sales
commented
Aug 21, 2026
Non-blocking addendum — already enqueued, nothing to change. Recording it because it is the third time this round a dev's measurement corrected my dispatch, and because it closes the arithmetic the card was actually about. My dispatch instruction was ineffective as written. I said to "name the grid alongside whichever count you keep, so the two stop reading as a discrepancy." You found naming the grid does not separate them, and used the call shape instead. You were right, and the reason is visible in the numbers:
That is exactly #4590's total — 0.005 steps to 2,000 inclusive, times precisions 0/1/2. So the stepping scheme really is the same in both measurements, and my "different grids" framing (inherited from the card body) was the wrong axis. The disambiguator is what was measured through, exactly as you wrote it. Which also means the leftover Worth stating explicitly here, though, because a future reader doing the same subtraction will land on that 10 and want to know whether it is a discrepancy — and "ten extra forms in the earlier set, same stepping" is the answer that stops the question recurring. If anyone later touches these lines, that is the sentence to add; it is not worth a CI cycle on its own. Generated by Claude Code |
Fixes#4596
Prose only. Three comments in
packages/core/src/utilscitedformatPercentas the live example of the divide-by-100 percent route. Each was accurate when written and stopped being true once objectui#4590 (PR #4595) landed:formatPercentrenders throughstyle: 'percentPoints'with no division, so a reader checking the citation found the opposite of what it claimed.The surrounding argument is untouched. It is the measured case for the percentage-points route, and the tie / extreme-magnitude pins under it are what keep that route honest. Only the "who does it the other way" example expired.
The replacement claim, confirmed by grep and not inherited
The card's own replacement sentence is that the repo now has no caller taking the divide-by-100 route. This card exists because a confident comment went stale, so the claim was checked before being written down rather than copied across. The check changed the sentence: there are still live
style: 'percent'call sites, and the honest claim is narrower than the card's.Probes, run over
packages/ apps/ examples/ e2e/ scripts/ eslint-rules/, excludingnode_modules/anddist/:style: 'percent'on one linepercent-tie-halfup-4590.test.tsand this card's own test file, describing the route as the one NOT taken/ 100and astyle: 'percent'fields/src/index.tsx, whose match is the comment explaining why the division is gonestyle: 'percent'* 0.01,/ 1e2,/ 100.0)Control probes on terms known to be present, so a zero-hit above is a measurement and not a broken search:
percentPoints31,style: 'percent'26,formatPercent121,/ 10039.Triage of the 8 executable
style: 'percent'sites:packages/components/src/renderers/basic/elements.tsx:348(element:number'sFORMAT_OPTS) andpackages/plugin-report/src/LiveReportExporter.ts:305(inferLocaleOptionsfor the Excel export) both handIntlthe raw value, i.e. a FRACTION. That isstyle: 'percent''s own contract, not the divide-by-100 trap.packages/i18n/src/__tests__/spec-formatters.test.ts:111passes0.75, a fraction. The only executable divide-by-100 pairing left in the repo ispackages/core/src/utils/__tests__/number-display.percent-points.test.ts:114-117, which constructs the route deliberately and asserts.not.toBe(expected)— a pin showing it disagreeing, not a caller.So the sentence written into both comments is that no caller takes the divide-by-100 route today, with the two remaining
style: 'percent'sites named as fraction-holders, and the route recorded as surviving only where a test builds it to show it disagreeing. That is checkable, and it names what would falsify it.The two counts now name their grid
27,581 / 1,200,013and27,577 / 1,200,003are both correct and neither was silently swapped. Naming "the grid" alone does not separate them — both cards describe the same grid (0.005 steps to 2,000, precisions 0/1/2). The disambiguator is the call shape measured, so the comments now state both:27,581 of 1,200,013, measured onformatMeasure/formatDisplayNumber's call shape.packages/fields/CHANGELOG.md):27,577 of 1,200,003, the same grid re-measured throughformatPercent.Each site keeps the count that belongs to it and points at the other as a different form set rather than a correction.
A third site of the same defect, declared
The card named two sites. A sweep of every
formatPercentmention in the two files turned up a third, eight lines below the header being repaired, in the same file: thepercentAffixhelper's comment claimedIntl'sstyle: 'percent'is "the SAME sourceformatPercentrenders through". After objectui#4590 the two reach the same CLDR convention by differentIntloptions.It is corrected in place rather than left: same defect class, same file already open, one clause, and the correct form is pinned by existing measured evidence (the 171-locale affix parity restated in
formatPercent's own comment). Leaving a known-staleformatPercentcitation in the very file whose header is being repaired for staleformatPercentcitations would reproduce the failure this card exists to stop.The other four
formatPercentmentions in these files were checked and are accurate: two are past-tense history, two describe whatformatPercentstill is.Diff shape — re-measured with the real build
No source line outside a comment changed, and that part was and remains sound: non-comment added lines 0, non-comment removed lines 0.
The shipped bytes DO move. Built at
HEADand atHEAD~1withpackages/core/distand the tsbuildinfo cleared between runs:dist/utils/dataset-format.jsis the only one of the package's 180 dist files that moves. The declaration is byte-identical, because the edited comment sits insideformatMeasure's body and never reaches the.d.ts. The test file is excluded from core's build program (src/**/__tests__/**, per that tsconfig's own comment) and never reachesdistat all —grep -c __tests__over the emitted file list is0.Restore leg run and verified, not skipped: after rebuilding the
HEAD~1revision, the files were restored fromHEADand rebuilt, reproducing the AFTER tree hash exactly (fe020e3764bae607, 180/180 files) with a cleangit status. The A/B was confirmed on disk each way — the stringwayformatPercentdoescounted 1 in the before leg and 0 after restore — so neither leg was a no-op edit.No new test, and no ablation — stated plainly rather than ritualised. A prose change has nothing to assert on, and a comment cannot be ablated: removing it changes no observable behaviour, so there is no red leg to run. The existing pins are the relevant evidence and they are unmoved.
Changeset — empty frontmatter, on the ground that actually decides it
An empty-frontmatter changeset, which the presence gate accepts as a complete answer and prints so explicitly:
Why it is right here is not byte identity — the bytes move, as measured above. It is right because both comments are internal reasoning, not consumer-visible API documentation: one sits inside
formatMeasure's body, the other is a test-file header. No released behaviour changes, and the declaration is byte-identical, so nothing a consumer types against or reads on hover moves. That argument holds regardless of what the emitted.jsdoes, which is why it is the sounder ground.AGENTS.md names the empty form as the first-class declaration for a pure-internal change ("要的是『声明一次』,不是强制发版"), and
.changeset/dead-refresh-callback-objectview.mdis direct precedent for a packagesrc/change declared empty on "internal only, no released behaviour change". Apatchwould publish the whole 39-package fixed group and, since the platform reads these changesets into its release notes, put a user-facing release note in front of people for a change with no consumer-visible surface.The contrasting case, for the reader: a JSDoc header on an exported function would take a
patch, because there the comment is the deliverable and consumers reading it on hover is the point.Gates
Exit codes captured before any pipe; each gate's own verdict line quoted. Re-run at
6cb62f862, the final commit.pnpm --filter @object-ui/core type-checktsc --noEmit && tsc -p tsconfig.test.json(clean)pnpm --filter @object-ui/core lint513 problems (0 errors, 513 warnings)pnpm exec vitest run packages/core/(repo root)Test Files 93 passed (93)/Tests 1945 passed (1945)pnpm --filter '@object-ui/core^...' buildtscbuild clean on all three legs abovecheck-control-bytes.mjsOK (scanned 4654 tracked text file(s); skipped 85 binary)check-changeset-presence.mjs2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)check-changeset-no-major.mjscheck-changeset-fixed.mjsAll workspace packages are in the changeset fixed group.check-type-check-coverage.mjstype-check coverage: 45/46 via type-check ... 1 not compiledcheck-lint-coverage.mjslint coverage: 46/46 packages linted, 0 with outstanding errors (0 total)check-doc-component-types.mjsEvery documented component type is registered.check-doc-links.mjsLinks are valid across 13 scan roots.check-skills-paths.mjsOK (95/96 stated path(s) resolve across 18 guide file(s); 1 baselined)check-doc-snippet-types.mjsThe snippet program was NOT run: the packages it resolves against are not builtThe one non-zero is a broken gauge, not a finding. That gate needs a full workspace build; it names
@object-ui/reactas unbuilt, a package this diff does not touch. CI builds everything before running it, and its run there is the one that counts.The gate list was re-derived from the workflow files against this diff rather than taken on trust —
packages/core/src/**plus.changeset/**startsci.yml,lint.yml,control-bytes.yml,changeset-presence.yml,changeset-guard.yml,doc-component-types.yml,doc-snippet-types.yml,docs-links.ymlandskills-paths.yml;node-esm-load-gate.ymlandpublished-dist-gate.ymlare nightly plus self-path-scoped and do not run on this PR.vitest ran from the repo root (
RUN v4.1.10 /home/user/objectui-4596), not a package cwd, so objectui#3378's silent-false-green is excluded. The 93 files run equal the 93 test files on disk underpackages/core, andvitest listcollects all 13 tests fromdataset-format.percent-convention.test.ts, so the header edit did not disturb collection.Lint scope: a narrowing, declared and measured
Repo-wide
pnpm lint(turbo run lint, 46 packages) is CI's run. Locally it was narrowed to@object-ui/core, which is the identical command CI runs for that package (eslint .) and which contains 100% of the changed source files. The three pieces that make this a measurement rather than a gap:eslint .resolved inpackages/core.--format json: 185 files, 0 errors, 513 warnings. Both changed files are in that population, each aterrors=0, warnings=0.Found on the way, filed not folded in
1.60%where half-up is1.61%#5607 —plugin-dashboard'srecordFields.tsx:189-192does(value / 100) * 100before callingformatPercent, re-introducing one call frame upstream the exact artefact objectui#4590 removed. Measured: 19,978 of 199,000 values change bit pattern and 1,108 rendered strings move, e.g.1.605at 2 decimals renders1.60%where half-up is1.61%. A concrete user-visible rendering defect, kept out of this PR.27,581 of 1,200,013percent figure with no grid named, so it still reads as a discrepancy against #4590's 27,577 #5608 —packages/core/src/utils/number-display.ts:118andnumber-display.percent-points.test.ts:96carry the bare27,581 of 1,200,013figure with no grid or call shape named, so the discrepancy reading this card removes from two sites survives at two others. Prose only,finding-labelled, unassigned.Generated by Claude Code