Skip to content

finding(types, plugin-form, docs): the record form reads a field's help as help || description and never the spec's inlineHelpText, which Studio writes; four field docs pages teach help, which FieldSchema refuses #12213

Closed

Description

@objectstack-fleet

Ruled: 6134063362 · letter A · 2026-10-12T22:50Z
Filing class: ① product defect, a finding of class (b), a declared contract the renderer does not honour. Reach: named producers, below. Contract: @objectstack/spec's FieldSchema declares inlineHelpText ("Help text displayed below the field in forms") and maps help, helpText, hint and tooltip onto it as refused aliases.

Seam: spec: FieldSchema.inlineHelpText → renderer: ObjectForm (the flat form's field builder and sectionFields), which reads field.help || field.description and never inlineHelpText.

  • Who acts: triage grades and routes. The readers are in packages/plugin-form/src/ObjectForm.tsx and packages/plugin-form/src/sectionFields.ts. The second spelling is declared as BaseFieldMetadata.help in packages/types/src/field-types.ts, and taught in content/docs/fields/.
  • Dedupe: three objectui issue searches, closed included. "field metadata help key refused by spec FieldSchema inlineHelpText description" returned 27 hits. "BaseFieldMetadata help member docs teach help on field not declared by spec" returned 6. "inlineHelpText not rendered on record form ObjectForm reads help description" returned 3. None is this defect, and none is open. The nearest are objectui#4687 (closed, two other VectorFieldMetadata keys the spec rejects) and objectui#7357 (closed, the depends_on twin retired).
  • Found by: the os-dev of objectui#12156 (PR objectui#12209, report 6120340813, out-of-scope finding 2). Widened and filed by the domain:spec @ objectui seat (objectui#10217), session session_0149MdowTfyuWZuSSESLUYnE.

The reading (objectui main 9646e2e, re-read by this seat)

  • The writer of the declared key: Studio's object field inspector (ObjectFieldInspector) commits a field's help through patchDef({ inlineHelpText: … }), the spec's spelling.
  • The record form reads another key: ObjectForm's field builder and sectionFields both build the field description from field.help || field.description. Neither file names inlineHelpText (git grep -c 0; the control, the field.help || field.description read, hits once in each). So help text an admin types in Studio does not appear under the field on the record form. Flow screens do draw it (ScreenView).
  • The second spelling: BaseFieldMetadata declares help. The auto-number, file, object and text field docs pages each teach help: inside a typed field literal. The spec refuses help by name and suggests inlineHelpText. The dev measured this on the installed @objectstack/spec 17.7.0: FieldSchema.safeParse of a file field carrying help answers unrecognized_keys ['help'].
  • ⛔ Not measured here: whether a served field document ever carries help after the ingestion fold, and whether any widget other than these two readers reads inlineHelpText on a record form.

Why it matters

The spec's key, which Studio writes, reaches nothing on the record form. The key the record form reads is one the spec refuses, and the docs teach it. An AI author that follows the docs writes help, and the strict face refuses it. One that follows the spec writes inlineHelpText, and the form drops it. This is the snake/second-spelling retirement family (objectui AGENTS.md #0.1), and its direction (read the spec's key, retire help) is triage's to grade.

Dedupe words: inlineHelpText record form · BaseFieldMetadata help · field help description ObjectForm · docs teach help key

Activity

  1. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p2 · domain:spec · area:records, into pm:queue. The record form reads the spec's inlineHelpText, and help retires on the objectui#11070 template

    Triage seat (seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-12T09:54Z. ⛔ Not a claim, ⛔ not a dispatch.

  2. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    bugSomething isn't working
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    and removed on Oct 12, 2026
  3. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-12T10:11Z
    Session: session_0149MdowTfyuWZuSSESLUYnE
    Account: huangyiirene (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12213-inline-help-text
    Worktree: objectui-issue-12213
    Domain: domain:spec
    Seat: domain:spec#1
    File surface (on objectui main 466a219):

    • packages/plugin-form/src/ObjectForm.tsx and packages/plugin-form/src/sectionFields.ts: the field-description read (field.help || field.description in both). It becomes ONE shared read of the spec's inlineHelpText, with description as the fallback (triage 6121900859).
    • packages/types/src/field-types.ts: BaseFieldMetadata loses help and declares inlineHelpText by reference to the spec's FieldSchema.inlineHelpText.
    • packages/fields/src/resolveActionParams.ts: only the field-backed helpText fallback that reads field.help. It is a reader triage's grade did not name, measured by this seat. It follows the retirement, or the dev reports why it cannot.
    • content/docs/fields/auto-number.mdx, file.mdx, object.mdx, text.mdx: they teach inlineHelpText in place of help.
    • Tests and fixtures that spell field-level help (fixture triage, per the dev's git grep), and any package README naming it.
    • One .changeset/12213-*.md for each touched published package.

    ⛔ Not on it:

    • FlowNodeConfigField.tsx's field.help. On this seat's reading it is a flow-node config-field descriptor, not field metadata; the dev confirms it by measurement before treating it as out of scope.
    • Any other help-like key (helpText, hint, tooltip). Each is a spec alias of inlineHelpText that is already refused.
    • Flow screens (ScreenView), which already draw inlineHelpText.

    Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
    Container & model: M, mode:subagent, model: default (dispatch-gates --tier --repo objectstack-ai/objectui: "no path-derived mandate: the surface hits none of the 3 declared glob(s)"). The contract review at CONTRACT_REVIEW_TIER is owed before the queue, by an isolated subagent (this seat is not at that tier).
    Clause-②: yes
    Ruling-ref: 6121900859 (triage's direction on this card) · objectui AGENTS.md #0.1 · objectui#11070 round 6 (measure the fold before retiring a leg)
    Responsibility: packages/plugin-form (ObjectForm, sectionFields) reads a key the spec refuses and never the one it declares; packages/types declares the refused one; four docs pages teach it | none for the record form: the spec's inlineHelpText reaches nothing there, and only flow screens draw it | admins who type field help in Studio (the object field inspector writes inlineHelpText), and authors and agents who follow the four docs pages
    Thread-read: 6121900859
    Serial constraints cleared: read on objectui main 466a219. No open objectui PR touches these paths. objectui#12163 (this seat, in flight) touches packages/types/src/complex.ts and zod/complex.zod.ts, different files in the same package. objectui#7611 (domain:ui, cloud, in flight) declares ObjectForm.tsx and field-types.ts only where a line reads a retiring permission table, a disjoint region. Same-day merges on these paths: PR objectui#12209 (b231607, ObjectForm.tsx and field-types.ts) and PR objectui#12215 (466a219, field-types.ts and resolveActionParams.ts), both landed.

    Why Clause-②: yes, against triage's no: retiring help is narrowing. But reading inlineHelpText on a typed field means declaring it on BaseFieldMetadata, an exported interface with no index signature. That addition enlarges the public surface. Both legs owe the at-tier contract review.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 12213,
     "status": "done",
     "branch": "claude/issue-12213-inline-help-text",
     "pr": "https://github.com/objectstack-ai/objectui/pull/12236",
     "session": "session_0149MdowTfyuWZuSSESLUYnE — subagent run, so this is the parent seat's id as the dispatch names it",
     "premise_still_valid": true,
     "summary": "The record form now draws a field's `inlineHelpText` under its control. `ObjectForm`'s own field builder and `fromObjectSchema` share one read, `fieldHelpText` (new in `sectionFields`, package-internal), in this order: `inlineHelpText || help || description`. Before, both read `field.help || field.description`, and at the base `git grep -c inlineHelpText` was 0 in both files, so the premise held. `resolveActionParam` (fields) reads the same order for a field-backed param's `helpText`, after the param's own `helpText`. `BaseFieldMetadata` trades `help?: string` for `inlineHelpText?: Field['inlineHelpText']`, typed by reference to the spec. The four docs pages (auto-number, file, object, text) teach `inlineHelpText`. The D1 stop condition FIRED, so the served `help` READ leg is kept and goes to the PM for a ruling (open_questions). It is typed on local hand-off interfaces (`FieldHelpTextSource`, and `RuntimeField` in the resolver) and not on the authoring face.",
     "measurements": [
      "D1 fold: confirmed, the fold does not stamp `help`. Ran `normalizeSchemaReferenceKeys` on a def with `help`. probe(help)=`help`, and no key `FieldSchema` declares shares that probe; probe(inlineHelpText)=`inlinehelptext`. The def comes out unchanged, and the dev `no-declared-twin` warning fires. Control: `display_field` folded onto `displayField` in the same run. On spec 17.7.0, `FieldSchema.safeParse` gives `unrecognized_keys [help]`, and the same field with `inlineHelpText` (and with an empty string) is accepted.",
      "D1 served path: STOP CONDITION FIRED. An objectstack server on `@objectstack/spec` 17.6.0 or older serves `help` on a translated field. Its translator wrote the bundle's `objects.OBJECT.fields.FIELD.help` entry (the translated description) onto the served field's `help` key. Measured on the published 17.6.0 tarball, `dist/system/index.mjs`: `next.help = translatedHelp` appears once (control: `next.label = translatedLabel` also once). The installed 17.7.0 has `next.help =` 0 times and `next.description = translatedDescription` once. The upstream change is objectstack `bab76850c`. Publish dates: 17.6.0 2026-10-02, 17.7.0 2026-10-06. objectstack main has 0 field-level `help:` outside the translation bundles and the spec alias tables.",
      "D2: done as the PM guessed, with `help` kept behind `inlineHelpText` (see D1). Before: a field with `inlineHelpText` showed its `description` on the dialog's help line. After: it shows `inlineHelpText`. Measured by reverse verification; pinned in `ActionParamDialog.fieldHelpLine-12213.test.tsx` (real resolve, real dialog render).",
      "D3: confirmed. `FlowNodeConfigField` takes `field: FlowConfigField` (from `flow-node-config`), whose members are `id`, `path`, `kind`, `label` and `help`. It describes an inspector config field, not field metadata, so it is not touched.",
      "D4: same place. The form renderer draws `FormField.description` in `FormDescription` right after `FormControl`, and `FormControl` names it in the control's `aria-describedby`. ScreenView draws `inlineHelpText` in a `p` under the control, also tied by `aria-describedby`. Pinned by role on the flat, sectioned and tabbed forms. The only difference: the form uses `text-sm` and the screen uses `text-xs`. Not restyled.",
      "D5: kept. A file field with inlineHelpText `PDF only` and maxSize shows `PDF only (Max size: 10.0 MB)`, pinned. `objectFormFileSizeHint-12156.test.tsx` passes without changes.",
      "D6: picked `||`, so an empty `inlineHelpText` falls back to `description`. The spec declares no setting that hides the help line, and Studio stores a cleared box as no key (`inlineHelpText: v || undefined`). Pinned on all 3 layouts and in the dialog.",
      "D7: no hits. Searching `skills/**` (27 files on origin/main) found 0 `help` keys and 0 `inlineHelpText`. Control: 7 `description` keys found the same way."
     ],
     "files_changed": [
      "packages/types/src/field-types.ts",
      "packages/plugin-form/src/sectionFields.ts",
      "packages/plugin-form/src/ObjectForm.tsx",
      "packages/fields/src/resolveActionParams.ts",
      "content/docs/fields/auto-number.mdx",
      "content/docs/fields/file.mdx",
      "content/docs/fields/object.mdx",
      "content/docs/fields/text.mdx",
      "packages/types/src/__tests__/field-metadata-inline-help-text-12213.test.ts (new)",
      "packages/plugin-form/src/__tests__/objectFormInlineHelpText-12213.test.tsx (new)",
      "packages/app-shell/src/views/ActionParamDialog.fieldHelpLine-12213.test.tsx (new; the D2 pin, a test in app-shell)",
      ".changeset/12213-types-inline-help-text.md (types minor, breaking stated, FROM help TO inlineHelpText, Clause-② line)",
      ".changeset/12213-plugin-form-inline-help-text.md (patch, FROM TO)",
      ".changeset/12213-fields-action-param-help.md (patch, FROM TO)"
     ],
     "deviations": [
      "Stop condition D1 fired, so the served `help` read leg is NOT deleted. It is reported here with options (open_questions). Retiring `help` from `BaseFieldMetadata` and from the four docs pages went ahead: the authoring face is a different thing from the served leg, and the claim's surface names the type change.",
      "Route: the shared helper lives in `sectionFields.ts`, as the PM suggested, and is not in `@object-ui/fields`. One read shared with the resolver would need a new fields module plus an export from `packages/fields/src/index.tsx`. Neither is on the claim's file list, and the claim says stop on breach. So the resolver writes out the same order, with a comment naming `fieldHelpText`. I briefly wrote that cross-package version and reverted it before the first commit, so it is in no commit.",
      "app-shell type-check ran with NODE_OPTIONS=--max-old-space-size=6144, not 4096, because app-shell (with its tests) is the largest tsc program in the repo. Every other heavy run used 4096.",
      "Added a test file in app-shell, the D2 dialog pin the dispatch asked for. app-shell gets no changeset because it is test-only; `check-changeset-presence` passes with the 3 changesets.",
      "The report has `measurements`, `files_changed` and `deviations` fields beyond the template, because the dispatch asked for files changed and deviations."
     ],
     "tests": "All at HEAD 629e77d, run after the last commit. Under os-verify-lock, each line is the lock's own `VERDICT command-exit` reading. (1) `pnpm exec vitest run packages/plugin-form/`: VERDICT command-exit 0; Test Files 179 passed (179); Tests 2200 passed | 1 skipped. (2) `pnpm exec vitest run packages/types/ packages/fields/ packages/core/src/utils/`: VERDICT command-exit 0; Test Files 723 passed | 1 skipped (724); Tests 16105 passed | 7 skipped. (3) the 80 app-shell test files naming resolveActionParams or ActionParamDialog, plus 3 plugin-grid files naming resolveActionParam or helpText (bulkFieldBackedParam-12105, defaultFromRowProjection-10277, resolveBulkActions), a declared narrowing: VERDICT command-exit 0; Test Files 83 passed (83); Tests 816 passed. (4) `pnpm exec vitest run scripts/__tests__/`: VERDICT command-exit 0; Test Files 180 passed | 2 skipped (182); Tests 5490 passed. (5) dependency-closure build `turbo run build --filter=@object-ui/plugin-form^... --concurrency=2`: VERDICT command-exit 0, 11/11 tasks. Then `pnpm --filter @object-ui/types type-check && pnpm --filter @object-ui/fields type-check && pnpm --filter @object-ui/plugin-form type-check`: VERDICT command-exit 0, and each script echoed `tsc --noEmit && ... tsc -p tsconfig.test.json`. (6) the doc-snippets scoped build, 35/35 tasks, VERDICT command-exit 0; then `pnpm --filter @object-ui/app-shell type-check`: VERDICT command-exit 0, `tsc --noEmit && tsc -p tsconfig.test.json` echoed. Gates, not locked, exit codes captured before any pipe: check:doc-snippets 0 (789 of 789 blocks judged, 0 failed; the first try exited 2, PRECONDITION NOT MET because packages were unbuilt, NOT MEASURED until the scoped build); check:doc-examples 0 (same: 2, then 0); check:doc-types 0; check:doc-json 0; check:designer-field-key-parity 0 (OK); check:spec-symbols 0; check:readme-exports 0 (the first try exited 1 with the population collapsed because packages were unbuilt; after the build: OK, 591 self-imports, 591 real); check:new-line-citations 0 (0 new citations); check:control-bytes 0; changeset:check 0; check:changeset-claims 0; node scripts/check-changeset-presence.mjs 0 (7 source files of 4 released packages, 3 changesets); node scripts/check-changeset-no-major.mjs 0. Derived from the diff: check:test-path-roots 0; check:pending-changeset-literals 0; check:doc-fences 0; check:doc-example-ids 0; check:vi-mock-specifiers 0; check:unreferenced-sources 0; check-governed-queue-guard --test over 14 paths: NOT GOVERNED. Lint, a measured narrowing: `eslint --no-inline-config --format json` over the 7 changed ts/tsx files gave exit 0, 7 files, 0 errors, 70 warnings. 67 of the warnings are in those files at the base (53 ObjectForm, 10 sectionFields, 4 field-types, 0 resolveActionParams, measured on the base blobs); 3 are `as any` schema casts in the new plugin-form test. Population: eslint.config.js covers **/*.{ts,tsx}. Invariance: no parserOptions.project or projectService (type-aware linting is off), and no rule in eslint-rules/ reads another file, so this diff cannot change the verdict on any untouched file. Reverse verification from committed state, each with a trap restore from HEAD and a blob-hash check. (a) ObjectForm.tsx, sectionFields.ts and resolveActionParams.ts checked out from base 6c437b0. On disk: fieldHelpText in sectionFields went 5 to 0, field.inlineHelpText in the resolver 1 to 0. The new pins then gave 8 failed, 14 passed: inlineHelpText x3 layouts, served-help-loses x3, the size hint, and the dialog inlineHelpText case. Restored: git diff HEAD empty, hashes match. (b) `help?: string` re-added to BaseFieldMetadata, marker on disk 1: types `tsc -p tsconfig.test.json` exited 2 with exactly 4 errors in the new pin (2x TS2344, 2x TS2578). Restored, hash match. (c) `help:` back in content/docs/fields/text.mdx: check:doc-snippets exited 1, TS2353 `help` does not exist in type TextFieldMetadata, 1 of 789 failed. Restored, hash match. No dist ablation was needed: vitest aliases @object-ui/* to src.",
     "mcp_calls": "0 — no MCP GitHub tool called",
     "api_writes": "2 relay strokes, each carried by one POST /repos/objectstack-ai/objectstack/dispatches (204). (1) pr_create: POST /repos/objectstack-ai/objectui/pulls (draft, base main), then POST /repos/objectstack-ai/objectui/issues/12236/assignees [huangyiirene]. Read back: 12492 bytes sent, 12492 stored, identical, assignee listed. (2) this report: POST /repos/objectstack-ai/objectui/issues/12213/comments. Plus git push x3 to claude/issue-12213-inline-help-text (empty branch probe, then 2 commits), which are not REST. 0 label writes.",
     "open_questions": [
      {
       "question": "Should the served `help` READ leg (step 2 of `fieldHelpText` in plugin-form and of the resolver's field-backed `helpText`) retire? Only objectstack servers on spec 17.6.0 or older produce it (the translator put the translated description on `help`). 17.7.0 serves that text on `description`.",
       "options": [
        "A. Retire now: delete one step in each reader and the two local `help` members, and state the floor in a changeset. Cost: against a 17.6.x-or-older server, non-English record forms show the source-language description in place of the translated one. English is unaffected, because the bundle entry is extracted from description.",
        "B. Keep until a named server floor, e.g. until objectui requires a 17.7+ server. This is the state this PR ships. Cost: a second spelling stays in the reader, which AGENTS.md #0.1 discourages, and the four-axis framework asks for named external-user evidence before a staged step. I have none.",
        "C. Fold `help` onto `description` at ingestion. Not viable: `description` is already set on the same def, and the fold never overwrites."
       ],
       "recommendation": "A. Real business need: the only producer is an older server whose translator is already fixed upstream and published, and any 17.x server can be upgraded within the major. Long-term soundness: one contract key (#0.1). Mistake-proofing AI authors: the spec door already refuses `help`, so nothing legitimate writes it. Startup focus: transitions are retired at once unless a named external user needs a stage, and none is named. The PM rules; this round kept the leg as the stop condition required."
      }
     ],
     "out_of_scope_findings": [
      "class: b · reach: named producer, the docs pages content/docs/fields/text.mdx, auto-number.mdx and object.mdx, plus the TextFieldMetadata / AutoNumberFieldMetadata / ObjectFieldMetadata declarations they import · evidence: on spec 17.7.0, `FieldSchema.safeParse` refuses, by unrecognized_keys, `pattern` and `pattern_message` on a text field, `starting_number`, and `schema` on an object field. The type values `auto_number` and `object` give invalid_value at `type`. Control: the text literal with label, maxLength and inlineHelpText is accepted (the 12213 types pin). Seam: spec:FieldSchema (strict, \"Unrecognized key(s) on this field\") → consumer: those docs literals and the type members, renderer readers not measured. Same family as this card (field metadata keys the spec refuses), so it goes onto the family's closing card, not a single-point card · dedupe words: TextFieldMetadata pattern_message spec refuses · auto_number type not in FieldSchema · ObjectFieldMetadata schema key refused · field docs teach keys FieldSchema refuses",
      "carrier: 承接者:无 · noted, not filed: Studio's object form canvas (ObjectFormCanvas) draws a field's `description` above the stub and never draws `inlineHelpText`. After this PR, a field with both shows different text on the canvas and on the record form. Read from code only; not reproduced at a public door.",
      "carrier: 承接者:无 · noted, not filed: a comment in plugin-detail's buildDefaultPageSchema says the spec's ObjectFieldLike reads `help`. Since spec 17.7.0 that duck type has no `help` member.",
      "carrier: 承接者:无 · noted, not filed: only ObjectForm's own builder appends the file or image size hint. Forms that go through fromObjectSchema (tabbed, drawer, modal, wizard, split) show none. This predates this card and was read from code, not reproduced."
     ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Stop condition D1 fired: the served help read leg needs a ruling · pm:dispatched → needs-user-decision · 2026-10-12T11:18Z

    domain:spec @ objectui seat (objectui#10217) · session session_0149MdowTfyuWZuSSESLUYnE. Checked against GitHub and objectstack main, not against the report (6123163546). Thread-read: 6123163546.

    What was checked: PR objectui#12236 is draft against main, with Clause-②: yes at line start. Its 14 files fall inside claim 6122167210. The record form reads inlineHelpText through one shared read, fieldHelpText. help is gone from BaseFieldMetadata and the four docs pages. The dev's stop condition fired, and the seat re-measured its premise. objectstack bab76850c (#21956, 2026-10-06, first released in spec 17.7.0) moved the translator from next.help = translatedHelp to next.description = translatedDescription. So an objectstack server on spec 17.6.0 or older serves a field's translated help on help, and the ingestion fold does not stamp help onto anything.

    State: pm:dispatched → needs-user-decision in this act. The assignee stays. PR objectui#12236 lands as built, with its first line switched to Part of #12213 so this card stays open as the decision's anchor. The PR keeps today's behaviour for the help leg (it already read field.help before), so landing it decides nothing either way. What it delivers now, regardless of the answer: Studio help text (inlineHelpText) shows under the field on the record form. Contract review and landing proceed as usual.

    维护者速读

    记录表单现在会显示 Studio 里填的帮助文字了(本 PR 照常落地)。剩一个问题:旧版 objectstack 服务端(spec 17.6.0 及更早)把翻译后的帮助文字放在一个叫 help 的键上,17.7.0 起才改放 description。objectui 的读取现在是「inlineHelpText → help → description」,中间那一步只为兼容旧服务端。

    • A:现在就删掉 help 这一步(一处小改动)。代价:还连着 17.6 及更早服务端的独立部署,非英文用户看到的帮助文字会变回未翻译的原文;英文不受影响。
    • B:先保留,等 objectui 正式要求服务端 ≥17.7 时再删。代价:多留一个「第二拼写」读法,而框架要求分阶段过渡须有具名外部用户证据,目前没有。

    席位推荐 A。

    选 A 还是 B?

    决策分析

    一句话问题: 旧服务端发来的「翻译后帮助文字」用的是一个已退役的键名,objectui 还要不要为它多读一步?

    Governing text:

    • objectui AGENTS.md #0.1:不在渲染端为不合规的元数据加宽容回退(「reading both columns and fields … to make non-compliant metadata "work."」)。
    • objectui AGENTS.md §9 版本号策略:「objectui 的 major 与 @objectstack(spec/client/formula)的 major 保持一致 … 心智模型:major 相同即兼容」。
    • 本卡分诊方向 6121900859:「first measure whether a served field document still carries help after the ingestion fold. If it does, that leg is reported before it is removed.」
    • 四轴框架「创业阶段不扩散」:「废弃别名/拼写与能力退役默认立即退休 … staged 仅凭具名外部用户证据方可荐」。

    协议声明、是否改协议: spec 17.7.0 起 FieldSchema 拒收 help(建议 inlineHelpText),服务端译文放 description。两个选项都不改协议。

    前提(re-check 命令,各带阳性对照):

    1. 旧服务端发 help:objectstack git show bab76850c -- packages/spec/src/system/i18n-resolver.ts | grep -n "next.help = translatedHelp",命中 1 处(删除行)。对照:git grep -n "next.description = translatedDescription" origin/main -- packages/spec/src/system/i18n-resolver.ts,命中 1。
    2. 折叠不处理 help:dev 报告 6123163546 D1 实测(display_field 折叠为对照)。
    3. objectui 包声明的服务端下限不一:types 与 plugin-form 依赖 @objectstack/spec ^17.7.0,但服务端适配器 data-objectstack 依赖 @objectstack/client ^17.3.0、@objectstack/spec ^17.5.0(各包 package.json)。
    4. objectstack 自带的 console 随服务端同版本发布(.objectui-sha 钉住),所以只有「独立安装 @object-ui/* 并连旧服务端」的部署会受 A 影响。这类部署是否存在,未测。

    选项 × 真实代价 × 工作量:

    选项 做什么 客户看到什么 工作量
    A 立即退役 删 fieldHelpText 与 resolver 里的 help 一步,删两个本地成员;changeset 写明译文帮助需服务端 ≥17.7.0 连 17.6 及更早服务端的独立部署:非英文记录表单的帮助文字变回原文 domain:spec · 1 个小 PR(约 10 行加 pin 翻转)· 先例 PR objectui#12215(同族退役)
    B 留到具名下限 本 PR 现状;本卡转 pm:on-hold,Restart-when: 为 objectui 的服务端下限 ≥17.7.0 无变化 0 现在,下限到达时 1 个小 PR

    业务含义直译: A 是只认新版服务端的说法,旧服务端的译文帮助退回原文。B 是在旧服务端退场之前,继续兼容它的旧说法。

    四轴(业务立场):

    • ① 项目长远合理性: 两年后只有一个键,inlineHelpText 加上 description 回退。A 一次到位。B 留一个按服务端版本存在的第二拼写,要等一个尚未定义的下限事件才能删。
    • ② 实际业务拉动: objectstack 自带的 console 不受影响。受影响的只有独立部署连旧服务端,未测,具名用户 0。
    • ③ 防 AI 犯错: spec 已拒收 help,AI 作者写不进去。读端那一步只服务旧服务端,对 AI 作者无影响。A 让读端只有一个键,更难被误读成「help 仍是合法拼写」。
    • ④ 创业阶段不扩散: 框架默认立即退役,分阶段须具名外部用户证据。目前没有。

    推荐:A(按①得出,②④ 同向,③ 中性偏 A)。

    • 回退:B,仅当维护者知道有独立部署连着 17.7 之前的服务端。
    • 置信缺口: 前提 4 的独立部署本席看不到。data-objectstack 声明 @objectstack/client ^17.3.0,是一个兼容旧服务端的意图信号。
    • 自检:只看①选 A;②③④ 是否翻转:否。

    裁后执行:

    • 裁 A:本席在本卡续派一个小 PR(Fixes #12213),删除那一步并翻转 pin,入队前过达档复核。
    • 裁 B:本卡转 pm:on-hold,带 Restart-when: 行(objectui 的服务端下限 ≥17.7.0),到点续派同样的小 PR。

    os-decision-facets

    • ① 项目长远合理性:A 一个键一次到位;B 留按服务端版本存在的第二拼写,待未定义的下限事件。
    • ② 实际业务拉动:自带 console 不受影响;受影响面仅独立部署连旧服务端,未测,具名用户 0。
    • ③ 防 AI 犯错:spec 已拒收 help;A 读端只认一个键,更难被误读为合法拼写。
    • ④ 创业阶段不扩散:默认立即退役;分阶段须具名外部用户证据,目前无。
    • Prior rulings read: objectui#11070 round 6 (display_field retired on the fold's ground; that ground does not hold here, since the fold does not stamp help); objectui#12157 (same family, landed 466a219); fix(spec): serve a field's translated help on description, never on an undeclared help objectstack#21956 (bab76850c, the translator fix); thread: 3

    相关单与 PR: PR objectui#12236 · objectui#12156 · objectui#12157 · objectstack-ai/objectstack#21956.


    Generated by Claude Code

  6. 1 remaining item

  7. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 12213,
     "status": "done",
     "branch": "claude/issue-12213-inline-help-text",
     "pr": "https://github.com/objectstack-ai/objectui/pull/12236",
     "session": "session_0149MdowTfyuWZuSSESLUYnE — subagent run, so this is the parent seat's id as the dispatch names it",
     "premise_still_valid": true,
     "summary": "Patch round 1, after contract review 6123580193. The JSDoc on `BaseFieldMetadata.inlineHelpText` said \"(`fieldHelpText` in `@object-ui/fields`)\", but the helper lives in `@object-ui/plugin-form`'s `sectionFields`. It now names `@object-ui/plugin-form`. That is one line in packages/types/src/field-types.ts, commit bfc920f on top of 629e77d (`git diff 629e77d bfc920f --stat`: 1 file changed, 1 insertion(+), 1 deletion(-)). I read the changeset .changeset/12213-types-inline-help-text.md and it needs no edit: it never names the package `fieldHelpText` lives in, and its one package mention, that the record form draws the help line in `@object-ui/plugin-form`, is true. The served `help` leg and the PR body were not touched. The PR read mergeable_state `clean` at 629e77d, so `origin/main` was not merged.",
     "files_changed": [
      "packages/types/src/field-types.ts (one JSDoc line)"
     ],
     "deviations": [
      "Before the types type-check I ran the dependency-closure build `turbo run build --filter=@object-ui/types^...` (only @object-ui/test-support, a devDependency) in the same locked command. It executed no task (turbo answered 0 tasks), so it changed nothing.",
      "Also checked, outside the five named gates: `git grep fieldHelpText` over packages, content and .changeset. The other comments that name the helper's package say `@object-ui/plugin-form`, which is correct, so no other text was made false in this round."
     ],
     "tests": "At HEAD bfc920f, after the commit. Locked (os-verify-lock, VERDICT command-exit 0, held 65s): `pnpm --filter @object-ui/types type-check` echoed `tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json` and exited 0, then `pnpm exec vitest run packages/types/src/__tests__/field-metadata-inline-help-text-12213.test.ts` gave Test Files 1 passed (1), Tests 2 passed (2). Unlocked, exit codes captured before any pipe: `pnpm check:new-line-citations` exit 0, `VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0`; `pnpm check:control-bytes` exit 0, `check-control-bytes: OK (scanned 8480 tracked text file(s); skipped 85 binary)`; `node scripts/check-changeset-presence.mjs` exit 0, `7 source file(s) of 4 released package(s) changed, and this change declares 3 changeset(s)`.",
     "mcp_calls": "0 — no MCP GitHub tool called",
     "api_writes": "1 relay stroke: POST /repos/objectstack-ai/objectui/issues/12213/comments (this report), carried by one POST /repos/objectstack-ai/objectstack/dispatches. Plus one git push 629e77d..bfc920f to claude/issue-12213-inline-help-text, no force, which is not REST. 0 label writes, 0 PR body edits.",
     "open_questions": [],
     "out_of_scope_findings": []
    }

    Generated by Claude Code

  8. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT (partial landing) · PR objectui#12236 @ bfc920f · 2026-10-12T12:13Z

    domain:spec @ objectui seat (objectui#10217) · session session_0149MdowTfyuWZuSSESLUYnE. Checked against GitHub, not against the reports (6123163546, 6123648541).
    Implemented-by: claude/issue-12213-inline-help-text · Reviewed-by: session_0149MdowTfyuWZuSSESLUYnE, plus the contract-review-tier record 6124039934 on the PR (PASS on head bfc920f3ff85d1bd449a89e2eda5c182f5af14a5, Local-runs: none). It stands on its own; the earlier 6123580193 judged 629e77d.

    Checklist (head bfc920f)

    • Shape: draft ✓ · base main ✓ · first line Part of #12213 (switched by the seat, so this card stays open as the decision's anchor) ✓ · Clause-②: yes at line start ✓ · PR assignee huangyiirene ✓. A body scan finds no closing keyword.
    • Surface: 14 files, inside claim 6122167210. Not governed. 518 changed lines. mergeable_state clean.
    • Delivered: the record form's two builders share one read, fieldHelpText, which reads inlineHelpText first and falls back to description. resolveActionParam follows the same order. BaseFieldMetadata swaps help for inlineHelpText typed by reference to the spec. The four docs pages teach inlineHelpText. Placement is the same as flow screens: under the control, tied by aria-describedby.
    • Changesets, each sentence read against the diff: types minor (the help removal is BREAKING, FROM → TO, plus the added member), plugin-form patch, fields patch. app-shell carries a test only and owes none.
    • Patch round 1 (bfc920f): one published JSDoc phrase corrected (fieldHelpText lives in @object-ui/plugin-form, not @object-ui/fields). The compare from 629e77d is 1 file, +1 −1.
    • CI on bfc920f: 43 runs, 40 success and 3 skipped, 0 red.

    Not landed here, in the decision box: the served help read leg (6123212511, A retire now / B keep until a named server floor). The PR keeps it as today's behaviour, so the merge decides nothing.

    Out-of-scope findings:

    • The other keys the field docs and types teach that FieldSchema refuses: filed as objectui#12242 (the family close-out card; triage already graded it into pm:queue).
    • ObjectFormCanvas draws description only, so the Studio canvas and the record form can show different help text. The review escalated it twice. Not filed: it is a code reading with no measured wrong result at a public door, so it fails the filing gate's reach: requirement. It stays in Acceptance notes, with carrier none.
    • A stale ObjectFieldLike.help comment in plugin-detail, and the size hint appended by the flat builder only (both predate this card): Acceptance notes, carrier none.

    Landing: pr_ready + automerge_enable through the relay in this act. At the merge, this card is released (Release: line, assignee cleared) into the decision box, which holds the remainder.


    Generated by Claude Code

  9. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: session session_0149MdowTfyuWZuSSESLUYnE · cause: partial landing, the remainder waits on a ruling · destination: the decision box (needs-user-decision, question 6123212511) · 2026-10-12T12:32Z

    domain:spec @ objectui seat (objectui#10217).

    • Landed: PR objectui#12236 merged through the queue at 2026-10-12T12:31Z as 923504f4a9, which is on origin/main. Verified by content: BaseFieldMetadata declares inlineHelpText by reference to the spec and no longer declares help, and fieldHelpText is read by both record-form builders. Verified by git patch-id --stable: the PR's net diff and the merge commit both give 711400d14b. Studio help text now shows under the field on the record form.
    • Remaining: the served help read leg, A (retire now) or B (keep until a named server floor), at 6123212511. The card stays open because the PR said Part of.
    • After the ruling: the next claimant (this seat, if it is still seated) re-claims with a fresh Claim: and dispatches the follow-up PR, Fixes #12213. The branch claude/issue-12213-inline-help-text is merged; the follow-up starts from main. The contract review's note for that PR: lift the one read into @object-ui/fields so the order has one home.
    • Assignee cleared in this act.

    Generated by Claude Code

  10. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #331 item 3 · letter A · maintainer 「同意」 2026-10-12T22:45Z

    Director seat, summon #39, session_01TJKP6W6UDYEBHtccVdpVoz (GitHub os-steve; seat post objectstack-ai/objectstack#12708; written as objectstack-fleet[bot] through the relay, read back). Presented in this seat's chat as batch #331 item 3 with recommendation A; the maintainer's word was 「同意」. Thread-read: 6124330899.

    A — the served help read leg retires now. fieldHelpText in @object-ui/plugin-form and the field-backed helpText fallback in @object-ui/fields read inlineHelpText, then description, and no longer help; the two local help members go with them. The changeset states the floor: translated field help needs an objectstack server on spec 17.7.0 or later (objectstack-ai/objectstack bab76850c, objectstack#21956). Governing text: the standing ruling (objectstack#12708 ledger 5552700625, protocol as baseline); objectui AGENTS.md #0.1; the framework's retirement rule (immediate; staged only on named external-user evidence, and none is named). The server-floor counter-argument (AGENTS.md §9, same major is compatible) is answered: compatibility is promised to the spec's contract, which the 17.6.0 translator did not keep, and the fix is released. B is not taken.

    • Workload (the card's column for A): domain:spec @ objectui · 1 small PR · precedent PR fix(fields,types,app-shell): the lookup widget reads allowCreate, lookupColumns and lookupPageSize alone; the snake_case twins retire (objectui#12157) #12215.
    • Execution parameters: this card moves needs-user-decision → pm:queue (domain:spec) in this act, unassigned. The seat re-claims with a fresh Claim: and dispatches one PR from main, Fixes #12213: delete the help step in both readers; lift the one read into @object-ui/fields so the order has one home (the contract review's note, 6124330899); flip the served-help pins from "loses" to "ignored"; the changeset FROM → TO with the server floor. The contract review at CONTRACT_REVIEW_TIER is owed before the queue.
    • Premise and fork clause: the only producer of a served help key is an objectstack server on spec 17.6.0 or earlier. If the dev finds another producer on objectui or objectstack main (outside tests, docs and the spec's alias tables), it reports and stops; ⛔ no silent B.
    • 四棱:卡面 6123212511 的四棱块本席逐条确认;只看①选 A;②③④ 是否翻转:否。
  11. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-12T23:10Z
    Session: session_015YrgVw7e65cs1ndbebt46G
    Account: os-justin
    Branch: claude/issue-12213-help-leg-retire
    Worktree: objectui-issue-12213
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/plugin-form/src/sectionFields.ts (fieldHelpText and FieldHelpTextSource), packages/plugin-form/src/ObjectForm.tsx (the import and the description: fieldHelpText(field) line only), packages/fields/src/resolveActionParams.ts (the field-backed helpText fallback and its local help member), packages/fields/src/ (the one shared read, its home file and the package entry's export), packages/types/src/field-types.ts (the docblock that points at fieldHelpText only), the pins that read these (packages/plugin-form/src/__tests__/, packages/plugin-form/src/sectionFields*.test.ts, packages/fields/src/** tests, packages/app-shell/src/views/ActionParamDialog.fieldHelpLine-12213.test.tsx, packages/app-shell/src/utils/resolveActionParams.test.ts, packages/types/src/__tests__/field-metadata-inline-help-text-12213.test.ts), the touched packages' READMEs, .changeset/12213-*.md (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus (default tier: a ruling implementation; dispatch-gates --tier --repo objectstack-ai/objectui answered no path-derived mandate)
    Clause-②: yes
    Responsibility: objectui's two readers (plugin-form fieldHelpText, fields resolveActionParams) still read the spec-refused help key | none: spec 17.7.0+ refuses help and its translator serves description (objectstack bab76850c) | only an objectstack server on spec 17.6.0 or older serves help; named users 0 (ruling 6134063362)
    Ruling-ref: 6134063362
    Thread-read: 6134063362
    Serial constraints cleared: PR objectui#12236 (merged 923504f) and PR objectui#12257 (merged 10aba37) touched these files, both landed; objectui#7611 (domain:ui, in flight) declares field-types.ts and ObjectForm.tsx only on lines that read a retiring permission table, a disjoint region; no open PR touches plugin-form, fields or types (open PRs read {{NOW}})

    Clause-② reads yes: lifting the read into @object-ui/fields adds a public export to that package, and retiring help narrows FieldHelpTextSource. The dev measures the exact export closure in the report. The contract-review-tier review is owed before the queue.


    Generated by Claude Code

  12. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 12213,
     "status": "done",
     "branch": "claude/issue-12213-help-leg-retire",
     "pr": "https://github.com/objectstack-ai/objectui/pull/12283",
     "session": "session_015YrgVw7e65cs1ndbebt46G — the id the dispatch and the claim name; this is a subagent run, so it is the parent seat's id",
     "premise_still_valid": true,
     "summary": "Ruling A is implemented. A field's help line has one read, `fieldHelpText`, now exported from `@object-ui/fields`: `inlineHelpText || description`, with an empty string reading as absent and `help` no longer read. The record form (`ObjectForm`'s builder and `fromObjectSchema`) and `resolveActionParam` both call it. plugin-form keeps no copy and no re-export, and both local `help` members are gone (`FieldHelpTextSource` in plugin-form, `RuntimeField.help` in the resolver). The served-`help` pins are flipped to `ignored` with weight: `help` plus `description` shows the description, and `help` alone shows no help line. The changesets state the floor: translated field help needs an objectstack server on spec 17.7.0 or later (objectstack `bab76850c`, objectstack#21956). The fork clause did not fire: no other producer of a served field `help` was found on objectui or objectstack main.",
     "measurements": [
      "Assumption 1 CONFIRMED at objectui `48fb558d`: the served leg is read in exactly two places, plugin-form `sectionFields` `fieldHelpText` and the resolver's `helpText` line. `ObjectForm` calls the first and has no read of its own. The two local members are `FieldHelpTextSource.help` and `RuntimeField.help`. Every other non-test `.help` read is a non-field shape: flow config fields (`FlowNodeConfigField.tsx`, `StudioDesignSurface.tsx` via `newFlowTriggerFields`), `ShareDialog` options, and `BulkActionDialog`'s `BulkActionParam.help`, which `resolveBulkActions` fills from the resolver's `helpText`.",
      "Assumption 2 CONFIRMED: `git grep -c` for fieldHelpText or FieldHelpTextSource over both package entries gives exit 1, 0 hits; the control `ObjectForm` gives 24 in `plugin-form/src/index.tsx`. There is no non-public home: `@object-ui/fields` publishes `.` and `./style.css` only. So the lift adds one public export.",
      "Export closure, measured on the built d.ts with a TypeScript-checker script (`getExportsOfModule` on each package's `exports['.'].types` file), base `48fb558d` build vs head `06213286` build. `@object-ui/fields`: 191 names to 192. The only new name is `fieldHelpText`, typed `(field: Pick of BaseFieldMetadata's inlineHelpText and description) => string | undefined`, declared in `dist/fieldHelpText.d.ts`; its one import is `BaseFieldMetadata` from `@object-ui/types`, which is already exported there. `@object-ui/plugin-form`: 59 names to 59, identical lists. `FieldHelpTextSource` is not an export name at either point. Its only built home was plugin-form's `dist/sectionFields.d.ts`, which no `exports` entry reaches; it had the type and the function at base and has 0 hits now. Controls: `resolveActionParam` PRESENT in fields, `ObjectForm` PRESENT in plugin-form, at both points.",
      "Assumption 3, the fork clause: NOT FIRED. objectui `48fb558d`, outside tests and docs: `help:` writers are 17 files and none writes the key onto a field definition (flow config fields, i18n catalogues, share options, bulk params). JSON `\"help\":` keys: 0 files, control `\"description\":` 118. `transformSpecTranslations` flattens a field's `label` and `options` only. objectui i18n/react/core/data-objectstack/providers `.help` reads: 0, control `.label` hits in `useObjectLabel.ts`. `getFieldLabels` and `/i18n/labels`: 0 repo-wide, control `/api/v1/i18n/translations` hit in `loadLanguage.ts`. objectstack origin/main `84643802` (fetched): `next.help =` in `i18n-resolver.ts` 0, control `next.description = translatedDescription` 1. The 2441 `help:` / `.help =` lines outside tests and docs are translation-bundle entries (the translator's input), spec alias tables, the translation schema's own `help` member, bulk-action params, and one near miss: the `/i18n/labels` response (`GetFieldLabelsResponse.labels.FIELD.help`, from `resolveObjectFieldLabels`). That is a separate labels document, not a served field definition, and objectui never requests it, so it reaches neither reader. Read as outside the clause; the PM may judge otherwise.",
      "Assumption 4 CONFIRMED and swept: the repo-wide test sweep for a served field `help` found exactly the two named pins. `field-metadata-inline-help-text-12213.test.ts` (types) pins `help` as a refused authoring key; it is unchanged and still true. The remaining `help:` hits in tests are bulk params, flow config fields and connector inputs.",
      "Assumption 5 re-derived: a grep of tests naming `resolveActionParam`, `ActionParamDialog`, `fieldHelpText` or `inlineHelpText` (app-shell, plugin-grid, apps/console, plugin-detail, plugin-view) gives 97 files. The union with the dispatch's list adds `FormPage.richTextHints-12110`, `FormPage.fieldSpec` and `resolveBulkActions.test.ts`, for 100. All passed (979 tests). plugin-form's `sectionFields*` and `sectionEntryOverrides-10475` ran inside the whole plugin-form suite.",
      "Assumption 6: `field-types.ts`'s docblock now names `@object-ui/fields` as `fieldHelpText`'s home. The resolver's comments no longer mention a `help` leg. sectionFields' docblock went out with the function, and the comment at `fromObjectSchema` names the new home. READMEs: fields gained a section for the export. plugin-form's README row (`description`: help text under the control) is a FormField key and stays true. No `content/docs` page names `fieldHelpText` or the leg.",
      "Same-day churn: main moved from the dispatch tip `1fb1ced3` to `48fb558d` before the worktree was cut. That commit touches 4 CI and scripts files, none on this card's paths. The snippets the card quoted matched main."
     ],
     "files_changed": [
      "packages/fields/src/fieldHelpText.ts (new: the one read)",
      "packages/fields/src/index.tsx (export of fieldHelpText)",
      "packages/fields/src/resolveActionParams.ts (fallback calls fieldHelpText; RuntimeField.help removed; neighbour docblocks)",
      "packages/plugin-form/src/sectionFields.ts (local fieldHelpText and FieldHelpTextSource removed; imports it from @object-ui/fields)",
      "packages/plugin-form/src/ObjectForm.tsx (the import only)",
      "packages/types/src/field-types.ts (one docblock phrase: fieldHelpText's home)",
      "packages/fields/README.md (new section: A field's help line)",
      "packages/fields/src/__tests__/fieldHelpText-12213.test.tsx (new pin of the export and its source type)",
      "packages/plugin-form/src/__tests__/objectFormInlineHelpText-12213.test.tsx (served help: read to ignored, helpOnly case)",
      "packages/app-shell/src/views/ActionParamDialog.fieldHelpLine-12213.test.tsx (served help: read to ignored, helpOnly case)",
      ".changeset/12213-fields-field-help-text-export.md (new, fields minor, Clause-② line)",
      ".changeset/12213-fields-action-param-help.md (edited: patch to minor, TO side, BREAKING floor)",
      ".changeset/12213-plugin-form-inline-help-text.md (edited: patch to minor, TO side, BREAKING floor)"
     ],
     "gates": [
      "head 06213286 for every reading below",
      "build (locked): turbo build @object-ui/console... 35/35 (13 cached); @object-ui/cli... + @object-ui/plugin-ai... 10/10; earlier @object-ui/plugin-form... 12/12",
      "type-check exit 0, each echoing its tsc chain: @object-ui/types, @object-ui/fields, @object-ui/plugin-form, @object-ui/plugin-grid, @object-ui/app-shell",
      "vitest packages/fields/ + packages/plugin-form/ + types 12213 pin: 431 files passed, 1 skipped; 6226 tests passed, 8 skipped; exit 0",
      "vitest consumer set (100 files): 100 passed, 979 tests; exit 0",
      "vitest scripts/__tests__/: 187 files passed, 2 skipped; 5621 tests passed, 2 skipped; exit 0",
      "check:readme-exports 0 (592 self-imports all real, 0 unbuilt; the new fieldHelpText import judged real). First try exited 1 because cli and plugin-ai were unbuilt: a precondition, NOT MEASURED, rerun after building them",
      "check:spec-symbols 0 · check:self-import 0 · check:phantom-deps 0 · check:unreferenced-sources 0 (covers 1 package, not fields) · check:handler-key-reads 0 · check:designer-field-key-parity 0",
      "check:eager-closure 0: head reading 3131.3 KB gzipped of a 3204.6 KB budget (headroom 73.3 KB); the base was not measured, so no delta is claimed",
      "check:esm-specifiers 0 · check:changeset-claims 0 (3 changesets read, no self-contradiction, no pending body names a touched file) · check:pending-changeset-literals 0 · check:new-line-citations 0 (0 new) · check:control-bytes 0",
      "node scripts/check-changeset-fixed.mjs 0 · check-changeset-presence 0 (9 source files of 4 released packages, 1 changeset added) · check-changeset-no-major 0 · check-changeset-overwrite report-only: 2 pending 12213 changesets modified (deliberate, see deviations)",
      "derived extras: check:test-path-roots 0 · check:vi-mock-specifiers 0 · check:dist-completeness 0 · check-type-check-coverage 0 · check-governed-queue-guard --test over the 13 paths: NOT GOVERNED",
      "eslint, a measured narrowing: --no-inline-config --format json over the 9 touched ts/tsx files (JSON count 9) gives 0 errors and 213 warnings; the base blobs give 212. The +1 is react-refresh/only-export-components on the new re-export in fields/src/index.tsx, the same rule its 53 other non-component exports trip. Population: eslint.config.js `**/*.{ts,tsx}`. Invariance: no parserOptions.project or projectService, and no eslint-rules/ rule reads another file",
      "reverse verification from committed head via ablation-replace (wrap mode, restored to the HEAD blob a1b6da85, git diff HEAD empty): A (runtime, the help leg re-added) turns the 3 pin files from 28 passed to 7 failed and 21 passed, exactly the 7 ignored cases; B (type level, help re-added to the parameter type) makes fields tsc -p tsconfig.test.json exit 1 with TS2578 unused @ts-expect-error in fieldHelpText-12213.test.tsx"
     ],
     "line_budget": "n/a: the diff touches no skills/** file and no ratcheted line ledger. Diff 13 files, +221 -101.",
     "deviations": [
      "Changesets: the two pending, unreleased 12213 changesets (plugin-form, fields) are EDITED, not only supplemented: each said the `help` leg is still read, which would publish false in the same release. Each now states FROM the last release TO `inlineHelpText || description`, carries the BREAKING floor section, and is raised from patch to minor (priced by the AGENTS.md section 9 policy). One new changeset declares the export with the Clause-② line. check-changeset-overwrite reports the two edits (report-only, its case 2).",
      "`@object-ui/types` gets no changeset for its one docblock phrase (behaviour and surface unchanged). `@object-ui/app-shell` changes a test only.",
      "`fieldHelpText` drops the old plugin-form signature's `null | undefined` tolerance. Every caller passes a defined field: both form builders guard, and the resolver returns before the read when the field is missing.",
      "The build went wider than the named `@object-ui/plugin-form^...` closure: the whole `@object-ui/console...` closure, plus cli and plugin-ai. The app-shell and plugin-grid type-checks, check:readme-exports and check:eager-closure read built dist outside that closure. Changing types' docblock invalidated the turbo cache of every downstream package.",
      "app-shell type-check ran with NODE_OPTIONS=--max-old-space-size=6144, not 4096. The reason is carried over from the prior 12213 round's reading (the largest tsc program in the repo); 4096 was not re-measured here.",
      "Lock: batch 2 (whole fields and plugin-form suites, then the 100-file consumer set, at maxWorkers 2) held the shared lock 22m36s, a long hold. The other holds were 1s, 3m32s, 52s, 6m57s and 6m28s.",
      "Within the claimed resolveActionParams.ts, the neighbour docblocks of `RuntimeField.inlineHelpText` and `description` moved with the `help` member. ObjectForm.tsx changed its import line only; the existing comment above `description: fieldHelpText(field)` is still true and was left alone."
     ],
     "tests": "All at head 06213286, after the last commit; every locked run's own VERDICT line read command-exit 0. (1) Locked: turbo build @object-ui/plugin-form... 12/12, then type-check types, fields and plugin-form, exit 0 each. (2) Locked: `pnpm exec vitest run --maxWorkers=2 packages/fields/ packages/plugin-form/ packages/types/src/__tests__/field-metadata-inline-help-text-12213.test.ts` gives Test Files 431 passed, 1 skipped (432); Tests 6226 passed, 8 skipped (6234). The 100-file consumer set gives Test Files 100 passed (100); Tests 979 passed (979). (3) Locked, verbose: the three 12213 pin files give 28 passed. Ablation A (ablation-replace anchor `return field.inlineHelpText || field.description || undefined;` x1 to x0, blob a1b6da85 to 5e0e18b6) gives Tests 7 failed, 21 passed (28), then restored: blob == HEAD, git diff HEAD empty. Ablation B (parameter type plus help) gives `error TS2578: Unused '@ts-expect-error' directive` at fieldHelpText-12213.test.tsx, then restored, hash-checked. (4) Locked: turbo build @object-ui/console... 35/35, then type-check plugin-grid and app-shell, exit 0. (5) Locked: turbo build cli and plugin-ai closures 10/10, then `pnpm exec vitest run --maxWorkers=2 scripts/__tests__/` gives Test Files 187 passed, 2 skipped (189); Tests 5621 passed, 2 skipped (5623). Gate list in `gates`.",
     "mcp_calls": "0 — no MCP GitHub tool called",
     "api_writes": "2 relay strokes, each one POST /repos/objectstack-ai/objectstack/dispatches (204) executed by fleet-write as objectstack-fleet[bot]. (1) pr_create: POST /repos/objectstack-ai/objectui/pulls (draft, base main), then POST /repos/objectstack-ai/objectui/issues/12283/assignees [os-justin]. Relay read-back: 10192 bytes sent, 10192 stored, identical; assignee listed. (2) This report: POST /repos/objectstack-ai/objectui/issues/12213/comments. Plus 2 git pushes to claude/issue-12213-help-leg-retire (the empty-branch probe, then commit 06213286), no force; these are not REST. 0 label writes, 0 PR body edits. Reads were unauthenticated single-card REST GETs (the issue, its comments, PR 12283).",
     "open_questions": [],
     "out_of_scope_findings": []
    }

    Generated by Claude Code

  13. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT · PR objectui#12283 @ 06213286 · 2026-10-13T00:30Z

    domain:spec @ objectui seat (objectui#10217) · session session_015YrgVw7e65cs1ndbebt46G. Checked against GitHub and the PR's diff, not against the report (6135156455). Ruling-ref: 6134063362 (letter A). Thread-read: 6135156455.
    Implemented-by: claude/issue-12213-help-leg-retire · Reviewed-by: session_015YrgVw7e65cs1ndbebt46G, plus the contract-review-tier record 6135284087 on the PR (PASS on head 0621328684dac02a4b93051bcb2088276350e4f7, Local-runs: none), written by an isolated at-tier reviewer that read only the card, the PR and the head's check-runs.

    Checklist (head 06213286)

    • Shape: draft ✓ · base main ✓ · first line Fixes #12213, as the ruling asked ✓ · Clause-②: yes at line start ✓ · PR assignee os-justin ✓. A body scan finds a closing keyword on line 1 only.
    • Surface: 13 files, +221 −101, all inside claim 6134381355. Not governed (check-governed-merges --pr: 0 of 13 paths, 322 changed lines).
    • The ruling, delivered: one read, fieldHelpText in @object-ui/fields (inlineHelpText || description, an empty string reading as absent, no help). ObjectForm's builder, fromObjectSchema and resolveActionParam call it, and plugin-form keeps no copy. Both local help members (FieldHelpTextSource.help, RuntimeField.help) are gone. The served-help pins flip from "loses" to "ignored" with weight: help plus description draws the description, and help alone draws no help line.
    • Dropped null | undefined tolerance: read on the head. ObjectForm calls it inside if (field), fromObjectSchema returns early on !field, and resolveActionParam returns before the helpText line on !field.
    • Fork clause: not fired. The dev's near miss, objectstack's /i18n/labels response, is a labels document, not a served field definition, and objectui never requests it. This seat re-read objectui main: i18n/labels and getFieldLabels give 0 hits, with the control /api/v1/i18n/translations hitting. The contract review judged it the same way, independently.
    • Changesets, each sentence read against the diff:
      • 12213-fields-field-help-text-export.md (new, minor): the export, its order, its Pick<BaseFieldMetadata, 'inlineHelpText' | 'description'> parameter (a typed literal carrying help fails to compile, pinned by a live @ts-expect-error), and the Clause-②: yes line. All match.
      • 12213-fields-action-param-help.md (edited, patch → minor): FROM param.helpText ?? field.help ?? field.description (the last release) TO param.helpText ?? fieldHelpText(field); the param's own helpText still wins; the BREAKING section states the floor (spec ≥ 17.7.0, objectstack bab76850c). All match.
      • 12213-plugin-form-inline-help-text.md (edited, patch → minor): FROM field.help || field.description TO field.inlineHelpText || field.description; the read now lives in @object-ui/fields; the same BREAKING floor. The line "help is still read" is gone, which would have published false in this release. All match.
      • The two edits fall on unreleased changesets (zero 12213 in the three CHANGELOGs on main), so editing them is right. minor for a breaking change is objectui's fixed-group policy, per the contract review's ②.
    • CI on 06213286: 33 runs, 30 success, 3 skipped (the coverage lane and dependabot, by their path switches), 0 red. mergeable_state is clean. The CI budget comment reads 3131.2 KB of 3204.6 KB for the eager closure.

    Out-of-scope findings: none from this round. The round-1 Acceptance notes (ObjectFormCanvas draws description only; a plugin-detail comment lists help) are untouched and stay notes with carrier none, as 6124052930 judged.

    Landing: pr_ready + automerge_enable through the relay in this act. At the merge, Fixes #12213 closes this card.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanepriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions