Repository navigation
test(spec): the last ui/ file group's test titles state each cited decision in words instead of a tracker number (stage 23) - #21947
Merged
Conversation
…cision in words instead of a tracker number (stage 23) Stage 23 of the spec lane's share of the runtime-string burn-down: the test strings shipped under packages/spec/src, the last name-ordered ui/ group (view-item-config-type.test.ts through widget.test.ts). 100 literals in 16 files (97 test titles and 3 declared strings: one table label that prints inside for-of titles, and two expect messages) lose 106 tracker ids: 25 literals now state the cited decision in words, 20 get their subject back in words, and 55 drop a number the title already explains. No needle sits in this group. 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): |
This was referenced Oct 6, 2026
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Oct 7, 2026
… an undeclared `help` (objectstack-ai#21956) Fixes objectstack-ai#21948 Clause-②: no ## What changed `translateObject` used to put a bundle's `objects.OBJECT.fields.FIELD.help` entry on a `help` key that `FieldSchema` does not declare. The served field then failed `FieldSchema` with `unrecognized_keys`. A consumer that reads only declared keys rendered the English `description`, and the console logged one ingestion warning per such field. - **Target key, measured.** The extractor writes that bundle entry from `field.help ?? field.description` (`packages/cli/src/utils/i18n-extract.ts:1223`). `FieldSchema` refuses `help`, so on a spec-valid field the only source is `description`. The nine bundle source trees author 0 `inlineHelpText` and 0 field `help`. The nine `en` bundles carry 523 `help` entries. - **`translateField`** (`packages/spec/src/system/i18n-resolver.ts:3054`) now serves the translated help on `description` and writes no `help` key. `inlineHelpText` is not touched. - **Precedence: ADR-0029 D9.2a**, the resolver's own rule, applied through the existing `valueOverridesPackagedBase` predicate. There is no second comparison. The catalog applies only while the served field's `description` equals the packaged field's. - No packaged base supplied: the catalog applies (the conservative edge objectstack-ai#8284 established). - A field the base does not declare counts as diverged, which is `packagedPart`'s convention. The new finder `packagedObjectField` (`:1434`) reads both field-map shapes. - A field's `label` is unchanged and stays a flat `catalog ?? document`, as its existing pin scopes it. - **`ObjectFieldLike`** (`:2453`) drops its `help?: string` member. This is safe: - its `[key: string]: any` index signature still accepts and types a `help` key, so a caller that writes or reads one still compiles (probe below); - `packages/spec/api-surface/system.json` records only `ObjectFieldLike (interface)`, not its members, and `check:api-surface` stays green; - the one in-repo importer (`service-analytics`, which reads `options` only) still typechecks. - The `translateObject` docblock no longer says it translates a field's `help`. A new section states the target key and the D9.2a precedence. - `.changeset/21948-spec-field-help-served-on-description.md`: `@objectstack/spec` `patch`. ## Clause-② — measured `no` - No Zod schema, parse or export changed. These all stay green: `check:authorable-surface`, `check:api-surface`, `check:export-origins`, and `check:generated` (15 artifacts up to date). - **Type probe** (scratch, not committed), compiled against the rebuilt `dist/system/index.d.ts`, exit 0: - `const legacy: ObjectFieldLike = { name: 'x', help: 'legacy' }` compiles, and so does reading `legacy.help`; - a declared member still refuses a wrong value (an `@ts-expect-error` on `label: 42` is consumed); - `const proof: number = ({} as ObjectFieldLike).help` compiles, which shows the probe read the rebuilt declaration. - **Control leg:** the same probe against a copy of that `.d.ts` with BASE's `help?: string` put back gives exit 2, with exactly one error: TS2322 on the `proof` line. Writing and reading `help` compile under both declarations. - So no value the type or the schemas used to accept is refused now. The one type-level delta is that `ObjectFieldLike['help']` is now read through the index signature (`any`) instead of `string | undefined`. That is stated here for the at-tier review. ## Measured All at HEAD `3ad2f22bed` unless stated. **Corpus at the resolver seam (scratch script, not committed).** Every object in `packages/platform-objects/scripts/i18n-extract.config.ts` (48 objects, 617 fields), with that package's real bundles, using each object as its own packaged base: | | served `help` keys | `help` refused by `FieldSchema` | `sys_user` fields with `help` | zh-CN `description` equal to the bundle entry | |---|---|---|---|---| | BASE behaviour (ablation leg 1 below) | 332 | 332 | 18 of 26 | 0 | | HEAD | 0 | 0 | 0 of 26 | 332 | - At HEAD in zh-CN, `sys_user.two_factor_enabled.description` = `该用户是否已启用双因素认证。由 better-auth 的 \`twoFactor\` 插件维护。`. - In `en`, 0 descriptions change from source, because the en entries repeat the source. - **NOT MEASURED: the HTTP door** (`GET /api/v1/meta/object/sys_user`). The spec change invalidates the showcase build closure: 62 of 63 turbo tasks miss the cache. The pins and the corpus run read the same `translateMetadataDocument` dispatch the REST read calls. **Pins** (`packages/spec/src/system/i18n-resolver.test.ts:3552`, 9 cases): - a zh-CN served field carries no `help`, has the translation on `description`, and parses with no `unrecognized_keys`; - the untranslated control is unchanged; - a field with both `description` and `inlineHelpText` gets the translation on `description`, and `inlineHelpText` is untouched; - a diverged `description` is kept in zh-CN and en, through the type dispatch, while the undiverged sibling is translated; - a field the base does not declare counts as diverged; - with no packaged base (`undefined`, `null`, or omitted) the catalog applies; - an absent `description` is filled by the catalog; - array-shaped fields are judged against an array-shaped base; - the input is not mutated. No existing pin asserted a served field `help`. I searched every test outside the bundle suites, so none had to move. **Ablation**, run on the committed head. Each leg used `scripts/ablation-replace.mjs` in WRAP mode plus a trap. Predictions were written down before the run. Both legs were restored, with the restored blob equal to HEAD (`a8eade91`) and `git diff HEAD` empty: | leg | mutation (anchor 1 → 0 on disk) | predicted | observed | |---|---|---|---| | 1 | restore BASE's two lines (write `next.help`, never `description`) | 7 failed / 2 passed (control and no-mutation stay green) | `Tests 7 failed \| 2 passed` | | 2 | flat overlay (the D9.2a comparison replaced by `true`) | 3 failed: the diverged, undeclared-field and array cases | `Tests 3 failed \| 6 passed` | - Leg 1 sample: `expected 'Whether two-factor authentication is …' to be '该用户是否已启用双因素认证。…'`. - Leg 2 sample: `expected '该用户是否已启用双因素认证。…' to be 'Edited by the tenant.'`. **Tests** - `@objectstack/spec`, full local project: `Test Files 619 passed`, `Tests 18480 passed | 1 todo`. - `pnpm --filter @objectstack/spec typecheck`: exit 0. Its test layer compiles under `tsconfig.test.json` with the identity-pinned debt held. - `@objectstack/service-analytics`: `typecheck` exit 0. The three dimension/label suites that call `translateObject`: `Tests 53 passed`. - Targeted eslint over the two changed `.ts` files: 0 errors and 0 warnings. That run is not the repo-wide lint, which is CI's. **Gates.** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran` derived 85 families: 84 ran with exit 0 and 1 is NOT MEASURED. - The NOT MEASURED one is `pnpm check:dual-build-cjs-loads`, which exits 3 with `PREREQUISITE NOT MET` because 78 packages have no `dist/`. - Narrowed in its place: all 19 `require` entries of `@objectstack/spec`'s `exports` load from the rebuilt `dist`, and `system.translateObject` is a function. - `pnpm check:lean-entry-closure` first answered exit 3 (`objectql/core` unbuilt). After `turbo run build --filter=@objectstack/objectql...` it answered exit 0, and that is the recorded code. **Ships:** `npm pack --dry-run` of `@objectstack/spec` lists `dist/system/index.js`, `.mjs` and `.d.ts`. Both runtime files carry `packagedObjectField` and no `next.help = translatedHelp`. **Base:** origin/main moved to `a3bd157730` (objectstack-ai#21947, test titles under `packages/spec/src/ui/` only). None of this PR's files is touched, so it is not merged. ## Known readers in objectui objectui at `.objectui-sha` `0abd4f9f`, read-only. No objectui file is edited here. - `packages/plugin-form/src/ObjectForm.tsx:1033` and `packages/plugin-form/src/sectionFields.ts:311` (`field.help || field.description`), and `packages/app-shell/src/utils/resolveActionParams.ts:714` (`param.helpText ?? field.help ?? field.description`). - All three fall back to `description`, so they render the same translated text, and their `help` arm is now dead. Retiring those arms is objectui's job. - The ingestion warning is `packages/core/src/utils/reference-keys.ts:362`, reached through the `no-declared-twin` arm (`:415`) of `canonicalizeRetiredFieldKeys`. It fires for any undeclared key on a served field def, so it goes quiet once no `help` is served. ## Acceptance notes None of these is addressed in this PR. 1. **Studio `saveFields` write-back.** NOT MEASURED; this is a read-only inference. - objectui `packages/app-shell/src/services/MetadataService.ts:898` to `:939` carries per-field server keys from the translated read back into the object PUT. - `help` is not in objectui's `RETIRED_FIELD_KEYS` (`packages/types/src/internal/retired-field-keys.ts`). So a field save on a platform object with bundle `help` entries should have sent a key `FieldSchema` refuses. - This PR removes the source. - Carrier: this PR. Reach would need one measured PUT. 2. **The extractor's `field.help ??` arm** (`packages/cli/src/utils/i18n-extract.ts:1223`) reads a key `FieldSchema` refuses, so it is dead on every spec-valid field. Carrier: `domain:cli`; none in flight. 3. **Field `placeholder` is never overlaid.** `FieldTranslationSchema` declares `placeholder`, and the extractor emits `objects.OBJECT.fields.FIELD.placeholder` (`:1224`), but `translateField` never overlays it. The nine shipped bundles carry 0 field-level placeholder entries (the 4 per locale are action params), so it is dormant. Carrier: none. 4. **`inlineHelpText` has no translation path.** The extractor never reads it, so an authored one is never offered for translation. The nine bundle sources author 0 of them. Carrier: none. 5. **Docs line.** `content/docs/protocol/kernel/i18n-standard.mdx:166` lists a field's `label` / `help` / `placeholder` as display labels, but `FieldSchema` declares no `help`. Carrier: none. --- _Generated by [Claude Code](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 23 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 last name-orderedui/group: the 16 id-bearing test files directly underpackages/spec/src/ui/fromview-item-config-type.test.tstowidget.test.ts. Those files carried 100 messages and 106 tracker ids, citing 53 records. All 106 now either state what their record decided, in words (form D), or are dropped where the title already says it. No needle sits in this group. Text only: no assertion, identifier, test count or code comment changes, and no file is renamed.Census at the base (
9e33ee7c59)Instruments:
census10.cjs(md59d08602ab972b4b8643c90d64d40fa41),census.cjs(md56e42a45a926d375013c32d62f16a296e),census-wide.cjs(md5c98410a19529c439adb0afbfb00026a2) anddirtable.cjs(md5dda605c54745b4a60cc14c9a686e4eff), byte-identical to the copies stages 10 to 22 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 worktree was cut from
origin/mainat9e33ee7c59, the claim's base. Both instruments read 571 messages / 604 ids in 127 files, the seat's reading and stage 22's head reading.api/system/src/)ui/(this PR: 16 of the 21 files)ai/contracts/The group reads 100 messages / 106 ids in 16 files, the seat's figures file for file:
ui/)view-item-config-type.test.tsview-metadata-schema.test.tsview-metadata-type.test.tsview-overlay-options-bag.test.tsview-overlay-options-type.test.tsview-overlay-owner-hidden-retirement.test.tsview-overlay-viewkind-arm.test.tsview-overlay-viewkind-type.test.tsview-strictness-batch18.test.tsview-submit-redirect-url.test.tsview-union-branch-focus.test.tsview-union-diagnostics.test.tsview-union-retirement-prescription.test.tsview.test.tswidget-i18n-retirement.test.tswidget.test.tsThree more test files sit in the same name range and carry no id (
view-item-owner-hidden-retirement.test.ts,view-list-tabs-retirement.test.ts,vocabulary-derivation.test.ts). The three "other" strings are rewritten and declared to the text-only tool: the table label atview-union-branch-focus.test.ts:139, which prints inside twofor … oftest titles, and the expect messages atview.test.ts:4099andwidget-i18n-retirement.test.ts:135.ui/notification.test.tsandapi/api-error-code-type.test.ts, outside the group, read 1 id each at the base and at the head. Dark:view.test.tsreads 0 at the head while 92 of its comment lines still carry a number. Planted in a scratch tree: an id put into awidget.test.tstitle reads 1 / 1 (title:describe), and an id put into aview-metadata-type.test.tscomment reads 0.#plus digits) reads the same as the gate pattern in 15 of the 16 files at the base.view.test.tsreads 2 more, and keeps them at the head: the CSS colours'#00cc00'(:2770) and'#22c55e'(:3537), fixture values that cite nothing.ui/reads 7 / 7, 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 22's re-cut named this group at 106 ids, and this census reads 106, so no re-cut was needed.view.test.ts(43 ids) is one file inside one text-only proof here, so it is not split.ui/after this PR reads 7 / 7, all kept items: stage 20'scomponent-props-unknown-members.pin.test.ts:322, stage 21's four colour literals (dashboard-chart-structure-refusal.test.ts:94,dashboard.test.ts:124), and stage 22's two needles (notification.test.ts:123,strictness-batch14.test.ts:395).Named for the next stages (cut from the head census, 471 / 498):
api/, 201 ids in 40 files, with no subdirectory. Its first name-ordered group near the bound isai-agents-envelope.test.tsthroughpackage-lifecycle.test.ts: 27 files, 100 messages / 106 ids (95 / 101 titles, 5 / 5 other:auth.test.ts,discovery-environment-subset.pin.test.tsand three inexport-job-family-retirement.test.ts). The second isplugin-rest-api.handler-status-retirement.test.tsthroughzod-issues-to-fields.test.ts: 13 files, 89 / 95,protocol.test.tsalone 50.system/167, two stages. The files directly insrc/, 120, one.:322and stage 22's two. One stage, with an at-tier review.What each id became
Every cited record was fetched with all its comments through REST, and its decision was read from its ruling, ACCEPT and landing comments: 53 records, 51 answer 200 and 2 answer 404. Five citations are objectui's and were read from objectui:
objectui#5233,objectui#2231(cited bare atview-strictness-batch18.test.ts:309),objectui#6237(cited bare atview.test.ts:949),objectui#5435andobjectui#3289. Three same-number records in the other repository were fetched first and set aside:objectstack#2231is a version-packages PR,objectstack#6237a datasource PR, andobjectui#2998a form PR;framework#1894 / #2998are this repository's #1894 and #2998 under its old name. The two that answer 404 were read from what landed:columnStateto the view-metadata surface as an explicit runtime-only overlay key — unblocks objectui#5233's ruled patch-only write #9933, from its landing commitd5552ca13f("admit columnState as an explicitly runtime-only view-overlay key") and the CHANGELOG entry ford5552ca;UserActionsConfigSchemaadoptsgroup/hideFields/rowColor— the three toolbar affordancesListViewhonours but no spec-valid document can declare (ruled A on objectui#5435) #11195, from PR spec(ui): UserActionsConfigSchema adopts group / hideFields / rowColor (ruled A on objectui#5435) #11458, the PR that closed it ("UserActionsConfigSchema adopts group / hideFields / rowColor (ruled A on objectui#5435)").One citation names the wrong record, and the titles now state what landed instead.
#3896 close-out(twice inview.test.ts) names #3896, the sharing-rule criteria card, which records no decision about these keys; the two titles state the decision from the landed tombstones ofform.defaultSortandview.responsive/view.performance, as stage 20 did foraction.test.ts.Where a record's first decision was corrected later, the title follows the correction:
FormViewSchema.groupsis declared as "alias to sections" but nothing folds it — every consumer reads onlysections#6926: its first triage direction retired thegroupsalias; the measurement found live consumers, and the maintainer re-ruled A, a fold at the producer. The two titles say "the producer-sidegroupsfold" and "folds ontosections".publicPickerreports the CONTAINER branch's diagnostic — the author is told to fixviewKind/config, not the key they typed #7510: the "[A bad key inside a form field'spublicPickerreports the CONTAINER branch's diagnostic — the author is told to fixviewKind/config, not the key they typed #7510] ⛔ the acceptance face did not move" describe sits beside two ruled moves recorded in its own comments, so the title now names what did not move it: "⛔ the branch focusing did not move the acceptance face".Stated in words:
ui/)view-metadata-schema.test.ts:95{}— the pin this line used to make, reversed by the identity precondition".strip()is untouched.view-metadata-schema.test.ts:125defineView's guidance.view-metadata-schema.test.ts:215objectui#5233view-metadata-schema.test.ts:413columnState-only patch (the patch-only write the console persists)"persistViewPatchstores the patch only, not the merged base.view-overlay-owner-hidden-retirement.test.ts:335view-overlay-viewkind-arm.test.ts:102view-strictness-batch18.test.ts:91view-strictness-batch18.test.ts:149.passthrough()was removed a CLOSED parent too".passthrough()calls go.view-strictness-batch18.test.ts:364ViewItemSchemaand a reopened wire member in the union.view-strictness-batch18.test.ts:403sort[]closed again with no declaredid.view-union-diagnostics.test.ts:246view.test.ts:342viewModewith exactly the granularities objectui'sGanttViewhonours, measured, not invented (the spec half of objectui#5074's ruling).view.test.ts:441sortclause is retired — one spelling, the array"view.test.ts:873objectui#6237view.test.ts:949FormSectionConfigis split, so tabbed sections take a predicate and wizard steps carry none.objectui#2231view.test.ts:2876677b591movedprefixand the{ type, field }summaryform into the spec, closing objectui's local.extend().view.test.ts:3144form.defaultSortwas removed because nothing read it.objectui#5435view.test.ts:3386group/hideFields/rowColor, with the defaults copied fromListView's reads.view.test.ts:3826view.test.ts:3847view.test.ts:4099(expect message)HttpMethodTypewas renamed toHttpMethodSubset"HttpMethodkeeps its name and its wire contract.view.test.ts:4708type: 'calendar'axis is NOT gated by theallowedVisualizationscheck (ruled: a completeness warning)"allowedVisualizationsonly; thetype: 'calendar'route is carried at warning bycheckViewCompleteness.view.test.ts:4793pagination.pageSizeis the one bound; no per-kindlimiton the view configs"pagination.pageSize; the per-kindlimitwas removed before it shipped.widget-i18n-retirement.test.ts:70objectui#3289widget-i18n-retirement.test.ts:196errorslot is exactly the one objectui renamed its own slot onto, with no alias"errorMessageslot became the spec'serror, with no alias, and the form renderer produces it.Subject back in words (20 literals): "(binding pair, #7741)" becomes "(the object + viewKind binding pair)"; "union error behaviour (#5014)" becomes "union error behaviour (where a branch prescription gets buried)"; the five
#7496prefixes become "the ruled redirecturlshape —" (twice) and "ruled bullet 1 / 2 / 3 —", the file's own name for the ruling's three bullets; "the pre-#7510 ranking" becomes "the pre-fix ranking"; "the #4001 wrap prescription" becomes "thedefineViewwrap prescription"; the acceptance-face describe atview-union-branch-focus.test.ts:261(above); "the #6926 fold" becomes "the producer-sidegroupsfold"; "(#7025 membership)" becomes "and the union corpus pins it accepted"; "(#8321/#12174)" becomes "(a negative or fractional scale)", what that test probes; "the exact declaration #9340 exists to make legal" and "the gap #9340 closes" name "this block"; "(acceptance criterion, objectstack#11195)" becomes "(the acceptance criterion for adopting the three keys)"; "(#7176 rides …)" becomes "(the retirement rides …)"; "the axis #13817 does not gate" becomes "the axis theallowedVisualizationscheck does not gate"; "zero holders after #5055" becomes "after the widget + i18n retirement"; "#5055 — the one surviving shape" becomes "the widget retirement — the one surviving shape".Dropped where already stated (55 literals, 57 ids). A number goes only where the title already says its decision. Examples: the four
[#19920]prefixes ("… typed by its arm, not unknown", "… a parsed view body, not unknown") and[#19871]; the six[#20051]describes on theoptionsbag and the one inview-union-retirement-prescription.test.ts; the eight#20186describes ("a column-less list PATCH is judged by the list member", "each member judges ONE viewKind", …); the three[#6391]describes, three[#7510]titles and the[#21180]table label ("the retiredpublicPickerkey itself"); "(#3095)", "(#5074)" after ".strip()round-tripping is untouched", "(#9933)" after "runtime-only overlay key", and theview.test.tstails(#15469),(#6926),(#12174),(#19088),(#7084),(#9340 — …),(#17499),(#18791),(framework#1894 / #2998),(#5073 — …)x2,(#8010),[#4688],[#4691],(#6416 / #6619),(#17063),(#16885),(#13817)and(#16577). The batch label批 18stays, in stage 20's "批 19, unknown keys refused" form on the file's first describe and bare on the other four.W2stays: the file's own header defines W1 and W2. The commitce70876estays in "(measured on origin/main ce70876)": a commit, not a tracker id.No file is renamed.
Readers
-t/--testNamePattern(the 3 hits aredocker build -t,type -tandlsof -t).__snapshots__directory is tracked underpackages/spec, and none of the 16 files calls a snapshot matcher.repoproject (packages/spec/vitest.repo-tests.json); all run inlocal.git grepat the base, across the tracked tree outside its own file. No gate, doc, filter, snapshot, QA checklist entry orscripts/check-*.mjsself-test reads one. The 16 hits are windows that share wording with code comments and one CHANGELOG line: 15 comments in the migration registry, its semantic entries andview-list-tabs-retirement.test.tsread "(ruling B on [Decision] 一次退役,要写一条记录还是两条?—— 迁移条目的 D2/D3 约定,两处成文相互矛盾 #17152)", andpackages/spec/CHANGELOG.md:30342reads "runtime-only overlay key (spec: admitcolumnStateto the view-metadata surface as an explicit runtime-only overlay key — unblocks objectui#5233's ruled patch-only write #9933)".columnStatesection ofview-metadata-schema.test.tsas "§spec: admitcolumnStateto the view-metadata surface as an explicit runtime-only overlay key — unblocks objectui#5233's ruled patch-only write #9933": a code comment atpackages/spec/scripts/strictness-ledger.test.ts:380and theview.zod.tsrow ofdocs/audits/2026-07-unknown-key-strictness-ledger.md. Neither matches a string; both point a reader at the section, which still carries "columnState — runtime-only overlay key" in its title and its banner comment. A code comment and an audit record are not this card's share, so neither is edited.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 three lines:view-union-branch-focus.test.ts:139,view.test.ts:4099andwidget-i18n-retirement.test.ts:135.+and-lines are exactly the 100 planned lines as multisets, and every file keeps its line count.it.eachrow given an id VIOLATION; an undeclared expect message changed VIOLATION; a title re-split into a+chain DIFF; a declared expect message reverted to base SAME; a declared expect message given a new id VIOLATION; the declared table label given a new id VIOLATION; a template-literal title given a new id VIOLATION..eachtitle changes,view-overlay-viewkind-arm.test.ts:102, a%stemplate whose placeholder and rows are untouched. The table label atview-union-branch-focus.test.ts:139feeds twofor … oftemplate titles, which print it whole. The template-literal title at:173changes only its text before${label}.Test counts: the 16 files were run at the base, in a separate base worktree, and at the head, with
--project local --project repo. Both sides read 862 tests in 16 files, all passed, with the same count and status sequence per file in 16 of 16. 574 full test names change, and each changed name equals the base name with the planned replacements applied (0 mismatches). No full name repeats on either side.Changeset:
skip-changesetMeasured, not assumed:
npm pack --dry-runof@objectstack/speclists 2068 files. 0 of the 16 touched files are in it, and no*.test.tsat all. The controlssrc/ui/view.zod.ts,src/ui/widget.zod.tsanddist/index.mjsare in it.dist/, a new phrase and an old one each read in 0 files. The controlUnrecognized keyreads in 42.So this PR publishes nothing, and no changeset is added.
Verification (at
75022207b3)pnpm turbo run buildover all packages: 71 / 71, through the shared verify lock (VERDICT command-exit 0).@objectstack/spec:vitest run --project local: 619 files, 18471 passed, 1 todo.typecheck: exit 0, includingcheck:test-typecheck(52 files / 246 errors / 135 pinned signatures held). Its program holds all 16 group files, counted by path 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 22, 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.--no-inline-configover the 16 files reads 0 errors and 0 warnings. The population comes from ESLint's own config: 16 configured, 0 ignored. No file setsparserOptions.projectorprojectService, so no untouched file's verdict can move.check-governed-merges --test: NOT governed, 200 changed lines (+100 / -100).mainsince the baseRe-fetched just before this PR opened,
origin/mainwas four commits past the base (1f0469655f: #21939, #21937, #21943, #21928). They touch 32 files, none of the 16; two are underpackages/spec(a step-18 semantic migration entry and the migration registry, neither a test file). Somainwas not merged. The census on that tree still reads 571 / 604 in test files and 0 elsewhere.git merge-treeonto1f0469655fis clean, and none of the 8 open PRs touches any of the 16 files.Acceptance notes
{{record.FIELD}}title.view-submit-redirect-url.test.ts:187keeps its literal placeholder after "ruled bullet 2 —"; this body spells it withFIELDbecause the platform strips angle-bracket fragments from PR text.packages/spec/src,api/api-error-code-type.test.ts:71("[[finding] four more exported spec types resolve tounknownwhile their TSDoc promises a shape —ViewMetadataParsed,InlineAction,AssembledViewArtifact,JoinedReportBlock(the #19871 class, other sites) #19920] …"),stack.test.ts:1510("(spec: retire thepagemember of the list-viewtypeenum and itspageNamemount — enforce-or-remove, the objectui render half was never built (maintainer 2026-09-09 「撤」) #17063)"),system/stack-server.test.ts:93andsystem/translation.test.ts:672/:767("(未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001)").metadata-protocol11,objectql8,spec/scripts8,lint6,rest4,plugin-auth3,cli2, and one each inplugin-security,plugin-sharing,qa/dogfoodandservice-automation), each package's share under the [finding] runtime warnings outside the migration ledger print tracker numbers to authors and operators: theAutomationEngineresumeAuthority boot warning (#3801/#5561/#3823) and two objectql data-event warnings (#4639/#4626) #20513 lane children. The threeplugin-authtitles cite objectstack's organization/create 的闸门读的是被降级的 OS_MULTI_ORG_ENABLED,不是权威的 OS_TENANCY_POSTURE —— 只设权威 knob 的有墙部署,引导式「创建工作区」是死路 #5233, a different record fromobjectui#5233.columnStateto the view-metadata surface as an explicit runtime-only overlay key — unblocks objectui#5233's ruled patch-only write #9933" cross-references above, the[#7741]/[#21180]corpus notes inview-union-branch-focus.test.tsandview-union-diagnostics.test.ts, and the#5055banners inwidget-i18n-retirement.test.ts. Code comments are not this card's share.Generated by Claude Code