test(spec): the second ui/ file group's test titles state each cited decision in words instead of a tracker number (stage 21) - #21907
Merged
Conversation
…decision in words instead of a tracker number (stage 21) Stage 21 of the spec lane's share of the runtime-string burn-down: the test strings shipped under packages/spec/src, the second name-ordered ui/ group (component-record-blocks.test.ts through dashboard.test.ts). 99 literals in 6 files (98 test titles and one orderPin label that becomes an it() title) lose 105 tracker ids: 21 now state the cited decision in words, 15 get their subject back in words, and 63 drop a number the title already explains. The four CSS hex colour literals '#111' / '#222' in two widget fixtures stay: they cite no record and are input the schema under test reads, never an expected value. Text only: one line per literal, no assertion, identifier, test count, code comment or file name changes. Claude-Session: https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ Co-authored-by: Claude <noreply@anthropic.com>
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
…'s real guard, and the offset-alias title reads straight The row-cap describe in component.test.ts said a bound view fills `limit` "only when it is unset", which is the narrower sentence the record behind it corrected: the gate fills `limit` whenever the authored one is not a usable cap (`!isUsableRowLimit(authored)`). The title now says that. The offset-alias title in dashboard-compareto.test.ts is reworded so it parses on first read. Text only: two title literals, one line each. Claude-Session: https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ Co-authored-by: Claude <noreply@anthropic.com>
Brings the branch current with main for a full CI run; the merged range touches none of this branch's six test files. Claude-Session: https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ Co-authored-by: Claude <noreply@anthropic.com>
Brings the branch current with main for a fresh CI run; the merged commit touches none of this branch's six test files. Claude-Session: https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #20749
Clause-②: no
Stage 21 of this card: the next area of class (e), the test strings shipped under
packages/spec/src, as ruled in5902360492on #20513. This stage takes the second name-orderedui/group: the test files directly underpackages/spec/src/ui/fromcomponent-record-blocks.test.tstodashboard.test.ts. Those files carried 103 messages and 109 tracker-shaped ids, citing 58 records. 105 of those ids now either state what their record decided, in words (form D), or are dropped where the title already says it. Four stay: they are CSS colour literals in two widget fixtures, not citations (below). Text only: no assertion, identifier, test count or code comment changes, and no file is renamed.Census at the base (
1e18a0735c)Instruments:
census10.cjs(md59d08602ab972b4b8643c90d64d40fa41),census.cjs(md56e42a45a926d375013c32d62f16a296e),census-wide.cjs(md5c98410a19529c439adb0afbfb00026a2) anddirtable.cjs(md5dda605c54745b4a60cc14c9a686e4eff), byte-identical to the copies stages 10 to 20 used. A literal counts as a test title when its folded message is argument 0 of adescribe/it/testcall,.each/.skip/.onlychains included. Everything else is an "other" string.The base is
1e18a0735c, stage 20's landing and the claim's base. Both instruments read 764 messages / 807 ids in 159 files, the seat's reading and stage 20's head reading.ui/(this PR: 7 of the 53 files)api/system/src/)ai/contracts/The group reads 103 messages / 109 ids in 7 files, the seat's figures file for file:
ui/)component-record-blocks.test.tscomponent-reference-rail.test.tscomponent-type-vocabulary.test.tscomponent.test.tsdashboard-chart-structure-refusal.test.tsdashboard-compareto.test.tsdashboard.test.tscomponent-report-items-action-members-typed.pin.test.tssits in the same name range and carries no id. The five "other" strings are the four colour literals anddashboard.test.ts:205.ui/view.test.ts, outside the group, reads 43 ids at the base and at the head. Dark:component.test.tsreads 0 at the head while 200 of its comment lines still carry a number. Planted in scratch copies of head files: an id put into acomponent-record-blocks.test.tstitle reads 1 / 1, and an id put into adashboard-compareto.test.tscomment reads 0.#plus digits) reads the same as the gate pattern in 6 of the 7 files at the base.component.test.tsreads one more:decision batch #77, a two-digit batch number the gate pattern does not count. It leaves with the id beside it, as stages 9, 13 and 15 did with theirs.ui/reads 201 / 213, and no other file moved.How the area was chosen
ui/has no subdirectory test file with an id, so it is taken in name-ordered file groups near the ~100-id bound. Stage 20's re-cut named this group at 109 ids, and this census reads 109, so no re-cut was needed.Named for the next stages (cut from the head census, 665 / 702):
ui/213 ids. One is stage 20's keptcomponent-props-unknown-members.pin.test.ts:322, four are this group's colour literals, and 208 sit in the 45 files afterdashboard.test.ts. The next group nearest 100 runs fromdataset-filter-nested-relation-list.test.tstoview-inline-object-binding.test.ts: 29 files, 96 messages / 102 ids, 7 of them "other". Cutting two files earlier gives 98. The lastui/group is then the 16 files fromview-item-config-type.test.tstowidget.test.ts: 100 messages / 106 ids,view.test.tsalone 43.api/201, two stages.system/165, two. The files directly insrc/, 120, one.:322, one stage, with an at-tier review.The five "other" strings: four kept, one rewritten
'#111'/'#222'atdashboard-chart-structure-refusal.test.ts:94anddashboard.test.ts:124are kept. They are three-digit CSS hex colours, not placeholders for a record:colors: ['#111', '#222']in a widget'schartConfig, andpalette: ['#111', '#222']inside the free-formoptionsbag. They cite nothing. But they are not input and expected value at once, the case stage 12 dropped. Each is input that the schema under test reads (ChartConfigSchema.colorsis a string-array or string-map union), and the assertions read other things: the first parse must succeed, the second assertsoptions.stacked. So by the claim's rule they stay, and are reported. They match the gate pattern only because a short hex colour can be all digits. They are the only four such literals in the whole census.dashboard.test.ts:205is the label argument of the file'sorderPinhelper, which passes it toit(). So it is a test title one call down, and no assertion reads it. It is rewritten and declared to the text-only tool.No string in the group is a needle (an id that is the expected value of an assertion over a docblock or another file's text). The three known needles are in
ai/andcontracts/.What each id became
Every cited record was read with its comments through REST: 54 answer 200 and 4 answer 404. Four citations are cross-repo:
ui#6206(also spelledui#6206-B),ui#6207andobjectui#8221were read from objectui and answer 200.framework#2501was read under the repository's current name, as stage 18 readframework#2536. #5042 is a pull request,#4001batch 14. The four 404s were read from what landed, through the commits the stage-5 comment sweep (#20576) re-anchored them to:element:record_picker的sort/limit扁平简写:renderer 兑现、schema 未声明(#5775 实施中新测出,A 表之外的第 7 处) #6276:78f0be872, which declares the record picker's flatsort/limit(maintainer ruling 2026-08-08, direction A).page:tabsitems[].iconis the exact sibling of #9881 — live objectui reader, no.describe(), no accept-pin #9972:60e0f900a, which records the live read point ofpage:tabsitems[].iconand its accept pin.sys_activity.typea closed platform vocabulary or an author-extensible one? Both readings are true of the code today #11507:88b9d749a, which declaressys_activity.typean open, author-extensible vocabulary (maintainer ruling 2026-08-24, direction 4).record:activity's authorabletypesfilter is a CLOSED enum over a vocabulary #11507 just ruled open #11658:1a6a19c31, which opensRecordActivityProps.typesto author-contributed kinds, executing that ruling.Each of those titles already carried its decision, so the number is dropped.
component.test.ts:3037also gets its subject back: "the ruling" becomes "the open-vocabulary ruling".Stated in words:
ui/)component-record-blocks.test.ts:355record:discussion/record:chatterpair — one shared row"record:discussionis wired to the chatter row on purpose: one renderer, one accept face.component.test.ts:63titlebecomes optional, and an omitted title means the renderer derives the heading from the record.component.test.ts:89,:262component.test.ts:235type, which collides with the componenttype"typetotabStyle, because in a flat nodetypeis the component's own dispatch key.component.test.ts:122component.test.ts:406,:2932component.test.ts:649children"childrenas their one composition key, andbodyis not declared.component.test.ts:768hideEmpty/collapsible/showBorder; the renderer is unchanged.component.test.ts:889title, deliberately withheld as a second spelling oflabel"titlestays out becauselabelalready names the heading slot.component.test.ts:2078,:2142,:2899,:2908element:form, and "… through the kept map row (retired, no renderer)" twicecomponent.test.ts:3325#4001 batch D.component.test.ts:3419object-*block family entersComponentPropsMap.ui#6207component.test.ts:3468datatakes the ViewDataSchema provider object — the two spec authorities converged"object-grid.dataconverges onViewDataSchema, and the bare array is refused.component.test.ts:4499limitonly when the authored one is not a usable cap"limit, which a bound view's page size fills whenever the authored one is not a usable cap (the gate's!isUsableRowLimit(authored)).dashboard.test.ts:419dashboard.test.ts:850columnsstill declares no default … (the renderer infers it from widget spans)".default(12)would retire the renderer's span inference and switch every auto-flow dashboard to the positioned grid.Subject back in words (15 literals): "the #5068 gate" becomes "the props gate" (
component-reference-rail.test.ts:34); "the three #18305 blocks" / "object blocks" become "object-map / object-gantt / object-tree" (component-type-vocabulary.test.ts:88,component.test.ts:4295); the four "#11661 keys" titles namedefaultCollapsed/icon/description(component.test.ts:832,:848,:860,:875), because id-free sibling titles already say "the section presentation keys"; "#18639 scope fences" becomes "scope fences of thecolumnswidening"; "the twin of the #14406 census pin" becomes "the twin of the census pin that no door refuses the rule array"; "the #7750 specimen shape" becomes "the my-work specimen shape"; the four#5011 —prefixes indashboard-compareto.test.tsbecomecompareTo —where the title needs a subject, and go where it already has one (:61); "the words #5042 measured" becomes "every word authors were measured spelling … reaches …".Dropped where already stated (63 literals, 69 ids). A number goes only where the title already says its decision. Examples: "ComponentPropsMap["record:alert"] (#8744)"; "user:profile is not author-placeable (#14159, ruling B)"; "ai:chat_window is retired, refused by name (#21504)"; the six "(#6276)" picker titles, each already naming what the declaration does; "the four
object-*sortdoors — one sort orthography, the array (objectui#8221, decision batch #77, option B; #18305)"; the[#4876],[#5010],[#17779],[#20958]and[#21293]prefixes ondashboard.test.ts, each in front of the rule it names; "drill branch (#5022): …", whose sibling labels already read "… branch: …".批 17stays as a batch label in stage 18's form, andADR-0021/ADR-0049style citations are untouched.No file is renamed. None of the 7 file names carries a number.
Readers
-t/--testNamePattern(the hits aremapfile -t,docker build -t,type -t,lsof -t, and a preflight's option vocabulary).__snapshots__directory is tracked underpackages/spec, and none of the 7 files calls a snapshot matcher.localproject;packages/spec/vitest.repo-tests.jsonlists none of them.git grepat the base, across the tracked tree outside its own file. No gate, doc, filter, snapshot orscripts/check-*.mjsself-test reads one. The 6 hits:lint/src/validate-component-props.test.ts:540("the showcasemy-work: the personal work queue authorsfilters:(plural) and no$filterever reaches the wire — the grid lists every row #7750 specimen shape");sourceentry,docs/qa/platform-checklist/areas/dashboards.json:406, which anchors ondashboard-compareto.test.ts#dashboardand describes it in its own words ("dashboard widgetcompareTo:三个声明分支在 ADR-0021 dataset 路径上全部无效(两个静默丢弃,一个抛错) #5011 — compareTo converged on …"). The checklist gate looks up thedashboardsymbol, which this PR leaves in the file, and reads none of the titles.pnpm check:platform-checklistexits 0 at the head;service-analytics(dataset-compare-dimension-resolution.test.ts:74, "dashboard widgetcompareTo:三个声明分支在 ADR-0021 dataset 路径上全部无效(两个静默丢弃,一个抛错) #5011 — …");ui/stage,ui/view.test.ts:4236, the visibility twin of the message-order describe, citing 三个手写 unrecognized_keys error map 绕过 strictUnknownKeyError,把说明句夹在「哪个键错了」与处方之间 —— #5955 的修法与 #5593 的迁移都够不到 #6416 / [spec] Fold the three hand-written unrecognized_keys error maps intostrictObjectguidance — requires a set-keyed guidance form, and closes the alias-integrity gate's blind spot (#6416 direction 2) #6619.Text-only proof
Stage 10's scratch tool (
textonly10.cjs, md5d5e4801dbb4329ab1984da91e92fc47c) compares base and head file by file on three legs:#plus digits after. This stage declares one line,dashboard.test.ts:205.+and-lines are exactly the 99 planned lines as multisets, and every file keeps its line count.dashboard-chart-structure-refusal.test.tsis untouched.it.eachrow given an id VIOLATION; an undeclaredorderPinlabel changed VIOLATION; a title re-split into a+chain DIFF; the declared label reverted to base SAME; the declared label given a new id VIOLATION; a kept colour literal edited VIOLATION. The first run predicted VIOLATION for the declared-label revert: putting(#5022)back where it was reproduces the base text exactly, so SAME is the right answer, and a control that gives the label a new id was added. That run read 11 of 12..eachtitle,%s/$nameplaceholder or table row changes.Test counts: the 7 files were run at the base, in a separate base worktree, and at the head, with
--project local --project repo. Both sides read 677 tests in 7 files, all passed, with the same count and status sequence per file in 7 of 7. 469 full test names change, and each changed name equals the base name with the planned replacements applied (0 mismatches). One full name repeats 5 times on both sides: anit.eachrow indashboard.test.tswhose printed name is cut at the same point for 5 rows. Only its describe prefix changed.Changeset:
skip-changesetMeasured, not assumed:
npm pack --dry-runof@objectstack/speclists 2068 files. 0 of the 6 touched files are in it, and no*.test.tsat all. The controlssrc/ui/component.zod.tsanddist/index.mjsare in it.dist/, a new phrase and an old literal each read in 0 files. The controlUnrecognized keyreads in 42.So this PR publishes nothing, and no changeset is added.
Verification (at
ec96327761)pnpm turbo run buildover all packages: 71 / 71, through the shared verify lock (VERDICT command-exit 0).@objectstack/spec:vitest run --project local: 618 files, 18450 passed, 1 todo.typecheck: exit 0, includingcheck:test-typecheck(52 files / 246 errors / 135 pinned signatures held). Its program holds all 7 group files, counted withtsc --listFilesOnly -p tsconfig.test.json.check:generated: all 15 generated artifacts up to date, against thedist/the build above wrote.dispatch-gates --commandsderived 79 families, the same set as stage 20, and all 79 exit 0.--ranreconciles: 79 derived, 79 run, 0 NOT-MEASURED, 0 UNRUN, every family with its exit code recorded. The five roster families whose rosters sit under a touched directory were also run, and each exits 0:check:meta-url-spelling,check:spec-changes,check:authz-resolver,check:error-code-casingandcheck:filter-alias-parity. So doescheck:platform-checklist, for the checklist entry above.--no-inline-configover the 7 files reads 0 errors and 0 warnings. The population comes from ESLint's own config: 7 configured, 0 ignored. No file setsparserOptions.projectorprojectService, so no untouched file's verdict can move.check-governed-merges --test: NOT governed, 198 changed lines (+99 / -99).69ea423302: two titles reworded, one line each: the row-cap describe (component.test.ts:4499) now states the gate's guard, and the offset-alias title (dashboard-compareto.test.ts:160) reads straight. Text-only proof against the base: 7 of 7 SAME, 99 changed leaves (98 title, 1 declared). The 7 files at base and head: 677 / 677 passed, count and status sequence identical in 7 of 7, 469 changed full names, 0 mismatches against the plan. ESLint over the 7 files: 0 errors, 0 warnings. The group census still reads 4 / 4.typecheckexit 0, andcheck:nul-bytesOK. The derived gate set is the same 79 families; they were not re-run for a two-literal change.mainsince the baseRe-fetched just before this PR opened,
origin/mainwas four commits past the base (cab6396715: #21875, #21896, #21893, #21900). None touches any of the 7 files. #21893 touches 8packages/specfiles underautomation/andmigrations/, and the census overpackages/spec/srcat866683f96f(after #21893) still reads 764 / 807 with no file moved, so the merged tree reads this PR's 665 / 702. #21900 touches two morepackages/specfiles, both non-test migration entries, which this census does not count. Somainwas not merged.git merge-treeontocab6396715is clean.Acceptance notes
packages/spec/src, for examplesystem/i18n-resolver.test.ts:1982("(spec(ui):walkAddressedPageComponentsskipspage:card'sproperties.footeras a back-compat spelling, butPageCardProps.footeris a declared, rendered slot, so nodes there go unjudged; the three platform page walks disagree on positions #20940)"),ui/page.test.ts:696("(ui#6206-B, finding(spec):ElementDataSourceSchema.filter(page.zod.ts) still declares the MongoDB-styleFilterConditionSchema— the binding-level sibling of #14406 outsideComponentPropsMap, while objectui's composition seam lowers three shapes and its own pins author the tuple array #15442)"),ui/view-strictness-batch18.test.ts:91("未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001 批 18 — …"),ui/view.test.ts:4236("(三个手写 unrecognized_keys error map 绕过 strictUnknownKeyError,把说明句夹在「哪个键错了」与处方之间 —— #5955 的修法与 #5593 的迁移都够不到 #6416 / [spec] Fold the three hand-written unrecognized_keys error maps intostrictObjectguidance — requires a set-keyed guidance form, and closes the alias-integrity gate's blind spot (#6416 direction 2) #6619)") andui/view.test.ts:4793("(spec(ui): the new per-kind viewlimitand the basepagination.pageSizeare two authorable row bounds with no declared precedence — and an APPLIED default makes the react tier's own "fills it only when unset" arm unreachable #19228)").describe/it/testlines outsidepackages/spec/srcfinds 40 lines citing ids this PR handled, in 10 packages:lint25 (8 files),service-analytics3 (1),cli2 (1),platform-objects2 (1),plugin-audit2 (2),plugin-security2 (2), and one each inplugin-sharing,rest,service-automationandspec/scripts. Examples:lint/src/validate-component-props.test.ts:783("… are dispatched (spec:record:alert/record:quick_actions/record:historyhave no ComponentPropsMap row — same silent no-op mechanism #8691 closed for the rail #8744)"),service-analytics/src/__tests__/dataset-compare-dimension-resolution.test.ts:74("dashboard widgetcompareTo:三个声明分支在 ADR-0021 dataset 路径上全部无效(两个静默丢弃,一个抛错) #5011 — …"),rest/src/meta-types-schema-titles.test.ts:131("spec: the dashboard authoring form has no channel for ITEM-level property names —header.actions[]columns render as raw keys in every locale, andcolumnsdocuments a default it never declares #16458 — …"). The two[#6206]hits inplugin-securityandplugin-sharingcite objectstack#6206, a different record fromui#6206.#9198 tombstonecomment incomponent.test.ts, the#19228header abovecomponent.test.ts:4499, and the#6416/#5955docblock abovedashboard.test.ts:163. Comments are not this card's share, and none is touched here.Generated by Claude Code